001/* SecureRandom.java --- Secure Random class implementation
002   Copyright (C) 1999, 2001, 2002, 2003, 2005, 2006
003   Free Software Foundation, Inc.
004
005This file is part of GNU Classpath.
006
007GNU Classpath is free software; you can redistribute it and/or modify
008it under the terms of the GNU General Public License as published by
009the Free Software Foundation; either version 2, or (at your option)
010any later version.
011
012GNU Classpath is distributed in the hope that it will be useful, but
013WITHOUT ANY WARRANTY; without even the implied warranty of
014MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015General Public License for more details.
016
017You should have received a copy of the GNU General Public License
018along with GNU Classpath; see the file COPYING.  If not, write to the
019Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02002110-1301 USA.
021
022Linking this library statically or dynamically with other modules is
023making a combined work based on this library.  Thus, the terms and
024conditions of the GNU General Public License cover the whole
025combination.
026
027As a special exception, the copyright holders of this library give you
028permission to link this library with independent modules to produce an
029executable, regardless of the license terms of these independent
030modules, and to copy and distribute the resulting executable under
031terms of your choice, provided that you also meet, for each linked
032independent module, the terms and conditions of the license of that
033module.  An independent module is a module which is not derived from
034or based on this library.  If you modify this library, you may extend
035this exception to your version of the library, but you are not
036obligated to do so.  If you do not wish to do so, delete this
037exception statement from your version. */
038
039package java.security;
040
041import gnu.classpath.SystemProperties;
042import gnu.java.lang.CPStringBuilder;
043import gnu.java.security.Engine;
044import gnu.java.security.action.GetSecurityPropertyAction;
045import gnu.java.security.jce.prng.SecureRandomAdapter;
046import gnu.java.security.jce.prng.Sha160RandomSpi;
047
048import java.io.IOException;
049import java.io.InputStream;
050import java.lang.reflect.InvocationTargetException;
051import java.net.MalformedURLException;
052import java.net.URL;
053import java.util.Enumeration;
054import java.util.Random;
055import java.util.logging.Level;
056import java.util.logging.Logger;
057
058/**
059 * An interface to a cryptographically secure pseudo-random number
060 * generator (PRNG). Random (or at least unguessable) numbers are used
061 * in all areas of security and cryptography, from the generation of
062 * keys and initialization vectors to the generation of random padding
063 * bytes.
064 *
065 * @author Mark Benvenuto (ivymccough@worldnet.att.net)
066 * @author Casey Marshall
067 */
068public class SecureRandom extends Random
069{
070
071  // Constants and fields.
072  // ------------------------------------------------------------------------
073
074  /** Service name for PRNGs. */
075  private static final String SECURE_RANDOM = "SecureRandom";
076
077  private static final long serialVersionUID = 4940670005562187L;
078
079  //Serialized Field
080  long counter = 0;             //Serialized
081  Provider provider = null;
082  byte[] randomBytes = null;    //Always null
083  int randomBytesUsed = 0;
084  SecureRandomSpi secureRandomSpi = null;
085  byte[] state = null;
086  private String algorithm;
087
088  private boolean isSeeded = false;
089
090  // Constructors.
091  // ------------------------------------------------------------------------
092
093  /**
094     Default constructor for SecureRandom. It constructs a
095     new SecureRandom by instantating the first SecureRandom
096     algorithm in the default security provier.
097
098     It is not seeded and should be seeded using setSeed or else
099     on the first call to getnextBytes it will force a seed.
100
101     It is maintained for backwards compatibility and programs
102     should use {@link #getInstance(java.lang.String)}.
103   */
104  public SecureRandom()
105  {
106    Provider[] p = Security.getProviders();
107
108    //Format of Key: SecureRandom.algname
109    String key;
110
111    String classname = null;
112    int i;
113    Enumeration e;
114    for (i = 0; i < p.length; i++)
115      {
116        e = p[i].propertyNames();
117        while (e.hasMoreElements())
118          {
119            key = (String) e.nextElement();
120            if (key.startsWith("SECURERANDOM."))
121              {
122                if ((classname = p[i].getProperty(key)) != null)
123                  {
124                    try
125                      {
126                        secureRandomSpi = (SecureRandomSpi) Class.
127                          forName(classname).newInstance();
128                        provider = p[i];
129                        algorithm = key.substring(13); // Minus SecureRandom.
130                        return;
131                      }
132                    catch (ThreadDeath death)
133                      {
134                        throw death;
135                      }
136                    catch (Throwable t)
137                      {
138                        // Ignore.
139                      }
140                  }
141              }
142          }
143      }
144
145    // Nothing found. Fall back to SHA1PRNG
146    secureRandomSpi = new Sha160RandomSpi();
147    algorithm = "Sha160";
148  }
149
150  /**
151     A constructor for SecureRandom. It constructs a new
152     SecureRandom by instantating the first SecureRandom algorithm
153     in the default security provier.
154
155     It is seeded with the passed function and is useful if the user
156     has access to hardware random device (like a radiation detector).
157
158     It is maintained for backwards compatibility and programs
159     should use getInstance.
160
161     @param seed Seed bytes for class
162   */
163  public SecureRandom(byte[] seed)
164  {
165    this();
166    setSeed(seed);
167  }
168
169  /**
170     A constructor for SecureRandom. It constructs a new
171     SecureRandom using the specified SecureRandomSpi from
172     the specified security provier.
173
174     @param secureRandomSpi A SecureRandomSpi class
175     @param provider A Provider class
176   */
177  protected SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider)
178  {
179    this(secureRandomSpi, provider, "unknown");
180  }
181
182  /**
183   * Private constructor called from the getInstance() method.
184   */
185  private SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider,
186                       String algorithm)
187  {
188    this.secureRandomSpi = secureRandomSpi;
189    this.provider = provider;
190    this.algorithm = algorithm;
191  }
192
193  /**
194   * Returns an instance of a <code>SecureRandom</code> from the first provider
195   * that implements it.
196   *
197   * @param algorithm The algorithm name.
198   * @return A new <code>SecureRandom</code> implementing the given algorithm.
199   * @throws NoSuchAlgorithmException If no installed provider implements the
200   *           given algorithm.
201   * @throws IllegalArgumentException if <code>algorithm</code> is
202   *           <code>null</code> or is an empty string.
203   */
204  public static SecureRandom getInstance(String algorithm)
205      throws NoSuchAlgorithmException
206  {
207    Provider[] p = Security.getProviders();
208    NoSuchAlgorithmException lastException = null;
209    for (int i = 0; i < p.length; i++)
210      try
211        {
212          return getInstance(algorithm, p[i]);
213        }
214      catch (NoSuchAlgorithmException x)
215        {
216          lastException = x;
217        }
218    if (lastException != null)
219      throw lastException;
220    throw new NoSuchAlgorithmException(algorithm);
221  }
222
223  /**
224   * Returns an instance of a <code>SecureRandom</code> for the specified
225   * algorithm from the named provider.
226   *
227   * @param algorithm The algorithm name.
228   * @param provider The provider name.
229   * @return A new <code>SecureRandom</code> implementing the chosen
230   *         algorithm.
231   * @throws NoSuchAlgorithmException If the named provider does not implement
232   *           the algorithm, or if the implementation cannot be instantiated.
233   * @throws NoSuchProviderException If no provider named <code>provider</code>
234   *           is currently installed.
235   * @throws IllegalArgumentException if either <code>algorithm</code> or
236   *           <code>provider</code> is <code>null</code> or empty.
237   */
238  public static SecureRandom getInstance(String algorithm, String provider)
239      throws NoSuchAlgorithmException, NoSuchProviderException
240  {
241    if (provider == null)
242      throw new IllegalArgumentException("provider MUST NOT be null");
243    provider = provider.trim();
244    if (provider.length() == 0)
245      throw new IllegalArgumentException("provider MUST NOT be empty");
246    Provider p = Security.getProvider(provider);
247    if (p == null)
248      throw new NoSuchProviderException(provider);
249    return getInstance(algorithm, p);
250  }
251
252  /**
253   * Returns an instance of a <code>SecureRandom</code> for the specified
254   * algorithm from the given provider.
255   *
256   * @param algorithm The <code>SecureRandom</code> algorithm to create.
257   * @param provider The provider to use.
258   * @throws NoSuchAlgorithmException If the algorithm cannot be found, or if
259   *           the class cannot be instantiated.
260   * @throws IllegalArgumentException if either <code>algorithm</code> or
261   *           <code>provider</code> is <code>null</code>, or if
262   *           <code>algorithm</code> is an empty string.
263   */
264  public static SecureRandom getInstance(String algorithm, Provider provider)
265      throws NoSuchAlgorithmException
266  {
267    CPStringBuilder sb = new CPStringBuilder("SecureRandom for algorithm [")
268        .append(algorithm).append("] from provider[")
269        .append(provider).append("] could not be created");
270    Throwable cause;
271    try
272      {
273        Object spi = Engine.getInstance(SECURE_RANDOM, algorithm, provider);
274        return new SecureRandom((SecureRandomSpi) spi, provider, algorithm);
275      }
276    catch (InvocationTargetException x)
277      {
278        cause = x.getCause();
279        if (cause instanceof NoSuchAlgorithmException)
280          throw (NoSuchAlgorithmException) cause;
281        if (cause == null)
282          cause = x;
283      }
284    catch (ClassCastException x)
285      {
286        cause = x;
287      }
288    NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
289    x.initCause(cause);
290    throw x;
291  }
292
293  /**
294     Returns the provider being used by the current SecureRandom class.
295
296     @return The provider from which this SecureRandom was attained
297   */
298  public final Provider getProvider()
299  {
300    return provider;
301  }
302
303  /**
304   * Returns the algorithm name used or "unknown" when the algorithm
305   * used couldn't be determined (as when constructed by the protected
306   * 2 argument constructor).
307   *
308   * @since 1.5
309   */
310  public String getAlgorithm()
311  {
312    return algorithm;
313  }
314
315  /**
316     Seeds the SecureRandom. The class is re-seeded for each call and
317     each seed builds on the previous seed so as not to weaken security.
318
319     @param seed seed bytes to seed with
320   */
321  public void setSeed(byte[] seed)
322  {
323    secureRandomSpi.engineSetSeed(seed);
324    isSeeded = true;
325  }
326
327  /**
328     Seeds the SecureRandom. The class is re-seeded for each call and
329     each seed builds on the previous seed so as not to weaken security.
330
331     @param seed 8 seed bytes to seed with
332   */
333  public void setSeed(long seed)
334  {
335    // This particular setSeed will be called by Random.Random(), via
336    // our own constructor, before secureRandomSpi is initialized.  In
337    // this case we can't call a method on secureRandomSpi, and we
338    // definitely don't want to throw a NullPointerException.
339    // Therefore we test.
340    if (secureRandomSpi != null)
341      {
342        byte[] tmp = { (byte) (0xff & (seed >> 56)),
343                       (byte) (0xff & (seed >> 48)),
344                       (byte) (0xff & (seed >> 40)),
345                       (byte) (0xff & (seed >> 32)),
346                       (byte) (0xff & (seed >> 24)),
347                       (byte) (0xff & (seed >> 16)),
348                       (byte) (0xff & (seed >> 8)),
349                       (byte) (0xff & seed)
350        };
351        secureRandomSpi.engineSetSeed(tmp);
352        isSeeded = true;
353      }
354  }
355
356  /**
357     Generates a user specified number of bytes. This function
358     is the basis for all the random functions.
359
360     @param bytes array to store generated bytes in
361   */
362  public void nextBytes(byte[] bytes)
363  {
364    if (!isSeeded)
365      setSeed(getSeed(32));
366    randomBytesUsed += bytes.length;
367    counter++;
368    secureRandomSpi.engineNextBytes(bytes);
369  }
370
371  /**
372     Generates an integer containing the user specified
373     number of random bits. It is right justified and padded
374     with zeros.
375
376     @param numBits number of random bits to get, 0 <= numBits <= 32;
377
378     @return the random bits
379   */
380  protected final int next(int numBits)
381  {
382    if (numBits == 0)
383      return 0;
384
385    byte[] tmp = new byte[(numBits + 7) / 8];
386    this.nextBytes(tmp);
387    int ret = 0;
388    for (int i = 0; i < tmp.length; i++)
389      ret |= (tmp[i] & 0xFF) << (8 * i);
390
391    long mask = (1L << numBits) - 1;
392    return (int) (ret & mask);
393  }
394
395  /**
396     Returns the given number of seed bytes. This method is
397     maintained only for backwards capability.
398
399     @param numBytes number of seed bytes to get
400
401     @return an array containing the seed bytes
402   */
403  public static byte[] getSeed(int numBytes)
404  {
405    return SecureRandomAdapter.getSeed(numBytes);
406  }
407
408  /**
409     Returns the specified number of seed bytes.
410
411     @param numBytes number of seed bytes to get
412
413     @return an array containing the seed bytes
414   */
415  public byte[] generateSeed(int numBytes)
416  {
417    return secureRandomSpi.engineGenerateSeed(numBytes);
418  }
419
420}