■ 現象内容
http://blogs.yahoo.co.jp/dk521123/34330480.htmlhttp://blogs.yahoo.co.jp/dk521123/33640872.html
http://blogs.yahoo.co.jp/dk521123/36419973.html
http://blogs.yahoo.co.jp/dk521123/32780473.html
で、Javaの暗号化/複合化処理を実装したが、 以下の「■ サンプル」のように、処理時間を計測してみた。 結果は、以下「出力結果」になるのだが、初回にPCで大体1~1.5秒掛かる。 Raspberry PIやスマホなどの非力なデバイス上で実行した場合、更に掛かってしまう。
■ サンプル
以下の関連記事のサンプルを参考に時間計測のログを張ってみるhttp://blogs.yahoo.co.jp/dk521123/34330480.html
import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; public class Main { public static void main(String[] args) { try { String key = "1234567890123456"; String original = "This is a source of string!!"; String algorithm = "AES"; System.out.println("[1]"); long start = System.currentTimeMillis(); String encrypedResult = CipherHelper.encrypt(original, key, algorithm); System.out.println("Time:" + (System.currentTimeMillis() - start) + "[ms]"); System.out.println("暗号化文字列:" + encrypedResult); System.out.println("[2]"); start = System.currentTimeMillis(); String decryptedResult = CipherHelper.decrypt(encrypedResult, key, algorithm); System.out.println("Time:" + (System.currentTimeMillis() - start) + "[ms]"); System.out.println("復号化文字列:" + decryptedResult); System.out.println("[3]"); start = System.currentTimeMillis(); String encrypedResult2 = CipherHelper.encrypt(original, key, algorithm); System.out.println("Time:" + (System.currentTimeMillis() - start) + "[ms]"); System.out.println("暗号化文字列:" + encrypedResult2); System.out.println("[4]"); start = System.currentTimeMillis(); String decryptedResult2 = CipherHelper.decrypt(encrypedResult, key, algorithm); System.out.println("Time:" + (System.currentTimeMillis() - start) + "[ms]"); System.out.println("復号化文字列:" + decryptedResult2); } catch (Exception ex) { ex.printStackTrace(); } } public static class CipherHelper { /** * 文字列を16文字の秘密鍵でAES暗号化してBase64した文字列で返す */ public static String encrypt(String originalSource, String secretKey, String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { byte[] originalBytes = originalSource.getBytes(); byte[] encryptBytes = cipher(true, originalBytes, secretKey, algorithm); byte[] encryptBytesBase64 = Base64.getEncoder().encode(encryptBytes); return new String(encryptBytesBase64); } /** * Base64されたAES暗号化文字列を元の文字列に復元する */ public static String decrypt(String encryptBytesBase64String, String secretKey, String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { byte[] encryptBytes = Base64.getDecoder().decode(encryptBytesBase64String); byte[] originalBytes = cipher(false, encryptBytes, secretKey, algorithm); return new String(originalBytes); } /** * 暗号化/複合化の共通部分 */ private static byte[] cipher(boolean isEncrypt, byte[] source, String secretKey, String algorithm) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { byte[] secretKeyBytes = secretKey.getBytes(); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKeyBytes, algorithm); Cipher cipher = Cipher.getInstance(algorithm); if (isEncrypt) { cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); } else { cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); } return cipher.doFinal(source); } } }
出力結果
[1] Time:1478[ms] <=★約1~1.5秒かかる★ 暗号化文字列:B/UZj3IF6F6tObxiTAqdDsDLxUKGCBuAYjVTQP1GSnI= [2] Time:1[ms] <=☆1ミリ秒☆ 復号化文字列:This is a source of string!! [3] Time:0[ms] <=☆1ミリ秒未満☆ 暗号化文字列:B/UZj3IF6F6tObxiTAqdDsDLxUKGCBuAYjVTQP1GSnI= [4] Time:0[ms] <=☆1ミリ秒未満☆ 復号化文字列:This is a source of string!!
■ 原因
暗号化・複合化で使用している「Cipher.getInstance()」の初回に時間がかかるため。 # cipher.init()も若干時間がかかっている計測のため、以下のようにログを打ち込む
・・・ long start = System.currentTimeMillis(); byte[] secretKeyBytes = secretKey.getBytes(); System.out.println("Time for secretKey.getBytes():" + (System.currentTimeMillis() - start) + "[ms]"); start = System.currentTimeMillis(); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKeyBytes, algorithm); System.out.println("Time for new SecretKeySpec():" + (System.currentTimeMillis() - start) + "[ms]"); start = System.currentTimeMillis(); Cipher cipher = Cipher.getInstance(algorithm); System.out.println("Time for Cipher.getInstance():" + (System.currentTimeMillis() - start) + "[ms]"); start = System.currentTimeMillis(); if (isEncrypt) { cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); } else { cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); } System.out.println("Time for Cipher.init():" + (System.currentTimeMillis() - start) + "[ms]"); ・・・出力結果
[1] Time for Base64.getEncoder().encode:1[ms] Time for secretKey.getBytes():0[ms] Time for new SecretKeySpec():3[ms] Time for Cipher.getInstance():870[ms] <=!!注目!! ★ここに時間が掛かっている★ Time for Cipher.init():78[ms] <=★ここも多少時間が掛かっている★ Time for Cipher.doFinal():1[ms] Time for Base64.getEncoder().encode:0[ms] Time:958[ms] 暗号化文字列:B/UZj3IF6F6tObxiTAqdDsDLxUKGCBuAYjVTQP1GSnI= [2] Time for Base64.getDecoder().decode:0[ms] Time for secretKey.getBytes():0[ms] Time for new SecretKeySpec():0[ms] Time for Cipher.getInstance():0[ms] Time for Cipher.init():0[ms] Time for Cipher.doFinal():0[ms] Time:1[ms] 復号化文字列:This is a source of string!! [3] Time for Base64.getEncoder().encode:0[ms] Time for secretKey.getBytes():0[ms] Time for new SecretKeySpec():0[ms] Time for Cipher.getInstance():0[ms] Time for Cipher.init():1[ms] Time for Cipher.doFinal():0[ms] Time for Base64.getEncoder().encode:0[ms] Time:1[ms] 暗号化文字列:B/UZj3IF6F6tObxiTAqdDsDLxUKGCBuAYjVTQP1GSnI= [4] Time for Base64.getDecoder().decode:0[ms] Time for secretKey.getBytes():0[ms] Time for new SecretKeySpec():0[ms] Time for Cipher.getInstance():0[ms] Time for Cipher.init():0[ms] Time for Cipher.doFinal():0[ms] Time:1[ms] 復号化文字列:This is a source of string!!