2014-06-28 5 views
11

से सार्वजनिक कुंजी को देखते हुए प्राप्त एक SecKeyRef कोई RSA निजी कुंजी से SecItemImport का उपयोग कर वहाँ प्राप्त करने या केवल सार्वजनिक प्रमुख घटकों के लिए एक SecKeyRef बनाने के लिए एक रास्ता है भरी हुई? ओपनएसएसएल में मॉड्यूलस और सार्वजनिक एक्सपोनेंट को एक नई संरचना में कॉपी करके किया जा सकता है, लेकिन SecKeyRef अपारदर्शी है और मैं इस ऑपरेशन को करने वाले फ़ंक्शन को खोजने में असमर्थ हूं।निजी SecKeyRef

उत्तर

1

MacOS 10.12 के रूप में, आईओएस/tvOS 10, और watchOS 3 समारोह SecKeyCopyPublicKey अब यह करने के लिए मौजूद है।

0

पुराना सवाल, लेकिन क्योंकि मैं आज इसके साथ लड़ रहा था, मुझे एक रास्ता मिला। मान लीजिए कि आप बेस 64 इनकोडिंग सार्वजनिक RSA कुंजी करते हैं (यह प्रमाण पत्र नहीं है, यह der नहीं है, पीईएम, ...), जावा (X509 प्रमाण पत्र सार्वजनिक कुंजी) में बनाया है, तो आप SecKeyRef इस तरह से बना सकते हैं:

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

थोड़ा सा अजीब, मेरा कोड नहीं, पूरे दिन गुगल था, कई टुकड़े एक साथ चिपके हुए थे। इसे साफ करना है, ... इसे इंटरनेट से संकलित एक हैक के रूप में लें।

सर्वर के खिलाफ परीक्षण किया गया जहां कोड जावा में है और यह एकमात्र तरीका है कि इसे कैसे किया जाए। एकमात्र रास्ता मैंने पाया। शायद एक और तरीके हैं, लेकिन केवल यह मेरे लिए काम करता है और मैं इस आरएसए सार्वजनिक कुंजी के साथ एन्क्रिप्ट कर सकता हूं (और हमारा सर्वर कोड (जावा) इसे डिक्रिप्ट कर सकता है। और यह केवल पैडिंग के बिना काम करता है (अनुशंसित नहीं) या kSecPaddingOAEP पैडिंग के साथ आईओएस तरफ और RSA/NONE/OAEPWithSHA1AndMGF1Padding जावा तरफ से।

संबंधित मुद्दे