web-dev-qa-db-ja.com

AES-GCM-256での認証タグの計算方法

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();
    }
1
RE350

はい、それはdoFinalメソッドによって内部的に行われています。 Cipherクラスの Javadoc によれば、

doFinal(byte [] input)

GCM/CCMなどのAEADモードが使用されている場合、暗号化の場合は認証タグが付加され、復号化の場合は認証タグが検証されます。

したがって、暗号化/復号化プロセス中に、authタグを明示的に追加/検証する必要はありません。

1
user90696