LoginSignup
1
1

More than 5 years have passed since last update.

古めのJerseyClient&Oracle JDK1.6でBouncyCastleを使いTLS1.2接続

Posted at

はじめに

JDK1.6で動いている環境から社内のシステムにTLS1.2で接続する必要があり、いろいろと調べた結果BouncyCastleを使うしか方法がなく、なんとか接続できたので記録として残しておきます。
社で使用しているJDKはIBM JDK1.6のため、まだサポートがありTLS1.2接続も可能でした。しかし、接続先が許可しているCipherと一致するものが存在せず、BouncyCastleに頼ることにしました。

こちらの記事は自宅で確認したため、Oracle JDKを使用しています。
ちなみにOracleについてもhttps://www.oracle.com/technetwork/java/javase/overview-156328.html#R160_121に記載があるように商用サポートを受ければTLS1.2が使えるバージョンが入手可能のようです。ただし、Cipher Suitesがどうなっているかは要確認です。

動作確認環境

OS:Window 10
Oracle JDK: Version 1.6.0_45
Java Library:
bcprov-jdk15on-160.jar
bctls-jdk15on-160.jar
jersey-client-1.8.jar
jersey-core-1.8.jar
json-20131018.jar

1. Bouncy Castleの設定

%JAVA_HOME%\jre\lib\security\java.securityに
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
を追加します。

#
# List of providers and their preference orders (see above):
#
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=com.sun.net.ssl.internal.ssl.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider
security.provider.6=com.sun.security.sasl.Provider
security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.8=sun.security.smartcardio.SunPCSC
security.provider.9=sun.security.mscapi.SunMSCAPI
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider

2. ソースコード準備

BCtest.java
package tlsclient.tworks55;

import java.security.Security;

public class BCtest {

    public static void main(String[] args) {
        // BC is the ID for the Bouncy Castle provider;
        if (Security.getProvider("BC") == null) {
            System.out.println("Bouncy Castle provider is NOT available");
        } else {
            System.out.println("Bouncy Castle provider is available");
        }
    }

}
TLSJerseyClientTest.java
package tlsclient.tworks55;

import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
import org.json.JSONObject;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.urlconnection.HTTPSProperties;

import java.security.Provider;
import java.security.Security;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.ws.rs.core.MediaType;

public class TLSJerseyClientTest {
    public static void main(String[] args) {
        try {
            TrustManager[] trustAllCerts = { new InsecureTrustManager() };
            HostnameVerifier hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
            ClientConfig config = new DefaultClientConfig();

            Provider provider = new BouncyCastleJsseProvider();
            Security.addProvider(provider);
            SSLContext ctx = SSLContext.getInstance("TLSv1.2", provider.getName());

            ctx.init(null, trustAllCerts, null);

            config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
                    new HTTPSProperties(hostnameVerifier, ctx));
            Client c = Client.create(config);
            WebResource resource = c.resource("https://github.com/login/oauth/access_token");

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("client_id", "*** Set client_id here ***");
            jsonObject.put("client_secret", "*** Set client_secret here ***");
            jsonObject.put("code", "*** Set code here ***");
            String response = resource.type(MediaType.APPLICATION_JSON_TYPE).post(String.class, jsonObject.toString());

            System.out.println(response);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
InsecureTrustManager.java
package tlsclient.tworks55;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;

public class InsecureTrustManager implements X509TrustManager {
    /**
     * {@inheritDoc}
     */
    public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
        // Everyone is trusted!
    }

    /**
     * {@inheritDoc}
     */
    public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
        // Everyone is trusted!
    }

    /**
     * {@inheritDoc}
     */
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}

※Githubはこちら

3. Bouncy Castleが読めているか確認

BCtest.javaを実行し"Bouncy Castle provider is available"が表示されることを確認します。

Bouncy Castle provider is available

Not Availableになった場合は、設定がうまくいっていません。

4. TLSv1.2でサイトに接続

上記ソースコードは、GithubithubにAuthorizing OAuth Appsの設定をした上で、OAuth Tokenを取得する部分を試す感じになっています。
GithubのOauth Appsはhttps://github.com/settings/applications/newで作成可能です。
client_id及びclient_secretは、アプリ作成時にサイトに表示されますが、codeについては動的に生成する必要があります。

ブラウザで以下のようにClient_idをセットするとcallback URLに対してcodeがパラメーターとして渡されます。
https://github.com/login/oauth/authorize?client_id=[Set Client id here]

Callback URLをLocalhostなどにしておけば、ブラウザ上に
http://localhost:5555/?code=d86cabc30fdabc6abcb8
といった形で表示されますので、これをメモしておきます。

TLSJerseyClientTest.javaの以下にそれぞれパラメーターをセットして、実行します。

jsonObject.put("client_id", "*** Set client_id here ***");
jsonObject.put("client_secret", "*** Set client_secret here ***");
jsonObject.put("code", "*** Set code here ***");

うまく行けば、以下のような結果が得られます。

access_token=abc4cf0fda71e2abc358c22fba7abc8aabc56abc&scope=&token_type=bearer

5. java.security.InvalidKeyException: Illegal key size が発生する場合の対応

接続先の状況によるものだと思いますが、InvalidKeyExceptionが発生するケースがあるようです。
その際はjce_policy-6をダウンロードし、以下にライブラリをコピーすると動作するようです。

%JAVA_HOME%\jre\lib\security
local_policy.jar
US_export_policy.jar

以下、InvalidKeyException発生例:

