8246613: Choose the default SecureRandom algo based on registration ordering

Fixed java.security.Provider and SecureRandom to use the 1st registered SecureRandom service

Reviewed-by: weijun, mullan
This commit is contained in:
Valerie Peng 2020-06-12 02:34:44 +00:00
parent edefd3c198
commit 0b8f18beda
3 changed files with 220 additions and 102 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -259,35 +259,51 @@ public class SecureRandom extends java.util.Random {
}
private void getDefaultPRNG(boolean setSeed, byte[] seed) {
String prng = getPrngAlgorithm();
if (prng == null) {
// bummer, get the SUN implementation
prng = "SHA1PRNG";
Service prngService = null;
String prngAlgorithm = null;
for (Provider p : Providers.getProviderList().providers()) {
// SUN provider uses the SunEntries.DEF_SECURE_RANDOM_ALGO
// as the default SecureRandom algorithm; for other providers,
// Provider.getDefaultSecureRandom() will use the 1st
// registered SecureRandom algorithm
if (p.getName().equals("SUN")) {
prngAlgorithm = SunEntries.DEF_SECURE_RANDOM_ALGO;
prngService = p.getService("SecureRandom", prngAlgorithm);
break;
} else {
prngService = p.getDefaultSecureRandomService();
if (prngService != null) {
prngAlgorithm = prngService.getAlgorithm();
break;
}
}
}
// per javadoc, if none of the Providers support a RNG algorithm,
// then an implementation-specific default is returned.
if (prngService == null) {
prngAlgorithm = "SHA1PRNG";
this.secureRandomSpi = new sun.security.provider.SecureRandom();
this.provider = Providers.getSunProvider();
if (setSeed) {
this.secureRandomSpi.engineSetSeed(seed);
}
} else {
try {
SecureRandom random = SecureRandom.getInstance(prng);
this.secureRandomSpi = random.getSecureRandomSpi();
this.provider = random.getProvider();
if (setSeed) {
this.secureRandomSpi.engineSetSeed(seed);
}
this.secureRandomSpi = (SecureRandomSpi)
prngService.newInstance(null);
this.provider = prngService.getProvider();
} catch (NoSuchAlgorithmException nsae) {
// never happens, because we made sure the algorithm exists
// should not happen
throw new RuntimeException(nsae);
}
}
if (setSeed) {
this.secureRandomSpi.engineSetSeed(seed);
}
// JDK 1.1 based implementations subclass SecureRandom instead of
// SecureRandomSpi. They will also go through this code path because
// they must call a SecureRandom constructor as it is their superclass.
// If we are dealing with such an implementation, do not set the
// algorithm value as it would be inaccurate.
if (getClass() == SecureRandom.class) {
this.algorithm = prng;
this.algorithm = prngAlgorithm;
}
}
@ -620,13 +636,6 @@ public class SecureRandom extends java.util.Random {
instance.provider, algorithm);
}
/**
* Returns the {@code SecureRandomSpi} of this {@code SecureRandom} object.
*/
SecureRandomSpi getSecureRandomSpi() {
return secureRandomSpi;
}
/**
* Returns the provider of this {@code SecureRandom} object.
*
@ -868,30 +877,6 @@ public class SecureRandom extends java.util.Random {
return retVal;
}
/**
* Gets a default PRNG algorithm by looking through all registered
* providers. Returns the first PRNG algorithm of the first provider that
* has registered a {@code SecureRandom} implementation, or null if none of
* the registered providers supplies a {@code SecureRandom} implementation.
*/
private static String getPrngAlgorithm() {
for (Provider p : Providers.getProviderList().providers()) {
// For SUN provider, we use SunEntries.DEFF_SECURE_RANDOM_ALGO
// as the default SecureRandom algorithm; for other providers,
// we continue to iterate through to the 1st SecureRandom
// service
if (p.getName().equals("SUN")) {
return SunEntries.DEF_SECURE_RANDOM_ALGO;
}
for (Service s : p.getServices()) {
if (s.getType().equals("SecureRandom")) {
return s.getAlgorithm();
}
}
}
return null;
}
/*
* Lazily initialize since Pattern.compile() is heavy.
* Effective Java (2nd Edition), Item 71.