JDK-6382135 : RSA premaster secret error / Cannot find any provider supporting RSA/ECB/PKCS1Padding
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-02-07
  • Updated: 2011-02-16
  • Resolved: 2006-05-12
Description
FULL PRODUCT VERSION :
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Windows -XP

A DESCRIPTION OF THE PROBLEM :
While communicating to an Active Directory server via SSL and also exuting the application with a security manager in place javax.naming.CommunicationException exception is thrown.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :

1. Include the root certificate of Active Direcotry into the cacerts of the JAVA_HOME/jre/lib/security folder.

2.Create a class file from the attached testcase

3. JAR this class file. Make sure that a policy file exists to grant it all the permissions. Excute it via the command prompt and use

java -Djava.security.manager   <class file>

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I was expecting the user to be successfully authenticated and no exceptions to be thrown.
ACTUAL -
javax.naming.CommunicationException: simple bind failed: <server ip>:636 [Root
xception is javax.net.ssl.SSLKeyException: RSA premaster secret error]
 
ERROR MESSAGES/STACK TRACES THAT OCCUR :
javax.naming.CommunicationException: simple bind failed: <server ip>:636 [Root
xception is javax.net.ssl.SSLKeyException: RSA premaster secret error]
        at com.sun.jndi.ldap.LdapClient.authenticate(Unknown Source)
        at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source)
        at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source)
        at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(Unknown Source)
        at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(Unknown Source)
        at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(Unknown Source)
        at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source)
        at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
        at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
        at javax.naming.InitialContext.init(Unknown Source)
        at javax.naming.InitialContext.<init>(Unknown Source)
        at javax.naming.directory.InitialDirContext.<init>(Unknown Source)
        at com.docfinity.loginmodule.OitJndiLoginModule.getContext(OitJndiLogin
odule.java:138)
        at com.docfinity.loginmodule.OitJndiLoginModule.login(OitJndiLoginModul
.java:81)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at javax.security.auth.login.LoginContext.invoke(Unknown Source)
        at javax.security.auth.login.LoginContext.access$000(Unknown Source)
        at javax.security.auth.login.LoginContext$4.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.login.LoginContext.invokePriv(Unknown Source)
        at javax.security.auth.login.LoginContext.login(Unknown Source)
        at com.docfinity.application.LoginManager.authenticateJndi(LoginManager
java:260)
        at com.docfinity.application.LoginManager.actionPerformed(LoginManager.
ava:129)
        at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
        at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Sou
