仕事で暗号化アルゴリズムについて調べて、ググっても「これだ!」って記事が見つからなかったのでメモ。
前置き
私はあまり暗号化アルゴリズムに詳しくない。
で、
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; }