summaryrefslogtreecommitdiff
path: root/gnu/java/security
diff options
context:
space:
mode:
authorGuilhem Lavaux <guilhem@kaffe.org>2006-02-04 18:38:03 +0000
committerGuilhem Lavaux <guilhem@kaffe.org>2006-02-04 18:38:03 +0000
commit3af9dde820e3a7f8194964ec9dcc8539dd4af2b8 (patch)
tree7abe48072a9d59def3ea20a23d9609435d1a4548 /gnu/java/security
parenta92748b017d37f8e4a83997933c5850f9484df9d (diff)
downloadclasspath-3af9dde820e3a7f8194964ec9dcc8539dd4af2b8.tar.gz
2006-02-04 Guilhem Lavaux <guilhem@kaffe.org>
* Resynchronized with GNU Classpath's HEAD branch.
Diffstat (limited to 'gnu/java/security')
-rw-r--r--gnu/java/security/der/DERValue.java29
-rw-r--r--gnu/java/security/der/DERWriter.java6
-rw-r--r--gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java80
-rw-r--r--gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java8
-rw-r--r--gnu/java/security/key/dss/DSSKeyPairGenerator.java80
-rw-r--r--gnu/java/security/key/dss/FIPS186.java20
-rw-r--r--gnu/java/security/key/rsa/RSAKeyPairGenerator.java16
-rw-r--r--gnu/java/security/sig/BaseSignature.java17
-rw-r--r--gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java9
-rw-r--r--gnu/java/security/sig/rsa/RSA.java11
-rw-r--r--gnu/java/security/util/PRNG.java156
-rw-r--r--gnu/java/security/util/Prime2.java383
-rw-r--r--gnu/java/security/x509/ext/GeneralNames.java21
13 files changed, 483 insertions, 353 deletions
diff --git a/gnu/java/security/der/DERValue.java b/gnu/java/security/der/DERValue.java
index 9a597d724..d98ce78ec 100644
--- a/gnu/java/security/der/DERValue.java
+++ b/gnu/java/security/der/DERValue.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package gnu.java.security.der;
+import gnu.java.security.x509.Util;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -108,7 +110,9 @@ public class DERValue implements DER
}
catch (IOException ioe)
{
- encoded = new byte[0];
+ IllegalArgumentException iae = new IllegalArgumentException ();
+ iae.initCause (ioe);
+ throw iae;
}
}
return length;
@@ -138,7 +142,9 @@ public class DERValue implements DER
}
catch (IOException ioe)
{
- encoded = new byte[0];
+ IllegalArgumentException iae = new IllegalArgumentException ();
+ iae.initCause (ioe);
+ throw iae;
}
}
return (byte[]) encoded.clone();
@@ -156,7 +162,9 @@ public class DERValue implements DER
}
catch (IOException ioe)
{
- encoded = new byte[0];
+ IllegalArgumentException iae = new IllegalArgumentException ();
+ iae.initCause (ioe);
+ throw iae;
}
}
return encoded.length;
@@ -164,7 +172,18 @@ public class DERValue implements DER
public String toString()
{
- return "DERValue [ tag=" + tag + ", class=" + tagClass + ", constructed="
- + constructed + ", value=" + value + " ]";
+ String start = "DERValue ( [";
+ if (tagClass == DER.UNIVERSAL)
+ start = start + "UNIVERSAL ";
+ else if (tagClass == DER.PRIVATE)
+ start = start + "PRIVATE ";
+ else if (tagClass == DER.APPLICATION)
+ start = start + "APPLICATION ";
+ start = start + tag + "] constructed=" + constructed + ", value=";
+ if (constructed)
+ start = start + "\n" + Util.hexDump(getEncoded(), "\t");
+ else
+ start = start + value;
+ return start + " )";
}
}
diff --git a/gnu/java/security/der/DERWriter.java b/gnu/java/security/der/DERWriter.java
index 78524fc94..4298151e0 100644
--- a/gnu/java/security/der/DERWriter.java
+++ b/gnu/java/security/der/DERWriter.java
@@ -84,6 +84,12 @@ public class DERWriter implements DER
public static int write(OutputStream out, DERValue object)
throws IOException
{
+ if (DER.CONSTRUCTED_VALUE.equals (object.getValue ()))
+ {
+ out.write (object.getEncoded ());
+ return object.getLength ();
+ }
+
out.write(object.getExternalTag());
Object value = object.getValue();
if (value == null)
diff --git a/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java b/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java
index 5cb1380d2..2f4d36d51 100644
--- a/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java
+++ b/gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java
@@ -42,7 +42,10 @@ import gnu.java.security.Registry;
import gnu.java.security.key.dss.DSSKeyPairGenerator;
import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
import java.security.SecureRandom;
+import java.security.interfaces.DSAKeyPairGenerator;
+import java.security.interfaces.DSAParams;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.DSAParameterSpec;
import java.util.HashMap;
@@ -55,9 +58,10 @@ import java.util.HashMap;
* a call to an <code>initialize()</code> method), the GNU Crypto provider
* uses a default <i>modulus</i> size (keysize) of 1024 bits.<p>
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.1.2.1 $
*/
-public class DSSKeyPairGeneratorSpi extends KeyPairGeneratorAdapter
+public class DSSKeyPairGeneratorSpi extends KeyPairGeneratorAdapter implements
+ DSAKeyPairGenerator
{
// Constants and variables
@@ -79,14 +83,7 @@ public class DSSKeyPairGeneratorSpi extends KeyPairGeneratorAdapter
public void initialize(int keysize, SecureRandom random)
{
- HashMap attributes = new HashMap();
- attributes.put(DSSKeyPairGenerator.MODULUS_LENGTH, new Integer(keysize));
- if (random != null)
- {
- attributes.put(DSSKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
- }
-
- adaptee.setup(attributes);
+ this.initialize(keysize, false, random);
}
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
@@ -96,9 +93,9 @@ public class DSSKeyPairGeneratorSpi extends KeyPairGeneratorAdapter
if (params != null)
{
if (!(params instanceof DSAParameterSpec))
- {
- throw new InvalidAlgorithmParameterException("params");
- }
+ throw new InvalidAlgorithmParameterException(
+ "Parameters argument is not a non-null instance, or " +
+ "sub-instance, of java.security.spec.DSAParameterSpec");
attributes.put(DSSKeyPairGenerator.DSS_PARAMETERS, params);
}
@@ -108,6 +105,61 @@ public class DSSKeyPairGeneratorSpi extends KeyPairGeneratorAdapter
attributes.put(DSSKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
}
- adaptee.setup(attributes);
+ try
+ {
+ adaptee.setup(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ InvalidAlgorithmParameterException y =
+ new InvalidAlgorithmParameterException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ // java.security.interfaces.DSAKeyPairGenerator interface implementation -----
+
+ public void initialize(DSAParams params, SecureRandom random)
+ throws InvalidParameterException
+ {
+ if (params == null || !(params instanceof DSAParameterSpec))
+ throw new InvalidParameterException(
+ "Parameters argument is either null or is not an instance, or " +
+ "sub-instance, of java.security.spec.DSAParameterSpec");
+ DSAParameterSpec spec = (DSAParameterSpec) params;
+ try
+ {
+ this.initialize((AlgorithmParameterSpec) spec, random);
+ }
+ catch (InvalidAlgorithmParameterException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
+ }
+
+ public void initialize(int modlen, boolean genParams, SecureRandom random)
+ throws InvalidParameterException
+ {
+ HashMap attributes = new HashMap();
+ attributes.put(DSSKeyPairGenerator.MODULUS_LENGTH, new Integer(modlen));
+ if (random != null)
+ attributes.put(DSSKeyPairGenerator.SOURCE_OF_RANDOMNESS, random);
+
+ attributes.put(DSSKeyPairGenerator.USE_DEFAULTS,
+ Boolean.valueOf(!genParams));
+ attributes.put(DSSKeyPairGenerator.STRICT_DEFAULTS, Boolean.TRUE);
+ try
+ {
+ adaptee.setup(attributes);
+ }
+ catch (IllegalArgumentException x)
+ {
+ InvalidParameterException y = new InvalidParameterException();
+ y.initCause(x);
+ throw y;
+ }
}
}
diff --git a/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java b/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java
index 21a596a5f..b1dab1de8 100644
--- a/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java
+++ b/gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java
@@ -43,7 +43,7 @@ import gnu.java.security.key.KeyPairGeneratorFactory;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
-import java.security.KeyPairGeneratorSpi;
+import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
@@ -64,9 +64,9 @@ import java.security.spec.AlgorithmParameterSpec;
* Crypto provider uses a default <i>modulus</i> size (keysize) of 1024 bits for
* the DSS (Digital Signature Standard) a.k.a <i>DSA</i>.<p>
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.1.2.1 $
*/
-abstract class KeyPairGeneratorAdapter extends KeyPairGeneratorSpi
+abstract class KeyPairGeneratorAdapter extends KeyPairGenerator
{
// Constants and variables
@@ -85,7 +85,7 @@ abstract class KeyPairGeneratorAdapter extends KeyPairGeneratorSpi
*/
protected KeyPairGeneratorAdapter(String kpgName)
{
- super();
+ super(kpgName);
this.adaptee = KeyPairGeneratorFactory.getInstance(kpgName);
}
diff --git a/gnu/java/security/key/dss/DSSKeyPairGenerator.java b/gnu/java/security/key/dss/DSSKeyPairGenerator.java
index 3f9c80625..16af5e048 100644
--- a/gnu/java/security/key/dss/DSSKeyPairGenerator.java
+++ b/gnu/java/security/key/dss/DSSKeyPairGenerator.java
@@ -41,6 +41,7 @@ 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;
@@ -88,10 +89,55 @@ public class DSSKeyPairGenerator implements IKeyPairGenerator
/** 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. */
+ /**
+ * 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}.
*/
@@ -181,6 +227,9 @@ public class DSSKeyPairGenerator implements IKeyPairGenerator
private BigInteger XKEY;
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
// Constructor(s)
// -------------------------------------------------------------------------
@@ -222,6 +271,10 @@ public class DSSKeyPairGenerator implements IKeyPairGenerator
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)
@@ -250,9 +303,16 @@ public class DSSKeyPairGenerator implements IKeyPairGenerator
g = KEY_PARAMS_1024.getG();
break;
default:
- p = null;
- q = null;
- g = null;
+ 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
@@ -353,8 +413,14 @@ public class DSSKeyPairGenerator implements IKeyPairGenerator
rnd.nextBytes(buffer);
}
else
- {
- new SecureRandom ().nextBytes(buffer);
- }
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
}
}
diff --git a/gnu/java/security/key/dss/FIPS186.java b/gnu/java/security/key/dss/FIPS186.java
index 796f24bd3..c796bab2c 100644
--- a/gnu/java/security/key/dss/FIPS186.java
+++ b/gnu/java/security/key/dss/FIPS186.java
@@ -39,6 +39,7 @@ 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;
@@ -53,7 +54,7 @@ import java.security.SecureRandom;
* Standard (DSS)</a>, Federal Information Processing Standards Publication 186.
* National Institute of Standards and Technology.
*
- * @version $Revision: 1.1 $
+ * @version $Revision: 1.1.2.1 $
*/
public class FIPS186
{
@@ -87,6 +88,9 @@ public class FIPS186
/** The optional {@link SecureRandom} instance to use. */
private SecureRandom rnd = null;
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
// Constructor(s)
// -------------------------------------------------------------------------
@@ -126,7 +130,7 @@ public class FIPS186
*
* 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 gnu.crypto.hash.Sha160} and a user supplied <i>SEED</i>
+ * 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> &lt; q
* &lt; 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
@@ -279,8 +283,14 @@ public class FIPS186
rnd.nextBytes(buffer);
}
else
- {
- new SecureRandom ().nextBytes(buffer);
- }
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
}
}
diff --git a/gnu/java/security/key/rsa/RSAKeyPairGenerator.java b/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
index a9738e751..360036723 100644
--- a/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
+++ b/gnu/java/security/key/rsa/RSAKeyPairGenerator.java
@@ -40,6 +40,7 @@ package gnu.java.security.key.rsa;
import gnu.java.security.Registry;
import gnu.java.security.key.IKeyPairGenerator;
+import gnu.java.security.util.PRNG;
import gnu.java.security.util.Prime2;
import java.math.BigInteger;
@@ -109,6 +110,9 @@ public class RSAKeyPairGenerator implements IKeyPairGenerator
/** The optional {@link SecureRandom} instance to use. */
private SecureRandom rnd = null;
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
// Constructor(s)
// -------------------------------------------------------------------------
@@ -229,8 +233,14 @@ public class RSAKeyPairGenerator implements IKeyPairGenerator
rnd.nextBytes(buffer);
}
else
- {
- new SecureRandom ().nextBytes(buffer);
- }
+ getDefaultPRNG().nextBytes(buffer);
+ }
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
}
}
diff --git a/gnu/java/security/sig/BaseSignature.java b/gnu/java/security/sig/BaseSignature.java
index f82346feb..5b43f2c27 100644
--- a/gnu/java/security/sig/BaseSignature.java
+++ b/gnu/java/security/sig/BaseSignature.java
@@ -41,10 +41,10 @@ package gnu.java.security.sig;
import gnu.java.security.hash.IMessageDigest;
import gnu.java.security.prng.IRandom;
import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.PRNG;
import java.security.PrivateKey;
import java.security.PublicKey;
-import java.security.SecureRandom;
import java.util.Map;
import java.util.Random;
@@ -76,6 +76,9 @@ public abstract class BaseSignature implements ISignature
/** The optional {@link IRandom} instance to use. */
private IRandom irnd;
+ /** Our default source of randomness. */
+ private PRNG prng = null;
+
// Constructor(s)
// -------------------------------------------------------------------------
@@ -224,9 +227,7 @@ public abstract class BaseSignature implements ISignature
}
}
else
- {
- new SecureRandom ().nextBytes(buffer);
- }
+ getDefaultPRNG().nextBytes(buffer);
}
private void setup(Map attributes)
@@ -244,4 +245,12 @@ public abstract class BaseSignature implements ISignature
irnd = (IRandom) obj;
}
}
+
+ private PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
}
diff --git a/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java b/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java
index d6bbfe56b..efe580d51 100644
--- a/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java
+++ b/gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java
@@ -40,9 +40,9 @@ package gnu.java.security.sig.rsa;
import gnu.java.security.prng.IRandom;
import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.PRNG;
import java.io.ByteArrayOutputStream;
-import java.security.SecureRandom;
import java.security.interfaces.RSAKey;
import java.util.Random;
@@ -70,6 +70,9 @@ public class EME_PKCS1_V1_5
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ /** Our default source of randomness. */
+ private PRNG prng = PRNG.getInstance();
+
// Constructor(s)
// -------------------------------------------------------------------------
@@ -128,8 +131,7 @@ public class EME_PKCS1_V1_5
final byte[] PS = new byte[k - M.length - 3];
// FIXME. This should be configurable, somehow.
- SecureRandom rnd = new SecureRandom ();
- rnd.nextBytes(PS);
+ prng.nextBytes(PS);
int i = 0;
for (; i < PS.length; i++)
{
@@ -300,6 +302,5 @@ public class EME_PKCS1_V1_5
baos.reset();
return result;
-
}
}
diff --git a/gnu/java/security/sig/rsa/RSA.java b/gnu/java/security/sig/rsa/RSA.java
index 4ef7232f1..7d1707e19 100644
--- a/gnu/java/security/sig/rsa/RSA.java
+++ b/gnu/java/security/sig/rsa/RSA.java
@@ -39,12 +39,11 @@ exception statement from your version. */
package gnu.java.security.sig.rsa;
import gnu.java.security.Properties;
-import gnu.java.security.key.rsa.GnuRSAKey;
+import gnu.java.security.util.PRNG;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
-import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
@@ -79,6 +78,9 @@ public class RSA
private static final BigInteger ONE = BigInteger.ONE;
+ /** Our default source of randomness. */
+ private static final PRNG prng = PRNG.getInstance();
+
// Constructor(s)
// -------------------------------------------------------------------------
@@ -340,16 +342,15 @@ public class RSA
final int upper = (N.bitLength() + 7) / 8;
final int lower = upper / 2;
final byte[] bl = new byte[1];
- SecureRandom rnd = new SecureRandom ();
int b;
do
{
- rnd.nextBytes(bl);
+ prng.nextBytes(bl);
b = bl[0] & 0xFF;
}
while (b < lower || b > upper);
final byte[] buffer = new byte[b]; // 256-bit MPI
- rnd.nextBytes(buffer);
+ prng.nextBytes(buffer);
return new BigInteger(1, buffer);
}
}
diff --git a/gnu/java/security/util/PRNG.java b/gnu/java/security/util/PRNG.java
new file mode 100644
index 000000000..138cc6bcb
--- /dev/null
+++ b/gnu/java/security/util/PRNG.java
@@ -0,0 +1,156 @@
+/* PRNG.java -- A Utility methods for default source of randomness
+ 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.util;
+
+import java.util.HashMap;
+
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.prng.MDGenerator;
+
+/**
+ * A useful hash-based (SHA) pseudo-random number generator used
+ * throughout this library.
+ *
+ * @see MDGenerator
+ */
+public class PRNG
+{
+ // Constans and fields
+ // --------------------------------------------------------------------------
+
+ /** The underlying {@link IRandom}. */
+ private IRandom delegate;
+
+ // Constructor(s)
+ // --------------------------------------------------------------------------
+
+ /**
+ * Private constructor to enforce using the Factory method.
+ *
+ * @param delegate
+ * the undelying {@link IRandom} object used.
+ */
+ private PRNG(IRandom delegate)
+ {
+ super();
+
+ this.delegate = delegate;
+ }
+
+ // Class methods
+ // --------------------------------------------------------------------------
+
+ public static final PRNG getInstance()
+ {
+ IRandom delegate = new MDGenerator();
+ try
+ {
+ HashMap map = new HashMap();
+ // initialise it with a seed
+ long t = System.currentTimeMillis();
+ byte[] seed = new byte[] {
+ (byte) (t >>> 56), (byte) (t >>> 48),
+ (byte) (t >>> 40), (byte) (t >>> 32),
+ (byte) (t >>> 24), (byte) (t >>> 16),
+ (byte) (t >>> 8), (byte) t};
+ map.put(MDGenerator.SEEED, seed);
+ delegate.init(map); // default is to use SHA-1 hash
+ }
+ catch (Exception x)
+ {
+ throw new ExceptionInInitializerError(x);
+ }
+
+ return new PRNG(delegate);
+ }
+
+ // Instance methods
+ // --------------------------------------------------------------------------
+
+ /**
+ * Completely fills the designated <code>buffer</code> with random data
+ * generated by the underlying delegate.
+ *
+ * @param buffer
+ * the place holder of random bytes generated by the underlying
+ * delegate. On output, the contents of <code>buffer</code> are
+ * replaced with pseudo-random data, iff the <code>buffer</code>
+ * size is not zero.
+ */
+ public void nextBytes(byte[] buffer)
+ {
+ nextBytes(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Fills the designated <code>buffer</code>, starting from byte at position
+ * <code>offset</code> with, at most, <code>length</code> bytes of random
+ * data generated by the underlying delegate.
+ *
+ * @see IRandom#nextBytes
+ */
+ public void nextBytes(byte[] buffer, int offset, int length)
+ {
+ try
+ {
+ delegate.nextBytes(buffer, offset, length);
+ }
+ catch (LimitReachedException x) // re-initialise with a seed
+ {
+ try
+ {
+ HashMap map = new HashMap();
+ long t = System.currentTimeMillis();
+ byte[] seed = new byte[] {
+ (byte)(t >>> 56), (byte)(t >>> 48),
+ (byte)(t >>> 40), (byte)(t >>> 32),
+ (byte)(t >>> 24), (byte)(t >>> 16),
+ (byte)(t >>> 8), (byte) t };
+ map.put(MDGenerator.SEEED, seed);
+ delegate.init(map); // default is to use SHA-1 hash
+ delegate.nextBytes(buffer, offset, length);
+ }
+ catch (Exception y)
+ {
+ throw new ExceptionInInitializerError(y);
+ }
+ }
+ }
+}
diff --git a/gnu/java/security/util/Prime2.java b/gnu/java/security/util/Prime2.java
index bf8df55ad..6e46f5fca 100644
--- a/gnu/java/security/util/Prime2.java
+++ b/gnu/java/security/util/Prime2.java
@@ -38,13 +38,10 @@ exception statement from your version. */
package gnu.java.security.util;
-import gnu.java.security.Properties;
-
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.math.BigInteger;
import java.util.Map;
-import java.util.Random;
import java.util.WeakHashMap;
/**
@@ -189,7 +186,7 @@ public class Prime2
/**
* <p>Java port of Colin Plumb primality test (Euler Criterion)
* implementation for a base of 2 --from bnlib-1.1 release, function
- * primeTest() in prime.c. this is his comments; (bn is our w).</p>
+ * primeTest() in prime.c. this is his comments.</p>
*
* <p>"Now, check that bn is prime. If it passes to the base 2, it's prime
* beyond all reasonable doubt, and everything else is just gravy, but it
@@ -234,86 +231,61 @@ public class Prime2
* All primes <code>== 1 (mod 4)</code> can be expressed as <code>a^2 +
* (2*b)^2</code>, but I see no cheap way to evaluate this condition."</p>
*
- * @param w the number to test.
+ * @param bn the number to test.
* @return <code>true</code> iff the designated number passes Euler criterion
* as implemented by Colin Plumb in his <i>bnlib</i> version 1.1.
*/
-
- // FIXME this method incorrectly returns false for certain primes, notably
- // 38737, 61681, 65537, 229153, and 274177.
- public static boolean passEulerCriterion(final BigInteger w)
+ public static boolean passEulerCriterion(final BigInteger bn)
{
- // first check if it's already a known prime
- WeakReference obj = (WeakReference) knownPrimes.get(w);
- if (obj != null && w.equals(obj.get()))
- {
- if (DEBUG && debuglevel > 4)
- {
- debug("found in known primes");
- }
- return true;
- }
-
- BigInteger w_minus_one = w.subtract(ONE);
- BigInteger e = w_minus_one;
+ BigInteger bn_minus_one = bn.subtract(ONE);
+ BigInteger e = bn_minus_one;
// l is the 3 least-significant bits of e
int l = e.and(BigInteger.valueOf(7L)).intValue();
int j = 1; // Where to start in prime array for strong prime tests
- BigInteger A;
+ BigInteger a;
int k;
- if ((l & 7) != 0)
+ if (l != 0)
{
e = e.shiftRight(1);
- A = TWO.modPow(e, w);
- if ((l & 7) == 6)
- { // bn == 7 mod 8, expect +1
- if (A.bitCount() != 1)
+ a = TWO.modPow(e, bn);
+ if (l == 6) // bn == 7 mod 8, expect +1
+ {
+ if (a.bitLength() != 1)
{
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " fails Euler criterion #1...");
- }
+ debugBI("Fails Euler criterion #1", bn);
return false; // Not prime
}
k = 1;
}
- else
- { // bn == 3 or 5 mod 8, expect -1 == bn-1
- A = A.add(ONE);
- if (!A.equals(w))
+ else // bn == 3 or 5 mod 8, expect -1 == bn-1
+ {
+ a = a.add(ONE);
+ if (a.compareTo(bn) != 0)
{
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " fails Euler criterion #2...");
- }
+ debugBI("Fails Euler criterion #2", bn);
return false; // Not prime
}
k = 1;
- if ((l & 4) != 0)
- { // bn == 5 mod 8, make odd for strong tests
+ if ((l & 4) != 0) // bn == 5 mod 8, make odd for strong tests
+ {
e = e.shiftRight(1);
k = 2;
}
}
}
- else
- { // bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn
+ else // bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn
+ {
e = e.shiftRight(2);
- A = TWO.modPow(e, w);
- if (A.bitCount() == 1)
- {
- j = 0; // Re-do strong prime test to base 2
- }
+ a = TWO.modPow(e, bn);
+ if (a.bitLength() == 1)
+ j = 0; // Re-do strong prime test to base 2
else
{
- A = A.add(ONE);
- if (!A.equals(w))
+ a = a.add(ONE);
+ if (a.compareTo(bn) != 0)
{
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " fails Euler criterion #3...");
- }
+ debugBI("Fails Euler criterion #3", bn);
return false; // Not prime
}
}
@@ -329,187 +301,38 @@ public class Prime2
// when the previous test was as good as a strong prime test, but 1/8 of
// the time, j = 0 because the strong prime test to the base 2 needs to
// be re-done.
- //for (int i = j; i < SMALL_PRIME_COUNT; i++) {
- for (int i = j; i < 13; i++)
- { // try only the first 13 primes
- A = SMALL_PRIME[i];
- A = A.modPow(e, w);
- if (A.bitCount() == 1)
- {
- continue; // Passed this test
- }
+ for (int i = j; i < 7; i++) // try only the first 7 primes
+ {
+ a = SMALL_PRIME[i];
+ a = a.modPow(e, bn);
+ if (a.bitLength() == 1)
+ continue; // Passed this test
+
l = k;
while (true)
{
- // A = A.add(ONE);
- // if (A.equals(w)) { // Was result bn-1?
- if (A.equals(w_minus_one))
- { // Was result bn-1?
- break; // Prime
- }
- if (--l == 0)
- { // Reached end, not -1? luck?
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " fails Euler criterion #4...");
- }
+// a = a.add(ONE);
+// if (a.compareTo(w) == 0) { // Was result bn-1?
+ if (a.compareTo(bn_minus_one) == 0) // Was result bn-1?
+ break; // Prime
+
+ if (--l == 0) // Reached end, not -1? luck?
+ {
+ debugBI("Fails Euler criterion #4", bn);
return false; // Failed, not prime
}
// This portion is executed, on average, once
- // A = A.subtract(ONE); // Put a back where it was
- A = A.modPow(TWO, w);
- if (A.bitCount() == 1)
+// a = a.subtract(ONE); // Put a back where it was
+ a = a.modPow(TWO, bn);
+ if (a.bitLength() == 1)
{
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " fails Euler criterion #5...");
- }
+ debugBI("Fails Euler criterion #5", bn);
return false; // Failed, not prime
}
}
// It worked (to the base primes[i])
}
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " passes Euler criterion...");
- }
-
- // store it in the known primes weak hash-map
- knownPrimes.put(w, new WeakReference(w));
-
- return true;
- }
-
- /**
- * <p>Checks Fermat's Little Theorem for base <i>b</i>; i.e.
- * <code><i>b</i>**(w-1) == 1 (mod w)</code>.</p>
- *
- * @param w the number to test.
- * @param t the number of random bases to test.
- * @return <code>true</code> iff <code><i>b</i>**(w-1) == 1 (mod w)</code>,
- * for some <i>b</i>.
- */
- public static boolean passFermatLittleTheorem(final BigInteger w, int t)
- {
- final BigInteger w_minus_one = w.subtract(ONE);
- if (t <= 0)
- {
- t = 10; // XXX
- }
- if (!TWO.modPow(w_minus_one, w).equals(ONE))
- {
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " fails Fermat's little theorem for base 2");
- }
- return false;
- }
- for (int i = 0; i < t; i++)
- {
- byte[] buf = new byte[(w.bitLength() + 7) / 8 - 1];
- BigInteger base = null;
- do
- {
- new Random ().nextBytes(buf);
- base = new BigInteger(1, buf);
- }
- while (base.compareTo(TWO) < 0 || base.compareTo(w_minus_one) > 0);
- if (!base.modPow(w_minus_one, w).equals(ONE))
- {
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16)
- + " fails Fermat's little theorem for base "
- + base.toString(16));
- }
- return false;
- }
- }
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " passes Fermat's little theorem for " + t
- + " bases...");
- }
- return true;
- }
-
- /**
- * <p>Applies the Miller-Rabin strong probabilistic primality test.</p>
- *
- * <p>The HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Note
- * 4.57 states that for <code>q</code>, <code>n=18</code> is enough while
- * for <code>p</code>, <code>n=6</code> (512 bits) or <code>n=3</cdoe> (1024
- * bits) are enough to yield <i>robust</i> primality tests. The values used
- * are from table 4.4 given in Note 4.49.</p>
- *
- * @param w the number to test.
- * @return <code>true</code> iff the designated number passes the Miller-
- * Rabin probabilistic primality test for a computed number of rounds.
- */
- public static boolean passMillerRabin(BigInteger n, int t)
- {
- int nbytes = (n.bitLength() + 7) / 8;
- byte[] ab = new byte[nbytes];
-
- // 1. Write n - 1 = 2^s * r.
- BigInteger n_minus_1 = n.subtract(ONE);
- BigInteger r = n_minus_1;
- int s = 0;
- while (!r.testBit(0))
- {
- r = r.shiftRight(1);
- s++;
- }
-
- // 2. For i from 1 to t, do:
- for (int i = 0; i < t; i++)
- {
-
- // 2.1 Choose a random integer a, 2 <= a <= n - 2.
- BigInteger a;
- do
- {
- new Random ().nextBytes(ab);
- a = new BigInteger(1, ab);
- }
- while (a.compareTo(TWO) < 0 || a.compareTo(n) > 0);
-
- // 2.2 Compute y = a^r mod n.
- BigInteger y = a.modPow(r, n);
-
- // If y != 1 and y != n - 1, then:
- if (!y.equals(ONE) && !y.equals(n_minus_1))
- {
- for (int j = 1; j < s - 1 && !y.equals(n_minus_1); j++)
- {
- // Compute y = y^2 mod n.
- y = y.modPow(TWO, n);
-
- // If y = 1 return "composite"
- if (y.equals(ONE))
- {
- if (DEBUG && debuglevel > 4)
- {
- debug(n.toString(16) + " fails Miller-Rabin test...");
- }
- return false;
- }
- }
- // If y != n - 1 return "composite"
- if (!y.equals(n_minus_1))
- {
- if (DEBUG && debuglevel > 4)
- {
- debug(n.toString(16) + " fails Miller-Rabin test...");
- }
- return false;
- }
- }
- }
- if (DEBUG && debuglevel > 4)
- {
- debug(n.toString(16) + " passes Miller-Rabin test...");
- }
+ debugBI("Passes Euler criterion", bn);
return true;
}
@@ -519,114 +342,76 @@ public class Prime2
}
/**
- * <p>This implementation does not rely solely on the Miller-Rabin strong
- * probabilistic primality test to claim the primality of the designated
- * number. It instead, tries dividing the designated number by the first 1000
- * small primes, and if no divisor was found, invokes a port of Colin Plumb's
- * implementation of the Euler Criterion, then tries the Miller-Rabin test.</p>
+ * Wrapper around {@link BigInteger#isProbablePrime(int)} with few pre-checks.
*
* @param w the integer to test.
* @param certainty the certainty with which to compute the test.
- * @param doMillerRabin if <code>true</code> and the designated integer was
- * already found to be a probable prime, then also do a Miller-Rabin test.
- * @return <code>true</code> iff the designated number has no small prime
- * divisor passes the Euler criterion, and optionally a Miller-Rabin test.
*/
public static boolean isProbablePrime(BigInteger w, int certainty)
{
// Nonnumbers are not prime.
if (w == null)
- {
return false;
- }
// eliminate trivial cases when w == 0 or 1
if (w.equals(ZERO) || w.equals(ONE))
- {
return false;
- }
// Test if w is a known small prime.
for (int i = 0; i < SMALL_PRIME_COUNT; i++)
- {
if (w.equals(SMALL_PRIME[i]))
{
if (DEBUG && debuglevel > 4)
- {
debug(w.toString(16) + " is a small prime");
- }
return true;
}
- }
- // trial division with first 1000 primes
- if (hasSmallPrimeDivisor(w))
+ // Check if it's already a known prime
+ WeakReference obj = (WeakReference) knownPrimes.get(w);
+ if (obj != null && w.equals(obj.get()))
{
if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " has a small prime divisor. Rejected...");
- }
- return false;
+ debug("found in known primes");
+ return true;
}
- // Do a check with Fermat's little theorem.
- // if (passFermatLittleTheorem(w, certainty)) {
- // if (DEBUG && debuglevel > 4) {
- // debug(w.toString(16)+" passes Fermat's little theorem...");
- // }
- // } else {
- // if (DEBUG && debuglevel > 4) {
- // debug(w.toString(16)+" fails Fermat's little theorem. Rejected...");
- // }
- // return false;
- // }
-
- // Euler's criterion.
- // if (passEulerCriterion(w)) {
- // if (DEBUG && debuglevel > 4) {
- // debug(w.toString(16)+" passes Euler's criterion...");
- // }
- // } else {
- // if (DEBUG && debuglevel > 4) {
- // debug(w.toString(16)+" fails Euler's criterion. Rejected...");
- // }
- // return false;
- // }
-
- // Miller-Rabin probabilistic primality test.
- if (passMillerRabin(w, certainty))
- {
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " passes Miller-Rabin PPT...");
- }
- }
- else
+ // trial division with first 1000 primes
+ if (hasSmallPrimeDivisor(w))
{
if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " fails Miller-Rabin PPT. Rejected...");
- }
+ debug(w.toString(16) + " has a small prime divisor. Rejected...");
return false;
}
- if (DEBUG && debuglevel > 4)
- {
- debug(w.toString(16) + " is probable prime. Accepted...");
- }
+// Euler's criterion.
+// if (passEulerCriterion(w)) {
+// if (DEBUG && debuglevel > 4) {
+// debug(w.toString(16)+" passes Euler's criterion...");
+// }
+// } else {
+// if (DEBUG && debuglevel > 4) {
+// debug(w.toString(16)+" fails Euler's criterion. Rejected...");
+// }
+// return false;
+// }
+//
+// if (DEBUG && debuglevel > 4)
+// {
+// debug(w.toString(16) + " is probable prime. Accepted...");
+// }
+
+ boolean result = w.isProbablePrime(certainty);
+ if (result && certainty > 0) // store it in the known primes weak hash-map
+ knownPrimes.put(w, new WeakReference(w));
+
+ return result;
+ }
- // now compare to JDK primality test
- if (DEBUG && debuglevel > 0 && !w.isProbablePrime(certainty))
- {
- System.err.println("The gnu.crypto library and the JDK disagree on "
- + "whether 0x" + w.toString(16)
- + " is a probable prime or not.");
- System.err.println("While this library claims it is, the JDK claims"
- + " the opposite.");
- System.err.println("Please contact the maintainer of this library, "
- + "and provide this message for further investigation. TIA");
- }
+ // helper methods -----------------------------------------------------------
- return true;
+ private static final void debugBI(String msg, BigInteger bn)
+ {
+ if (DEBUG && debuglevel > 4)
+ debug("*** " + msg + ": 0x" + bn.toString(16));
}
}
diff --git a/gnu/java/security/x509/ext/GeneralNames.java b/gnu/java/security/x509/ext/GeneralNames.java
index e92aedaef..dae94cd9f 100644
--- a/gnu/java/security/x509/ext/GeneralNames.java
+++ b/gnu/java/security/x509/ext/GeneralNames.java
@@ -52,6 +52,8 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import javax.security.auth.x500.X500Principal;
+
public class GeneralNames
{
@@ -81,12 +83,14 @@ public class GeneralNames
if (!nameList.isConstructed())
throw new IOException("malformed GeneralNames");
int len = 0;
+ int i = 0;
while (len < nameList.getLength())
{
DERValue name = der.read();
List namePair = new ArrayList(2);
- if (name.getTagClass() != DER.APPLICATION)
- throw new IOException("malformed GeneralName");
+ int tagClass = name.getTagClass();
+ if (tagClass != DER.CONTEXT)
+ throw new IOException("malformed GeneralName: Tag class is " + tagClass);
namePair.add(new Integer(name.getTag()));
DERValue val = null;
switch (name.getTag())
@@ -99,6 +103,15 @@ public class GeneralNames
break;
case OTHER_NAME:
+ // MUST return the encoded bytes of the OID/OctetString sequence
+ byte[] anotherName = name.getEncoded();
+ anotherName[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE);
+ namePair.add(anotherName);
+ // DERReader goes back on Constructed things so we need to skip over them
+ DERValue skip = der.read(); // skip OID
+ skip = der.read(); // skip Octet String
+ break;
+
case EDI_PARTY_NAME:
namePair.add(name.getValue());
break;
@@ -106,7 +119,9 @@ public class GeneralNames
case DIRECTORY_NAME:
byte[] b = name.getEncoded();
b[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE);
- namePair.add(new X500DistinguishedName(b).toString());
+ DERReader r = new DERReader (b);
+ r.read ();
+ namePair.add(new X500Principal(r.read ().getEncoded ()).toString());
break;
case IP_ADDRESS: