diff options
author | Guilhem Lavaux <guilhem@kaffe.org> | 2006-02-04 18:38:03 +0000 |
---|---|---|
committer | Guilhem Lavaux <guilhem@kaffe.org> | 2006-02-04 18:38:03 +0000 |
commit | 3af9dde820e3a7f8194964ec9dcc8539dd4af2b8 (patch) | |
tree | 7abe48072a9d59def3ea20a23d9609435d1a4548 /gnu/java/security | |
parent | a92748b017d37f8e4a83997933c5850f9484df9d (diff) | |
download | classpath-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.java | 29 | ||||
-rw-r--r-- | gnu/java/security/der/DERWriter.java | 6 | ||||
-rw-r--r-- | gnu/java/security/jce/sig/DSSKeyPairGeneratorSpi.java | 80 | ||||
-rw-r--r-- | gnu/java/security/jce/sig/KeyPairGeneratorAdapter.java | 8 | ||||
-rw-r--r-- | gnu/java/security/key/dss/DSSKeyPairGenerator.java | 80 | ||||
-rw-r--r-- | gnu/java/security/key/dss/FIPS186.java | 20 | ||||
-rw-r--r-- | gnu/java/security/key/rsa/RSAKeyPairGenerator.java | 16 | ||||
-rw-r--r-- | gnu/java/security/sig/BaseSignature.java | 17 | ||||
-rw-r--r-- | gnu/java/security/sig/rsa/EME_PKCS1_V1_5.java | 9 | ||||
-rw-r--r-- | gnu/java/security/sig/rsa/RSA.java | 11 | ||||
-rw-r--r-- | gnu/java/security/util/PRNG.java | 156 | ||||
-rw-r--r-- | gnu/java/security/util/Prime2.java | 383 | ||||
-rw-r--r-- | gnu/java/security/x509/ext/GeneralNames.java | 21 |
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> < 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 @@ -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: |