我正在尝试从DNSSEC算法13(ECDSAP256SHA256)的已知私钥获取公钥。我使用了这个例子:https://stackoverflow.com/a/17062076/3090865
为我的密钥修改了这个:
// using figures on: https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses
// gcc -Wall ecdsapubkey.c -o ecdsapubkey -lcrypto
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>
#include <openssl/bn.h>
int main()
{
EC_KEY *eckey = NULL;
EC_POINT *pub_key = NULL;
const EC_GROUP *group = NULL;
BIGNUM start;
BIGNUM *res;
BN_CTX *ctx;
BN_init(&start);
ctx = BN_CTX_new(); // ctx is an optional buffer to save time from allocating and deallocating memory whenever required
res = &start;
BN_hex2bn(&res,"589c51d2b528a99c1d19702f865284ec09e3e080606ddc3f56f0906268fd25e3");
eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
group = EC_KEY_get0_group(eckey);
pub_key = EC_POINT_new(group);
EC_KEY_set_private_key(eckey, res);
/* pub_key is a new uninitialized `EC_POINT*`. priv_key res is a `BIGNUM*`. */
if (!EC_POINT_mul(group, pub_key, res, NULL, NULL, ctx))
printf("Error at EC_POINT_mul.\n");
EC_KEY_set_public_key(eckey, pub_key);
char *cc = EC_POINT_point2hex(group, pub_key, 4, ctx);
printf("%s", cc);
BN_CTX_free(ctx);
free(cc);
return 0;
}
尝试:
$ gcc -lcrypto t.c
$ ./a.out | perl -e 'print pack "H*", <>' | base64
BDdZbz79hEKFi9bIlExzZEqPQVhNqcjJqaWSWnoBTYn21XEL7y4YQXnB8N4JWAy33inTD1CyEI20
TusbH6MSxyc=
这就是我在DNS服务器(PowerDNS)中的内容:
Private-key-format: v1.2
Algorithm: 13 (ECDSAP256SHA256)
PrivateKey: WJxR0rUoqZwdGXAvhlKE7Anj4IBgbdw/VvCQYmj9JeM=
获取DNSKEY记录:
$ dig @127.0.0.1 +short example.com DNSKEY
257 3 13 JELaKnxPV49rnxShsHbS8MX9rfJZcpRKgqCHUn1WYyDLcXGDYYEQ8soL I9OLVJFN5Gn/4TjXF6g0T1IEBsuFew==
它绝对不符合我用OpenSSL获得的密钥。为什么呢?
答案 0 :(得分:1)
我没有考虑的主要问题是这个密钥有不同的长度:从openssl返回的密钥以二进制格式长65字节,而DNS服务器的密钥长64字节。如果我在十六进制编辑器中查看两个键的二进制重新表示,我可以看到它们仅与第一个字节不同。可以在此处找到更详细的解释:https://stackoverflow.com/a/43742420/3090865
所以,这个C代码可能会像这样重写(还有一个是使用了错误的曲线,应该是NID_X9_62_prime256v1):
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>
#include <openssl/bn.h>
int main()
{
EC_KEY *eckey = NULL;
EC_POINT *pub_key = NULL;
const EC_GROUP *group = NULL;
BIGNUM start;
BIGNUM *res;
BN_CTX *ctx;
BN_init(&start);
ctx = BN_CTX_new(); // ctx is an optional buffer to save time from allocating and deallocating memory whenever required
res = &start;
BN_hex2bn(&res,"589c51d2b528a99c1d19702f865284ec09e3e080606ddc3f56f0906268fd25e3");
eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
group = EC_KEY_get0_group(eckey);
pub_key = EC_POINT_new(group);
EC_KEY_set_private_key(eckey, res);
/* pub_key is a new uninitialized `EC_POINT*`. priv_key res is a `BIGNUM*`. */
if (!EC_POINT_mul(group, pub_key, res, NULL, NULL, ctx))
printf("Error at EC_POINT_mul.\n");
EC_KEY_set_public_key(eckey, pub_key);
char *cc = EC_POINT_point2hex(group, pub_key, 4, ctx);
printf("%s", cc+2);
BN_CTX_free(ctx);
free(cc);
return 0;
}
现在匹配:
$ ./a.out | perl -e 'print pack "H*", <>' | base64
JELaKnxPV49rnxShsHbS8MX9rfJZcpRKgqCHUn1WYyDLcXGDYYEQ8soLI9OLVJFN5Gn/4TjXF6g0
T1IEBsuFew==