mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
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:
parent
edefd3c198
commit
0b8f18beda
3 changed files with 220 additions and 102 deletions
|
@ -858,10 +858,18 @@ public abstract class Provider extends Properties {
|
|||
// serviceMap changed since last call to getServices()
|
||||
private volatile transient boolean servicesChanged;
|
||||
|
||||
// Map<String,String> used to keep track of legacy registration
|
||||
private transient Map<String,String> legacyStrings;
|
||||
|
||||
// Map<ServiceKey,Service>
|
||||
// used for services added via putService(), initialized on demand
|
||||
private transient Map<ServiceKey,Service> serviceMap;
|
||||
|
||||
// For backward compatibility, the registration ordering of
|
||||
// SecureRandom (RNG) algorithms needs to be preserved for
|
||||
// "new SecureRandom()" calls when this provider is used
|
||||
private transient Set<Service> prngServices;
|
||||
|
||||
// Map<ServiceKey,Service>
|
||||
// used for services added via legacy methods, init on demand
|
||||
private transient Map<ServiceKey,Service> legacyMap;
|
||||
|
@ -913,12 +921,18 @@ public abstract class Provider extends Properties {
|
|||
putAll(copy);
|
||||
}
|
||||
|
||||
private static boolean isProviderInfo(Object key) {
|
||||
// check whether to update 'legacyString' with the specified key
|
||||
private boolean checkLegacy(Object key) {
|
||||
String keyString = (String)key;
|
||||
if (keyString.startsWith("Provider.")) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
legacyChanged = true;
|
||||
if (legacyStrings == null) {
|
||||
legacyStrings = new LinkedHashMap<>();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -934,20 +948,20 @@ public abstract class Provider extends Properties {
|
|||
|
||||
private Object implRemove(Object key) {
|
||||
if (key instanceof String) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return null;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.remove((String)key);
|
||||
}
|
||||
return super.remove(key);
|
||||
}
|
||||
|
||||
private boolean implRemove(Object key, Object value) {
|
||||
if (key instanceof String && value instanceof String) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return false;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.remove((String)key, (String)value);
|
||||
}
|
||||
return super.remove(key, value);
|
||||
}
|
||||
|
@ -955,20 +969,21 @@ public abstract class Provider extends Properties {
|
|||
private boolean implReplace(Object key, Object oldValue, Object newValue) {
|
||||
if ((key instanceof String) && (oldValue instanceof String) &&
|
||||
(newValue instanceof String)) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return false;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.replace((String)key, (String)oldValue,
|
||||
(String)newValue);
|
||||
}
|
||||
return super.replace(key, oldValue, newValue);
|
||||
}
|
||||
|
||||
private Object implReplace(Object key, Object value) {
|
||||
if ((key instanceof String) && (value instanceof String)) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return null;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.replace((String)key, (String)value);
|
||||
}
|
||||
return super.replace(key, value);
|
||||
}
|
||||
|
@ -977,17 +992,26 @@ public abstract class Provider extends Properties {
|
|||
private void implReplaceAll(BiFunction<? super Object, ? super Object,
|
||||
? extends Object> function) {
|
||||
legacyChanged = true;
|
||||
if (legacyStrings == null) {
|
||||
legacyStrings = new LinkedHashMap<>();
|
||||
} else {
|
||||
legacyStrings.replaceAll((BiFunction<? super String, ? super String,
|
||||
? extends String>) function);
|
||||
}
|
||||
super.replaceAll(function);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // Function must actually operate over strings
|
||||
private Object implMerge(Object key, Object value, BiFunction<? super Object,
|
||||
? super Object, ? extends Object> remappingFunction) {
|
||||
private Object implMerge(Object key, Object value,
|
||||
BiFunction<? super Object, ? super Object, ? extends Object>
|
||||
remappingFunction) {
|
||||
if ((key instanceof String) && (value instanceof String)) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return null;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.merge((String)key, (String)value,
|
||||
(BiFunction<? super String, ? super String,
|
||||
? extends String>) remappingFunction);
|
||||
}
|
||||
return super.merge(key, value, remappingFunction);
|
||||
}
|
||||
|
@ -996,10 +1020,12 @@ public abstract class Provider extends Properties {
|
|||
private Object implCompute(Object key, BiFunction<? super Object,
|
||||
? super Object, ? extends Object> remappingFunction) {
|
||||
if (key instanceof String) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return null;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.compute((String) key,
|
||||
(BiFunction<? super String,? super String,
|
||||
? extends String>) remappingFunction);
|
||||
}
|
||||
return super.compute(key, remappingFunction);
|
||||
}
|
||||
|
@ -1008,10 +1034,12 @@ public abstract class Provider extends Properties {
|
|||
private Object implComputeIfAbsent(Object key, Function<? super Object,
|
||||
? extends Object> mappingFunction) {
|
||||
if (key instanceof String) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return null;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.computeIfAbsent((String) key,
|
||||
(Function<? super String, ? extends String>)
|
||||
mappingFunction);
|
||||
}
|
||||
return super.computeIfAbsent(key, mappingFunction);
|
||||
}
|
||||
|
@ -1020,35 +1048,40 @@ public abstract class Provider extends Properties {
|
|||
private Object implComputeIfPresent(Object key, BiFunction<? super Object,
|
||||
? super Object, ? extends Object> remappingFunction) {
|
||||
if (key instanceof String) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return null;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.computeIfPresent((String) key,
|
||||
(BiFunction<? super String, ? super String,
|
||||
? extends String>) remappingFunction);
|
||||
}
|
||||
return super.computeIfPresent(key, remappingFunction);
|
||||
}
|
||||
|
||||
private Object implPut(Object key, Object value) {
|
||||
if ((key instanceof String) && (value instanceof String)) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return null;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.put((String)key, (String)value);
|
||||
}
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
private Object implPutIfAbsent(Object key, Object value) {
|
||||
if ((key instanceof String) && (value instanceof String)) {
|
||||
if (isProviderInfo(key)) {
|
||||
if (!checkLegacy(key)) {
|
||||
return null;
|
||||
}
|
||||
legacyChanged = true;
|
||||
legacyStrings.putIfAbsent((String)key, (String)value);
|
||||
}
|
||||
return super.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
private void implClear() {
|
||||
if (legacyStrings != null) {
|
||||
legacyStrings.clear();
|
||||
}
|
||||
if (legacyMap != null) {
|
||||
legacyMap.clear();
|
||||
}
|
||||
|
@ -1056,6 +1089,7 @@ public abstract class Provider extends Properties {
|
|||
legacyChanged = false;
|
||||
servicesChanged = false;
|
||||
serviceSet = null;
|
||||
prngServices = null;
|
||||
super.clear();
|
||||
putId();
|
||||
}
|
||||
|
@ -1095,7 +1129,7 @@ public abstract class Provider extends Properties {
|
|||
* service objects.
|
||||
*/
|
||||
private void ensureLegacyParsed() {
|
||||
if (legacyChanged == false) {
|
||||
if (legacyChanged == false || (legacyStrings == null)) {
|
||||
return;
|
||||
}
|
||||
serviceSet = null;
|
||||
|
@ -1104,7 +1138,7 @@ public abstract class Provider extends Properties {
|
|||
} else {
|
||||
legacyMap.clear();
|
||||
}
|
||||
for (Map.Entry<?,?> entry : super.entrySet()) {
|
||||
for (Map.Entry<String,String> entry : legacyStrings.entrySet()) {
|
||||
parseLegacyPut(entry.getKey(), entry.getValue());
|
||||
}
|
||||
removeInvalidServices(legacyMap);
|
||||
|
@ -1125,12 +1159,12 @@ public abstract class Provider extends Properties {
|
|||
}
|
||||
}
|
||||
|
||||
private String[] getTypeAndAlgorithm(String key) {
|
||||
private static String[] getTypeAndAlgorithm(String key) {
|
||||
int i = key.indexOf('.');
|
||||
if (i < 1) {
|
||||
if (debug != null) {
|
||||
debug.println("Ignoring invalid entry in provider "
|
||||
+ name + ":" + key);
|
||||
debug.println("Ignoring invalid entry in provider: "
|
||||
+ key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -1143,15 +1177,7 @@ public abstract class Provider extends Properties {
|
|||
private static final String ALIAS_PREFIX_LOWER = "alg.alias.";
|
||||
private static final int ALIAS_LENGTH = ALIAS_PREFIX.length();
|
||||
|
||||
private void parseLegacyPut(Object k, Object v) {
|
||||
if (!(k instanceof String) || !(v instanceof String)) {
|
||||
return;
|
||||
}
|
||||
String name = (String) k;
|
||||
String value = (String) v;
|
||||
if (isProviderInfo(name)) {
|
||||
return;
|
||||
}
|
||||
private void parseLegacyPut(String name, String value) {
|
||||
if (name.toLowerCase(ENGLISH).startsWith(ALIAS_PREFIX_LOWER)) {
|
||||
// e.g. put("Alg.Alias.MessageDigest.SHA", "SHA-1");
|
||||
// aliasKey ~ MessageDigest.SHA
|
||||
|
@ -1193,6 +1219,10 @@ public abstract class Provider extends Properties {
|
|||
legacyMap.put(key, s);
|
||||
}
|
||||
s.className = className;
|
||||
|
||||
if (type.equals("SecureRandom")) {
|
||||
updateSecureRandomEntries(true, s);
|
||||
}
|
||||
} else { // attribute
|
||||
// e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software");
|
||||
String attributeValue = value;
|
||||
|
@ -1352,9 +1382,46 @@ public abstract class Provider extends Properties {
|
|||
servicesChanged = true;
|
||||
synchronized (this) {
|
||||
putPropertyStrings(s);
|
||||
if (type.equals("SecureRandom")) {
|
||||
updateSecureRandomEntries(true, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSecureRandomEntries(boolean doAdd, Service s) {
|
||||
Objects.requireNonNull(s);
|
||||
if (doAdd) {
|
||||
if (prngServices == null) {
|
||||
prngServices = new LinkedHashSet<Service>();
|
||||
}
|
||||
prngServices.add(s);
|
||||
} else {
|
||||
prngServices.remove(s);
|
||||
}
|
||||
|
||||
if (debug != null) {
|
||||
debug.println((doAdd? "Add":"Remove") + " SecureRandom algo " +
|
||||
s.getAlgorithm());
|
||||
}
|
||||
}
|
||||
|
||||
// used by new SecureRandom() to find out the default SecureRandom
|
||||
// service for this provider
|
||||
synchronized Service getDefaultSecureRandomService() {
|
||||
checkInitialized();
|
||||
|
||||
if (legacyChanged) {
|
||||
prngServices = null;
|
||||
ensureLegacyParsed();
|
||||
}
|
||||
|
||||
if (prngServices != null && !prngServices.isEmpty()) {
|
||||
return prngServices.iterator().next();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the string properties for this Service in this Provider's
|
||||
* Hashtable.
|
||||
|
@ -1448,6 +1515,9 @@ public abstract class Provider extends Properties {
|
|||
}
|
||||
synchronized (this) {
|
||||
removePropertyStrings(s);
|
||||
if (type.equals("SecureRandom")) {
|
||||
updateSecureRandomEntries(false, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue