2016-12-14 128 views
0

我正在開發應用程序,我需要通過使用Objective C或Swift創建CSR,這並不容易。所以我選擇了OpenSSL來創建CSR,並且我創建了成功的代碼如下所示,但我的另一個核心要求是將密鑰存儲在安全區域中,但在OpenSSL中這是不可能的,因爲我在線搜索。 現在我想在安全飛地中的目標c中創建密鑰對,然後將這些公鑰(帶有數據)和私鑰(帶有參考)導出到openSSL(EC_KEY),然後從中創建CSR。我發現這個this link導出密鑰,但沒有辦法導出私鑰(不可能與數據,但與參考)。從iOS導出公鑰和私鑰到OpenSSL

我需要一些指導如何做到這一點。

- (void)genCSRX509ForEC 
{ 
    int    ret = 0; 
    DSA    *r = NULL; 
    BIGNUM   *bne = NULL; 


int    nVersion = 1; 

unsigned long e = RSA_F4; 

X509_REQ  *x509_req = NULL; 
X509_NAME  *x509_name = NULL; 
EVP_PKEY  *pKey = NULL; 
BIO    *out = NULL; 

const char  *szCountry = "USA"; 
const char  *szProvince = "MA"; 
const char  *szCity = "Boston"; 
const char  *szOrganization = "MyComp"; 
const char  *szCommon = "MYC"; 

const char  *szPath = "x509Req.pem"; 

// 1. generate rsa key 
bne = BN_new(); 
ret = BN_set_word(bne,e); 
if(ret != 1){ 
    goto free_all; 
} 

r = DSA_new(); 
//  
// EC_KEY* _ec_key = EC_KEY_new(); 
// EC_GROUP* ec_group_new = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); 
// const EC_GROUP* ec_group = ec_group_new; 
// if (!EC_KEY_set_group(_ec_key,ec_group)) 
//  NSLog(@"Error in initializeCrypto, EC_KEY_set_group failed!"); 

    // Segfault at this position 


    //////////////////////////// CREATE KEYPAIR ///////////////////////////////////// 

    EC_KEY* _ec_key = EC_KEY_new(); 
    EC_GROUP* ec_group_new = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); 
    const EC_GROUP* ec_group = ec_group_new; 
    if (!EC_KEY_set_group(_ec_key,ec_group)) 
     NSLog(@"Error in initializeCrypto, EC_KEY_set_group failed!"); 

    EC_KEY_generate_key(_ec_key); 

    ret = EC_KEY_check_key(_ec_key); 
    if (ret != 1){ 
     goto free_all; 
    } 

     const BIGNUM *privateKey = EC_KEY_get0_private_key(_ec_key); 
     const EC_POINT *publicKey = EC_KEY_get0_public_key(_ec_key); 

     privateKeySize = i2d_ECPrivateKey(_ec_key,NULL); 
     unsigned char *privateKeyBuf = OPENSSL_malloc(privateKeySize); 
     memset(privateKeyBuf, 0, privateKeySize); 
     int status = i2d_ECPrivateKey(_ec_key,&privateKeyBuf); 
     if (!ret){ 
     NSLog(@"Private key to DER failed\n"); 
     return; 
     } 
     else { 
     NSLog(@"Private key %s",privateKeyBuf); 
     } 
    privateKeyUnsignedChar = privateKeyBuf; 

     publicKeySize = i2o_ECPublicKey(_ec_key,NULL); 
     unsigned char *publicKeyBuf = OPENSSL_malloc(privateKeySize); 
     memset(publicKeyBuf, 0, privateKeySize); 
     ret = i2o_ECPublicKey(_ec_key,&publicKeyBuf); 
     if (!ret){ 
     NSLog(@"Public key to octed failed\n"); 
     return; 
     } 
     else { 
     NSLog(@"Public key %s",publicKeyBuf); 
     } 
    publicKeyUnsignedChar = publicKeyBuf; 
    NSLog(@"key generation generated"); 

    //////////////////////////// CREATE KEYPAIR END ///////////////////////////////////// 


    // 2. set version of x509 req 
    x509_req = X509_REQ_new(); 
    ret = X509_REQ_set_version(x509_req, nVersion); 
    if (ret != 1){ 
     goto free_all; 
    } 

    // 3. set subject of x509 req 
    x509_name = X509_REQ_get_subject_name(x509_req); 

    ret = X509_NAME_add_entry_by_txt(x509_name,"C", MBSTRING_ASC, (const unsigned char*)szCountry, -1, -1, 0); 
    if (ret != 1){ 
     goto free_all; 
    } 

    ret = X509_NAME_add_entry_by_txt(x509_name,"ST", MBSTRING_ASC, (const unsigned char*)szProvince, -1, -1, 0); 
    if (ret != 1){ 
     goto free_all; 
    } 

    ret = X509_NAME_add_entry_by_txt(x509_name,"L", MBSTRING_ASC, (const unsigned char*)szCity, -1, -1, 0); 
    if (ret != 1){ 
     goto free_all; 
    } 

    ret = X509_NAME_add_entry_by_txt(x509_name,"O", MBSTRING_ASC, (const unsigned char*)szOrganization, -1, -1, 0); 
    if (ret != 1){ 
     goto free_all; 
    } 

    ret = X509_NAME_add_entry_by_txt(x509_name,"CN", MBSTRING_ASC, (const unsigned char*)szCommon, -1, -1, 0); 
    if (ret != 1){ 
     goto free_all; 
    } 

    // 4. set public key of x509 req 
    pKey = EVP_PKEY_new(); 
    EVP_PKEY_assign_EC_KEY(pKey, _ec_key); 
    r = NULL; // will be free rsa when EVP_PKEY_free(pKey) 

    ret = X509_REQ_set_pubkey(x509_req, pKey); 
    if (ret != 1){ 
     goto free_all; 
    } 

    // 5. set sign key of x509 req 
    ret = X509_REQ_sign(x509_req, pKey, EVP_sha256()); // return x509_req->signature->length 
    if (ret <= 0){ 
     goto free_all; 
    } 

    out = BIO_new_file(szPath,"w"); 
    ret = PEM_write_bio_X509_REQ(out, x509_req); 
    X509_REQ_print_fp(stdout, x509_req); 


    [self createFileForPEM:x509_req]; 

    // PEM_write_X509_REQ(pemFile, certSigningRequest); 
    // 6. free 
