Javaで共通鍵暗号方式「AES」を使用した暗号化と復号化

Java プログラミング
この記事は約7分で読めます。

※当ブログではアフィリエイト広告を利用しています。

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

暗号化は難しい。。

参考サイト

Java「AES暗号」メモ(Hishidama’s AES Sample)

AES128bit暗号化/復号化を文字列で行なってみる – bose999の試験管の中の話

コメント

タイトルとURLをコピーしました