我在base64中有一个RSa publicKey值,如何在不添加Keychain的情况下转换为SecKeyRef对象 我可以将RSA Raw值添加到不是X509格式的Keychain中吗?
提前致谢
答案 0 :(得分:2)
以下代码来自Apple的CryptoExercise示例,位于SecKeyWrapper.m中。它假定“publicKey”NSData对象是二进制DER编码的ASN.1对象,而不是base-64编码。因此,您必须先获得base-64解码器并应用它。您可能还想阅读Apple Developer论坛中的this post。
- (SecKeyRef)addPeerPublicKey:(NSString *)peerName keyBits:(NSData *)publicKey {
OSStatus sanityCheck = noErr;
SecKeyRef peerKeyRef = NULL;
CFTypeRef persistPeer = NULL;
LOGGING_FACILITY( peerName != nil, @"Peer name parameter is nil." );
LOGGING_FACILITY( publicKey != nil, @"Public key parameter is nil." );
NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]];
NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init];
[peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
[peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag];
[peerPublicKeyAttr setObject:publicKey forKey:(id)kSecValueData];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];
sanityCheck = SecItemAdd((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&persistPeer);
// The nice thing about persistent references is that you can write their value out to disk and
// then use them later. I don't do that here but it certainly can make sense for other situations
// where you don't want to have to keep building up dictionaries of attributes to get a reference.
//
// Also take a look at SecKeyWrapper's methods (CFTypeRef)getPersistentKeyRefWithKeyRef:(SecKeyRef)key
// & (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef.
LOGGING_FACILITY1( sanityCheck == noErr || sanityCheck == errSecDuplicateItem, @"Problem adding the peer public key to the keychain, OSStatus == %d.", sanityCheck );
if (persistPeer) {
peerKeyRef = [self getKeyRefWithPersistentKeyRef:persistPeer];
} else {
[peerPublicKeyAttr removeObjectForKey:(id)kSecValueData];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];
// Let's retry a different way.
sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&peerKeyRef);
}
LOGGING_FACILITY1( sanityCheck == noErr && peerKeyRef != NULL, @"Problem acquiring reference to the public key, OSStatus == %d.", sanityCheck );
[peerTag release];
[peerPublicKeyAttr release];
if (persistPeer) CFRelease(persistPeer);
return peerKeyRef;
}
答案 1 :(得分:1)
如果有人遇到这个问题并且正在寻找Cocoa答案:
NSData *privateKeyPEMData = [privateKeyPEM dataUsingEncoding:NSUTF8StringEncoding];
CFArrayRef imported = NULL;
SecKeychainRef importedKeychain = NULL;
OSStatus err = 0;
SecExternalFormat format = kSecFormatOpenSSL;
SecKeyRef privateKey = NULL;
[privateKeyString dataUsingEncoding:NSUTF8StringEncoding];
err = SecItemImport((__bridge CFDataRef)(privateKeyPEMData), (CFStringRef)@"pem", &format, NULL, kNilOptions, kNilOptions, importedKeychain, &imported);
NSLog(@"%@ ERROR: %@", self.class, [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil]);
assert(err == errSecSuccess);
assert(CFArrayGetCount(imported) == 1);
privateKey = (SecKeyRef)CFArrayGetValueAtIndex(imported, 0);