iOS SecKeyRef到NSData

我有两个公钥和私钥,都存储在SecKeyRefvariables中。 为了简单起见,让我们从公开的一个开始。 我想要做的是将其导出到一个NSData对象。 为此,苹果公司提供了一个几乎是着名的代码片段,在这里:

- (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”)。 新版本看起来像这样:

 - (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 ”(又名'const void * ')的Objective-C指针的间接指针的转换不允许使用ARC

现在,我希望在你的帮助下,第一个问题不再是一个问题,因为我不想build立一个查询或者不想从钥匙链中提取密钥。 我有一个variables,我希望从那里提取它。 variables的名字是givenPublicKey ,这就是我希望转换为NSData的键。

那么,我将如何去做这个并解决这个ARC问题呢?

后续:我怎样才能把一个私钥导出到NSData,因为我已经读了好几次,我试图使用的函数只能用于公钥。

  • 使用未公开的标识符“publicTag”

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

 #define kPublicKeyTag "com.apple.sample.publickey" static const uint8_t publicKeyIdentifier[] = kPublicKeyTag; NSData *publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)]; 
  • 对于指向“CFTypeRef”(又名'const void *')的Objective-C指针的间接指针的转换不允许使用ARC

这可以通过使用临时CFTypeRefvariables来解决:

 CFTypeRef result; sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, &result); if (sanityCheck == errSecSuccess) { publicKeyBits = CFBridgingRelease(result); } 
  • 我不想build立一个查询或不要从钥匙串中提取密钥。 我有一个variables,我想从那里提取…

据我所知,你必须临时存储SecKeyRef到钥匙串。 SecItemAdd可以select将添加的项目作为数据返回。 从文档:

要获取添加项的数据作为CFDataReftypes的对象,请指定返回types键kSecReturnData ,其值为kCFBooleanTrue

把所有这些放在一起,下面的代码应该做你想做的事情:

 - (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; } 

我希望这个工作,我目前无法testing。

  • 后续:我怎样才能把一个私钥导出到NSData,因为我已经读了几次,我试图使用的函数只能用于公钥。

我不知道。