iOS SecKeyRef到NSData [英] iOS SecKeyRef to NSData

查看:310
本文介绍了iOS SecKeyRef到NSData的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个密钥,public和private,都存储在SecKeyRef变量中。为简单起见,让我们从公众开始吧。我想做的是将它导出到NSData对象。为此,Apple提供了几乎着名的代码片段,其中包括:

I have two keys, public and private, that are both stored in SecKeyRef-variables. For simplicity's sake, let's start with the public one. What I wanna do is export it to an NSData object. For that, there is an almost famous code snippet provide by Apple, which is here:

- (NSData *)getPublicKeyBits {
    OSStatus sanityCheck = noErr;
    NSData * publicKeyBits = nil;

    NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init];

    // Set the public key query dictionary.
    [queryPublicKey setObject:(id)kSecClassKey forKey:(id)kSecClass];
    [queryPublicKey setObject:publicTag forKey:(id)kSecAttrApplicationTag];
    [queryPublicKey setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
    [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData];

    // Get the key bits.
    sanityCheck = SecItemCopyMatching((CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKeyBits);

    if (sanityCheck != noErr)
    {
        publicKeyBits = nil;
    }

    [queryPublicKey release];

    return publicKeyBits;
}

我有Xcode 4.6.2,但代码看似错误(在每次转换为id之前添加__bridge。新版本看起来像这样:

I have Xcode 4.6.2, however, and the code appears erroneous ("__bridge" is added before each conversion to id). The new version looks like this:

- (NSData *)getPublicKeyBitsFromKey:(SecKeyRef)givenKey {
    OSStatus sanityCheck = noErr;
    NSData * publicKeyBits = nil;

    NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init];

    // Set the public key query dictionary.
    [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
    [queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
    [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnData];

    // Get the key bits.
    sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKeyBits);

    if (sanityCheck != noErr)
    {
        publicKeyBits = nil;
    }

    return publicKeyBits;
}

但仍有两个错误:


  • 使用未声明的标识符'publicTag'

  • 强制转换指向'CFTypeRef '的Objective-C指针的间接指针(又名'const void * ')不允许使用ARC

  • use of undeclared identifier 'publicTag'
  • Cast of an indirect pointer to an Objective-C pointer to 'CFTypeRef ' (aka 'const void *') is disallowed with ARC

现在,我希望在你的帮助下,第一个问题将不再是一个问题,因为我不想构建一个查询或诸如此类来从密钥链中提取密钥。 我在变量中有它,我希望从那里提取它。变量的名称是 givenPublicKey ,这是我希望转换为的键NSData。

Now, I hope that after your help, the first issue will no longer be a problem, for I do not want to build a query or whatnot to extract the key from the keychain. I have it in a variable and I wish to extract it from there. The variable's name is givenPublicKey, and that's the key I wish to convert to NSData.

那么,我将如何解决这个ARC问题?

So, how would I go about doing this and solving this ARC-issue?

关注 - up:如何将私有密钥导出到NSData,因为我已经多次读过我正在尝试使用的函数仅适用于公钥。

Follow-up: How can I export a private key to NSData, since I've read several time that the function I'm trying to work with only works for public keys.

推荐答案


  • 使用未声明的标识符'publicTag'

  • publicTag 只是添加到Keychain项目的一些唯一标识符。在CryptoExercise示例项目中,它被定义为

    The publicTag is just some unique identifier added to the Keychain items. In the CryptoExercise sample project it is defined as

    #define kPublicKeyTag "com.apple.sample.publickey"
    static const uint8_t publicKeyIdentifier[] = kPublicKeyTag;
    NSData *publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
    




    • 强制转换指向'CFTypeRef的Objective-C指针的间接指针'(又名'const void *')不允许使用ARC

    • 这可以通过使用临时来解决CFTypeRef 变量:

      This can be solved by using a temporary CFTypeRef variable:

      CFTypeRef result;
      sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, &result);
      if (sanityCheck == errSecSuccess) {
          publicKeyBits = CFBridgingRelease(result);
      }
      




      • 我不想构建查询或什么从钥匙串中提取钥匙。我有一个变量,我想从那里提取它...

      • 据我所知,你必须存储SecKeyRef临时到Keychain。 SecItemAdd
        可以选择将添加的项目作为数据返回。从文档中:

        As far as I know, you have to store the SecKeyRef to the Keychain temporarily. SecItemAdd has the option to return the added item as data. From the documentation:


        获取添加项目的数据作为 CFDataRef
        指定返回类型键 kSecReturnData ,其值为
        kCFBooleanTrue

        将所有这些放在一起,以下代码应该做你想要的:

        Putting all that together, the following code should do what you want:

        - (NSData *)getPublicKeyBitsFromKey:(SecKeyRef)givenKey {
        
            static const uint8_t publicKeyIdentifier[] = "com.your.company.publickey";
            NSData *publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
        
            OSStatus sanityCheck = noErr;
            NSData * publicKeyBits = nil;
        
            NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init];
            [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
            [queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
            [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
        
            // Temporarily add key to the Keychain, return as data:
            NSMutableDictionary * attributes = [queryPublicKey mutableCopy];
            [attributes setObject:(__bridge id)givenKey forKey:(__bridge id)kSecValueRef];
            [attributes setObject:@YES forKey:(__bridge id)kSecReturnData];
            CFTypeRef result;
            sanityCheck = SecItemAdd((__bridge CFDictionaryRef) attributes, &result);
            if (sanityCheck == errSecSuccess) {
                publicKeyBits = CFBridgingRelease(result);
        
                // Remove from Keychain again:
                (void)SecItemDelete((__bridge CFDictionaryRef) queryPublicKey);
            }
        
            return publicKeyBits;
        }
        

        我希望这有效,我目前无法测试。

        I hope that this works, I cannot test it at the moment.


        • 后续:如何将私钥导出到NSData,因为我已经读了好几次我正在尝试工作的函数仅适用于公钥。

        我不知道。

        这篇关于iOS SecKeyRef到NSData的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