- (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之前被添加).新版本如下所示:
- (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
现在,我希望在您的帮助之后,第一个问题将不再是一个问题,因为我不想构建一个查询或什么不能从钥匙串中提取密钥.我有一个变量,我想从中提取它.该变量的名称为givenPublicKey,这是我要转换为NSData的关键字.
那么,我怎么去做这个和解决这个ARC问题?
后续程序:如何将私钥导出到NSData,因为我已经读了几次,我正在尝试使用的功能只适用于公钥.
解决方法
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
这可以通过使用临时CFTypeRef变量来解决:
CFTypeRef result; sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey,&result); if (sanityCheck == errSecSuccess) { publicKeyBits = CFBridgingRelease(result); }
>我不想构建一个查询,或者什么不能从钥匙串中提取密钥.我有一个变量,我想从中提取它
据我所知,您必须临时将密钥匙存储到钥匙扣. SecItemAdd
可以选择将添加的项目作为数据返回.从文档:
To obtain the data of the added item as an object of type
CFDataRef
,
specify the return type keykSecReturnData
with a value of
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; }
我希望这样工作,我现在不能测试.
>跟进:如何将私钥导出到NSData,因为我已经读了好几次,我正在尝试使用的功能只适用于公钥.
我不知道.