仕事で暗号化アルゴリズムについて調べて、ググっても「これだ!」って記事が見つからなかったのでメモ。
前置き
私はあまり暗号化アルゴリズムに詳しくない。
で、
JavaでTriple DESのCBCモードで暗号化されたデータを復号化・・・と書いてあるように読める仕様書をもらったんだけど、その仕様書にCBCモードで暗号化する手順も一緒に載ってて、
「ん?Cipher.getInstanceに”DESede/CBC”指定するのとなにか違うの?」と疑問に思ったので、実際に手作業でCBC処理した結果と比較してみた。
まぁつまり、Cipher.getInstanceに”DESede/CBC”指定して暗号化した結果と、前の暗号化ブロックとXORしてDESede/ECBで暗号化した結果を次のブロックとXORして・・・っていう、仕様書に書いてあったCBCの暗号化手順の結果が同じかどうかの確認をしたかったのです。
仕様書の書き方が分かり難かっただけなのです。
前提
暗号アルゴリズムはTripleDES(DESede)。
言語はJavaで、Cipherクラスを使用する。
初期ベクタはオール0の8byte
手作業時に使用するブロック暗号モードはECB。
ブロックモードについては下記サイトが非常に分かりやすかった。
http://www.triplefalcon.com/Lexicon/Encryption-Block-Mode-1.htm
方法と結果
下記コードで同じデータを暗号化して、内容を比較する。
結果、一致した。
まぁそうなるわな。
2×3と2を3回足した結果を比較するようなもんなんだけど。
でもこれで安心してCBCを指定して使えます。
//DESede/CBCで暗号化
public static encDESedeCBC(byte[] src, SecretKey key, int cryptType) throws Exception {
Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(new byte[8]));
byte[] data = src;
int padSize = src.length % 8;
//8の倍数になるようにパディング
if(padSize > 0)
{
byte[] baPad = new byte[8-padSize];
data = ByteUtil.margeBytes(src, baPad);
}
return cipher.doFinal(data);
}
//手作業でCBC
public static byte[] encDESedeCBCwithECB(byte[] src, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] data=src;
int padSize = src.length % 8;
//8の倍数になるようにパディング
if(padSize > 0)
{
byte[] baPad = new byte[8-padSize];
data = ByteUtil.margeBytes(src, baPad);
}
ByteBuffer bs = ByteBuffer.wrap(data);
ByteBuffer bd = ByteBuffer.allocate(data.length);
bs.limit(data.length);
byte[] oct = new byte[8];
byte[] dt = new byte[8];
while(bs.remaining() > 0)
{
bs.get(oct);
//XORを取る
for(int i=0; i < 8; i++)
{
dt[i] = (byte)(dt[i] ^ oct[i]);
}
dt = cipher.doFinal(dt);
bd.put(dt);
}
bd.flip();
byte[] dest = new byte[bd.limit()];
bd.get(dest);
return dest;
}