Générer une paire de clés publique et privée EC Diffie-Hellman

Je dois générer une paire de clés EC Diffie Hellman. J’utilise la courbe nommée secp256r1 et OpenSSL. Voici ce que j’ai avec moi jusqu’à présent:

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

J’ai compris que pour que cette fonction fonctionne, j’ai besoin d’un object EVP_KEY avec la clé publique du second parti. J’ai cette clé publique dans un tableau d’octets, ainsi que sa longueur. Comment est-ce que je le convertis au type requirejs? Et aussi je ne pouvais pas trouver la courbe secp256r1 dans OpenSSL, mais j’ai utilisé celle du code après quelques recherches. Est-ce correct?

Merci !

La clé publique du pair est un point sur la courbe. De 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 */; 

Je pense que vous devez appeler EC_POINT_new ( c_lcl.h est un en-tête privé, vous n’avez donc pas access à la structure).

Heureusement, il y a beaucoup de fonctions pour les manipuler. De la documentation EC_POINT_new(3) :

Les EC_POINT peuvent être convertis vers et à partir de diverses représentations externes. Les représentations sockets en charge sont les chaînes d’octets, BIGNUM et hexadécimaux. Le format de la représentation externe est décrit par le point_conversion_form. Voir EC_GROUP_copy (3) pour une description de point_conversion_form. Les chaînes d’octets sont stockées dans une mémoire tampon avec une longueur de mémoire tampon associée. Un point contenu dans un BIGNUM est calculé en le convertissant en une chaîne d’octets, puis en convertissant cette chaîne d’octets en un entier BIGNUM. Les points au format hexadécimal sont stockés dans une chaîne de caractères terminée par la valeur NULL, chaque caractère étant l’une des valeurs imprimables comsockets entre 0 et 9 ou AF (ou af).

Voir aussi EC_POINT_set_affine_coordinates_GFp , EC_POINT_set_affine_coordinates_GF2m et EC_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); ... 

Vous pouvez voir un exemple sur la manière de définir le point sur le wiki OpenSSL à la section Cryptographie à courbes elliptiques .