Я пытаюсь написать прототип, который генерирует набор ключей эклиптической кривой (256 бит), а затем подписывает сообщение с использованием закрытого ключа. У меня есть код, который генерирует и управляет ключами, которые работают хорошо, но когда я пытаюсь вызвать SecKeyRawSign, я получаю ошибку -50 errSecParam. Код для генерации ключей выглядит следующим образом:SecKeyRawSign возвращает -50 при подписании ключа EC
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)")
}
}
код подписание выглядит следующим образом:
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()
}
Очевидно, что окончательный охранник в знаковой функции в настоящее время отключен, и это возвращение errSecParam.
Кто-нибудь успешно выполнил ввод данных в iOS с помощью ключей ЕС? Если это так, вы видите что-то очевидное здесь? Тангенциально есть способ получить дополнительную информацию о самой ошибке.
Редактировать: Чтобы добавить важную деталь, если я ничего не сделаю, кроме как изменить этот код, чтобы генерировать 2048-битные ключи RSA, код работает нормально. Создаются ключи и сообщение подписывается. Только с 256-битными ключами EC он терпит неудачу. Есть ли альтернативный метод для ECDSA в iOS?