2012-12-28 10 views
5

क्या यह संभव है, और यदि ऐसा है तो कैसे? मैं ऐसे प्रोटोकॉल के साथ काम कर रहा हूं जिसके लिए क्लाइंट प्रमाणपत्र की आवश्यकता है, इसलिए मैं एक बार उत्पन्न करना चाहता हूं और इसे भविष्य के उपयोग के लिए कीचेन में स्टोर करना चाहता हूं।आईओएस सुरक्षा.फ्रेमवर्क के साथ एक स्व-हस्ताक्षरित प्रमाणपत्र उत्पन्न करना?

मैं वर्तमान में SecKeyGeneratePair के माध्यम से प्रमुख जोड़े उत्पन्न करने के लिए सुरक्षा ढांचे का उपयोग कर रहा हूं, लेकिन क्या X.50 9 प्रमाण पत्र में जेनरेट की गई सार्वजनिक कुंजी को पैकेज करने का कोई तरीका है और इसे नई सेकेंडेंटिटी बनाने के लिए निजी कुंजी के साथ जोड़ना है? मुझे लगता है कि एक तरीका होना चाहिए क्योंकि आईओएस और मैक पर सुरक्षा ढांचा समान होना चाहिए, और मैक पर कीचेन एक्सेस स्वयं हस्ताक्षरित प्रमाणपत्र उत्पन्न कर सकती है।

ओपनएसएसएल एक विकल्प है, लेकिन यदि संभव हो तो मैं निर्मित सुरक्षा ढांचे में निर्मित का उपयोग करूंगा। धन्यवाद।

+0

ऐसा लगता है कि यह सुरक्षा ढांचे के साथ वर्तमान में संभव नहीं है, इसलिए मुझे ओपनएसएसएल का उपयोग करना होगा। जानकारी: https://devforums.apple.com/message/652850 बग: http://www.openradar.me/12938395 – brianpartridge

उत्तर

4

ऐ - यह (और खूनी दर्दनाक) है। नीचे वह कोड है जिसका मैं उपयोग कर रहा हूं। यह SecKeyGeneratePair() में उत्पन्न कुंजी के साथ संकेत करता है (और इसलिए कीचेन/बाहरी पहुंच में)।

क्रैकिंग में मेरे लिए क्रूक्स यह पता लगा रहा था कि SecKeyRawSign केवल SHA1 पसंद आया।

यदि आप मेरे हाथ से कुछ मौजूदा रनिंग कोड लेना चाहते हैं, इसे साफ करें, दस्तावेज़ जोड़ें और फिर आनंद लेने के लिए एक अच्छा अपाचे लाइसेंस के साथ इसे जिथब पर प्राप्त करें, तो मुझे डीएम के लिए स्वतंत्र महसूस करें।

