「AES」とは、アメリカ合衆国の旧国家暗号規格であった「DES」が安全性の低下により、後続として公募され、採用された新暗号化規格らしい。
その「AES」は、「ブロック暗号」という共通鍵暗号方式の一種みたい。
「ブロック暗号」とは、平文をブロックという固定長の単位に分割し、暗号化していくという方式らしい。
さて、難しいことはそっと横に置いといて、「AES」をJavaで実装してみた。
メインメソッド
まずはメインメソッド。
コマンドライン引数を暗号化メソッド、復号化メソッドに渡してやる。
また、暗号化キーと初期化ベクトルを固定値で用意した。
今回使用する「暗号利用モード(ブロック処理の種類)」は「CBC」というものを指定するのだが、これはブロックの暗号化を行う際に、前のブロックの暗号化した結果を利用し、暗号化するというもの。
一番初めのブロックに対しては、前のブロックがないので、「初期化ベクトル」という外部値を利用する。
public class AesTest { public static final String ENCRYPT_KEY = "1234567890123456"; public static final String ENCRYPT_IV = "abcdefghijklmnop"; /** * メインメソッド * * @param args */ public static void main(String[] args) { // 暗号化メソッド呼出 System.out.println(encrypt(args[0])); // 復号化メソッド呼出 System.out.println(decrypt(encrypt(args[0]))); } }暗号化メソッド
上記で説明した「暗号利用モード(ブロック処理の種類)」は「CBC」を指定し、「パディング方式」は「PKCS5Padding」を指定した。
「パディング方式」とは、ブロック長に満たない場合の補完の方式だ。
また、暗号化結果は、データを64種類の印字可能な英数字のみで表現する「Base64」でエンコードを行った。
なお、「Base64」クラスを使用するためにはこちらより、「Commons Codec」をダウンロードし、jarファイル「commons-codec-1.8.jar」をインポートする必要がある。
/** * 暗号化メソッド * * @param text 暗号化する文字列 * @return 暗号化文字列 */ public static String encrypt(String text) { // 変数初期化 String strResult = null; try { // 文字列をバイト配列へ変換 byte[] byteText = text.getBytes("UTF-8"); // 暗号化キーと初期化ベクトルをバイト配列へ変換 byte[] byteKey = ENCRYPT_KEY.getBytes("UTF-8"); byte[] byteIv = ENCRYPT_IV.getBytes("UTF-8"); // 暗号化キーと初期化ベクトルのオブジェクト生成 SecretKeySpec key = new SecretKeySpec(byteKey, "AES"); IvParameterSpec iv = new IvParameterSpec(byteIv); // Cipherオブジェクト生成 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Cipherオブジェクトの初期化 cipher.init(Cipher.ENCRYPT_MODE, key, iv); // 暗号化の結果格納 byte[] byteResult = cipher.doFinal(byteText); // Base64へエンコード strResult = Base64.encodeBase64String(byteResult); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } // 暗号化文字列を返却 return strResult; }復号化メソッド
今度は復号化。
こちらは、暗号化メソッドと逆のことをする。
/** * 復号化メソッド * * @param text 復号化する文字列 * @return 復号化文字列 */ public static String decrypt(String text) { // 変数初期化 String strResult = null; try { // Base64をデコード byte[] byteText = Base64.decodeBase64(text); // 暗号化キーと初期化ベクトルをバイト配列へ変換 byte[] byteKey = ENCRYPT_KEY.getBytes("UTF-8"); byte[] byteIv = ENCRYPT_IV.getBytes("UTF-8"); // 復号化キーと初期化ベクトルのオブジェクト生成 SecretKeySpec key = new SecretKeySpec(byteKey, "AES"); IvParameterSpec iv = new IvParameterSpec(byteIv); // Cipherオブジェクト生成 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Cipherオブジェクトの初期化 cipher.init(Cipher.DECRYPT_MODE, key, iv); // 復号化の結果格納 byte[] byteResult = cipher.doFinal(byteText); // バイト配列を文字列へ変換 strResult = new String(byteResult, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } // 復号化文字列を返却 return strResult; }実行結果
「test123」という値をコマンドライン引数で渡し、暗号化・復号化をしてみた。
結果は以下のようになった。
BTRsN57DlDsSB9aPzgt/Vg== test123暗号化は難しい。。
参考サイト
コメント