JDK-8158633 : BASE64 encoded cert not correctly parsed with UTF-16
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.crypto
  • Affected Version: 8u76
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2016-06-02
  • Updated: 2018-02-15
  • Resolved: 2016-06-17
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u162Fixed 9 b124Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b04, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
windows 10 64

A DESCRIPTION OF THE PROBLEM :
simple connect https website,it could not work when use utf-16 in source file

REGRESSION.  Last worked in version 8u74

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
public class Test {
	public static void main(String[] args) throws Exception {
		URLConnection openConnection = new URL("https://www.google.com").openConnection();
		openConnection.connect();		
	}
}


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
simple code above,if save as utf-8,it runs ok,if save as utf-16,it crash
ACTUAL -
report error

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.ExceptionInInitializerError
	at javax.crypto.JceSecurity.loadPolicies(JceSecurity.java:317)
	at javax.crypto.JceSecurity.setupJurisdictionPolicies(JceSecurity.java:262)
	at javax.crypto.JceSecurity.access$000(JceSecurity.java:48)
	at javax.crypto.JceSecurity$1.run(JceSecurity.java:80)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.crypto.JceSecurity.<clinit>(JceSecurity.java:77)
	at javax.crypto.JceSecurityManager.<clinit>(JceSecurityManager.java:65)
	at javax.crypto.Cipher.getConfiguredPermission(Cipher.java:2587)
	at javax.crypto.Cipher.getMaxAllowedKeyLength(Cipher.java:2611)
	at sun.security.ssl.CipherSuite$BulkCipher.isAvailable(CipherSuite.java:548)
	at sun.security.ssl.CipherSuite$BulkCipher.isAvailable(CipherSuite.java:527)
	at sun.security.ssl.CipherSuite.isAvailable(CipherSuite.java:194)
	at sun.security.ssl.SSLContextImpl.getApplicableCipherSuiteList(SSLContextImpl.java:346)
	at sun.security.ssl.SSLContextImpl.getDefaultCipherSuiteList(SSLContextImpl.java:304)
	at sun.security.ssl.SSLSocketImpl.init(SSLSocketImpl.java:626)
	at sun.security.ssl.SSLSocketImpl.<init>(SSLSocketImpl.java:537)
	at sun.security.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:72)
	at sun.net.www.protocol.https.HttpsClient.createSocket(HttpsClient.java:405)
	at sun.net.NetworkClient.doConnect(NetworkClient.java:162)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)
	at sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:264)
	at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:367)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:191)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1105)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:999)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:177)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
	at Test.main(Test.java:7)
Caused by: java.lang.SecurityException: Framework jar verification can not be initialized
	at javax.crypto.JarVerifier.<clinit>(JarVerifier.java:192)
	... 29 more
Caused by: java.security.PrivilegedActionException: java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: java.lang.IllegalArgumentException: Illegal base64 character -2
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.crypto.JarVerifier.<clinit>(JarVerifier.java:151)
	... 29 more
Caused by: java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: java.lang.IllegalArgumentException: Illegal base64 character -2
	at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:110)
	at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)
	at javax.crypto.JarVerifier.parseCertificate(JarVerifier.java:206)
	at javax.crypto.JarVerifier.access$100(JarVerifier.java:37)
	at javax.crypto.JarVerifier$1.run(JarVerifier.java:158)
	at javax.crypto.JarVerifier$1.run(JarVerifier.java:152)
	... 31 more
Caused by: java.io.IOException: java.lang.IllegalArgumentException: Illegal base64 character -2
	at sun.security.util.Pem.decode(Pem.java:49)
	at sun.security.provider.X509Factory.readOneBlock(X509Factory.java:638)
	at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:96)
	... 36 more
Caused by: java.lang.IllegalArgumentException: Illegal base64 character -2
	at java.util.Base64$Decoder.decode0(Base64.java:714)
	at java.util.Base64$Decoder.decode(Base64.java:526)
	at sun.security.util.Pem.decode(Pem.java:47)
	... 38 more

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class Test {
	public static void main(String[] args) throws Exception {
		URLConnection openConnection = new URL("https://www.google.com").openConnection();
		openConnection.connect();		
	}
}
---------- END SOURCE ----------


Comments
Reproducible now. Fix found. The bug reporter is using UTF-16 as the default charset and new String(byte[]) reads ASCII bytes as double-byte chars.
17-06-2016

This bug originates in JCE code in a String Certificate that hasn't changed in while. Digging down, it appears that this *MIGHT* be related to a PEM/Base64 for parsing certificates that went into 8u76. JDK-8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness, as jdk7 did -java.util.Base64.getMimeDecoder().decode(new String(data, 0, pos)); === +return Pem.decode(new String(data, 0, pos)); Note: Pallavi/I were not able to duplicate this from the command line, but Pallavi was able to get it to duplicate when using Eclipse. I have not contacted submitter, but this looks sufficiently suspicious for further investigation. The JCE JarVerifier that contains the Certificate String is in the closed repo:
08-06-2016

I'm still not understanding the root of this problem, and why it's been marked as resolved. This stacktrace doesn't match 8u76 at all, open or closed. Did someone insert an older version of jce.jar?
07-06-2016

Checked again and realized that I had reproduced the issue in Eclipse, on command line it doesn't throw this error.
06-06-2016

This is very surprising. I had no problems running this on Windows using 8u91, or Solaris/sparc using 8u74, 77, 91, 92. Please provide additional information about how to reproduce this issue: % javac -version javac 1.8.0_91 %java -version java version "1.8.0_91" Java(TM) SE Runtime Environment (build 1.8.0_91-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode) % file JI9039020.java JI9039020.java: C source, Big-endian UTF-16 Unicode text, with CRLF line terminators % javac -encoding utf16 JI9039020.java % java -Djavax.net.debug=all -Dhttps.proxyHost=<internal-proxy> -Dhttps.proxyPort=80 JI9039020 ...complete handshake deleted... main, READ: TLSv1.2 Handshake, length = 40 Padded plaintext after DECRYPTION: len = 16 0000: 14 00 00 0C EE A4 D0 99 FF EC C9 57 C1 FE A3 61 ...........W...a *** Finished verify_data: { 238, 164, 208, 153, 255, 236, 201, 87, 193, 254, 163, 97 } *** %% Cached client session: [Session-1, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256] [read] MD5 and SHA1 hashes: len = 16 0000: 14 00 00 0C EE A4 D0 99 FF EC C9 57 C1 FE A3 61 ...........W...a %
03-06-2016

Looks like a security problem with initializing crypto provider.
03-06-2016

Attached test case executed on : JDK 8u74 - Pass JDK 8u76 - Fail JDK 8u92- Fail JDK 9 - Pass
03-06-2016