free_all: 
    X509_REQ_free(x509_req); 
    BIO_free_all(out); 

    EVP_PKEY_free(pKey); 
// BN_free(bne); 


} 
+0

對於互操作性,您還應該在鍵上設置'OPENSSL_EC_NAMED_CURVE'標誌。另請參閱[橢圓曲線密碼學|在OpenSSL wiki上命名曲線](https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography#Named_Curves)。 – jww

+0

@jww通過這個,我們可以與從OpenSSL生成的密鑰進行交互,但是如何使用這個「kSecAttrTokenIDSecureEnclave」將私鑰存儲在目標c中的安全區域中?這可能會使用OpenSSL – Aleem

回答

0

參考https://www.openssl.org/docs/man1.0.2/crypto/d2i_ECPrivate_key.htmlhttps://www.openssl.org/docs/man1.0.2/crypto/d2i_ECPrivateKey.html

你可以調用i2d_ECPrivateKey將其轉換爲DER格式給出unsigned char數組中,然後將其轉化爲Base64和寫入文件。

//int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out); 
int len = -1; 
unsigned char outbuf[2000]; /*large enough to hold the key.*/ 
len = i2d_ECPrivateKey(_ec_key, outbuf); 
/*Now, you have outbuf with len bytes*/ 
/*Write it to file with in DER format and you can use d2i_ECPrivateKey to import it. */