2017-10-03 6 views
1

J'essaie de calculer la clé publique à partir d'un secret donné par openssl. Je reçois cette erreur:Erreur openssl définition incomplète de type 'struct ec_key_st'

main.c:27: error: incomplete definition of type 'struct ec_key_st' 
    printf("d: %s\n", BN_bn2hex(eckey->priv_key)); 
           ~~~~~^ 

Voici mon code:

#include <stdio.h> 

#include <openssl/ec.h> 
#include <openssl/ecdsa.h> 
#include <openssl/bn.h> 
#include <openssl/obj_mac.h> 

int main() 
{ 
    BN_CTX *ctx = BN_CTX_new(); 

    EC_KEY *eckey = EC_KEY_new(); 
    EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1); 
    EC_KEY_set_group(eckey, group); 

    BIGNUM *prv = BN_new(); 
    BN_hex2bn(&prv, "b14fac12b3fa7dd6f2562a18d554fcd6818137ebb7e0d119ab0776d6407664f9"); 
    EC_KEY_set_private_key(eckey, prv); 

    EC_POINT *Q = EC_POINT_new(group); 
    EC_POINT_mul(group, Q, prv, NULL, NULL, ctx); 
    EC_KEY_set_public_key(eckey, Q); 

    if (EC_KEY_check_key(eckey)) 
    printf("Key succesfully checked.\n"); 

    printf("d: %s\n", BN_bn2hex(eckey->priv_key)); 
    printf("X: %s\n", BN_bn2hex(&eckey->pub_key->X)); 
    printf("Y: %s\n", BN_bn2hex(&eckey->pub_key->Y)); 

    EC_GROUP_free (group); group = NULL; 
    EC_KEY_free (eckey); eckey = NULL; 
    return 0; 
} 

Quel est le problème avec le code ci-dessus? Si j'enlève les lignes printf, ça fonctionne bien. J'apprécierais que quelqu'un m'aide à me débarrasser de cette erreur.

Répondre

0

Vous devez obtenir le fichier d'en-tête "ec_lcl.h" du libraire openssl, afin d'accéder aux membres de la structure "ec_key_st". Notez que "ECKEY" est défini comme:

typedef struct ec_key_st EC_KEY; 

Si vous mettez "ec_lcl.h" dans votre dossier de projet, puis changer votre code à ceci:

#include <stdio.h> 

#include <openssl/ec.h> 
#include <openssl/ecdsa.h> 
#include <openssl/bn.h> 
#include <openssl/obj_mac.h> 

#include "ec_lcl.h" 

int main() 
{ 
    BN_CTX *ctx = BN_CTX_new(); 

    struct ec_key_st *eckey = EC_KEY_new(); 
    EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1); 
    EC_KEY_set_group(eckey, group); 

    BIGNUM *prv = BN_new(); 
    BN_hex2bn(&prv, "b14fac12b3fa7dd6f2562a18d554fcd6818137ebb7e0d119ab0776d6407664f9"); 
    EC_KEY_set_private_key(eckey, prv); 

    EC_POINT *Q = EC_POINT_new(group); 
    EC_POINT_mul(group, Q, prv, NULL, NULL, ctx); 
    EC_KEY_set_public_key(eckey, Q); 

    if (EC_KEY_check_key(eckey)) 
    printf("Key succesfully checked.\n"); 

    printf("d: %s\n", BN_bn2hex(eckey->priv_key)); 
    printf("X: %s\n", BN_bn2hex(&eckey->pub_key->X)); 
    printf("Y: %s\n", BN_bn2hex(&eckey->pub_key->Y)); 

    EC_GROUP_free (group); group = NULL; 
    EC_KEY_free (eckey); eckey = NULL; 
    return 0; 
} 
+0

Cette n'est pas la bonne façon de faire les choses. "ec_lcl.h" est un fichier d'en-tête interne qui ne fait pas partie de l'API publique. L'accès direct aux composants internes de la structure est susceptible de passer d'une version d'OpenSSL à une autre. Il existe des fonctions API publiques pour accéder à ces éléments, qui devraient être utilisées à la place. Voir la réponse de @bartonjs –

+1

Est-ce vraiment "pas la bonne façon"? "pas correct" techniquement? socialement? Pourquoi? parce que d'autres personnes de l'ocd pourraient avoir mal à leurs sentiments? OpenSSL est une bibliothèque open source. Donc, si certaines personnes peuvent lire et comprendre ses internes, ils devraient avoir le droit de les utiliser comme ils l'entendent, du moins tant qu'ils ne s'attendent pas à ce que leur code fonctionne avec les changements futurs de cette bibliothèque. – hutheano

+0

En utilisant ec_lcl.h vous devenez vulnérable aux problèmes où un champ est ajouté ou supprimé à une structure dans la prochaine mise à jour. Votre code pense qu'il est au décalage 16, son code pense qu'il est au décalage 24, et maintenant vous travaillez avec un champ autre que vous pensiez. Bien que cela soit vrai dans les en-têtes publics, aussi, un changement de structure publique brise tout le monde (leur bug) et un changement vers un privé ne vous casse que (votre bug). Donc, oui, c'est définitivement "pas la bonne façon". – bartonjs

4

Vous utilisez 1.1 OpenSSL, et ils ont décidé que vous ne deviez plus fouiner dans les entrailles de leurs structures.

eckey->priv_key était un moyen valable d'accéder à la clé privée dans OpenSSL 1.0.x, mais maintenant la seule façon correcte est EC_KEY_get0_private_key(eckey)

De même, pour la clé publique il est EC_KEY_get0_public_key(eckey).

Ces deux fonctions ont été déclarées au cours OpenSSL 1.0.x, de sorte que vous pouvez écrire le code pour être le même entre eux.

Alors

printf("d: %s\n", BN_bn2hex(eckey->priv_key)); 
printf("X: %s\n", BN_bn2hex(&eckey->pub_key->X)); 
printf("Y: %s\n", BN_bn2hex(&eckey->pub_key->Y)); 

deviendrait

{ 
    const BIGNUM* d = EC_KEY_get0_private_key(eckey); 
    const EC_POINT* Q = EC_KEY_get0_public_key(eckey); 
    const EC_GROUP* group = EC_KEY_get0_group(eckey); 
    BIGNUM* x = BN_new(); 
    BIGNUM* y = BN_new(); 

    if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, null)) 
    { 
     error(); 
    } 

    printf("d: %s\n", BN_bn2hex(d)); 
    printf("X: %s\n", BN_bn2hex(x)); 
    printf("Y: %s\n", BN_bn2hex(y)); 

    BN_free(x); 
    BN_free(y); 
} 

Cela permet de maintenir votre code de travail, même lorsque OpenSSL 1.1.1 décide de refaire la mise en page de struct qui a été caché dans ec_lcl.h

+0

En fait, EC_KEY a été * toujours * déclaré opaque, même dans 1.0.x. Donc, accéder directement à ses internes n'était jamais une manière valide de faire les choses. En dehors de cela, c'est une bonne réponse. –