package org.bouncycastle.math.ec.test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;
public class F2mProofer
{
private static final int NUM_SAMPLES = 1000;
private static final String PATH = "crypto/test/src/org/bouncycastle/math/ec/test/samples/";
private static final String INPUT_FILE_NAME_PREFIX = "Input_";
private static final String RESULT_FILE_NAME_PREFIX = "Output_";
/**
* The standard curves on which the tests are done
*/
public static final String[] CURVES = { "sect163r2", "sect233r1",
"sect283r1", "sect409r1", "sect571r1" };
private String pointToString(ECPoint.F2m p)
{
ECFieldElement.F2m x = (ECFieldElement.F2m) p.getX();
ECFieldElement.F2m y = (ECFieldElement.F2m) p.getY();
int m = x.getM();
int len = m / 2 + 5;
StringBuffer sb = new StringBuffer(len);
sb.append('(');
sb.append(x.toBigInteger().toString(16));
sb.append(", ");
sb.append(y.toBigInteger().toString(16));
sb.append(')');
return sb.toString();
}
private void generateRandomInput(X9ECParameters x9ECParameters)
throws NoSuchAlgorithmException, IOException
{
ECPoint.F2m g = (ECPoint.F2m) x9ECParameters.getG();
int m = ((ECFieldElement.F2m) (g.getX())).getM();
SecureRandom secRand = SecureRandom.getInstance("SHA1PRNG");
Properties inputProps = new Properties();
for (int i = 0; i < NUM_SAMPLES; i++)
{
BigInteger rand = new BigInteger(m, secRand);
inputProps.put(Integer.toString(i), rand.toString(16));
}
String bits = Integer.toString(m);
FileOutputStream fos = new FileOutputStream(PATH
+ INPUT_FILE_NAME_PREFIX + bits + ".properties");
inputProps.store(fos, "Input Samples of length" + bits);
}
private void multiplyPoints(X9ECParameters x9ECParameters,
String classPrefix) throws IOException
{
ECPoint.F2m g = (ECPoint.F2m) x9ECParameters.getG();
int m = ((ECFieldElement.F2m) (g.getX())).getM();
String inputFileName = PATH + INPUT_FILE_NAME_PREFIX + m
+ ".properties";
Properties inputProps = new Properties();
inputProps.load(new FileInputStream(inputFileName));
Properties outputProps = new Properties();
for (int i = 0; i < NUM_SAMPLES; i++)
{
BigInteger rand = new BigInteger(inputProps.getProperty(Integer
.toString(i)), 16);
ECPoint.F2m result = (ECPoint.F2m) g.multiply(rand);
String resultStr = pointToString(result);
outputProps.setProperty(Integer.toString(i), resultStr);
}
String outputFileName = PATH + RESULT_FILE_NAME_PREFIX + classPrefix
+ "_" + m + ".properties";
FileOutputStream fos = new FileOutputStream(outputFileName);
outputProps.store(fos, "Output Samples of length" + m);
}
private Properties loadResults(String classPrefix, int m)
throws IOException
{
FileInputStream fis = new FileInputStream(PATH
+ RESULT_FILE_NAME_PREFIX + classPrefix + "_" + m + ".properties");
Properties res = new Properties();
res.load(fis);
return res;
}
private void compareResult(X9ECParameters x9ECParameters,
String classPrefix1, String classPrefix2) throws IOException
{
ECPoint.F2m g = (ECPoint.F2m) x9ECParameters.getG();
int m = ((ECFieldElement.F2m) (g.getX())).getM();
Properties res1 = loadResults(classPrefix1, m);
Properties res2 = loadResults(classPrefix2, m);
Set keys = res1.keySet();
Iterator iter = keys.iterator();
while (iter.hasNext())
{
String key = (String) iter.next();
String result1 = res1.getProperty(key);
String result2 = res2.getProperty(key);
if (!(result1.equals(result2)))
{
System.err.println("Difference found: m = " + m + ", "
+ result1 + " does not equal " + result2);
}
}
}
private static void usage()
{
System.err.println("Usage: F2mProofer [-init | -multiply <className> "
+ "| -compare <className1> <className2>]");
}
public static void main(String[] args) throws Exception
{
if (args.length == 0)
{
usage();
return;
}
F2mProofer proofer = new F2mProofer();
if (args[0].equals("-init"))
{
System.out.println("Generating random input...");
for (int i = 0; i < CURVES.length; i++)
{
X9ECParameters x9ECParameters = SECNamedCurves
.getByName(CURVES[i]);
proofer.generateRandomInput(x9ECParameters);
}
System.out
.println("Successfully generated random input in " + PATH);
}
else if (args[0].equals("-compare"))
{
if (args.length < 3)
{
usage();
return;
}
String classPrefix1 = args[1];
String classPrefix2 = args[2];
System.out.println("Comparing results...");
for (int i = 0; i < CURVES.length; i++)
{
X9ECParameters x9ECParameters = SECNamedCurves
.getByName(CURVES[i]);
proofer.compareResult(x9ECParameters, classPrefix1,
classPrefix2);
}
System.out.println("Successfully compared results in " + PATH);
}
else if (args[0].equals("-multiply"))
{
if (args.length < 2)
{
usage();
return;
}
String classPrefix = args[1];
System.out.println("Multiplying points...");
for (int i = 0; i < CURVES.length; i++)
{
X9ECParameters x9ECParameters = SECNamedCurves
.getByName(CURVES[i]);
proofer.multiplyPoints(x9ECParameters, classPrefix);
}
System.out.println("Successfully generated multiplied points in "
+ PATH);
}
else
{
usage();
}
}
}