2012-11-19 14 views
12

Sto provando a generare un CSR in iOS. Poiché apparentemente il framework di sicurezza Apple per iOS non include i metodi per la generazione di CSR, ho dovuto compilare il codice sorgente OpenSSL per il mio progetto.Generazione di una richiesta di firma del certificato OpenSSL in iOS con chiavi salvate con portachiavi

Ora voglio sapere come utilizzare questi metodi con i tasti che ho generato in precedenza nel Portachiavi. Cioè, ho bisogno di convertire il tipo SecKeyRef in tipi OpenSSL come EVP_PKEY. Questo mi permetterà di chiamare il metodo OpenSSL X509_REQ_set_pubkey.

Qualcuno conosce un modo per raggiungere questo obiettivo?

+0

correlati, si veda [Simple Certificate Enrollment Protocol] (https://tools.ietf.org/html/draft-gutmann-scep-00) (SCEP). Peter Gutmann ne ha assunto la manutenzione nel maggio 2015, quindi dovrebbe andare avanti. – jww

risposta

16

Ho trovato la soluzione da solo.

Prima di tutto è necessario estrarre la chiave dal portachiavi come NSData.

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

Ora abbiamo bisogno di lanciare questi dati come unsigned char e dare al metodo 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); 
} 

che genera un semplice CSR in OpenSSL (non firmato) con una chiave pubblica e un nome comune e lo stampa allo standard.

+1

Funziona alla grande! Sei anche riuscito a firmarlo? – joakimb

1

Bene, il materiale del keystore non funzionava correttamente per noi, quindi li abbiamo generati e archiviati come file. Se qualcuno avesse mai bisogno di questo, lo lascerò qui.

+ (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); 
} 
Problemi correlati