Ich versuche, einen Prototyp zu schreiben, der eine Reihe von Ecliptic Curve-Schlüsseln (256 Bit) generiert und dann eine Nachricht mit dem privaten Schlüssel signiert. Ich habe Code, der die Schlüssel erzeugt und verwaltet, was gut funktioniert, aber wenn ich versuche, SecKeyRawSign aufzurufen, bekomme ich einen Fehler von -50 errSecParam. Der Code, um die Schlüssel zu generieren sieht wie folgt aus:SecKeyRawSign gibt beim Signieren mit EC-Schlüssel -50 zurück
private func generateKeyPair() throws {
var error: Unmanaged<CFError>? = nil
let acl = SecAccessControlCreateWithFlags(nil, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
[.touchIDAny, .privateKeyUsage], &error)
guard error == nil else {
throw MessageError(message: "Could not create ACL: \(error)")
}
// We don't want the public key stored in the ecure enclave, so we create it as
// non permament and add it manually to the keychain later
let publicKeyParameters: [CFString: Any] = [
kSecAttrIsPermanent: false,
kSecAttrApplicationTag: ViewController.KeyTag,
kSecAttrLabel: ViewController.PublicLabel
]
let privateKeyParameters: [CFString: Any] = [
kSecAttrIsPermanent: true,
kSecAttrApplicationTag: ViewController.KeyTag,
kSecAttrLabel: ViewController.PrivateLabel,
kSecAttrAccessControl: acl!
]
var parameters: [CFString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeEC,
kSecAttrKeySizeInBits: NSNumber(value: 256),
kSecPublicKeyAttrs: publicKeyParameters,
kSecPrivateKeyAttrs: privateKeyParameters
]
// On the simulator we can't use the Secure Enclave
if hasSecureEnclave() {
parameters[kSecAttrTokenID] = kSecAttrTokenIDSecureEnclave
}
var pubKeyRef, privKeyRef: SecKey?
var result = SecKeyGeneratePair(parameters as CFDictionary, &pubKeyRef, &privKeyRef)
guard result == noErr else {
throw MessageError(message: "Could not create key pair: \(result)")
}
parameters = [
kSecClass: kSecClassKey,
kSecAttrKeyType: kSecAttrKeyTypeEC,
kSecAttrApplicationTag: ViewController.KeyTag,
kSecAttrLabel: ViewController.PublicLabel,
kSecAttrKeyClass: kSecAttrKeyClassPublic,
kSecValueRef: pubKeyRef!
]
result = SecItemAdd(parameters as CFDictionary, nil)
guard result == noErr else {
throw MessageError(message: "Could not add public key to keychain: \(result)")
}
}
Der Code zur Unterzeichnung wie folgt aussieht:
private func signWithPrivateKey(_ text: String, _ key: SecKey) throws -> String? {
var digest = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
let data = text.data(using: .utf8)!
let _ = digest.withUnsafeMutableBytes { digestBytes in
data.withUnsafeBytes { dataBytes in
CC_SHA256(dataBytes, CC_LONG(data.count), digestBytes)
}
}
var signature = Data(count: SecKeyGetBlockSize(key))
var signatureLength = signature.count
let result = signature.withUnsafeMutableBytes { signatureBytes in
digest.withUnsafeBytes { digestBytes in
SecKeyRawSign(key,
SecPadding.PKCS1SHA256,
digestBytes,
digest.count,
signatureBytes,
&signatureLength)
}
}
guard result == noErr else {
throw MessageError(message: "Could not sign data: \(result)")
}
return signature.base64EncodedString()
}
Offensichtlich ist die letzte Wache in der Signum-Funktion wird ausgelöst, und es ist der Rückkehr errSecParam.
Hat jemand erfolgreich Datensignierung in iOS mit EC-Schlüsseln durchgeführt? Wenn ja, siehst du hier etwas Offensichtliches? Tangential gibt es eine Möglichkeit, mehr Informationen über den Fehler selbst zu erhalten.
Edit: Um ein wichtiges Detail hinzuzufügen, wenn ich nichts anderes mache, als diesen Code zu ändern, um stattdessen 2048 Bit RSA-Schlüssel zu generieren, funktioniert der Code gut. Schlüssel generieren und die Nachricht ist signiert. Es ist nur mit 256-Bit-EC-Schlüsseln, dass es fehlschlägt. Gibt es eine alternative Methode für ECDSA in iOS?