ROUTE 3390

備忘録的な用途で書いていますが、どなたかの役に立つ事があれば嬉しいです。

ブロック暗号方式に挑戦。 Mcryptを使ってみた

McryptでCBCモードを使う機会があったのでメモ

use strict;
use warnings;

use Mcrypt qw(:ALGORITHMS :MODES);
use Digest::MD5 qw(md5_hex);

my $FILE_NAME = 'kkkkk.txt';
my $FILE = '/home/sasakure/' . $FILE_NAME;

my $td = Mcrypt->new(
    algorithm => Mcrypt::RIJNDAEL_128,
    mode => Mcrypt::CBC,
  );

warn "key length "   . $td->{KEY_SIZE}   . "\n";  # 16
warn "iv length "    . $td->{IV_SIZE}    . "\n";  # 16
warn "block length " . $td->{BLOCK_SIZE} . "\n";  # 16
# cipherによってそれぞれのサイズは変わってくる(確認してないけどたぶん)

my $key = md5_hex('mynameis'); # md5はとりあえず16バイトになるから使っているだけ
my $iv  = md5_hex('sasakure');

$td->init( pack('H*', $key), $iv);

open(my $fh, '<', $FILE) || die $!;
while ( read ( $fh, my $buf, 16 ) ) {
  # ブロックサイズに合わせて暗号化しないと警告が出る。
  my $residue = length($buf) % 16;
  my $padding_num = 16 - $residue;
  if ($residue > 0) {
    # 最後16バイトに満たない場合にパディングする。
    map { $buf .= $_ } pack('C*', map { 0x00 } (1..$padding_num));
  }
  print $td->encrypt( $buf );
}
close($fh);

exit;


そもそもブロック暗号方式というものに初めて触れたので、それもメモ


ブロック暗号について
暗号化したいデータを一定の長さに区切って暗号化します。


いくつかモードがあるけれど、僕が理解したのは下記2つ
ECBモード
1つの鍵で暗号化を行います。なので、鍵さえ知っていれば全てのブロックを複合化出来る事になります。
ランダムアクセスが出来る事も特徴の1つです。


CBCモード
Cipher Block Chainingの略です。チェーンという単語から何かが繋がっている感じがイメージ出来るかと思います。
鍵はECBと同様に1つですが、それだけではなく、隣のブロックの暗号化した結果を鍵と一緒に暗号化の材料とします。


暗号化したブロックと鍵を合わせて、新しい鍵を作ります。
その新しい鍵を使って次のブロックを暗号化します。
そこで暗号化されたブロックと、鍵をまた合わせて、更に次のブロックを暗号化します。


逆に複合化する時は隣のブロックが必要になります。
という事はECBのようにランダムアクセスは出来ません。
その代わりにECBよりも推測されづらくなるわけです。


ちなみに一番最初のブロックはiv(イニシャライズ ベクター)という値を使います。
一番最初のブロックは「暗号化された隣のブロック」が無いのでその代わりですね。