2019/01/26 23:06:46 org.bouncycastle.jsse.provider.ProvTlsClient notifyAlertRaised
警告: Client raised fatal(2) internal_error(80) alert: Failed to read record
java.lang.RuntimeException: java.security.InvalidKeyException: Illegal key size
    at org.bouncycastle.tls.crypto.impl.jcajce.JceChaCha20Poly1305.init(Unknown Source)
    at org.bouncycastle.tls.crypto.impl.TlsAEADCipher.<init>(Unknown Source)
    at org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto.createChaCha20Poly1305(Unknown Source)
    at org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto.createCipher(Unknown Source)
    at org.bouncycastle.tls.crypto.impl.AbstractTlsSecret.createCipher(Unknown Source)
    at org.bouncycastle.tls.AbstractTlsClient.getCipher(Unknown Source)
    at org.bouncycastle.tls.TlsClientProtocol.handleHandshakeMessage(Unknown Source)
    at org.bouncycastle.tls.TlsProtocol.processHandshakeQueue(Unknown Source)
    at org.bouncycastle.tls.TlsProtocol.processRecord(Unknown Source)
    at org.bouncycastle.tls.RecordStream.readRecord(Unknown Source)
    at org.bouncycastle.tls.TlsProtocol.safeReadRecord(Unknown Source)
    at org.bouncycastle.tls.TlsProtocol.blockForHandshake(Unknown Source)
    at org.bouncycastle.tls.TlsClientProtocol.connect(Unknown Source)
    at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1031)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler$1$1.getOutputStream(URLConnectionClientHandler.java:225)
    at com.sun.jersey.api.client.CommittingOutputStream.commitWrite(CommittingOutputStream.java:117)
    at com.sun.jersey.api.client.CommittingOutputStream.write(CommittingOutputStream.java:89)
    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 java.io.BufferedWriter.flush(BufferedWriter.java:236)
    at com.sun.jersey.core.util.ReaderWriter.writeToAsString(ReaderWriter.java:191)
    at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:128)
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:88)
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:58)
    at com.sun.jersey.api.client.RequestWriter.writeRequestEntity(RequestWriter.java:300)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:204)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:147)
    at com.sun.jersey.api.client.Client.handle(Client.java:648)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:670)
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:563)
    at tlsclient.tworks55.TLSJerseyClientTest.main(TLSJerseyClientTest.java:42)
Caused by: java.security.InvalidKeyException: Illegal key size
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    ... 39 more
com.sun.jersey.api.client.ClientHandlerException: org.bouncycastle.tls.TlsFatalAlert: internal_error(80)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:149)
    at com.sun.jersey.api.client.Client.handle(Client.java:648)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:670)
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:563)
    at tlsclient.tworks55.TLSJerseyClientTest.main(TLSJerseyClientTest.java:42)
Caused by: org.bouncycastle.tls.TlsFatalAlert: internal_error(80)
    at org.bouncycastle.tls.TlsProtocol.safeReadRecord(Unknown Source)
    at org.bouncycastle.tls.TlsProtocol.blockForHandshake(Unknown Source)
    at org.bouncycastle.tls.TlsClientProtocol.connect(Unknown Source)
    at org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1031)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler$1$1.getOutputStream(URLConnectionClientHandler.java:225)
    at com.sun.jersey.api.client.CommittingOutputStream.commitWrite(CommittingOutputStream.java:117)
    at com.sun.jersey.api.client.CommittingOutputStream.write(CommittingOutputStream.java:89)
    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 java.io.BufferedWriter.flush(BufferedWriter.java:236)
    at com.sun.jersey.core.util.ReaderWriter.writeToAsString(ReaderWriter.java:191)
    at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:128)
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:88)
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:58)
    at com.sun.jersey.api.client.RequestWriter.writeRequestEntity(RequestWriter.java:300)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:204)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:147)
    ... 5 more
Caused by: java.lang.RuntimeException: java.security.InvalidKeyException: Illegal key size
    at org.bouncycastle.tls.crypto.impl.jcajce.JceChaCha20Poly1305.init(Unknown Source)
    at org.bouncycastle.tls.crypto.impl.TlsAEADCipher.<init>(Unknown Source)
    at org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto.createChaCha20Poly1305(Unknown Source)
    at org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto.createCipher(Unknown Source)
    at org.bouncycastle.tls.crypto.impl.AbstractTlsSecret.createCipher(Unknown Source)
    at org.bouncycastle.tls.AbstractTlsClient.getCipher(Unknown Source)
    at org.bouncycastle.tls.TlsClientProtocol.handleHandshakeMessage(Unknown Source)
    at org.bouncycastle.tls.TlsProtocol.processHandshakeQueue(Unknown Source)
    at org.bouncycastle.tls.TlsProtocol.processRecord(Unknown Source)
    at org.bouncycastle.tls.RecordStream.readRecord(Unknown Source)
    ... 29 more
Caused by: java.security.InvalidKeyException: Illegal key size
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    ... 39 more

参考URL

https://www.bouncycastle.org/
http://www.bouncycastle.org/wiki/display/JA1/Frequently+Asked+Questions#FrequentlyAskedQuestions-1.WhydoIget%22java.lang.SecurityException:Unsupportedkeysizeoralgorithmparameters%22or%22java.security.InvalidKeyException:Illegalkeysize%22whenItryusingtheBouncyCastleProvider?
http://tech-son.hatenablog.jp/entry/2017/11/01/003000
https://stackoverflow.com/questions/33364100/how-to-use-tls-1-2-in-java-6
https://stackoverflow.com/questions/6363801/invalidkeyexception-illegal-key-size-java-code-throwing-exception-for-encryp?rq=1
https://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1