【问题标题】:iOS keychain issue. SecKeyRef always is null as result of SecItemCopyMatching()iOS 钥匙串问题。由于 SecItemCopyMatching() 的结果,SecKeyRef 始终为 null
【发布时间】:2012-07-02 21:05:31
【问题描述】:

SecKeyRef 始终为空,即使我没有从任何状态中得到任何错误。我最初认为这是一个弧线问题,但演员表看起来还不错。任何帮助将不胜感激。

+ (SecKeyRef)addPublicKey:(NSString *)key withTag:(NSString *)tag
    {
        // This will be base64 encoded, decode it.
        NSData *d_key = [key dataUsingEncoding:NSUTF8StringEncoding];

        if (d_key == nil) return (FALSE);

        NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];

        // Delete any old lingering key with the same tag
        NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
        [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
        [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
        [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
        SecItemDelete((__bridge CFDictionaryRef)publicKey);

        CFTypeRef persistKey = nil;

        // Add persistent version of the key to system keychain
        [publicKey setObject:d_key forKey:(__bridge id)kSecValueData];
        [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)kSecAttrKeyClass];
        [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];

        OSStatus secStatus = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);

        NSLog(@"OSStatus = %ld", secStatus);  // Always returns no error = 0

        if (persistKey != nil) CFRelease(persistKey);

        if ((secStatus != noErr) && (secStatus != errSecDuplicateItem)) {
            return nil;
        }

        // Now fetch the SecKeyRef version of the key
        SecKeyRef keyRef;

        [publicKey removeObjectForKey:(__bridge id)kSecValueData];
        [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
        [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
        [publicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];


        secStatus = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);

        NSLog(@"secStatus = %ld", secStatus); // Always returns no error = 0

        return keyRef; // Always null!
    }

【问题讨论】:

    标签: objective-c ios keychain


    【解决方案1】:

    我正在做类似的事情并偶然发现了这篇文章。我试过你的代码,它对我来说很好,所以我认为它是正确的。我怀疑关键数据有误。我尝试通过这种方法提供错误的关键数据,它给了我一个空引用,就像你说的那样。我正在使用这个从模数和指数构建公钥(ASN.1 DER)-

    https://github.com/meinside/iphonelib/blob/master/security/CryptoUtil.m#L67

    请注意,有几个待处理的拉取请求。

    我认为也许你应该尝试一个 .cer 文件或使用 openssl 生成一个 rsa 密钥,并使用 CryptoUtil 的模数和指数。

    【讨论】:

      【解决方案2】:

      我意识到这是一个老问题,但我遇到了同样的问题,所以我将在这里添加我的发现。也许它会帮助别人。

      首先,在您的情况下,您似乎没有在解码 RSA 密钥。您有注释来解码 base64 编码的密钥,但是您只需将其转换为 NSData 对象。您必须对 RSA 密钥进行 base64 解码。

      其次,确保从密钥字符串中去除标题和任何新行。

      然后 base64 解码字符串并将其转换为 NSData 以用于 kSecValueData。

      在我的情况下,我将密钥转换为 NSData,然后对其进行解码...不确定这是否是解码器的问题,但我一直得到一个空的 secKeyRef。我的解码器仅在我解码密钥字符串然后转换为 NSData 时才有效。

      那条信息让我有一阵子退缩了。

      【讨论】:

        【解决方案3】:

        我也遇到了这个问题,最后可以通过以正确的格式(ASN.1 DER 格式)发送输入数据(关键参数)来解决它。尽管没有错误和状态代码 0,但下面的方法没有产生任何密钥,就像@reedjsmith 提到的那样 - 当数据以任何其他格式(纯 base64 编码数据)或使用 PKCS#1 填充以外的任何内容生成的密钥数据时发送。

        • (SecKeyRef)addPublicKey:(NSString *)key withTag:(NSString *)tag

        【讨论】:

        • 这是一个问题,而不是一个答案。如果您无法发表评论,那么您将无法在短时间内将答案发布为问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-16
        相关资源
        最近更新 更多