2016-06-09 3 views
1

Problème: En utilisant le code de démonstration écrit (donné ci-dessous), je peux créer et vérifier sans problèmes. Cependant, en utilisant l'outil de ligne de commande openssl, la vérification d'une signature (créée par le code de démonstration) semble toujours échouer.Créer et vérifier la signature dans le code et à partir de la ligne de commande en utilisant ECDSA

Qu'est-ce que je l'ai fait: Le code de démonstration crée une clé publique/privée définie paire, signe alors un hachage défini et vérifie.

C'est la sortie du programme:

Public key: 04DFEC134530603832A31F8885EF01888884483D611F87A698213F168534EC06D85D21F7C85795435BC9A7F78190126CC6E52E050CBDFD43E27175FB1DF3E3DEF6 
Hash: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 
Verified EC Signature 
R: 383EB65E4A284CBCBA41A9777CE7C0816C5C23161EA9BC4EF8B1E668C7641A2A 
S: 608F4BAB9DFE6DC8F976C32D72508CD5BD68F9E325ADED69A9883CE487E6698B 

comme sorties bien les fichiers follwing:

  • privkey.pem (clé privée au format PEM)
  • pubkey.pem (clé publique au format PEM)
  • data.bin (le hachage, rien d'extraordinaire)
  • data_sig.der (la signature codée DER: R & valeur S)

Tous les fichiers semblent être créés correctement.

Ensuite, j'essaie de vérifier data_sig.der avec l'outil de ligne de commande openssl.

$ openssl dgst -verify pubkey.pem -signature data_sig.der data.bin 
Verification Failure 

Pourquoi cela échoue-t-il?

Je ne peux que supposer que l'un des 4 fichiers a été écrit de manière incorrecte, mais je tout revérifié et ne peut pas repérer mon erreur.

De plus, en utilisant les fichiers PEM créés par le programme de démonstration, signe & vérifier belles œuvres de la ligne de commande:

$openssl dgst -sign privkey.pem data.bin > data_sig2.der 
$openssl dgst -verify pubkey.pem -signature data_sig2.der data.bin 
Verified OK 

Voici le code de démonstration (compile avec gcc demo_code.c -lcrypto -lssl -o demo_code):

#include <stdio.h> 
#include <stdlib.h> 

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

void createSignature() 
{ 
    EC_KEY* eckey = EC_KEY_new(); 
    EC_GROUP* ecgroup = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); 
    EC_KEY_set_group(eckey,ecgroup); 
    EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); 

    /* the private key value */ 
    const char *p_str = "7D22AB6A1FD3FC1F5EBEDCA222151375683B733E9DDC9CA5B2485E202C55D25C"; 
    BIGNUM* prv = BN_new(); 
    BN_hex2bn(&prv, p_str); 
    EC_POINT* pub = EC_POINT_new(ecgroup); 

    /* calculate the public key */ 
    EC_POINT_mul(ecgroup, pub, prv, NULL, NULL, NULL); 

    /* add the private & public key to the EC_KEY structure */ 
    EC_KEY_set_private_key(eckey, prv); 
    EC_KEY_set_public_key(eckey, pub); 
    /* output public key in hex format */ 
    char* hexPKey = EC_POINT_point2hex(ecgroup, pub, POINT_CONVERSION_UNCOMPRESSED, NULL); 
    printf("Public key: %s \n", hexPKey); 
    /* create hash */ 
    printf("Hash: "); 
    uint8_t hash[32]; 
    for(int i=0; i < 32; i++) { 
     hash[i] = i; 
     printf("%02x",hash[i]); 
    } 
    printf("\n"); 
    /* create and verify signature */ 
    ECDSA_SIG* signature = ECDSA_do_sign(hash, 32, eckey); 
    //hash[0] = 0xff; // Uncomment to test if verification fails with a wrong hash 
    if (1 != ECDSA_do_verify(hash, 32, signature, eckey)) { 
     printf("Failed to verify EC Signature\n"); 
    } else { 
     printf("Verified EC Signature\n"); 
    } 
    /*print R & S value in hex format */ 
    char* hexR = BN_bn2hex(signature->r); 
    char* hexS = BN_bn2hex(signature->s); 
    printf("R: %s \nS: %s\n", hexR, hexS); 
    /* export raw signature to DER-encoded format */ 
    int sigSize = i2d_ECDSA_SIG(signature, NULL); 
    uint8_t* derSig = (uint8_t*)malloc(sigSize); 
    uint8_t* p = derSig; //memset(sig_bytes, 6, sig_size); 
    sigSize= i2d_ECDSA_SIG(signature, &p); 

    EVP_PKEY* pkey = EVP_PKEY_new(); 
    EVP_PKEY_set1_EC_KEY(pkey, eckey); 

    /* write files */ 
    FILE* fp = fopen("pubkey.pem", "w"); 
    PEM_write_PUBKEY(fp, pkey); 
    fclose(fp); 
    fp = fopen("privkey.pem", "w"); 
    PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, 0, NULL); 
    fclose(fp); 
    fp = fopen("data.bin", "w"); 
    fwrite(hash, 1, sizeof(hash), fp); 
    fclose(fp); 
    fp = fopen("data_sig.der", "w"); 
    fwrite(derSig, 1, sigSize, fp); 
    fclose(fp); 

    /* free runtime allocated res */ 
    free(derSig); 
    OPENSSL_free(hexPKey); OPENSSL_free(hexR); OPENSSL_free(hexS); 
    BN_free(prv); 
    EC_POINT_free(pub); 
    EC_GROUP_free(ecgroup); 
    EC_KEY_free(eckey); 
} 

