1 /*
2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.security;
27 
28 import java.util.*;
29 import java.util.regex.*;
30 
31 import java.security.Provider.Service;
32 import java.util.function.Function;
33 
34 import dalvik.system.VMRuntime;
35 import sun.security.jca.*;
36 import sun.security.jca.GetInstance.Instance;
37 
38 /**
39  * This class provides a cryptographically strong random number
40  * generator (RNG).
41  *
42  * <p>A cryptographically strong random number
43  * minimally complies with the statistical random number generator tests
44  * specified in <a href="http://csrc.nist.gov/cryptval/140-2.htm">
45  * <i>FIPS 140-2, Security Requirements for Cryptographic Modules</i></a>,
46  * section 4.9.1.
47  * Additionally, SecureRandom must produce non-deterministic output.
48  * Therefore any seed material passed to a SecureRandom object must be
49  * unpredictable, and all SecureRandom output sequences must be
50  * cryptographically strong, as described in
51  * <a href="http://www.ietf.org/rfc/rfc1750.txt">
52  * <i>RFC 1750: Randomness Recommendations for Security</i></a>.
53  *
54  * <p>A caller obtains a SecureRandom instance via the
55  * no-argument constructor or one of the {@code getInstance} methods:
56  *
57  * <pre>
58  *      SecureRandom random = new SecureRandom();
59  * </pre>
60  *
61  * <p> Many SecureRandom implementations are in the form of a pseudo-random
62  * number generator (PRNG), which means they use a deterministic algorithm
63  * to produce a pseudo-random sequence from a true random seed.
64  * Other implementations may produce true random numbers,
65  * and yet others may use a combination of both techniques.
66  *
67  * <p> Typical callers of SecureRandom invoke the following methods
68  * to retrieve random bytes:
69  *
70  * <pre>
71  *      SecureRandom random = new SecureRandom();
72  *      byte bytes[] = new byte[20];
73  *      random.nextBytes(bytes);
74  * </pre>
75  *
76  * <p> Callers may also invoke the {@code generateSeed} method
77  * to generate a given number of seed bytes (to seed other random number
78  * generators, for example):
79  * <pre>
80  *      byte seed[] = random.generateSeed(20);
81  * </pre>
82  *
83  * Note: Depending on the implementation, the {@code generateSeed} and
84  * {@code nextBytes} methods may block as entropy is being gathered,
85  * for example, if they need to read from /dev/random on various Unix-like
86  * operating systems.
87  *
88  * The SHA1PRNG algorithm from the Crypto provider has been deprecated as it was insecure, and also
89  * incorrectly used by some apps as a key derivation function. See
90  * <a href="http://android-developers.blogspot.com/2016/06/security-crypto-provider-deprecated-in.html">
91  * Security &quot;Crypto&quot; provider deprecated in Android N</a> for details.
92  *
93  * @see java.security.SecureRandomSpi
94  * @see java.util.Random
95  *
96  * @author Benjamin Renaud
97  * @author Josh Bloch
98  */
99 
100 public class SecureRandom extends java.util.Random {
101 
102     // Android-removed: this debugging mechanism is not supported in Android.
103     /*
104     private static final Debug pdebug =
105                         Debug.getInstance("provider", "Provider");
106     private static final boolean skipDebug =
107         Debug.isOn("engine=") && !Debug.isOn("securerandom");
108     */
109     // END Android-removed
110 
111     /**
112      * The provider.
113      *
114      * @serial
115      * @since 1.2
116      */
117     private Provider provider = null;
118 
119     /**
120      * The provider implementation.
121      *
122      * @serial
123      * @since 1.2
124      */
125     private SecureRandomSpi secureRandomSpi = null;
126 
127     /*
128      * The algorithm name of null if unknown.
129      *
130      * @serial
131      * @since 1.5
132      */
133     private String algorithm;
134 
135     // Seed Generator
136     private static volatile SecureRandom seedGenerator = null;
137 
138     /**
139      * Constructs a secure random number generator (RNG) implementing the
140      * default random number algorithm.
141      *
142      * <p> This constructor traverses the list of registered security Providers,
143      * starting with the most preferred Provider.
144      * A new SecureRandom object encapsulating the
145      * SecureRandomSpi implementation from the first
146      * Provider that supports a SecureRandom (RNG) algorithm is returned.
147      * If none of the Providers support a RNG algorithm,
148      * then an implementation-specific default is returned.
149      *
150      * <p> Note that the list of registered providers may be retrieved via
151      * the {@link Security#getProviders() Security.getProviders()} method.
152      *
153      * <p> See the SecureRandom section in the <a href=
154      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
155      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
156      * for information about standard RNG algorithm names.
157      *
158      * <p> The returned SecureRandom object has not been seeded.  To seed the
159      * returned object, call the {@code setSeed} method.
160      * If {@code setSeed} is not called, the first call to
161      * {@code nextBytes} will force the SecureRandom object to seed itself.
162      * This self-seeding will not occur if {@code setSeed} was
163      * previously called.
164      */
SecureRandom()165     public SecureRandom() {
166         /*
167          * This call to our superclass constructor will result in a call
168          * to our own {@code setSeed} method, which will return
169          * immediately when it is passed zero.
170          */
171         super(0);
172         getDefaultPRNG(false, null);
173     }
174 
175     /**
176      * Constructs a secure random number generator (RNG) implementing the
177      * default random number algorithm.
178      * The SecureRandom instance is seeded with the specified seed bytes.
179      *
180      * <p> This constructor traverses the list of registered security Providers,
181      * starting with the most preferred Provider.
182      * A new SecureRandom object encapsulating the
183      * SecureRandomSpi implementation from the first
184      * Provider that supports a SecureRandom (RNG) algorithm is returned.
185      * If none of the Providers support a RNG algorithm,
186      * then an implementation-specific default is returned.
187      *
188      * <p> Note that the list of registered providers may be retrieved via
189      * the {@link Security#getProviders() Security.getProviders()} method.
190      *
191      * <p> See the SecureRandom section in the <a href=
192      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
193      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
194      * for information about standard RNG algorithm names.
195      *
196      * @param seed the seed.
197      */
SecureRandom(byte seed[])198     public SecureRandom(byte seed[]) {
199         super(0);
200         getDefaultPRNG(true, seed);
201     }
202 
getDefaultPRNG(boolean setSeed, byte[] seed)203     private void getDefaultPRNG(boolean setSeed, byte[] seed) {
204         String prng = getPrngAlgorithm();
205         if (prng == null) {
206             // Android-changed, should never happen
207             throw new IllegalStateException("No SecureRandom implementation!");
208         } else {
209             try {
210                 SecureRandom random = SecureRandom.getInstance(prng);
211                 this.secureRandomSpi = random.getSecureRandomSpi();
212                 this.provider = random.getProvider();
213                 if (setSeed) {
214                     this.secureRandomSpi.engineSetSeed(seed);
215                 }
216             } catch (NoSuchAlgorithmException nsae) {
217                 // never happens, because we made sure the algorithm exists
218                 throw new RuntimeException(nsae);
219             }
220         }
221         // JDK 1.1 based implementations subclass SecureRandom instead of
222         // SecureRandomSpi. They will also go through this code path because
223         // they must call a SecureRandom constructor as it is their superclass.
224         // If we are dealing with such an implementation, do not set the
225         // algorithm value as it would be inaccurate.
226         if (getClass() == SecureRandom.class) {
227             this.algorithm = prng;
228         }
229     }
230 
231     /**
232      * Creates a SecureRandom object.
233      *
234      * @param secureRandomSpi the SecureRandom implementation.
235      * @param provider the provider.
236      */
SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider)237     protected SecureRandom(SecureRandomSpi secureRandomSpi,
238                            Provider provider) {
239         this(secureRandomSpi, provider, null);
240     }
241 
SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider, String algorithm)242     private SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider,
243             String algorithm) {
244         super(0);
245         this.secureRandomSpi = secureRandomSpi;
246         this.provider = provider;
247         this.algorithm = algorithm;
248 
249         // BEGIN Android-removed: this debugging mechanism is not supported in Android.
250         /*
251         if (!skipDebug && pdebug != null) {
252             pdebug.println("SecureRandom." + algorithm +
253                 " algorithm from: " + this.provider.getName());
254         }
255         */
256         // END Android-removed
257     }
258 
259     /**
260      * Returns a SecureRandom object that implements the specified
261      * Random Number Generator (RNG) algorithm.
262      *
263      * <p> This method traverses the list of registered security Providers,
264      * starting with the most preferred Provider.
265      * A new SecureRandom object encapsulating the
266      * SecureRandomSpi implementation from the first
267      * Provider that supports the specified algorithm is returned.
268      *
269      * <p> Note that the list of registered providers may be retrieved via
270      * the {@link Security#getProviders() Security.getProviders()} method.
271      *
272      * <p> The returned SecureRandom object has not been seeded.  To seed the
273      * returned object, call the {@code setSeed} method.
274      * If {@code setSeed} is not called, the first call to
275      * {@code nextBytes} will force the SecureRandom object to seed itself.
276      * This self-seeding will not occur if {@code setSeed} was
277      * previously called.
278      *
279      * @param algorithm the name of the RNG algorithm.
280      * See the SecureRandom section in the <a href=
281      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
282      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
283      * for information about standard RNG algorithm names.
284      *
285      * @return the new SecureRandom object.
286      *
287      * @exception NoSuchAlgorithmException if no Provider supports a
288      *          SecureRandomSpi implementation for the
289      *          specified algorithm.
290      *
291      * @see Provider
292      *
293      * @since 1.2
294      */
getInstance(String algorithm)295     public static SecureRandom getInstance(String algorithm)
296             throws NoSuchAlgorithmException {
297         Instance instance = GetInstance.getInstance("SecureRandom",
298             SecureRandomSpi.class, algorithm);
299         return new SecureRandom((SecureRandomSpi)instance.impl,
300             instance.provider, algorithm);
301     }
302 
303     /**
304      * Maximum SDK version for which the workaround for the Crypto provider is in place.
305      *
306      * <p> We provide instances from the Crypto provider (although the provider is not installed) to
307      * apps targeting M or earlier versions of the SDK.
308      *
309      * <p> Default is 23 (M). We have it as a field for testability and it shouldn't be changed.
310      *
311      * @hide
312      */
313     public static final int DEFAULT_SDK_TARGET_FOR_CRYPTO_PROVIDER_WORKAROUND = 23;
314 
315     private static int sdkTargetForCryptoProviderWorkaround =
316             DEFAULT_SDK_TARGET_FOR_CRYPTO_PROVIDER_WORKAROUND;
317 
318     /**
319      * Only for testing.
320      *
321      * @hide
322      */
setSdkTargetForCryptoProviderWorkaround(int sdkTargetVersion)323     public static void setSdkTargetForCryptoProviderWorkaround(int sdkTargetVersion) {
324         sdkTargetForCryptoProviderWorkaround = sdkTargetVersion;
325     }
326 
327     /**
328      * Only for testing.
329      *
330      * @hide
331      */
getSdkTargetForCryptoProviderWorkaround()332     public static int getSdkTargetForCryptoProviderWorkaround() {
333         return sdkTargetForCryptoProviderWorkaround;
334     }
335 
336     /**
337      * Returns a SecureRandom object that implements the specified
338      * Random Number Generator (RNG) algorithm.
339      *
340      * <p> A new SecureRandom object encapsulating the
341      * SecureRandomSpi implementation from the specified provider
342      * is returned.  The specified provider must be registered
343      * in the security provider list.
344      *
345      * <p> Note that the list of registered providers may be retrieved via
346      * the {@link Security#getProviders() Security.getProviders()} method.
347      *
348      * <p> The returned SecureRandom object has not been seeded.  To seed the
349      * returned object, call the {@code setSeed} method.
350      * If {@code setSeed} is not called, the first call to
351      * {@code nextBytes} will force the SecureRandom object to seed itself.
352      * This self-seeding will not occur if {@code setSeed} was
353      * previously called.
354      *
355      * @param algorithm the name of the RNG algorithm.
356      * See the SecureRandom section in the <a href=
357      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
358      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
359      * for information about standard RNG algorithm names.
360      *
361      * @param provider the name of the provider.
362      *
363      * @return the new SecureRandom object.
364      *
365      * @exception NoSuchAlgorithmException if a SecureRandomSpi
366      *          implementation for the specified algorithm is not
367      *          available from the specified provider.
368      *
369      * @exception NoSuchProviderException if the specified provider is not
370      *          registered in the security provider list.
371      *
372      * @exception IllegalArgumentException if the provider name is null
373      *          or empty.
374      *
375      * @see Provider
376      *
377      * @since 1.2
378      */
getInstance(String algorithm, String provider)379     public static SecureRandom getInstance(String algorithm, String provider)
380             throws NoSuchAlgorithmException, NoSuchProviderException {
381         try {
382             Instance instance = GetInstance.getInstance("SecureRandom",
383                     SecureRandomSpi.class, algorithm, provider);
384             return new SecureRandom((SecureRandomSpi) instance.impl,
385                     instance.provider, algorithm);
386         } catch (NoSuchProviderException nspe) {
387             if ("Crypto".equals(provider)) {
388                 System.logE(" ********** PLEASE READ ************ ");
389                 System.logE(" * ");
390                 System.logE(" * New versions of the Android SDK no longer support the Crypto provider.");
391                 System.logE(" * If your app was relying on setSeed() to derive keys from strings, you");
392                 System.logE(" * should switch to using SecretKeySpec to load raw key bytes directly OR");
393                 System.logE(" * use a real key derivation function (KDF). See advice here : ");
394                 System.logE(" * http://android-developers.blogspot.com/2016/06/security-crypto-provider-deprecated-in.html ");
395                 System.logE(" *********************************** ");
396                 if (VMRuntime.getRuntime().getTargetSdkVersion()
397                         <= sdkTargetForCryptoProviderWorkaround) {
398                     System.logE(" Returning an instance of SecureRandom from the Crypto provider");
399                     System.logE(" as a temporary measure so that the apps targeting earlier SDKs");
400                     System.logE(" keep working. Please do not rely on the presence of the Crypto");
401                     System.logE(" provider in the codebase, as our plan is to delete it");
402                     System.logE(" completely in the future.");
403                     return getInstanceFromCryptoProvider(algorithm);
404                 }
405             }
406 
407             throw nspe;
408         }
409     }
410 
getInstanceFromCryptoProvider(String algorithm)411     private static SecureRandom getInstanceFromCryptoProvider(String algorithm)
412             throws NoSuchAlgorithmException {
413         Provider cryptoProvider;
414         try {
415             cryptoProvider = (Provider) SecureRandom.class.getClassLoader()
416                     .loadClass(
417                             "org.apache.harmony.security.provider.crypto.CryptoProvider")
418                     .newInstance();
419         } catch (Exception e) {
420             throw new RuntimeException(e);
421         }
422         Service service = cryptoProvider.getService("SecureRandom", algorithm);
423         Instance instance = GetInstance.getInstance(service, SecureRandomSpi.class);
424         return new SecureRandom(
425                 (SecureRandomSpi) instance.impl, instance.provider, algorithm);
426     }
427 
428     /**
429      * Returns a SecureRandom object that implements the specified
430      * Random Number Generator (RNG) algorithm.
431      *
432      * <p> A new SecureRandom object encapsulating the
433      * SecureRandomSpi implementation from the specified Provider
434      * object is returned.  Note that the specified Provider object
435      * does not have to be registered in the provider list.
436      *
437      * <p> The returned SecureRandom object has not been seeded.  To seed the
438      * returned object, call the {@code setSeed} method.
439      * If {@code setSeed} is not called, the first call to
440      * {@code nextBytes} will force the SecureRandom object to seed itself.
441      * This self-seeding will not occur if {@code setSeed} was
442      * previously called.
443      *
444      * @param algorithm the name of the RNG algorithm.
445      * See the SecureRandom section in the <a href=
446      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
447      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
448      * for information about standard RNG algorithm names.
449      *
450      * @param provider the provider.
451      *
452      * @return the new SecureRandom object.
453      *
454      * @exception NoSuchAlgorithmException if a SecureRandomSpi
455      *          implementation for the specified algorithm is not available
456      *          from the specified Provider object.
457      *
458      * @exception IllegalArgumentException if the specified provider is null.
459      *
460      * @see Provider
461      *
462      * @since 1.4
463      */
getInstance(String algorithm, Provider provider)464     public static SecureRandom getInstance(String algorithm,
465             Provider provider) throws NoSuchAlgorithmException {
466         Instance instance = GetInstance.getInstance("SecureRandom",
467             SecureRandomSpi.class, algorithm, provider);
468         return new SecureRandom((SecureRandomSpi)instance.impl,
469             instance.provider, algorithm);
470     }
471 
472     /**
473      * Returns the SecureRandomSpi of this SecureRandom object.
474      */
getSecureRandomSpi()475     SecureRandomSpi getSecureRandomSpi() {
476         return secureRandomSpi;
477     }
478 
479     /**
480      * Returns the provider of this SecureRandom object.
481      *
482      * @return the provider of this SecureRandom object.
483      */
getProvider()484     public final Provider getProvider() {
485         return provider;
486     }
487 
488     /**
489      * Returns the name of the algorithm implemented by this SecureRandom
490      * object.
491      *
492      * @return the name of the algorithm or {@code unknown}
493      *          if the algorithm name cannot be determined.
494      * @since 1.5
495      */
getAlgorithm()496     public String getAlgorithm() {
497         return (algorithm != null) ? algorithm : "unknown";
498     }
499 
500     /**
501      * Reseeds this random object. The given seed supplements, rather than
502      * replaces, the existing seed. Thus, repeated calls are guaranteed
503      * never to reduce randomness.
504      *
505      * @param seed the seed.
506      *
507      * @see #getSeed
508      */
setSeed(byte[] seed)509     synchronized public void setSeed(byte[] seed) {
510         secureRandomSpi.engineSetSeed(seed);
511     }
512 
513     /**
514      * Reseeds this random object, using the eight bytes contained
515      * in the given {@code long seed}. The given seed supplements,
516      * rather than replaces, the existing seed. Thus, repeated calls
517      * are guaranteed never to reduce randomness.
518      *
519      * <p>This method is defined for compatibility with
520      * {@code java.util.Random}.
521      *
522      * @param seed the seed.
523      *
524      * @see #getSeed
525      */
526     @Override
setSeed(long seed)527     public void setSeed(long seed) {
528         /*
529          * Ignore call from super constructor (as well as any other calls
530          * unfortunate enough to be passing 0).  It's critical that we
531          * ignore call from superclass constructor, as digest has not
532          * yet been initialized at that point.
533          */
534         if (seed != 0) {
535             secureRandomSpi.engineSetSeed(longToByteArray(seed));
536         }
537     }
538 
539     /**
540      * Generates a user-specified number of random bytes.
541      *
542      * <p> If a call to {@code setSeed} had not occurred previously,
543      * the first call to this method forces this SecureRandom object
544      * to seed itself.  This self-seeding will not occur if
545      * {@code setSeed} was previously called.
546      *
547      * @param bytes the array to be filled in with random bytes.
548      */
549     @Override
nextBytes(byte[] bytes)550     synchronized public void nextBytes(byte[] bytes) {
551         secureRandomSpi.engineNextBytes(bytes);
552     }
553 
554     /**
555      * Generates an integer containing the user-specified number of
556      * pseudo-random bits (right justified, with leading zeros).  This
557      * method overrides a {@code java.util.Random} method, and serves
558      * to provide a source of random bits to all of the methods inherited
559      * from that class (for example, {@code nextInt},
560      * {@code nextLong}, and {@code nextFloat}).
561      *
562      * @param numBits number of pseudo-random bits to be generated, where
563      * {@code 0 <= numBits <= 32}.
564      *
565      * @return an {@code int} containing the user-specified number
566      * of pseudo-random bits (right justified, with leading zeros).
567      */
568     @Override
next(int numBits)569     final protected int next(int numBits) {
570         int numBytes = (numBits+7)/8;
571         byte b[] = new byte[numBytes];
572         int next = 0;
573 
574         nextBytes(b);
575         for (int i = 0; i < numBytes; i++) {
576             next = (next << 8) + (b[i] & 0xFF);
577         }
578 
579         return next >>> (numBytes*8 - numBits);
580     }
581 
582     /**
583      * Returns the given number of seed bytes, computed using the seed
584      * generation algorithm that this class uses to seed itself.  This
585      * call may be used to seed other random number generators.
586      *
587      * <p>This method is only included for backwards compatibility.
588      * The caller is encouraged to use one of the alternative
589      * {@code getInstance} methods to obtain a SecureRandom object, and
590      * then call the {@code generateSeed} method to obtain seed bytes
591      * from that object.
592      *
593      * @param numBytes the number of seed bytes to generate.
594      *
595      * @return the seed bytes.
596      *
597      * @see #setSeed
598      */
getSeed(int numBytes)599     public static byte[] getSeed(int numBytes) {
600         if (seedGenerator == null) {
601             seedGenerator = new SecureRandom();
602         }
603         return seedGenerator.generateSeed(numBytes);
604     }
605 
606     /**
607      * Returns the given number of seed bytes, computed using the seed
608      * generation algorithm that this class uses to seed itself.  This
609      * call may be used to seed other random number generators.
610      *
611      * @param numBytes the number of seed bytes to generate.
612      *
613      * @return the seed bytes.
614      */
generateSeed(int numBytes)615     public byte[] generateSeed(int numBytes) {
616         return secureRandomSpi.engineGenerateSeed(numBytes);
617     }
618 
619     /**
620      * Helper function to convert a long into a byte array (least significant
621      * byte first).
622      */
longToByteArray(long l)623     private static byte[] longToByteArray(long l) {
624         byte[] retVal = new byte[8];
625 
626         for (int i = 0; i < 8; i++) {
627             retVal[i] = (byte) l;
628             l >>= 8;
629         }
630 
631         return retVal;
632     }
633 
634     /**
635      * Gets a default PRNG algorithm by looking through all registered
636      * providers. Returns the first PRNG algorithm of the first provider that
637      * has registered a SecureRandom implementation, or null if none of the
638      * registered providers supplies a SecureRandom implementation.
639      */
getPrngAlgorithm()640     private static String getPrngAlgorithm() {
641         for (Provider p : Providers.getProviderList().providers()) {
642             for (Service s : p.getServices()) {
643                 if (s.getType().equals("SecureRandom")) {
644                     return s.getAlgorithm();
645                 }
646             }
647         }
648         return null;
649     }
650 
651     /*
652      * Lazily initialize since Pattern.compile() is heavy.
653      * Effective Java (2nd Edition), Item 71.
654      */
655     private static final class StrongPatternHolder {
656         /*
657          * Entries are alg:prov separated by ,
658          * Allow for prepended/appended whitespace between entries.
659          *
660          * Capture groups:
661          *     1 - alg
662          *     2 - :prov (optional)
663          *     3 - prov (optional)
664          *     4 - ,nextEntry (optional)
665          *     5 - nextEntry (optional)
666          */
667         private static Pattern pattern =
668             Pattern.compile(
669                 "\\s*([\\S&&[^:,]]*)(\\:([\\S&&[^,]]*))?\\s*(\\,(.*))?");
670     }
671 
672     /**
673      * Returns a {@code SecureRandom} object.
674      *
675      * In Android this is equivalent to get a SHA1PRNG from OpenSSLProvider.
676      *
677      * Some situations require strong random values, such as when
678      * creating high-value/long-lived secrets like RSA public/private
679      * keys.  To help guide applications in selecting a suitable strong
680      * {@code SecureRandom} implementation, Java distributions
681      * include a list of known strong {@code SecureRandom}
682      * implementations in the {@code securerandom.strongAlgorithms}
683      * Security property.
684      * <p>
685      * Every implementation of the Java platform is required to
686      * support at least one strong {@code SecureRandom} implementation.
687      *
688      * @return a strong {@code SecureRandom} implementation
689      *
690      * @throws NoSuchAlgorithmException if no algorithm is available
691      *
692      * @see Security#getProperty(String)
693      *
694      * @since 1.8
695      */
getInstanceStrong()696     public static SecureRandom getInstanceStrong()
697             throws NoSuchAlgorithmException {
698         String property = AccessController.doPrivileged(
699             new PrivilegedAction<String>() {
700                 @Override
701                 public String run() {
702                     return Security.getProperty(
703                         "securerandom.strongAlgorithms");
704                 }
705             });
706 
707         if ((property == null) || (property.length() == 0)) {
708             throw new NoSuchAlgorithmException(
709                 "Null/empty securerandom.strongAlgorithms Security Property");
710         }
711 
712         String remainder = property;
713         while (remainder != null) {
714             Matcher m;
715             if ((m = StrongPatternHolder.pattern.matcher(
716                     remainder)).matches()) {
717 
718                 String alg = m.group(1);
719                 String prov = m.group(3);
720 
721                 try {
722                     if (prov == null) {
723                         return SecureRandom.getInstance(alg);
724                     } else {
725                         return SecureRandom.getInstance(alg, prov);
726                     }
727                 } catch (NoSuchAlgorithmException |
728                         NoSuchProviderException e) {
729                 }
730                 remainder = m.group(5);
731             } else {
732                 remainder = null;
733             }
734         }
735 
736         throw new NoSuchAlgorithmException(
737             "No strong SecureRandom impls available: " + property);
738     }
739 
740     // Declare serialVersionUID to be compatible with JDK1.1
741     static final long serialVersionUID = 4940670005562187L;
742 
743     // Retain unused values serialized from JDK1.1
744     /**
745      * @serial
746      */
747     private byte[] state;
748     /**
749      * @serial
750      */
751     private MessageDigest digest = null;
752     /**
753      * @serial
754      *
755      * We know that the MessageDigest class does not implement
756      * java.io.Serializable.  However, since this field is no longer
757      * used, it will always be NULL and won't affect the serialization
758      * of the SecureRandom class itself.
759      */
760     private byte[] randomBytes;
761     /**
762      * @serial
763      */
764     private int randomBytesUsed;
765     /**
766      * @serial
767      */
768     private long counter;
769 }
770