Я пытаюсь сделать следующее в моем IOS приложении:Ошибка аутентификации пытается подписать данные с ЕС закрытым ключом от Secure Enclave
- генерировать пару ключей с помощью
SecKeyGeneratePair
, хранение секретного ключа в Secure Enclave - Войдите некоторые данные, используя секретный ключ
Это работает, если я повешу на секретный ключе справки, когда ключи первые сгенерированными, но не работает, если я пытаюсь извлечь ссылку из брелки после отбрасывания начальный p ointer.
Ключи генерируются следующим образом:
func generateKeyPair() -> Bool {
if let access = SecAccessControlCreateWithFlags(nil,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
[.userPresence, .privateKeyUsage],
nil) {
let privateKeyAttr = [kSecAttrIsPermanent : 1,
kSecAttrApplicationTag : privateTag,
kSecAttrAccessControl as String: access
] as NSDictionary
let publicKeyAttr = [kSecAttrIsPermanent : 0,
kSecAttrApplicationTag : publicTag
] as NSDictionary
let keyPairAttr = [kSecAttrKeySizeInBits : 256,
kSecAttrKeyType : kSecAttrKeyTypeEC,
kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
kSecPrivateKeyAttrs : privateKeyAttr,
kSecPublicKeyAttrs : publicKeyAttr] as NSDictionary
let err = SecKeyGeneratePair(keyPairAttr, &publicKey, &privateKey)
return err == noErr
}
метод Подписание ниже:
func signData(plainText: Data) -> NSData? {
guard privateKey != nil else {
print("Private key unavailable")
return nil
}
let digestToSign = self.sha1DigestForData(data: plainText as NSData) as Data
let signature = UnsafeMutablePointer<UInt8>.allocate(capacity: 128)
var signatureLength = 128
let err = SecKeyRawSign(privateKey!,
.PKCS1SHA1,
[UInt8](digestToSign),
Int(CC_SHA1_DIGEST_LENGTH),
signature,
&signatureLength)
print("Signature status: \(err)")
let sigData = NSData(bytes: signature, length: Int(signatureLength))
return sigData
}
func sha1DigestForData(data: NSData) -> NSData {
let len = Int(CC_SHA1_DIGEST_LENGTH)
let digest = UnsafeMutablePointer<UInt8>.allocate(capacity: len)
CC_SHA1(data.bytes, CC_LONG(data.length), digest)
return NSData(bytesNoCopy: UnsafeMutableRawPointer(digest), length: len)
}
Это просит моего отпечатка пальца и работает безупречно. Затем я использую другой способ, чтобы получить ключ ссылки из брелка:
func getPrivateKeyRef() -> SecKey? {
let parameters = [
kSecClass as String: kSecClassKey,
kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
kSecAttrApplicationTag as String: privateTag,
kSecReturnRef as String: true,
] as [String : Any]
var ref: AnyObject?
let status = SecItemCopyMatching(parameters as CFDictionary, &ref)
print("Get key status: \(status)")
if status == errSecSuccess { return ref as! SecKey? } else { return nil }
}
SecItemCopyMatching
возвращает статус успеха, но попытка использовать полученный SecKey
элемент в качестве секретного ключа в SecKeyRawSign
приводит к ошибке -25293 Authorization/Authentication failed.
появляется только этот статус после того, как я предоставил свой отпечаток, так что фактическая проверка отпечатка пальца удалась, но ключ каким-то образом остается непригодным.
Каков правильный способ использования ключа, сохраненного в Secure Enclave, для подписи данных?
Вы были в состоянии получить это работает? У меня такая же проблема, SecItemCopyMatch успешна, но диалог отпечатков пальцев не запускается, и SecKeyRawSign терпит неудачу. – Krypton
@ Криптон да, см. Мой собственный ответ ниже, как я получил его на работу. – SaltyNuts