CryptoExercise の SecKeyWrapperaddPeerPublicKey:keyBits:
メソッドを使用して、RSA 公開鍵を iPhone のキーチェーンに追加しようとしています。このメソッドのロジックは、最初にキーをキーチェーンに追加しようとし、既にそこにある(sanityCheck==errSecDuplicateItem)
場合は、を呼び出してキーチェーンからこのキーを取得しようとすることSecKeyItemCopyMatching()
です。
それはまさに私の場合に起こることです: キーはすでにキーチェーンにあるので、SecKeyItemAdd() returns errSecDuplicateItem
.
次に、既存のキーを取得しようとしますがSecKeyItemCopyMatching() returns 0
(エラーがなかったことを示します)、2 番目のパラメーター ( peerKeyRef
) は必死に nil のままです。
これはどのように可能ですか?これの何が問題なのですか?
[SecKeyWrapper addPeerPublicKey:keyBits:]
参考までに、CryptoExercise サンプルのコードを次に示します。
- (SecKeyRef)addPeerPublicKey:(NSString *)peerName keyBits:(NSData *)publicKey {
OSStatus sanityCheck = noErr;
SecKeyRef peerKeyRef = NULL;
CFTypeRef persistPeer = NULL;
LOGGING_FACILITY( peerName != nil, @"Peer name parameter is nil." );
LOGGING_FACILITY( publicKey != nil, @"Public key parameter is nil." );
NSData *peerTag = [[NSData alloc] initWithBytes:(const void *) [peerName UTF8String] length:[peerName length]];
NSMutableDictionary *peerPublicKeyAttr = [[NSMutableDictionary alloc] init];
[peerPublicKeyAttr setObject:(__bridge id) kSecClassKey forKey:(__bridge id) kSecClass];
[peerPublicKeyAttr setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id) kSecAttrKeyType];
[peerPublicKeyAttr setObject:peerTag forKey:(__bridge id) kSecAttrApplicationTag];
[peerPublicKeyAttr setObject:publicKey forKey:(__bridge id) kSecValueData];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id) kSecReturnPersistentRef];
sanityCheck = SecItemAdd((__bridge CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *) &persistPeer);
// The nice thing about persistent references is that you can write their value out to disk and
// then use them later. I don't do that here but it certainly can make sense for other situations
// where you don't want to have to keep building up dictionaries of attributes to get a reference.
//
// Also take a look at SecKeyWrapper's methods (CFTypeRef)getPersistentKeyRefWithKeyRef:(SecKeyRef)key
// & (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef.
LOGGING_FACILITY1( sanityCheck == noErr || sanityCheck == errSecDuplicateItem, @"Problem adding the peer public key to the keychain, OSStatus == %ld.", sanityCheck );
if (persistPeer) {
peerKeyRef = [self getKeyRefWithPersistentKeyRef:persistPeer];
} else {
[peerPublicKeyAttr removeObjectForKey:(__bridge id) kSecValueData];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id) kSecReturnRef];
// Let's retry a different way.
sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *) &peerKeyRef);
}
LOGGING_FACILITY1( sanityCheck == noErr && peerKeyRef != NULL, @"Problem acquiring reference to the public key, OSStatus == %ld.", sanityCheck );
if (persistPeer) CFRelease(persistPeer);
return peerKeyRef;
}