(NSData *)signCSR:(NSData *)derCSR forDays:(double)days NIDstToKeep:(NSSet *)nidsToAllow 
{ 
    const unsigned char * ptr; 
    NSUInteger len; 

    // Gather the details for the CA cert (my cert) from 
    // OSX. 
    // 
    X509 * x509_mycert = NULL; 
    SecIdentityRef identityRef = [self secIdentityRef]; 
    if (!identityRef) 
     return nil; 

    SecCertificateRef certificateRef = [self secCertificateRef]; 
    if (!certificateRef) 
     return nil; 

    CFDataRef certAsDer = SecCertificateCopyData(certificateRef); 
    if (!certAsDer) 
     return nil; 

    // Jump over the fence to OpenSSL - and create 
    // an X509 version. 
    // 
    ptr = CFDataGetBytePtr(certAsDer); 
    len = CFDataGetLength(certAsDer); 

    if (!(d2i_X509(&x509_mycert, &ptr, len))) 
     return nil; 

    // And likewise for the CSR. 
    // 
    ptr = (const unsigned char *)[derCSR bytes]; 
    len = [derCSR length]; 

    X509_REQ *req = NULL; 
    if (!(d2i_X509_REQ(&req, &ptr, len))) 
     return nil; 

    // Copy the CSR into a an actual x509 tenative 
    // structure; i.e. the cert we'll issue signed. 
    // 
    X509 * x509_to_sign = X509_new(); 

    assert(X509_set_subject_name(x509_to_sign,req->req_info->subject)); 
    assert(X509_set_issuer_name(x509_to_sign, X509_get_subject_name(x509_mycert))); 

    EVP_PKEY * pubkey_csr = X509_REQ_get_pubkey(req); 
    X509_set_pubkey(x509_to_sign,pubkey_csr); 
    EVP_PKEY_free(pubkey_csr); 

    X509_gmtime_adj(X509_get_notBefore(x509_to_sign),0L); 
    X509_gmtime_adj(X509_get_notAfter(x509_to_sign),(long)floor(60*60*24*days)); 

    if (nidsToAllow && [nidsToAllow count]) { 
     // Faily blindly copy all known extensions. 
     // 
     for(int i = X509_get_ext_count(x509_to_sign); i > 0; i--) { 
      X509_EXTENSION * ext = X509_get_ext(x509_to_sign,i-i); 
      int nid = OBJ_obj2nid(ext->object); 
      if ([nidsToAllow containsObject:[NSNumber numberWithInt:nid]]) { 
       // NSLog(@"Keeping %s at %d", OBJ_nid2sn(nid),i-i); 
       continue; 
      } 
      // NSLog(@"Killing %s at %d", OBJ_nid2sn(nid),i-1); 
      X509_delete_ext(x509_to_sign, i-i); 
     } 
    } else { 
     // wipe them all. 
     // 
     while (X509_get_ext_count(x509_to_sign) > 0) { 
      X509_delete_ext(x509_to_sign, 0); 
     } 
    }; 

    // Set a random serial. 
    // 
    ASN1_INTEGER *bs = ASN1_INTEGER_new(); 
    long rnd = 0; 
    if (!(RAND_bytes((unsigned char *)&rnd, sizeof(rnd)))) 
     return nil; 

    rnd = labs(rnd); 
    ASN1_INTEGER_set(bs, rnd); 

    if (!((X509_set_serialNumber(x509_to_sign,bs)))) 
     return nil; 

    ASN1_INTEGER_free(bs); 

    // Force v3 
    // 
    X509V3_CTX ctx2; 
    X509_set_version(x509_to_sign,2); /* version 3 certificate */ 
    X509V3_set_ctx(&ctx2, x509_mycert, x509_to_sign, NULL, NULL, 0); 

    // Pull in additional x509v3 sections. 
    // 
    if (DBA) { 
     assert(X509V3_set_nconf(&ctx2, conf)); 
     assert(X509V3_EXT_add_nconf(conf, &ctx2, section, x509_to_sign)); 
    } 
    // Specify signature type. 
    // 
    x509_to_sign->cert_info->signature->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption); 

    // Construct the ASN.1 blob which contains all the information 
    // we are going to sign. 
    // 
    const ASN1_ITEM * it = ASN1_ITEM_rptr(X509_CINF); 
    unsigned char *buf_in=NULL; 
    ASN1_VALUE * asn = (ASN1_VALUE *)(x509_to_sign->cert_info); 
    int inl = ASN1_item_i2d(asn,&buf_in, it); 

    // Small area to hold the signature on the SHA1 hash. 
    // 
    size_t sigLen = SecKeyGetBlockSize(privateKey); 
    uint8_t * sig = (uint8_t *)malloc(sigLen * sizeof(uint8_t)); 
    memset((void*)sig, 0, sigLen); 

