KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > SecureRandom


1 /*
2  * @(#)SecureRandom.java 1.47 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7  
8 package java.security;
9
10 import java.util.*;
11
12 import java.security.Provider.Service;
13
14 import sun.security.jca.*;
15 import sun.security.jca.GetInstance.Instance;
16
17 /**
18  * <p>This class provides a cryptographically strong random number
19  * generator (RNG). Many implementations are in the form of a pseudo-random
20  * number generator (PRNG), which means they use a deterministic algorithm
21  * to produce a pseudo-random sequence from a true random seed.
22  * Other implementations may produce true random numbers
23  * and yet others may use a combination of both techniques.
24  *
25  * <p>A cryptographically strong random number
26  * minimally complies with the statistical random number generator tests
27  * specified in <a HREF="http://csrc.nist.gov/cryptval/140-2.htm">
28  * <i>FIPS 140-2, Security Requirements for Cryptographic Modules</i></a>,
29  * section 4.9.1.
30  * Additionally, SecureRandom must produce non-deterministic
31  * output and therefore it is required that the seed material be unpredictable
32  * and that output of SecureRandom be cryptographically strong sequences as
33  * described in <a HREF="http://www.ietf.org/rfc/rfc1750.txt">
34  * <i>RFC 1750: Randomness Recommendations for Security</i></a>.
35  *
36  * <p>Like other algorithm-based classes in Java Security, SecureRandom
37  * provides implementation-independent algorithms, whereby a caller
38  * (application code) requests a particular RNG algorithm
39  * and is handed back a SecureRandom object for that algorithm. It is
40  * also possible, if desired, to request a particular algorithm from a
41  * particular provider. See the <code>getInstance</code> methods.
42  *
43  * <p>Thus, there are two ways to request a SecureRandom object: by
44  * specifying either just an algorithm name, or both an algorithm name
45  * and a package provider.
46  *
47  * <ul>
48  *
49  * <li>If just an algorithm name is specified, as in:
50  * <pre>
51  * SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
52  * </pre>
53  * the system will determine if there is an implementation of the algorithm
54  * requested available in the environment, and if there is more than one, if
55  * there is a preferred one.<p>
56  *
57  * <li>If both an algorithm name and a package provider are specified, as in:
58  * <pre>
59  * SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
60  * </pre>
61  * the system will determine if there is an implementation of the
62  * algorithm in the package requested, and throw an exception if there
63  * is not.
64  *
65  * </ul>
66  *
67  * <p>The SecureRandom implementation attempts to completely
68  * randomize the internal state of the generator itself unless
69  * the caller follows the call to a <code>getInstance</code> method
70  * with a call to the <code>setSeed</code> method:
71  * <pre>
72  * SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
73  * random.setSeed(seed);
74  * </pre>
75  *
76  * <p>After the caller obtains the SecureRandom object from the
77  * <code>getInstance</code> call, it can call <code>nextBytes</code>
78  * to generate random bytes:
79  * <pre>
80  * byte bytes[] = new byte[20];
81  * random.nextBytes(bytes);
82  * </pre>
83  *
84  * <p>The caller may also invoke the <code>generateSeed</code> method
85  * to generate a given number of seed bytes (to seed other random number
86  * generators, for example):
87  * <pre>
88  * byte seed[] = random.generateSeed(20);
89  * </pre>
90  *
91  * @see java.security.SecureRandomSpi
92  * @see java.util.Random
93  *
94  * @version 1.47, 12/19/03
95  * @author Benjamin Renaud
96  * @author Josh Bloch
97  */

