2014-06-28 14 views
11

Cho một SecKeyRef được nạp bằng cách sử dụng SecItemImport từ khóa riêng RSA có cách nào để lấy hoặc tạo SecKeyRef chỉ cho các thành phần khóa công khai không? Trong OpenSSL, điều này có thể được thực hiện bằng cách sao chép mô-đun và số mũ công khai thành một cấu trúc mới, nhưng SecKeyRef là mờ và tôi không thể tìm thấy một hàm thực hiện thao tác này.Lấy chìa khóa công khai từ riêng SecKeyRef

Trả lời

1

Tính đến hệ điều hành MacOS 10.12, iOS/tvOS 10, và watchos 3 chức năng SecKeyCopyPublicKey bây giờ tồn tại để làm điều này.

0

Câu hỏi cũ, nhưng vì tôi đã chiến đấu với nó ngày hôm nay, tôi đã tìm thấy một cách. Hãy nói rằng bạn có mã hóa base64 khóa RSA công cộng (nó không phải là giấy chứng nhận, nó không der, pem, ...), được tạo ra trong Java (X509 giấy chứng nhận khóa công khai), bạn có thể tạo SecKeyRef theo cách này:

- (NSData *)stripPublicKeyHeader2:(NSData *)keyBits { 
    // Skip ASN.1 public key header 
    if (keyBits == nil) { 
    return nil; 
    } 

    unsigned int len = [keyBits length]; 
    if (!len) { 
    return nil; 
    } 

    unsigned char *c_key = (unsigned char *)[keyBits bytes]; 
    unsigned int idx = 0; 

    if (c_key[idx++] != 0x30) { 
    return nil; 
    } 

    if (c_key[idx] > 0x80) { 
    idx += c_key[idx] - 0x80 + 1; 
    } 
    else { 
    idx++; 
    } 

    if (idx >= len) { 
    return nil; 
    } 

    if (c_key[idx] != 0x30) { 
    return nil; 
    } 

    idx += 15; 

    if (idx >= len - 2) { 
    return nil; 
    } 

    if (c_key[idx++] != 0x03) { 
    return nil; 
    } 

    if (c_key[idx] > 0x80) { 
    idx += c_key[idx] - 0x80 + 1; 
    } 
    else { 
    idx++; 
    } 

    if (idx >= len) { 
    return nil; 
    } 

    if (c_key[idx++] != 0x00) { 
    return nil; 
    } 

    if (idx >= len) { 
    return nil; 
    } 

    // Now make a new NSData from this buffer 
    return([NSData dataWithBytes:&c_key[idx] length:len - idx]); 
} 

- (SecKeyRef)publicKey:(NSData *)d_key withTag:(NSString *)tag 
{ 
    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]]; 

    NSDictionary *saveDict = @{ 
          (__bridge id) kSecClass : (__bridge id) kSecClassKey, 
          (__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeRSA, 
          (__bridge id) kSecAttrApplicationTag : d_tag, 
          (__bridge id) kSecAttrKeyClass : (__bridge id) kSecAttrKeyClassPublic, 
          (__bridge id) kSecValueData : d_key 
          }; 

    OSStatus secStatus = SecItemAdd((__bridge CFDictionaryRef)saveDict, NULL); 
    if (secStatus == errSecDuplicateItem) { 
    SecItemDelete((__bridge CFDictionaryRef)saveDict); 
    secStatus = SecItemAdd((__bridge CFDictionaryRef)saveDict, NULL); 
    } 

    if (secStatus != noErr) { 
    return NULL; 
    } 

    NSDictionary *queryDict = @{ 
           (__bridge id) kSecClass : (__bridge id) kSecClassKey, 
           (__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeRSA, 
           (__bridge id) kSecAttrApplicationTag : tag, 
           (__bridge id) kSecAttrKeyClass : (__bridge id)kSecAttrKeyClassPublic, 
           (__bridge id) kSecReturnRef : (__bridge id) kCFBooleanTrue 
           }; 

    // Now fetch the SecKeyRef version of the key 
    SecKeyRef keyRef = nil; 
    secStatus = SecItemCopyMatching((__bridge CFDictionaryRef)queryDict, 
            (CFTypeRef *)&keyRef); 

    if (secStatus != noErr) { 
    return NULL; 
    } 

    return keyRef; 
} 

NSData *keyData = [[NSData alloc] initWithBase64EncodedString:@"base64encoded X509 private key" 
                   options:0]; 
certificateData = [self stripPublicKeyHeader2:keyData]; 
SecKeyRef key = [self publicKey:certificateData withTag:[[NSUUID UUID] UUIDString]]; 

Hơi khó xử, không phải mã của tôi, là Googling cho cả ngày, nhiều mảnh dán lại với nhau. Phải làm sạch nó, ... Lấy nó như là một hack được biên dịch từ internet.

Được thử nghiệm đối với máy chủ có mã trong Java và đây là cách duy nhất để thực hiện. Cách duy nhất tôi đã tìm thấy. Có thể có một cách khác, nhưng chỉ có một cách này có hiệu quả với tôi và tôi có thể mã hóa bằng khóa công khai RSA này (và mã máy chủ của chúng tôi (Java) có thể giải mã nó và nó chỉ hoạt động mà không có đệm (không được khuyến nghị) hoặc với lớp đệm kSecPaddingOAEP trên iOS bên và với RSA/NONE/OAEPWithSHA1AndMGF1Padding đứng về phía Java.

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