int main(int argc, char** argv) { 
    createSignature(); 
    return (EXIT_SUCCESS); 
} 

Répondre

2

Il semble que vous signiez des données plutôt que des résultats de hachage de données. Mais lorsque vous exécutez:

$ openssl dgst -verify pubkey.pem -signature data_sig.der data.bin 

OpenSSL utilitaire hachage SHA256 calculer à partir data.bin et essayez de vérifier la signature sur ce hachage.

Vous devez calco SHA256 de 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f et le résultat des signes:

void createSignature() 
{ 
    EC_KEY* eckey = EC_KEY_new(); 
    EC_GROUP* ecgroup = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); 
    EC_KEY_set_group(eckey,ecgroup); 
    EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); 

    /* the private key value */ 
    const char *p_str = "7D22AB6A1FD3FC1F5EBEDCA222151375683B733E9DDC9CA5B2485E202C55D25C"; 
    BIGNUM* prv = BN_new(); 
    BN_hex2bn(&prv, p_str); 
    EC_POINT* pub = EC_POINT_new(ecgroup); 

    /* calculate the public key */ 
    EC_POINT_mul(ecgroup, pub, prv, NULL, NULL, NULL); 

    /* add the private & public key to the EC_KEY structure */ 
    EC_KEY_set_private_key(eckey, prv); 
    EC_KEY_set_public_key(eckey, pub); 
    /* output public key in hex format */ 
    char* hexPKey = EC_POINT_point2hex(ecgroup, pub, POINT_CONVERSION_UNCOMPRESSED, NULL); 
    printf("Public key: %s \n", hexPKey); 
    /* create hash */ 
    printf("Data: "); 
    uint8_t data[32]; 
    for(int i=0; i < 32; i++) { 
     data[i] = i; 
     printf("%02x",data[i]); 
    } 
    printf("\n"); 

    uint8_t hash[32]; 
    SHA256_CTX sha256; 
    SHA256_Init(&sha256); 
    SHA256_Update(&sha256, data, sizeof(data)); 
    SHA256_Final(hash, &sha256); 

    printf("Hash: "); 
    for(int i=0; i < 32; i++) { 
     data[i] = i; 
     printf("%02x",hash[i]); 
    } 
    printf("\n"); 

    /* create and verify signature */ 
    ECDSA_SIG* signature = ECDSA_do_sign(hash, 32, eckey); 
    /* hash[0] = 0xff; // Uncomment to test if verification fails with a wrong hash */ 
    if (1 != ECDSA_do_verify(hash, 32, signature, eckey)) { 
     printf("Failed to verify EC Signature\n"); 
    } else { 
     printf("Verified EC Signature\n"); 
    } 
    /*print R & S value in hex format */ 
    char* hexR = BN_bn2hex(signature->r); 
    char* hexS = BN_bn2hex(signature->s); 
    printf("R: %s \nS: %s\n", hexR, hexS); 
    /* export raw signature to DER-encoded format */ 
    int sigSize = i2d_ECDSA_SIG(signature, NULL); 
    uint8_t* derSig = (uint8_t*)malloc(sigSize); 
    uint8_t* p = derSig; //memset(sig_bytes, 6, sig_size); 
    sigSize= i2d_ECDSA_SIG(signature, &p); 

    EVP_PKEY* pkey = EVP_PKEY_new(); 
    EVP_PKEY_set1_EC_KEY(pkey, eckey); 

    /* write files */ 
    FILE* fp = fopen("pubkey.pem", "w"); 
    PEM_write_PUBKEY(fp, pkey); 
    fclose(fp); 
    fp = fopen("privkey.pem", "w"); 
    PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, 0, NULL); 
    fclose(fp); 
    fp = fopen("data.bin", "w"); 
    fwrite(data, 1, sizeof(data), fp); 
    fclose(fp); 
    fp = fopen("data_sig.der", "w"); 
    fwrite(derSig, 1, sigSize, fp); 
    fclose(fp); 

    /* free runtime allocated res */ 
    free(derSig); 
    OPENSSL_free(hexPKey); 
    OPENSSL_free(hexR); OPENSSL_free(hexS); 
    BN_free(prv); 
    EC_POINT_free(pub); 
    EC_GROUP_free(ecgroup); 
    EC_KEY_free(eckey); 
} 

fonctionne maintenant vérifier OpenSSL:

$ openssl dgst -verify pubkey.pem -signature data_sig.der data.bin 
Verified OK 
+0

Vous avez raison! - Merci beaucoup – 0laf