Windows10にしたらJBossでSQL Serverに繋がらなくなった件

久しぶりに技術系エントリ

仕事でJBoss6AS + Java6 + SQL ServerなシステムをWin7マシンで作ってて、それはちゃんと動いてて納品したのが1年前。
で、今年に入ってWin7マシンをWin10にアップグレードしたのね。
で、また仕事で上記のJBossのシステムの機能追加案件が来たので起動してみたら、DBの接続辺りで下記のような例外が出てた。

WARN  [org.jboss.resource.connectionmanager.JBossManagedConnectionPool] Throwable while attempting to get a new connection: null: org.jboss.resource.JBossResourceException: Could not create connection; - nested throwable: (com.microsoft.sqlserver.jdbc.SQLServerException: ドライバーが SSL (Secure Sockets Layer) 暗号化による SQL Server への安全な接続を確立できませんでした。エラー: "java.lang.RuntimeException: Could not generate DH keypair"。 ClientConnectionId:806f4f33-0e99-431b-8aa1-307314d64b11)
	at org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory.getLocalManagedConnection(LocalManagedConnectionFactory.java:261) [:6.1.0.Final]
	at org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory.createManagedConnection(LocalManagedConnectionFactory.java:215) [:6.1.0.Final]
	at org.jboss.resource.connectionmanager.InternalManagedConnectionPool.createConnectionEventListener(InternalManagedConnectionPool.java:648) [:6.1.0.Final]
	at org.jboss.resource.connectionmanager.InternalManagedConnectionPool.getConnection(InternalManagedConnectionPool.java:272) [:6.1.0.Final]
	at org.jboss.resource.connectionmanager.JBossManagedConnectionPool$BasePool.getConnection(JBossManagedConnectionPool.java:690) [:6.1.0.Final]
	at org.jboss.resource.connectionmanager.BaseConnectionManager2.getManagedConnection(BaseConnectionManager2.java:403) [:6.1.0.Final]
	at org.jboss.resource.connectionmanager.TxConnectionManager.getManagedConnection(TxConnectionManager.java:414) [:6.1.0.Final]
	at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:496) [:6.1.0.Final]
	at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:941) [:6.1.0.Final]
	at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89) [:6.1.0.Final]
	(略)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: ドライバーが SSL (Secure Sockets Layer) 暗号化による SQL Server への安全な接続を確立できませんでした。エラー: "java.lang.RuntimeException: Could not generate DH keypair"。 ClientConnectionId:806f4f33-0e99-431b-8aa1-307314d64b11
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1667) [:]
	at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1668) [:]
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1323) [:]
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:991) [:]
	at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:827) [:]
	at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1012) [:]
	at org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory.getLocalManagedConnection(LocalManagedConnectionFactory.java:229) [:6.1.0.Final]
	... 36 more
Caused by: javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190) [:1.6]
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1731) [:1.6]
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1692) [:1.6]
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1675) [:1.6]
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1204) [:1.6]
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181) [:1.6]
	at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1618) [:]
	... 41 more
Caused by: java.lang.RuntimeException: Could not generate DH keypair
	at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:106) [:1.6]
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:556) [:1.6]
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:183) [:1.6]
	at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593) [:1.6]
	at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529) [:1.6]
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:925) [:1.6]
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170) [:1.6]
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197) [:1.6]
	... 43 more
Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
	at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..) [sunjce_provider.jar:1.6]
	at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627) [:1.6.0_31]
	at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:100) [:1.6]
	... 50 more

どうやらSQLサーバとJDBCドライバ間でSSL通信していて、そのSSLで使うDiffie-Hellman アルゴリズムの素数がJava8未満だと1024bitを超える素数は使えないらしく、Win10だと勝手に1024bit超の素数を使おうとしちゃってエラーになってるみたい。
参考:http://tt4cs.blogspot.jp/2014/04/sunjce-diffie-hellman-only-accepts-1024-bits-or-shorter.html
Java8なら問題無いみたい。

で、今回の対象のJBoss6ASはJRE6じゃないと(5でも行ける?)動かないので、Javaのバージョン上げるのは無し。
JRE7でもダメっぽいね。

ググっても日本語サイトでは解決方法が見当たらなかったのね。
仕方ないからGoogle先生に翻訳してもらいながら海外サイトを探したら見つかった。

http://stackoverflow.com/questions/32230342/getting-could-not-generate-dh-keypair-exception
ここのAnswerに解決方法が書かれていたので引用します。

  • download bcprov-jdk15on-$version.jar from http://www.bouncycastle.org/latest_releases.html and put it in your JRE/lib/ext
  • edit JRE/lib/security/java.security to add to the list of providers a line like security.provider.N=org.bouncycastle.jce.provider.BouncyCastleProvider where N is the next available number.

    日本語で手順を書くと

    • まずhttp://www.bouncycastle.org/latest_releases.htmlから、bcprov-jdk15on-$version.jarをダウンロードする。
      ($versionはこのjarのバージョン番号。現時点(2016/11/02)では115)
    • bcprov-jdk15on-$version.jarを対象JREのJRE/lib/extに配置する。
    • 対象JREのJRE/lib/security/java.securityをテキストエディタで開いて、”security.provider.<JREのバージョン>”で検索する。
      Java6ならsecurity.provider.6
      多分50行目付近で見つかると思う。
    • 見つかった行の先頭を#でコメントアウトして、代わりに
      security.provider.<JREのバージョン>=org.bouncycastle.jce.provider.BouncyCastleProvider
      を追加する。

    これで動くようになりましたとさ。

    Javaのこういうところも嫌いだ。

    コメントを残す

    メールアドレスが公開されることはありません。 が付いている欄は必須項目です

    認証のために問題を解いて下さい * Time limit is exhausted. Please reload CAPTCHA.