Java SE 7(JDK7)でECC(楕円曲線暗号)を試す

  • 投稿日:
  • by
  • Category:
[追記あり] Java SE 6にBouncy Castleを入れて性能比較しました。
----
なんかいろいろ勘違いしているので助けてください(泣

7月28日(現地時間)にJava SE 7およびJDK7がリリースされました。
楕円曲線暗号(ECC)
いくつかのECCベースのアルゴリズム(ECDSA/ECDH)を提供する新しいネイティブ・プロバイダがJava SE 7リリースに追加されました。
Java SE 6にもJava ™ Cryptography Architecture Standard Algorithm Name Documentation にあるように、"EC"および"HOGEwithECDSA"が使えるみたいなので、Java SE 7のネイティブプロバイダとの性能比較とかできるのでは?と思い、早速コードを書いてみました。
作成したソースコードはこちら:EC.java [8/14更新]

import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
public class EC {
	public static void main(String[] args) {
		byte[] message = "The quick brown fox jumps over the lazy dog"
				.getBytes();
		byte[] sign = null;
		KeyPairGenerator keyPairGenerator = null;
		long generateKeyPairStart;
		long generateKeyPairEnd;
		try {
			keyPairGenerator = KeyPairGenerator.getInstance("EC");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return;
		}
		SecureRandom secureRandom = new SecureRandom();
		keyPairGenerator.initialize(256, secureRandom);
		generateKeyPairStart = System.nanoTime();
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		generateKeyPairEnd = System.nanoTime();
		PrivateKey privateKey = keyPair.getPrivate();
		PublicKey publicKey = keyPair.getPublic();
		Signature signatureSign = null;
		long signStart = 0;
		long signEnd = 0;
		try {
			signatureSign = Signature.getInstance("NONEwithECDSA");
			signatureSign.initSign(privateKey, secureRandom);
			signatureSign.update(message);
			signStart = System.nanoTime();
			sign = signatureSign.sign();
			signEnd = System.nanoTime();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return;
		} catch (InvalidKeyException e) {
			e.printStackTrace();
			return;
		} catch (SignatureException e) {
			e.printStackTrace();
			return;
		}
		Signature signatureVerify = null;
		boolean verifyResult;
		long verifyStart;
		long verifyEnd;
		try {
			signatureVerify = Signature.getInstance("NONEwithECDSA");
			signatureVerify.initVerify(publicKey);
			signatureVerify.update(message);
			verifyStart = System.nanoTime();
			verifyResult = signatureVerify.verify(sign);
			verifyEnd = System.nanoTime();
			if (verifyResult) {
				System.out.print("OK");
				System.out.print("\t");
			} else {
				System.out.print("NG");
				System.out.print("\t");
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return;
		} catch (InvalidKeyException e) {
			e.printStackTrace();
			return;
		} catch (SignatureException e) {
			e.printStackTrace();
			return;
		}
		System.out.print(generateKeyPairEnd - generateKeyPairStart);
		System.out.print("\t");
		System.out.print(signEnd - signStart);
		System.out.print("\t");
		System.out.print(verifyEnd - verifyStart);
		System.out.println();
	}
}

結果:
Java SE 6では(そのままの環境では)ECが使えないみたいです。コンパイルはできるのですが、NoSuchAlgorithmException が出てしまいました。

110731_1.png

java.security.NoSuchAlgorithmException: EC KeyPairGenerator not available
    at java.security.KeyPairGenerator.getInstance(KeyPairGenerator.java:176)
    at EC.main(EC.java:21)
ということで、当初やりたかった性能比較はできませんでした。
とりあえず、Java SE 7で署名と検証ができているのでよしとするかな...。

----
[追記]記事を書いた後に調べたり、コメントをいただいた通り、Java SE 6では別途ECの実装が必要でした。
Bouncy CastleをJava SE 6に設定、コードの処理の始めと終わりに時間取得と差をとるコードを埋め込んで、性能比較しました。

※本当は時間取得関数の粒度の考慮やプロファイラを使った測定をするのですが、概ねの感覚をつかむためだけなので簡易的なものにしました。
表の値は1000回の平均値です。
 鍵ペア生成(generateKeyPair)署名(sign)検証(verify)
Java SE 6(Bouncy Castle)[ns]1968249234508112939902893
Java SE 7[ns]544651439026575771905
性能比[%](6/7)36141155691.3
時間比[%](7/6)0.027670.086570.1447

おー、大幅に速くなりました。
別途実装を用意しなくてもよくなったので、Java SE 7を用いたECCを使うシステムに期待大です。

コメントを頂いた@satorukannoさん、line君、ありがとうございました。
このエントリーをはてなブックマークに追加

コメント(2)

コメントする