6

addPeerPublicKey:keyBits:我正在尝试使用 CryptoExercise 的 SecKeyWrapper方法将 RSA 公钥添加到我的 iPhone 钥匙串中。此方法的逻辑是它首先尝试将密钥添加到钥匙串,如果它已经存在(sanityCheck==errSecDuplicateItem),它会尝试通过调用从钥匙串中检索此密钥SecKeyItemCopyMatching()

这正是我的情况:钥匙已经在钥匙串中,所以调用SecKeyItemAdd() returns errSecDuplicateItem.

然后它会尝试检索现有的密钥,但是SecKeyItemCopyMatching() returns 0(表明没有错误)但第二个参数 ( peerKeyRef) 仍然绝望地为零。

这怎么可能?这有什么问题?

以下是[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;
}
4

1 回答 1

4

我遇到了同样的问题,我假设您尝试导入不是从另一台 iOS 设备导出的 RSA 密钥。

原因似乎是不兼容的密钥格式 - 详细而言,iOS 期望不设置某些 ASN1 标头。为什么函数返回 OK 对我来说只能用一个错误来解释......

查看http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/上的代码,这是正确的解决方案,对我有用 - 非常感谢 Chris Luke

于 2013-07-20T14:21:26.290 回答