2012-11-19 4 views
12

Ich versuche, eine CSR in iOS zu generieren. Da das Apple-Sicherheitsframework für iOS keine Methoden zur CSR-Generierung enthält, musste ich den OpenSSL-Quellcode für mein Projekt kompilieren.Generieren einer OpenSSL Certificate Signing-Anfrage in iOS mit Schlüsselbund gespeicherten Schlüsseln

Jetzt möchte ich wissen, wie man diese Methoden mit den Schlüsseln verwendet, die ich zuvor im Schlüsselbund generiert habe. Das heißt, ich muss den SecKeyRef-Typ in OpenSSL-Typen wie EVP_PKEY konvertieren. Dadurch kann ich die OpenSSL-Methode X509_REQ_set_pubkey aufrufen.

Kennt jemand einen Weg, dies zu erreichen?

+0

Verwandte finden Sie unter [Simple Certificate Enrollment Protocol] (https://tools.ietf.org/html/draft-gutmann-scep-00) (SCEP). Peter Gutmann hat die Wartung im Mai 2015 übernommen, also sollte es weitergehen. – jww

Antwort

16

Die Lösung selbst gefunden.

Zuerst müssen Sie den Schlüssel aus dem Schlüsselbund als NSData extrahieren.

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

Jetzt müssen wir diese Daten als unsigned char werfen und geben es an die Methode 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); 
} 

, dass eine einfache CSR in OpenSSL (nicht unterzeichnet) mit einem öffentlichen Schlüssel und einem gemeinsamen Namen erzeugt und druckt es auf den Standard aus.

+1

Das funktioniert super! Hast du es auch geschafft, es zu unterschreiben? – joakimb

1

Nun, das Keystore-Zeug funktionierte nicht richtig für uns, also erzeugten wir sie und speicherten sie als Dateien. Wenn jemand das jemals braucht, werde ich es hier lassen.

+ (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); 
} 
Verwandte Themen