2012-11-19 11 views
12

मैं आईओएस में सीएसआर उत्पन्न करने की कोशिश कर रहा हूं। चूंकि स्पष्ट रूप से आईओएस के लिए ऐप्पल सुरक्षा ढांचे में सीएसआर पीढ़ी के तरीकों को शामिल नहीं किया गया है, मुझे अपनी परियोजना के लिए ओपनएसएसएल स्रोत कोड संकलित करना पड़ा।कीचैन संग्रहीत कुंजी के साथ आईओएस में ओपनएसएसएल सर्टिफिकेट साइनिंग अनुरोध उत्पन्न करना

अब मैं जानना चाहता हूं कि इन तरीकों का उपयोग पहले कीचैन में जेनरेट की गई कुंजी के साथ कैसे किया जाए। यही है, मुझे SecKeyRef प्रकार को OpenSSL प्रकारों जैसे EVP_PKEY में परिवर्तित करने की आवश्यकता है। इससे मुझे OpenSSL विधि X509_REQ_set_pubkey को कॉल करने की अनुमति मिल जाएगी।

क्या कोई इसे प्राप्त करने का तरीका जानता है?

+0

संबंधित, देखें [सरल प्रमाणपत्र नामांकन प्रोटोकॉल] (https://tools.ietf.org/html/draft-gutmann-scep-00) (SCEP)। मई, 2015 में पीटर गुटमैन ने इसका रखरखाव संभाला, इसलिए इसे आगे बढ़ना चाहिए। – jww

उत्तर

16

स्वयं समाधान मिला।

सबसे पहले आपको कीचेन से एनएसडीटा के रूप में कुंजी निकालने की आवश्यकता है।

- (NSData *) getKeyDataWithIdentifier:(NSString *) identifier 
{ 
    NSData * keyBits = nil; 
    NSMutableDictionary * keyQuery = [[NSMutableDictionary alloc] init]; 
    NSData * encodedId = [identifier dataUsingEncoding:NSUTF8StringEncoding]; 
    [keyQuery setObject:encodedId forKey:kSecAttrApplicationTag]; 
    [keyQuery setObject:kSecClassKey forKey:kSecClass]; 
    [keyQuery setObject:[NSNumber numberWithBool:YES] forKey:kSecReturnData]; 
    [keyQuery setObject:kSecAttrKeyTypeRSA forKey:kSecAttrKeyType]; 

    OSStatus sanityCheck = SecItemCopyMatching((CFDictionaryRef)keyQuery, (CFTypeRef *)&keyBits); 

    if (sanityCheck != noErr) { 
     NSLog(@"Error: %ld", sanityCheck); 
    } 

    return keyBits; 
} 

अब हम अहस्ताक्षरित चार के रूप में इस डेटा डाल सकते हैं और यह विधि d2i_RSAPublicKey

- (void) generateCSR:(NSData *) keyData 
{ 
    X509_REQ *req = NULL; 
    X509_NAME *name= NULL; 
    EVP_PKEY *key; 
    const unsigned char * bits = (unsigned char *) [keyData bytes]; 
    int length = [keyData length]; 

    if ((req=X509_REQ_new()) == NULL) { 
     NSLog(@"big error"); 
     return; 
    } 

    RSA * rsa = NULL; 
    key=EVP_PKEY_new(); 
    d2i_RSAPublicKey(&rsa, &bits, length); 
    EVP_PKEY_assign_RSA(key,rsa); 
    name = X509_REQ_get_subject_name(req); 
    X509_REQ_set_pubkey(req, key); 

    /* This function creates and adds the entry, working out the 
    * correct string type and performing checks on its length. 
    * Normally we'd check the return value for errors... 
      */ 
    X509_NAME_add_entry_by_txt(name,"CN", 
           MBSTRING_ASC, "My certificate request", -1, -1, 0); 
    X509_REQ_print_fp(stdout, req); 
} 

कि एक सार्वजनिक कुंजी और एक आम नाम के साथ OpenSSL (पर हस्ताक्षर नहीं) में एक साधारण सीएसआर उत्पन्न करने के लिए देने की आवश्यकता और इसे मानक आउट में प्रिंट करता है।

+1

यह बहुत अच्छा काम करता है! क्या आपने इसे साइन करने में भी कामयाब रहे हैं? – joakimb

1

ठीक है, कीस्टोर सामान हमारे लिए सही काम नहीं कर रहा था, इसलिए हमने उन्हें उत्पन्न किया और उन्हें फ़ाइलों के रूप में संग्रहीत किया। अगर किसी को कभी इसकी ज़रूरत है, तो मैं इसे यहां छोड़ दूंगा।

+ (void)generateCsrAndKeyAtPath:(NSString *)csrPath KeyPath:(NSString *)keyPath Username:(NSString *)username { 
    int i; 
    RSA *rsakey; 
    X509_REQ *req; 
    X509_NAME *subj; 
    EVP_PKEY *pkey; 
    EVP_MD *digest; 
    FILE *fp; 

    structentry[ENTRIES - 1].value = [username UTF8String]; 

    // standard set up for OpenSSL 
    OpenSSL_add_all_algorithms(); 
    ERR_load_crypto_strings(); 

    // Generate the RSA key; we don't assign a callback to monitor progress 
    // since generating keys is fast enough these days 
    rsakey = RSA_generate_key(2048, RSA_F4, NULL, NULL); 

    // Create evp obj to hold our rsakey 
    if (!(pkey = EVP_PKEY_new())) 
     NSLog(@"Could not create EVP object"); 

    if (!(EVP_PKEY_set1_RSA(pkey, rsakey))) 
     NSLog(@"Could not assign RSA key to EVP object"); 

    // create request object 
    if (!(req = X509_REQ_new())) 
     NSLog(@"Failed to create X509_REQ object"); 
    X509_REQ_set_pubkey(req, pkey); 

    // create and fill in subject object 
    if (!(subj = X509_NAME_new())) 
     NSLog(@"Failed to create X509_NAME object"); 

    for (i = 0; i < ENTRIES; i++) { 
     int nid;     // ASN numeric identifier 
     X509_NAME_ENTRY *ent; 

     if ((nid = OBJ_txt2nid(structentry[i].key)) == NID_undef) { 
      fprintf(stderr, "Error finding NID for %s\n", structentry[i].key); 
      NSLog(@"Error on lookup"); 
     } 
     if (!(ent = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC, 
       structentry[i].value, -1))) 
      NSLog(@"Error creating Name fewfwefewf from NID"); 

     if (X509_NAME_add_entry(subj, ent, -1, 0) != 1) 
      NSLog(@"Error adding fewfwefewf to Name"); 
    } 
    if (X509_REQ_set_subject_name(req, subj) != 1) 
     NSLog(@"Error adding subject to request"); 

    // request is filled in and contains our generated public key; 
    // now sign it 
    digest = (EVP_MD *) EVP_sha1(); 

    if (!(X509_REQ_sign(req, pkey, digest))) 
     NSLog(@"Error signing request"); 

    // write output files 
    if (!(fp = fopen([csrPath UTF8String], "wb"))) 
     NSLog(@"Error writing to request file"); 
    if (PEM_write_X509_REQ(fp, req) != 1) 
     NSLog(@"Error while writing request"); 
    fclose(fp); 

    if (!(fp = fopen([keyPath UTF8String], "w"))) 
     NSLog(@"Error writing to private key file"); 
    if (PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, 0, NULL) != 1) 
     NSLog(@"Error while writing private key"); 
    fclose(fp); 

    EVP_PKEY_free(pkey); 
    X509_REQ_free(req); 
} 
संबंधित मुद्दे