ce)
        at java.awt.Component.processMouseEvent(Unknown Source)
        at javax.swing.JComponent.processMouseEvent(Unknown Source)
        at java.awt.Component.processEvent(Unknown Source)
        at java.awt.Container.processEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Window.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source

        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: javax.net.ssl.SSLKeyException: RSA premaster secret error
        at com.sun.net.ssl.internal.ssl.PreMasterSecret.<init>(Unknown Source)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(Unknow
 Source)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown
Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Sourc
)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source

        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(U
known Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(Unknown Sourc
)
        at com.sun.net.ssl.internal.ssl.AppOutputStream.write(Unknown Source)
        at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
        at java.io.BufferedOutputStream.flush(Unknown Source)
        at com.sun.jndi.ldap.Connection.writeRequest(Unknown Source)
        at com.sun.jndi.ldap.LdapClient.ldapBind(Unknown Source)
        ... 50 more
Caused by: java.security.NoSuchAlgorithmException: Cannot find any provider sup
orting RSA/ECB/PKCS1Padding
        at javax.crypto.Cipher.getInstance(DashoA12275)
        at com.sun.net.ssl.internal.ssl.JsseJce.getCipher(Unknown Source)
        at com.sun.net.ssl.internal.ssl.RSACipher.<init>(Unknown Source)
        at com.sun.net.ssl.internal.ssl.RSACipher.getInstance(Unknown Source)
        ... 63 more

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.util.Hashtable;
import javax.naming.ldap.*;
import javax.naming.directory.*;
import javax.naming.*;
  
public class searchssl
{
	public static void main (String[] args)
	{
	
		Hashtable env = new Hashtable();
		

		String adminName = "<username>";
		String adminPassword = "<passoword>";
		String ldapURL = "ldap://<serverip>:636";
 
		//Access the keystore, this is where the Root CA public key cert was installed
		//Could also do this via the command line option java -Djavax.net.ssl.trustStore....
		//No need to specifiy the keystore password for read operations
		System.out.println(System.getProperty("java.home"));
		System.out.println(System.getProperty("user.home"));
		String keystore = System.getProperty("java.home") + "/lib/security/cacerts";
		System.setProperty("javax.net.ssl.trustStore",keystore);
		
		env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
		
		//set security credentials
		env.put(Context.SECURITY_AUTHENTICATION,"simple");
		env.put(Context.SECURITY_PRINCIPAL,adminName);
		env.put(Context.SECURITY_CREDENTIALS,adminPassword);
 
		//specify use of ssl
		env.put(Context.SECURITY_PROTOCOL,"ssl");
				
		//connect to my domain controller
		env.put(Context.PROVIDER_URL,ldapURL);
		try {
 
			// Create the initial directory context
			LdapContext ctx = new InitialLdapContext(env,null);
			//Create the critical Sort control that sorts based on "cn"
			Control[] ctxCtls = new Control[]{
			    new SortControl(new String[]{"cn"}, Control.CRITICAL)
			};

			//Set the context's request controls to be ctxCtls
			ctx.setRequestControls(ctxCtls);
		
			//Create the search controls
			SearchControls searchCtls = new SearchControls();
		
			//Specify the attributes to return
			String returnedAtts[]={"sn","givenName","mail"};
			searchCtls.setReturningAttributes(returnedAtts);
		
			//Specify the search scope
			searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
 
			//specify the LDAP search filter
			String searchFilter = "(&(objectClass=user)(mail=*))";
 
			//Specify the Base for the search
			String searchBase = "DC=OIT,DC=DocFinity,DC=com";
 
			//initialize counter to total the results
			int totalResults = 0;
 
 
			// Search for objects using the filter
			NamingEnumeration answer = ctx.search(searchBase, searchFilter, searchCtls);
 
			//Loop through the search results
			while (answer.hasMoreElements()) {
		    		SearchResult sr = (SearchResult)answer.next();
 
				totalResults++;
 
				System.out.println(">>>" + sr.getName());
 
				// Print out some of the attributes, catch the exception if the attributes have no values
				Attributes attrs = sr.getAttributes();
				if (attrs != null) {
					try {
					System.out.println("   surname: " + attrs.get("sn").get());
					System.out.println("   firstname: " + attrs.get("givenName").get());
					System.out.println("   mail: " + attrs.get("mail").get());
					System.out.println("   password: " + attrs.get("userPassword"));
					}
					catch (NullPointerException e)	{
					System.out.println("Errors listing attributes: " + e);
					}
				}
 
			}
 
 			System.out.println("Total results: " + totalResults);
			ctx.close();
 
		}
		catch (NamingException e) {
			System.err.println("Problem searching directory: " + e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.err.println("IO Exception while setting the sort control: " + e);
		}
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Use Jdk1.4.2

Comments
EVALUATION In response to the JDC comments: if this only happens when the java.ext.dirs is set to exclude jre/lib/ext, then this is a user error and not a bug. The jre/lib/ext directory contains core system classes that are required for the JRE to operate correctly. In particular for this case, it contains sunjce_provider.jar, which contains all the implementations of encryption algorithms such as RSA/AES/DES, etc. In other words, the error messages is totally correct because if jre/lib/ext is excluded, there is no implementation for RSA available. The correct solution is to either put the application JAR files on the regular classpath ("-classpath") or if they need to be on the extension class path, use -Djava.ext.dirs=c:\jdk_location\jre\lib\ext;c:\other_directory (on Windows use ; as path separator; on Solaris/Linux use : ). See also http://java.sun.com/j2se/1.5.0/docs/guide/extensions/spec.html Closing as not-a-bug. If this can also be reproduced (using the directions mentioned above) when jre/lib/ext is included on the extension class path, please reopen or file a new bug (or let me know by adding JDC comments to this bug).
12-05-2006

EVALUATION Please check Andreas' suggestion number 2, we've had a number of bugs filed due to a particular IDE (Eclipse) putting the sunjce_provider.jar on the bootclasspath. If so, then this is a duplicate of 6331571. I would like to get this fixed in mustang, but may not have time.
08-02-2006

EVALUATION I am unable to reproduce this. If you can reproduce it, please do the following: (1) run the following program from the command line using "java -showversion -XX:+PrintVMOptions -XX:+PrintCommandLineFlags CipherTest". If it throws an Exception, send the complete output. === import java.util.*; public class CipherTest { // run 'java -showversion -XX:+PrintVMOptions -XX:+PrintCommandLineFlags CipherTest' public static void main(String[] args) throws Exception { System.out.println(new TreeMap(System.getProperties())); System.out.println(); System.out.println(Arrays.asList(java.security.Security.getProviders())); System.out.println(); System.out.println(Class.forName("javax.crypto.Cipher")); System.out.println(); System.out.println(javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1Padding")); System.out.println("Test OK"); } } === (2) If it does not fail from the command line but fails when you run it in your IDE or some other environment, then that environment/IDE is busted and needs to be fixed. In particular, it should not modify the bootclasspath or the location of the extensions directory. (3) If this program works but some other program fails *when run from the command line*, please send a reasonably self contained test case. That means including any java.policy or other supporting files that may be needed. And if possible, the test should not depend on servers that are non publicly accessible.
08-02-2006