Skip to content

Instantly share code, notes, and snippets.

@hube12
Created February 6, 2021 18:54
Show Gist options
  • Select an option

  • Save hube12/e307153689390d3fc49495debf0aab67 to your computer and use it in GitHub Desktop.

Select an option

Save hube12/e307153689390d3fc49495debf0aab67 to your computer and use it in GitHub Desktop.
Example of seed from curves
package javaECC;
import org.bouncycastle.crypto.generators.ElGamalParametersGenerator;
import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.crypto.params.ElGamalParameters;
import org.bouncycastle.util.BigIntegers;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Objects;
public class App {
// compile group: 'org.bouncycastle', name: 'bcprov-jdk15', version: '1.46'
private static final BigInteger ONE = BigInteger.valueOf(1);
private static final BigInteger TWO = BigInteger.valueOf(2);
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
public static Pair<BigInteger, BigInteger> getKeyPair() {
/*
* Returns the keys pair (private,public) of a random curve
*/
int strength = 1024;
int certainty = 20;
ElGamalParametersGenerator pGen = new ElGamalParametersGenerator();
pGen.init(strength, certainty, SECURE_RANDOM);
// generate the Diffie hellman secure parameters
ElGamalParameters egp = pGen.generateParameters();
// we use a limit of 64 bits instead of 0 as elgamal do
DHParameters dhp = new DHParameters(egp.getP(), egp.getG(), null, 64);
// choose a random private key (short)
BigInteger x = calculatePrivate(dhp, SECURE_RANDOM);
// derive the long public key
BigInteger y = calculatePublic(dhp, x);
return new Pair<>(x, y);
}
public static ElGamalParameters generateFixedDHParameters() {
int strength = 1024;
int certainty = 20;
SecureRandom random = new SecureRandom();
ElGamalParametersGenerator pGen = new ElGamalParametersGenerator();
pGen.init(strength, certainty, random);
// generate the Diffie hellman secure parameters
return pGen.generateParameters();
}
public static Pair<BigInteger, BigInteger> getDHKeyPair(ElGamalParameters egp) {
/*
* Returns the keys pair (private,public) of a fixed curve
*/
DHParameters dhp = new DHParameters(egp.getP(), egp.getG(), null, 64);
// choose a random private key (short)
BigInteger x = calculatePrivate(dhp, SECURE_RANDOM);
// derive the long public key
BigInteger y = calculatePublic(dhp, x);
return new Pair<>(x, y);
}
public static Pair<BigInteger, BigInteger> getKeyPairFromPG(BigInteger P, BigInteger G) {
/*
* Returns the keys pair (private,public) of a fixed curve
*/
DHParameters dhp = new DHParameters(P, G, null, 64);
// choose a random private key (short)
BigInteger x = calculatePrivate(dhp, SECURE_RANDOM);
// derive the long public key
BigInteger y = calculatePublic(dhp, x);
return new Pair<>(x, y);
}
private static BigInteger calculatePrivate(DHParameters dhParams, SecureRandom random) {
BigInteger p = dhParams.getP();
int limit = dhParams.getL();
if (limit != 0) {
return new BigInteger(limit, random).setBit(limit - 1);
}
BigInteger min = TWO;
int m = dhParams.getM();
if (m != 0) {
min = ONE.shiftLeft(m - 1);
}
BigInteger max = p.subtract(TWO);
BigInteger q = dhParams.getQ();
if (q != null) {
max = q.subtract(TWO);
}
return BigIntegers.createRandomInRange(min, max, random);
}
private static BigInteger calculatePublic(DHParameters dhParams, BigInteger x) {
return dhParams.getG().modPow(x, dhParams.getP());
}
public static BigInteger getPublicFromPrivate(DHParameters dhParameters, BigInteger x) {
return calculatePublic(dhParameters, x);
}
public static BigInteger getPublicFromPrivate(BigInteger P, BigInteger G, BigInteger x) {
return calculatePublic(new DHParameters(P, G, null, 64), x);
}
public static BigInteger getPublicFromPrivate(ElGamalParameters egp, BigInteger x) {
return calculatePublic(new DHParameters(egp.getP(), egp.getG(), null, 64), x);
}
public static final class Pair<A, B> {
private final A a;
private final B b;
public Pair(A a, B b) {
this.a = a;
this.b = b;
}
public Pair(Pair<? extends A, ? extends B> other) {
this(other.a, other.b);
}
public A getFirst() {
return this.a;
}
public B getSecond() {
return this.b;
}
public int hashCode() {
return Objects.hash(this.a, this.b);
}
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (other != null && other.getClass() == Pair.class) {
Pair<?, ?> that = (Pair<?, ?>) other;
return Objects.equals(this.a, that.a) && Objects.equals(this.b, that.b);
} else {
return false;
}
}
public String toString() {
return "(" + this.a + ", " + this.b + ")";
}
}
public static void showBasicUsage(){
Pair<BigInteger, BigInteger> keyPair = getKeyPair();
BigInteger externalSeed = keyPair.getFirst(); // short key of 64 bits
BigInteger internalSeed = keyPair.getSecond(); // long key of 1024 bits
System.out.printf("You could use seed : %s which would internally map to %s%n", internalSeed, externalSeed);
System.out.printf("External seed of %d bits%n", externalSeed.bitLength());
System.out.printf("Internal seed of %d bits%n", internalSeed.bitLength());
}
public static ElGamalParameters showRecommendUsage(){
// we recommend dumping an instance of egp inside the source code, it's totally secure to have it fixed, plus way faster
ElGamalParameters egp = generateFixedDHParameters();
// first keys
Pair<BigInteger, BigInteger> keyPair1 = getDHKeyPair(egp);
BigInteger externalSeed = keyPair1.getFirst(); // short key of 64 bits
BigInteger internalSeed = keyPair1.getSecond(); // long key of 1024 bits
System.out.printf("You could use seed : %s which would internally map to %s%n", internalSeed, externalSeed);
System.out.printf("External seed of %d bits%n", externalSeed.bitLength());
System.out.printf("Internal seed of %d bits%n", internalSeed.bitLength());
// second keys
Pair<BigInteger, BigInteger> keyPair2 = getDHKeyPair(egp);
externalSeed = keyPair2.getFirst(); // short key of 64 bits
internalSeed = keyPair2.getSecond(); // long key of 1024 bits
System.out.printf("You could use seed : %s which would internally map to %s%n", internalSeed, externalSeed);
System.out.printf("External seed of %d bits%n", externalSeed.bitLength());
System.out.printf("Internal seed of %d bits%n", internalSeed.bitLength());
return egp;
}
public static Pair<BigInteger,BigInteger> showEasierExample(){
// we recommend dumping an instance of egp inside the source code, it's totally secure to have it fixed, plus way faster
ElGamalParameters egp = generateFixedDHParameters();
BigInteger P = egp.getP();
BigInteger G = egp.getG();
Pair<BigInteger, BigInteger> keyPair = getKeyPairFromPG(P, G);
BigInteger externalSeed = keyPair.getFirst(); // short key of 64 bits
BigInteger internalSeed = keyPair.getSecond(); // long key of 1024 bits
System.out.printf("You could use seed : %s which would internally map to %s%n", internalSeed, externalSeed);
System.out.printf("External seed of %d bits%n", externalSeed.bitLength());
System.out.printf("Internal seed of %d bits%n", internalSeed.bitLength());
return new Pair<>(P,G);
}
public static void recoverPublicKeyFromPrivate(){
// generate parameters (done once before the mod release)
ElGamalParameters egp = generateFixedDHParameters();
BigInteger P = egp.getP();
BigInteger G = egp.getG();
// generated when generating the world (or not-> inputted short seed)
Pair<BigInteger, BigInteger> keyPair1 = getDHKeyPair(egp);
BigInteger externalSeed = keyPair1.getFirst(); // short key of 64 bits
BigInteger internalSeed = keyPair1.getSecond(); // long key of 1024 bits
// recover the public long key from the private key (aka the user input short seed)
BigInteger internalSeedFromExternalSeed1 = getPublicFromPrivate(egp,externalSeed);
BigInteger internalSeedFromExternalSeed2 = getPublicFromPrivate(P,G,externalSeed);
BigInteger internalSeedFromExternalSeed3 = getPublicFromPrivate(new DHParameters(P, G, null, 64),externalSeed);
assert internalSeedFromExternalSeed1.equals(internalSeed);
assert internalSeedFromExternalSeed2.equals(internalSeed);
assert internalSeedFromExternalSeed3.equals(internalSeed);
System.out.println("Passed");
}
public static void main(String[] args) {
showBasicUsage();
ElGamalParameters egp=showRecommendUsage();
System.out.printf("P,G=%s,%s%n", egp.getP(),egp.getG());
Pair<BigInteger,BigInteger> PG=showEasierExample();
System.out.printf("P,G=%s,%s%n", PG.getFirst(), PG.getSecond());
recoverPublicKeyFromPrivate();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment