Messily fix RSA

This commit is contained in:
Max Goedjen 2025-08-24 14:00:24 -07:00
parent b28ff410c9
commit ce52dd2b35
No known key found for this signature in database
5 changed files with 37 additions and 43 deletions

View File

@ -135,47 +135,44 @@ extension Agent {
}
let dataToSign = reader.readNextChunk()
let signed = try await store.sign(data: dataToSign, with: secret, for: provenance)
let derSignature = signed
let rawRepresentation = try await store.sign(data: dataToSign, with: secret, for: provenance)
let curveData = Data(writer.curveType(for: secret.keyType).utf8)
// Convert from DER formatted rep to raw (r||s)
let signedData: Data
if secret.keyType.algorithm == .ecdsa {
let rawLength = rawRepresentation.count/2
// Check if we need to pad with 0x00 to prevent certain
// ssh servers from thinking r or s is negative
let paddingRange: ClosedRange<UInt8> = 0x80...0xFF
var r = Data(rawRepresentation[0..<rawLength])
if paddingRange ~= r.first! {
r.insert(0x00, at: 0)
}
var s = Data(rawRepresentation[rawLength...])
if paddingRange ~= s.first! {
s.insert(0x00, at: 0)
}
let rawRepresentation: Data
switch (secret.keyType.algorithm, secret.keyType.size) {
case (.ecdsa, 256):
rawRepresentation = try CryptoKit.P256.Signing.ECDSASignature(derRepresentation: derSignature).rawRepresentation
case (.ecdsa, 384):
rawRepresentation = try CryptoKit.P384.Signing.ECDSASignature(derRepresentation: derSignature).rawRepresentation
default:
throw AgentError.unsupportedKeyType
var signatureChunk = Data()
signatureChunk.append(writer.lengthAndData(of: r))
signatureChunk.append(writer.lengthAndData(of: s))
var mutSignedData = Data()
var sub = Data()
sub.append(writer.lengthAndData(of: curveData))
sub.append(writer.lengthAndData(of: signatureChunk))
mutSignedData.append(writer.lengthAndData(of: sub))
signedData = mutSignedData
} else {
var mutSignedData = Data()
var sub = Data()
sub.append(writer.lengthAndData(of: Data("rsa-sha2-512".utf8)))
sub.append(writer.lengthAndData(of: rawRepresentation))
mutSignedData.append(writer.lengthAndData(of: sub))
signedData = mutSignedData
}
let rawLength = rawRepresentation.count/2
// Check if we need to pad with 0x00 to prevent certain
// ssh servers from thinking r or s is negative
let paddingRange: ClosedRange<UInt8> = 0x80...0xFF
var r = Data(rawRepresentation[0..<rawLength])
if paddingRange ~= r.first! {
r.insert(0x00, at: 0)
}
var s = Data(rawRepresentation[rawLength...])
if paddingRange ~= s.first! {
s.insert(0x00, at: 0)
}
var signatureChunk = Data()
signatureChunk.append(writer.lengthAndData(of: r))
signatureChunk.append(writer.lengthAndData(of: s))
var signedData = Data()
var sub = Data()
sub.append(writer.lengthAndData(of: curveData))
sub.append(writer.lengthAndData(of: signatureChunk))
signedData.append(writer.lengthAndData(of: sub))
if let witness = witness {
try await witness.witness(accessTo: secret, from: store, by: provenance)
}

View File

@ -51,16 +51,14 @@ public extension SecretStore {
/// Returns the appropriate keychian signature algorithm to use for a given secret.
/// - Parameters:
/// - secret: The secret which will be used for signing.
/// - allowRSA: Whether or not RSA key types should be permited.
/// - Returns: The appropriate algorithm.
func signatureAlgorithm(for secret: SecretType, allowRSA: Bool = false) -> SecKeyAlgorithm {
func signatureAlgorithm(for secret: SecretType) -> SecKeyAlgorithm {
switch (secret.keyType.algorithm, secret.keyType.size) {
case (.ecdsa, 256):
return .ecdsaSignatureMessageX962SHA256
case (.ecdsa, 384):
return .ecdsaSignatureMessageX962SHA384
case (.rsa, 1024), (.rsa, 2048):
guard allowRSA else { fatalError() }
return .rsaSignatureMessagePKCS1v15SHA512
default:
fatalError()

View File

@ -104,9 +104,8 @@ extension OpenSSHKeyWriter {
"nistp" + String(describing: keyType.size)
case .mldsa:
"mldsa" + String(describing: keyType.size)
case .rsa:
// All RSA keys use the same 512 bit hash function
"rsa-sha2-512"
default:
fatalError()
}
}

View File

@ -69,7 +69,7 @@ extension SecureEnclave {
switch (attributes.keyType.algorithm, attributes.keyType.size) {
case (.ecdsa, 256):
let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData)
return try key.signature(for: data).derRepresentation
return try key.signature(for: data).rawRepresentation
case (.mldsa, 65):
guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() }
let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData)

View File

@ -79,7 +79,7 @@ extension SmartCard {
}
let key = untypedSafe as! SecKey
var signError: SecurityError?
guard let signature = SecKeyCreateSignature(key, signatureAlgorithm(for: secret, allowRSA: true), data as CFData, &signError) else {
guard let signature = SecKeyCreateSignature(key, signatureAlgorithm(for: secret), data as CFData, &signError) else {
throw SigningError(error: signError)
}
return signature as Data