JettyでSSL for Windows 〜オレオレ証明書編

tomcatapacheは普段使い慣れているのであれだが、Jettyの場合はどうなるのか紐解いてみた。簡単かと思いきや意外なところではまってしまったので備忘録として。ベースは「Jetty/Howto/Configure SSL」( http://wiki.eclipse.org/Jetty/Howto/Configure_SSL)を参考に。

  • Jetty 7.1.3
  • Java 1.6

(オレオレ)証明書とキーペアを作る

これは「Jetty/Howto/Configure SSL」に書いてある通り。jettyに付属のkeytoolを使用する。(Java付属のkeytoolではないところに注意)。で、マニュアルどおりにjettyを別名とした証明書を発行する。

>keytool -keystore keystore -alias jetty -genkey -keyalg RSA

まぁ簡単。実行するとこうなる。

C:\home\jetty-hightide-7.1.2.v20100523\etc>keytool -keystore keystore -alias jet
ty -genkey -keyalg RSA
キーストアのパスワードを入力してください:
keytool エラー: java.io.IOException: Keystore was tampered with, or password was
 incorrect

キーストアのパスワードを聞いてくる。最初これは自身で設定するものかと思いきや、キーストアのデフォのパスワードを聞いてきているらしい。でもいくら読んでも「Jetty/Howto/Configure SSL」には見当たらない。(サンプルには「password」で設定してあるがダメだった)。ググること2時間、ありました「Keystore password for Jetty 7.0 SSL configuration」(http://stackoverflow.com/questions/4690970/keystore-password-for-jetty-7-0-ssl-configuration)に。

The default password for the keystore that is shipped with jetty is storepwd.

せめて括弧とかダブルクォーテーションとかつけようぜ。結構見てたページだったけど何度もスルーしてた。ということでやってみたが・・・

C:\home\jetty-hightide-7.1.2.v20100523\etc>keytool -keystore keystore -alias jet
ty -genkey -keyalg RSA
キーストアのパスワードを入力してください:storepwd
keytool エラー: java.lang.Exception: 鍵ペアは生成されませんでした。別名 
はすでに存在します。

あるのぉ??じゃぁhogeでとりあえず。

C:\home\jetty-hightide-7.1.2.v20100523\etc>keytool -keystore keystore -alias hoge -genkey -keyalg RSA
キーストアのパスワードを入力してください:storepwd
姓名を入力してください。
  [Unknown]:  jetty.eclipse.org
組織単位名を入力してください。
  [Unknown]:  jetty
組織名を入力してください。
  [Unknown]:  jetty. Ltd.
都市名または地域名を入力してください。
  [Unknown]:  tokyo
州名または地方名を入力してください。
  [Unknown]:
この単位に該当する 2 文字の国番号を入力してください。
  [Unknown]:  JP
CN=jetty.eclipse.org, OU=jetty, O=jetty. Ltd., L=tokyo, ST=Unknown, C=JP でよろ
しいですか?
  [no]:  yes

 の鍵パスワードを入力してください。
        (キーストアのパスワードと同じ場合は RETURN を押してください):

OK、できたっぽい。じゃぁ確認。

C:\home\jetty-hightide-7.1.2.v20100523\etc>keytool -list -v -keystore keystore
キーストアのパスワードを入力してください:

キーストアのタイプ: JKS
キーストアのプロバイダ: SUN

キーストアには 2 エントリが含まれます。

別名: jetty
作成日: 2008/11/07
エントリタイプ: PrivateKeyEntry
証明連鎖の長さ: 1
証明書[1]:
所有者: CN=jetty.mortbay.org, OU=Jetty, O=Mort Bay Consulting Pty Ltd, L=Unknown
, ST=Unknown, C=Unknown
発行者: CN=jetty.mortbay.org, OU=Jetty, O=Mort Bay Consulting Pty Ltd, L=Unknown
, ST=Unknown, C=Unknown
シリアル番号: 4913c3f4
有効期間の開始日: Fri Nov 07 13:28:36 JST 2008 終了日: Tue Mar 25 13:28:36 JST 2
036
証明書のフィンガープリント:
         MD5:  59:80:DB:FA:2F:9D:5C:87:88:1B:9A:9F:BF:FA:DE:92
         SHA1: 66:62:5A:2B:2F:96:E1:88:E7:27:19:E0:0E:C6:60:B0:FC:86:B2:64
         署名アルゴリズム名: MD5withRSA
         バージョン: 1


 *******************************************
 *******************************************


別名: hoge
作成日: 2011/08/29
エントリタイプ: PrivateKeyEntry
証明連鎖の長さ: 1
証明書[1]:
所有者: CN=jetty.eclipse.org, OU=jetty, O=jetty. Ltd., L=tokyo, ST=Unknown, C=JP

発行者: CN=jetty.eclipse.org, OU=jetty, O=jetty. Ltd., L=tokyo, ST=Unknown, C=JP

シリアル番号: 4e5a8fa6
有効期間の開始日: Mon Aug 29 03:57:42 JST 2011 終了日: Sun Nov 27 03:57:42 JST 2
011
証明書のフィンガープリント:
         MD5:  91:2D:B1:61:38:7F:4A:38:08:1A:57:61:76:46:EE:17
         SHA1: 28:74:8D:52:DF:F8:E1:51:D2:78:0A:A9:B9:EA:EB:9E:35:B7:D0:CD
         署名アルゴリズム名: SHA1withRSA
         バージョン: 3


 *******************************************
 *******************************************


これの意味するところは、jettyをエイリアスとする証明書はデフォで登録されているということのようだ。それに合わせて「jetty-ssl.xml」は記述されているため、実は何もしなくてもオレオレ証明書は使える状態になっている。

jetty-ssl.xmlの用意

デフォのままでOK

jettyを起動。

jetty-ssl.xmlを読み込ませるところに注意。

2011-08-29 04:16:52.916:INFO::Started SelectChannelConnector@0.0.0.0:8080
2011-08-29 04:16:52.926:WARN::FAILED SslSelectChannelConnector@0.0.0.0:8443: jav
a.security.UnrecoverableKeyException: Cannot recover key
2011-08-29 04:16:52.929:WARN::FAILED org.eclipse.jetty.server.Server@6632060c: j
ava.security.UnrecoverableKeyException: Cannot recover key
2011-08-29 04:16:52.930:WARN::EXCEPTION
java.security.UnrecoverableKeyException: Cannot recover key
        at sun.security.provider.KeyProtector.recover(Unknown Source)
        at sun.security.provider.JavaKeyStore.engineGetKey(Unknown Source)
        at sun.security.provider.JavaKeyStore$JKS.engineGetKey(Unknown Source)
        at java.security.KeyStore.getKey(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SunX509KeyManagerImpl.(Unknown Sou
rce)
        at com.sun.net.ssl.internal.ssl.KeyManagerFactoryImpl$SunX509.engineInit

えっと、Cannot recover keyだそうで、ググってみるとパスワードが間違っているか、keystoreが壊れているかだそうで。ここでは対処は2つ。

  • しょせんキーストアはファイルなので、keystoreファイルを入れ替えて初期状態に。
  • 邪魔な証明書を消す

消すのはこんな感じで。

C:\home\jetty\etc>keytool -delete -alias hoge -keystore keystore -storepass storepwd

C:\home\jetty\etc>keytool -delete -alias jetty -keystore keystore -storepass storepwd

C:\home\jetty\etc>keytool -list -v -keystore keystore
キーストアのパスワードを入力してください:

キーストアのタイプ: JKS
キーストアのプロバイダ: SUN

キーストアには 0 エントリが含まれます。

で、もっかい証明書を作ってjettyを起動。

C:\home\jetty>java -jar start.jar etc/jetty-ssl.xml
2011-08-29 04:21:53.355:INFO::Logging to StdErrLog::DEBUG=false via org.eclipse.
jetty.util.log.StdErrLog
2011-08-29 04:21:53.572:INFO::jetty-7.1.2.v20100523
2011-08-29 04:21:53.589:INFO::Deployment monitor C:\home\jetty-hightide-7.1.2.v2
0100523\contexts at interval 5
2011-08-29 04:21:53.594:INFO::Deployable added: C:\home\jetty-hightide-7.1.2.v20
100523\contexts\hightide.xml
2011-08-29 04:21:53.623:INFO::Deployable added: C:\home\jetty-hightide-7.1.2.v20
100523\contexts\test-jndi.xml
2011-08-29 04:21:54.924:INFO::Deployable added: C:\home\jetty-hightide-7.1.2.v20
100523\contexts\javadoc.xml
2011-08-29 04:21:54.952:INFO::Deployable added: C:\home\jetty-hightide-7.1.2.v20
100523\contexts\test.xml
2011-08-29 04:21:54.977:INFO::Extract jar:file:/C:/home/jetty-hightide-7.1.2.v20
100523/webapps/test.war!/ to C:\Users\yukinkster\AppData\Local\Temp\Jetty_0_0_0_
0_8080_test.war__test__fdyupb\webapp
2011-08-29 04:21:55.546:INFO::Logging to StdErrLog::DEBUG=false via org.eclipse.
jetty.util.log.StdErrLog
2011-08-29 04:21:56.177:INFO:org.eclipse.jetty.servlets.ProxyServlet:ProxyServle
t @ /test/javadoc to http://download.eclipse.org/jetty/stable-7/apidocs
2011-08-29 04:21:56.182:INFO::Deployable added: C:\home\jetty-hightide-7.1.2.v20
100523\contexts\test-annotations.xml
2011-08-29 04:21:56.264:INFO::Deployable added: C:\home\jetty-hightide-7.1.2.v20
100523\contexts\test-jaas.xml
2011-08-29 04:21:56.297:INFO::Deployment monitor C:\home\jetty-hightide-7.1.2.v2
0100523\webapps at interval 5
2011-08-29 04:21:56.301:INFO::Deployable added: C:\home\jetty-hightide-7.1.2.v20
100523\webapps\cometd.war
2011-08-29 04:21:56.317:INFO::Copying WEB-INF/lib jar:file:/C:/home/jetty-highti
de-7.1.2.v20100523/webapps/cometd.war!/WEB-INF/lib/ to C:\Users\yukinkster\AppDa
ta\Local\Temp\Jetty_0_0_0_0_8080_cometd.war__cometd__.t2qfkl\webinf\WEB-INF\lib
2011-08-29 04:21:56.511:INFO::Copying WEB-INF/classes from jar:file:/C:/home/jet
ty-hightide-7.1.2.v20100523/webapps/cometd.war!/WEB-INF/classes/ to C:\Users\yuk
inkster\AppData\Local\Temp\Jetty_0_0_0_0_8080_cometd.war__cometd__.t2qfkl\webinf
\WEB-INF\classes
2011-08-29 04:21:57.207:INFO::Logging to StdErrLog::DEBUG=false via org.eclipse.
jetty.util.log.StdErrLog
2011-08-29 04:21:57.269:INFO:/cometd:Configuring cometd java demo null null
2011-08-29 04:21:57.285:INFO:/cometd:TimesyncExtension null null
2011-08-29 04:21:57.301:INFO:/cometd:AcknowledgedMessagesExtension null null
INIT org.eclipse.jetty.servlet.ServletHolder$Config@16ea7549
2011-08-29 04:21:57.363:INFO::Deployable added: C:\home\jetty-hightide-7.1.2.v20
100523\webapps\async-rest
2011-08-29 04:21:57.425:INFO::Deployable added: C:\home\jetty-hightide-7.1.2.v20
100523\webapps\root
2011-08-29 04:21:57.472:INFO::Started SelectChannelConnector@0.0.0.0:8080
2011-08-29 04:21:57.490:INFO::Started SslSelectChannelConnector@0.0.0.0:8443
2011-08-29 04:22:57.697:INFO::org.eclipse.jetty.io.nio.SelectorManager$SelectSet
@b278874 JVM BUG(s) - injecting delay1 times

「2011-08-29 04:21:57.490:INFO::Started SslSelectChannelConnector@0.0.0.0:8443」となっているのでちゃんと起動しているようだ。実際に、https://localhost:8443/でアクセスできる。(オレオレ証明書なので証明書を信頼できない旨の警告は出るがかまわず進めばページは表示される。)

パスワードを隠す

設定ファイルにパスワードをベタで書くのはまずいのでMD5とかでちょちょっと思ったら、jetty-ssl.xmlにはOBF形式で書かれていた。「obfuscated」らしいが、これもjettyのutilでできるようだ。(http://docs.codehaus.org/display/JETTY/Securing+Passwords

  • jetty-core-6.1.14.jarをダウンロード
  • org.mortbay.jetty.security.Passwordを使ってOBF形式にする
C:\home\jetty\lib>java -cp jetty-util-7.1.2.v20100523.jar;jetty-core-6.1.14.jar org.mortbay.jetty.security.Password password
password
OBF:1v2j1uum1xtv1zej1zer1xtn1uvk1v1v
Exception in thread "main" java.lang.NoClassDefFoundError: org/mortbay/util/Stri
ngUtil
        at org.mortbay.jetty.security.Credential$MD5.digest(Credential.java:195)

        at org.mortbay.jetty.security.Password.main(Password.java:227)
Caused by: java.lang.ClassNotFoundException: org.mortbay.util.StringUtil
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)
        ... 2 more

どうやら予定では、 clear text, obfuscated, md5, encryptedの4つが出力される予定だったが、clear text, obfuscatedを出力した後で、MD5で変換クラスがなかったようでエラー・・・まぁobfuscatedが欲しかったのでそこは無視。

passwordのOBFは「1v2j1uum1xtv1zej1zer1xtn1uvk1v1v」ということで。

jetty-sslの修正

証明書を作るとき、パスワードをデフォルトと変更して入力した場合はjetty-sslも変更しなくてはならない。

  
    
      
	8443
	30000
        2
        100
	/etc/keystore
	OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4 ←これはキーストアのパスワードなので変更しない
	OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4 ←ここを変更する
        /etc/keystore
        OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4 ←これ何だろ。
      
    
  

portを変更

8443で動作するが、apacheで連携しているみたいにURLにportをなくしてアクセスするようにしておきたい。まぁ80ポートで。この辺りに情報はありそうなので今度調べる。

Apacheは必要か

どうやらJettyはwebサーバ機能はtomcatよりも色々持っているようなので特にapacheと連携する必要はないように思われる。まぁ80ポート化が上手くいかなかったら手っ取り早いのはapacheと連携だけど。。。

keystoreのパスワードの変更

>keytool -storepasswd -keystore keystore
キーストアのパスワードを入力してください:
新規 keystore password:
新規 keystore password を再入力してください: