1 /* SecureRandom.java --- Secure Random class implementation
2    Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 package java.security;
39 
40 import java.io.Serializable;
41 import java.util.Random;
42 import java.util.Enumeration;
43 
44 import gnu.java.security.Engine;
45 
46 /**
47  * An interface to a cryptographically secure pseudo-random number
48  * generator (PRNG). Random (or at least unguessable) numbers are used
49  * in all areas of security and cryptography, from the generation of
50  * keys and initialization vectors to the generation of random padding
51  * bytes.
52  *
53  * @author Mark Benvenuto <ivymccough@worldnet.att.net>
54  * @author Casey Marshall
55  */
56 public class SecureRandom extends Random
57 {
58 
59   // Constants and fields.
60   // ------------------------------------------------------------------------
61 
62   /** Service name for PRNGs. */
63   private static final String SECURE_RANDOM = "SecureRandom";
64 
65   private static final long serialVersionUID = 4940670005562187L;
66 
67   //Serialized Field
68   long counter = 0;		//Serialized
69   Provider provider = null;
70   byte[] randomBytes = null;	//Always null
71   int randomBytesUsed = 0;
72   SecureRandomSpi secureRandomSpi = null;
73   byte[] state = null;
74 
75   // Constructors.
76   // ------------------------------------------------------------------------
77 
78   /**
79      Default constructor for SecureRandom. It constructs a
80      new SecureRandom by instantating the first SecureRandom
81      algorithm in the default security provier.
82 
83      It is not seeded and should be seeded using setSeed or else
84      on the first call to getnextBytes it will force a seed.
85 
86      It is maintained for backwards compatibility and programs
87      should use {@link #getInstance(java.lang.String)}.
88    */
SecureRandom()89   public SecureRandom()
90   {
91     Provider p[] = Security.getProviders();
92 
93     //Format of Key: SecureRandom.algname
94     String key;
95 
96     String classname = null;
97     int i, flag = 0;
98     Enumeration e;
99     for (i = 0; i < p.length; i++)
100       {
101         e = p[i].propertyNames();
102         while (e.hasMoreElements())
103           {
104             key = (String) e.nextElement();
105             if (key.startsWith("SECURERANDOM."))
106               {
107                 if ((classname = p[i].getProperty(key)) != null)
108                   {
109                     try
110                       {
111                         secureRandomSpi = (SecureRandomSpi) Class.
112                           forName(classname).newInstance();
113                         provider = p[i];
114                         return;
115                       }
116                     catch (Throwable ignore) { }
117                   }
118               }
119           }
120       }
121 
122     // Nothing found. Fall back to SHA1PRNG
123     secureRandomSpi = new gnu.java.security.provider.SHA1PRNG();
124   }
125 
126   /**
127      A constructor for SecureRandom. It constructs a new
128      SecureRandom by instantating the first SecureRandom algorithm
129      in the default security provier.
130 
131      It is seeded with the passed function and is useful if the user
132      has access to hardware random device (like a radiation detector).
133 
134      It is maintained for backwards compatibility and programs
135      should use getInstance.
136 
137      @param seed Seed bytes for class
138    */
SecureRandom(byte[] seed)139   public SecureRandom(byte[] seed)
140   {
141     this();
142     setSeed(seed);
143   }
144 
145   /**
146      A constructor for SecureRandom. It constructs a new
147      SecureRandom using the specified SecureRandomSpi from
148      the specified security provier.
149 
150      @param secureRandomSpi A SecureRandomSpi class
151      @param provider A Provider class
152    */
SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider)153   protected SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider)
154   {
155     this.secureRandomSpi = secureRandomSpi;
156     this.provider = provider;
157   }
158 
159   // Class methods.
160   // ------------------------------------------------------------------------
161 
162   /**
163    * Returns an instance of a SecureRandom. It creates the class from
164    * the first provider that implements it.
165    *
166    * @param algorithm The algorithm name.
167    * @return A new SecureRandom implementing the given algorithm.
168    * @throws NoSuchAlgorithmException If no installed provider implements
169    *         the given algorithm.
170    */
getInstance(String algorithm)171   public static SecureRandom getInstance(String algorithm) throws
172     NoSuchAlgorithmException
173   {
174     Provider p[] = Security.getProviders();
175     for (int i = 0; i < p.length; i++)
176       {
177         try
178           {
179             return getInstance(algorithm, p[i]);
180           }
181         catch (NoSuchAlgorithmException ignored)
182           {
183           }
184       }
185 
186     // None found.
187     throw new NoSuchAlgorithmException(algorithm);
188   }
189 
190   /**
191    * Returns an instance of a SecureRandom. It creates the class
192    * for the specified algorithm from the named provider.
193    *
194    * @param algorithm The algorithm name.
195    * @param provider  The provider name.
196    * @return A new SecureRandom implementing the chosen algorithm.
197    * @throws NoSuchAlgorithmException If the named provider does not implement
198    *         the algorithm, or if the implementation cannot be
199    *         instantiated.
200    * @throws NoSuchProviderException If no provider named
201    *         <code>provider</code> is currently installed.
202    * @throws IllegalArgumentException If <code>provider</code> is null
203    *         or is empty.
204    */
getInstance(String algorithm, String provider)205   public static SecureRandom getInstance(String algorithm, String provider)
206   throws NoSuchAlgorithmException, NoSuchProviderException
207   {
208     if (provider == null || provider.length() == 0)
209       throw new IllegalArgumentException("Illegal provider");
210 
211     Provider p = Security.getProvider(provider);
212     if (p == null)
213       throw new NoSuchProviderException();
214 
215     return getInstance(algorithm, p);
216   }
217 
218   /**
219    * Returns an instance of a SecureRandom. It creates the class for
220    * the specified algorithm from the given provider.
221    *
222    * @param algorithm The SecureRandom algorithm to create.
223    * @param provider  The provider to get the instance from.
224    * @throws NoSuchAlgorithmException If the algorithm cannot be found, or
225    *         if the class cannot be instantiated.
226    * @throws IllegalArgumentException If <code>provider</code> is null.
227    */
getInstance(String algorithm, Provider provider)228   public static SecureRandom getInstance(String algorithm, Provider provider)
229   throws NoSuchAlgorithmException
230   {
231     if (provider == null)
232       throw new IllegalArgumentException("Illegal provider");
233     try
234       {
235         return new SecureRandom((SecureRandomSpi)
236           Engine.getInstance(SECURE_RANDOM, algorithm, provider),
237           provider);
238       }
239     catch (java.lang.reflect.InvocationTargetException ite)
240       {
241 	throw new NoSuchAlgorithmException(algorithm);
242       }
243     catch (ClassCastException cce)
244       {
245         throw new NoSuchAlgorithmException(algorithm);
246       }
247   }
248 
249   // Instance methods.
250   // ------------------------------------------------------------------------
251 
252   /**
253      Returns the provider being used by the current SecureRandom class.
254 
255      @return The provider from which this SecureRandom was attained
256    */
getProvider()257   public final Provider getProvider()
258   {
259     return provider;
260   }
261 
262   /**
263      Seeds the SecureRandom. The class is re-seeded for each call and
264      each seed builds on the previous seed so as not to weaken security.
265 
266      @param seed seed bytes to seed with
267    */
setSeed(byte[] seed)268   public void setSeed(byte[] seed)
269   {
270     secureRandomSpi.engineSetSeed(seed);
271   }
272 
273   /**
274      Seeds the SecureRandom. The class is re-seeded for each call and
275      each seed builds on the previous seed so as not to weaken security.
276 
277      @param seed 8 seed bytes to seed with
278    */
setSeed(long seed)279   public void setSeed(long seed)
280   {
281     // This particular setSeed will be called by Random.Random(), via
282     // our own constructor, before secureRandomSpi is initialized.  In
283     // this case we can't call a method on secureRandomSpi, and we
284     // definitely don't want to throw a NullPointerException.
285     // Therefore we test.
286     if (secureRandomSpi != null)
287       {
288         byte tmp[] = { (byte) (0xff & (seed >> 56)),
289 		       (byte) (0xff & (seed >> 48)),
290 		       (byte) (0xff & (seed >> 40)),
291 		       (byte) (0xff & (seed >> 32)),
292 		       (byte) (0xff & (seed >> 24)),
293 		       (byte) (0xff & (seed >> 16)),
294 		       (byte) (0xff & (seed >> 8)),
295 		       (byte) (0xff & seed)
296         };
297         secureRandomSpi.engineSetSeed(tmp);
298       }
299   }
300 
301   /**
302      Generates a user specified number of bytes. This function
303      is the basis for all the random functions.
304 
305      @param bytes array to store generated bytes in
306    */
nextBytes(byte[] bytes)307   public void nextBytes(byte[] bytes)
308   {
309     randomBytesUsed += bytes.length;
310     counter++;
311     secureRandomSpi.engineNextBytes(bytes);
312   }
313 
314   /**
315      Generates an integer containing the user specified
316      number of random bits. It is right justified and padded
317      with zeros.
318 
319      @param numBits number of random bits to get, 0 <= numBits <= 32;
320 
321      @return the random bits
322    */
next(int numBits)323   protected final int next(int numBits)
324   {
325     if (numBits == 0)
326       return 0;
327 
328     byte tmp[] = new byte[numBits / 8 + (1 * (numBits % 8))];
329 
330     secureRandomSpi.engineNextBytes(tmp);
331     randomBytesUsed += tmp.length;
332     counter++;
333 
334     int ret = 0;
335 
336     for (int i = 0; i < tmp.length; i++)
337       ret |= (tmp[i] & 0xFF) << (8 * i);
338 
339     long mask = (1L << numBits) - 1;
340     return (int) (ret & mask);
341   }
342 
343   /**
344      Returns the given number of seed bytes. This method is
345      maintained only for backwards capability.
346 
347      @param numBytes number of seed bytes to get
348 
349      @return an array containing the seed bytes
350    */
getSeed(int numBytes)351   public static byte[] getSeed(int numBytes)
352   {
353     byte tmp[] = new byte[numBytes];
354 
355     new Random().nextBytes(tmp);
356     return tmp;
357     //return secureRandomSpi.engineGenerateSeed( numBytes );
358   }
359 
360   /**
361      Returns the specified number of seed bytes.
362 
363      @param numBytes number of seed bytes to get
364 
365      @return an array containing the seed bytes
366    */
generateSeed(int numBytes)367   public byte[] generateSeed(int numBytes)
368   {
369     return secureRandomSpi.engineGenerateSeed(numBytes);
370   }
371 
372 }
373