#if TARGET_OS_IPHONE 
    // IPhone Way of doing it - where we need to construct the 
    // SHA1 of the 'to sign' area ourselves. As SecKeyRawSign 
    // does not seem to handly anything beyond a SHA1. 
    // 
    NSData * buffToSign = [NSData dataWithBytes:buf_in length:inl]; 
    NSData * buffSha1ToSign = [buffToSign sha1]; 

    size_t sigLenUsed = sigLen; 

    OSStatus status = SecKeyRawSign(privateKey, kSecPaddingPKCS1SHA1, [buffSha1ToSign bytes], [buffSha1ToSign length], sig, &sigLenUsed); 
    assert(status == noErr); 
    assert(sigLenUsed == sigLen); 

#else 
    // MacOSX offical way of doing this - which seems to do the SHA1 fun, 
    // padding and games deeper down; and where we simply pass the blob. 
    // 
    CFErrorRef error = NULL; 
    SecTransformRef signer = SecSignTransformCreate(privateKey, &error); 
    if (error) { CFShow(error); assert(0); }; 

    NSData * blockToSign = [NSData dataWithBytes:buf_in length:inl]; 
    SecTransformSetAttribute(signer, kSecTransformInputAttributeName, 
          (__bridge CFTypeRef) blockToSign, &error); 
    if (error) { CFShow(error); assert(0); }; 

    CFDataRef signature = SecTransformExecute(signer, &error); 
    if (error) { CFShow(error); assert(0); }; 

    assert(sigLen == CFDataGetLength(signature)); 
    bcopy(CFDataGetBytePtr(signature), sig, sigLen); 
#endif 

    // Wrap up the rest of the block with the bits and bobs needed to 
    // create a valid ASN1 block to share as a PEM or DER. Which most 
    // crucially is about copying the just created signature into it. 
    // 
    x509_to_sign->sig_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption); 
    x509_to_sign->signature->data = sig; 
    x509_to_sign->signature->length = sigLen; 
    x509_to_sign->signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); 
    x509_to_sign->signature->flags|=ASN1_STRING_FLAG_BITS_LEFT; 

    unsigned char * derbuff = NULL; 
    int derlen = i2d_X509(x509_to_sign, &derbuff); 

    NSData * signedDer = [NSData dataWithBytes:derbuff length:derlen]; 

    free(sig); 
    OPENSSL_free(x509_to_sign); 
    OPENSSL_free(x509_mycert); 

    return signedDer; 
} 

ध्यान दें कि मैं कुछ मालिकाना/गैर सरकारी बिट्स बाहर छीन लिया - तो ऊपर संभवत: कुछ ही CFReleases() और विविध याद करेंगे।

+0

मैं ओपनएसएसएल के साथ ऐसा करने में पहले से ही सक्षम हूं, कम कोड के साथ भी, मैं एक की तलाश में था केवल सुरक्षा ढांचे के साथ रास्ता। यह इस धारणा पर भी निर्भर करता है कि SecCertificateCopyData डीईआर डेटा देता है, जो ऐप्पल डेवलपर मंचों पर eskimo1 इंगित कर सकता है। – brianpartridge

+0

ठीक है - Sec *() et.al का उपयोग करने में सक्षम आईओएस पर उचित कीफ के साथ, स्वयं हस्ताक्षरित, अनुरोध उत्पन्न करने और इस तरह के अनुरोध पर हस्ताक्षर करने के लिए ठीक है (एक विज्ञापन-पीओपी आधारित 'भौतिक स्थान में मिलते हैं और चिंप्स का उपयोग करके साइन' ऐप)। और ऐप को वास्तविक संवेदनशील क्रिप्टो सामग्री से अवगत होने के बिना ऐसा करें। लेकिन सीरियल/डीएन के लिए कम से कम एक्सटेंशन और समान एएसएन 1/डीईआर मैंगलिंग को आकार देने के लिए बहुत सारे ओपनएसएसएल के साथ SecKeyGeneratePair/SecSign/आदि को घेरने का कोई तरीका नहीं मिला है। जिसके लिए कोई सेक * विकल्प नहीं है। मुझे dirkx (at) webweaving (dot) संगठन पर एक मेल छोड़ने के लिए स्वतंत्र महसूस करें। –

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