Aug 25, 2009

[Merlin] JDK 1.4.x 環境で HMAC with the SHA256 を使用する方法

JavaSE 5 以降の環境では HMAC with the SHA256 が標準機能としてサポートされているので、JRE さえあれば簡単に実現できる。 JavaSE 1.4 以前の環境では HMAC with the SHA256 は標準でサポートされていないので、サードパーティーのライブラリを導入する等の工夫が必要となる。 JavaSE 1.4 で HMAC with the SHA256 を使用する方法をメモしておく。

GNU Crypt の導入

今回は JavaSE 1.4 環境に GNU Crypt を導入する。 GNU Crypt とは

GNU Crypto, part of the GNU project, released under the aegis of GNU, aims at providing free, versatile, high-quality, and provably correct implementations of cryptographic primitives and tools in the Java programming language for use by programmers and end-users.
というもの。
導入する環境は以下の通り。
$ java -version
java version "1.4.2_08"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_08-b03)
Java HotSpot(TM) Client VM (build 1.4.2_08-b03, mixed mode)
GNU Crypt
http://www.gnu.org/software/gnu-crypto/

GNU Crypt のインストール

GNU Crypt のバイナリをダウンロード、解凍し、JRE に登録する。

$ wget ftp://ftp.gnu.org/gnu/gnu-crypto/binaries/gnu-crypto-2.0.1-bin-r1.tar.gz
$ tar zxvf ./gnu-crypto-2.0.1-bin-r1.tar.gz
$ cp ./gnu-crypto-2.0.1-bin/lib/javax-crypto.jar $JAVA_HOME/jre/lib/ext
$ cp ./gnu-crypto-2.0.1-bin/lib/javax-security.jar $JAVA_HOME/jre/lib/ext
$ cp ./gnu-crypto-2.0.1-bin/lib/gnu-crypto.jar $JAVA_HOME/jre/lib/ext


JRE の java.security を編集する。
$ cd $JAVA_HOME/jre/lib/security/
$ cp ./java.security ./java.security.original
$ vi ./java.security
$ diff ./java.security.original ./java.security
51a52
> security.provider.6=gnu.crypto.jce.GnuCrypto
"security.provider.6" の "6" は他の設定と被らない値を指定する。

最後に JRE に同梱されている jce.jar を外しておく。
$ mv $JAVA_HOME/jre/lib/jce.jar /home
同梱されている jce.jar を外す理由は以下の通り。
Installing the JCE Classes

Java runtimes such as those based around Classpath, Kaffe, and JREs from Sun and IBM up to version 1.4 do not include the JCE classes, encompassed by the javax.crypto package and its subpackages. Furthermore, many commercial Java 1.4 and later runtime environments do not allow providers to be installed if they are not digitally signed by an authority. The GNU Crypto developers do not agree with this practice and are not seeking to have GNU Crypto's provider signed.

To overcome this GNU Crypto includes a clean-room implementation of the javax.crypto packages, which is a modified version of the clean-room JCE distributed by the Legion of the Bouncy Castle . If building these classes is enabled at compile-time, a Java archive file javax-crypto.jar will be built, along with the appropriate shared native libraries if you are using GCJ. Simply adding it to your system classpath should suffice, possibly replacing or superceding the jce.jar file that came with your virtual machine.

GNU Crypt で HMAC with the SHA256

GNU Crypt で HMAC with the SHA256 を行うコード例は以下の通り。 JavaSE 5.0 以降のコードと異なるのは

  • アルゴリズム名を "HMAC-SHA256" とすること(JavaSE 5.0 以降では "HmacSHA256")
  • Mac#getInstance に GNU Crypt の Provider を渡すこと
の 2 点。
String plain = "foo";
String key = "bar";
byte[] keyAsBytes = key.getBytes("UTF-8");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyAsBytes,"HMAC-SHA256");
Mac mac = Mac.getInstance("HMAC-SHA256", Security.getProvider("GNU-CRYPTO"));
mac.init(secretKeySpec);

byte[] data = plain.getBytes("UTF-8");
byte[] hashAsBytes = mac.doFinal(data);

String hash = new BASE64Encoder().encode(hashAsBytes);

トラブルシューティング

トラブルシューティングというか失敗記録というか・・・。
javax.crypt の置き換えを忘れると GNU Crypt の jar が未署名というエラーで正常に動作しないので注意。

Exception in thread "main" java.security.NoSuchProviderException: JCE cannot authenticate the provider GNU-CRYPTO
        at javax.crypto.SunJCE_b.a(DashoA6275)
        at javax.crypto.SunJCE_b.a(DashoA6275)
        at javax.crypto.Mac.getInstance(DashoA6275)
        at Temp.main(Temp.java:17)
Caused by: java.util.jar.JarException: file:j2sdk1.4.2_08/jre/lib/ext/gnu-crypto.jar has unsigned entries - gnu/crypto/Properties$1.class
        at javax.crypto.SunJCE_d.b(DashoA6275)
        at javax.crypto.SunJCE_d.a(DashoA6275)
        at javax.crypto.SunJCE_d.a(DashoA6275)
        at javax.crypto.SunJCE_b.b(DashoA6275)

だとか、
java.lang.SecurityException: The provider GNU-CRYPTO may not be signed by a trusted party
        at javax.crypto.SunJCE_b.a(DashoA6275)
        at javax.crypto.Mac.getInstance(DashoA6275)

だとかの例外が出たら、javax.crypt の置き換え忘れを疑ってみると良い。

Posted in Merlin | このエントリーをはてなブックマークに追加 | この記事をクリップ! livedoor クリップ |