事象
OpenSSLで作成した秘密鍵をJava(Eclipse + Maven環境)で読み込み、公開鍵で暗号化されたデータを復号しようとした際に例外が発生しました。
秘密鍵ファイルは以下のように作成しています。
// 秘密鍵作成
$ openssl genrsa -out rsa_2048_priv.pem 2048
// 秘密鍵をPEMからPKCS#8のDERフォーマットに変換
$ openssl pkcs8 -in rsa_2048_priv.pem -topk8 -nocrypt -outform DER -out rsa_2048_priv.der
クラスパス直下(Maven的にはsrc/main/resources)に秘密鍵ファイル(rsa_2048_priv.der)を置いておき、ClassLoader.getResourceAsStream()で読み込んでPrivateKeyインスタンスを作ります。
// 鍵ファイル内容のバイト配列を作成
InputStream in =
this.getClass().getClassLoader().getResourceAsStream("rsa_2048_priv.der");
byte[] buff = new byte[in.available()];
in.read(buff);
// 秘密鍵インスタンス生成
KeySpec keyspec = new PKCS8EncodedKeySpec(buff); <-- 以下のエラーが発生する
KeyFactory keyfactory = KeyFactory.getInstance( "RSA");
Key privateKey = keyfactory.generatePrivate(keyspec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
すると例外が発生。
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=111, too big.
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217)
at java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
(snip)
原因
原因究明の為、試しにsrc/main/resourcesに置いた鍵ファイルを実行ディレクトリ直下に置いてクラスパスではなくファイルパスで読み込むとエラー無く成功します。
原因は環境別ビルドの為に行っているMavenのリソースフィルタリングの際、resources配下の全ファイルにUTF-8変換が走る設定をしていた為でした。
src/main/resources内のファイルをclassesにコピーする際、propertiesはUTF-8にして貰っていいですが、バイナリまで対象になっていて結果鍵ファイルが壊れ、KeySpecクラスインスタンスの生成に失敗していました。
対処
pom.xmlでバイナリファイルはリソースフィルタリングの対象から外し、単純にclassesにコピーだけして貰います。
Maven Resources Pluginのドキュメントに方法が載っています。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<encoding>UTF-8</encoding>
<!-- .derファイルはフィルタリングしない設定を追加 -->
<nonFilteredFileExtensions>
<nonFilteredFileExtension>der</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
これでUTF-8変換が走らず、OpenSSLで作られたままのバイナリファイルとしてclassesにコピーされ、インスタンス化に成功しました。
得た教訓
Mavenリソースフィルタリングしている場合、/src/main/resourcesにバイナリを置く時は要注意。