AES共通鍵暗号
Javaのjavax.crypto APIを使い、AES/CBC/PKCS5Paddingで機密データを暗号化・復号します。
「AES共通鍵暗号」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
対称暗号と非対称暗号
対称暗号では暗号化と復号に同じ鍵を使用します(高速で、大量データに適しています)。非対称暗号では公開鍵と秘密鍵のペアを使用します(低速ですが、鍵交換や署名に使用されます)。AES は標準的な対称暗号です。
AES のモード: CBC と GCM
AES には複数のモードがあります。AES/CBC/PKCS5Padding は一般的ですが、認証機能がありません。AES/GCM/NoPadding は暗号化と認証の両方(AEAD)を提供するため、新しいコードでは強く推奨されます。
AES 鍵の生成
KeyGenerator を使用して、256 ビットの AES 鍵を安全に生成します。
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256); // 256-bit key
SecretKey key = kg.generateKey();
// Persist the key:
String b64Key = Base64.getEncoder().encodeToString(key.getEncoded());
// Restore the key:
byte[] decoded = Base64.getDecoder().decode(b64Key);
SecretKey restored = new SecretKeySpec(decoded, "AES");AES/GCM 暗号化
GCM モードでは、暗号化ごとに一意の 12 バイトの初期化ベクトル(IV)が必要です。暗号化処理のたびに新しいランダムな IV を生成してください。同じ鍵で IV を再利用してはいけません。
byte[] iv = new byte[12]; // 96-bit IV for GCM
new SecureRandom().nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128, iv); // 128-bit auth tag
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
// Transmit/store: IV + ciphertext (IV is not secret)AES/GCM 復号
保存されたデータから IV を取り出し、spec を再構成して復号します。GCM は真正性を自動的に検証するため、改ざんされたデータでは AEADBadTagException がスローされます。
// Assume stored = iv + ciphertext:
byte[] iv = Arrays.copyOfRange(stored, 0, 12);
byte[] ciphertext = Arrays.copyOfRange(stored, 12, stored.length);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv));
byte[] plaintext = cipher.doFinal(ciphertext); // throws if tampered暗号文と一緒に IV を保存する
IV は秘密ではないため、暗号文の先頭に付加するか、暗号文と一緒に保存します。受信側は復号に IV を必要とします。鍵は秘密に保管する必要があります。
byte[] encryptedData = new byte[iv.length + ciphertext.length];
System.arraycopy(iv, 0, encryptedData, 0, iv.length);
System.arraycopy(ciphertext, 0, encryptedData, iv.length, ciphertext.length);
String b64 = Base64.getEncoder().encodeToString(encryptedData);パスワードからの鍵導出(PBKDF2)
パスワードを AES 鍵として直接使用してはいけません。エントロピーが低すぎるためです。ランダムなソルトと高い反復回数を使用して、PBKDF2 で鍵を導出します。
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 310_000, 256);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] keyBytes = skf.generateSecret(spec).getEncoded();
SecretKey key = new SecretKeySpec(keyBytes, "AES");Java Security Provider の使用
JDK のデフォルトプロバイダーは AES を処理します。追加のアルゴリズムや FIPS 準拠が必要な場合は、Bouncy Castle プロバイダーを使用します。
// With Bouncy Castle:
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");エンベロープ暗号化パターン
ランダムに生成したデータ暗号化鍵(DEK)でデータを暗号化します。AWS KMS や HashiCorp Vault などの KMS に保存した鍵暗号化鍵(KEK)で DEK を暗号化します。これにより、鍵が露出する範囲を限定できます。
Spring アプリケーションでの AES
Spring Security の TextEncryptor または Spring Security Crypto モジュールを使用すると、Cipher や IV を手動で管理せずに、高水準の AES 暗号化を利用できます。
TextEncryptor encryptor = Encryptors.text(password, salt);
String encrypted = encryptor.encrypt("sensitive data");
String decrypted = encryptor.decrypt(encrypted);よくある落とし穴
同じ鍵で IV を再利用すること、ECB モードを使用すること(パターンが保持されます)、パスワードを鍵として直接使用すること、認証タグを無視することは、決して行わないでください。新しいコードでは必ず GCM を使用します。
確認問題
AES/CBC にはなく、AES/GCM にある機能は何ですか。
まとめ
認証付き暗号化には AES/GCM/NoPadding を使用します。暗号化ごとに新しいランダムな 12 バイトの IV を生成します。IV は暗号文の先頭に付加します。パスワードからは PBKDF2 で鍵を導出します。同じ鍵で IV を再利用してはいけません。
よくある質問
「AES共通鍵暗号」レッスンは無料ですか?
はい。「AES共通鍵暗号」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「AES共通鍵暗号」で何を学びますか?
Javaのjavax.crypto APIを使い、AES/CBC/PKCS5Paddingで機密データを暗号化・復号します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「AES共通鍵暗号」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。