AES-GCM-256を使用して文字列を暗号化および復号化するサンプルコードがあります。
暗号化側で認証タグがどのように生成され、復号化側でどのように使用されているのか理解できません。
実際、ここでは、暗号化側でも検証側でも検証タグを生成していないため、ライブラリ自体によって内部的に行われています。
private static String encrypt(String s, byte[] k) throws Exception {
SecureRandom r = SecureRandom.getInstance("SHA1PRNG");
// Generate 128 bit IV for Encryption
byte[] iv = new byte[12]; r.nextBytes(iv);
SecretKeySpec eks = new SecretKeySpec(k, "AES");
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
// Generated Authentication Tag should be 128 bits
c.init(Cipher.ENCRYPT_MODE, eks, new GCMParameterSpec(128, iv));
byte[] es = c.doFinal(s.getBytes(StandardCharsets.UTF_8));
// Construct Output as "IV + CIPHERTEXT"
byte[] os = new byte[12 + es.length];
System.arraycopy(iv, 0, os, 0, 12);
System.arraycopy(es, 0, os, 12, es.length);
// Return a Base64 Encoded String
return Base64.getEncoder().encodeToString(os);
}
private static String decrypt(String eos, byte[] k) throws Exception {
// Recover our Byte Array by Base64 Decoding
byte[] os = Base64.getDecoder().decode(eos);
// Check Minimum Length (IV (12) + TAG (16))
if (os.length > 28) {
byte[] iv = Arrays.copyOfRange(os, 0, 12);
byte[] es = Arrays.copyOfRange(os, 12, os.length);
// Perform Decryption
SecretKeySpec dks = new SecretKeySpec(k, "AES");
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
c.init(Cipher.DECRYPT_MODE, dks, new GCMParameterSpec(128, iv));
// Return our Decrypted String
return new String(c.doFinal(es), StandardCharsets.UTF_8);
}
throw new Exception();
}
はい、それはdoFinal
メソッドによって内部的に行われています。 Cipher
クラスの Javadoc によれば、
doFinal(byte [] input)
GCM/CCMなどのAEADモードが使用されている場合、暗号化の場合は認証タグが付加され、復号化の場合は認証タグが検証されます。
したがって、暗号化/復号化プロセス中に、authタグを明示的に追加/検証する必要はありません。