共通鍵暗号
共通鍵 (Common Key; 対称鍵) は暗号化と復号化に同じ鍵を使用する方法です。
パスワードを使用した暗号化として一般に広く使用されています。
共通鍵暗号は暗号化と復号化に同じ鍵を使用しなければならないため、離れたところで
暗号化を行わなければならない場合は鍵を持ち出さなければならないという運用上の
弱点があります。インターネットのような信頼性の低い非専用回線ネットワークを
経由してデータを受け渡しするような場合は公開鍵暗号
を使用してください。
しかし公開鍵方式と比べて強度的な弱さがあるわけではなく、単に秘匿性の高い
データを平文のままファイルやデータベースに保存したくないというような場合には
共通鍵の方が向いています。
共通鍵アルゴリズム
代表的な共通鍵アルゴリズムは以下の通り。Sun JSE 6 のデフォルト状態は輸入管理
制限によって 128bit の制限が設けられています。大抵の状況では 128bit blowfish か
AES で十分と思われますが、日本国内での利用であれば
制限を解除する事でより強度の高い暗号を
使用することもできます。
DES は認知度さえ高いですが既に解読が可能な状態であるため、互換性が必要な場合でも
トリプル DES を使用してください。
|
ブロック長 |
鍵長 |
|
| DES |
64bit |
56bit |
Data Encyption Standard: 1970 年代から存在する暗号化方式。
米国の暗号規格として長い間採用されていたため世界中で広く使われていますが、
現在では専用のコンピュータで数日程度で解読できるためセキュリティが重視
される状況では使用されていません。
|
| トリプルDES |
- |
- |
Triple DES (DESede): 暗号化、復号化、暗号化と DES を 3 重に施す方式。
3 倍に拡張したキーの中に 3 つのサブキーが含まれる。全て同じサブキー
を使用すれば DES と互換性のある暗号化/復号化を行うことができる。
|
| Blowfish |
64bit |
32-448bit |
アルゴリズムに特許がとられていないため完全なライセンスフリーで利用
できる。デフォルトで 128bit 制限あり。
|
| AES |
128bit |
128, 192, 256bit |
Advanced Encryption Standard: DES に代わる暗号化アルゴリズムと
して 2001 年に米国暗号規格となった暗号化方式。デフォルトで 128bit 制限あり。
|
Java で使用できるアルゴリズムは
こちら
を参照。
共通鍵の作成
共通鍵は数十~数百ビットの短いバイナリから生成します。パスワードなどの可変長
データを鍵として使用する場合は一度 MD5 や SHA などでハッシュ化したものを使用
してください。
Java
// 共通鍵の作成
String password = "abc678iop";
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] key = md.digest(password.getBytes("UTF-8"));
SecretKey secretKey = new SecretKeySpec(key, 0, 16, "Blowfish");
システム的にキーを発生させて良いのであれば
KeyGenerator
を使用します。
Java
KeyGenerator generator = KeyGenerator.getInstance("Blowfish");
generator.init(128);
SecretKey secretKey = generator.generateKey();
// キーの保存
byte[] encoded = secretKey.getEncoded();
out.write(encoded);
// キーの復元
secretKey = new SecretKeySpec(encoded, "Blowfish");
暗号化と復号化
共通鍵方式での暗号化はアルゴリズム
を指定して取得した Cipher
を使用します。
// 暗号化するバイナリデータ
String clearText = "This is secret text.";
byte[] binary = clearText.getBytes("UTF-8");
// 暗号化の実行
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encrypted = cipher.doFinal(binary);
復号化は init() に渡すモードが異なるだけで暗号化とほとんど同じです。
// 復号化の実行
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] binary = cipher.doFinal(encrypted);
// 元の文字列を復元
String clearText = new String(binary, "UTF-8");