2013-07-12 10 views
6

Próbuję dodać klucz publiczny RSA do pęku kluczy mojego iPhone'a za pomocą metody SecKeyWrapper CryptoExercise addPeerPublicKey:keyBits:. Logika tej metody polega na tym, że najpierw próbuje dodać klucz do pęku kluczy, a jeśli już istnieje, to próbuje odzyskać ten klucz z pęku kluczy dzwoniąc pod numer SecKeyItemCopyMatching().SecItemCopyMatching zwraca wartość zerową bez żadnego błędu

To jest dokładnie to, co dzieje się w moim przypadku: klucz jest już w pęku kluczy, więc połączenie z SecKeyItemAdd() returns errSecDuplicateItem.

Następnie próbuje odzyskać istniejący klucz, ale SecKeyItemCopyMatching() returns 0 (wskazując, że nie wystąpił błąd), ale drugi parametr (peerKeyRef) pozostaje desesperately nil.

Jak to jest możliwe? Co jest z tym nie tak?

Oto kod [SecKeyWrapper addPeerPublicKey:keyBits:] z CryptoExercise próbki dla odniesienia:

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

Nie sądzę, że to istotne dla twojego problemu, ale wygląda na to, że zapytanie, które przekazujesz do 'SecItemCopyMatching' zawiera zarówno" kSecReturnRef', jak i 'kSecReturnPersistentRef' ustawione na true. To sprawi, że wartość zostanie zwrócona w 'peerKeyRef' a' CFDictionaryRef' zamiast 'SecKeyRef', której twój kod wydaje się oczekiwać. – bdash

+0

Zauważyłem, że, ale ponieważ tak jest napisane w oryginalnej próbce Apple, zostawiłem to tak, dopóki nie stwarza problemu. Próbowałem usunąć starą wartość i uzyskano ten sam wynik: brak wyniku. – Sebastien

Odpowiedz

4

miałem ten sam problem i zakładam próby importowania klucza RSA, który nie był eksportowany z innego urządzenia z systemem iOS.

Powód wydaje się być niekompatybilnym formatem klucza - w szczegółach system iOS oczekuje, że niektóre nagłówki ASN1 NIE zostaną ustawione. Dlaczego funkcje zwraca OK jest dla mnie wytłumaczalne tylko z błędem ...

Zapoznaj się z kodu w http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/ jest to poprawne rozwiązanie i działa na mnie - tak dzięki Chris Łukasza

+0

Czy macie podobny przykład do klucza prywatnego? – Turowicz

Powiązane problemy