com.rotilho.jnano.commons.ED25519 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jnano-commons Show documentation
Show all versions of jnano-commons Show documentation
JNano provides a set of low level Nano operations that includes signing, seed generation, block hashing and account creation.
package com.rotilho.jnano.commons;
import com.rfksystems.blake2b.Blake2b;
import com.rfksystems.blake2b.security.Blake2bProvider;
import net.i2p.crypto.eddsa.EdDSAEngine;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.Utils;
import net.i2p.crypto.eddsa.math.Curve;
import net.i2p.crypto.eddsa.math.Field;
import net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding;
import net.i2p.crypto.eddsa.math.ed25519.Ed25519ScalarOps;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.Security;
import java.util.Arrays;
import static com.rotilho.jnano.commons.Preconditions.checkHash;
import static com.rotilho.jnano.commons.Preconditions.checkKey;
import static com.rotilho.jnano.commons.Preconditions.checkSignature;
final class ED25519 {
private static EdDSANamedCurveSpec ED25519_BLAKE2B_CURVES_PEC;
static {
Security.addProvider(new Blake2bProvider());
Field ED25519_FIELD = new Field(
256, // b
Utils.hexToBytes("edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f"), // q
new Ed25519LittleEndianEncoding());
Curve ED25519_CURVE = new Curve(ED25519_FIELD,
Utils.hexToBytes("a3785913ca4deb75abd841414d0a700098e879777940c78c73fe6f2bee6c0352"), // d
ED25519_FIELD.fromByteArray(Utils.hexToBytes("b0a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b"))); // I
ED25519_BLAKE2B_CURVES_PEC = new EdDSANamedCurveSpec(
EdDSANamedCurveTable.ED_25519,
ED25519_CURVE,
Blake2b.BLAKE2_B_512, // H
new Ed25519ScalarOps(), // l
ED25519_CURVE.createPoint( // B
Utils.hexToBytes("5866666666666666666666666666666666666666666666666666666666666666"),
true)); // Precompute tables for B
EdDSANamedCurveTable.defineCurve(ED25519_BLAKE2B_CURVES_PEC);
}
private ED25519() {
}
static byte[] createPublicKey(byte[] privateKey) {
checkKey(privateKey);
EdDSAPrivateKeySpec key = new EdDSAPrivateKeySpec(privateKey, ED25519_BLAKE2B_CURVES_PEC);
return key.getA().toByteArray();
}
static byte[] sign(byte[] hash, byte[] privateKey) {
checkHash(hash);
checkKey(privateKey);
try {
EdDSAEngine edDSAEngine = new EdDSAEngine(MessageDigest.getInstance(Blake2b.BLAKE2_B_512));
EdDSAPrivateKeySpec edDSAPrivateKeySpec = new EdDSAPrivateKeySpec(privateKey, ED25519_BLAKE2B_CURVES_PEC);
EdDSAPrivateKey edDSAPrivateKey = new EdDSAPrivateKey(edDSAPrivateKeySpec);
edDSAEngine.initSign(edDSAPrivateKey);
edDSAEngine.setParameter(EdDSAEngine.ONE_SHOT_MODE);
edDSAEngine.update(hash);
return edDSAEngine.sign();
} catch (GeneralSecurityException e) {
throw new IllegalStateException("It wasn't possible to sign " + Arrays.toString(hash), e);
}
}
static boolean verify(byte[] signature, byte[] hash, byte[] publicKey) {
checkSignature(signature);
checkHash(hash);
checkKey(publicKey);
try {
EdDSAEngine edDSAEngine = new EdDSAEngine(MessageDigest.getInstance(Blake2b.BLAKE2_B_512));
EdDSAPublicKeySpec edDSAPublicKeySpec = new EdDSAPublicKeySpec(publicKey, ED25519_BLAKE2B_CURVES_PEC);
EdDSAPublicKey edDSAPublicKey = new EdDSAPublicKey(edDSAPublicKeySpec);
edDSAEngine.initVerify(edDSAPublicKey);
edDSAEngine.setParameter(EdDSAEngine.ONE_SHOT_MODE);
edDSAEngine.update(hash);
return edDSAEngine.verify(signature);
} catch (GeneralSecurityException e) {
throw new IllegalStateException("It wasn't possible to verify " + Arrays.toString(hash), e);
}
}
}