c - OpenSSL i2d_ECPrivateKey() 崩溃

标签 c openssl elliptic-curve

我有以下程序。它成功获取了原始的 32 字节 EC 私钥数据,然后从中创建了一个 EC_KEY。但是 i2d_ECPrivateKey 无法给出 DER 编码私钥的大小,因为它会崩溃。有谁知道为什么以及如何解决这个问题?

#include "CBWIF.h"
#include <openssl/ssl.h>

int main(int argc, char * argv[]) {

    CBWIF wif;

    if (argc != 2)
        return EXIT_FAILURE;

    // Decode WIF string
    CBByteArray str;
    CBInitByteArrayFromString(&str, argv[1], false);
    CBInitWIFFromString(&wif, &str, false);
    CBDestroyByteArray(&str);

    // Get key
    uint8_t key[32];
    CBWIFGetPrivateKey(&wif, key);
    CBDestroyWIF(&wif);

    // Create OpenSSL key

    EC_KEY * eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
    BIGNUM * bn = BN_bin2bn(key, CB_PRIVKEY_SIZE, NULL);
    if (!EC_KEY_set_private_key(eckey, bn)) 
        return EXIT_FAILURE;

    // Convert key to DER format

    int len = i2d_ECPrivateKey(eckey, NULL); // <-- CRASH HERE  
    unsigned char derkey[len];
    i2d_ECPrivateKey(eckey, (unsigned char **)&derkey);

    EC_KEY_free(eckey);

    // Encode DER key as hex

    char out[len*2+1];  
    CBBytesToString(derkey, 0, len, out, false);

    // Print to stdout      
    puts(out);

    return EXIT_SUCCESS;
}

CB_PRIVKEY_SIZE 是 32。我验证了来自 CBWIFGetPrivateKey 的 key 数据是正确的。该程序因以下堆栈跟踪而崩溃:

#0  0x00007ffff766cb03 in EC_POINT_point2oct () from /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0
#1  0x00007ffff7658124 in i2d_ECPrivateKey () from /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0
#2  0x0000000000400bf6 in main (argc=2, argv=0x7fffffffe038) at examples/WIF2DER.c:46

最佳答案

原因是你不能在没有设置公钥的情况下运行 i2d_ECPrivateKey,这可能是由于 OpenSSL 中的错误。我生成了公钥并解决了一些其他问题,现在程序可以运行了:

#include "CBWIF.h"
#include <openssl/ssl.h>

int main(int argc, char * argv[]) {

    CBWIF wif;

    if (argc != 2)
        return EXIT_FAILURE;

    // Decode WIF string
    CBByteArray str;
    CBInitByteArrayFromString(&str, argv[1], false);
    CBInitWIFFromString(&wif, &str, false);
    CBDestroyByteArray(&str);

    // Get key
    uint8_t key[32];
    CBWIFGetPrivateKey(&wif, key);
    CBDestroyWIF(&wif);

    // Create OpenSSL key
    EC_KEY * eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
    BIGNUM * bn = BN_bin2bn(key, CB_PRIVKEY_SIZE, NULL);

    if (!EC_KEY_set_private_key(eckey, bn)) 
        return EXIT_FAILURE;

    // Create public key as OpenSSL cannot do this easily
    EC_GROUP * group = EC_GROUP_new_by_curve_name(NID_secp256k1);
    EC_POINT * point = EC_POINT_new(group);
    BN_CTX * ctx = BN_CTX_new();

    EC_POINT_mul(group, point, bn, NULL, NULL, ctx);

    BN_CTX_free(ctx);
    EC_GROUP_free(group);
    BN_free(bn);

    if (!EC_KEY_set_public_key(eckey, point))
        return EXIT_FAILURE;

    EC_POINT_free(point);

    // Check the key
    if (!EC_KEY_check_key(eckey))
        return EXIT_FAILURE;

    // Convert key to DER format
    int len = i2d_ECPrivateKey(eckey, NULL);    
    unsigned char derkey[len];
    unsigned char * derkeyPtr = derkey;
    i2d_ECPrivateKey(eckey, &derkeyPtr);

    // Freeing the EC_KEY here crashes for some reason???

    // Encode DER key as hex

    char out[len*2+1];  
    CBBytesToString(derkey, 0, len, out, false);

    // Print to stdout
    puts(out);

    return EXIT_SUCCESS;
}

关于c - OpenSSL i2d_ECPrivateKey() 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24534320/

相关文章:

c - MPI:当预期的 MPI_Recv 数量未知时该怎么办

c - RRD具有高精度?

java - 使用 BouncyCaSTLe 从 PEM 格式恢复 EC 私钥

c# - 验证 Java Card 签名

c - 帮助我理解这些计算时间

C 字符串指针函数 strdel

Ruby - 不支持的密码算法 (AES-256-GCM)

c++ - 字符串未使用 <openssl/aes> 正确解密

c++ - CURLpp:TLS 握手错误