2

EC Diffie Hellman 키 쌍을 생성해야합니다. 나는 커브와 OpenSSL이라는 이름의 secp256r1을 사용하고있다. 나는이 기능이 작동하려면, 내가 두 번째 당사자의 공개 키와 EVP_KEY 객체를 필요로 파악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; 
} 

: 이것은 내가 지금까지 나와 함께있을 것입니다. 나는이 공개 키를 바이트 배열과 길이로 가지고있다. 어떻게 그것을 필요한 유형으로 변환합니까? 또한 OpenSSL에서 secp256r1 커브를 찾을 수 없었지만 코드를 사용하여 일부 연구를 수행했습니다. 맞습니까?

감사합니다.

+0

저는 OpenSSL에 대한 전문 지식이 없지만 독자 분의 암호 작성은 위험 할 수 있습니다. 예를 들어, 수신하고 신뢰할 수있는 키가 무엇이든간에 의사 소통을하려는 상대방에게 속한 것이어야합니다. 즉, [중간자 공격] (http : //en.wikipedia. org/wiki/Man-in-the-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_new 호출 할 필요가 생각 (c_lcl.h 개인 헤더입니다, 그래서 당신은 구조에 액세스 할 수 없습니다).

다행히도, 조작 할 수있는 많은 기능이 있습니다. EC_POINT_new(3) 문서에서 :

EC_POINTs는과 다양한 외부 표현에서 변환 할 수 있습니다. 지원되는 표현은 옥텟 문자열이며 BIGNUM은 이고 16 진수입니다. 외부 표현의 형식은 point_conversion_form에 의해 설명 된 입니다. point_conversion_form에 대한 설명은 EC_GROUP_copy (3)을 참조하십시오. 옥텟 문자열은 연관된 버퍼 길이와 함께 버퍼에 저장됩니다. BIGNUM에있는 포인트는 포인트를 옥텟 문자열로 변환하고 을 변환 한 다음 해당 옥텟 문자열을 BIGNUM 정수로 변환하여 계산합니다. 의 16 진수 형식은 NULL로 끝나는 문자열 에 저장되며 각 문자는 인쇄 가능한 값 0-9 또는 A-F (또는 a-f) 중 하나입니다.

$ 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이 위키에 지점을 설정하는 방법의 예를 볼 수 있습니다

또한 EC_POINT_set_affine_coordinates_GFp, EC_POINT_set_affine_coordinates_GF2mEC_KEY_set_public_key를 참조하십시오.

관련 문제