OpenSSL DER ECDSA 编码错误

Posted

技术标签:

【中文标题】OpenSSL DER ECDSA 编码错误【英文标题】:OpenSSL DER ECDSA encoding error 【发布时间】:2018-05-15 10:04:48 【问题描述】:

我正在尝试将 ECDSA Curve448 密钥编码为一个小型且可移植的字节数组。我正在尝试使用 DER 来完成此操作,因为低级 API 不适用于 Curve448。但是,当我使用以下代码时:

std::vector<std::vector<uint8_t>> vecs;
uint8_t* buf = nullptr;

EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED448, NULL);
EVP_PKEY_keygen_init(pctx);
EVP_PKEY* pkey;
EVP_PKEY_keygen(pctx, &pkey);
EVP_PKEY_CTX_free(pctx);

size_t n = i2d_PublicKey(pkey, &buf);

ERR_print_errors_fp(stderr);

vecs.emplace_back(buf, buf + n);

n 设置为 -1,因此 vecs.emplace_back 失败。 ERR_print_errors_fp 打印:

140691149055104:error:0D0A40A7:asn1 encoding routines:i2d_PublicKey:unsupported public key type:../crypto/asn1/i2d_pu.c:35

我该如何解决这个问题,或者我应该有更好的方法吗?

我正在使用来自 debian Experiment 的 openssl v1.1.1。

【问题讨论】:

请注意,i2d_PrivateKey() 返回一个 int (有符号)而不是 size_t (无符号),就像您在代码中那样。当您说“n 设置为 -1”时,因为您将它存储在 size_t 中,它实际上可能设置为一个非常大的正数 - 如果您测试“n 【参考方案1】:

您是要写出私钥还是公钥?我问是因为您上面的代码有size_t n = i2d_PrivateKey(pkey, &amp;buf);,即尝试对私钥进行编码,但错误消息显示i2d_PublicKey:unsupported public key type

无论如何i2d_PublicKey 用于以旧式“传统”格式写出公钥。由于 ED448 是一种新算法,因此没有为它定义这样的格式。相反,您必须使用 SubjectPublicKeyInfo 格式。为此的 OpenSSL 函数是(令人困惑的相似)i2d_PUBKEY()。手册页在这里:

https://www.openssl.org/docs/man1.1.1/man3/i2d_PUBKEY.html

【讨论】:

对不起,我在我的程序中同时编码了一个私钥和一个公钥,上面是一个稍微简化的例子,我一定是不小心复制了错误的行。我已经更新了问题。

以上是关于OpenSSL DER ECDSA 编码错误的主要内容,如果未能解决你的问题,请参考以下文章

将 AWS KMS ECDSA_SHA_256 签名从 DER 编码的 ANS.1 格式转换为 JWT base64url 编码的 R || NodeJS/Javascript 中的 S 格式

由cryptopp创建的DER编码公钥与openssl不同

DER编码

带有来自 OpenSSL 的 ECDSA 证书的 Golang HTTPS

无法从 Java 读取 OpenSSL 生成的 ECDSA 密钥:InvalidKeySpecException

如何从 OpenSSL 中的 ECDSA 私钥获取公钥?