1 module hunt.security.SecureRandom;
2 
3 import hunt.Exceptions;
4 
5 
6 /**
7  * This class provides a cryptographically strong random number
8  * generator (RNG).
9  *
10  * <p>A cryptographically strong random number
11  * minimally complies with the statistical random number generator tests
12  * specified in <a href="http://csrc.nist.gov/cryptval/140-2.htm">
13  * <i>FIPS 140-2, Security Requirements for Cryptographic Modules</i></a>,
14  * section 4.9.1.
15  * Additionally, SecureRandom must produce non-deterministic output.
16  * Therefore any seed material passed to a SecureRandom object must be
17  * unpredictable, and all SecureRandom output sequences must be
18  * cryptographically strong, as described in
19  * <a href="http://www.ietf.org/rfc/rfc1750.txt">
20  * <i>RFC 1750: Randomness Recommendations for Security</i></a>.
21  *
22  * <p>A caller obtains a SecureRandom instance via the
23  * no-argument constructor or one of the {@code getInstance} methods:
24  *
25  * <pre>
26  *      SecureRandom random = new SecureRandom();
27  * </pre>
28  *
29  * <p> Many SecureRandom implementations are in the form of a pseudo-random
30  * number generator (PRNG), which means they use a deterministic algorithm
31  * to produce a pseudo-random sequence from a true random seed.
32  * Other implementations may produce true random numbers,
33  * and yet others may use a combination of both techniques.
34  *
35  * <p> Typical callers of SecureRandom invoke the following methods
36  * to retrieve random bytes:
37  *
38  * <pre>
39  *      SecureRandom random = new SecureRandom();
40  *      byte bytes[] = new byte[20];
41  *      random.nextBytes(bytes);
42  * </pre>
43  *
44  * <p> Callers may also invoke the {@code generateSeed} method
45  * to generate a given number of seed bytes (to seed other random number
46  * generators, for example):
47  * <pre>
48  *      byte seed[] = random.generateSeed(20);
49  * </pre>
50  *
51  * Note: Depending on the implementation, the {@code generateSeed} and
52  * {@code nextBytes} methods may block as entropy is being gathered,
53  * for example, if they need to read from /dev/random on various Unix-like
54  * operating systems.
55  *
56  * @see java.security.SecureRandomSpi
57  * @see java.util.Random
58  *
59  * @author Benjamin Renaud
60  * @author Josh Bloch
61  */
62 
63 class SecureRandom  { // : java.util.Random
64 
65     // private static final Debug pdebug =
66     //                     Debug.getInstance("provider", "Provider");
67     // private static final bool skipDebug =
68     //     Debug.isOn("engine=") && !Debug.isOn("securerandom");
69 
70     // /**
71     //  * The provider.
72     //  *
73     //  * @serial
74     //  * @since 1.2
75     //  */
76     // private Provider provider = null;
77 
78     // /**
79     //  * The provider implementation.
80     //  *
81     //  * @serial
82     //  * @since 1.2
83     //  */
84     // private SecureRandomSpi secureRandomSpi = null;
85 
86     // /*
87     //  * The algorithm name of null if unknown.
88     //  *
89     //  * @serial
90     //  * @since 1.5
91     //  */
92     // private string algorithm;
93 
94     // // Seed Generator
95     // private static volatile SecureRandom seedGenerator = null;
96 
97     /**
98      * Constructs a secure random number generator (RNG) implementing the
99      * default random number algorithm.
100      *
101      * <p> This constructor traverses the list of registered security Providers,
102      * starting with the most preferred Provider.
103      * A new SecureRandom object encapsulating the
104      * SecureRandomSpi implementation from the first
105      * Provider that supports a SecureRandom (RNG) algorithm is returned.
106      * If none of the Providers support a RNG algorithm,
107      * then an implementation-specific default is returned.
108      *
109      * <p> Note that the list of registered providers may be retrieved via
110      * the {@link Security#getProviders() Security.getProviders()} method.
111      *
112      * <p> See the SecureRandom section in the <a href=
113      * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
114      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
115      * for information about standard RNG algorithm names.
116      *
117      * <p> The returned SecureRandom object has not been seeded.  To seed the
118      * returned object, call the {@code setSeed} method.
119      * If {@code setSeed} is not called, the first call to
120      * {@code nextBytes} will force the SecureRandom object to seed itself.
121      * This self-seeding will not occur if {@code setSeed} was
122      * previously called.
123      */
124     this() {
125         /*
126          * This call to our superclass constructor will result in a call
127          * to our own {@code setSeed} method, which will return
128          * immediately when it is passed zero.
129          */
130         // super(0);
131         // getDefaultPRNG(false, null);
132     }
133 
134     /**
135      * Constructs a secure random number generator (RNG) implementing the
136      * default random number algorithm.
137      * The SecureRandom instance is seeded with the specified seed bytes.
138      *
139      * <p> This constructor traverses the list of registered security Providers,
140      * starting with the most preferred Provider.
141      * A new SecureRandom object encapsulating the
142      * SecureRandomSpi implementation from the first
143      * Provider that supports a SecureRandom (RNG) algorithm is returned.
144      * If none of the Providers support a RNG algorithm,
145      * then an implementation-specific default is returned.
146      *
147      * <p> Note that the list of registered providers may be retrieved via
148      * the {@link Security#getProviders() Security.getProviders()} method.
149      *
150      * <p> See the SecureRandom section in the <a href=
151      * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
152      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
153      * for information about standard RNG algorithm names.
154      *
155      * @param seed the seed.
156      */
157     this(byte[] seed) {
158         // super(0);
159         // getDefaultPRNG(true, seed);
160     }
161 
162     // private void getDefaultPRNG(bool setSeed, byte[] seed) {
163     //     string prng = getPrngAlgorithm();
164     //     if (prng is null) {
165     //         // bummer, get the SUN implementation
166     //         prng = "SHA1PRNG";
167     //         this.secureRandomSpi = new sun.security.provider.SecureRandom();
168     //         this.provider = Providers.getSunProvider();
169     //         if (setSeed) {
170     //             this.secureRandomSpi.engineSetSeed(seed);
171     //         }
172     //     } else {
173     //         try {
174     //             SecureRandom random = SecureRandom.getInstance(prng);
175     //             this.secureRandomSpi = random.getSecureRandomSpi();
176     //             this.provider = random.getProvider();
177     //             if (setSeed) {
178     //                 this.secureRandomSpi.engineSetSeed(seed);
179     //             }
180     //         } catch (NoSuchAlgorithmException nsae) {
181     //             // never happens, because we made sure the algorithm exists
182     //             throw new RuntimeException(nsae);
183     //         }
184     //     }
185     //     // JDK 1.1 based implementations subclass SecureRandom instead of
186     //     // SecureRandomSpi. They will also go through this code path because
187     //     // they must call a SecureRandom constructor as it is their superclass.
188     //     // If we are dealing with such an implementation, do not set the
189     //     // algorithm value as it would be inaccurate.
190     //     if (getClass() == SecureRandom.class) {
191     //         this.algorithm = prng;
192     //     }
193     // }
194 
195     // /**
196     //  * Creates a SecureRandom object.
197     //  *
198     //  * @param secureRandomSpi the SecureRandom implementation.
199     //  * @param provider the provider.
200     //  */
201     // protected SecureRandom(SecureRandomSpi secureRandomSpi,
202     //                        Provider provider) {
203     //     this(secureRandomSpi, provider, null);
204     // }
205 
206     // private SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider,
207     //         string algorithm) {
208     //     super(0);
209     //     this.secureRandomSpi = secureRandomSpi;
210     //     this.provider = provider;
211     //     this.algorithm = algorithm;
212 
213     //     if (!skipDebug && pdebug !is null) {
214     //         pdebug.println("SecureRandom." ~ algorithm +
215     //             " algorithm from: " ~ this.provider.getName());
216     //     }
217     // }
218 
219     // /**
220     //  * Returns a SecureRandom object that implements the specified
221     //  * Random Number Generator (RNG) algorithm.
222     //  *
223     //  * <p> This method traverses the list of registered security Providers,
224     //  * starting with the most preferred Provider.
225     //  * A new SecureRandom object encapsulating the
226     //  * SecureRandomSpi implementation from the first
227     //  * Provider that supports the specified algorithm is returned.
228     //  *
229     //  * <p> Note that the list of registered providers may be retrieved via
230     //  * the {@link Security#getProviders() Security.getProviders()} method.
231     //  *
232     //  * <p> The returned SecureRandom object has not been seeded.  To seed the
233     //  * returned object, call the {@code setSeed} method.
234     //  * If {@code setSeed} is not called, the first call to
235     //  * {@code nextBytes} will force the SecureRandom object to seed itself.
236     //  * This self-seeding will not occur if {@code setSeed} was
237     //  * previously called.
238     //  *
239     //  * @param algorithm the name of the RNG algorithm.
240     //  * See the SecureRandom section in the <a href=
241     //  * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
242     //  * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
243     //  * for information about standard RNG algorithm names.
244     //  *
245     //  * @return the new SecureRandom object.
246     //  *
247     //  * @exception NoSuchAlgorithmException if no Provider supports a
248     //  *          SecureRandomSpi implementation for the
249     //  *          specified algorithm.
250     //  *
251     //  * @see Provider
252     //  *
253     //  * @since 1.2
254     //  */
255     // static SecureRandom getInstance(string algorithm)
256     //         throws NoSuchAlgorithmException {
257     //     Instance instance = GetInstance.getInstance("SecureRandom",
258     //         SecureRandomSpi.class, algorithm);
259     //     return new SecureRandom((SecureRandomSpi)instance.impl,
260     //         instance.provider, algorithm);
261     // }
262 
263     // /**
264     //  * Returns a SecureRandom object that implements the specified
265     //  * Random Number Generator (RNG) algorithm.
266     //  *
267     //  * <p> A new SecureRandom object encapsulating the
268     //  * SecureRandomSpi implementation from the specified provider
269     //  * is returned.  The specified provider must be registered
270     //  * in the security provider list.
271     //  *
272     //  * <p> Note that the list of registered providers may be retrieved via
273     //  * the {@link Security#getProviders() Security.getProviders()} method.
274     //  *
275     //  * <p> The returned SecureRandom object has not been seeded.  To seed the
276     //  * returned object, call the {@code setSeed} method.
277     //  * If {@code setSeed} is not called, the first call to
278     //  * {@code nextBytes} will force the SecureRandom object to seed itself.
279     //  * This self-seeding will not occur if {@code setSeed} was
280     //  * previously called.
281     //  *
282     //  * @param algorithm the name of the RNG algorithm.
283     //  * See the SecureRandom section in the <a href=
284     //  * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
285     //  * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
286     //  * for information about standard RNG algorithm names.
287     //  *
288     //  * @param provider the name of the provider.
289     //  *
290     //  * @return the new SecureRandom object.
291     //  *
292     //  * @exception NoSuchAlgorithmException if a SecureRandomSpi
293     //  *          implementation for the specified algorithm is not
294     //  *          available from the specified provider.
295     //  *
296     //  * @exception NoSuchProviderException if the specified provider is not
297     //  *          registered in the security provider list.
298     //  *
299     //  * @exception IllegalArgumentException if the provider name is null
300     //  *          or empty.
301     //  *
302     //  * @see Provider
303     //  *
304     //  * @since 1.2
305     //  */
306     // static SecureRandom getInstance(string algorithm, string provider)
307     //         throws NoSuchAlgorithmException, NoSuchProviderException {
308     //     Instance instance = GetInstance.getInstance("SecureRandom",
309     //         SecureRandomSpi.class, algorithm, provider);
310     //     return new SecureRandom((SecureRandomSpi)instance.impl,
311     //         instance.provider, algorithm);
312     // }
313 
314     // /**
315     //  * Returns a SecureRandom object that implements the specified
316     //  * Random Number Generator (RNG) algorithm.
317     //  *
318     //  * <p> A new SecureRandom object encapsulating the
319     //  * SecureRandomSpi implementation from the specified Provider
320     //  * object is returned.  Note that the specified Provider object
321     //  * does not have to be registered in the provider list.
322     //  *
323     //  * <p> The returned SecureRandom object has not been seeded.  To seed the
324     //  * returned object, call the {@code setSeed} method.
325     //  * If {@code setSeed} is not called, the first call to
326     //  * {@code nextBytes} will force the SecureRandom object to seed itself.
327     //  * This self-seeding will not occur if {@code setSeed} was
328     //  * previously called.
329     //  *
330     //  * @param algorithm the name of the RNG algorithm.
331     //  * See the SecureRandom section in the <a href=
332     //  * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
333     //  * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
334     //  * for information about standard RNG algorithm names.
335     //  *
336     //  * @param provider the provider.
337     //  *
338     //  * @return the new SecureRandom object.
339     //  *
340     //  * @exception NoSuchAlgorithmException if a SecureRandomSpi
341     //  *          implementation for the specified algorithm is not available
342     //  *          from the specified Provider object.
343     //  *
344     //  * @exception IllegalArgumentException if the specified provider is null.
345     //  *
346     //  * @see Provider
347     //  *
348     //  * @since 1.4
349     //  */
350     // static SecureRandom getInstance(string algorithm,
351     //         Provider provider) throws NoSuchAlgorithmException {
352     //     Instance instance = GetInstance.getInstance("SecureRandom",
353     //         SecureRandomSpi.class, algorithm, provider);
354     //     return new SecureRandom((SecureRandomSpi)instance.impl,
355     //         instance.provider, algorithm);
356     // }
357 
358     // /**
359     //  * Returns the SecureRandomSpi of this SecureRandom object.
360     //  */
361     // SecureRandomSpi getSecureRandomSpi() {
362     //     return secureRandomSpi;
363     // }
364 
365     // /**
366     //  * Returns the provider of this SecureRandom object.
367     //  *
368     //  * @return the provider of this SecureRandom object.
369     //  */
370     // final Provider getProvider() {
371     //     return provider;
372     // }
373 
374     // /**
375     //  * Returns the name of the algorithm implemented by this SecureRandom
376     //  * object.
377     //  *
378     //  * @return the name of the algorithm or {@code unknown}
379     //  *          if the algorithm name cannot be determined.
380     //  * @since 1.5
381     //  */
382     // string getAlgorithm() {
383     //     return (algorithm !is null) ? algorithm : "unknown";
384     // }
385 
386     /**
387      * Reseeds this random object. The given seed supplements, rather than
388      * replaces, the existing seed. Thus, repeated calls are guaranteed
389      * never to reduce randomness.
390      *
391      * @param seed the seed.
392      *
393      * @see #getSeed
394      */
395     void setSeed(byte[] seed) {
396         // secureRandomSpi.engineSetSeed(seed);
397         implementationMissing(false);
398     }
399 
400     // /**
401     //  * Reseeds this random object, using the eight bytes contained
402     //  * in the given {@code long seed}. The given seed supplements,
403     //  * rather than replaces, the existing seed. Thus, repeated calls
404     //  * are guaranteed never to reduce randomness.
405     //  *
406     //  * <p>This method is defined for compatibility with
407     //  * {@code java.util.Random}.
408     //  *
409     //  * @param seed the seed.
410     //  *
411     //  * @see #getSeed
412     //  */
413     // override
414     // void setSeed(long seed) {
415     //     /*
416     //      * Ignore call from super constructor (as well as any other calls
417     //      * unfortunate enough to be passing 0).  It's critical that we
418     //      * ignore call from superclass constructor, as digest has not
419     //      * yet been initialized at that point.
420     //      */
421     //     if (seed != 0) {
422     //         secureRandomSpi.engineSetSeed(longToByteArray(seed));
423     //     }
424     // }
425 
426     /**
427      * Generates a user-specified number of random bytes.
428      *
429      * <p> If a call to {@code setSeed} had not occurred previously,
430      * the first call to this method forces this SecureRandom object
431      * to seed itself.  This self-seeding will not occur if
432      * {@code setSeed} was previously called.
433      *
434      * @param bytes the array to be filled in with random bytes.
435      */
436     // override
437     void nextBytes(byte[] bytes) {
438         // secureRandomSpi.engineNextBytes(bytes);
439         implementationMissing(false);
440     }
441 
442     // /**
443     //  * Generates an integer containing the user-specified number of
444     //  * pseudo-random bits (right justified, with leading zeros).  This
445     //  * method overrides a {@code java.util.Random} method, and serves
446     //  * to provide a source of random bits to all of the methods inherited
447     //  * from that class (for example, {@code nextInt},
448     //  * {@code nextLong}, and {@code nextFloat}).
449     //  *
450     //  * @param numBits number of pseudo-random bits to be generated, where
451     //  * {@code 0 <= numBits <= 32}.
452     //  *
453     //  * @return an {@code int} containing the user-specified number
454     //  * of pseudo-random bits (right justified, with leading zeros).
455     //  */
456     // override
457     // final protected int next(int numBits) {
458     //     int numBytes = (numBits+7)/8;
459     //     byte b[] = new byte[numBytes];
460     //     int next = 0;
461 
462     //     nextBytes(b);
463     //     for (int i = 0; i < numBytes; i++) {
464     //         next = (next << 8) + (b[i] & 0xFF);
465     //     }
466 
467     //     return next >>> (numBytes*8 - numBits);
468     // }
469 
470     // /**
471     //  * Returns the given number of seed bytes, computed using the seed
472     //  * generation algorithm that this class uses to seed itself.  This
473     //  * call may be used to seed other random number generators.
474     //  *
475     //  * <p>This method is only included for backwards compatibility.
476     //  * The caller is encouraged to use one of the alternative
477     //  * {@code getInstance} methods to obtain a SecureRandom object, and
478     //  * then call the {@code generateSeed} method to obtain seed bytes
479     //  * from that object.
480     //  *
481     //  * @param numBytes the number of seed bytes to generate.
482     //  *
483     //  * @return the seed bytes.
484     //  *
485     //  * @see #setSeed
486     //  */
487     // static byte[] getSeed(int numBytes) {
488     //     if (seedGenerator is null) {
489     //         seedGenerator = new SecureRandom();
490     //     }
491     //     return seedGenerator.generateSeed(numBytes);
492     // }
493 
494     // /**
495     //  * Returns the given number of seed bytes, computed using the seed
496     //  * generation algorithm that this class uses to seed itself.  This
497     //  * call may be used to seed other random number generators.
498     //  *
499     //  * @param numBytes the number of seed bytes to generate.
500     //  *
501     //  * @return the seed bytes.
502     //  */
503     // byte[] generateSeed(int numBytes) {
504     //     return secureRandomSpi.engineGenerateSeed(numBytes);
505     // }
506 
507     // /**
508     //  * Helper function to convert a long into a byte array (least significant
509     //  * byte first).
510     //  */
511     // private static byte[] longToByteArray(long l) {
512     //     byte[] retVal = new byte[8];
513 
514     //     for (int i = 0; i < 8; i++) {
515     //         retVal[i] = (byte) l;
516     //         l >>= 8;
517     //     }
518 
519     //     return retVal;
520     // }
521 
522     // /**
523     //  * Gets a default PRNG algorithm by looking through all registered
524     //  * providers. Returns the first PRNG algorithm of the first provider that
525     //  * has registered a SecureRandom implementation, or null if none of the
526     //  * registered providers supplies a SecureRandom implementation.
527     //  */
528     // private static string getPrngAlgorithm() {
529     //     for (Provider p : Providers.getProviderList().providers()) {
530     //         for (Service s : p.getServices()) {
531     //             if (s.getType().equals("SecureRandom")) {
532     //                 return s.getAlgorithm();
533     //             }
534     //         }
535     //     }
536     //     return null;
537     // }
538 
539     // /*
540     //  * Lazily initialize since Pattern.compile() is heavy.
541     //  * Effective Java (2nd Edition), Item 71.
542     //  */
543     // private static final class StrongPatternHolder {
544     //     /*
545     //      * Entries are alg:prov separated by ,
546     //      * Allow for prepended/appended whitespace between entries.
547     //      *
548     //      * Capture groups:
549     //      *     1 - alg
550     //      *     2 - :prov (optional)
551     //      *     3 - prov (optional)
552     //      *     4 - ,nextEntry (optional)
553     //      *     5 - nextEntry (optional)
554     //      */
555     //     private static Pattern pattern =
556     //         Pattern.compile(
557     //             "\\s*([\\S&&[^:,]]*)(\\:([\\S&&[^,]]*))?\\s*(\\,(.*))?");
558     // }
559 
560     // /**
561     //  * Returns a {@code SecureRandom} object that was selected by using
562     //  * the algorithms/providers specified in the {@code
563     //  * securerandom.strongAlgorithms} {@link Security} property.
564     //  * <p>
565     //  * Some situations require strong random values, such as when
566     //  * creating high-value/long-lived secrets like RSA public/private
567     //  * keys.  To help guide applications in selecting a suitable strong
568     //  * {@code SecureRandom} implementation, Java distributions
569     //  * include a list of known strong {@code SecureRandom}
570     //  * implementations in the {@code securerandom.strongAlgorithms}
571     //  * Security property.
572     //  * <p>
573     //  * Every implementation of the Java platform is required to
574     //  * support at least one strong {@code SecureRandom} implementation.
575     //  *
576     //  * @return a strong {@code SecureRandom} implementation as indicated
577     //  * by the {@code securerandom.strongAlgorithms} Security property
578     //  *
579     //  * @throws NoSuchAlgorithmException if no algorithm is available
580     //  *
581     //  * @see Security#getProperty(string)
582     //  *
583     //  * @since 1.8
584     //  */
585     // static SecureRandom getInstanceStrong()
586     //         throws NoSuchAlgorithmException {
587 
588     //     string property = AccessController.doPrivileged(
589     //         new PrivilegedAction!string() {
590     //             override
591     //             string run() {
592     //                 return Security.getProperty(
593     //                     "securerandom.strongAlgorithms");
594     //             }
595     //         });
596 
597     //     if ((property is null) || (property.length() == 0)) {
598     //         throw new NoSuchAlgorithmException(
599     //             "Null/empty securerandom.strongAlgorithms Security Property");
600     //     }
601 
602     //     string remainder = property;
603     //     while (remainder !is null) {
604     //         Matcher m;
605     //         if ((m = StrongPatternHolder.pattern.matcher(
606     //                 remainder)).matches()) {
607 
608     //             string alg = m.group(1);
609     //             string prov = m.group(3);
610 
611     //             try {
612     //                 if (prov is null) {
613     //                     return SecureRandom.getInstance(alg);
614     //                 } else {
615     //                     return SecureRandom.getInstance(alg, prov);
616     //                 }
617     //             } catch (NoSuchAlgorithmException |
618     //                     NoSuchProviderException e) {
619     //             }
620     //             remainder = m.group(5);
621     //         } else {
622     //             remainder = null;
623     //         }
624     //     }
625 
626     //     throw new NoSuchAlgorithmException(
627     //         "No strong SecureRandom impls available: " ~ property);
628     // }
629 
630     // // Declare serialVersionUID to be compatible with JDK1.1
631     // // static final long serialVersionUID = 4940670005562187L;
632 
633     // // Retain unused values serialized from JDK1.1
634     // /**
635     //  * @serial
636     //  */
637     // private byte[] state;
638     // /**
639     //  * @serial
640     //  */
641     // private MessageDigest digest = null;
642     // /**
643     //  * @serial
644     //  *
645     //  * We know that the MessageDigest class does not implement
646     //  * java.io.Serializable.  However, since this field is no longer
647     //  * used, it will always be NULL and won't affect the serialization
648     //  * of the SecureRandom class itself.
649     //  */
650     // private byte[] randomBytes;
651     // /**
652     //  * @serial
653     //  */
654     // private int randomBytesUsed;
655     // /**
656     //  * @serial
657     //  */
658     // private long counter;
659 }