我正在尝试制作一个程序,在使用OppenSSL EC函数EC_KEY_generate_key生成公钥/私钥对后将它们存储在单独的文件中并检索它们以生成ECDH密钥。
我的问题是,虽然我正确地存储它们(没有任何额外的字符),当我读取文件并尝试将十六进制字符转换为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 failedn");
} else {
printf("Key verified OKn");
}
//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库…
EC公钥不是整数;它是一个曲线点,可以认为是对整数。这两个整数是点坐标(通常称为X和Y)。
一些符号:曲线定义在有限域中。有限域元素可以映射为从0到q-1的整数,其中q是字段大小(在您使用的曲线的情况下,q是一个略小于2192的素数整数)。设n为q-1的字节数:这是q-1的无符号大端位数表示的大小,即满足28(n-1) <= q-1 <2 <一口> 8 n 一口>。对于曲线,n = 24。
有了这些符号,曲线点的标准表示恰好由1+2n字节组成,按顺序是:- 值0x04的字节
- x/n字节的无符号大端表示
- y除以n字节的无符号大端表示
所以这解释了你的'0x04'额外字节;此外,由于x和y要在n字节上编码,这可能会强制包含额外的'0x00'字节,以防它们的实际值小于28(n-1)(根据您的曲线,这应该是这种情况,平均而言,大约1/128的公钥)。
还有这种表示的其他变体(压缩,其中总大小为1+n,第一个字节为0x02或0x03,以及混合,大小为1+2n,第一个字节为0x06或0x07),但它们在ECDSA标准(X9.62-2005)中被认为是可选的,有传言说压缩格式是专利的。
底线:如果您想编码和解码EC公钥,您应该查看o2i_ECPublicKey()
和i2o_ECPublicKey()
,并将它们作为任意字节序列处理,而不是编码的整数。