2013-05-25 32 views
14

Tôi có hai khóa, công khai và riêng tư, cả hai đều được lưu trữ trong các biến SecKeyRef. Để đơn giản, hãy bắt đầu với công chúng. Những gì tôi muốn làm là xuất nó sang một đối tượng NSData. Cho rằng, có một đoạn mã gần như nổi tiếng cung cấp bởi Apple, mà là ở đây:iOS SecKeyRef đến 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; 
} 

Tôi có Xcode 4.6.2, tuy nhiên, và mã xuất hiện có sai sót ("__bridge" được thêm vào trước mỗi chuyển đổi sang id). Phiên bản mới trông như thế này:

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

Hiện vẫn còn hai lỗi, mặc dù:

  • sử dụng định danh chưa được khai báo 'publicTag'
  • Cast của một con trỏ gián tiếp đến một con trỏ Objective-C để 'CFTypeRef ' (aka 'khoảng trống const *') là không được phép với ARC

Bây giờ, tôi hy vọng rằng sau khi giúp đỡ của bạn, vấn đề đầu tiên w bệnh không còn là một vấn đề, vì tôi không muốn xây dựng một truy vấn hoặc không có gì để trích xuất khóa từ keychain. Tôi có nó trong một biến và tôi muốn trích xuất nó từ đó. Tên biến là givenPublicKey và đó là khóa tôi muốn chuyển đổi thành NSData.

Vì vậy, làm cách nào để tôi thực hiện việc này và giải quyết vấn đề ARC này?

Theo dõi: Làm cách nào để xuất khóa riêng sang NSData, vì tôi đã đọc một vài lần chức năng mà tôi đang cố gắng làm việc chỉ hoạt động với khóa công khai.

+0

Bạn có thể tham chiếu đoạn mã tới tài liệu/trang web của Apple không? – MCKapur

+0

Chắc chắn, đây là: http://developer.apple.com/library/ios/#samplecode/CryptoExercise/Listings/Classes_SecKeyWrapper_m.html#//apple_ref/doc/uid/DTS40008019-Classes_SecKeyWrapper_m-DontLinkElementID_17 – arik

Trả lời

11
  • sử dụng định danh chưa được khai báo 'publicTag'

Các publicTag chỉ là một số định danh duy nhất được bổ sung vào các mục Keychain. Trong dự án mẫu CryptoExercise nó được định nghĩa là

#define kPublicKeyTag "com.apple.sample.publickey" 
static const uint8_t publicKeyIdentifier[] = kPublicKeyTag; 
NSData *publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)]; 
  • Cast của một con trỏ gián tiếp đến một con trỏ Objective-C để 'CFTypeRef' (aka 'const void *') là không được phép với ARC

này có thể được giải quyết bằng cách sử dụng một tạm thời CFTypeRef biến:

CFTypeRef result; 
sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, &result); 
if (sanityCheck == errSecSuccess) { 
    publicKeyBits = CFBridgingRelease(result); 
} 
  • tôi không muốn xây dựng một truy vấn hoặc whatnot để trích xuất khóa từ keychain. Tôi có nó trong một biến và tôi muốn trích xuất nó từ đó ...

Theo như tôi biết, bạn phải lưu trữ SecKeyRef cho Keychain tạm thời. SecItemAdd có tùy chọn trả lại mục được thêm dưới dạng dữ liệu. Từ các tài liệu:

Để có được các dữ liệu của mục thêm vào như là một đối tượng kiểu CFDataRef, xác định kiểu trả về chính kSecReturnData với một giá trị của kCFBooleanTrue.

Đưa tất cả những gì với nhau, các mã sau đây nên làm những gì bạn muốn:

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

Tôi hy vọng rằng công trình này, tôi không thể kiểm tra nó vào lúc này.

  • Theo dõi: Làm cách nào tôi có thể xuất khóa riêng sang NSData, vì tôi đã đọc nhiều lần chức năng tôi đang cố gắng làm việc chỉ hoạt động với khóa công khai.

Tôi không biết.

+0

Cảm ơn, nó hoạt động ! – arik

+0

chúng ta có thể sử dụng nó cho mac? trả về lỗi - khóa không hợp lệ khi được sử dụng – Adwait

+1

Tôi lấy lại kích thước lạ cho dữ liệu chính. Trong trường hợp của tôi, tôi đã nhập một danh tính có khóa 2048bit (256 byte), Tuy nhiên NSData được trả lại từ hàm này có kích thước 270 byte. – liamo

Các vấn đề liên quan