org.whispersystems.curve25519.Curve25519 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of curve25519-java Show documentation
Show all versions of curve25519-java Show documentation
Curve25519 library for Java
/**
* Copyright (C) 2014-2016 Open Whisper Systems
*
* Licensed according to the LICENSE file in this repository.
*/
package org.whispersystems.curve25519;
/**
* A Curve25519 interface for generating keys, calculating agreements, creating signatures,
* and verifying signatures.
*
* @author Moxie Marlinspike
*/
public class Curve25519 {
public static final String NATIVE = "native";
public static final String JAVA = "java";
public static final String J2ME = "j2me";
public static final String BEST = "best";
public static Curve25519 getInstance(String type) throws NoSuchProviderException {
return getInstance(type, null);
}
public static Curve25519 getInstance(String type, SecureRandomProvider random)
throws NoSuchProviderException
{
if (NATIVE.equals(type)) return new Curve25519(constructNativeProvider(random));
else if (JAVA.equals(type)) return new Curve25519(constructJavaProvider(random));
else if (J2ME.equals(type)) return new Curve25519(constructJ2meProvider(random));
else if (BEST.equals(type)) return new Curve25519(constructOpportunisticProvider(random));
else throw new NoSuchProviderException(type);
}
private final Curve25519Provider provider;
private Curve25519(Curve25519Provider provider) {
this.provider = provider;
}
/**
* {@link Curve25519} is backed by either a native (via JNI)
* or pure-Java provider. By default it prefers the native provider, and falls back to the
* pure-Java provider if the native library fails to load.
*
* @return true if backed by a native provider, false otherwise.
*/
public boolean isNative() {
return provider.isNative();
}
/**
* Generates a Curve25519 keypair.
*
* @return A randomly generated Curve25519 keypair.
*/
public Curve25519KeyPair generateKeyPair() {
byte[] privateKey = provider.generatePrivateKey();
byte[] publicKey = provider.generatePublicKey(privateKey);
return new Curve25519KeyPair(publicKey, privateKey);
}
/**
* Calculates an ECDH agreement.
*
* @param publicKey The Curve25519 (typically remote party's) public key.
* @param privateKey The Curve25519 (typically yours) private key.
* @return A 32-byte shared secret.
*/
public byte[] calculateAgreement(byte[] publicKey, byte[] privateKey) {
if (publicKey == null || privateKey == null) {
throw new IllegalArgumentException("Keys must not be null!");
}
if (publicKey.length != 32 || privateKey.length != 32) {
throw new IllegalArgumentException("Keys must be 32 bytes!");
}
return provider.calculateAgreement(privateKey, publicKey);
}
/**
* Calculates a Curve25519 signature.
*
* @param privateKey The private Curve25519 key to create the signature with.
* @param message The message to sign.
* @return A 64-byte signature.
*/
public byte[] calculateSignature(byte[] privateKey, byte[] message) {
if (privateKey == null || privateKey.length != 32) {
throw new IllegalArgumentException("Invalid private key length!");
}
byte[] random = provider.getRandom(64);
return provider.calculateSignature(random, privateKey, message);
}
/**
* Verify a Curve25519 signature.
*
* @param publicKey The Curve25519 public key the signature belongs to.
* @param message The message that was signed.
* @param signature The signature to verify.
* @return true if valid, false if not.
*/
public boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature) {
if (publicKey == null || publicKey.length != 32) {
throw new IllegalArgumentException("Invalid public key!");
}
if (message == null || signature == null || signature.length != 64) {
return false;
}
return provider.verifySignature(publicKey, message, signature);
}
/**
* Calculates a Unique Curve25519 signature.
*
* @param privateKey The private Curve25519 key to create the signature with.
* @param message The message to sign.
* @return A 96-byte signature.
*/
public byte[] calculateVrfSignature(byte[] privateKey, byte[] message) {
if (privateKey == null || privateKey.length != 32) {
throw new IllegalArgumentException("Invalid private key!");
}
byte[] random = provider.getRandom(64);
return provider.calculateVrfSignature(random, privateKey, message);
}
/**
* Verify a Unique Curve25519 signature.
*
* @param publicKey The Curve25519 public key the unique signature belongs to.
* @param message The message that was signed.
* @param signature The unique signature to verify.
*
* @return The vrf for this signature.
*/
public byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature)
throws VrfSignatureVerificationFailedException
{
if (publicKey == null || publicKey.length != 32) {
throw new IllegalArgumentException("Invalid public key!");
}
if (message == null || signature == null || signature.length != 96) {
throw new VrfSignatureVerificationFailedException("Invalid message or signature format");
}
return provider.verifyVrfSignature(publicKey, message, signature);
}
private static Curve25519Provider constructNativeProvider(SecureRandomProvider random) throws NoSuchProviderException {
return constructClass("NativeCurve25519Provider", random);
}
private static Curve25519Provider constructJavaProvider(SecureRandomProvider random) throws NoSuchProviderException {
return constructClass("JavaCurve25519Provider", random);
}
private static Curve25519Provider constructJ2meProvider(SecureRandomProvider random) throws NoSuchProviderException {
return constructClass("J2meCurve25519Provider", random);
}
private static Curve25519Provider constructOpportunisticProvider(SecureRandomProvider random) throws NoSuchProviderException {
return constructClass("OpportunisticCurve25519Provider", random);
}
private static Curve25519Provider constructClass(String name, SecureRandomProvider random) throws NoSuchProviderException {
try {
Curve25519Provider provider = (Curve25519Provider)Class.forName("org.whispersystems.curve25519." + name).newInstance();
if (random != null) {
provider.setRandomProvider(random);
}
return provider;
} catch (InstantiationException e) {
throw new NoSuchProviderException(e);
} catch (IllegalAccessException e) {
throw new NoSuchProviderException(e);
} catch (ClassNotFoundException e) {
throw new NoSuchProviderException(e);
}
}
}