gpt4 book ai didi

Java 11 Curve25519 实现不作为信号库

转载 作者:行者123 更新时间:2023-12-04 12:09:34 27 4
gpt4 key购买 nike

在 Java 11 中引入了 curve25519 内置实现。由于我不知道这一点,直到最近才发现它,我正在使用 a library from Signal .这是我在切换到 Java 11 的实现之前的代码:

private final Curve25519 CURVE_25519 = Curve25519.getInstance(Curve25519.JAVA);

public Curve25519KeyPair calculateRandomKeyPair() {
return CURVE_25519.generateKeyPair();
}

public byte[] calculateSharedSecret(byte[] publicKey, byte[] privateKey) {
return CURVE_25519.calculateAgreement(publicKey, privateKey);
}
这是我现在的代码:
private final String XDH = "XDH";
private final String CURVE = "X25519";

@SneakyThrows
public KeyPair calculateRandomKeyPair() {
return KeyPairGenerator.getInstance(CURVE).generateKeyPair();
}

@SneakyThrows
public byte[] calculateSharedSecret(byte[] publicKeyBytes, XECPrivateKey privateKey) {
var paramSpec = new NamedParameterSpec(CURVE);
var keyFactory = KeyFactory.getInstance(XDH);

var publicKeySpec = new XECPublicKeySpec(paramSpec, new BigInteger(publicKeyBytes));
var publicKey = keyFactory.generatePublic(publicKeySpec);

var keyAgreement = KeyAgreement.getInstance(XDH);
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);
return keyAgreement.generateSecret();
}
显然,第二个实现不起作用,而第一个实现。最初,我以为我做错了什么,所以我阅读了文档并检查了类似的答案,但是,由于我没有找到任何有用的信息,我决定进一步挖掘并尝试检查 Signal 的库和 Java 是否生成相同的公钥鉴于私有(private)的。为此,我写了这个片段:
import org.whispersystems.curve25519.Curve25519;
import sun.security.ec.XECOperations;
import sun.security.ec.XECParameters;

import java.security.InvalidAlgorithmParameterException;
import java.security.spec.NamedParameterSpec;
import java.util.Arrays;

private static boolean generateJava11KeyPair() throws InvalidAlgorithmParameterException {
var signalKeyPair = Curve25519.getInstance(Curve25519.JAVA).generateKeyPair();

var signalPublicKey = signalKeyPair.getPublicKey();
var params = XECParameters.get(InvalidAlgorithmParameterException::new, NamedParameterSpec.X25519);
var ops = new XECOperations(params);
var javaPublicKey = ops.computePublic(signalKeyPair.getPrivateKey().clone()).toByteArray();

return Arrays.equals(signalPublicKey, javaPublicKey);
}
(Java实现后计算公钥的代码摘自sun.security.ec.XDHKeyPairGenerator)
此方法打印 false,这意味着这两个实现实际上的行为方式不同。在这一点上,我想知道这是一个 Java 错误还是我遗漏了什么。提前致谢。

最佳答案

Bernstein 等人为 X25519(和 X448)公钥和私钥定义的编码是无符号固定长度小端,而由 BigInteger.toByteArray() 返回的表示形式并被ctor接受BigInteger(byte[])是二进制补码可变长度大端。由于 255 位四舍五入为 32 字节,其中备用位始终为零(对于 XDH),因此可以忽略符号差异,但其他因素很重要。
JCA 确实制作了接口(interface)类 XECPrivateKey返回,对应的Spec接受,这些表格,但对于 XECPublicKey[Spec]它使用 BigInteger .对于 Key.getEncoded() 返回的(分别)“X509”和“PKCS8”编码(分别),它确实使用了 Bernstein 形式。并被 KeyFactory 接受,但那些具有仅 XDH(或仅 Bernstein XDH-and-EdDSA)系统(如 X3DH)不使用的元数据。
AFAICS 您的选择是

  • 需要时字节反转和(零)填充代码中的 JCA 公共(public)值,或
  • 使用 Key.getEncoded()并解析特定于算法的部分或相反地构建算法通用结构以作为 X509EncodedKeySpec 传递至 KeyFactory.getInstance("Xblah") .

  • 第二种方法过去曾被问及其他算法:“传统”(X9 风格)EC——尤其是比特币和相关硬币的 secp256k1,它通常只使用原始 X9/SECG 数据而没有元数据——和RSA,其中一些系统使用原始 PKCS1 格式(这里私钥比公钥更常见);如果您愿意,我可以找到一些几乎重复的内容来说明该方法。

    关于Java 11 Curve25519 实现不作为信号库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67332030/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com