4

我正在尝试制作一个程序,在它使用 OppenSSL EC 函数 EC_KEY_generate_key 生成公钥/私钥对后,将它们存储在单独的文件中并检索它们以生成 ECDH KEY。

我的问题是,虽然我正确存储它们(没有任何附加字符),但当我读取文件并尝试将十六进制字符转换为 BIGNUM 时,随机出现字符“04”或“00”(有时甚至不出现)。因此,当我尝试设置公钥/私钥并检查整个密钥时,它会失败。谁能帮我解决这个问题?密钥检查失败是由这些字符引起的还是正常的?

这是我生成/存储私钥的代码(公钥相同):

    EC_KEY *b = NULL;
const BIGNUM *ppriv_b;
FILE *claveprivb;
const EC_GROUP *group;

b = EC_KEY_new_by_curve_name(NID_X9_62_prime192v1);
group = EC_KEY_get0_group(b);

EC_KEY_generate_key(b);
    claveprivb = fopen("/tmp/mnt/claveprivb", "w+");
    ppriv_b = EC_KEY_get0_private_key(b);
if ((ppriv_b != NULL)) 
    BN_print_fp(claveprivb,ppriv_b);
    fclose(claveprivb);

    //Afterwards do the same with the public key

这是我检索私钥的代码:

    int i, s, blen, bout, ret = 0;
unsigned char *bbuf;
FILE *clavepriv, *clavetotalb;
const char cpriv_string[PRIVATE_KEY_SIZE];
BIGNUM *priv;
EC_KEY *b = NULL;
const EC_GROUP *groupb;

    b = EC_KEY_new_by_curve_name(NID_X9_62_prime192v1);
groupb = EC_KEY_get0_group(b);
    //Open the file with the hexadecimals (PRIVATE KEY)
    clavepriv = fopen("/tmp/mnt/claveprivb", "r");
kk2 = fread(&cpriv_string, sizeof(char), PRIVATE_KEY_SIZE, clavepriv);

priv = BN_new();
    //THIS FUNCTION (HEX2BN) GENERATES THE RANDOM CHARACTER: 
kk2 = BN_hex2bn(&priv, cpriv_string);
ret = EC_KEY_set_private_key(b, priv);

    //HERE I retrieve the public key by the same way and set it into EC_KEY b,
    //the same random character appears in the public key

    if (!EC_KEY_check_key(b)) {
    printf("EC_KEY_check_key failed\n");
} else {
    printf("Key verified OK\n");
}
    //It fails when try to check it.

int k;
clavetotalb = fopen("/tmp/mnt/clavetotalb", "w+");
k = EC_KEY_print_fp(clavetotalb, b, 0);

bout = ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(b), b,
        KDF1_SHA1);

任何建议将不胜感激!!!!谢谢!

在我阅读了答案后,我尝试使用这些方法对公钥进行解码和编码,但是当我尝试计算 ECDH 密钥时,我遇到了分段错误。我的程序的目标是生成两个 EC 密钥,将它们写入几个文件,然后检索它们并用它们计算一个 ECDH 密钥。这是我在第一个线程中从原始程序中更改的内容列表,如果有问题请告诉我:

* Generate EC key (public & private)
* Decode the private key with i2d_ECPrivatekey()
* Decode the public key with i2o_ECPublickey()
* Write them into several files.
* Read the file with the public key.
* Encode it with o2i_ECPublickey()
* Read the file with the private key.
* Encode it with d2i_ECPrivatekey().
* Compute the ECDH key.(Here is where I get the segmentation fault)

我已经厌倦了这个 OpenSSL 库……对于初次使用的用户来说太难了……

4

1 回答 1

5

EC 公钥不是整数;它是一个曲线点,可以被认为是一整数。这两个整数是点坐标(通常称为XY)。

一些符号:曲线是在有限域中定义的。有限域元素可以映射到从0q-1的整数,其中q是域大小(在您使用的曲线的情况下,q是略低于2 192的素数)。令nq-1的字节大小:这是q -1的无符号大端表示的大小,即满足2 8(n-1) <= q-1 < 2 8n的整数。对于您的曲线,n = 24

使用这些符号,曲线点的标准表示正好包含1+2n个字节,按以下顺序:

  • 值 0x04 的字节
  • xn字节上的无符号大端表示
  • yn字节上的无符号大端表示

所以这解释了你的“0x04”额外字节;此外,由于xy将在n个字节上进行编码,因此这可能会强制包含额外的 '0x00' 字节,以防它们的实际值小于2 8(n-1)(根据您的曲线,这平均而言,大约 1/128 的公钥应该是这种情况)。

这种表示还有其他变体(compressed,其中总大小为1+n,第一个字节为 0x02 或 0x03,以及hybrid,大小为1+2n,其中第一个字节为 0x06 或 0x07),但它们是在 ECDSA 标准 (X9.62-2005) 中被认为是可选的,并且有传言说压缩格式已获得专利。

底线:如果您想编码和解码 EC 公钥,您应该查看o2i_ECPublicKey()and i2o_ECPublicKey(),并将它们作为任意字节序列处理,而不是编码整数。

于 2011-05-06T12:36:08.713 回答