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 dataToSign = reader.readNextChunk()
let signed = try await store.sign(data: dataToSign, with: secret, for: provenance) let rawRepresentation = try await store.sign(data: dataToSign, with: secret, for: provenance)
let derSignature = signed
let curveData = Data(writer.curveType(for: secret.keyType).utf8) 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 var signatureChunk = Data()
switch (secret.keyType.algorithm, secret.keyType.size) { signatureChunk.append(writer.lengthAndData(of: r))
case (.ecdsa, 256): signatureChunk.append(writer.lengthAndData(of: s))
rawRepresentation = try CryptoKit.P256.Signing.ECDSASignature(derRepresentation: derSignature).rawRepresentation var mutSignedData = Data()
case (.ecdsa, 384): var sub = Data()
rawRepresentation = try CryptoKit.P384.Signing.ECDSASignature(derRepresentation: derSignature).rawRepresentation sub.append(writer.lengthAndData(of: curveData))
default: sub.append(writer.lengthAndData(of: signatureChunk))
throw AgentError.unsupportedKeyType 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 { if let witness = witness {
try await witness.witness(accessTo: secret, from: store, by: provenance) 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. /// Returns the appropriate keychian signature algorithm to use for a given secret.
/// - Parameters: /// - Parameters:
/// - secret: The secret which will be used for signing. /// - secret: The secret which will be used for signing.
/// - allowRSA: Whether or not RSA key types should be permited.
/// - Returns: The appropriate algorithm. /// - 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) { switch (secret.keyType.algorithm, secret.keyType.size) {
case (.ecdsa, 256): case (.ecdsa, 256):
return .ecdsaSignatureMessageX962SHA256 return .ecdsaSignatureMessageX962SHA256
case (.ecdsa, 384): case (.ecdsa, 384):
return .ecdsaSignatureMessageX962SHA384 return .ecdsaSignatureMessageX962SHA384
case (.rsa, 1024), (.rsa, 2048): case (.rsa, 1024), (.rsa, 2048):
guard allowRSA else { fatalError() }
return .rsaSignatureMessagePKCS1v15SHA512 return .rsaSignatureMessagePKCS1v15SHA512
default: default:
fatalError() fatalError()

View File

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

View File

@ -69,7 +69,7 @@ extension SecureEnclave {
switch (attributes.keyType.algorithm, attributes.keyType.size) { switch (attributes.keyType.algorithm, attributes.keyType.size) {
case (.ecdsa, 256): case (.ecdsa, 256):
let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData) 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): case (.mldsa, 65):
guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() }
let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData) let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData)

View File

@ -79,7 +79,7 @@ extension SmartCard {
} }
let key = untypedSafe as! SecKey let key = untypedSafe as! SecKey
var signError: SecurityError? 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) throw SigningError(error: signError)
} }
return signature as Data return signature as Data