使用ECDSA在代码和命令行中创建并验证签名

使用ECDSA在代码和命令行中创建并验证签名,c,openssl,pem,ecdsa,der,C,Openssl,Pem,Ecdsa,Der,问题: 使用编写的演示代码(如下所示),我可以毫无问题地创建和验证。 但是,使用openssl命令行工具验证签名(由演示代码创建) 似乎总是失败 我所做的: 演示代码创建一个已定义的公钥/私钥对,然后对已定义的哈希进行签名并进行验证 这是程序输出: Public key: 04DFEC134530603832A31F8885EF01888884483D611F87A698213F168534EC06D85D21F7C85795435BC9A7F78190126CC6E52E050CBDFD43E

问题: 使用编写的演示代码(如下所示),我可以毫无问题地创建和验证。 但是,使用openssl命令行工具验证签名(由演示代码创建) 似乎总是失败

我所做的: 演示代码创建一个已定义的公钥/私钥对,然后对已定义的哈希进行签名并进行验证

这是程序输出:

Public key: 04DFEC134530603832A31F8885EF01888884483D611F87A698213F168534EC06D85D21F7C85795435BC9A7F78190126CC6E52E050CBDFD43E27175FB1DF3E3DEF6 
Hash: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
Verified EC Signature
R: 383EB65E4A284CBCBA41A9777CE7C0816C5C23161EA9BC4EF8B1E668C7641A2A 
S: 608F4BAB9DFE6DC8F976C32D72508CD5BD68F9E325ADED69A9883CE487E6698B
它还输出以下文件:

  • privkey.pem
    (pem格式的私钥)
  • pubkey.pem
    (pem格式的公钥)
  • data.bin
    (散列,没什么特别的)
  • data\u sig.der
    (der编码签名:R&S值)
所有文件似乎都已正确创建

接下来,我尝试使用openssl命令行工具验证
data\u sig.der

$ openssl dgst -verify pubkey.pem -signature data_sig.der data.bin
Verification Failure
为什么会失败

我只能假设4个文件中有一个写错了, 但我仔细检查了一切,无法发现我的错误

此外,使用演示程序创建的PEM文件, 从命令行签名并验证工作正常:

$openssl dgst -sign privkey.pem data.bin > data_sig2.der
$openssl dgst -verify pubkey.pem -signature data_sig2.der data.bin
Verified OK
下面是演示代码(使用gcc demo_code.c-lcrypto-lssl-o demo_code编译):

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
void createSignature()
{
EC_KEY*eckey=EC_KEY_new();
EC_组*ecgroup=EC_组_新_按_曲线_名称(NID_X9_62_prime256v1);
ECU密钥组(eckey,ecgroup);
eckey_set_asn1_标志(eckey、OPENSSL_ECU命名曲线);
/*私钥值*/
const char*p_str=“7D22AB6A1FD3FC1F5EBEDCA22151375683B733E9DDC9CA5B2485E202C55D25C”;
BIGNUM*prv=BN_new();
20亿欧元(&prv,p_str);
EC_POINT*pub=EC_POINT_new(ecgroup);
/*计算公钥*/
EC_POINT_mul(ecgroup、pub、prv、NULL、NULL、NULL);
/*将私钥和公钥添加到EC_密钥结构中*/
EC_-KEY_-set_-private_-KEY(eckey,prv);
EC_KEY_set_public_KEY(eckey,pub);
/*以十六进制格式输出公钥*/
char*hexPKey=EC_POINT_point2hex(ecgroup,pub,POINT_CONVERSION_UNCOMPRESSED,NULL);
printf(“公钥:%s\n”,hexPKey);
/*创建散列*/
printf(“散列:”);
uint8_t散列[32];
对于(int i=0;i<32;i++){
散列[i]=i;
printf(“%02x”,散列[i]);
}
printf(“\n”);
/*创建并验证签名*/
ECDSA_SIG*signature=ECDSA_do_sign(散列,32,eckey);
//哈希[0]=0xff;//如果验证失败且哈希错误,则取消对测试的注释
如果(1!=ECDSA\u do\u验证(哈希,32,签名,eckey)){
printf(“验证EC签名失败\n”);
}否则{
printf(“经验证的EC签名”);
}
/*以十六进制格式打印R&S值*/
char*hexR=BN_bn2hex(签名->r);
char*hexS=BN_bn2hex(签名->s);
printf(“R:%s\n:%s\n”,hexR,hexS);
/*将原始签名导出为DER编码格式*/
int sigSize=i2d_ECDSA_SIG(签名,NULL);
uint8_t*derSig=(uint8_t*)malloc(sigSize);
uint8_t*p=derSig;//memset(sig_字节,6,sig_大小);
sigSize=i2d_ECDSA_SIG(签名和p);
EVP_PKEY*PKEY=EVP_PKEY_new();
EVP_PKEY_set1_EC_KEY(PKEY,eckey);
/*写文件*/
文件*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(散列,1,sizeof(散列),fp);
fclose(fp);
fp=fopen(“数据符号顺序”,“w”);
fwrite(derSig,1,sigSize,fp);
fclose(fp);
/*自由运行时分配的资源*/
免费(derSig);
OPENSSL_-free(hexPKey);OPENSSL_-free(hexR);OPENSSL_-free(hexS);
无BN_(prv);
免费欧共体(pub);
欧共体集团自由(欧共体集团);
无电子钥匙(电子钥匙);
}
int main(int argc,字符**argv){
createSignature();
返回(退出成功);
}

似乎您对数据进行了签名,而不是对数据进行哈希运算的结果。但当你跑步时:

$ openssl dgst -verify pubkey.pem -signature data_sig.der data.bin
openssl实用程序从
data.bin
计算sha256哈希,并尝试验证此哈希上的签名

因此,您需要从
000102030405060708090A0B0C0D0E0F1011112131415161718191A1B1C1D1E1F计算sha256,并签署结果:

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);
}
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);
}
$ openssl dgst -verify pubkey.pem -signature data_sig.der data.bin
Verified OK