2013-07-12 13 views
6

Ich versuche, einen öffentlichen RSA Schlüssel zu meinem iPhone Schlüsselbund mit CryptoExercise SecKeyWrapper addPeerPublicKey:keyBits: Methode hinzuzufügen. Die Logik dieser Methode ist, dass es zunächst versucht, den Schlüssel zum Schlüsselbund hinzuzufügen, und wenn es bereits dort (sanityCheck==errSecDuplicateItem) versucht, diesen Schlüssel aus dem Schlüsselbund durch Aufrufen von SecKeyItemCopyMatching() abrufen.SecItemCopyMatching gibt keinen Wert ohne Fehler zurück.

Genau das passiert in meinem Fall: Der Schlüssel ist bereits im Schlüsselbund, also der Anruf an SecKeyItemAdd() returns errSecDuplicateItem.

Dann versucht es, den vorhandenen Schlüssel aber SecKeyItemCopyMatching() returns 0 abzurufen (anzeigend, dass es keinen Fehler gab), aber der zweite Parameter (peerKeyRef) bleibt desesperate Null.

Wie ist das möglich? Was ist daran falsch? Hier

ist der Code von [SecKeyWrapper addPeerPublicKey:keyBits:] von CryptoExercise Probe als Referenz:

- (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:(__bridge id) kSecClassKey forKey:(__bridge id) kSecClass]; 
    [peerPublicKeyAttr setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id) kSecAttrKeyType]; 
    [peerPublicKeyAttr setObject:peerTag forKey:(__bridge id) kSecAttrApplicationTag]; 
    [peerPublicKeyAttr setObject:publicKey forKey:(__bridge id) kSecValueData]; 
    [peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id) kSecReturnPersistentRef]; 

    sanityCheck = SecItemAdd((__bridge 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 == %ld.", sanityCheck); 

    if (persistPeer) { 
     peerKeyRef = [self getKeyRefWithPersistentKeyRef:persistPeer]; 
    } else { 
     [peerPublicKeyAttr removeObjectForKey:(__bridge id) kSecValueData]; 
     [peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id) kSecReturnRef]; 
     // Let's retry a different way. 
     sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *) &peerKeyRef); 
    } 

    LOGGING_FACILITY1(sanityCheck == noErr && peerKeyRef != NULL, @"Problem acquiring reference to the public key, OSStatus == %ld.", sanityCheck); 

    if (persistPeer) CFRelease(persistPeer); 
    return peerKeyRef; 
} 
+1

Ich glaube nicht, dass es relevant für Ihr Problem, aber es scheint so, als ob die Abfrage, die Sie an "SecItemCopyMatching" übergeben, sowohl "kSecReturnRef" als auch "kSecReturnPersistentRef" enthält, die auf "true" gesetzt sind. Dadurch wird der Wert in "peerKeyRef" und "CFDictionaryRef" zurückgegeben und nicht in dem von Ihrem Code erwarteten 'SecKeyRef'. – bdash

+0

Das ist mir aufgefallen, aber da es so ist, wie es im ursprünglichen Apple-Beispiel geschrieben ist, habe ich es so gelassen, bis es ein Problem verursacht. Ich habe versucht, den alten Wert zu entfernen, und es ergab dasselbe Ergebnis: kein Ergebnis. – Sebastien

Antwort

4

Ich hatte das gleiche Problem, und ich nehme an, Sie versuchen, einen RSA-Schlüssel zu importieren, die nicht von einem anderen iOS-Gerät exportiert wurde.

Der Grund scheint ein inkompatibles Schlüsselformat zu sein - im Detail erwartet iOS, dass einige ASN1-Header NICHT gesetzt werden. Warum die Funktionen OK zurückgibt, ist für mich nur erklärbar mit einem Fehler ...

Überprüfen Sie den Code aus bei http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/ dies die richtige Lösung ist, und arbeitet für mich - so dank Chris Luke

+0

Haben Sie ein ähnliches Beispiel für einen privaten Schlüssel? – Turowicz

Verwandte Themen