我在java中生成一个curve25519 ECDH键区,如下所示
public static final String ALGORITHM = "ECDH";
public static final String CURVE = "curve25519";
public static byte[] getEncodedPublicKey(PublicKey key) throws Exception {
ECPublicKey ecKey = (ECPublicKey) key;
return ecKey.getQ().getEncoded(true);
}
Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM, PROVIDER);
X9ECParameters ecParameters = CustomNamedCurves.getByName(CURVE);
ECParameterSpec ecSpec = new ECParameterSpec(ecParameters.getCurve(), ecParameters.getG(), ecParameters.getN(), ecParameters.getH(), ecParameters.getSeed());
KeyPair recieverKeypair = keyPairGenerator.initialize(ecSpec, new SecureRandom());
system.out.println(new String(org.bouncycastle.util.encoders.Base64.encode((getEncodedPublicKey(receiverKeyPair.getPublic()))))
我正在使用上面在我的nodejs项目中打印的公钥,如下所示
crypto.createPublicKey({
key: receiverPublicKey, //string
format:'der',
type: 'spki',
})
这会引发此错误:
Error: error:0D07209B:asn1 encoding routines:ASN1_get_object:too long
at Object.createPublicKey (node:internal/crypto/keys:595:12)
at generateSharedKey (/home/wsl/projects/node-ndhm-crypto/src/EncryptData.ts:133:23)
at Object.exports.encrypt (/home/wsl/projects/node-ndhm-crypto/src/EncryptData.ts:61:21)
任何帮助都将不胜感激。谢谢。
发布于 2022-01-13 11:52:27
导入失败是因为这两种代码都使用不同的密钥格式:目前,Java代码中的公钥是使用ecKey.getQ().getEncoded(true)
以压缩格式导出的,而NodeJS代码需要X.509/SPKI格式(DER编码)的公钥。
如果在Java代码中使用ecKey.getEncoded()
,则公开密钥以X.509/SPKI格式导出(DER编码),并与NodeJS端兼容。
请注意,在NodeJS代码中,必须反转Java端可能的Base64编码:
var receiverPublicKey = Buffer.from('<Base64 encoded X.509/SPKI key>', 'base64');
更改Java代码可能是不可避免的,因为根据文档,crypto.createPublicKey()
不支持导入压缩、未压缩或原始密钥。处理未压缩键的ECDH类也不是选项,因为不支持曲线25519。
发布于 2022-01-15 06:25:15
首先,首先要明确的是,在Weierstrass表单中使用curve25519是不标准的(至少目前还不是;如果采用NIST 800-186草案将允许它的名称为W-25519,尽管不清楚有谁想要或将它用于任何事情),而且肯定没有得到伯恩斯坦的批准;具体来说,这与许多协议和系统采用的标准X25519或XDH25519算法不兼容,这些协议和系统使用蒙哥马利-表单方程和计算以及X-仅表示点。这可能就是为什么弹力把它放在“习惯”之下的原因。
OpenSSL是nodejs密码的基础,它遵循标准(嗯,这次),不支持X9/Weierstrass形式的这条曲线,但它支持任意的“显式”Weierstrass曲线,而且(幸运的是?)通过使用X9ECParamters
和ECParameterSpec
类,您的Java代码使用了(现在通常不喜欢)的显式格式。X9型ECDH (和ECDSA)的SPKI格式的编码取决于曲线参数的值及其长度(曲线固定)和点表示(其值变化,但曲线有两个固定长度之一)因此,曲线和点表示的SPKI格式由一个固定前缀和一个点表示组成,对于显式curve25519(W)压缩了该前缀。
"\x30\x82\x01\x11\x30\x81\xea\x06\x07\x2a\x86\x48\xce\x3d\x02\x01"+
"\x30\x81\xde\x02\x01\x01\x30\x2b\x06\x07\x2a\x86\x48\xce\x3d\x01"+
"\x01\x02\x20\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"+
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"+
"\xff\xff\xed\x30\x44\x04\x20\x2a\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"+
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"+
"\xaa\xaa\x98\x49\x14\xa1\x44\x04\x20\x7b\x42\x5e\xd0\x97\xb4\x25"+
"\xed\x09\x7b\x42\x5e\xd0\x97\xb4\x25\xed\x09\x7b\x42\x5e\xd0\x97"+
"\xb4\x26\x0b\x5e\x9c\x77\x10\xc8\x64\x04\x41\x04\x2a\xaa\xaa\xaa"+
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"+
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xad\x24\x5a\x20\xae\x19\xa1"+
"\xb8\xa0\x86\xb4\xe0\x1e\xdd\x2c\x77\x48\xd1\x4c\x92\x3d\x4d\x7e"+
"\x6d\x7c\x61\xb2\x29\xe9\xc5\xa2\x7e\xce\xd3\xd9\x02\x20\x10\x00"+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\xde"+
"\xf9\xde\xa2\xf7\x9c\xd6\x58\x12\x63\x1a\x5c\xf5\xd3\xed\x02\x01"+
"\x08\x03\x22\x00"
您可以简单地连接到您拥有的内容(正如Topaco所指出的,在un-base64-ing之后;作为检查,它必须与第一个字节0x02或0x03正好是33个字节)。
https://stackoverflow.com/questions/70693834
复制相似问题