import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.NamedParameterSpec;
import java.security.spec.XECPrivateKeySpec;
import java.security.spec.XECPublicKeySpec;
import java.util.HexFormat;

import javax.crypto.KeyAgreement;

public class Main {

// https://openjdk.org/jeps/324
public static void main(String[] args) throws Exception {

byte[] publicKey = HexFormat.of().parseHex("e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493");
//byte[] publicKey = HexFormat.of().parseHex("e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a413");
byte[] privateKey = HexFormat.of().parseHex("4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d");
NamedParameterSpec paramSpec = new NamedParameterSpec("X25519");

KeyFactory kf = KeyFactory.getInstance("XDH");
reverse(publicKey);
BigInteger u = new BigInteger(1, publicKey);
XECPublicKeySpec pubSpec = new XECPublicKeySpec(paramSpec, u);
PublicKey pubKey = kf.generatePublic(pubSpec);

XECPrivateKeySpec privSpec = new XECPrivateKeySpec(paramSpec, privateKey);
PrivateKey privKey = kf.generatePrivate(privSpec);

KeyAgreement ka = KeyAgreement.getInstance("XDH");
ka.init(privKey);
ka.doPhase(pubKey, true);
byte[] secret = ka.generateSecret();

System.out.println( HexFormat.of().formatHex(secret));
}

private static void reverse(byte[] array) {
for(int i = 0; i < array.length / 2; i++)
{
byte temp = array[i];
array[i] = array[array.length - i - 1];
array[array.length - i - 1] = temp;
}
}
} 