Imported GNU Classpath 0.90
Imported GNU Classpath 0.90
* scripts/makemake.tcl: Set gnu/java/awt/peer/swing to ignore.
* gnu/classpath/jdwp/VMFrame.java (SIZE): New constant.
* java/lang/VMCompiler.java: Use gnu.java.security.hash.MD5.
* java/lang/Math.java: New override file.
* java/lang/Character.java: Merged from Classpath.
(start, end): Now 'int's.
(canonicalName): New field.
(CANONICAL_NAME, NO_SPACES_NAME, CONSTANT_NAME): New constants.
(UnicodeBlock): Added argument.
(of): New overload.
(forName): New method.
Updated unicode blocks.
(sets): Updated.
* sources.am: Regenerated.
* Makefile.in: Likewise.
From-SVN: r111942
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
/* DSSKey.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.util.FormatUtil;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.Key;
|
||||
import java.security.interfaces.DSAKey;
|
||||
import java.security.interfaces.DSAParams;
|
||||
import java.security.spec.DSAParameterSpec;
|
||||
|
||||
/**
|
||||
* <p>A base asbtract class for both public and private DSS (Digital Signature
|
||||
* Standard) keys. It encapsulates the three DSS numbers: <code>p</code>,
|
||||
* <code>q</code> and <code>g</code>.</p>
|
||||
*
|
||||
* <p>According to the JDK, cryptographic <i>Keys</i> all have a <i>format</i>.
|
||||
* The format used in this implementation is called <i>Raw</i>, and basically
|
||||
* consists of the raw byte sequences of algorithm parameters. The exact order
|
||||
* of the byte sequences and the implementation details are given in each of
|
||||
* the relevant <code>getEncoded()</code> methods of each of the private and
|
||||
* public keys.</p>
|
||||
*
|
||||
* @version $Revision: 1.4 $
|
||||
* @see DSSPrivateKey#getEncoded
|
||||
* @see DSSPublicKey#getEncoded
|
||||
*/
|
||||
public abstract class DSSKey implements Key, DSAKey
|
||||
{
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A prime modulus, where <code>2<sup>L-1</sup> < p < 2<sup>L</sup></code>
|
||||
* for <code>512 <= L <= 1024</code> and <code>L</code> a multiple of
|
||||
* <code>64</code>.
|
||||
*/
|
||||
protected final BigInteger p;
|
||||
|
||||
/**
|
||||
* A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup> < q
|
||||
* < 2<sup>160</sup></code>.
|
||||
*/
|
||||
protected final BigInteger q;
|
||||
|
||||
/**
|
||||
* <code>g = h<sup>(p-1)</sup>/q mod p</code>, where <code>h</code> is any
|
||||
* integer with <code>1 < h < p - 1</code> such that <code>h<sup>
|
||||
* (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order <code>q mod p
|
||||
* </code>).
|
||||
*/
|
||||
protected final BigInteger g;
|
||||
|
||||
/**
|
||||
* Identifier of the default encoding format to use when externalizing the
|
||||
* key material.
|
||||
*/
|
||||
protected final int defaultFormat;
|
||||
|
||||
// Constructor(s)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Trivial protected constructor.
|
||||
*
|
||||
* @param defaultFormat the identifier of the encoding format to use by
|
||||
* default when externalizing the key.
|
||||
* @param p the DSS parameter <code>p</code>.
|
||||
* @param q the DSS parameter <code>q</code>.
|
||||
* @param g the DSS parameter <code>g</code>.
|
||||
*/
|
||||
protected DSSKey(int defaultFormat, BigInteger p, BigInteger q, BigInteger g)
|
||||
{
|
||||
super();
|
||||
|
||||
this.defaultFormat = defaultFormat <= 0 ? Registry.RAW_ENCODING_ID
|
||||
: defaultFormat;
|
||||
this.p = p;
|
||||
this.q = q;
|
||||
this.g = g;
|
||||
}
|
||||
|
||||
// Class methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Instance methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// java.security.interfaces.DSAKey interface implementation ----------------
|
||||
|
||||
public DSAParams getParams()
|
||||
{
|
||||
return new DSAParameterSpec(p, q, g);
|
||||
}
|
||||
|
||||
// java.security.Key interface implementation ------------------------------
|
||||
|
||||
public String getAlgorithm()
|
||||
{
|
||||
return Registry.DSS_KPG;
|
||||
}
|
||||
|
||||
/** @deprecated see getEncoded(int). */
|
||||
public byte[] getEncoded()
|
||||
{
|
||||
return getEncoded(defaultFormat);
|
||||
}
|
||||
|
||||
public String getFormat()
|
||||
{
|
||||
return FormatUtil.getEncodingShortName(defaultFormat);
|
||||
}
|
||||
|
||||
// Other instance methods --------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Returns <code>true</code> if the designated object is an instance of
|
||||
* {@link DSAKey} and has the same DSS (Digital Signature Standard) parameter
|
||||
* values as this one.</p>
|
||||
*
|
||||
* @param obj the other non-null DSS key to compare to.
|
||||
* @return <code>true</code> if the designated object is of the same type and
|
||||
* value as this one.
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof DSAKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DSAKey that = (DSAKey) obj;
|
||||
return p.equals(that.getParams().getP())
|
||||
&& q.equals(that.getParams().getQ())
|
||||
&& g.equals(that.getParams().getG());
|
||||
}
|
||||
|
||||
// abstract methods to be implemented by subclasses ------------------------
|
||||
|
||||
public abstract byte[] getEncoded(int format);
|
||||
}
|
||||
@@ -0,0 +1,445 @@
|
||||
/* 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 gnu.java.security.util.PRNG;
|
||||
|
||||
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 default pre-
|
||||
* computed values of <code>p</code>, <code>q</code> and <code>g</code> for
|
||||
* a given modulus length. The ultimate behaviour of this generator with
|
||||
* regard to using pre-computed parameter sets will depend on the value of
|
||||
* this property and of the following one {@link #STRICT_DEFAULTS}:
|
||||
*
|
||||
* <ol>
|
||||
* <li>If this property is {@link Boolean#FALSE} then this generator
|
||||
* will accept being setup for generating parameters for any modulus length
|
||||
* provided the modulus length is between <code>512</code> and
|
||||
* <code>1024</code>, and is of the form <code>512 + 64 * n</code>. In
|
||||
* addition, a new paramter set will always be generated; i.e. no pre-
|
||||
* computed values are used.</li>
|
||||
*
|
||||
* <li>If this property is {@link Boolean#TRUE} and the value of
|
||||
* {@link #STRICT_DEFAULTS} is also {@link Boolean#TRUE} then this generator
|
||||
* will only accept being setup for generating parameters for modulus
|
||||
* lengths of <code>512</code>, <code>768</code> and <code>1024</code>. Any
|
||||
* other value, of the modulus length, even if between <code>512</code> and
|
||||
* <code>1024</code>, and of the form <code>512 + 64 * n</code>, will cause
|
||||
* an {@link IllegalArgumentException} to be thrown. When those modulus
|
||||
* length (<code>512</code>, <code>768</code>, and <code>1024</code>) are
|
||||
* specified, the paramter set is always the same.</li>
|
||||
*
|
||||
* <li>Finally, if this property is {@link Boolean#TRUE} and the value of
|
||||
* {@link #STRICT_DEFAULTS} is {@link Boolean#FALSE} then this generator
|
||||
* will behave as in point 1 above, except that it will use pre-computed
|
||||
* values when possible; i.e. the modulus length is one of <code>512</code>,
|
||||
* <code>768</code>, or <code>1024</code>.</li>
|
||||
* </ol>
|
||||
*
|
||||
* The default value of this property is {@link Boolean#TRUE}.
|
||||
*/
|
||||
public static final String USE_DEFAULTS = "gnu.crypto.dss.use.defaults";
|
||||
|
||||
/**
|
||||
* Property name of the Boolean indicating wether or not to generate new
|
||||
* parameters, even if the modulus length <i>L</i> is not one of the pre-
|
||||
* computed defaults (value {@link Boolean#FALSE}), or throw an exception
|
||||
* (value {@link Boolean#TRUE}) -- the exception in this case is an
|
||||
* {@link IllegalArgumentException}. The default value for this property is
|
||||
* {@link Boolean#FALSE}. The ultimate behaviour of this generator will
|
||||
* depend on the values of this and {@link #USE_DEFAULTS} properties -- see
|
||||
* {@link #USE_DEFAULTS} for more information.
|
||||
*/
|
||||
public static final String STRICT_DEFAULTS = "gnu.crypto.dss.strict.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";
|
||||
|
||||
/**
|
||||
* Property name of the preferred encoding format to use when externalizing
|
||||
* generated instance of key-pairs from this generator. The property is taken
|
||||
* to be an {@link Integer} that encapsulates an encoding format identifier.
|
||||
*/
|
||||
public static final String PREFERRED_ENCODING_FORMAT = "gnu.crypto.dss.encoding";
|
||||
|
||||
/** Default value for the modulus length. */
|
||||
public static final int DEFAULT_MODULUS_LENGTH = 1024;
|
||||
|
||||
/** Default encoding format to use when none was specified. */
|
||||
private static final int DEFAULT_ENCODING_FORMAT = Registry.RAW_ENCODING_ID;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Our default source of randomness. */
|
||||
private PRNG prng = null;
|
||||
|
||||
/** Preferred encoding format of generated keys. */
|
||||
private int preferredFormat;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
Boolean strictDefaults = (Boolean) attributes.get(STRICT_DEFAULTS);
|
||||
if (strictDefaults == null)
|
||||
strictDefaults = Boolean.FALSE;
|
||||
|
||||
// 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:
|
||||
if (strictDefaults.equals(Boolean.TRUE))
|
||||
throw new IllegalArgumentException(
|
||||
"Does not provide default parameters for " + L
|
||||
+ "-bit modulus length");
|
||||
else
|
||||
{
|
||||
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);
|
||||
|
||||
// what is the preferred encoding format
|
||||
Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
|
||||
preferredFormat = formatID == null
|
||||
? DEFAULT_ENCODING_FORMAT
|
||||
: formatID.intValue();
|
||||
|
||||
// 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(preferredFormat, p, q, g, y);
|
||||
PrivateKey secK = new DSSPrivateKey(preferredFormat, 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
|
||||
getDefaultPRNG().nextBytes(buffer);
|
||||
}
|
||||
|
||||
private PRNG getDefaultPRNG()
|
||||
{
|
||||
if (prng == null)
|
||||
prng = PRNG.getInstance();
|
||||
|
||||
return prng;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/* DSSKeyPairPKCS8Codec.java -- PKCS#8 Encoding/Decoding handler
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is 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, 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; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, 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.OID;
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.der.DER;
|
||||
import gnu.java.security.der.DERReader;
|
||||
import gnu.java.security.der.DERValue;
|
||||
import gnu.java.security.der.DERWriter;
|
||||
import gnu.java.security.key.IKeyPairCodec;
|
||||
import gnu.java.security.util.DerUtil;
|
||||
import gnu.java.security.util.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* An implementation of an {@link IKeyPairCodec} that knows how to encode /
|
||||
* decode PKCS#8 ASN.1 external representation of DSS private keys.
|
||||
*
|
||||
* @author Casey Marshall (rsdio@metastatic.org)
|
||||
*/
|
||||
public class DSSKeyPairPKCS8Codec
|
||||
implements IKeyPairCodec
|
||||
{
|
||||
private static final OID DSA_ALG_OID = new OID(Registry.DSA_OID_STRING);
|
||||
|
||||
// implicit 0-arguments constructor
|
||||
|
||||
public int getFormatID()
|
||||
{
|
||||
return PKCS8_FORMAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParameterException ALWAYS.
|
||||
*/
|
||||
public byte[] encodePublicKey(PublicKey key)
|
||||
{
|
||||
throw new InvalidParameterException("Wrong format for public keys");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PKCS#8 ASN.1 <i>PrivateKeyInfo</i> representation of a DSA
|
||||
* private key. The ASN.1 specification is as follows:
|
||||
*
|
||||
* <pre>
|
||||
* PrivateKeyInfo ::= SEQUENCE {
|
||||
* version INTEGER, -- MUST be 0
|
||||
* privateKeyAlgorithm AlgorithmIdentifier,
|
||||
* privateKey OCTET STRING
|
||||
* }
|
||||
*
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL
|
||||
* }
|
||||
*
|
||||
* DssParams ::= SEQUENCE {
|
||||
* p INTEGER,
|
||||
* q INTEGER,
|
||||
* g INTEGER
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return the DER encoded form of the ASN.1 representation of the
|
||||
* <i>PrivateKeyInfo</i> field in an X.509 certificate.
|
||||
* @throw InvalidParameterException if an error occurs during the marshalling
|
||||
* process.
|
||||
*/
|
||||
public byte[] encodePrivateKey(PrivateKey key)
|
||||
{
|
||||
if (! (key instanceof DSSPrivateKey))
|
||||
throw new InvalidParameterException("Wrong key type");
|
||||
|
||||
DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
|
||||
|
||||
DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
|
||||
|
||||
DSSPrivateKey pk = (DSSPrivateKey) key;
|
||||
BigInteger p = pk.getParams().getP();
|
||||
BigInteger q = pk.getParams().getQ();
|
||||
BigInteger g = pk.getParams().getG();
|
||||
BigInteger x = pk.getX();
|
||||
|
||||
ArrayList params = new ArrayList(3);
|
||||
params.add(new DERValue(DER.INTEGER, p));
|
||||
params.add(new DERValue(DER.INTEGER, q));
|
||||
params.add(new DERValue(DER.INTEGER, g));
|
||||
DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
|
||||
|
||||
ArrayList algorithmID = new ArrayList(2);
|
||||
algorithmID.add(derOID);
|
||||
algorithmID.add(derParams);
|
||||
DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
|
||||
algorithmID);
|
||||
|
||||
DERValue derPrivateKey = new DERValue(DER.OCTET_STRING, Util.trim(x));
|
||||
|
||||
ArrayList pki = new ArrayList(3);
|
||||
pki.add(derVersion);
|
||||
pki.add(derAlgorithmID);
|
||||
pki.add(derPrivateKey);
|
||||
DERValue derPKI = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, pki);
|
||||
|
||||
byte[] result;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
DERWriter.write(baos, derPKI);
|
||||
result = baos.toByteArray();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
InvalidParameterException y = new InvalidParameterException();
|
||||
y.initCause(e);
|
||||
throw y;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParameterException ALWAYS.
|
||||
*/
|
||||
public PublicKey decodePublicKey(byte[] input)
|
||||
{
|
||||
throw new InvalidParameterException("Wrong format for public keys");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param input the byte array to unmarshall into a valid DSS
|
||||
* {@link PrivateKey} instance. MUST NOT be null.
|
||||
* @return a new instance of a {@link DSSPrivateKey} decoded from the
|
||||
* <i>PrivateKeyInfo</i> material fed as <code>input</code>.
|
||||
* @throw InvalidParameterException if an exception occurs during the
|
||||
* unmarshalling process.
|
||||
*/
|
||||
public PrivateKey decodePrivateKey(byte[] input)
|
||||
{
|
||||
if (input == null)
|
||||
throw new InvalidParameterException("Input bytes MUST NOT be null");
|
||||
|
||||
BigInteger version, p, q, g, x;
|
||||
DERReader der = new DERReader(input);
|
||||
try
|
||||
{
|
||||
DERValue derPKI = der.read();
|
||||
DerUtil.checkIsConstructed(derPKI, "Wrong PrivateKeyInfo field");
|
||||
|
||||
DERValue derVersion = der.read();
|
||||
if (! (derVersion.getValue() instanceof BigInteger))
|
||||
throw new InvalidParameterException("Wrong Version field");
|
||||
|
||||
version = (BigInteger) derVersion.getValue();
|
||||
if (version.compareTo(BigInteger.ZERO) != 0)
|
||||
throw new InvalidParameterException("Unexpected Version: " + version);
|
||||
|
||||
DERValue derAlgoritmID = der.read();
|
||||
DerUtil.checkIsConstructed(derAlgoritmID, "Wrong AlgorithmIdentifier field");
|
||||
|
||||
DERValue derOID = der.read();
|
||||
OID algOID = (OID) derOID.getValue();
|
||||
if (! algOID.equals(DSA_ALG_OID))
|
||||
throw new InvalidParameterException("Unexpected OID: " + algOID);
|
||||
|
||||
DERValue derParams = der.read();
|
||||
DerUtil.checkIsConstructed(derParams, "Wrong DSS Parameters field");
|
||||
|
||||
DERValue val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong P field");
|
||||
p = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong Q field");
|
||||
q = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong G field");
|
||||
g = (BigInteger) val.getValue();
|
||||
|
||||
val = der.read();
|
||||
byte[] xBytes = (byte[]) val.getValue();
|
||||
x = new BigInteger(1, xBytes);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
InvalidParameterException y = new InvalidParameterException();
|
||||
y.initCause(e);
|
||||
throw y;
|
||||
}
|
||||
|
||||
return new DSSPrivateKey(Registry.PKCS8_ENCODING_ID, p, q, g, x);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,383 @@
|
||||
/* DSSKeyPairRawCodec.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.key.IKeyPairCodec;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
/**
|
||||
* <p>An object that implements the {@link IKeyPairCodec} operations for the
|
||||
* <i>Raw</i> format to use with DSS keypairs.</p>
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
public class DSSKeyPairRawCodec implements IKeyPairCodec
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Constructor(s)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// implicit 0-arguments constructor
|
||||
|
||||
// Class methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Instance methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// gnu.crypto.keys.IKeyPairCodec interface implementation ------------------
|
||||
|
||||
public int getFormatID()
|
||||
{
|
||||
return RAW_FORMAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the encoded form of the designated DSS (Digital Signature
|
||||
* Standard) public key according to the <i>Raw</i> format supported by
|
||||
* this library.</p>
|
||||
*
|
||||
* <p>The <i>Raw</i> format for a DSA public key, in this implementation, is
|
||||
* a byte sequence consisting of the following:</p>
|
||||
* <ol>
|
||||
* <li>4-byte magic consisting of the value of the literal
|
||||
* {@link Registry#MAGIC_RAW_DSS_PUBLIC_KEY},<li>
|
||||
* <li>1-byte version consisting of the constant: 0x01,</li>
|
||||
* <li>4-byte count of following bytes representing the DSA parameter
|
||||
* <code>p</code> in internet order,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the DSA parameter
|
||||
* <code>p</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the DSA parameter
|
||||
* <code>q</code>,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the DSA parameter
|
||||
* <code>q</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the DSA parameter
|
||||
* <code>g</code>,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the DSA parameter
|
||||
* <code>g</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the DSA parameter
|
||||
* <code>y</code>,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the DSA parameter
|
||||
* <code>y</code>,</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param key the key to encode.
|
||||
* @return the <i>Raw</i> format encoding of the designated key.
|
||||
* @throws IllegalArgumentException if the designated key is not a DSS
|
||||
* (Digital Signature Standard) one.
|
||||
* @see Registry#MAGIC_RAW_DSS_PUBLIC_KEY
|
||||
*/
|
||||
public byte[] encodePublicKey(PublicKey key)
|
||||
{
|
||||
if (!(key instanceof DSSPublicKey))
|
||||
{
|
||||
throw new IllegalArgumentException("key");
|
||||
}
|
||||
|
||||
DSSPublicKey dssKey = (DSSPublicKey) key;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
// magic
|
||||
baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0]);
|
||||
baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[1]);
|
||||
baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[2]);
|
||||
baos.write(Registry.MAGIC_RAW_DSS_PUBLIC_KEY[3]);
|
||||
|
||||
// version
|
||||
baos.write(0x01);
|
||||
|
||||
// p
|
||||
byte[] buffer = dssKey.getParams().getP().toByteArray();
|
||||
int length = buffer.length;
|
||||
baos.write(length >>> 24);
|
||||
baos.write((length >>> 16) & 0xFF);
|
||||
baos.write((length >>> 8) & 0xFF);
|
||||
baos.write(length & 0xFF);
|
||||
baos.write(buffer, 0, length);
|
||||
|
||||
// q
|
||||
buffer = dssKey.getParams().getQ().toByteArray();
|
||||
length = buffer.length;
|
||||
baos.write(length >>> 24);
|
||||
baos.write((length >>> 16) & 0xFF);
|
||||
baos.write((length >>> 8) & 0xFF);
|
||||
baos.write(length & 0xFF);
|
||||
baos.write(buffer, 0, length);
|
||||
|
||||
// g
|
||||
buffer = dssKey.getParams().getG().toByteArray();
|
||||
length = buffer.length;
|
||||
baos.write(length >>> 24);
|
||||
baos.write((length >>> 16) & 0xFF);
|
||||
baos.write((length >>> 8) & 0xFF);
|
||||
baos.write(length & 0xFF);
|
||||
baos.write(buffer, 0, length);
|
||||
|
||||
// y
|
||||
buffer = dssKey.getY().toByteArray();
|
||||
length = buffer.length;
|
||||
baos.write(length >>> 24);
|
||||
baos.write((length >>> 16) & 0xFF);
|
||||
baos.write((length >>> 8) & 0xFF);
|
||||
baos.write(length & 0xFF);
|
||||
baos.write(buffer, 0, length);
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public PublicKey decodePublicKey(byte[] k)
|
||||
{
|
||||
// magic
|
||||
if (k[0] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0]
|
||||
|| k[1] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[1]
|
||||
|| k[2] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[2]
|
||||
|| k[3] != Registry.MAGIC_RAW_DSS_PUBLIC_KEY[3])
|
||||
{
|
||||
throw new IllegalArgumentException("magic");
|
||||
}
|
||||
|
||||
// version
|
||||
if (k[4] != 0x01)
|
||||
{
|
||||
throw new IllegalArgumentException("version");
|
||||
}
|
||||
int i = 5;
|
||||
|
||||
int l;
|
||||
byte[] buffer;
|
||||
|
||||
// p
|
||||
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
|
||||
| (k[i++] & 0xFF);
|
||||
buffer = new byte[l];
|
||||
System.arraycopy(k, i, buffer, 0, l);
|
||||
i += l;
|
||||
BigInteger p = new BigInteger(1, buffer);
|
||||
|
||||
// q
|
||||
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
|
||||
| (k[i++] & 0xFF);
|
||||
buffer = new byte[l];
|
||||
System.arraycopy(k, i, buffer, 0, l);
|
||||
i += l;
|
||||
BigInteger q = new BigInteger(1, buffer);
|
||||
|
||||
// g
|
||||
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
|
||||
| (k[i++] & 0xFF);
|
||||
buffer = new byte[l];
|
||||
System.arraycopy(k, i, buffer, 0, l);
|
||||
i += l;
|
||||
BigInteger g = new BigInteger(1, buffer);
|
||||
|
||||
// y
|
||||
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
|
||||
| (k[i++] & 0xFF);
|
||||
buffer = new byte[l];
|
||||
System.arraycopy(k, i, buffer, 0, l);
|
||||
i += l;
|
||||
BigInteger y = new BigInteger(1, buffer);
|
||||
|
||||
return new DSSPublicKey(p, q, g, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the encoded form of the designated DSS (Digital Signature
|
||||
* Standard) private key according to the <i>Raw</i> format supported by
|
||||
* this library.</p>
|
||||
*
|
||||
* <p>The <i>Raw</i> format for a DSA private key, in this implementation, is
|
||||
* a byte sequence consisting of the following:</p>
|
||||
* <ol>
|
||||
* <li>4-byte magic consisting of the value of the literal
|
||||
* {@link Registry#MAGIC_RAW_DSS_PRIVATE_KEY},<li>
|
||||
* <li>1-byte version consisting of the constant: 0x01,</li>
|
||||
* <li>4-byte count of following bytes representing the DSA parameter
|
||||
* <code>p</code> in internet order,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the DSA parameter
|
||||
* <code>p</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the DSA parameter
|
||||
* <code>q</code>,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the DSA parameter
|
||||
* <code>q</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the DSA parameter
|
||||
* <code>g</code>,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the DSA parameter
|
||||
* <code>g</code>,</li>
|
||||
* <li>4-byte count of following bytes representing the DSA parameter
|
||||
* <code>x</code>,</li>
|
||||
* <li>n-bytes representation of a {@link BigInteger} obtained by invoking
|
||||
* the <code>toByteArray()</code> method on the DSA parameter
|
||||
* <code>x</code>,</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param key the key to encode.
|
||||
* @return the <i>Raw</i> format encoding of the designated key.
|
||||
* @throws IllegalArgumentException if the designated key is not a DSS
|
||||
* (Digital Signature Standard) one.
|
||||
*/
|
||||
public byte[] encodePrivateKey(PrivateKey key)
|
||||
{
|
||||
if (!(key instanceof DSSPrivateKey))
|
||||
{
|
||||
throw new IllegalArgumentException("key");
|
||||
}
|
||||
|
||||
DSSPrivateKey dssKey = (DSSPrivateKey) key;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
// magic
|
||||
baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0]);
|
||||
baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[1]);
|
||||
baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[2]);
|
||||
baos.write(Registry.MAGIC_RAW_DSS_PRIVATE_KEY[3]);
|
||||
|
||||
// version
|
||||
baos.write(0x01);
|
||||
|
||||
// p
|
||||
byte[] buffer = dssKey.getParams().getP().toByteArray();
|
||||
int length = buffer.length;
|
||||
baos.write(length >>> 24);
|
||||
baos.write((length >>> 16) & 0xFF);
|
||||
baos.write((length >>> 8) & 0xFF);
|
||||
baos.write(length & 0xFF);
|
||||
baos.write(buffer, 0, length);
|
||||
|
||||
// q
|
||||
buffer = dssKey.getParams().getQ().toByteArray();
|
||||
length = buffer.length;
|
||||
baos.write(length >>> 24);
|
||||
baos.write((length >>> 16) & 0xFF);
|
||||
baos.write((length >>> 8) & 0xFF);
|
||||
baos.write(length & 0xFF);
|
||||
baos.write(buffer, 0, length);
|
||||
|
||||
// g
|
||||
buffer = dssKey.getParams().getG().toByteArray();
|
||||
length = buffer.length;
|
||||
baos.write(length >>> 24);
|
||||
baos.write((length >>> 16) & 0xFF);
|
||||
baos.write((length >>> 8) & 0xFF);
|
||||
baos.write(length & 0xFF);
|
||||
baos.write(buffer, 0, length);
|
||||
|
||||
// x
|
||||
buffer = dssKey.getX().toByteArray();
|
||||
length = buffer.length;
|
||||
baos.write(length >>> 24);
|
||||
baos.write((length >>> 16) & 0xFF);
|
||||
baos.write((length >>> 8) & 0xFF);
|
||||
baos.write(length & 0xFF);
|
||||
baos.write(buffer, 0, length);
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public PrivateKey decodePrivateKey(byte[] k)
|
||||
{
|
||||
// magic
|
||||
if (k[0] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0]
|
||||
|| k[1] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[1]
|
||||
|| k[2] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[2]
|
||||
|| k[3] != Registry.MAGIC_RAW_DSS_PRIVATE_KEY[3])
|
||||
{
|
||||
throw new IllegalArgumentException("magic");
|
||||
}
|
||||
|
||||
// version
|
||||
if (k[4] != 0x01)
|
||||
{
|
||||
throw new IllegalArgumentException("version");
|
||||
}
|
||||
int i = 5;
|
||||
|
||||
int l;
|
||||
byte[] buffer;
|
||||
|
||||
// p
|
||||
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
|
||||
| (k[i++] & 0xFF);
|
||||
buffer = new byte[l];
|
||||
System.arraycopy(k, i, buffer, 0, l);
|
||||
i += l;
|
||||
BigInteger p = new BigInteger(1, buffer);
|
||||
|
||||
// q
|
||||
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
|
||||
| (k[i++] & 0xFF);
|
||||
buffer = new byte[l];
|
||||
System.arraycopy(k, i, buffer, 0, l);
|
||||
i += l;
|
||||
BigInteger q = new BigInteger(1, buffer);
|
||||
|
||||
// g
|
||||
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
|
||||
| (k[i++] & 0xFF);
|
||||
buffer = new byte[l];
|
||||
System.arraycopy(k, i, buffer, 0, l);
|
||||
i += l;
|
||||
BigInteger g = new BigInteger(1, buffer);
|
||||
|
||||
// x
|
||||
l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
|
||||
| (k[i++] & 0xFF);
|
||||
buffer = new byte[l];
|
||||
System.arraycopy(k, i, buffer, 0, l);
|
||||
i += l;
|
||||
BigInteger x = new BigInteger(1, buffer);
|
||||
|
||||
return new DSSPrivateKey(p, q, g, x);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/* DSSKeyPairX509Codec.java -- X.509 Encoding/Decoding handler
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is 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, 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; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, 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.OID;
|
||||
import gnu.java.security.Registry;
|
||||
import gnu.java.security.der.BitString;
|
||||
import gnu.java.security.der.DER;
|
||||
import gnu.java.security.der.DERReader;
|
||||
import gnu.java.security.der.DERValue;
|
||||
import gnu.java.security.der.DERWriter;
|
||||
import gnu.java.security.key.IKeyPairCodec;
|
||||
import gnu.java.security.util.DerUtil;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* An implementation of an {@link IKeyPairCodec} that knows how to encode /
|
||||
* decode X.509 ASN.1 external representation of DSS public keys.
|
||||
*/
|
||||
public class DSSKeyPairX509Codec
|
||||
implements IKeyPairCodec
|
||||
{
|
||||
private static final OID DSA_ALG_OID = new OID(Registry.DSA_OID_STRING);
|
||||
|
||||
// implicit 0-arguments constructor
|
||||
|
||||
public int getFormatID()
|
||||
{
|
||||
return X509_FORMAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X.509 ASN.1 <i>SubjectPublicKeyInfo</i> representation of a
|
||||
* DSA public key. The ASN.1 specification, as defined in RFC-3280, and
|
||||
* RFC-2459, is as follows:
|
||||
*
|
||||
* <pre>
|
||||
* SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* subjectPublicKey BIT STRING
|
||||
* }
|
||||
*
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL
|
||||
* }
|
||||
*
|
||||
* DssParams ::= SEQUENCE {
|
||||
* p INTEGER,
|
||||
* q INTEGER,
|
||||
* g INTEGER
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
|
||||
* DER-encoded form of the DSA public key as an INTEGER.</p>
|
||||
*
|
||||
* <pre>
|
||||
* DSAPublicKey ::= INTEGER -- public key, Y
|
||||
* </pre>
|
||||
*
|
||||
* @param key the {@link PublicKey} instance to encode. MUST be an instance of
|
||||
* {@link DSSPublicKey}.
|
||||
* @return the ASN.1 representation of the <i>SubjectPublicKeyInfo</i> in an
|
||||
* X.509 certificate.
|
||||
* @throw InvalidParameterException if <code>key</code> is not an instance
|
||||
* of {@link DSSPublicKey} or if an exception occurs during the
|
||||
* marshalling process.
|
||||
*/
|
||||
public byte[] encodePublicKey(PublicKey key)
|
||||
{
|
||||
if (! (key instanceof DSSPublicKey))
|
||||
throw new InvalidParameterException("key");
|
||||
|
||||
DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
|
||||
|
||||
DSSPublicKey dssKey = (DSSPublicKey) key;
|
||||
BigInteger p = dssKey.getParams().getP();
|
||||
BigInteger q = dssKey.getParams().getQ();
|
||||
BigInteger g = dssKey.getParams().getG();
|
||||
BigInteger y = dssKey.getY();
|
||||
|
||||
DERValue derP = new DERValue(DER.INTEGER, p);
|
||||
DERValue derQ = new DERValue(DER.INTEGER, q);
|
||||
DERValue derG = new DERValue(DER.INTEGER, g);
|
||||
|
||||
ArrayList params = new ArrayList(3);
|
||||
params.add(derP);
|
||||
params.add(derQ);
|
||||
params.add(derG);
|
||||
DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
|
||||
|
||||
ArrayList algorithmID = new ArrayList(2);
|
||||
algorithmID.add(derOID);
|
||||
algorithmID.add(derParams);
|
||||
DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
|
||||
algorithmID);
|
||||
|
||||
DERValue derDSAPublicKey = new DERValue(DER.INTEGER, y);
|
||||
byte[] yBytes = derDSAPublicKey.getEncoded();
|
||||
DERValue derSPK = new DERValue(DER.BIT_STRING, new BitString(yBytes));
|
||||
|
||||
ArrayList spki = new ArrayList(2);
|
||||
spki.add(derAlgorithmID);
|
||||
spki.add(derSPK);
|
||||
DERValue derSPKI = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, spki);
|
||||
|
||||
byte[] result;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
DERWriter.write(baos, derSPKI);
|
||||
result = baos.toByteArray();
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
InvalidParameterException e = new InvalidParameterException();
|
||||
e.initCause(x);
|
||||
throw e;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParameterException ALWAYS.
|
||||
*/
|
||||
public byte[] encodePrivateKey(PrivateKey key)
|
||||
{
|
||||
throw new InvalidParameterException("Wrong format for private keys");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param input the byte array to unmarshall into a valid DSS
|
||||
* {@link PublicKey} instance. MUST NOT be null.
|
||||
* @return a new instance of a {@link DSSPublicKey} decoded from the
|
||||
* <i>SubjectPublicKeyInfo</i> material in an X.509 certificate.
|
||||
* @throw InvalidParameterException if an exception occurs during the
|
||||
* unmarshalling process.
|
||||
*/
|
||||
public PublicKey decodePublicKey(byte[] input)
|
||||
{
|
||||
if (input == null)
|
||||
throw new InvalidParameterException("Input bytes MUST NOT be null");
|
||||
|
||||
BigInteger p, g, q, y;
|
||||
DERReader der = new DERReader(input);
|
||||
try
|
||||
{
|
||||
DERValue derSPKI = der.read();
|
||||
DerUtil.checkIsConstructed(derSPKI, "Wrong SubjectPublicKeyInfo field");
|
||||
|
||||
DERValue derAlgorithmID = der.read();
|
||||
DerUtil.checkIsConstructed(derAlgorithmID, "Wrong AlgorithmIdentifier field");
|
||||
|
||||
DERValue derOID = der.read();
|
||||
if (! (derOID.getValue() instanceof OID))
|
||||
throw new InvalidParameterException("Wrong Algorithm field");
|
||||
|
||||
OID algOID = (OID) derOID.getValue();
|
||||
if (! algOID.equals(DSA_ALG_OID))
|
||||
throw new InvalidParameterException("Unexpected OID: " + algOID);
|
||||
|
||||
DERValue derParams = der.read();
|
||||
DerUtil.checkIsConstructed(derParams, "Wrong DSS Parameters field");
|
||||
|
||||
DERValue val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong P field");
|
||||
p = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong Q field");
|
||||
q = (BigInteger) val.getValue();
|
||||
val = der.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong G field");
|
||||
g = (BigInteger) val.getValue();
|
||||
|
||||
val = der.read();
|
||||
if (! (val.getValue() instanceof BitString))
|
||||
throw new InvalidParameterException("Wrong SubjectPublicKey field");
|
||||
|
||||
byte[] yBytes = ((BitString) val.getValue()).toByteArray();
|
||||
|
||||
DERReader dsaPub = new DERReader(yBytes);
|
||||
val = dsaPub.read();
|
||||
DerUtil.checkIsBigInteger(val, "Wrong Y field");
|
||||
y = (BigInteger) val.getValue();
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
InvalidParameterException e = new InvalidParameterException();
|
||||
e.initCause(x);
|
||||
throw e;
|
||||
}
|
||||
|
||||
return new DSSPublicKey(Registry.X509_ENCODING_ID, p, q, g, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParameterException ALWAYS.
|
||||
*/
|
||||
public PrivateKey decodePrivateKey(byte[] input)
|
||||
{
|
||||
throw new InvalidParameterException("Wrong format for private keys");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/* DSSPrivateKey.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.key.IKeyPairCodec;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.interfaces.DSAPrivateKey;
|
||||
|
||||
/**
|
||||
* <p>An object that embodies a DSS (Digital Signature Standard) private key.</p>
|
||||
*
|
||||
* @version $Revision: 1.2 $
|
||||
* @see #getEncoded
|
||||
*/
|
||||
public class DSSPrivateKey extends DSSKey implements PrivateKey, DSAPrivateKey
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>A randomly or pseudorandomly generated integer with <code>0 < x <
|
||||
* q</code>.</p>
|
||||
*/
|
||||
private final BigInteger x;
|
||||
|
||||
// Constructor(s)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Convenience constructor. Calls the constructor with 5 arguments passing
|
||||
* {@link Registry#RAW_ENCODING_ID} as the identifier of the preferred
|
||||
* encoding format.
|
||||
*
|
||||
* @param p the public modulus.
|
||||
* @param q the public prime divisor of <code>p-1</code>.
|
||||
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
|
||||
* <sub>p</sub></code>.
|
||||
* @param x the private key part.
|
||||
*/
|
||||
public DSSPrivateKey(BigInteger p, BigInteger q, BigInteger g, BigInteger x)
|
||||
{
|
||||
this(Registry.RAW_ENCODING_ID, p, q, g, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of a <code>DSSPrivateKey</code> given the
|
||||
* designated arguments.
|
||||
*
|
||||
* @param preferredFormat the indetifier of the preferred encoding format to
|
||||
* use when externalizing this key.
|
||||
* @param p the public modulus.
|
||||
* @param q the public prime divisor of <code>p-1</code>.
|
||||
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
|
||||
* <sub>p</sub></code>.
|
||||
* @param x the private key part.
|
||||
*/
|
||||
public DSSPrivateKey(int preferredFormat, BigInteger p, BigInteger q,
|
||||
BigInteger g, BigInteger x)
|
||||
{
|
||||
super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.PKCS8_ENCODING_ID
|
||||
: preferredFormat,
|
||||
p, q, g);
|
||||
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
// Class methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class method that takes the output of the <code>encodePrivateKey()</code>
|
||||
* method of a DSS keypair codec object (an instance implementing
|
||||
* {@link gnu.java.security.key.IKeyPairCodec} for DSS keys, and re-constructs
|
||||
* an instance of this object.
|
||||
*
|
||||
* @param k the contents of a previously encoded instance of this object.
|
||||
* @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
|
||||
* <code>k</code>, to represent a valid encoding of an
|
||||
* instance of this object.
|
||||
* @exception IllegalArgumentException if the byte sequence does not represent
|
||||
* a valid encoding of an instance of this object.
|
||||
*/
|
||||
public static DSSPrivateKey valueOf(byte[] k)
|
||||
{
|
||||
// try RAW codec
|
||||
if (k[0] == Registry.MAGIC_RAW_DSS_PRIVATE_KEY[0])
|
||||
try
|
||||
{
|
||||
return (DSSPrivateKey) new DSSKeyPairRawCodec().decodePrivateKey(k);
|
||||
}
|
||||
catch (IllegalArgumentException ignored)
|
||||
{
|
||||
}
|
||||
|
||||
// try PKCS#8 codec
|
||||
return (DSSPrivateKey) new DSSKeyPairPKCS8Codec().decodePrivateKey(k);
|
||||
}
|
||||
|
||||
// Instance methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// java.security.interfaces.DSAPrivateKey interface implementation ---------
|
||||
|
||||
public BigInteger getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
// Other instance methods --------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Returns the encoded form of this private key according to the
|
||||
* designated format.</p>
|
||||
*
|
||||
* @param format the desired format identifier of the resulting encoding.
|
||||
* @return the byte sequence encoding this key according to the designated
|
||||
* format.
|
||||
* @exception IllegalArgumentException if the format is not supported.
|
||||
* @see DSSKeyPairRawCodec
|
||||
*/
|
||||
public byte[] getEncoded(int format)
|
||||
{
|
||||
byte[] result;
|
||||
switch (format)
|
||||
{
|
||||
case IKeyPairCodec.RAW_FORMAT:
|
||||
result = new DSSKeyPairRawCodec().encodePrivateKey(this);
|
||||
break;
|
||||
case IKeyPairCodec.PKCS8_FORMAT:
|
||||
result = new DSSKeyPairPKCS8Codec().encodePrivateKey(this);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported encoding format: "
|
||||
+ format);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns <code>true</code> if the designated object is an instance of
|
||||
* {@link DSAPrivateKey} and has the same DSS (Digital Signature Standard)
|
||||
* parameter values as this one.</p>
|
||||
*
|
||||
* @param obj the other non-null DSS key to compare to.
|
||||
* @return <code>true</code> if the designated object is of the same type and
|
||||
* value as this one.
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof DSAPrivateKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DSAPrivateKey that = (DSAPrivateKey) obj;
|
||||
return super.equals(that) && x.equals(that.getX());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/* DSSPublicKey.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.key.IKeyPairCodec;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.PublicKey;
|
||||
import java.security.interfaces.DSAPublicKey;
|
||||
|
||||
/**
|
||||
* <p>An object that embodies a DSS (Digital Signature Standard) public key.</p>
|
||||
*
|
||||
* @version $Revision: 1.2 $
|
||||
* @see #getEncoded
|
||||
*/
|
||||
public class DSSPublicKey extends DSSKey implements PublicKey, DSAPublicKey
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* <code>y = g<sup>x</sup> mod p</code> where <code>x</code> is the private
|
||||
* part of the DSA key.
|
||||
*/
|
||||
private final BigInteger y;
|
||||
|
||||
// Constructor(s)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Conveience constructor. Calls the constructor with 5 arguments passing
|
||||
* {@link Registry#RAW_ENCODING_ID} as the identifier of the preferred
|
||||
* encoding format.
|
||||
*
|
||||
* @param p the public modulus.
|
||||
* @param q the public prime divisor of <code>p-1</code>.
|
||||
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
|
||||
* <sub>p</sub></code>.
|
||||
* @param y the public key part.
|
||||
*/
|
||||
public DSSPublicKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y)
|
||||
{
|
||||
this(Registry.RAW_ENCODING_ID, p, q, g, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of <code>DSSPublicKey</code> given the designated
|
||||
* arguments.
|
||||
*
|
||||
* @param preferredFormat the identifier of the preferred encoding format to
|
||||
* use when externalizing this key.
|
||||
* @param p the public modulus.
|
||||
* @param q the public prime divisor of <code>p-1</code>.
|
||||
* @param g a generator of the unique cyclic group <code>Z<sup>*</sup>
|
||||
* <sub>p</sub></code>.
|
||||
* @param y the public key part.
|
||||
*/
|
||||
public DSSPublicKey(int preferredFormat, BigInteger p, BigInteger q,
|
||||
BigInteger g, BigInteger y)
|
||||
{
|
||||
super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.X509_ENCODING_ID
|
||||
: preferredFormat,
|
||||
p, q, g);
|
||||
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
// Class methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class method that takes the output of the <code>encodePublicKey()</code>
|
||||
* method of a DSS keypair codec object (an instance implementing
|
||||
* {@link gnu.java.security.key.IKeyPairCodec} for DSS keys, and re-constructs
|
||||
* an instance of this object.
|
||||
*
|
||||
* @param k the contents of a previously encoded instance of this object.
|
||||
* @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
|
||||
* <code>k</code>, to represent a valid encoding of an
|
||||
* instance of this object.
|
||||
* @exception IllegalArgumentException if the byte sequence does not represent
|
||||
* a valid encoding of an instance of this object.
|
||||
*/
|
||||
public static DSSPublicKey valueOf(byte[] k)
|
||||
{
|
||||
// try RAW codec
|
||||
if (k[0] == Registry.MAGIC_RAW_DSS_PUBLIC_KEY[0])
|
||||
try
|
||||
{
|
||||
return (DSSPublicKey) new DSSKeyPairRawCodec().decodePublicKey(k);
|
||||
}
|
||||
catch (IllegalArgumentException ignored)
|
||||
{
|
||||
}
|
||||
|
||||
// try X.509 codec
|
||||
return (DSSPublicKey) new DSSKeyPairX509Codec().decodePublicKey(k);
|
||||
}
|
||||
|
||||
// Instance methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// java.security.interfaces.DSAPublicKey interface implementation ----------
|
||||
|
||||
public BigInteger getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
// Other instance methods --------------------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Returns the encoded form of this public key according to the designated
|
||||
* format.</p>
|
||||
*
|
||||
* @param format the desired format identifier of the resulting encoding.
|
||||
* @return the byte sequence encoding this key according to the designated
|
||||
* format.
|
||||
* @exception IllegalArgumentException if the format is not supported.
|
||||
* @see DSSKeyPairRawCodec
|
||||
*/
|
||||
public byte[] getEncoded(int format)
|
||||
{
|
||||
byte[] result;
|
||||
switch (format)
|
||||
{
|
||||
case IKeyPairCodec.RAW_FORMAT:
|
||||
result = new DSSKeyPairRawCodec().encodePublicKey(this);
|
||||
break;
|
||||
case IKeyPairCodec.X509_FORMAT:
|
||||
result = new DSSKeyPairX509Codec().encodePublicKey(this);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported encoding format: "
|
||||
+ format);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns <code>true</code> if the designated object is an instance of
|
||||
* {@link DSAPublicKey} and has the same DSS (Digital Signature Standard)
|
||||
* parameter values as this one.</p>
|
||||
*
|
||||
* @param obj the other non-null DSS key to compare to.
|
||||
* @return <code>true</code> if the designated object is of the same type and
|
||||
* value as this one.
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof DSAPublicKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DSAPublicKey that = (DSAPublicKey) obj;
|
||||
return super.equals(that) && y.equals(that.getY());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
/* FIPS186.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.hash.Sha160;
|
||||
import gnu.java.security.util.PRNG;
|
||||
import gnu.java.security.util.Prime2;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* <p>An implementation of the DSA parameters generation as described in
|
||||
* FIPS-186.</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.
|
||||
*
|
||||
* @version $Revision: 1.2 $
|
||||
*/
|
||||
public class FIPS186
|
||||
{
|
||||
|
||||
// Constants and variables
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public static final int DSA_PARAMS_SEED = 0;
|
||||
|
||||
public static final int DSA_PARAMS_COUNTER = 1;
|
||||
|
||||
public static final int DSA_PARAMS_Q = 2;
|
||||
|
||||
public static final int DSA_PARAMS_P = 3;
|
||||
|
||||
public static final int DSA_PARAMS_E = 4;
|
||||
|
||||
public static final int DSA_PARAMS_G = 5;
|
||||
|
||||
/** The BigInteger constant 2. */
|
||||
private static final BigInteger TWO = new BigInteger("2");
|
||||
|
||||
private static final BigInteger TWO_POW_160 = TWO.pow(160);
|
||||
|
||||
/** The SHA instance to use. */
|
||||
private Sha160 sha = new Sha160();
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Our default source of randomness. */
|
||||
private PRNG prng = null;
|
||||
|
||||
// Constructor(s)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public FIPS186(int L, SecureRandom rnd)
|
||||
{
|
||||
super();
|
||||
|
||||
this.L = L;
|
||||
this.rnd = rnd;
|
||||
}
|
||||
|
||||
// Class methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Instance methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This method generates the DSS <code>p</code>, <code>q</code>, and
|
||||
* <code>g</code> parameters only when <code>L</code> (the modulus length)
|
||||
* is not one of the following: <code>512</code>, <code>768</code> and
|
||||
* <code>1024</code>. For those values of <code>L</code>, this implementation
|
||||
* uses pre-computed values of <code>p</code>, <code>q</code>, and
|
||||
* <code>g</code> given in the document <i>CryptoSpec</i> included in the
|
||||
* security guide documentation of the standard JDK distribution.<p>
|
||||
*
|
||||
* The DSS requires two primes , <code>p</code> and <code>q</code>,
|
||||
* satisfying the following three conditions:
|
||||
*
|
||||
* <ul>
|
||||
* <li><code>2<sup>159</sup> < q < 2<sup>160</sup></code></li>
|
||||
* <li><code>2<sup>L-1</sup> < p < 2<sup>L</sup></code> for a
|
||||
* specified <code>L</code>, where <code>L = 512 + 64j</code> for some
|
||||
* <code>0 <= j <= 8</code></li>
|
||||
* <li>q divides p - 1.</li>
|
||||
* </ul>
|
||||
*
|
||||
* The algorithm used to find these primes is as described in FIPS-186,
|
||||
* section 2.2: GENERATION OF PRIMES. This prime generation scheme starts by
|
||||
* using the {@link Sha160} and a user supplied <i>SEED</i>
|
||||
* to construct a prime, <code>q</code>, in the range 2<sup>159</sup> < q
|
||||
* < 2<sup>160</sup>. Once this is accomplished, the same <i>SEED</i>
|
||||
* value is used to construct an <code>X</code> in the range <code>2<sup>L-1
|
||||
* </sup> < X < 2<sup>L</sup>. The prime, <code>p</code>, is then
|
||||
* formed by rounding <code>X</code> to a number congruent to <code>1 mod
|
||||
* 2q</code>. In this implementation we use the same <i>SEED</i> value given
|
||||
* in FIPS-186, Appendix 5.
|
||||
*/
|
||||
public BigInteger[] generateParameters()
|
||||
{
|
||||
int counter, offset;
|
||||
BigInteger SEED, alpha, U, q, OFFSET, SEED_PLUS_OFFSET, W, X, p, c, g;
|
||||
byte[] a, u;
|
||||
byte[] kb = new byte[20]; // to hold 160 bits of randomness
|
||||
|
||||
// Let L-1 = n*160 + b, where b and n are integers and 0 <= b < 160.
|
||||
int b = (L - 1) % 160;
|
||||
int n = (L - 1 - b) / 160;
|
||||
BigInteger[] V = new BigInteger[n + 1];
|
||||
algorithm: while (true)
|
||||
{
|
||||
step1: while (true)
|
||||
{
|
||||
// 1. Choose an arbitrary sequence of at least 160 bits and
|
||||
// call it SEED.
|
||||
nextRandomBytes(kb);
|
||||
SEED = new BigInteger(1, kb).setBit(159).setBit(0);
|
||||
// Let g be the length of SEED in bits. here always 160
|
||||
// 2. Compute: U = SHA[SEED] XOR SHA[(SEED+1) mod 2**g]
|
||||
alpha = SEED.add(BigInteger.ONE).mod(TWO_POW_160);
|
||||
synchronized (sha)
|
||||
{
|
||||
a = SEED.toByteArray();
|
||||
sha.update(a, 0, a.length);
|
||||
a = sha.digest();
|
||||
u = alpha.toByteArray();
|
||||
sha.update(u, 0, u.length);
|
||||
u = sha.digest();
|
||||
}
|
||||
for (int i = 0; i < a.length; i++)
|
||||
{
|
||||
a[i] ^= u[i];
|
||||
}
|
||||
U = new BigInteger(1, a);
|
||||
// 3. Form q from U by setting the most significant bit (the
|
||||
// 2**159 bit) and the least significant bit to 1. In terms of
|
||||
// boolean operations, q = U OR 2**159 OR 1. Note that
|
||||
// 2**159 < q < 2**160.
|
||||
q = U.setBit(159).setBit(0);
|
||||
// 4. Use a robust primality testing algorithm to test whether
|
||||
// q is prime(1). A robust primality test is one where the
|
||||
// probability of a non-prime number passing the test is at
|
||||
// most 1/2**80.
|
||||
// 5. If q is not prime, go to step 1.
|
||||
if (Prime2.isProbablePrime(q))
|
||||
{
|
||||
break step1;
|
||||
}
|
||||
} // step1
|
||||
|
||||
// 6. Let counter = 0 and offset = 2.
|
||||
counter = 0;
|
||||
offset = 2;
|
||||
step7: while (true)
|
||||
{
|
||||
OFFSET = BigInteger.valueOf(offset & 0xFFFFFFFFL);
|
||||
SEED_PLUS_OFFSET = SEED.add(OFFSET);
|
||||
// 7. For k = 0,...,n let V[k] = SHA[(SEED + offset + k) mod 2**g].
|
||||
synchronized (sha)
|
||||
{
|
||||
for (int k = 0; k <= n; k++)
|
||||
{
|
||||
a = SEED_PLUS_OFFSET.add(
|
||||
BigInteger.valueOf(k & 0xFFFFFFFFL)).mod(
|
||||
TWO_POW_160).toByteArray();
|
||||
sha.update(a, 0, a.length);
|
||||
V[k] = new BigInteger(1, sha.digest());
|
||||
}
|
||||
}
|
||||
// 8. Let W be the integer:
|
||||
// V[0]+V[1]*2**160+...+V[n-1]*2**((n-1)*160)+(V[n]mod2**b)*2**(n*160)
|
||||
// and let : X = W + 2**(L-1).
|
||||
// Note that 0 <= W < 2**(L-1) and hence 2**(L-1) <= X < 2**L.
|
||||
W = V[0];
|
||||
for (int k = 1; k < n; k++)
|
||||
{
|
||||
W = W.add(V[k].multiply(TWO.pow(k * 160)));
|
||||
}
|
||||
W = W.add(V[n].mod(TWO.pow(b)).multiply(TWO.pow(n * 160)));
|
||||
X = W.add(TWO.pow(L - 1));
|
||||
// 9. Let c = X mod 2q and set p = X - (c - 1).
|
||||
// Note that p is congruent to 1 mod 2q.
|
||||
c = X.mod(TWO.multiply(q));
|
||||
p = X.subtract(c.subtract(BigInteger.ONE));
|
||||
// 10. If p < 2**(L-1), then go to step 13.
|
||||
if (p.compareTo(TWO.pow(L - 1)) >= 0)
|
||||
{
|
||||
// 11. Perform a robust primality test on p.
|
||||
// 12. If p passes the test performed in step 11, go to step 15.
|
||||
if (Prime2.isProbablePrime(p))
|
||||
{
|
||||
break algorithm;
|
||||
}
|
||||
}
|
||||
// 13. Let counter = counter + 1 and offset = offset + n + 1.
|
||||
counter++;
|
||||
offset += n + 1;
|
||||
// 14. If counter >= 4096 go to step 1, otherwise go to step 7.
|
||||
if (counter >= 4096)
|
||||
{
|
||||
continue algorithm;
|
||||
}
|
||||
} // step7
|
||||
} // algorithm
|
||||
|
||||
// compute g. from FIPS-186, Appendix 4:
|
||||
// 1. Generate p and q as specified in Appendix 2.
|
||||
// 2. Let e = (p - 1) / q
|
||||
BigInteger e = p.subtract(BigInteger.ONE).divide(q);
|
||||
BigInteger h = TWO;
|
||||
BigInteger p_minus_1 = p.subtract(BigInteger.ONE);
|
||||
g = TWO;
|
||||
// 3. Set h = any integer, where 1 < h < p - 1 and
|
||||
// h differs from any value previously tried
|
||||
for (; h.compareTo(p_minus_1) < 0; h = h.add(BigInteger.ONE))
|
||||
{
|
||||
// 4. Set g = h**e mod p
|
||||
g = h.modPow(e, p);
|
||||
// 5. If g = 1, go to step 3
|
||||
if (!g.equals(BigInteger.ONE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new BigInteger[] { SEED, BigInteger.valueOf(counter), q, p, e, g };
|
||||
}
|
||||
|
||||
// helper methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fills the designated byte array with random data.
|
||||
*
|
||||
* @param buffer the byte array to fill with random data.
|
||||
*/
|
||||
private void nextRandomBytes(byte[] buffer)
|
||||
{
|
||||
if (rnd != null)
|
||||
{
|
||||
rnd.nextBytes(buffer);
|
||||
}
|
||||
else
|
||||
getDefaultPRNG().nextBytes(buffer);
|
||||
}
|
||||
|
||||
private PRNG getDefaultPRNG()
|
||||
{
|
||||
if (prng == null)
|
||||
prng = PRNG.getInstance();
|
||||
|
||||
return prng;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user