OpenSSL:尝试解码 DER 数据

问题描述 投票:0回答:1

我有以下Python代码,它创建了一段DER数据“x25519_pubic_der”。

#!/usr/bin/python3

from cryptography.hazmat.primitives.asymmetric import x25519
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat

x25519_key = x25519.X25519PrivateKey.generate()
x25519_public_der = x25519_key.public_key().public_bytes(Encoding.DER,
                                                         PublicFormat.SubjectPublicKeyInfo)

我尝试使用 C 代码将这段数据解码回其原始二进制位,但不起作用。下面是一个测试程序(假设der数据传输正确,长度也正确)。

const unsigned char* ptr = x25519_public_der;
ASN1_OCTET_STRING* octet_string = d2i_ASN1_OCTET_STRING(NULL, &ptr, x25519_public_der_len);
if (!octet_string) {
   fprintf(stderr, "Error decoding DER data to binary bytes\n");
   return 1;
}

我怀疑 PublicFormat.SubjectPublicKeyInfo 可能会添加一些额外的编码,或者我没有使用正确的 d2i_ 函数(?),只是猜测......

基本上x25519_public_der包含44字节,我想使用C编程将其恢复到32字节。我认为这个问题可能是相关的,我如何将openssl创建的44字节x25519公钥传递给CryptoKit,它需要32字节的密钥长度,但我没有足够的背景来在C中实现它。

openssl der x25519
1个回答
0
投票

由于原始公钥位于 SPKI/DER Ed25519 密钥的末尾,因此可以简单地使用最后 32 个字节。

另一种方法是将 SPKI/DER 密钥导入为

EVP_PKEY
并使用
EVP_PKEY_get_raw_public_key
提取原始密钥,例如从 OpenSSL v3.0 开始:

const char spki_der[] = { 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0xf3, 0x7d, 0x76, 0xed, 0xe5, 0xd9, 0x01, 0xd1, 0xb5, 0x0c, 0x76, 0x8b, 0x68, 0x34, 0x12, 0x67, 0xa9, 0x88, 0xb6, 0xd9, 0x87, 0xde, 0x88, 0x3e, 0x47, 0xb7, 0xba, 0x17, 0x7d, 0x21, 0x3d, 0xe5 };
const unsigned char* data = (const unsigned char*)spki_der;
size_t datalen = sizeof(spki_der);

// Import SPKI/DER Ed25519 key
OSSL_DECODER_CTX* dctx;
EVP_PKEY* pkeyPub = NULL;
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkeyPub, "DER", NULL, "ED25519", OSSL_KEYMGMT_SELECT_PUBLIC_KEY, NULL, NULL);
OSSL_DECODER_from_data(dctx, &data, &datalen);

// Export raw 32 bytes key
unsigned char rawPub[32];
size_t rawPubLen = 32;
EVP_PKEY_get_raw_public_key(pkeyPub, rawPub, &rawPubLen); // pkey: 0xf37d76ede5d901d1b50c768b68341267a988b6d987de883e47b7ba177d213de5

为了完整起见:

OSSL_DECODER_CTX_new_for_pkey()
可用于导入不同类型的公共(第5个参数:
OSSL_KEYMGMT_SELECT_PUBLIC_KEY
)和私有(第5个参数:
OSSL_KEYMGMT_SELECT_KEYPAIR
)密钥(第4个参数,例如
"ED25519"
)和编码(第2个参数,例如
"PEM"
)或
"DER"
)。
对于私钥,必须使用
EVP_PKEY_get_raw_private_key()
导出原始密钥。

© www.soinside.com 2019 - 2024. All rights reserved.