共通鍵暗号方式のAESによる暗号化と復号化
提供: Java入門
2015年9月20日 (日) 17:12時点におけるDaemon (トーク | 投稿記録)による版 (ページの作成:「AESとは、共通鍵暗号方式の暗号アルゴリズムの1つです。AESは、Advanced Encryption Standardの略です。DESの安全性が低下していった...」)
スポンサーリンク
AESとは、共通鍵暗号方式の暗号アルゴリズムの1つです。AESは、Advanced Encryption Standardの略です。DESの安全性が低下していったため、代替のために開発されました。Javaでは、いろいろな暗号アルゴリズムが利用できます。ここでは、AESを利用して暗号化、復号化を行います。
読み方
- AES
- えーいーえす
- Advanced Exception Standard
- あどばんすど えんくりぷしょん すたんだーど
概要
AES以外の暗号アルゴリズムも利用できます。使用可能な暗号アルゴリズムを調べるをご参照ください。 このプログラムは、鍵長は、128ビットです。
流れ
プログラムの流れは、以下の通りです。
- 鍵を生成する
- IV(Initial Vector, 初期ベクトル)を生成する
- データを暗号化する
- 暗号化したデータを復号化する
PKCS5Paddingなどが見つからない
ブロック暗号方式は、データサイズがブロックサイズの倍数でないと暗号化できません。そのため、ブロックサイズに合わない最後のブロックをパディングで調整する必要があります。
パディングのためのPKCS5Paddingがあるはずなのですが、NOPADDINGしか見つからず、今回は、データサイズが必ずあっている前提でコードを書いています。
AES1
データサイズは、16バイトの倍数でなければなりません。
ソースコード AES1.java
/* * AES1.java * Copyright (C) 2015 kaoru <kaoru@localhost> */ import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.security.spec.KeySpec; import java.security.SecureRandom; import javax.crypto.spec.IvParameterSpec; import java.util.Base64; public class AES1 { enum MODE { ENCRYPT, DECRYPT }; public static SecretKey ENCRYPT_KEY; public static int KEY_SIZE = 128; public static byte[] ENCRYPT_IV;// = "abcdefghijabcdefghij"; public static String ALGORITHM = "AES_128/CBC/NOPADDING"; public static String CIPHER = "AES"; public static String char_code = "UTF-8"; public static String encrypt (String plaintext) throws Exception { byte[] cipher_byte = crypt(plaintext.getBytes(), MODE.ENCRYPT); String b64 = Base64.getEncoder().encodeToString(cipher_byte); return b64; } public static String decrypt (String text64) throws Exception { byte[] cipher_byte = Base64.getDecoder().decode(text64.getBytes() ); byte[] plain_byte = crypt(cipher_byte, MODE.DECRYPT); String plaintext = new String(plain_byte, char_code); return plaintext; } public static byte[] crypt(byte[] input, MODE mode) throws Exception { byte[] output; try { byte[] key = ENCRYPT_KEY.getEncoded(); byte[] iv = ENCRYPT_IV;//.getBytes(char_code); SecretKeySpec skey = new SecretKeySpec(key, CIPHER); IvParameterSpec ivp = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance(ALGORITHM); int m = (mode == MODE.ENCRYPT) ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; cipher.init(m, skey, ivp); output = cipher.doFinal(input); } catch (Exception e) { e.printStackTrace(); throw new Exception("Can not crypt"); } return output; } public static void makeKey () throws Exception { try { KeyGenerator keygen = KeyGenerator.getInstance(CIPHER); SecureRandom random = new SecureRandom(); keygen.init(KEY_SIZE, random); ENCRYPT_KEY = keygen.generateKey(); } catch (Exception e) { throw new Exception("Can not make key", e); } } public static void makeIv () throws Exception { SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); ENCRYPT_IV = new byte[16]; random.nextBytes(ENCRYPT_IV); } public static void main(String[] args) { String text = "HogehogeHogehoge"; try { makeKey(); makeIv(); String cipher_text = encrypt(text); String plain_text = decrypt(cipher_text); System.out.println(cipher_text); System.out.println(plain_text); } catch (Exception e) { e.printStackTrace(); } } }
コンパイル
javac AES1.java
実行例
$ java AES1 6TLZ+5HF/9CIbsWa/0mo6g== HogehogeHogehoge
エラーの例
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
平文のデータが16バイトの倍数でない場合、エラーになります。
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1016) at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:984) at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824) at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436) at javax.crypto.Cipher.doFinal(Cipher.java:2165)
java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long
IV(初期ベクトルのサイズは、16バイトでなければなりません。
java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long at com.sun.crypto.provider.CipherCore.init(CipherCore.java:516) at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:339) at javax.crypto.Cipher.implInit(Cipher.java:806) at javax.crypto.Cipher.chooseProvider(Cipher.java:864) at javax.crypto.Cipher.init(Cipher.java:1396) at javax.crypto.Cipher.init(Cipher.java:1327)
java.security.InvalidKeyException: The key must be 128 bits
鍵長は、128ビットでない場合、エラーになります。
java.security.InvalidKeyException: The key must be 128 bits at com.sun.crypto.provider.AESCipher.checkKeySize(AESCipher.java:158) at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:338) at javax.crypto.Cipher.implInit(Cipher.java:806) at javax.crypto.Cipher.chooseProvider(Cipher.java:864) at javax.crypto.Cipher.init(Cipher.java:1396) at javax.crypto.Cipher.init(Cipher.java:1327)
関連項目
- 使用可能な暗号アルゴリズムを調べる
- 共通鍵暗号方式のAESによる暗号化と復号化
- JavaでSHA256を計算する
- JavaでHMAC-SHA256を計算する
- 暗号
ツイート
スポンサーリンク