ファイルをパスワードで暗号化するデスクトップアプリを作ってみた。画面はこんな感じ。
ソフト本体(JARファイル)は以下で公開したよ。Macで作成したけど、JARなのでOSに依存せず動作するはず。
github.com
暗号化アルゴリズム
- 入力したパスワードをSHA-1でハッシュ化する
- ファイルをbyte列として読み込む
- パスワードハッシュとファイル内容を1 byteずつ突合し、XOR演算をする
- 新しいファイルとして出力する
ソース
アプリの核となる暗号化処理をする部分のソースはこんな感じ。BufferedStreamを使った方が処理は速くなると思うけど、ロジックがややこしくなるので使わなかった。
// 本処理 byte[] pw_hash = sha1(pw); int index = 0; FileInputStream fis = new FileInputStream(inputFile); FileOutputStream fos = new FileOutputStream(outputFile); byte[] data = new byte[1]; // ファイルから1バイトずつ読み込み、ハッシュとXOR演算する。 while ((fis.read(data, 0, 1)) != -1) { data[0] = (byte) (data[0] ^ pw_hash[index]); fos.write(data, 0, 1); // 演算用バイト列の中身は一回ごとにクリアする。 data[0] = 0; // ハッシュ値の項目番号は周期20でリセットする。 switch (index) { case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18: index++; break; case 19: index = 0; break; } } fis.close(); fos.close(); // パスワードからSHA-1のハッシュ値を算出するメソッド private static byte[] sha1(String pw) throws NoSuchAlgorithmException { MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); byte[] result = sha1.digest(pw.getBytes()); return result; }
セキュリティについて
暗号化セキュリティはそこまで強固ではないと思う。
共通鍵暗号だと見たとき、セキュリティに関してはハッシュ化アルゴリズムSHA-1の強度に依存していることになる。その点はSHA-256などにすれば多少マシにはなるだろう。
弱点になりそうなのは暗号の周期性だ。パスワードから生成された20 byteのハッシュをそのままXOR演算に使用しているため、ファイル内容に対して20 byteおきに同じ演算がなされることになる。それがファイル内容の周期性と噛み合ってしまったら、暗号として意味をなさなくなるかもしれない。
色々な暗号化システムで採用されている通り、やはり並び替え処理は必要なのだと思う。
まとめ
楽しかった。byteレベルでファイルを操作できることがわかったので、今後はそういう処理を使って便利な機能を有する何かを作りたい。面倒臭くない範囲で。