首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS SecKeyRef to NSData

iOS SecKeyRef to NSData
EN

Stack Overflow用户
提问于 2013-05-25 11:18:17
回答 1查看 13.8K关注 0票数 16

我有两个键,公共的和私有的,都存储在SecKeyRef-变量中。为了简单起见,让我们从公共的开始。我想要做的是将它导出到一个NSData对象。为此,Apple提供了一个几乎著名的代码片段,如下所示:

代码语言:javascript
复制
- (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,而且代码看起来是错误的("__bridge“是在每次转换到id之前添加的)。新版本如下:

代码语言:javascript
复制
- (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”的使用
  • 对目标的间接指针的转换--C指针指向'CFTypeRef‘(又名'const *')是不允许的

现在,我希望,在您的帮助下,第一个问题将不再是一个问题,因为我不想构建一个查询或诸如此类的东西,从密钥链提取密钥。,我把它放在一个变量中,我想从中提取它。变量的名字是givenPublicKey,这是我希望转换成NSData的键。

那么,我该怎么做才能解决ARC问题?

跟踪:如何将私钥导出到NSData,因为我已经读过几次我试图使用的函数只适用于公钥。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-05-25 13:16:23

  • 未声明标识符“publicTag”的使用

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

代码语言:javascript
复制
#define kPublicKeyTag "com.apple.sample.publickey"
static const uint8_t publicKeyIdentifier[] = kPublicKeyTag;
NSData *publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
  • 对目标的间接指针的转换--C指针指向'CFTypeRef‘(又名'const *')是不允许的

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

代码语言:javascript
复制
CFTypeRef result;
sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, &result);
if (sanityCheck == errSecSuccess) {
    publicKeyBits = CFBridgingRelease(result);
}
  • 我不想构建一个查询或者其他什么东西来从密钥链中提取密钥。我把它放在一个变量中,我想从中提取它.

据我所知,您必须暂时将SecKeyRef存储到密钥链。SecItemAdd可以选择将添加的项作为数据返回。从文件中:

若要作为CFDataRef类型的对象获取添加项的数据,请指定值为kCFBooleanTrue的返回类型键kSecReturnData

将所有这些放在一起,下面的代码应该可以做您想做的事情:

代码语言:javascript
复制
- (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;
}

我希望这是可行的,我现在不能测试它。

  • 跟踪:如何将私钥导出到NSData,因为我已经读过几次我试图使用的函数只适用于公钥。

我不知道。

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16748993

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档