如何为diffie hellman算法生成curve25519密钥对?

asa*_*gar 5 java encryption cryptography

我想在我的项目中实现 ECDHE 算法,为此我想使用 Curve25519。但卡住了如何为 Curve25519 生成密钥对。使用其他曲线我能够生成密钥对,但是对于curve25519 获取算法未找到

我尝试使用以下代码:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
        kpg.initialize(256);
        KeyPair private_Key1 = kpg.generateKeyPair();
       PublicKey ourPk1 = private_Key1.getPublic();
Run Code Online (Sandbox Code Playgroud)

Maa*_*wes 8

Curve25519似乎从 Java 11 开始受支持(请注意,标准 Java 现在遵循 OpenJDK Java)。

链接到 JEP(Java 增强提案)还包含示例代码,逐字包含在此处:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("XDH");
NamedParameterSpec paramSpec = new NamedParameterSpec("X25519");
kpg.initialize(paramSpec); // equivalent to kpg.initialize(255)
// alternatively: kpg = KeyPairGenerator.getInstance("X25519")
KeyPair kp = kpg.generateKeyPair();

KeyFactory kf = KeyFactory.getInstance("XDH");
BigInteger u = ...
XECPublicKeySpec pubSpec = new XECPublicKeySpec(paramSpec, u);
PublicKey pubKey = kf.generatePublic(pubSpec);

KeyAgreement ka = KeyAgreement.getInstance("XDH");
ka.init(kp.getPrivate());
ka.doPhase(pubKey, true);
byte[] secret = ka.generateSecret();
Run Code Online (Sandbox Code Playgroud)

注意,密钥工厂生成的公钥是对方的公钥。通常您会从字节中解码该值。


mic*_*alk 5

您可以使用BouncyCastle支持此曲线的加密提供程序:

import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;

import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;

public class Test {
    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        X9ECParameters curveParams = CustomNamedCurves.getByName("Curve25519");
        ECParameterSpec ecSpec = new ECParameterSpec(curveParams.getCurve(), curveParams.getG(), curveParams.getN(), curveParams.getH(), curveParams.getSeed());

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
        kpg.initialize(ecSpec);

        KeyPair keyPair = kpg.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

    }
}
Run Code Online (Sandbox Code Playgroud)

提取原始公钥

要提取原始x和(y公钥ECPoint),您可以使用以下代码:

byte[] encoded = publicKey.getEncoded();
ASN1Sequence asn1Primitive = ASN1Sequence.getInstance(encoded);
ASN1Encodable algorithmIdentifier = asn1Primitive.getObjectAt(0);
DERBitString ecPointBitString = (DERBitString) asn1Primitive.getObjectAt(1);

//use curve parameters from previous code snippet
ECPoint ecPoint = curveParams.getCurve().decodePoint(ecPointBitString.getOctets());
byte[] x = ecPoint.getAffineXCoord().getEncoded();
byte[] y = ecPoint.getAffineYCoord().getEncoded();
Run Code Online (Sandbox Code Playgroud)

这基本上是解析RFC5480SubjectPublicKeyInfo中描述的编码

提取原始私钥

BCECPrivateKey privateKey1 = (BCECPrivateKey) privateKey;
byte[] bigIntPk = privateKey1.getS().toByteArray();
Run Code Online (Sandbox Code Playgroud)

或者通过解析 DER 对象:

ASN1Sequence instance = ASN1Sequence.getInstance(privateKey.getEncoded());
DEROctetString pkOctetString = (DEROctetString) instance.getObjectAt(2);

ASN1Sequence ecPkSequence = DERSequence.getInstance(pkOctetString.getOctets());
DEROctetString pkOctets = (DEROctetString) ecPkSequence.getObjectAt(1);

byte[] bigIntPk = new BigInteger(1, pkOctets.getOctets()).toByteArray();
Run Code Online (Sandbox Code Playgroud)

  • @eigenfield是的,实际上使用“publicKey.getEncoded()”,您将获得编码的整个SubjectPublicKeyInfo结构,而使用“privateKey.getEncoded()”,您将获得以DER编码的整个“PrivateKeyInfo”结构。例如,要获取原始 32 字节曲线参数,您必须使用 DER 解析器对其进行解析。 (3认同)