暗号化
指定したファイルを読み込み、その内容をAESで暗号化した後、別のファイルに保存する仕組みです。
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.*;
public class FileEncryption {
public static void main(String[] args) {
File inputFile = new File("input.jpg");
File encryptedFile = new File("encrypted.dat");
try {
// AESキーの生成
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
// AES暗号器の初期化
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// ファイルをブロック単位で暗号化
try (FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(encryptedFile)) {
byte[] buffer = new byte[1024]; // 1KBのブロックサイズ
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
fos.write(output);
}
}
byte[] finalBytes = cipher.doFinal();
if (finalBytes != null) {
fos.write(finalBytes);
}
}
System.out.println("ファイルの暗号化が完了しました。");
} catch (java.security.NoSuchAlgorithmException e) {
System.err.println("指定された暗号アルゴリズムが存在しません: " + e.getMessage());
} catch (javax.crypto.NoSuchPaddingException e) {
System.err.println("指定されたパディング方式が存在しません: " + e.getMessage());
} catch (java.security.InvalidKeyException e) {
System.err.println("無効な鍵が使用されました: " + e.getMessage());
} catch (javax.crypto.IllegalBlockSizeException e) {
System.err.println("ブロックサイズが無効です: " + e.getMessage());
} catch (javax.crypto.BadPaddingException e) {
System.err.println("不正なパディングが検出されました: " + e.getMessage());
} catch (java.io.IOException e) {
System.err.println("ファイル処理中にエラーが発生しました: " + e.getMessage());
} catch (Exception e) {
System.err.println("予期しないエラーが発生しました: " + e.getMessage());
}
}
}
コードの説明:
- ファイル指定:
plain.txtが暗号化対象のファイルで、結果はencrypted.datに保存されます。
- 鍵生成:
- AESで128ビットの暗号鍵をランダムに生成します。この鍵は暗号化・復号時に利用されます。
- 暗号化プロセス:
Cipher.getInstance("AES")によりAES暗号器を作成し、暗号化モードに設定します。- 入力ファイルをバイト配列に読み込み、それを
doFinal()メソッドで暗号化します。
- 暗号化ファイルの保存:
- 暗号化されたバイト配列を出力ファイル
encrypted.datに書き込んで保存します。
- 暗号化されたバイト配列を出力ファイル
注意点:
- 復号化の際には、このプログラムで生成した
SecretKeyを保存しておく必要があります。 - ファイルの鍵管理には十分注意してください。鍵を紛失すると復号化できなくなります。
復号化
暗号化されたファイルを復号化するサンプルコードを示します。このコードは、暗号化時に使用した秘密鍵を使用して、元のデータを復元します。
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.KeyGenerator;
import java.io.*;
public class FileDecryption {
public static void main(String[] args) {
File encryptedFile = new File(“encrypted.dat”);
File outputFile = new File(“decrypted.jpg”);
try {
// AESキーの生成 (※ 実際の運用では暗号化時と同じ鍵を使用)
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
// AES復号化器の初期化
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
// 暗号化ファイルをブロック単位で復号化
try (FileInputStream fis = new FileInputStream(encryptedFile);
FileOutputStream fos = new FileOutputStream(outputFile)) {
byte[] buffer = new byte[1024]; // 1KBのブロックサイズ
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
fos.write(output);
}
}
byte[] finalBytes = cipher.doFinal();
if (finalBytes != null) {
fos.write(finalBytes);
}
}
System.out.println("ファイルの復号化が完了しました。");
} catch (java.security.NoSuchAlgorithmException e) {
System.err.println("指定された暗号アルゴリズムが存在しません: " + e.getMessage());
} catch (javax.crypto.NoSuchPaddingException e) {
System.err.println("指定されたパディング方式が存在しません: " + e.getMessage());
} catch (java.security.InvalidKeyException e) {
System.err.println("無効な鍵が使用されました: " + e.getMessage());
} catch (javax.crypto.IllegalBlockSizeException e) {
System.err.println("ブロックサイズが無効です: " + e.getMessage());
} catch (javax.crypto.BadPaddingException e) {
System.err.println("不正なパディングが検出されました: " + e.getMessage());
} catch (java.io.IOException e) {
System.err.println("ファイル処理中にエラーが発生しました: " + e.getMessage());
} catch (Exception e) {
System.err.println("予期しないエラーが発生しました: " + e.getMessage());
}
}
}
コードの重要な点
- 暗号化時と同じ秘密鍵を使用:
- 暗号化時と同じ
SecretKeyを使用する必要があります。このサンプルでは簡単化のために鍵を新しく生成していますが、実運用では鍵を保存し、復号化時に読み込む必要があります。
- 暗号化時と同じ
- 復号化モードの設定:
cipher.init(Cipher.DECRYPT_MODE, secretKey);を使用して、復号化モードに切り替えます。
- ファイル処理の流れ:
- 暗号化されたデータをバイト単位で読み込み、復号化されたデータを出力ファイル (
decrypted.jpg) に書き込みます。
- 暗号化されたデータをバイト単位で読み込み、復号化されたデータを出力ファイル (
注意点
- 秘密鍵の管理: 暗号化時に生成した鍵を適切に保存しておく必要があります。鍵がなければ復号化はできません。
- 暗号化されたファイルの整合性: 暗号化されたファイルが完全に保存されていることを確認してください。
暗号化するときの secretKey = keyGen.generateKey(); で使用したsecretKey を使用すれば復元できる
。暗号化時に使用した SecretKey を復号化時にも使用すれば、正確にデータを復元できます。
具体的には、暗号化時に生成した SecretKey は対称鍵暗号方式(AES)で利用されるため、同じ鍵を使用して復号化する必要があります。そのため、以下の点に注意してください:
必要な手順
- SecretKey の保存:
- 暗号化時に生成した
SecretKeyをメモリ内に保持するだけでなく、後で復号化に使用できるように保存する必要があります。 - 例として、鍵をファイルにバイナリ形式で保存する方法を用いる場合:java
try (FileOutputStream keyOut = new FileOutputStream("secretKey.key")) { keyOut.write(secretKey.getEncoded()); } - これにより、暗号化に使用した鍵をファイルとして保存できます。
- 暗号化時に生成した
- 復号化時に鍵を読み込む:
- 復号化時に、保存した鍵を再度読み込んで
SecretKeyを再構築します。javabyte[] keyBytes; try (FileInputStream keyIn = new FileInputStream("secretKey.key")) { keyBytes = keyIn.readAllBytes(); } SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(keyBytes, "AES");
- 復号化時に、保存した鍵を再度読み込んで
- 復号化処理:
- この鍵を使用して
Cipherを復号化モード (DECRYPT_MODE) に初期化し、暗号化されたデータを復号化します。
- この鍵を使用して
ポイント
- 対称鍵の安全な保管: 秘密鍵は暗号化と復号化の両方に必要不可欠です。鍵を安全に保管し、第三者に漏れないようにしてください。
- 鍵が一致すること: 暗号化時と復号化時の
SecretKeyが完全に一致していないと、復号化は失敗します。
暗号化時に使用した SecretKey を正しく保持し、復号化時に再利用すれば、問題なく元のデータを復元できます。



コメント