2

我需要生成EC Diffie Hellman密鑰對。我正在使用secp256r1命名曲線和OpenSSL。這是我與我至今:生成EC Diffie-Hellman公鑰和私鑰對

unsigned char *ecdh(size_t *secret_len) 
{ 
    EVP_PKEY_CTX *pctx, *kctx; 
    EVP_PKEY_CTX *ctx; 
    unsigned char *secret; 
    EVP_PKEY *pkey = NULL, *peerkey, *params = NULL; 
    /* NB: assumes pkey, peerkey have been already set up */ 

    /* Create the context for parameter generation */ 
    if(NULL == (pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) 
     printf("Error in EC key generation\n"); 

    /* Initialise the parameter generation */ 
    if(1 != EVP_PKEY_paramgen_init(pctx)) 
     printf("Error in EC key generation\n"); 

    /* We're going to use the ANSI X9.62 Prime 256v1 curve */ 
    if(1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1)) 
     printf("Error in EC key generation\n"); 

    /* Create the parameter object params */ 
    if (!EVP_PKEY_paramgen(pctx, &params)) 
     printf("Error in EC key generation\n"); 

    /* Create the context for the key generation */ 
    if(NULL == (kctx = EVP_PKEY_CTX_new(params, NULL))) 
     printf("Error in EC key generation\n"); 

    /* Generate the key */ 
    if(1 != EVP_PKEY_keygen_init(kctx)) 
     printf("Error in EC key generation\n"); 

    if (1 != EVP_PKEY_keygen(kctx, &pkey)) 
     printf("Error in EC key generation\n"); 

    /* Get the peer's public key, and provide the peer with our public key - 
    * how this is done will be specific to your circumstances */ 
    peerkey = get_peerkey(pkey); 

    /* Create the context for the shared secret derivation */ 
    if(NULL == (ctx = EVP_PKEY_CTX_new(pkey, NULL))) 
     printf("Error in EC key generation\n"); 

    /* Initialise */ 
    if(1 != EVP_PKEY_derive_init(ctx)) 
     printf("Error in EC key generation\n"); 

    /* Provide the peer public key */ 
    if(1 != EVP_PKEY_derive_set_peer(ctx, peerkey)) 
     printf("Error in EC key generation\n"); 

    /* Determine buffer length for shared secret */ 
    if(1 != EVP_PKEY_derive(ctx, NULL, secret_len)) 
     printf("Error in EC key generation\n"); 

    /* Create the buffer */ 
    if(NULL == (secret = OPENSSL_malloc(*secret_len))) 
     printf("Error in EC key generation\n"); 

    /* Derive the shared secret */ 
    if(1 != (EVP_PKEY_derive(ctx, secret, secret_len))) 
     printf("Error in EC key generation\n"); 

    EVP_PKEY_CTX_free(ctx); 
    EVP_PKEY_free(peerkey); 
    EVP_PKEY_free(pkey); 
    EVP_PKEY_CTX_free(kctx); 
    EVP_PKEY_free(params); 
    EVP_PKEY_CTX_free(pctx); 

    /* Never use a derived secret directly. Typically it is passed 
    * through some hash function to produce a key */ 
    return secret; 
} 

我要指出的是此功能工作,我需要第二方的公鑰EVP_KEY對象。我有這個公鑰在一個字節數組,也是它的長度。我如何將其轉換爲所需的類型?而且我也找不到OpenSSL中的secp256r1曲線,但是在做了一些研究之後,我使用了代碼中的那個曲線。這是對的嗎?

謝謝!

+0

我不是OpenSSL的專家,但有一件事我要提醒你的就是實現自己的密碼可能是危險的。例如,你不應該只是拿出你收到的任何密鑰,並相信它屬於你打算與之通信的一方:這會讓你服從[中間人攻擊者](http://en.wikipedia)。組織/維基/人在這方面的-middle_attack)。所以需要有某種類型的密鑰屬於聲明它的人。 – TheGreatContini

+0

實際上現在我發現密鑰帶有一個簽名(TLS中的服務器密鑰交換記錄就是我所說的),所以安全問題很好,我想:)我無法提取公鑰從簽名 –

+0

你的公鑰是什麼樣的?這個答案是否適用? http://stackoverflow.com/questions/2918923/evp-pkey-from-char-buffer-in-x509-pkcs7 – ChiaraHsieh

回答

1

對等體的公鑰是曲線上的一個點。從crypto\ec\ec_lcl.h

struct ec_key_st { 
    int version; 

    EC_GROUP *group; 

    EC_POINT *pub_key; 
    BIGNUM *priv_key; 

    unsigned int enc_flag; 
    point_conversion_form_t conv_form; 

    int  references; 
    int flags; 

    EC_EXTRA_DATA *method_data; 
} /* EC_KEY */; 

相信你需要調用EC_POINT_newc_lcl.h是一傢俬營頭,所以您將無法訪問結構)。

幸運的是,有很多的函數來處理它們。從EC_POINT_new(3)文檔:

EC_POINTs可以轉化爲與來自各種外部 表示。支持的表示形式是八位字符串,BIGNUMs 和十六進制。外部表示的格式是由point_conversion_form描述的 。有關point_conversion_form的描述,請參閱EC_GROUP_copy(3) 。八位字節字符串與關聯的緩衝區長度一起存儲在一個 緩衝區中。通過將點轉換爲八位字節字符串並且然後將該八位字節字符串轉換爲BIGNUM整數來計算保存在 BIGNUM中的點。在 十六進制格式點存儲在一個NULL結尾的字符串 其中每個字符可打印值0-9或A-F(或 A-F)中的一個。

另見EC_POINT_set_affine_coordinates_GFpEC_POINT_set_affine_coordinates_GF2mEC_KEY_set_public_key

$ grep -R EC_KEY_set_public_key * 
crypto/ec/ec.h:int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); 
... 

你可以看到如何在Elliptic Curve Cryptography設置OpenSSL的維基點的例子。