Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hook <dgh@cryptoworkshop.com>2013-05-10 13:16:11 +0400
committerDavid Hook <dgh@cryptoworkshop.com>2013-05-10 13:16:11 +0400
commit3c08ce8b495fc6f18ea20e4ddfbef3aa896a1fde (patch)
tree9546512e0dc2645ddd0e4e1c1e7420ee1aca0398
parentd5c6cb7a61d30ff3e11e422d61d7ed3b63911cfb (diff)
initial enabling of DSA2 with test vectors for lightweight API.
-rw-r--r--src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java146
-rw-r--r--src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java80
-rw-r--r--src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java15
-rw-r--r--src/test/java/org/bouncycastle/crypto/test/DSATest.java506
4 files changed, 684 insertions, 63 deletions
diff --git a/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java b/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
index be977d71..28110a53 100644
--- a/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+++ b/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
@@ -1,15 +1,16 @@
package org.bouncycastle.crypto.generators;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAValidationParameters;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
+import org.bouncycastle.util.encoders.Hex;
// TODO Update javadoc to mention FIPS 186-3 when done
/**
@@ -17,6 +18,7 @@ import java.security.SecureRandom;
*/
public class DSAParametersGenerator
{
+ private Digest digest;
private int L, N;
private int certainty;
private SecureRandom random;
@@ -25,6 +27,19 @@ public class DSAParametersGenerator
private static final BigInteger ONE = BigInteger.valueOf(1);
private static final BigInteger TWO = BigInteger.valueOf(2);
+ private boolean use186_3;
+ private int usageIndex;
+
+ public DSAParametersGenerator()
+ {
+ this(new SHA1Digest());
+ }
+
+ public DSAParametersGenerator(Digest digest)
+ {
+ this.digest = digest;
+ }
+
/**
* initialise the key generator.
*
@@ -37,23 +52,25 @@ public class DSAParametersGenerator
int certainty,
SecureRandom random)
{
- init(size, getDefaultN(size), certainty, random);
+ this.use186_3 = false;
+ this.L = size;
+ this.N = getDefaultN(size);
+ this.certainty = certainty;
+ this.random = random;
}
- // TODO Make public to enable support for DSA keys > 1024 bits
- private void init(
- int L,
- int N,
- int certainty,
- SecureRandom random)
+
+ public void init(
+ DSAParameterGenerationParameters params)
{
// TODO Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2)
// TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1?
-
- this.L = L;
- this.N = N;
- this.certainty = certainty;
- this.random = random;
+ this.use186_3 = true;
+ this.L = params.getL();
+ this.N = params.getN();
+ this.certainty = params.getCertainty();
+ this.random = params.getRandom();
+ this.usageIndex = params.getUsageIndex();
}
/**
@@ -64,7 +81,7 @@ public class DSAParametersGenerator
*/
public DSAParameters generateParameters()
{
- return L > 1024
+ return (use186_3)
? generateParameters_FIPS186_3()
: generateParameters_FIPS186_2();
}
@@ -75,18 +92,22 @@ public class DSAParametersGenerator
byte[] part1 = new byte[20];
byte[] part2 = new byte[20];
byte[] u = new byte[20];
- SHA1Digest sha1 = new SHA1Digest();
int n = (L - 1) / 160;
byte[] w = new byte[L / 8];
+ if (!(digest instanceof SHA1Digest))
+ {
+ throw new IllegalStateException("can only use SHA-1 for generating FIPS 186-2 parameters");
+ }
+
for (;;)
{
random.nextBytes(seed);
- hash(sha1, seed, part1);
+ hash(digest, seed, part1);
System.arraycopy(seed, 0, part2, 0, seed.length);
inc(part2);
- hash(sha1, part2, part2);
+ hash(digest, part2, part2);
for (int i = 0; i != u.length; i++)
{
@@ -111,12 +132,12 @@ public class DSAParametersGenerator
for (int k = 0; k < n; k++)
{
inc(offset);
- hash(sha1, offset, part1);
+ hash(digest, offset, part1);
System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length);
}
inc(offset);
- hash(sha1, offset, part1);
+ hash(digest, offset, part1);
System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length);
w[0] |= (byte)0x80;
@@ -166,7 +187,7 @@ public class DSAParametersGenerator
{
// A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
// FIXME This should be configurable (digest size in bits must be >= N)
- Digest d = new SHA256Digest();
+ Digest d = digest;
int outlen = d.getDigestSize() * 8;
// 1. Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2). If
@@ -192,6 +213,7 @@ public class DSAParametersGenerator
// 6. U = Hash (domain_parameter_seed) mod 2^(Nā€“1).
hash(d, seed, output);
+
BigInteger U = new BigInteger(1, output).mod(ONE.shiftLeft(N - 1));
// 7. q = 2^(Nā€“1) + U + 1 ā€“ ( U mod 2).
@@ -254,15 +276,19 @@ public class DSAParametersGenerator
// 11.8 If p is determined to be prime, then return VALID and the values of p, q and
// (optionally) the values of domain_parameter_seed and counter.
// TODO Make configurable (8-bit unsigned)?
-// int index = 1;
-// BigInteger g = calculateGenerator_FIPS186_3_Verifiable(d, p, q, seed, index);
-// if (g != null)
-// {
-// // TODO Should 'index' be a part of the validation parameters?
-// return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
-// }
-
- BigInteger g = calculateGenerator_FIPS186_3_Unverifiable(p, q, random);
+ BigInteger g = null;
+
+ if (usageIndex >= 0)
+ {
+ g = calculateGenerator_FIPS186_3_Verifiable(d, p, q, seed, usageIndex);
+ if (g != null)
+ {
+ return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter, usageIndex));
+ }
+ }
+
+ g = calculateGenerator_FIPS186_3_Unverifiable(p, q, random);
+
return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
}
@@ -281,34 +307,34 @@ public class DSAParametersGenerator
return calculateGenerator_FIPS186_2(p, q, r);
}
-// private static BigInteger calculateGenerator_FIPS186_3_Verifiable(Digest d, BigInteger p, BigInteger q,
-// byte[] seed, int index)
-// {
-//// A.2.3 Verifiable Canonical Generation of the Generator g
-// BigInteger e = p.subtract(ONE).divide(q);
-// byte[] ggen = Hex.decode("6767656E");
-//
-// // 7. U = domain_parameter_seed || "ggen" || index || count.
-// byte[] U = new byte[seed.length + ggen.length + 1 + 2];
-// System.arraycopy(seed, 0, U, 0, seed.length);
-// System.arraycopy(ggen, 0, U, seed.length, ggen.length);
-// U[U.length - 3] = (byte)index;
-//
-// byte[] w = new byte[d.getDigestSize()];
-// for (int count = 1; count < (1 << 16); ++count)
-// {
-// inc(U);
-// hash(d, U, w);
-// BigInteger W = new BigInteger(1, w);
-// BigInteger g = W.modPow(e, p);
-// if (g.compareTo(TWO) >= 0)
-// {
-// return g;
-// }
-// }
-//
-// return null;
-// }
+ private static BigInteger calculateGenerator_FIPS186_3_Verifiable(Digest d, BigInteger p, BigInteger q,
+ byte[] seed, int index)
+ {
+// A.2.3 Verifiable Canonical Generation of the Generator g
+ BigInteger e = p.subtract(ONE).divide(q);
+ byte[] ggen = Hex.decode("6767656E");
+
+ // 7. U = domain_parameter_seed || "ggen" || index || count.
+ byte[] U = new byte[seed.length + ggen.length + 1 + 2];
+ System.arraycopy(seed, 0, U, 0, seed.length);
+ System.arraycopy(ggen, 0, U, seed.length, ggen.length);
+ U[U.length - 3] = (byte)index;
+
+ byte[] w = new byte[d.getDigestSize()];
+ for (int count = 1; count < (1 << 16); ++count)
+ {
+ inc(U);
+ hash(d, U, w);
+ BigInteger W = new BigInteger(1, w);
+ BigInteger g = W.modPow(e, p);
+ if (g.compareTo(TWO) >= 0)
+ {
+ return g;
+ }
+ }
+
+ return null;
+ }
private static void hash(Digest d, byte[] input, byte[] output)
{
diff --git a/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java b/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java
new file mode 100644
index 00000000..ba841b8e
--- /dev/null
+++ b/src/main/java/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+public class DSAParameterGenerationParameters
+{
+ public static final int DIGITAL_SIGNATURE_USAGE = 1;
+ public static final int KEY_ESTABLISHMENT_USAGE = 2;
+
+ private final int l;
+ private final int n;
+ private final int usageIndex;
+ private final int certainty;
+ private final SecureRandom random;
+
+ /**
+ * Construct without a usage index, this will do a random construction of G.
+ *
+ * @param L desired length of prime P in bits (the effective key size).
+ * @param N desired length of prime Q in bits.
+ * @param certainty certainty level for prime number generation.
+ * @param random the source of randomness to use.
+ */
+ public DSAParameterGenerationParameters(
+ int L,
+ int N,
+ int certainty,
+ SecureRandom random)
+ {
+ this(L, N, certainty, random, -1);
+ }
+
+ /**
+ * Construct for a specific usage index - this has the effect of using verifiable canonical generation of G.
+ *
+ * @param L desired length of prime P in bits (the effective key size).
+ * @param N desired length of prime Q in bits.
+ * @param certainty certainty level for prime number generation.
+ * @param random the source of randomness to use.
+ * @param usageIndex a valid usage index.
+ */
+ public DSAParameterGenerationParameters(
+ int L,
+ int N,
+ int certainty,
+ SecureRandom random,
+ int usageIndex)
+ {
+ this.l = L;
+ this.n = N;
+ this.certainty = certainty;
+ this.usageIndex = usageIndex;
+ this.random = random;
+ }
+
+ public int getL()
+ {
+ return l;
+ }
+
+ public int getN()
+ {
+ return n;
+ }
+
+ public int getCertainty()
+ {
+ return certainty;
+ }
+
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ public int getUsageIndex()
+ {
+ return usageIndex;
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java b/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java
index 1cc4b93e..07d93d07 100644
--- a/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java
+++ b/src/main/java/org/bouncycastle/crypto/params/DSAValidationParameters.java
@@ -4,6 +4,7 @@ import org.bouncycastle.util.Arrays;
public class DSAValidationParameters
{
+ private int usageIndex;
private byte[] seed;
private int counter;
@@ -11,8 +12,17 @@ public class DSAValidationParameters
byte[] seed,
int counter)
{
+ this(seed, counter, -1);
+ }
+
+ public DSAValidationParameters(
+ byte[] seed,
+ int counter,
+ int usageIndex)
+ {
this.seed = seed;
this.counter = counter;
+ this.usageIndex = usageIndex;
}
public int getCounter()
@@ -25,6 +35,11 @@ public class DSAValidationParameters
return seed;
}
+ public int getUsageIndex()
+ {
+ return usageIndex;
+ }
+
public int hashCode()
{
return counter ^ Arrays.hashCode(seed);
diff --git a/src/test/java/org/bouncycastle/crypto/test/DSATest.java b/src/test/java/org/bouncycastle/crypto/test/DSATest.java
index 005ac521..2393e2d5 100644
--- a/src/test/java/org/bouncycastle/crypto/test/DSATest.java
+++ b/src/test/java/org/bouncycastle/crypto/test/DSATest.java
@@ -1,21 +1,27 @@
package org.bouncycastle.crypto.test;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import org.bouncycastle.crypto.digests.SHA224Digest;
+import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.generators.DSAKeyPairGenerator;
import org.bouncycastle.crypto.generators.DSAParametersGenerator;
import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
+import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
import org.bouncycastle.crypto.params.DSAParameters;
+import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
import org.bouncycastle.crypto.params.DSAValidationParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.DSASigner;
+import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.FixedSecureRandom;
import org.bouncycastle.util.test.SimpleTest;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
/**
* Test based on FIPS 186-2, Appendix 5, an example of DSA.
*/
@@ -92,6 +98,476 @@ public class DSATest
{
fail("verification fails");
}
+
+ dsa2Test1();
+ dsa2Test2();
+ dsa2Test3();
+ dsa2Test4();
+ }
+
+ private void dsa2Test1()
+ {
+ byte[] seed = Hex.decode("ED8BEE8D1CB89229D2903CBF0E51EE7377F48698");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator();
+
+ pGen.init(new DSAParameterGenerationParameters(1024, 160, 80, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 5)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("E950511EAB424B9A19A2AEB4E159B7844C589C4F", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "E0A67598CD1B763B" +
+ "C98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338" +
+ "FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3" +
+ "307DED2299A0EE606DF035177A239C34A912C202AA5F83B9" +
+ "C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440" +
+ "F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "D29D5121B0423C27" +
+ "69AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15" +
+ "C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A" +
+ "9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B" +
+ "76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA" +
+ "3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("D0EC4E50BB290A42E9E355C73D8809345DE2E139")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "25282217F5730501" +
+ "DD8DBA3EDFCF349AAFFEC20921128D70FAC44110332201BB" +
+ "A3F10986140CBB97C726938060473C8EC97B4731DB004293" +
+ "B5E730363609DF9780F8D883D8C4D41DED6A2F1E1BBBDC97" +
+ "9E1B9D6D3C940301F4E978D65B19041FCF1E8B518F5C0576" +
+ "C770FE5A7A485D8329EE2914A2DE1B5DA4A6128CEAB70F79", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("D0EC4E50BB290A42E9E355C73D8809345DE2E139", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("349C55648DCF992F3F33E8026CFAC87C1D2BA075"))));
+
+ byte[] msg = Hex.decode("A9993E364706816ABA3E25717850C26C9CD0D89D");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("636155AC9A4633B4665D179F9E4117DF68601F34", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("6C540B02D9D4852F89DF8CFC99963204F4347704", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+
+ }
+
+ private void dsa2Test2()
+ {
+ byte[] seed = Hex.decode("5AFCC1EFFC079A9CCA6ECA86D6E3CC3B18642D9BE1CC6207C84002A9");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA224Digest());
+
+ pGen.init(new DSAParameterGenerationParameters(2048, 224, 80, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 21)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "C196BA05AC29E1F9C3C72D56DFFC6154" +
+ "A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A06" +
+ "7CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
+ "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE6" +
+ "19ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1" +
+ "E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD9" +
+ "2D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
+ "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E" +
+ "5320121496DC65B3930E38047294FF877831A16D5228418D" +
+ "E8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A040" +
+ "2A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "A59A749A11242C58C894E9E5A91804E8"+
+ "FA0AC64B56288F8D47D51B1EDC4D65444FECA0111D78F35F"+
+ "C9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50"+
+ "48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B"+
+ "6E770409494B7FEE1DBB1E4B2BC2A53D4F893D418B715959"+
+ "2E4FFFDF6969E91D770DAEBD0B5CB14C00AD68EC7DC1E574"+
+ "5EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF"+
+ "D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E69"+
+ "5515B05BD412F5B8C2F4C77EE10DA48ABD53F5DD498927EE"+
+ "7B692BBBCDA2FB23A516C5B4533D73980B2A3B60E384ED20"+
+ "0AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "70035C9A3B225B258F16741F3941FBF0" +
+ "6F3D056CD7BD864604CBB5EE9DD85304EE8E8E4ABD5E9032" +
+ "11DDF25CE149075510ACE166970AFDC7DF552B7244F342FA" +
+ "02F7A621405B754909D757F97290E1FE5036E904CF593446" +
+ "0C046D95659821E1597ED9F2B1F0E20863A6BBD0CE74DACB" +
+ "A5D8C68A90B29C2157CDEDB82EC12B81EE3068F9BF5F7F34" +
+ "6ECA41ED174CCCD7D154FA4F42F80FFE1BF46AE9D8125DEB" +
+ "5B4BA08A72BDD86596DBEDDC9550FDD650C58F5AE5133509" +
+ "A702F79A31ECB490F7A3C5581631F7C5BE4FF7F9E9F27FA3" +
+ "90E47347AD1183509FED6FCF198BA9A71AB3335B4F38BE8D" +
+ "15496A00B6DC2263E20A5F6B662320A3A1EC033AA61E3B68", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("735959CC4463B8B440E407EECA8A473BF6A6D1FE657546F67D401F05"))));
+
+ byte[] msg = Hex.decode("23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("4400138D05F9639CAF54A583CAAF25D2B76D0C3EAD752CE17DBC85FE", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("874D4F12CB13B61732D398445698CFA9D92381D938AA57EE2C9327B3", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+ }
+
+ private void dsa2Test3()
+ {
+ byte[] seed = Hex.decode("4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
+
+ pGen.init(new DSAParameterGenerationParameters(2048, 256, 80, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 12)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "F56C2A7D366E3EBDEAA1891FD2A0D099" +
+ "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" +
+ "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" +
+ "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" +
+ "5909132627F51A0C866877E672E555342BDF9355347DBD43" +
+ "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" +
+ "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" +
+ "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" +
+ "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" +
+ "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" +
+ "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "8DC6CC814CAE4A1C05A3E186A6FE27EA" +
+ "BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1" +
+ "29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB" +
+ "6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2" +
+ "513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869" +
+ "7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0" +
+ "A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403" +
+ "45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8" +
+ "FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E" +
+ "428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC" +
+ "EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "2828003D7C747199143C370FDD07A286" +
+ "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" +
+ "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" +
+ "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" +
+ "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" +
+ "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" +
+ "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" +
+ "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" +
+ "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" +
+ "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" +
+ "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C"))));
+
+ byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("315C875DCD4850E948B8AC42824E9483A32D5BA5ABE0681B9B9448D444F2BE3C", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("89718D12E54A8D9ED066E4A55F7ED5A2229CD23B9A3CEE78F83ED6AA61F6BCB9", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
+ }
+
+ private void dsa2Test4()
+ {
+ byte[] seed = Hex.decode("193AFCA7C1E77B3C1ECC618C81322E47B8B8B997C9C83515C59CC446C2D9BD47");
+
+ DSAParametersGenerator pGen = new DSAParametersGenerator(new SHA256Digest());
+
+ pGen.init(new DSAParameterGenerationParameters(3072, 256, 80, new DSATestSecureRandom(seed)));
+
+ DSAParameters params = pGen.generateParameters();
+
+ DSAValidationParameters pv = params.getValidationParameters();
+
+ if (pv.getCounter() != 20)
+ {
+ fail("counter incorrect");
+ }
+
+ if (!Arrays.areEqual(seed, pv.getSeed()))
+ {
+ fail("seed incorrect");
+ }
+
+ if (!params.getQ().equals(new BigInteger("CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16)))
+ {
+ fail("Q incorrect");
+ }
+
+ if (!params.getP().equals(new BigInteger(
+ "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD610" +
+ "37E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE0" +
+ "5E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E" +
+ "5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
+ "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D" +
+ "3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E54" +
+ "2D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA63" +
+ "2C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
+ "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0E" +
+ "E6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0" +
+ "E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE0" +
+ "30D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
+ "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C56" +
+ "0EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A" +
+ "0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3" +
+ "D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16)))
+ {
+ fail("P incorrect");
+ }
+
+ if (!params.getG().equals(new BigInteger(
+ "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE" +
+ "3B7ACCC54D521E37F84A4BDD5B06B0970CC2D2BBB715F7B8" +
+ "2846F9A0C393914C792E6A923E2117AB805276A975AADB52" +
+ "61D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
+ "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A" +
+ "60126FEB2CF05DB8A7F0F09B3397F3937F2E90B9E5B9C9B6" +
+ "EFEF642BC48351C46FB171B9BFA9EF17A961CE96C7E7A7CC" +
+ "3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
+ "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B6" +
+ "7299E231F8BD90B39AC3AE3BE0C6B6CACEF8289A2E2873D5" +
+ "8E51E029CAFBD55E6841489AB66B5B4B9BA6E2F784660896" +
+ "AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
+ "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B98856" +
+ "7A88126B914D7828E2B63A6D7ED0747EC59E0E0A23CE7D8A" +
+ "74C1D2C2A7AFB6A29799620F00E11C33787F7DED3B30E1A2" +
+ "2D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16)))
+ {
+ fail("G incorrect");
+ }
+
+ DSAKeyPairGenerator kpGen = new DSAKeyPairGenerator();
+
+ kpGen.init(new DSAKeyGenerationParameters(new FixedSecureRandom(Hex.decode("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764")), params));
+
+ AsymmetricCipherKeyPair kp = kpGen.generateKeyPair();
+
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)kp.getPublic();
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)kp.getPrivate();
+
+ if (!pub.getY().equals(new BigInteger(
+ "8B891C8692D3DE875879390F2698B26FBECCA6B075535DCE" +
+ "6B0C862577F9FA0DEF6074E7A7624121224A595896ABD4CD" +
+ "A56B2CEFB942E025D2A4282FFAA98A48CDB47E1A6FCB5CFB" +
+ "393EF35AF9DF913102BB303C2B5C36C3F8FC04ED7B8B69FE" +
+ "FE0CF3E1FC05CFA713B3435B2656E913BA8874AEA9F93600" +
+ "6AEB448BCD005D18EC3562A33D04CF25C8D3D69844343442" +
+ "FA3DB7DE618C5E2DA064573E61E6D5581BFB694A23AC87FD" +
+ "5B52D62E954E1376DB8DDB524FFC0D469DF978792EE44173" +
+ "8E5DB05A7DC43E94C11A2E7A4FBE383071FA36D2A7EC8A93" +
+ "88FE1C4F79888A99D3B6105697C2556B79BB4D7E781CEBB3" +
+ "D4866AD825A5E830846072289FDBC941FA679CA82F5F78B7" +
+ "461B2404DB883D215F4E0676CF5493950AC5591697BFEA8D" +
+ "1EE6EC016B89BA51CAFB5F9C84C989FA117375E94578F28B" +
+ "E0B34CE0545DA46266FD77F62D8F2CEE92AB77012AFEBC11" +
+ "008985A821CD2D978C7E6FE7499D1AAF8DE632C21BB48CA5" +
+ "CBF9F31098FD3FD3854C49A65D9201744AACE540354974F9", 16)))
+ {
+ fail("Y value incorrect");
+ }
+
+ if (!priv.getX().equals(
+ new BigInteger("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764", 16)))
+ {
+ fail("X value incorrect");
+ }
+
+ DSASigner signer = new DSASigner();
+
+ signer.init(true, new ParametersWithRandom(kp.getPrivate(), new FixedSecureRandom(Hex.decode("A6902C1E6E3943C5628061588A8B007BCCEA91DBF12915483F04B24AB0678BEE"))));
+
+ byte[] msg = Hex.decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
+
+ BigInteger[] sig = signer.generateSignature(msg);
+
+ if (!sig[0].equals(new BigInteger("5F184E645A38BE8FB4A6871B6503A9D12924C7ABE04B71410066C2ECA6E3BE3E", 16)))
+ {
+ fail("R value incorrect");
+ }
+
+ if (!sig[1].equals(new BigInteger("91EB0C7BA3D4B9B60B825C3D9F2CADA8A2C9D7723267B033CBCDCF8803DB9C18", 16)))
+ {
+ fail("S value incorrect");
+ }
+
+ signer.init(false, kp.getPublic());
+
+ if (!signer.verifySignature(msg, sig[0], sig[1]))
+ {
+ fail("signature not verified");
+ }
}
public static void main(
@@ -99,4 +575,28 @@ public class DSATest
{
runTest(new DSATest());
}
+
+ private class DSATestSecureRandom
+ extends FixedSecureRandom
+ {
+ private boolean first = true;
+
+ public DSATestSecureRandom(byte[] value)
+ {
+ super(value);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ if (first)
+ {
+ super.nextBytes(bytes);
+ first = false;
+ }
+ else
+ {
+ bytes[bytes.length - 1] = 2;
+ }
+ }
+ }
}