首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法读取MbedTLS中的BouncyCastle公钥

无法读取MbedTLS中的BouncyCastle公钥
EN

Stack Overflow用户
提问于 2020-06-17 11:31:31
回答 1查看 267关注 0票数 1

我试图在运行mbedTLS的嵌入式设备和使用BouncyCastle的Java之间做一个ECDH。当我比较产生的密钥长度时,我得到了一个由mbedTLS制作的66字节密钥和由BC生成的65个字节。附加伪码:

代码语言:javascript
复制
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg.initialize(256);
KeyPair localKp = kpg.generateKey();

ASN1Sequence sequence = DERSequence.getInstance(localKp.getPublic().getEncoded());
DERBitString subjectPublicKey = (DERBitString) sequence.getObjectAt(1);
byte[] encodedLocalPublicKey = subjectPublicKey.getBytes();
// encodedLocalPublicKey.length -> 65

MbedTLS:

代码语言:javascript
复制
mbedtls_ecdh_context ecdh;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
const char pers[] = "ecdh";

mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
mbedtls_ecdh_init(&ecdh);

int ret = 0;
if((ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                               (const unsigned char *) pers,
                               sizeof pers )) != 0) {
    mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
}

ret = mbedtls_ecp_group_load(&ecdh.grp, MBEDTLS_ECP_DP_SECP256R1);
if (ret != 0) {
    mbedtls_printf( " failed\n  ! mbedtls_ecp_group_load returned %d\n", ret );
}

size_t olen;
unsigned char buf[1024];
ret = mbedtls_ecdh_make_public(&ecdh, &olen, buf, sizeof(buf), mbedtls_ctr_drbg_random, &ctr_drbg);
// ret is 0, olen is 66

当我将MbedTLS键加载到Java中时,它会抛出java.lang.IllegalArgumentException:无效点编码0x41:

代码语言:javascript
复制
byte[] publicKeyBytes = ... FROM MbedTLS
log.info("Public key length: {}", publicKeyBytes.length); // Shows 66
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("P-256");
ECPoint point = ecSpec.getCurve().decodePoint(publicKeyBytes); // This line throws

我尝试在Java之间和MbedTLS之间在MbedTLS之间执行ECDH。这两个测试都成功了,但它们不知何故不能交换跨平台。

我做错了什么?对不起,也许是明显的问题,但我正在设法处理它。我会感谢你的帮助。

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-18 08:01:40

来自API文档 for mbedtls_ecdh_make_public

此函数生成公钥并将其导出为TLS ClientKeyExchange有效负载。

这是TLS特有的函数。在例如RFC 8442中,我们看到椭圆曲线点的编码是:

代码语言:javascript
复制
struct {
    opaque point <1..2^8-1>;
} ECPoint;

这需要对TLS表示语言有一定的熟悉,但最终它相当于: TLS在通常的点编码开始时添加了一个额外的(无符号)字节,这将包含剩余部分的长度。

在您的示例中,可以看到mbedtls输出了66个字节。第一个字节包含值65,这是输出其余部分的长度,最后的65个字节与BC使用的格式相同。您需要提取最后65个字节,或者以某种方式忽略第一个字节。

在Java中生成KeyPair的方式非常脆弱,因为您只指定了大小,而没有指定确切的曲线。BC对于256位来说是默认的P-256,但它不是必需的行为,其他提供者(或将来的BC版本)可能会选择其他一些曲线。最好是显式地生成P-256 KeyPair。我还建议使用更清晰的代码来获取Java版本中的公钥编码:

代码语言:javascript
复制
byte[] spkiEnc = localKp.getPublic().getEncoded();
SubjectPublicKeyInfo spki = SubjectPublicKeyInfo.getInstance(spkiEnc);
byte[] encodedLocalPublicKey = spki.getPublicKeyData().getOctets();
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62427960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档