坑货libmcrypt

来源:互联网 发布:云计算优缺点 编辑:程序博客网 时间:2024/04/28 02:03

今天接触的了一个php版本的 aes-128-cbc

en/de原文如下


class SecretUtil {    public static $hex_iv = '00000000000000000000000000000000'; # converted JAVA byte code in to HEX and placed it here    //public static $hex_iv = 'EDD80600A09CFBCB4B152C2B2FAAA237'; # converted JAVA byte code in to HEX and placed it here    public static $key='my key';    public static function setKey(){        self::$key = hash('sha256', self::$key, true);    }    public static function encrypt($str){        self::setKey();        $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');        mcrypt_generic_init($td, self::$key, self::hexToStr(self::$hex_iv));        $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);        $pad = $block - (strlen($str) % $block);        $str .= str_repeat(chr($pad), $pad);        $encrypted = mcrypt_generic($td, $str);        mcrypt_generic_deinit($td);        mcrypt_module_close($td);        return base64_encode($encrypted);    }}


看起来好简单的样子。可是我发现怎么也还原不了,无头绪了半天。。。。。。真的半天,直到发现libmcrypt的确是个坑货 


If you're writing code to encrypt/encrypt data in 2015, you should use openssl_encrypt() and openssl_decrypt(). The underlying library (libmcrypt) has been abandoned since 2007, and performs far worse than OpenSSL (which leverages AES-NI on modern processors and is cache-timing safe).


Also, MCRYPT_RIJNDAEL_256 is not AES-256, it's a different variant of the Rijndael block cipher. If you want AES-256 in mcrypt, you have to use MCRYPT_RIJNDAEL_128 with a 32-byte key. OpenSSL makes it more obvious which mode you are using (i.e. 'aes-128-cbc' vs 'aes-256-ctr').


那么好吧。事情就简单了
 self::$key = hash('sha256', self::$key, true);
 这个坑就填了。原来的加解密其实是使用的aes-256-cbc
 第二个坑容易找  $pad = $block - (strlen($str) % $block);
 正好加密内容的长度为 block_size,也就是16时,这家伙会直接追加16个0x10,这个比较有个性。所以使用openssl时也不能使用padding了,得自己来
 我们来试试对应的ruby实现

#encoding:utf-8require 'openssl'require 'base64'key=OpenSSL::Digest::SHA256.digest('my key') %w(AES-128-CBC AES-256-CBC).each do |flavour|string ='12345678901234561234567890123456asfg' c = OpenSSL::Cipher::Cipher .new flavour   pad= c.block_size - string.length % c.block_size    str=string    str<<  Array.new(pad){|x| x=pad}.pack('c*') #unless  pad == 16   puts "string pad #{pad} to #{str.length}: #{str.unpack('H*')[0]}"    c.encryptc.padding=0c.key = keyiv=Array.new(16,0).pack('c*')c.iv=iv enc = c.update(str) + c.final    en_str=Base64.strict_encode64(enc)puts "#{flavour} encrypt #{string} \r\n#{en_str}"#解密过程d=  OpenSSL::Cipher::Cipher .new flavourd.decryptd.padding=0d.key=keyd.iv=ivdec=Base64.strict_decode64(en_str)de_str=d.update(dec)+ d.finalputs "#{flavour} decrypt #{en_str} \r\n#{de_str.unpack('H*')[0]}"#前面填的坑要自己来埋,去掉最后的padding个padding字符last_char=de_str[-1,1].ord padding=Array.new(last_char,last_char).pack('c*')  puts "padding #{padding.unpack('H*')[0] }"de_str=de_str[0,de_str.length-padding.length] if de_str.end_with?(padding) puts "drop padding #{de_str} \r\nhex:#{de_str.unpack('H*')[0]}"end 



0 0