-
Bug
-
Resolution: Fixed
-
P3
-
6, 6u20, 6u21
-
b142
-
generic, x86
-
generic, windows_xp
-
Not verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2203040 | 6u27 | Miroslaw Niemiec | P2 | Resolved | Fixed | b02 |
A DESCRIPTION OF THE REQUEST :
Requesting support for doing raw RSA signing with SunMSCAPI - at present only SHA-1, MD5 and MD2 signing is possible.
This would include the SunMSCAPI provider having the following property or similar:
Signature.NONEwithRSA=sun.security.mscapi.RSASignature$NONE
Alternatively, the SunMSCAPI cipher class could be changed to support encrypting with private keys, although i suspect that the underlying MSCAPI doesn't allow that.
JUSTIFICATION :
NONEwithRSA Signing is required by JSSE for client authentication enabled SSL. At the moment because SunMSCAPI doesn't include a NONEwithRSA property, the default NONEwithRSA signature class is being used. This class merely wraps the cipher class - and the MSCAPI cipher class doesn't support encrypting with private keys. A "Bad Key" exception results.
See: http://forum.java.sun.com/thread.jspa?threadID=5188515&tstart=0
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
After setting a client application to use the Windows key and trust stores in the normal manner, and given that the server and client trust each other's certificates, using JSSE to connect to a server using SSL with client authentication should work.
ACTUAL -
The following error is thrown during the client verification stage, on the client end:
Exception in thread "main" javax.net.ssl.SSLException: java.security.ProviderException: java.security.KeyException: Bad Key.
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1520)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1487)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1470)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1396)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:64)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:276)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:122)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:212)
at SunMSCAPITest.main(SunMSCAPITest.java:37)
Caused by: java.security.ProviderException: java.security.KeyException: Bad Key.
at sun.security.mscapi.RSACipher.doFinal(RSACipher.java:242)
at sun.security.mscapi.RSACipher.engineDoFinal(RSACipher.java:266)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at java.security.Signature$CipherAdapter.engineSign(Signature.java:1225)
at java.security.Signature$Delegate.engineSign(Signature.java:1128)
at java.security.Signature.sign(Signature.java:522)
at com.sun.net.ssl.internal.ssl.RSASignature.engineSign(RSASignature.java:149)
at java.security.Signature$Delegate.engineSign(Signature.java:1128)
at java.security.Signature.sign(Signature.java:522)
at com.sun.net.ssl.internal.ssl.HandshakeMessage$CertificateVerify.<init>(HandshakeMessage.java:1216)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:715)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:197)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:511)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:449)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:817)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1029)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:621)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
... 6 more
Caused by: java.security.KeyException: Bad Key.
at sun.security.mscapi.RSACipher.encryptDecrypt(Native Method)
at sun.security.mscapi.RSACipher.doFinal(RSACipher.java:222)
... 23 more
---------- BEGIN SOURCE ----------
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import javax.net.ssl.SSLSocketFactory;
public class SunMSCAPITest {
// Website to access
public static final String TARGET_HTTPS_SERVER = "localhost";
public static final int TARGET_HTTPS_PORT = 8443;
public static void main(String[] args) throws Exception {
System.setProperty("javax.net.ssl.keyStoreProvider","SunMSCAPI");
System.setProperty("javax.net.ssl.keyStoreType","Windows-MY");
System.setProperty("javax.net.ssl.trustStoreProvider","SunMSCAPI");
System.setProperty("javax.net.ssl.trustStoreType","Windows-ROOT");
Socket socket = SSLSocketFactory.getDefault().createSocket(TARGET_HTTPS_SERVER,
TARGET_HTTPS_PORT);
try {
Writer out = new OutputStreamWriter(socket.getOutputStream(),
"ISO-8859-1");
out.write("GET / HTTP/1.1\r\n");
out.write("Host: " + TARGET_HTTPS_SERVER + ":" + TARGET_HTTPS_PORT
+ "\r\n");
out.write("Agent: SSL-TEST\r\n");
out.write("\r\n");
out.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(socket
.getInputStream(), "ISO-8859-1"));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} finally {
socket.close();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
At the moment this can be worked around by setting both the client and server applications to use one of the other signature types instead of NONEwithRSA:
i.e.
Provider p = Security.getProvider("SunMSCAPI");
p.setProperty("Signature.NONEwithRSA","sun.security.mscapi.RSASignature$SHA1");
This isn't always possible to do on the server end though, and breaks SSL compatibility.
Requesting support for doing raw RSA signing with SunMSCAPI - at present only SHA-1, MD5 and MD2 signing is possible.
This would include the SunMSCAPI provider having the following property or similar:
Signature.NONEwithRSA=sun.security.mscapi.RSASignature$NONE
Alternatively, the SunMSCAPI cipher class could be changed to support encrypting with private keys, although i suspect that the underlying MSCAPI doesn't allow that.
JUSTIFICATION :
NONEwithRSA Signing is required by JSSE for client authentication enabled SSL. At the moment because SunMSCAPI doesn't include a NONEwithRSA property, the default NONEwithRSA signature class is being used. This class merely wraps the cipher class - and the MSCAPI cipher class doesn't support encrypting with private keys. A "Bad Key" exception results.
See: http://forum.java.sun.com/thread.jspa?threadID=5188515&tstart=0
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
After setting a client application to use the Windows key and trust stores in the normal manner, and given that the server and client trust each other's certificates, using JSSE to connect to a server using SSL with client authentication should work.
ACTUAL -
The following error is thrown during the client verification stage, on the client end:
Exception in thread "main" javax.net.ssl.SSLException: java.security.ProviderException: java.security.KeyException: Bad Key.
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1520)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1487)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1470)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1396)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:64)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:276)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:122)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:212)
at SunMSCAPITest.main(SunMSCAPITest.java:37)
Caused by: java.security.ProviderException: java.security.KeyException: Bad Key.
at sun.security.mscapi.RSACipher.doFinal(RSACipher.java:242)
at sun.security.mscapi.RSACipher.engineDoFinal(RSACipher.java:266)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at java.security.Signature$CipherAdapter.engineSign(Signature.java:1225)
at java.security.Signature$Delegate.engineSign(Signature.java:1128)
at java.security.Signature.sign(Signature.java:522)
at com.sun.net.ssl.internal.ssl.RSASignature.engineSign(RSASignature.java:149)
at java.security.Signature$Delegate.engineSign(Signature.java:1128)
at java.security.Signature.sign(Signature.java:522)
at com.sun.net.ssl.internal.ssl.HandshakeMessage$CertificateVerify.<init>(HandshakeMessage.java:1216)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:715)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:197)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:511)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:449)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:817)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1029)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:621)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
... 6 more
Caused by: java.security.KeyException: Bad Key.
at sun.security.mscapi.RSACipher.encryptDecrypt(Native Method)
at sun.security.mscapi.RSACipher.doFinal(RSACipher.java:222)
... 23 more
---------- BEGIN SOURCE ----------
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import javax.net.ssl.SSLSocketFactory;
public class SunMSCAPITest {
// Website to access
public static final String TARGET_HTTPS_SERVER = "localhost";
public static final int TARGET_HTTPS_PORT = 8443;
public static void main(String[] args) throws Exception {
System.setProperty("javax.net.ssl.keyStoreProvider","SunMSCAPI");
System.setProperty("javax.net.ssl.keyStoreType","Windows-MY");
System.setProperty("javax.net.ssl.trustStoreProvider","SunMSCAPI");
System.setProperty("javax.net.ssl.trustStoreType","Windows-ROOT");
Socket socket = SSLSocketFactory.getDefault().createSocket(TARGET_HTTPS_SERVER,
TARGET_HTTPS_PORT);
try {
Writer out = new OutputStreamWriter(socket.getOutputStream(),
"ISO-8859-1");
out.write("GET / HTTP/1.1\r\n");
out.write("Host: " + TARGET_HTTPS_SERVER + ":" + TARGET_HTTPS_PORT
+ "\r\n");
out.write("Agent: SSL-TEST\r\n");
out.write("\r\n");
out.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(socket
.getInputStream(), "ISO-8859-1"));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} finally {
socket.close();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
At the moment this can be worked around by setting both the client and server applications to use one of the other signature types instead of NONEwithRSA:
i.e.
Provider p = Security.getProvider("SunMSCAPI");
p.setProperty("Signature.NONEwithRSA","sun.security.mscapi.RSASignature$SHA1");
This isn't always possible to do on the server end though, and breaks SSL compatibility.
- backported by
-
JDK-2203040 Request for raw RSA (NONEwithRSA) Signature support in SunMSCAPI
- Resolved
- duplicates
-
JDK-6458768 Signature.getInstance("NONEwithRSA") giving inconsistent behavior
- Closed
- relates to
-
JDK-7054708 More fix of 6578658.
- Closed
-
JDK-8149344 Application doesn't work with Java 8U45 using smartcard
- Closed
-
JDK-7050158 Cipher in plain RSA signing treats private keys as public
- Closed