-
Bug
-
Resolution: Fixed
-
P3
-
1.3.0
-
beta
-
generic
-
generic
Name: krC82822 Date: 03/06/2001
6 Mar 2001, eval1127@eng -- see also: #'s, 4405056, 4219386.
This may be a dupe/relative of # 4405056.
---------------
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0)
Java HotSpot(TM) Client VM (build 1.3.0, mixed mode)
The bug is a result of the implementation of the static getPrngAlgorithm()
method in java.security.SecureRandom. This operation is called as a result of
constructing a SecureRandom instance directly rather than through the
getInstance() operation.
The error occurs when a new provider is used that provides a new SecureRandom
implementation.
The offending code is shown below.
/**
* Gets a default PRNG algorithm by looking through all registered
* providers. Returns the first PRNG algorithm of the first provider that
* has registered a SecureRandom implementation, or null if none of the
* registered providers supplies a SecureRandom implementation.
*/
private static String getPrngAlgorithm() {
Provider[] provs = Security.getProviders();
for (int i=0; i<provs.length; i++) {
// search the provider's properties list for a property name
// that starts with "SecureRandom."
for (Enumeration e = provs[i].propertyNames();
e.hasMoreElements();) {
String propName = (String)e.nextElement();
if (propName.startsWith("SecureRandom.")) {
int index = propName.indexOf(".", 0);
return propName.substring(index+1);
}
}
}
return null;
}
The Sun provider adds two entries in the provider instance. These are as
follows,
public Object run()
{
....
put("SecureRandom.SHA1PRNG", "sun.security.provider.SecureRandom");
....
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
....
return null;
}
This means that the getPrngAlgorithm function is dependent on the actual
ordering of entries with the Hashtable.
If a different set of provider entries is used in this case only two entries,
corrsponding to the entries illustrated above but with differing implementations
Then the ordering of the entries in the enumeration may be different.
For example the getPrngAlgorithm() operation returned an algorithm string
'SHA1PRNG ImplementedIn'. This will obviously cause the call to getInstance() in
the SecureRandom(byte[] seed) constructor to fail.
The second coding error is the erroneous assumption that the
NoSuchAlgorithmException will never be thrown from the call to getInstance(). In
the situation described here the exception will indeed be thrown and the error
will cause a NullPointerException to be thrown when nextLong() of similar
operations are called.
The offending code fragment is below,
public SecureRandom(byte seed[]) {
super(0);
String prng = getPrngAlgorithm();
if (prng == null) {
// bummer, get the SUN implementation
this.secureRandomSpi = new sun.security.provider.SecureRandom();
this.provider = new sun.security.provider.Sun();
this.secureRandomSpi.engineSetSeed(seed);
} else {
try {
SecureRandom random = getInstance(prng);
this.secureRandomSpi = random.getSecureRandomSpi();
this.provider = random.getProvider();
this.secureRandomSpi.engineSetSeed(seed);
} catch (NoSuchAlgorithmException nsae) {
// never happens, because we made sure the algorithm exists
}
}
}
The most sensible solution would be to move to the situation where SecureRandom
did not derive from java.util.Random and adhered to the design contracts of the
JCA and JCE.
The problem is compounded by the fact that a much third party software has
implement code that uses the SecureRandom constructor making it difficult to
plugin new crypto providers.
(Review ID: 116890)
======================================================================