001    /* SecureRandom.java --- Secure Random class implementation
002       Copyright (C) 1999, 2001, 2002, 2003, 2005, 2006
003       Free Software Foundation, Inc.
004    
005    This file is part of GNU Classpath.
006    
007    GNU Classpath is free software; you can redistribute it and/or modify
008    it under the terms of the GNU General Public License as published by
009    the Free Software Foundation; either version 2, or (at your option)
010    any later version.
011    
012    GNU Classpath is distributed in the hope that it will be useful, but
013    WITHOUT ANY WARRANTY; without even the implied warranty of
014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015    General Public License for more details.
016    
017    You should have received a copy of the GNU General Public License
018    along with GNU Classpath; see the file COPYING.  If not, write to the
019    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020    02110-1301 USA.
021    
022    Linking this library statically or dynamically with other modules is
023    making a combined work based on this library.  Thus, the terms and
024    conditions of the GNU General Public License cover the whole
025    combination.
026    
027    As a special exception, the copyright holders of this library give you
028    permission to link this library with independent modules to produce an
029    executable, regardless of the license terms of these independent
030    modules, and to copy and distribute the resulting executable under
031    terms of your choice, provided that you also meet, for each linked
032    independent module, the terms and conditions of the license of that
033    module.  An independent module is a module which is not derived from
034    or based on this library.  If you modify this library, you may extend
035    this exception to your version of the library, but you are not
036    obligated to do so.  If you do not wish to do so, delete this
037    exception statement from your version. */
038    
039    package java.security;
040    
041    import gnu.classpath.SystemProperties;
042    import gnu.java.lang.CPStringBuilder;
043    import gnu.java.security.Engine;
044    import gnu.java.security.action.GetSecurityPropertyAction;
045    import gnu.java.security.jce.prng.SecureRandomAdapter;
046    import gnu.java.security.jce.prng.Sha160RandomSpi;
047    
048    import java.io.IOException;
049    import java.io.InputStream;
050    import java.lang.reflect.InvocationTargetException;
051    import java.net.MalformedURLException;
052    import java.net.URL;
053    import java.util.Enumeration;
054    import java.util.Random;
055    import java.util.logging.Level;
056    import 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     */
068    public 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    }