Tôi đang cố gắng thêm khóa công khai RSA vào móc khóa iPhone của mình bằng phương pháp SecKeyWrapper addPeerPublicKey:keyBits:
của CryptoExercise. Logic của phương pháp này là lần đầu tiên cố gắng thêm khóa vào keychain và nếu nó đã có (sanityCheck==errSecDuplicateItem)
, nó sẽ cố gắng truy xuất khóa này từ keychain bằng cách gọi SecKeyItemCopyMatching()
.SecItemCopyMatching trả về giá trị nil mà không có bất kỳ lỗi nào
Đó là chính xác những gì xảy ra trong trường hợp của tôi: chìa khóa đã có trong keychain, vì vậy hãy gọi tới số SecKeyItemAdd() returns errSecDuplicateItem
.
Sau đó, nó cố gắng truy xuất khóa hiện có nhưng SecKeyItemCopyMatching() returns 0
(chỉ ra rằng không có lỗi) nhưng tham số thứ hai (peerKeyRef
) vẫn không đáng kể.
Làm cách nào có thể? Điều gì là sai với điều này?
Đây là mã của [SecKeyWrapper addPeerPublicKey:keyBits:]
từ mẫu CryptoExercise để tham khảo:
- (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;
}
Tôi không nghĩ rằng đó là liên quan đến vấn đề của bạn, nhưng có vẻ như truy vấn bạn đang chuyển đến 'SecItemCopyMatching' bao gồm cả' kSecReturnRef' và 'kSecReturnPersistentRef' được đặt thành true. Điều đó sẽ làm cho giá trị được trả về trong 'peerKeyRef' là' CFDictionaryRef' thay vì 'SecKeyRef' mà mã của bạn trông đợi. – bdash
Tôi nhận thấy rằng, nhưng vì đó là cách nó được viết trong mẫu Apple gốc, tôi để nó như thế cho đến khi nó tạo ra một vấn đề. Tôi đã cố gắng để loại bỏ giá trị cũ và nó mang lại kết quả tương tự: không có kết quả nào cả. – Sebastien