2009-10-08 5 views

Répondre

2

Le code suivant provient de CryptoExercise exemple d'Apple, en SecKeyWrapper.m. Il suppose que l'objet NSData "publicKey" est l'objet ASN.1 codé en DER binaire, non codé en base 64. Vous devrez donc obtenir un décodeur de base 64 et l'appliquer en premier. Vous pouvez également lire this post dans les Forums des développeurs Apple.

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

Dans le cas où quelqu'un vient sur cette question et cherche la réponse de cacao:

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); 
Questions connexes