JDK-5060313 : javax.net.ssl - https - ssl - exception
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Cannot Reproduce
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-06-09
  • Updated: 2004-11-13
  • Resolved: 2004-11-13
Description

Name: js151677			Date: 06/09/2004


FULL PRODUCT VERSION :
java version "1.5.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta2-b51)
Java HotSpot(TM) Client VM (build 1.5.0-beta2-b51, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
I have a https server with a self issued certificate (I used keytool to generate it) and a java developed browser.
When I try to connect the browser to my server using https://localhost:8080/ it fails under version 150-beta2, but it works under version 1.4.1_02

The exception message is different if the certificate was generate using RSA or DSA algorithm

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
generate certificate using keytool
------------------------------------------------------------------------------------
keytool -genkey -keystore serverkeys -keyalg rsa -alias myalias
keytool -export -keystore serverkeys -alias myalias -file server.cer
keytool -import -keystore trustedcerts -alias myalias -file server.cer
------------------------------------------------------------------------------------
create a file named index.html as start for server
start server
java HttpsServer
start client
java -Djavax.net.ssl.trustStore=trustedcerts HttpBrowser
point browser to address https://localhost:8080/

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect to see the content of file index.html
ACTUAL -
I get an exception message

ERROR MESSAGES/STACK TRACES THAT OCCUR :
if the certificate is generate using RSA the exception is
---------------------------------------------------------------------------------
javax.net.ssl.SSLKeyException: RSA premaster secret error
javax.net.ssl.SSLKeyException: RSA premaster secret error
	at com.sun.net.ssl.internal.ssl.PreMasterSecret. (Unknown Source)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(Unknown 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 Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
	at HttpsBrowser.readURL(HttpsBrowser.java:78)
	at HttpsBrowser.run(HttpsBrowser.java:57)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.security.NoSuchAlgorithmException: Cannot find any provider supporting 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. (Unknown Source)
	at com.sun.net.ssl.internal.ssl.RSACipher.getInstance(Unknown Source)
	... 15 more
----------------------------------------------------------------------------
if the certificate was generated using DSA
----------------------------------------------------------------------------

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate secret
javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate secret
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
	at HttpsBrowser.readURL(HttpsBrowser.java:78)
	at HttpsBrowser.run(HttpsBrowser.java:57)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.RuntimeException: Could not generate secret
	at com.sun.net.ssl.internal.ssl.DHKeyExchange.getAgreedSecret(Unknown Source)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(Unknown 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 Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
	... 8 more
Caused by: java.security.NoSuchAlgorithmException: DiffieHellman KeyFactory not available
	at java.security.KeyFactory. (Unknown Source)
	at java.security.KeyFactory.getInstance(Unknown Source)
	... 15 more


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
--------------
server
--------------

import java.io.*;
import java.net.*;
import javax.net.*;
import javax.net.ssl.*;
import java.security.*;
import java.util.StringTokenizer;

public class HttpsServer {

	String keystore = "serverkeys";
	char keystorepass[] = "pwdserverkeystore".toCharArray();
	char keypassword[] = "pwdserverkeystore".toCharArray();

	public static final int HTTPS_PORT = 8080;

	public ServerSocket getServer() throws Exception {

		KeyStore ks = KeyStore.getInstance("JKS");
		ks.load(new FileInputStream(keystore), keystorepass);
		KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
		kmf.init(ks, keypassword);
		SSLContext sslcontext = SSLContext.getInstance("SSLv3");
		sslcontext.init(kmf.getKeyManagers(), null, null);
		ServerSocketFactory ssf = sslcontext.getServerSocketFactory();
		SSLServerSocket serversocket = (SSLServerSocket) ssf
				.createServerSocket(HTTPS_PORT);
		return serversocket;

	}
	public void run() {
		ServerSocket listen;
		try {
			listen = getServer();
			while (true) {
				Socket client = listen.accept();
				ProcessConnection cc = new ProcessConnection(client);
			}
		} catch (Exception e) {
			System.out.println("Exception: " + e.getMessage());
		}
	}

	class ProcessConnection extends Thread {
		Socket client;
		BufferedReader is;
		DataOutputStream os;

		public ProcessConnection(Socket s) {
			client = s;
			try {
				is = new BufferedReader(new InputStreamReader(client
						.getInputStream()));
				os = new DataOutputStream(client.getOutputStream());
			} catch (IOException e) {
				System.out.println("Exception: " + e.getMessage());
			}
			this.start();
		}

		public void run() {
			try {
				String request = is.readLine();
				System.out.println("Request: " + request);
				StringTokenizer st = new StringTokenizer(request);
				if ((st.countTokens() >= 2) && st.nextToken().equals("GET")) {
					if ((request = st.nextToken()).startsWith("/"))
						request = request.substring(1);
					if (request.equals(""))
						request = request + "index.html";
					File f = new File(request);
					shipDocument(os, f);
				} else {
					os.writeBytes("400 Bad Request");
				}
				client.close();
			} catch (Exception e) {
				System.out.println("Exception: " + e.getMessage());
			}
		}

		public void shipDocument(DataOutputStream out, File f) throws Exception {
			try {
				DataInputStream in = new DataInputStream(new FileInputStream(f));
				int len = (int) f.length();
				byte[] buf = new byte[len];
				in.readFully(buf);
				in.close();
				out.writeBytes("HTTP/1.0 200 OK\r\n");
				out.writeBytes("Content-Length: " + f.length() + "\r\n");
				out.writeBytes("Content-Type: text/html\r\n\r\n");
				out.write(buf);
				out.flush();
			} catch (Exception e) {
				out.writeBytes("<html><head><title>error</title></head><body>\r\n\r\n");
				out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n");
				out.writeBytes("Content-Type: text/html\r\n\r\n");
				out.writeBytes("</body></html>");
				out.flush();
			} finally {
				out.close();
			}
		}
	}

	public static void main(String argv[]) throws Exception {
		HttpsServer https = new HttpsServer();
		https.run();
	}
}

--------------
browser
--------------

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class HttpsBrowser implements ActionListener, Runnable {
	private JFrame frame;
	private JButton go;
	private JEditorPane content;
	private JTextField url;
	private JLabel statusLine;

	public HttpsBrowser() {
		buildBrowserInterface();
	}

	private void buildBrowserInterface() {
		frame = new JFrame("HTTPS Browser");
		frame.setDefaultCloseOperation(3);

		url = new JTextField("https://localhost:8080/", 25);
		go = new JButton("Go");
		go.addActionListener(this);

		JPanel controls = new JPanel(new FlowLayout());
		controls.add(new JLabel("URL:"));
		controls.add(url);
		controls.add(go);

		content = new JEditorPane();
		content.setEditable(false);
		content.setContentType("text/html");
		content.setText("");
		statusLine = new JLabel("Initialization Complete");

		JPanel panel = new JPanel(new BorderLayout(0, 2));
		frame.setContentPane(panel);

		panel.add(controls, "North");
		panel.add(new JScrollPane(content), "Center");
		panel.add(statusLine, "South");
		frame.pack();
		frame.setBounds(100, 100, 700, 500);
		frame.setExtendedState(6);
		frame.setVisible(true);
	}

	public void actionPerformed(ActionEvent event) {
		Thread thread = new Thread(this);
		thread.start();
	}
	public void run() {
		try {
			String str = url.getText();
			URL url = new URL(str);
			readURL(url);
		} catch (IOException ioe) {
			statusLine.setText("Error: " + ioe.getMessage());
			showException(ioe);
		}
	}

	private void showException(Exception ex) {
		StringWriter trace = new StringWriter();
		ex.printStackTrace(new PrintWriter(trace));
		content.setContentType("text/html");
		content.setText("<h3>" + ex + "</h3><pre>" + trace + "</pre>");
	}

	private void readURL(URL url) throws IOException {
		statusLine.setText("Opening " + url.toExternalForm());
		URLConnection connection = url.openConnection();
		StringBuffer buffer = new StringBuffer();
		BufferedReader in = null;
		try {
			in = new BufferedReader(new InputStreamReader(connection
					.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				buffer.append(line).append('\n');
				statusLine.setText("Read " + buffer.length() + " bytes...");
			}
		} finally {
			if (in != null)
				in.close();
		}
		String type = connection.getContentType();
		if (type == null)
			type = "text/plain";
		statusLine.setText("Content type " + type);
		content.setContentType(type);
		content.setText(buffer.toString());
		statusLine.setText("Done");
	}

	public static void main(String[] args) {
		HttpsBrowser browser = new HttpsBrowser();
	}
}

---------- END SOURCE ----------
(Incident Review ID: 276708) 
======================================================================

Comments
EVALUATION This example works fine for me when I use the standard configuration. For some reason, you are not finding the SunJCE which lives in the lib/ext/sunjce_provider.jar file. Are you using a different classloader which doesn't point at the extension directory, or did you remove the SunJCE from the list of installed providers, either via Security.removeProvider or by editing the lib/security/java.security file? Make sure you have this file installed, and have the provider registered in the provider list. import java.net.*; import java.security.*; import javax.crypto.*; public class DumpProviderInfo { public static void main(String args[]) throws Exception { Provider [] provs = Security.getProviders(); for (int i = 0 ; i < provs.length; i++) { System.out.println(""); System.out.println(provs[i].getName()); System.out.println(provs[i].getInfo()); System.out.println(provs[i].getVersion()); provs[i].list(System.out); } System.out.println("=====Where did you get RSA====="); Cipher c = Cipher.getInstance("AES/CBC/NoPadding"); } } And my output was: ...deleted... =====Where did you get RSA?===== SunJCE version 1.5 I'm marking as incomplete for now, but will close soon unless more information is obtained. ###@###.### 2004-06-09 Closing because we could not get more information from webbugs. ###@###.### 2004-11-13 00:19:20 GMT
09-06-2004