しいしせねっとわーく
[Java]

Javaセキュリティと暗号

Java のセキュリティ系機能は、かなり充実してきました。

基本的なパッケージは java.security です。

その他、javax.crypto に暗号化的なアルゴリズム系の処理があります。

cryptoの中心的なのは Cipherクラスです。

トリプルDESの暗号処理を作りながら見てみる? エラー処理は省いていますが、かなり多めのエラー処理が必要です。

初期化から

byte[] key = パスワード的なもの (共通鍵?)
javax.crypto.spec.DESedeKeySpec keySpec;
javax.security.SeacretKey skey; // 共通鍵/対称鍵
javax.crypt.Cipher c;

// 鍵の初期設定 (共通鍵があらかじめある場合)
keySpec = javax.crypto.spec.DESedeKeySpec(key);
skey = SecretKeyFactory.getInstance("DESede").generateSecret(keySpec); // 共通鍵なのでSecretKeyFactory

// 鍵の初期設定 (共通鍵を新しく生成する場合)
skey = KeyGenerator.getInstance("DESede").generateKey();

// 暗号処理の初期設定
c = Cipher.getInstance("DESede");
c.init(Cipher.ENCRYPT_MODE, skey); // 暗号化モード

byte[] src = 元データ;
byte[] dst;
// src を dst に暗号化 1回で完了する場合
dst = c.doFinal(src);
// 複数回の場合
dst = c.update(src); // の繰り返し
dst = c.doFinal(src); // 最後

鍵にもCipherにも アルゴリズムの指定が必要です。c.init() ではパラメータが必要な場合もあります。DESede/CBC/PKCS5Padding などの場合はinit()で別のパラメータが必要なようで、まだわかりません。

// 復号化
c.init(Cipher.DECRYPT_MODE, skey); // モードを変えて初期化
src = c.doFinal(dst);

復号化もだいたいおなじです。DECRYPT_MODE になっているところだけが違います。

// 別鍵の暗号化
javax.security.SeacretKey skey2; // 別の鍵。
byte[] wrapkey;
c.init(Cipher.WRAP_MODE, skey);
wrapkey = c.wrap(skey2);

// 別鍵の復号化
c.init(Cipher.UNWRAP_MODE, skey);
skey2 = (SecretKey)c.unwrap(wrapkey, "DESede", Cipher.SECRET_KEY);

// 鍵を元に
keySpec = (DESedeKeySpec)SecretKeyFactory.getInstance("DESede").getKeySpec(skey, javax.crypto.spec.DESedeKeySpec.class);
key = keySpec.getKey();
// key = skey,getEncoded(); でも似ていることはできなくもなく

別の鍵を暗号化(ラップ)することもできます。同じ鍵をラップしても、使える鍵がないと元に戻せないので意味がないです。復元するときには鍵の種類も指定する必要があります。鍵を元にするのは、手順的にはこんなになりますが、skey2.getEncoded() でも変わらない場合もあります。場合もあるだけなので推奨はしません。トリプルDES等々の場合にはパリティビットなどがあるためか元の鍵と全く同じ状態に復元されるのではなく、同じ意味で使える鍵として復元されるようです。

こんなかんじです。

参考

[しいしせねっと]