暗号化処理のCBCブロック暗号モード

仕事で暗号化アルゴリズムについて調べて、ググっても「これだ!」って記事が見つからなかったのでメモ。

前置き

私はあまり暗号化アルゴリズムに詳しくない。
で、
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;
    }

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

認証のために問題を解いて下さい * Time limit is exhausted. Please reload CAPTCHA.