98
99 public class SecureRandom extends java.util.Random JavaDoc {
100
101     /**
102      * The provider.
103      *
104      * @serial
105      * @since 1.2
106      */

107     private Provider JavaDoc provider = null;
108  
109     /**
110      * The provider implementation.
111      *
112      * @serial
113      * @since 1.2
114      */

115     private SecureRandomSpi JavaDoc secureRandomSpi = null;
116     
117     /*
118      * The algorithm name of null if unknown.
119      *
120      * @serial
121      * @since 1.5
122      */

123     private String JavaDoc algorithm;
124
125     // Seed Generator
126
private static SecureRandom JavaDoc seedGenerator = null;
127
128     /**
129      * <p>By using this constructor, the caller obtains a SecureRandom object
130      * containing the implementation from the highest-priority installed
131      * provider that has a SecureRandom implementation.
132      *
133      * <p>Note that this instance of SecureRandom has not been seeded.
134      * A call to the <code>setSeed</code> method will seed the SecureRandom
135      * object. If a call is not made to <code>setSeed</code>, the first call
136      * to the <code>nextBytes</code> method will force the SecureRandom object
137      * to seed itself.
138      *
139      * <p>This constructor is provided for backwards compatibility.
140      * The caller is encouraged to use one of the alternative
141      * <code>getInstance</code> methods to obtain a SecureRandom object.
142      */

143     public SecureRandom() {
144     /*
145      * This call to our superclass constructor will result in a call
146      * to our own <code>setSeed</code> method, which will return
147      * immediately when it is passed zero.
148      */

149     super(0);
150     getDefaultPRNG(false, null);
151     }
152
153     /**
154      * <p>By using this constructor, the caller obtains a SecureRandom object
155      * containing the implementation from the highest-priority installed
156      * provider that has a SecureRandom implementation. This constructor
157      * uses a user-provided seed in
158      * preference to the self-seeding algorithm referred to in the empty
159      * constructor description. It may be preferable to the empty constructor
160      * if the caller has access to high-quality random bytes from some physical
161      * device (for example, a radiation detector or a noisy diode).
162      *
163      * <p>This constructor is provided for backwards compatibility.
164      * The caller is encouraged to use one of the alternative
165      * <code>getInstance</code> methods to obtain a SecureRandom object, and
166      * then to call the <code>setSeed</code> method to seed it.
167      *
168      * @param seed the seed.
169      */

170     public SecureRandom(byte seed[]) {
171     super(0);
172     getDefaultPRNG(true, seed);
173     }
174     
175     private void getDefaultPRNG(boolean setSeed, byte[] seed) {
176     String JavaDoc prng = getPrngAlgorithm();
177     if (prng == null) {
178         // bummer, get the SUN implementation
179
prng = "SHA1PRNG";
180         this.secureRandomSpi = new sun.security.provider.SecureRandom();
181         this.provider = new sun.security.provider.Sun();
182         if (setSeed) {
183         this.secureRandomSpi.engineSetSeed(seed);
184         }
185     } else {
186         try {
187         SecureRandom JavaDoc random = SecureRandom.getInstance(prng);
188         this.secureRandomSpi = random.getSecureRandomSpi();
189         this.provider = random.getProvider();
190         if (setSeed) {
191             this.secureRandomSpi.engineSetSeed(seed);
192         }
193         } catch (NoSuchAlgorithmException JavaDoc nsae) {
194         // never happens, because we made sure the algorithm exists
195
}
196     }
197     // set algorithm if SecureRandom not subclassed (JDK 1.1 style)
198
if (getClass() == SecureRandom JavaDoc.class) {
199         this.algorithm = prng;
200     }
201     }
202
203     /**
204      * Creates a SecureRandom object.
205      *
206      * @param secureRandomSpi the SecureRandom implementation.
207      * @param provider the provider.
208      */

209     protected SecureRandom(SecureRandomSpi JavaDoc secureRandomSpi,
210                Provider JavaDoc provider) {
211     this(secureRandomSpi, provider, null);
212     }
213     
214     private SecureRandom(SecureRandomSpi JavaDoc secureRandomSpi, Provider JavaDoc provider,
215         String JavaDoc algorithm) {
216     super(0);
217     this.secureRandomSpi = secureRandomSpi;
218     this.provider = provider;
219     this.algorithm = algorithm;
220     }
221
222     /**
223      * Generates a SecureRandom object that implements the specified
224      * Random Number Generator (RNG) algorithm. If the default
225      * provider package provides an implementation of the requested algorithm,
226      * an instance of SecureRandom containing that implementation is returned.
227      * If the algorithm is not available in the default
228      * package, other packages are searched.
229      *
230      * <p>Note that the returned instance of SecureRandom has not been seeded.
231      * A call to the <code>setSeed</code> method will seed the SecureRandom
232      * object. If a call is not made to <code>setSeed</code>, the first call
233      * to the <code>nextBytes</code> method will force the SecureRandom object
234      * to seed itself.
235      *
236      * @param algorithm the name of the RNG algorithm.
237      * See Appendix A in the <a HREF=
238      * "../../../guide/security/CryptoSpec.html#AppA">
239      * Java Cryptography Architecture API Specification &amp; Reference </a>
240      * for information about standard RNG algorithm names.
241      *
242      * @return the new SecureRandom object.
243      *
244      * @exception NoSuchAlgorithmException if the RNG algorithm is
245      * not available in the caller's environment.
246      *
247      * @since 1.2
248      */

249     public static SecureRandom JavaDoc getInstance(String JavaDoc algorithm)
250         throws NoSuchAlgorithmException JavaDoc {
251     Instance instance = GetInstance.getInstance("SecureRandom",
252         SecureRandomSpi JavaDoc.class, algorithm);
253     return new SecureRandom JavaDoc((SecureRandomSpi JavaDoc)instance.impl,
254         instance.provider, algorithm);
255     }
256
257     /**
258      * Generates a SecureRandom object for the specified RNG
259      * algorithm, as supplied from the specified provider, if such a
260      * RNG implementation is available from the provider.
261      *
262      * <p>Note that the returned instance of SecureRandom has not been seeded.
263      * A call to the <code>setSeed</code> method will seed the SecureRandom
264      * object. If a call is not made to <code>setSeed</code>, the first call
265      * to the <code>nextBytes</code> method will force the SecureRandom object
266      * to seed itself.
267      *
268      * @param algorithm the name of the RNG algorithm.
269      * See Appendix A in the <a HREF=
270      * "../../../guide/security/CryptoSpec.html#AppA">
271      * Java Cryptography Architecture API Specification &amp; Reference </a>
272      * for information about standard RNG algorithm names.
273      *
274      * @param provider the name of the provider.
275      *
276      * @return the new SecureRandom object.
277      *
278      * @exception NoSuchAlgorithmException if the requested RNG
279      * implementation is not available from the provider.
280      *
281      * @exception NoSuchProviderException if the provider has not been
282      * configured.
283      *
284      * @exception IllegalArgumentException if the provider name is null
285      * or empty.
286      *
287      * @see Provider
288      *
289      * @since 1.2
290      */

291     public static SecureRandom JavaDoc getInstance(String JavaDoc algorithm, String JavaDoc provider)
292         throws NoSuchAlgorithmException JavaDoc, NoSuchProviderException JavaDoc {
293     Instance instance = GetInstance.getInstance("SecureRandom",
294         SecureRandomSpi JavaDoc.class, algorithm, provider);
295     return new SecureRandom JavaDoc((SecureRandomSpi JavaDoc)instance.impl,
296         instance.provider, algorithm);
297     }
298
299     /**
300      * Generates a SecureRandom object for the specified RNG
301      * algorithm, as supplied from the specified provider, if such a
302      * RNG implementation is available from the provider.
303      * Note: the <code>provider</code> doesn't have to be registered.
304      *
305      * <p>Note that the returned instance of SecureRandom has not been seeded.
306      * A call to the <code>setSeed</code> method will seed the SecureRandom
307      * object. If a call is not made to <code>setSeed</code>, the first call
308      * to the <code>nextBytes</code> method will force the SecureRandom object
309      * to seed itself.
310      *
311      * @param algorithm the name of the RNG algorithm.
312      * See Appendix A in the <a HREF=
313      * "../../../guide/security/CryptoSpec.html#AppA">
314      * Java Cryptography Architecture API Specification &amp; Reference </a>
315      * for information about standard RNG algorithm names.
316      *
317      * @param provider the provider.
318      *
319      * @return the new SecureRandom object.
320      *
321      * @exception NoSuchAlgorithmException if the requested RNG
322      * implementation is not available from the provider.
323      *
324      * @exception IllegalArgumentException if the <code>provider</code> is
325      * null.
326      *
327      * @see Provider
328      *
329      * @since 1.4
330      */

331     public static SecureRandom JavaDoc getInstance(String JavaDoc algorithm,
332         Provider JavaDoc provider) throws NoSuchAlgorithmException JavaDoc {
333     Instance instance = GetInstance.getInstance("SecureRandom",
334         SecureRandomSpi JavaDoc.class, algorithm, provider);
335     return new SecureRandom JavaDoc((SecureRandomSpi JavaDoc)instance.impl,
336         instance.provider, algorithm);
337     }
338  
339     /**
340      * Returns the SecureRandomSpi of this SecureRandom object.
341      */

342     SecureRandomSpi JavaDoc getSecureRandomSpi() {
343     return secureRandomSpi;
344     }
345
346     /**
347      * Returns the provider of this SecureRandom object.
348      *
349      * @return the provider of this SecureRandom object.
350      */

351     public final Provider JavaDoc getProvider() {
352     return provider;
353     }
354     
355     /**
356      * Returns the name of the algorithm implemented by this SecureRandom object.
357      *
358      * @return the name of the algorithm or <code>unknown</code> if the algorithm
359      * name cannot be determined.
360      * @since 1.5
361      */

362     public String JavaDoc getAlgorithm() {
363     return (algorithm != null) ? algorithm : "unknown";
364     }
365
366     /**
367      * Reseeds this random object. The given seed supplements, rather than
368      * replaces, the existing seed. Thus, repeated calls are guaranteed
369      * never to reduce randomness.
370      *
371      * @param seed the seed.
372      *
373      * @see #getSeed
374      */

375     synchronized public void setSeed(byte[] seed) {
376     secureRandomSpi.engineSetSeed(seed);
377     }
378
379     /**
380      * Reseeds this random object, using the eight bytes contained
381      * in the given <code>long seed</code>. The given seed supplements,
382      * rather than replaces, the existing seed. Thus, repeated calls
383      * are guaranteed never to reduce randomness.
384      *
385      * <p>This method is defined for compatibility with
386      * <code>java.util.Random</code>.
387      *
388      * @param seed the seed.
389      *
390      * @see #getSeed
391      */

392     public void setSeed(long seed) {
393     /*
394      * Ignore call from super constructor (as well as any other calls
395      * unfortunate enough to be passing 0). It's critical that we
396      * ignore call from superclass constructor, as digest has not
397      * yet been initialized at that point.
398      */

399     if (seed != 0) {
400         secureRandomSpi.engineSetSeed(longToByteArray(seed));
401     }
402     }
403
404     /**
405      * Generates a user-specified number of random bytes. This method is
406      * used as the basis of all random entities returned by this class
407      * (except seed bytes).
408      *
409      * @param bytes the array to be filled in with random bytes.
410      */

411
412     synchronized public void nextBytes(byte[] bytes) {
413     secureRandomSpi.engineNextBytes(bytes);
414     }
415
416     /**
417      * Generates an integer containing the user-specified number of
418      * pseudo-random bits (right justified, with leading zeros). This
419      * method overrides a <code>java.util.Random</code> method, and serves
420      * to provide a source of random bits to all of the methods inherited
421      * from that class (for example, <code>nextInt</code>,
422      * <code>nextLong</code>, and <code>nextFloat</code>).
423      *
424      * @param numBits number of pseudo-random bits to be generated, where
425      * 0 <= <code>numBits</code> <= 32.
426      *
427      * @return an <code>int</code> containing the user-specified number
428      * of pseudo-random bits (right justified, with leading zeros).
429      */

430     final protected int next(int numBits) {
431     int numBytes = (numBits+7)/8;
432     byte b[] = new byte[numBytes];
433     int next = 0;
434  
435     nextBytes(b);
436     for (int i = 0; i < numBytes; i++)
437         next = (next << 8) + (b[i] & 0xFF);
438  
439     return next >>> (numBytes*8 - numBits);
440     }
441
442     /**
443      * Returns the given number of seed bytes, computed using the seed
444      * generation algorithm that this class uses to seed itself. This
445      * call may be used to seed other random number generators.
446      *
447      * <p>This method is only included for backwards compatibility.
448      * The caller is encouraged to use one of the alternative
449      * <code>getInstance</code> methods to obtain a SecureRandom object, and
450      * then call the <code>generateSeed</code> method to obtain seed bytes
451      * from that object.
452      *
453      * @param numBytes the number of seed bytes to generate.
454      *
455      * @return the seed bytes.
456      *
457      * @see #setSeed
458      */

459     public static byte[] getSeed(int numBytes) {
460     if (seedGenerator == null)
461         seedGenerator = new SecureRandom JavaDoc();
462     return seedGenerator.generateSeed(numBytes);
463     }
464
465     /**
466      * Returns the given number of seed bytes, computed using the seed
467      * generation algorithm that this class uses to seed itself. This
468      * call may be used to seed other random number generators.
469      *
470      * @param numBytes the number of seed bytes to generate.
471      *
472      * @return the seed bytes.
473      */

474     public byte[] generateSeed(int numBytes) {
475     return secureRandomSpi.engineGenerateSeed(numBytes);
476     }
477
478     /**
479      * Helper function to convert a long into a byte array (least significant
480      * byte first).
481      */

482     private static byte[] longToByteArray(long l) {
483     byte[] retVal = new byte[8];
484
485     for (int i = 0; i < 8; i++) {
486         retVal[i] = (byte) l;
487         l >>= 8;
488     }
489
490     return retVal;
491     }
492
493     /**
494      * Gets a default PRNG algorithm by looking through all registered
495      * providers. Returns the first PRNG algorithm of the first provider that
496      * has registered a SecureRandom implementation, or null if none of the
497      * registered providers supplies a SecureRandom implementation.
498      */

499     private static String JavaDoc getPrngAlgorithm() {
500     List provs = Providers.getProviderList().providers();
501     for (Iterator t = provs.iterator(); t.hasNext();) {
502         Provider JavaDoc p = (Provider JavaDoc)t.next();
503         for (Iterator u = p.getServices().iterator(); u.hasNext();) {
504         Service s = (Service)u.next();
505         if (s.getType().equals("SecureRandom")) {
506             return s.getAlgorithm();
507         }
508         }
509     }
510     return null;
511     }
512
513     // Declare serialVersionUID to be compatible with JDK1.1
514
static final long serialVersionUID = 4940670005562187L;
515
516     // Retain unused values serialized from JDK1.1
517
/**
518      * @serial
519      */

520     private byte[] state;
521     /**
522      * @serial
523      */

524     private MessageDigest JavaDoc digest = null;
525     /**
526      * @serial
527      *
528      * We know that the MessageDigest class does not implement
529      * java.io.Serializable. However, since this field is no longer
530      * used, it will always be NULL and won't affect the serialization
531      * of the SecureRandom class itself.
532      */

533     private byte[] randomBytes;
534     /**
535      * @serial
536      */

537     private int randomBytesUsed;
538     /**
539      * @serial
540      */

541     private long counter;
542 }
543
Popular Tags