- /*
- * @(#)SecureRandom.java 1.36 00/02/02
- *
- * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the proprietary information of Sun Microsystems, Inc.
- * Use is subject to license terms.
- *
- */
-
- package java.security;
-
- import java.util.Enumeration;
-
- /**
- * <p>This class provides a cryptographically strong pseudo-random number
- * generator (PRNG).
- *
- * <p>Like other algorithm-based classes in Java Security, SecureRandom
- * provides implementation-independent algorithms, whereby a caller
- * (application code) requests a particular PRNG algorithm
- * and is handed back a SecureRandom object for that algorithm. It is
- * also possible, if desired, to request a particular algorithm from a
- * particular provider. See the <code>getInstance</code> methods.
- *
- * <p>Thus, there are two ways to request a SecureRandom object: by
- * specifying either just an algorithm name, or both an algorithm name
- * and a package provider.
- *
- * <ul>
- *
- * <li>If just an algorithm name is specified, as in:
- * <pre>
- * SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
- * </pre>
- * the system will determine if there is an implementation of the algorithm
- * requested available in the environment, and if there is more than one, if
- * there is a preferred one.<p>
- *
- * <li>If both an algorithm name and a package provider are specified, as in:
- * <pre>
- * SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
- * </pre>
- * the system will determine if there is an implementation of the
- * algorithm in the package requested, and throw an exception if there
- * is not.
- *
- * </ul>
- *
- * <p>The SecureRandom implementation attempts to completely
- * randomize the internal state of the generator itself unless
- * the caller follows the call to a <code>getInstance</code> method
- * with a call to the <code>setSeed</code> method:
- * <pre>
- * SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
- * random.setSeed(seed);
- * </pre>
- *
- * <p>After the caller obtains the SecureRandom object from the
- * <code>getInstance</code> call, it can call <code>nextBytes</code>
- * to generate random bytes:
- * <pre>
- * byte bytes[] = new byte[20];
- * random.nextBytes(bytes);
- * </pre>
- *
- * <p>The caller may also invoke the <code>generateSeed</code> method
- * to generate a given number of seed bytes (to seed other random number
- * generators, for example):
- * <pre>
- * byte seed[] = random.generateSeed(20);
- * </pre>
- *
- * @see java.security.SecureRandomSpi
- * @see java.util.Random
- *
- * @version 1.36, 02/02/00
- * @author Benjamin Renaud
- * @author Josh Bloch
- */
-
- public class SecureRandom extends java.util.Random {
-
- /**
- * The provider.
- *
- * @serial
- * @since 1.2
- */
- private Provider provider = null;
-
- /**
- * The provider implementation.
- *
- * @serial
- * @since 1.2
- */
- private SecureRandomSpi secureRandomSpi = null;
-
- // Seed Generator
- private static SecureRandom seedGenerator = null;
-
- /**
- * <p>By using this constructor, the caller obtains a SecureRandom object
- * containing the implementation from the highest-priority installed
- * provider that has a SecureRandom implementation.
- *
- * <p>Note that this instance of SecureRandom has not been seeded.
- * A call to the <code>setSeed</code> method will seed the SecureRandom
- * object. If a call is not made to <code>setSeed</code>, the first call
- * to the <code>nextBytes</code> method will force the SecureRandom object
- * to seed itself.
- *
- * <p>This constructor is provided for backwards compatibility.
- * The caller is encouraged to use one of the alternative
- * <code>getInstance</code> methods to obtain a SecureRandom object.
- */
- public SecureRandom() {
- /*
- * This call to our superclass constructor will result in a call
- * to our own <code>setSeed</code> method, which will return
- * immediately when it is passed zero.
- */
- super(0);
- String prng = getPrngAlgorithm();
- if (prng == null) {
- // bummer, get the SUN implementation
- this.secureRandomSpi = new sun.security.provider.SecureRandom();
- this.provider = new sun.security.provider.Sun();
- } else {
- try {
- SecureRandom random = SecureRandom.getInstance(prng);
- this.secureRandomSpi = random.getSecureRandomSpi();
- this.provider = random.getProvider();
- } catch (NoSuchAlgorithmException nsae) {
- // never happens, because we made sure the algorithm exists
- }
- }
- }
-
- /**
- * <p>By using this constructor, the caller obtains a SecureRandom object
- * containing the implementation from the highest-priority installed
- * provider that has a SecureRandom implementation. This constructor
- * uses a user-provided seed in
- * preference to the self-seeding algorithm referred to in the empty
- * constructor description. It may be preferable to the empty constructor
- * if the caller has access to high-quality random bytes from some physical
- * device (for example, a radiation detector or a noisy diode).
- *
- * <p>This constructor is provided for backwards compatibility.
- * The caller is encouraged to use one of the alternative
- * <code>getInstance</code> methods to obtain a SecureRandom object, and
- * then to call the <code>setSeed</code> method to seed it.
- *
- * @param seed the seed.
- */
- public SecureRandom(byte seed[]) {
- super(0);
- String prng = getPrngAlgorithm();
- if (prng == null) {
- // bummer, get the SUN implementation
- this.secureRandomSpi = new sun.security.provider.SecureRandom();
- this.provider = new sun.security.provider.Sun();
- this.secureRandomSpi.engineSetSeed(seed);
- } else {
- try {
- SecureRandom random = getInstance(prng);
- this.secureRandomSpi = random.getSecureRandomSpi();
- this.provider = random.getProvider();
- this.secureRandomSpi.engineSetSeed(seed);
- } catch (NoSuchAlgorithmException nsae) {
- // never happens, because we made sure the algorithm exists
- }
- }
- }
-
- /**
- * Creates a SecureRandom object.
- *
- * @param secureRandomSpi the SecureRandom implementation.
- * @param provider the provider.
- */
- protected SecureRandom(SecureRandomSpi secureRandomSpi,
- Provider provider) {
- super(0);
- this.secureRandomSpi = secureRandomSpi;
- this.provider = provider;
- }
-
- /**
- * Generates a SecureRandom object that implements the specified
- * Pseudo Random Number Generator (PRNG) algorithm. If the default
- * provider package provides an implementation of the requested PRNG,
- * an instance of SecureRandom containing that implementation is returned.
- * If the PRNG is not available in the default
- * package, other packages are searched.
- *
- * <p>Note that the returned instance of SecureRandom has not been seeded.
- * A call to the <code>setSeed</code> method will seed the SecureRandom
- * object. If a call is not made to <code>setSeed</code>, the first call
- * to the <code>nextBytes</code> method will force the SecureRandom object
- * to seed itself.
- *
- * @param algorithm the name of the PRNG algorithm.
- * See Appendix A in the <a href=
- * "../../../guide/security/CryptoSpec.html#AppA">
- * Java Cryptography Architecture API Specification & Reference </a>
- * for information about standard PRNG algorithm names.
- *
- * @return the new SecureRandom object.
- *
- * @exception NoSuchAlgorithmException if the PRNG algorithm is
- * not available in the caller's environment.
- *
- * @since 1.2
- */
- public static SecureRandom getInstance(String algorithm)
- throws NoSuchAlgorithmException {
- try {
- Object[] objs = Security.getImpl(algorithm,
- "SecureRandom",
- null);
- return new SecureRandom((SecureRandomSpi)objs[0],
- (Provider)objs[1]);
- } catch(NoSuchProviderException e) {
- throw new NoSuchAlgorithmException(algorithm + " not found");
- }
- }
-
- /**
- * Generates a SecureRandom object for the specified PRNG
- * algorithm, as supplied from the specified provider, if such a
- * PRNG implementation is available from the provider.
- *
- * <p>Note that the returned instance of SecureRandom has not been seeded.
- * A call to the <code>setSeed</code> method will seed the SecureRandom
- * object. If a call is not made to <code>setSeed</code>, the first call
- * to the <code>nextBytes</code> method will force the SecureRandom object
- * to seed itself.
- *
- * @param algorithm the name of the PRNG algorithm.
- * See Appendix A in the <a href=
- * "../../../guide/security/CryptoSpec.html#AppA">
- * Java Cryptography Architecture API Specification & Reference </a>
- * for information about standard PRNG algorithm names.
- *
- * @param provider the name of the provider.
- *
- * @return the new SecureRandom object.
- *
- * @exception NoSuchAlgorithmException if the requested PRNG
- * implementation is not available from the provider.
- *
- * @exception NoSuchProviderException if the provider has not been
- * configured.
- *
- * @see Provider
- *
- * @since 1.2
- */
- public static SecureRandom getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
- {
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("missing provider");
- Object[] objs = Security.getImpl(algorithm, "SecureRandom", provider);
- return new SecureRandom((SecureRandomSpi)objs[0], (Provider)objs[1]);
- }
-
- /**
- * Returns the SecureRandomSpi of this SecureRandom object.
- */
- SecureRandomSpi getSecureRandomSpi() {
- return secureRandomSpi;
- }
-
- /**
- * Returns the provider of this SecureRandom object.
- *
- * @return the provider of this SecureRandom object.
- */
- public final Provider getProvider() {
- return provider;
- }
-
- /**
- * Reseeds this random object. The given seed supplements, rather than
- * replaces, the existing seed. Thus, repeated calls are guaranteed
- * never to reduce randomness.
- *
- * @param seed the seed.
- */
- synchronized public void setSeed(byte[] seed) {
- secureRandomSpi.engineSetSeed(seed);
- }
-
- /**
- * Reseeds this random object, using the eight bytes contained
- * in the given <code>long seed</code>. The given seed supplements,
- * rather than replaces, the existing seed. Thus, repeated calls
- * are guaranteed never to reduce randomness.
- *
- * <p>This method is defined for compatibility with
- * <code>java.util.Random</code>.
- *
- * @param seed the seed.
- */
- public void setSeed(long seed) {
- /*
- * Ignore call from super constructor (as well as any other calls
- * unfortunate enough to be passing 0). It's critical that we
- * ignore call from superclass constructor, as digest has not
- * yet been initialized at that point.
- */
- if (seed != 0)
- secureRandomSpi.engineSetSeed(longToByteArray(seed));
- }
-
- /**
- * Generates a user-specified number of random bytes. This method is
- * used as the basis of all random entities returned by this class
- * (except seed bytes).
- *
- * @param bytes the array to be filled in with random bytes.
- */
-
- synchronized public void nextBytes(byte[] bytes) {
- secureRandomSpi.engineNextBytes(bytes);
- }
-
- /**
- * Generates an integer containing the user-specified number of
- * pseudo-random bits (right justified, with leading zeros). This
- * method overrides a <code>java.util.Random</code> method, and serves
- * to provide a source of random bits to all of the methods inherited
- * from that class (for example, <code>nextInt</code>,
- * <code>nextLong</code>, and <code>nextFloat</code>).
- *
- * @param numBits number of pseudo-random bits to be generated, where
- * 0 <= <code>numBits</code> <= 32.
- *
- * @return an <code>int</code> containing the user-specified number
- * of pseudo-random bits (right justified, with leading zeros).
- */
- final protected int next(int numBits) {
- int numBytes = (numBits+7)/8;
- byte b[] = new byte[numBytes];
- int next = 0;
-
- nextBytes(b);
- for (int i=0; i<numBytes; i++)
- next = (next << 8) + (b[i] & 0xFF);
-
- return next >>> (numBytes*8 - numBits);
- }
-
- /**
- * Returns the given number of seed bytes, computed using the seed
- * generation algorithm that this class uses to seed itself. This
- * call may be used to seed other random number generators.
- *
- * <p>This method is only included for backwards compatibility.
- * The caller is encouraged to use one of the alternative
- * <code>getInstance</code> methods to obtain a SecureRandom object, and
- * then call the <code>generateSeed</code> method to obtain seed bytes
- * from that object.
- *
- * @param numBytes the number of seed bytes to generate.
- *
- * @return the seed bytes.
- */
- public static byte[] getSeed(int numBytes) {
- if (seedGenerator == null)
- seedGenerator = new SecureRandom();
- return seedGenerator.generateSeed(numBytes);
- }
-
- /**
- * Returns the given number of seed bytes, computed using the seed
- * generation algorithm that this class uses to seed itself. This
- * call may be used to seed other random number generators.
- *
- * @param numBytes the number of seed bytes to generate.
- *
- * @return the seed bytes.
- */
- public byte[] generateSeed(int numBytes) {
- return secureRandomSpi.engineGenerateSeed(numBytes);
- }
-
- /**
- * Helper function to convert a long into a byte array (least significant
- * byte first).
- */
- private static byte[] longToByteArray(long l) {
- byte[] retVal = new byte[8];
-
- for (int i=0; i<8; i++) {
- retVal[i] = (byte) l;
- l >>= 8;
- }
-
- return retVal;
- }
-
- /**
- * Gets a default PRNG algorithm by looking through all registered
- * providers. Returns the first PRNG algorithm of the first provider that
- * has registered a SecureRandom implementation, or null if none of the
- * registered providers supplies a SecureRandom implementation.
- */
- private static String getPrngAlgorithm() {
- Provider[] provs = Security.getProviders();
- for (int i=0; i<provs.length; i++) {
- // search the provider's properties list for a property name
- // that starts with "SecureRandom."
- for (Enumeration e = provs[i].propertyNames();
- e.hasMoreElements();) {
- String propName = (String)e.nextElement();
- if (propName.startsWith("SecureRandom.")) {
- int index = propName.indexOf(".", 0);
- return propName.substring(index+1);
- }
- }
- }
- return null;
- }
-
- // Declare serialVersionUID to be compatible with JDK1.1
- static final long serialVersionUID = 4940670005562187L;
-
- // Retain unused values serialized from JDK1.1
- /**
- * @serial
- */
- private byte[] state;
- /**
- * @serial
- */
- private MessageDigest digest = null;
- /**
- * @serial
- *
- * We know that the MessageDigest class does not implement
- * java.io.Serializable. However, since this field is no longer
- * used, it will always be NULL and won't affect the serialization
- * of the SecureRandom class itself.
- */
- private byte[] randomBytes;
- /**
- * @serial
- */
- private int randomBytesUsed;
- /**
- * @serial
- */
- private long counter;
- }