summaryrefslogtreecommitdiff
path: root/gnu/java/security/key/dss/DSSKeyPairGenerator.java
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/java/security/key/dss/DSSKeyPairGenerator.java')
-rw-r--r--gnu/java/security/key/dss/DSSKeyPairGenerator.java360
1 files changed, 360 insertions, 0 deletions
diff --git a/gnu/java/security/key/dss/DSSKeyPairGenerator.java b/gnu/java/security/key/dss/DSSKeyPairGenerator.java
new file mode 100644
index 000000000..3f9c80625
--- /dev/null
+++ b/gnu/java/security/key/dss/DSSKeyPairGenerator.java
@@ -0,0 +1,360 @@
+/* DSSKeyPairGenerator.java --
+ Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.key.dss;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.Sha160;
+import gnu.java.security.key.IKeyPairGenerator;
+
+import java.io.PrintWriter;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.DSAParameterSpec;
+import java.util.Map;
+
+/**
+ * <p>A key-pair generator for asymetric keys to use in conjunction with the DSS
+ * (Digital Signature Standard).</p>
+ *
+ * References:<br>
+ * <a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital Signature
+ * Standard (DSS)</a>, Federal Information Processing Standards Publication 186.
+ * National Institute of Standards and Technology.
+ */
+public class DSSKeyPairGenerator implements IKeyPairGenerator
+{
+
+ // Debugging methods and variables
+ // -------------------------------------------------------------------------
+
+ private static final String NAME = "dss";
+
+ private static final boolean DEBUG = false;
+
+ private static final int debuglevel = 5;
+
+ private static final PrintWriter err = new PrintWriter(System.out, true);
+
+ private static void debug(String s)
+ {
+ err.println(">>> " + NAME + ": " + s);
+ }
+
+ // Constants and variables
+ // -------------------------------------------------------------------------
+
+ /** The BigInteger constant 2. */
+ private static final BigInteger TWO = new BigInteger("2");
+
+ /** Property name of the length (Integer) of the modulus (p) of a DSS key. */
+ public static final String MODULUS_LENGTH = "gnu.crypto.dss.L";
+
+ /** Property name of the Boolean indicating wether or not to use defaults. */
+ public static final String USE_DEFAULTS = "gnu.crypto.dss.use.defaults";
+
+ /**
+ * Property name of an optional {@link SecureRandom} instance to use. The
+ * default is to use a classloader singleton from {@link PRNG}.
+ */
+ public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dss.prng";
+
+ /**
+ * Property name of an optional {@link DSAParameterSpec} instance to use for
+ * this generator's <code>p</code>, <code>q</code>, and <code>g</code> values.
+ * The default is to generate these values or use pre-computed ones,
+ * depending on the value of the <code>USE_DEFAULTS</code> attribute.
+ */
+ public static final String DSS_PARAMETERS = "gnu.crypto.dss.params";
+
+ /** Default value for the modulus length. */
+ private static final int DEFAULT_MODULUS_LENGTH = 1024;
+
+ /** Initial SHS context. */
+ private static final int[] T_SHS = new int[] { 0x67452301, 0xEFCDAB89,
+ 0x98BADCFE, 0x10325476,
+ 0xC3D2E1F0 };
+
+ // from jdk1.3.1/docs/guide/security/CryptoSpec.html#AppB
+ public static final DSAParameterSpec KEY_PARAMS_512 = new DSAParameterSpec(
+ new BigInteger(
+ "fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae"
+ + "01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e17",
+ 16),
+ new BigInteger(
+ "962eddcc369cba8ebb260ee6b6a126d9346e38c5",
+ 16),
+ new BigInteger(
+ "678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e"
+ + "35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4",
+ 16));
+
+ public static final DSAParameterSpec KEY_PARAMS_768 = new DSAParameterSpec(
+ new BigInteger(
+ "e9e642599d355f37c97ffd3567120b8e25c9cd43e927b3a9670fbec5d8901419"
+ + "22d2c3b3ad2480093799869d1e846aab49fab0ad26d2ce6a22219d470bce7d77"
+ + "7d4a21fbe9c270b57f607002f3cef8393694cf45ee3688c11a8c56ab127a3daf",
+ 16),
+ new BigInteger(
+ "9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511",
+ 16),
+ new BigInteger(
+ "30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5facbaecbe95f190aa7a31d23c4"
+ + "dbbcbe06174544401a5b2c020965d8c2bd2171d3668445771f74ba084d2029d8"
+ + "3c1c158547f3a9f1a2715be23d51ae4d3e5a1f6a7064f316933a346d3f529252",
+ 16));
+
+ public static final DSAParameterSpec KEY_PARAMS_1024 = new DSAParameterSpec(
+ new BigInteger(
+ "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669"
+ + "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7"
+ + "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb"
+ + "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7",
+ 16),
+ new BigInteger(
+ "9760508f15230bccb292b982a2eb840bf0581cf5",
+ 16),
+ new BigInteger(
+ "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267"
+ + "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1"
+ + "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b"
+ + "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a",
+ 16));
+
+ private static final BigInteger TWO_POW_160 = TWO.pow(160);
+
+ /** The length of the modulus of DSS keys generated by this instance. */
+ private int L;
+
+ /** The optional {@link SecureRandom} instance to use. */
+ private SecureRandom rnd = null;
+
+ private BigInteger seed;
+
+ private BigInteger counter;
+
+ private BigInteger p;
+
+ private BigInteger q;
+
+ private BigInteger e;
+
+ private BigInteger g;
+
+ private BigInteger XKEY;
+
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ // implicit 0-arguments constructor
+
+ // Class methods
+ // -------------------------------------------------------------------------
+
+ // Instance methods
+ // -------------------------------------------------------------------------
+
+ // gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
+
+ public String name()
+ {
+ return Registry.DSS_KPG;
+ }
+
+ /**
+ * <p>Configures this instance.</p>
+ *
+ * @param attributes the map of name/value pairs to use.
+ * @exception IllegalArgumentException if the designated MODULUS_LENGTH
+ * value is not greater than 512, less than 1024 and not of the form
+ * <code>512 + 64j</code>.
+ */
+ public void setup(Map attributes)
+ {
+ // find out the modulus length
+ Integer l = (Integer) attributes.get(MODULUS_LENGTH);
+ L = (l == null ? DEFAULT_MODULUS_LENGTH : l.intValue());
+ if ((L % 64) != 0 || L < 512 || L > 1024)
+ throw new IllegalArgumentException(MODULUS_LENGTH);
+
+ // should we use the default pre-computed params?
+ Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS);
+ if (useDefaults == null)
+ {
+ useDefaults = Boolean.TRUE;
+ }
+
+ // are we given a set of DSA params or we shall use/generate our own?
+ DSAParameterSpec params = (DSAParameterSpec) attributes.get(DSS_PARAMETERS);
+ if (params != null)
+ {
+ p = params.getP();
+ q = params.getQ();
+ g = params.getG();
+ }
+ else if (useDefaults.equals(Boolean.TRUE))
+ {
+ switch (L)
+ {
+ case 512:
+ p = KEY_PARAMS_512.getP();
+ q = KEY_PARAMS_512.getQ();
+ g = KEY_PARAMS_512.getG();
+ break;
+ case 768:
+ p = KEY_PARAMS_768.getP();
+ q = KEY_PARAMS_768.getQ();
+ g = KEY_PARAMS_768.getG();
+ break;
+ case 1024:
+ p = KEY_PARAMS_1024.getP();
+ q = KEY_PARAMS_1024.getQ();
+ g = KEY_PARAMS_1024.getG();
+ break;
+ default:
+ p = null;
+ q = null;
+ g = null;
+ }
+ }
+ else
+ {
+ p = null;
+ q = null;
+ g = null;
+ }
+
+ // do we have a SecureRandom, or should we use our own?
+ rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
+
+ // set the seed-key
+ byte[] kb = new byte[20]; // we need 160 bits of randomness
+ nextRandomBytes(kb);
+ XKEY = new BigInteger(1, kb).setBit(159).setBit(0);
+ }
+
+ public KeyPair generate()
+ {
+ if (p == null)
+ {
+ BigInteger[] params = new FIPS186(L, rnd).generateParameters();
+ seed = params[FIPS186.DSA_PARAMS_SEED];
+ counter = params[FIPS186.DSA_PARAMS_COUNTER];
+ q = params[FIPS186.DSA_PARAMS_Q];
+ p = params[FIPS186.DSA_PARAMS_P];
+ e = params[FIPS186.DSA_PARAMS_E];
+ g = params[FIPS186.DSA_PARAMS_G];
+ if (DEBUG && debuglevel > 0)
+ {
+ debug("seed: " + seed.toString(16));
+ debug("counter: " + counter.intValue());
+ debug("q: " + q.toString(16));
+ debug("p: " + p.toString(16));
+ debug("e: " + e.toString(16));
+ debug("g: " + g.toString(16));
+ }
+ }
+
+ BigInteger x = nextX();
+ BigInteger y = g.modPow(x, p);
+
+ PublicKey pubK = new DSSPublicKey(p, q, g, y);
+ PrivateKey secK = new DSSPrivateKey(p, q, g, x);
+
+ return new KeyPair(pubK, secK);
+ }
+
+ // Other instance methods --------------------------------------------------
+
+ /**
+ * <p>This method applies the following algorithm described in 3.1 of
+ * FIPS-186:</p>
+ *
+ * <ol>
+ * <li>XSEED = optional user input.</li>
+ * <li>XVAL = (XKEY + XSEED) mod 2<sup>b</sup>.</li>
+ * <li>x = G(t, XVAL) mod q.</li>
+ * <li>XKEY = (1 + XKEY + x) mod 2<sup>b</sup>.</li>
+ * </ol>
+ *
+ * <p>Where <code>b</code> is the length of a secret b-bit seed-key (XKEY).</p>
+ *
+ * <p>Note that in this implementation, XSEED, the optional user input, is
+ * always zero.</p>
+ */
+ private synchronized BigInteger nextX()
+ {
+ byte[] xk = XKEY.toByteArray();
+ byte[] in = new byte[64]; // 512-bit block for SHS
+ System.arraycopy(xk, 0, in, 0, xk.length);
+
+ int[] H = Sha160.G(T_SHS[0], T_SHS[1], T_SHS[2], T_SHS[3], T_SHS[4], in, 0);
+ byte[] h = new byte[20];
+ for (int i = 0, j = 0; i < 5; i++)
+ {
+ h[j++] = (byte) (H[i] >>> 24);
+ h[j++] = (byte) (H[i] >>> 16);
+ h[j++] = (byte) (H[i] >>> 8);
+ h[j++] = (byte) H[i];
+ }
+ BigInteger result = new BigInteger(1, h).mod(q);
+ XKEY = XKEY.add(result).add(BigInteger.ONE).mod(TWO_POW_160);
+
+ return result;
+ }
+
+ /**
+ * <p>Fills the designated byte array with random data.</p>
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ {
+ rnd.nextBytes(buffer);
+ }
+ else
+ {
+ new SecureRandom ().nextBytes(buffer);
+ }
+ }
+}