2013-05-25 6 views
14

У меня есть два ключа, общедоступные и частные, которые хранятся в SecKeyRef-переменных. Для простоты, давайте начнем с публичного. Я хочу сделать это, экспортируя его в объект NSData. Для этого есть почти известный фрагмент кода обеспечивает от Apple, которая здесь:iOS SecKeyRef to NSData

- (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» добавляются перед каждым переходом к идентификатору). Новая версия выглядит следующим образом:

- (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»
  • Cast косвенного указателя на указатель Objective-C для «CFTypeRef » (он же «сопзЬ пустота *») отвергается с ARC

Теперь, я надеюсь, что после вашей помощи, первый номер ш я больше не буду проблемой, потому что я не хочу строить запрос или еще что-то, чтобы извлечь ключ из брелка. У меня есть переменная, и я хочу извлечь ее оттуда. Имя переменной givenPublicKey, и это ключ, который я хочу преобразовать в NSData.

Итак, как я буду заниматься этим и решить эту проблему с ARC?

Последующие действия: Как я могу экспортировать ключ в NSData, так как я читал несколько раз, что функция, с которой я пытаюсь работать, работает только для открытых ключей.

+0

Не могли бы вы ссылаться на фрагмент кода на документы/сайт Apple? – MCKapur

+0

Конечно, вот оно: http://developer.apple.com/library/ios/#samplecode/CryptoExercise/Listings/Classes_SecKeyWrapper_m.html#//apple_ref/doc/uid/DTS40008019-Classes_SecKeyWrapper_m-DontLinkElementID_17 – arik

ответ

11
  • использование необъявленной идентификатора «publicTag»

publicTag лишь некоторые уникальный идентификатор добавлен в связку ключей элементов. В примере проекта CryptoExercise она определяется как

#define kPublicKeyTag "com.apple.sample.publickey" 
static const uint8_t publicKeyIdentifier[] = kPublicKeyTag; 
NSData *publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)]; 
  • Cast косвенного указателя на указатель Objective-C к 'CFTypeRef' (он же 'сопзЬ пустота *') отвергается с ARC

Это может быть решена с помощью временной переменной: CFTypeRef

CFTypeRef result; 
sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, &result); 
if (sanityCheck == errSecSuccess) { 
    publicKeyBits = CFBridgingRelease(result); 
} 
  • Я не хочу, чтобы построить запрос или еще что-то, чтобы извлечь ключ из брелка. У меня есть переменная, и я хочу ее оттуда ...

Насколько я знаю, вам необходимо временно хранить SecKeyRef в Keychain. SecItemAdd имеет возможность вернуть добавленный элемент в качестве данных. Из документации:

Чтобы получить данные добавленного элемента в качестве объекта типа CFDataRef, указать тип возвращаемого значения ключа kSecReturnData со значением 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, так как я читал несколько раз, что функция, с которой я пытаюсь работать, работает только для открытых ключей.

Я не знаю.

+0

Спасибо, это работает ! – arik

+0

мы можем использовать его для mac? возвращает ошибку - недействительный ключ при использовании – Adwait

+1

Я возвращаю странный размер для данных ключа. В моем случае я импортировал идентификатор с 2048-битным ключом (256 байтов), однако NSData, возвращенный из этой функции, имеет размер 270 байт. – liamo