[BROKEN] Trying to get elliptic curve working, which is much too slow at the moment.
This commit is contained in:
@@ -11,6 +11,10 @@ import java.lang.Math;
|
||||
import java.lang.Thread;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import org.bouncycastle.asn1.nist.NISTNamedCurves;
|
||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
|
||||
@@ -27,188 +31,288 @@ import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.crypto.signers.ECDSASigner;
|
||||
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
|
||||
import org.bouncycastle.math.ec.ECAlgorithms;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
|
||||
class Generator {
|
||||
private FileWriter out;
|
||||
private SecureRandom rng;
|
||||
final static int COUNT = 500;
|
||||
|
||||
final static int NUM_THREADS = 4;
|
||||
|
||||
public Generator(SecureRandom r, FileWriter o) {
|
||||
rng = r;
|
||||
out = o;
|
||||
}
|
||||
|
||||
public void runTests(String curveName, int count)
|
||||
public static void main(String[] args)
|
||||
throws IOException, InterruptedException
|
||||
{
|
||||
Thread threads[] = new Thread[NUM_THREADS];
|
||||
new Generator().run();
|
||||
}
|
||||
|
||||
System.out.print("Generating " + curveName + " tests ");
|
||||
for(int i = 0; i < NUM_THREADS; i++) {
|
||||
X9ECParameters x9ECParameters = NISTNamedCurves.getByName(curveName);
|
||||
ECDomainParameters params = new ECDomainParameters(x9ECParameters.getCurve(),
|
||||
x9ECParameters.getG(),
|
||||
x9ECParameters.getN());
|
||||
Runner runner = new Runner(params, count / NUM_THREADS, this);
|
||||
Thread runThread = new Thread(runner);
|
||||
runThread.start();
|
||||
threads[i] = runThread;
|
||||
public Generator() { }
|
||||
|
||||
public void run()
|
||||
throws IOException, InterruptedException
|
||||
{
|
||||
OutFiles outfiles = new OutFiles();
|
||||
String[] curves = { "P-192", "P-224", "P-256", "P-384", "P-521" };
|
||||
ArrayList<Thread> threads = new ArrayList<Thread>();
|
||||
|
||||
System.out.print("Generating: ");
|
||||
for(String curve : curves) {
|
||||
X9ECParameters params = NISTNamedCurves.getByName(curve);
|
||||
ECDomainParameters dp = new ECDomainParameters(params.getCurve(),
|
||||
params.getG(),
|
||||
params.getN());
|
||||
Runner runner = new Runner(outfiles, dp);
|
||||
Thread thread = new Thread(runner);
|
||||
thread.start();
|
||||
threads.add(thread);
|
||||
}
|
||||
for(Thread thread : threads) {
|
||||
|
||||
for(Thread thread: threads) {
|
||||
thread.join();
|
||||
}
|
||||
System.out.println(" done.");
|
||||
}
|
||||
|
||||
public synchronized void output(AsymmetricCipherKeyPair kp,
|
||||
int digestsize,
|
||||
byte[] message,
|
||||
BigInteger[] rs)
|
||||
throws IOException
|
||||
{
|
||||
ECPublicKeyParameters pub = (ECPublicKeyParameters)kp.getPublic();
|
||||
ECPrivateKeyParameters priv = (ECPrivateKeyParameters)kp.getPrivate();
|
||||
out.write("c: " + pub.getParameters().getCurve().getFieldSize() + "\n");
|
||||
out.write("x: " + pub.getQ().getAffineXCoord().toBigInteger().toString(16) + "\n");
|
||||
out.write("y: " + pub.getQ().getAffineYCoord().toBigInteger().toString(16) + "\n");
|
||||
out.write("d: " + priv.getD().toString(16) + "\n");
|
||||
out.write("h: " + digestsize + "\n");
|
||||
out.write("m: " + asHex(message) + "\n");
|
||||
out.write("r: " + rs[0].toString(16) + "\n");
|
||||
out.write("s: " + rs[1].toString(16) + "\n");
|
||||
out.flush();
|
||||
System.out.print(".");
|
||||
System.out.flush();
|
||||
}
|
||||
public class OutFiles {
|
||||
public FileWriter negate;
|
||||
public FileWriter dble;
|
||||
public FileWriter add;
|
||||
public FileWriter mul;
|
||||
public FileWriter add2mul;
|
||||
public FileWriter sig;
|
||||
|
||||
private Digest appropriateDigest(int nsize)
|
||||
throws IOException
|
||||
{
|
||||
switch(nsize) {
|
||||
case 1: return new SHA1Digest();
|
||||
case 160: return new SHA1Digest();
|
||||
case 224: return new SHA224Digest();
|
||||
case 256: return new SHA256Digest();
|
||||
case 384: return new SHA384Digest();
|
||||
case 512: return new SHA512Digest();
|
||||
default:
|
||||
throw new IOException("Bad digest size!");
|
||||
}
|
||||
}
|
||||
|
||||
private int randomDigestSize()
|
||||
throws IOException
|
||||
{
|
||||
switch(getRandomChoice(5)) {
|
||||
case 0: return 1;
|
||||
case 1: return 224;
|
||||
case 2: return 256;
|
||||
case 3: return 384;
|
||||
case 4: return 512;
|
||||
default:
|
||||
throw new IOException("The world broke.");
|
||||
}
|
||||
}
|
||||
|
||||
private int getRandomChoice(int modulus) {
|
||||
byte randoms[] = new byte[2];
|
||||
rng.nextBytes(randoms);
|
||||
int random = ((int)randoms[0] << 8) + ((int)randoms[1]);
|
||||
return (Math.abs(random) % modulus);
|
||||
}
|
||||
|
||||
private String asHex(byte[] data) {
|
||||
String result = "";
|
||||
|
||||
for(byte value : data) {
|
||||
result = result + String.format("%02x", value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
throws IOException, InterruptedException
|
||||
{
|
||||
SecureRandom rng = new SecureRandom();
|
||||
FileWriter outfile = new FileWriter("signature.test", false);
|
||||
Generator gen = new Generator(rng, outfile);
|
||||
|
||||
gen.runTests("P-192", 500);
|
||||
gen.runTests("P-224", 500);
|
||||
gen.runTests("P-256", 500);
|
||||
gen.runTests("P-384", 500);
|
||||
gen.runTests("P-521", 500);
|
||||
}
|
||||
|
||||
private class Runner implements Runnable {
|
||||
private ECDomainParameters params;
|
||||
private int count;
|
||||
private Generator parent;
|
||||
|
||||
public Runner(ECDomainParameters params, int count, Generator parent)
|
||||
public OutFiles()
|
||||
{
|
||||
this.params = params;
|
||||
this.count = count;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
for(int i = 0; i < count; i++) {
|
||||
runTest();
|
||||
try {
|
||||
negate = new FileWriter("ec_negate.test", false);
|
||||
dble = new FileWriter("ec_dble.test", false);
|
||||
add = new FileWriter("ec_add.test", false);
|
||||
mul = new FileWriter("ec_mul.test", false);
|
||||
add2mul = new FileWriter("ec_add2mul.test", false);
|
||||
sig = new FileWriter("signature.test", false);
|
||||
} catch(IOException e) {
|
||||
System.out.println("Blech: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private AsymmetricCipherKeyPair getKeyPair()
|
||||
{
|
||||
ECKeyGenerationParameters params =
|
||||
new ECKeyGenerationParameters(this.params, this.parent.rng);
|
||||
ECKeyPairGenerator keygen = new ECKeyPairGenerator();
|
||||
keygen.init(params);
|
||||
return keygen.generateKeyPair();
|
||||
public synchronized void dump(FileWriter file, Map<String,String> x) {
|
||||
try {
|
||||
for(Map.Entry<String,String> entry : x.entrySet()) {
|
||||
file.write(entry.getKey());
|
||||
file.write(": ");
|
||||
file.write(entry.getValue());
|
||||
file.write("\n");
|
||||
file.flush();
|
||||
|
||||
if(file == negate) { System.out.print("N"); };
|
||||
if(file == dble) { System.out.print("D"); };
|
||||
if(file == add) { System.out.print("A"); };
|
||||
if(file == mul) { System.out.print("M"); };
|
||||
if(file == add2mul) { System.out.print("2"); };
|
||||
if(file == sig) { System.out.print("S"); };
|
||||
System.out.flush();
|
||||
}
|
||||
} catch(IOException e) {
|
||||
System.out.println("Argh: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Runner implements Runnable {
|
||||
private OutFiles outfiles;
|
||||
private SecureRandom rng;
|
||||
private ECDomainParameters ecparams;
|
||||
private BigInteger two;
|
||||
|
||||
public Runner(OutFiles outfiles, ECDomainParameters params) {
|
||||
this.outfiles = outfiles;
|
||||
this.ecparams = params;
|
||||
this.rng = new SecureRandom();
|
||||
this.two = BigInteger.valueOf(2);
|
||||
}
|
||||
|
||||
private byte[] getMessage()
|
||||
{
|
||||
int msgsize = getRandomChoice(1024);
|
||||
byte message[] = new byte[msgsize];
|
||||
rng.nextBytes(message);
|
||||
return message;
|
||||
public void run() {
|
||||
for(int i = 0; i < COUNT; i++) { generateNegateTests(); }
|
||||
for(int i = 0; i < COUNT; i++) { generateDoubleTests(); }
|
||||
for(int i = 0; i < COUNT; i++) { generateAddTests(); }
|
||||
for(int i = 0; i < COUNT; i++) { generateMulTests(); }
|
||||
for(int i = 0; i < COUNT; i++) { generateAdd2MulTests(); }
|
||||
for(int i = 0; i < COUNT; i++) { generateSignatureTests(); }
|
||||
}
|
||||
|
||||
private byte[] runHash(byte[] msg, int digestsize)
|
||||
throws IOException
|
||||
{
|
||||
Digest digestfn = appropriateDigest(digestsize);
|
||||
public void generateNegateTests() {
|
||||
ECPoint p = getPoint();
|
||||
ECPoint n = p.negate().normalize();
|
||||
HashMap<String,String> m = new HashMap<String,String>();
|
||||
|
||||
m.put("c", Integer.toString(ecparams.getN().bitLength()));
|
||||
m.put("x", p.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("y", p.getAffineYCoord().toBigInteger().toString(16));
|
||||
m.put("a", n.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("b", n.getAffineYCoord().toBigInteger().toString(16));
|
||||
outfiles.dump(outfiles.negate, m);
|
||||
}
|
||||
|
||||
public void generateDoubleTests() {
|
||||
ECPoint p = getPoint();
|
||||
ECPoint n = p.twice().normalize();
|
||||
HashMap<String,String> m = new HashMap<String,String>();
|
||||
|
||||
m.put("c", Integer.toString(ecparams.getN().bitLength()));
|
||||
m.put("x", p.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("y", p.getAffineYCoord().toBigInteger().toString(16));
|
||||
m.put("a", n.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("b", n.getAffineYCoord().toBigInteger().toString(16));
|
||||
outfiles.dump(outfiles.dble, m);
|
||||
}
|
||||
|
||||
public void generateAddTests() {
|
||||
ECPoint p1 = getPoint();
|
||||
ECPoint p2 = getPoint();
|
||||
ECPoint q = p1.add(p2).normalize();
|
||||
HashMap<String,String> m = new HashMap<String,String>();
|
||||
|
||||
m.put("c", Integer.toString(ecparams.getN().bitLength()));
|
||||
m.put("x", p1.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("y", p1.getAffineYCoord().toBigInteger().toString(16));
|
||||
m.put("q", p2.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("r", p2.getAffineYCoord().toBigInteger().toString(16));
|
||||
m.put("a", q.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("b", q.getAffineYCoord().toBigInteger().toString(16));
|
||||
outfiles.dump(outfiles.add, m);
|
||||
}
|
||||
|
||||
public void generateMulTests() {
|
||||
ECPoint p = getPoint();
|
||||
BigInteger k = getConstant();
|
||||
ECPoint q = p.multiply(k).normalize();
|
||||
HashMap<String,String> m = new HashMap<String,String>();
|
||||
|
||||
m.put("c", Integer.toString(ecparams.getN().bitLength()));
|
||||
m.put("x", p.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("y", p.getAffineYCoord().toBigInteger().toString(16));
|
||||
m.put("k", k.toString(16));
|
||||
m.put("a", q.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("b", q.getAffineYCoord().toBigInteger().toString(16));
|
||||
outfiles.dump(outfiles.mul, m);
|
||||
}
|
||||
|
||||
public void generateAdd2MulTests() {
|
||||
ECPoint p = getPoint();
|
||||
BigInteger a = getConstant();
|
||||
ECPoint q = getPoint();
|
||||
BigInteger b = getConstant();
|
||||
ECPoint r = ECAlgorithms.sumOfTwoMultiplies(p,a,q,b).normalize();
|
||||
HashMap<String,String> m = new HashMap<String,String>();
|
||||
|
||||
m.put("c", Integer.toString(ecparams.getN().bitLength()));
|
||||
m.put("x", p.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("y", p.getAffineYCoord().toBigInteger().toString(16));
|
||||
m.put("a", a.toString(16));
|
||||
m.put("q", q.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("r", q.getAffineYCoord().toBigInteger().toString(16));
|
||||
m.put("b", b.toString(16));
|
||||
m.put("s", r.getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("t", r.getAffineYCoord().toBigInteger().toString(16));
|
||||
outfiles.dump(outfiles.add2mul, m);
|
||||
}
|
||||
|
||||
public void generateSignatureTests() {
|
||||
AsymmetricCipherKeyPair kp = getKeyPair();
|
||||
ECPublicKeyParameters pub = (ECPublicKeyParameters)kp.getPublic();
|
||||
ECPrivateKeyParameters priv = (ECPrivateKeyParameters)kp.getPrivate();
|
||||
byte message[] = getMessage();
|
||||
int digestsize = getDigestSize();
|
||||
byte hash[] = runHash(message, digestsize);
|
||||
Digest msgdigest = getHash(digestsize);
|
||||
HMacDSAKCalculator kgen = new HMacDSAKCalculator(msgdigest);
|
||||
ECDSASigner signer = new ECDSASigner(kgen);
|
||||
signer.init(true, priv);
|
||||
BigInteger rs[] = signer.generateSignature(hash);
|
||||
HashMap<String,String> m = new HashMap<String,String>();
|
||||
|
||||
m.put("c", Integer.toString(ecparams.getN().bitLength()));
|
||||
m.put("x", pub.getQ().getAffineXCoord().toBigInteger().toString(16));
|
||||
m.put("y", pub.getQ().getAffineYCoord().toBigInteger().toString(16));
|
||||
m.put("d", priv.getD().toString(16));
|
||||
m.put("h", Integer.toString(digestsize));
|
||||
m.put("m", asHex(message));
|
||||
m.put("r", rs[0].toString(16));
|
||||
m.put("s", rs[1].toString(16));
|
||||
outfiles.dump(outfiles.sig, m);
|
||||
}
|
||||
|
||||
private byte[] runHash(byte[] msg, int size) {
|
||||
Digest digestfn = getHash(size);
|
||||
digestfn.update(msg, 0, msg.length);
|
||||
byte result[] = new byte[digestfn.getDigestSize()];
|
||||
digestfn.doFinal(result, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void runTest()
|
||||
{
|
||||
try {
|
||||
AsymmetricCipherKeyPair kp = getKeyPair();
|
||||
ECPublicKeyParameters pub = (ECPublicKeyParameters)kp.getPublic();
|
||||
ECPrivateKeyParameters priv = (ECPrivateKeyParameters)kp.getPrivate();
|
||||
private AsymmetricCipherKeyPair getKeyPair() {
|
||||
ECKeyGenerationParameters params =
|
||||
new ECKeyGenerationParameters(ecparams, rng);
|
||||
ECKeyPairGenerator keygen = new ECKeyPairGenerator();
|
||||
keygen.init(params);
|
||||
return keygen.generateKeyPair();
|
||||
}
|
||||
|
||||
byte message[] = getMessage();
|
||||
int digestsize = randomDigestSize();
|
||||
byte hash[] = runHash(message, digestsize);
|
||||
private byte[] getMessage() {
|
||||
int msgsize = rng.nextInt(1024);
|
||||
byte message[] = new byte[msgsize];
|
||||
rng.nextBytes(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
Digest msgdigest = appropriateDigest(digestsize);
|
||||
HMacDSAKCalculator kgen = new HMacDSAKCalculator(msgdigest);
|
||||
ECDSASigner signer = new ECDSASigner(kgen);
|
||||
signer.init(true, priv);
|
||||
BigInteger rs[] = signer.generateSignature(hash);
|
||||
parent.output(kp, digestsize, message, rs);
|
||||
} catch(IOException exc) {
|
||||
System.out.println("EXCEPTION!");
|
||||
run();
|
||||
private ECPoint getPoint() {
|
||||
BigInteger k = getConstant();
|
||||
return ecparams.getG().multiply(k).normalize();
|
||||
}
|
||||
|
||||
private BigInteger getConstant() {
|
||||
BigInteger n = ecparams.getN();
|
||||
int nBitLength = n.bitLength();
|
||||
|
||||
for(;;) {
|
||||
BigInteger d = new BigInteger(nBitLength, rng);
|
||||
|
||||
if(d.compareTo(two) < 0 || (d.compareTo(n) >= 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getDigestSize() {
|
||||
switch(rng.nextInt(5)) {
|
||||
case 0: return 1;
|
||||
case 1: return 224;
|
||||
case 2: return 256;
|
||||
case 3: return 384;
|
||||
case 4: return 512;
|
||||
default:
|
||||
return 999;
|
||||
}
|
||||
}
|
||||
|
||||
private Digest getHash(int nsize) {
|
||||
switch(nsize) {
|
||||
case 1: return new SHA1Digest();
|
||||
case 224: return new SHA1Digest();
|
||||
case 256: return new SHA1Digest();
|
||||
case 384: return new SHA1Digest();
|
||||
case 512: return new SHA1Digest();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String asHex(byte[] data) {
|
||||
String result = "";
|
||||
for(byte value : data) {
|
||||
result = result + String.format("%02x", value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
17500
tests/ecdsa/ec_add.test
Normal file
17500
tests/ecdsa/ec_add.test
Normal file
File diff suppressed because it is too large
Load Diff
22500
tests/ecdsa/ec_add2mul.test
Normal file
22500
tests/ecdsa/ec_add2mul.test
Normal file
File diff suppressed because it is too large
Load Diff
12500
tests/ecdsa/ec_dble.test
Normal file
12500
tests/ecdsa/ec_dble.test
Normal file
File diff suppressed because it is too large
Load Diff
15000
tests/ecdsa/ec_mul.test
Normal file
15000
tests/ecdsa/ec_mul.test
Normal file
File diff suppressed because it is too large
Load Diff
12500
tests/ecdsa/ec_negate.test
Normal file
12500
tests/ecdsa/ec_negate.test
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user