2012-11-19 15 views
12

iOSでCSRを生成しようとしています。 iOSのAppleセキュリティフレームワークには、CSR生成のためのメソッドが含まれていないように見えるので、プロジェクトのOpenSSLソースコードをコンパイルする必要がありました。iOSでOpenSSL証明書署名要求を生成するには

これまでキーチェーンで生成したキーでこれらのメソッドを使用する方法を知りたいと思います。つまり、私はSecKeyRef型をEVP_PKEYのようなOpenSSL型に変換する必要があります。これでOpenSSLメソッドX509_REQ_set_pubkeyを呼び出すことができます。

誰でもこれを達成する方法を知っていますか?

+0

関連、[シンプルな証明書登録プロトコル](https://tools.ietf.org/html/draft-gutmann-scep-00)(SCEP)を参照してください。ピーター・グットマンは2015年5月にそれを維持したので、前進していくべきです。 – jww

答えて

16

自分で解決策を見つけました。

まず、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; 
} 

今、私たちはunsigned char型として、このデータをキャストし、公開鍵と共通名とのOpenSSLでシンプルなCSR(署名されていない)を生成する方法の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); 
} 

にそれを与える必要がありますそれを標準出力に出力します。

+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); 
} 
関連する問題