Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate curve25519 key pair for diffie hellman algorithm?

I want to implement ECDHE algorithm in my project ,for that I want to use Curve25519.But stuck how to generate key-pair for Curve25519.With other curve I am able to generate key-pair,but for curve25519 getting algorithm not found

I tried with below code:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
        kpg.initialize(256);
        KeyPair private_Key1 = kpg.generateKeyPair();
       PublicKey ourPk1 = private_Key1.getPublic();
like image 256
asawari kengar Avatar asked Sep 09 '19 10:09

asawari kengar


People also ask

How is Diffie Hellman key generated?

In the Diffie–Hellman key exchange scheme, each party generates a public/private key pair and distributes the public key. After obtaining an authentic copy of each other's public keys, Alice and Bob can compute a shared secret offline. The shared secret can be used, for instance, as the key for a symmetric cipher.

What is X25519 key exchange?

X25519 is an elliptic curve Diffie-Hellman key exchange using Curve25519. It allows two parties to jointly agree on a shared secret using an insecure channel.


2 Answers

Curve25519 seems supported from Java 11 onwards (note that the standard Java follows the OpenJDK Java nowadays).

The linked to JEP (Java Enhancement Proposal) also contains sample code, included here verbatim:

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();

Note that the public key generated by the key factory is the one from the other party. Usually you would decode that value from bytes though.

like image 81
Maarten Bodewes Avatar answered Oct 26 '22 16:10

Maarten Bodewes


You could use BouncyCastle as cryptographic provider which has support for this curve :

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();

    }
}

Extracting raw public key

To extract raw x and y of ECPoint (public key) you can use this code:

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();

This is basically parsing the encoded SubjectPublicKeyInfo described in RFC5480

Extracting raw private key

BCECPrivateKey privateKey1 = (BCECPrivateKey) privateKey;
byte[] bigIntPk = privateKey1.getS().toByteArray();

or by parsing DER objects :

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();
like image 35
Michał Krzywański Avatar answered Oct 26 '22 15:10

Michał Krzywański