生成EC Diffie-Hellman公钥和私钥对

我需要生成一个EC Diffie Hellman密钥对。 我使用的是secp256r1命名曲线和OpenSSL。 这就是我到目前为止所拥有的:

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

我发现要使这个function起作用,我需要一个带有第二方公钥的EVP_KEY对象。 我在字节数组中有这个公钥,也有它的长度。 如何将其转换为所需类型? 而且我在OpenSSL中找不到secp256r1曲线,但在做了一些研究之后我在代码中使用了它。 这是对的吗?

谢谢 !

对等方的公钥是曲线上的一个点。 从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是一个私有头,所以你将无法访问该结构)。

幸运的是,有很多function可以操纵它们。 来自EC_POINT_new(3)文档:

EC_POINT可以转换为各种外部表示forms。 支持的表示是八位字符串,BIGNUM和hex。 外部表示的格式由point_conversion_form描述。 有关point_conversion_form的说明,请参阅EC_GROUP_copy(3)。 Octet字符串与相关的缓冲区长度一起存储在缓冲区中。 通过将该点转换为八位字节串然后将该八位字节串转换为BIGNUM整数来计算BIGNUM中保持的点。 hex格式的点存储在以NULL结尾的字符串中,其中每个字符是可打印值0-9或AF(或af)之一。

另请参阅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 wiki上设置点的示例。