package org.bouncycastle.crypto.test;
import java.math.BigInteger;
import java.security.SecureRandom;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.SimpleTestResult;
import org.bouncycastle.util.test.Test;
import org.bouncycastle.util.test.TestResult;
/**
* ECDSA tests are taken from X9.62.
*/
public class ECTest
implements Test
{
/**
* X9.62 - 1998,<br>
* J.3.1, Page 152, ECDSA over the field Fp<br>
* an example with 192 bit prime
*/
private class ECDSA192bitPrime
implements Test
{
BigInteger r = new BigInteger("3342403536405981729393488334694600415596881826869351677613");
BigInteger s = new BigInteger("5735822328888155254683894997897571951568553642892029982342");
SecureRandom k = new SecureRandom()
{
public void nextBytes(byte[] bytes)
{
byte[] k = new BigInteger("6140507067065001063065065565667405560006161556565665656654").toByteArray();
System.arraycopy(k, k.length-bytes.length, bytes, 0, bytes.length);
}
};
public String getName()
{
return "ECDSA 192 bit prime";
}
public TestResult perform()
{
ECCurve.Fp curve = new ECCurve.Fp(
new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b
ECDomainParameters params = new ECDomainParameters(
curve,
curve.decodePoint(Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
new BigInteger("6277101735386680763835789423176059013767194773182842284081")); // n
ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
params);
ParametersWithRandom param = new ParametersWithRandom(priKey, k);
ECDSASigner ecdsa = new ECDSASigner();
ecdsa.init(true, param);
byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
BigInteger[] sig = ecdsa.generateSignature(message);
if (!r.equals(sig[0]))
{
return new SimpleTestResult(false, getName()
+ ": r component wrong." + System.getProperty("line.separator")
+ " expecting: " + r + System.getProperty("line.separator")
+ " got : " + sig[0]);
}
if (!s.equals(sig[1]))
{
return new SimpleTestResult(false, getName()
+ ": s component wrong." + System.getProperty("line.separator")
+ " expecting: " + s + System.getProperty("line.separator")
+ " got : " + sig[1]);
}
// Verify the signature
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
curve.decodePoint(Hex.decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
params);
ecdsa.init(false, pubKey);
if ( ecdsa.verifySignature(message, sig[0], sig[1]) )
{
return new SimpleTestResult(true, getName() + ": Okay");
}
else
{
return new SimpleTestResult(false, getName() + ": verification fails");
}
}
}
/**
* X9.62 - 1998,<br>
* J.3.2, Page 155, ECDSA over the field Fp<br>
* an example with 239 bit prime
*/
private class ECDSA239bitPrime
implements Test
{
BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176");
BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783");
SecureRandom k = new SecureRandom()
{
public void nextBytes(byte[] bytes)
{
byte[] k = new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655").toByteArray();
System.arraycopy(k, k.length-bytes.length, bytes, 0, bytes.length);
}
};
public String getName()
{
return "ECDSA 239 bit prime";
}
public TestResult perform()
{
ECCurve.Fp curve = new ECCurve.Fp(
new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
ECDomainParameters params = new ECDomainParameters(
curve,
curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n
ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
params);
ECDSASigner ecdsa = new ECDSASigner();
ParametersWithRandom param = new ParametersWithRandom(priKey, k);
ecdsa.init(true, param);
byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
BigInteger[] sig = ecdsa.generateSignature(message);
if (!r.equals(sig[0]))
{
return new SimpleTestResult(false, getName()
+ ": r component wrong." + System.getProperty("line.separator")
+ " expecting: " + r + System.getProperty("line.separator")
+ " got : " + sig[0]);
}
if (!s.equals(sig[1]))
{
return new SimpleTestResult(false, getName()
+ ": s component wrong." + System.getProperty("line.separator")
+ " expecting: " + s + System.getProperty("line.separator")
+ " got : " + sig[1]);
}
// Verify the signature
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
curve.decodePoint(Hex.decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
params);
ecdsa.init(false, pubKey);
if ( ecdsa.verifySignature(message, sig[0], sig[1]) )
{
return new SimpleTestResult(true, getName() + ": Okay");
}
else
{
return new SimpleTestResult(false, getName() + ": signature fails");
}
}
}
/**
* key generation test
*/
private class ECDSAKeyGenTest
implements Test
{
public String getName()
{
return "ECDSA key generation test";
}
public TestResult perform()
{
SecureRandom random = new SecureRandom();
ECCurve.Fp curve = new ECCurve.Fp(
new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
ECDomainParameters params = new ECDomainParameters(
curve,
curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n
ECKeyPairGenerator pGen = new ECKeyPairGenerator();
ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
params,
random);
pGen.init(genParam);
AsymmetricCipherKeyPair pair = pGen.generateKeyPair();
ParametersWithRandom param = new ParametersWithRandom(pair.getPrivate(), random);
ECDSASigner ecdsa = new ECDSASigner();
ecdsa.init(true, param);
byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").toByteArray();
BigInteger[] sig = ecdsa.generateSignature(message);
ecdsa.init(false, pair.getPublic());
if (ecdsa.verifySignature(message, sig[0], sig[1]))
{
return new SimpleTestResult(true, getName() + ": Okay");
}
else
{
return new SimpleTestResult(false, getName() + ": signature fails");
}
}
}
/**
* Basic Key Agreement Test
*/
private class ECBasicAgreementTest
implements Test
{
public String getName()
{
return "EC basic agreement test";
}
public TestResult perform()
{
SecureRandom random = new SecureRandom();
ECCurve.Fp curve = new ECCurve.Fp(
new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
ECDomainParameters params = new ECDomainParameters(
curve,
curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n
ECKeyPairGenerator pGen = new ECKeyPairGenerator();
ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
params,
random);
pGen.init(genParam);
AsymmetricCipherKeyPair p1 = pGen.generateKeyPair();
AsymmetricCipherKeyPair p2 = pGen.generateKeyPair();
//
// two way
//
BasicAgreement e1 = new ECDHBasicAgreement();
BasicAgreement e2 = new ECDHBasicAgreement();
e1.init(p1.getPrivate());
e2.init(p2.getPrivate());
BigInteger k1 = e1.calculateAgreement(p2.getPublic());
BigInteger k2 = e2.calculateAgreement(p1.getPublic());
if (!k1.equals(k2))
{
return new SimpleTestResult(false, this.getName() + ": calculated agreement test failed");
}
//
// two way
//
e1 = new ECDHCBasicAgreement();
e2 = new ECDHCBasicAgreement();
e1.init(p1.getPrivate());
e2.init(p2.getPrivate());
k1 = e1.calculateAgreement(p2.getPublic());
k2 = e2.calculateAgreement(p1.getPublic());
if (!k1.equals(k2))
{
return new SimpleTestResult(false, this.getName() + ": calculated agreement test failed");
}
return new SimpleTestResult(true, this.getName() + ": Okay");
}
}
Test tests[] =
{
new ECDSA192bitPrime(),
new ECDSA239bitPrime(),
new ECDSAKeyGenTest(),
new ECBasicAgreementTest()
};
public String getName()
{
return "EC";
}
public TestResult perform()
{
for (int i = 0; i != tests.length; i++)
{
TestResult result = tests[i].perform();
if (!result.isSuccessful())
{
return result;
}
}
return new SimpleTestResult(true, "EC: Okay");
}
public static void main(
String[] args)
{
ECTest test = new ECTest();
TestResult result = test.perform();
System.out.println(result);
}
}