平文の暗号化 – 暗号処理の流れ

### 暗号化の流れ
(1)ブロック長に満たない部分をパディング方式で補完する
(2)アルゴリズムに対応したブロック長に分割する
※この時の分割ルールを決めるのが暗号利用モード
※分割モードによっては初期値が必要で、それがIV(初期ベクトル)
(3)暗号鍵を用いてアルゴリズムで暗号化
(4)分割されたデータを結合

複合化の流れ
(1)アルゴリズムに対応したブロック長に分割する
(2)暗号鍵を用いてアルゴリズムで複合化する
(3)暗号利用モードを元に分割されたデータを結合する
※分割モードによっては初期値が必要で、これがIV(初期化ベクトル)
(4)補完されたパディングをパディング方式で除去する

ブロック暗号では、ブロック長、秘密鍵、暗号アルゴリズム、暗号利用モード、パディング方式、IV(初期化ベクトル)のキーワードが重要
使用できる暗号化アルゴリズムは組み込まれているライブラリに依存
暗号利用モードにはECB, CBD, OFB, CFB
パディング方式はZeroBytePadding, パディング不要な状態であればZeroBytePaddingは何もしないのでPKCS#5 Paddingなどは独自に実装することができる。NoPaddingはできない

$ sudo apt install php-dev libmcrypt-dev php-pear
$ sudo pecl channel-update pecl.php.net
$ sudo pecl install mcrypt-1.0.1

function cipher_encrypt($input, $key){
  // 指定した暗号のブロックサイズを得る
  $size = mcrypt_get_block_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
  // PKCS5Padブロック長に満たないサイズを埋める
  $input = pkcs5_pad($input, $size);
  // 使用するアルゴリズムおよびモードのモジュールをオープンする
  $td = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_ECB, '');
  // オープンされたアルゴリズムのIVの大きさを返す
  $ivsize = mcrypt_enc_get_iv_size($td);
  // MCRYPT_RANDの初期化を行う
  srand();

  // 乱数ソースから初期化ベクトル(IV)を生成する
  // ECB以外では複合にIVが必要
  // ECBではIVは使用されないがIVがないとエラーが出る
  $iv = mcrypt_create_iv($ivsize, MCRYPT_RAND);
  // 暗号化に必要な全てのバッファを初期化
  mycrypt_generic_init($td, $key, $iv);
  // データを暗号化
  $data = mcrypt_generic($td, $input);
  // 暗号化モジュールを修了する
  mycrypt_generic_deinit($td);
  // mcryptモジュールを閉じる
  mcrypt_module_close($td);
  return $data;
}

// 複合化を行う
function cipher_decrypt($input, $key){
  // 指定した暗号のブロックサイズを得る
  $size = mcrypt_get_block_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
  // 使用するアルゴリズムおよびモジュールをオープンする
  $td = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_ECB, '');
  // オープンされたアルゴリズムのIVの大きさを返す
  $ivsize = mcrypt_enc_get_iv_size($td);
  // MCRYPT_RANDの初期化を行う
  srand();

  // 乱数ソースから初期化ベクトル(IV)を生成する
  // ECB以外では複合にIVが必要
  // ECBではIVは使用されないがIVがないとエラーが出る
  $iv = mcrypt_create_iv($ivsize, MCRYPT_RAND);
  // 暗号化に必要な全てのバッファを初期化する
  mcrypt_generic_init($td, $key, $iv);
  // データを複合する
  $data = mdecrypt_generic($td, $input);
  // 暗号化モジュールを修了
  mcrypt_generic_deinit($td);
  // mcryptモジュールを閉じる
  mcrypt_module_close($td);
  // PKCS5Padding埋められたバイト値を除く
  $data = pkcs5_unpad($data, $size);
  return $data;
}

// PKCS5Padding
// ブロック長に満たないサイズを埋める
function pkcs5_pad($text, $blocksize){
  $pad = $blocksize - (strlen($text) % $blocksize);
  return $text . str_repeat(chr($pad), $pad);
}

// PKCS5Padding
// 埋められたバイト値を除く
function pkcs5_unpad($text){
  $pad = ord($text{strlen($text)-1});
  if($pad > strlen($text)) return false;
  if(strspn($text, chr($pad), strlen($text) - $pad)!= $pad) return false;
  return substr($text, 0, -1 * $pad);
}

// 暗号化例
$data = "この文字を暗号化する";
$key = "ABCDEF";

echo "元データ:" . $data;
echo "<br>";
$encrypt = cipher_encrypt($data, $key);
echo "暗号化されたデータ:". $encrypt;
echo "<br>";
$decrypt = cipher_decrypt($encrypt,$key);
echo "複合化されたデータ:". $decrypt;

pecl/mcrypt requires PHP (version >= 7.2.0, version <= 7.3.0, excluded versions: 7.3.0), installed version is 7.4.3-4ubuntu2.18 No valid packages found install failed 仕組みはわかったけど、mcryptではなく、openssl_ecnrypt出ないと駄目やな