iOS:存储在安全飞地中的密钥不支持解密

iOS: Decryption not supported on key stored in secure enclave

编译 iOS 11(据称解决了所有与安全飞地相关的错误),我正在尝试创建存储在安全飞地中的密钥对以用于 encrypting/decrypting 数据,但是某处密钥被损坏:

CFErrorRef error = NULL;
NSError *gen_error = nil;

SecAccessControlRef sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlBiometryAny, &error);

if (sacObject == NULL || error != NULL) { /* handled */ }

NSDictionary *keyAttributes = @{
    (id)kSecClass: (id)kSecClassKey,
    (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC,
    (id)kSecAttrKeySizeInBits: @256,
    (id)kSecAttrTokenID: (id)kSecAttrTokenIDSecureEnclave,
    (id)kSecAttrIsPermanent: @YES,
    (id)kSecAttrApplicationTag: biometricKeyTag, //static between all calls
    (id)kSecAttrAccessControl: (__bridge_transfer id)sacObject,
};

SecKeyRef privateKey = (__bridge SecKeyRef) CFBridgingRelease(SecKeyCreateRandomKey((__bridge CFDictionaryRef)keyAttributes, (void *)&gen_error));

if (gen_error != nil || privateKey == nil) { /* handled */ }

SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey);

Boolean algorithmDSupported = SecKeyIsAlgorithmSupported(privateKey, kSecKeyOperationTypeDecrypt, kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM);
Boolean algorithmESupported = SecKeyIsAlgorithmSupported(publicKey, kSecKeyOperationTypeEncrypt, kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM);
// Returns true for both

// OK so far!

// Now retrieve the key just create to mock up using it later

NSDictionary *query = @{
    (id)kSecClass: (id)kSecClassKey,
    (id)kSecAttrApplicationTag: biometricKeyTag,
    (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC,
    (id)kSecReturnRef: @YES,
    (id)kSecUseOperationPrompt: @""
};
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&privateKey);

if (status != noErr || privateKey == NULL) { /* handled */ }

publicKey = SecKeyCopyPublicKey(privateKey);
Boolean algorithmDSupported2 = SecKeyIsAlgorithmSupported(privateKey, kSecKeyOperationTypeDecrypt, kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM);
Boolean algorithmESupported2 = SecKeyIsAlgorithmSupported(publicKey, kSecKeyOperationTypeEncrypt, kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM);
// Encryption on the public key is supported, but algorithmDSupported2 is false – cannot decrypt with the key any more

使用 SecItemCopyMatching 检索的密钥与 SecKeyCreateEncryptedData 加密似乎可行,但 SecKeyIsAlgorithmSupported on …TypeDecrypt returns 这些密钥为 false,并且无论如何尝试解密都会使应用程序崩溃。

How/why取回密钥后是不是失效了?

最后解决的是

  • 将 SecAccessControl 标志更改为 kSecAccessControlBiometryAny|kSecAccessControlPrivateKeyUsage
  • 正在将密钥类型更改为 kSecAttrKeyTypeECSECPrimeRandom
  • 移动 kSecPrivateKeyAttrs 键下的键属性

不知道为什么 Apple 让你搬起石头砸自己的脚,却没有正确验证密钥生成参数。