今天我们学习PHP中的一个过时的扩展Mcrypt。在PHP7之前,这个扩展是和PHP安装包一起发布的,现在新版本的PHP中已经没有了。如果需要使用这个扩展,需要单独安装,使用时会报outdatedwarning。因此,我们在学习使用这些函数时,需要使用@来抑制错误信息。当然,这组扩展的弃用警告是因为PHP更喜欢使用OpenSSL来处理类似的加密功能。模块与算法Mcrypt主要使用Mcrypt工具进行加密操作,所以在CentOS或者其他操作系统中,我们需要安装libmcrypt-devel才能使用这个扩展。如果无法在yum中安装,直接更新yum源即可。Mcrypt包含许多模块和算法。算法不用解释,就是加密数据的方式。模块包括CBC、OFB、CFB、ECB,是一系列分组流加密模式。有推荐模块和安全模块。具体区分可以参考相关资料。这里我们先看看我们的环境支持的模块和算法。$algorithms=@mcrypt_list_algorithms();print_r($algorithms);//数组//(//[0]=>cast-128//[1]=>gost//[2]=>rijndael-128//[3]=>twofish//[4]=>arcfour//[5]=>cast-256//[6]=>loki97//[7]=>rijndael-192//[8]=>saferplus//[9]=>唤醒//[10]=>blowfish-compat//[11]=>des//[12]=>rijndael-256//[13]=>serpent//[14]=>xtea//[15]=>blowfish//[16]=>enigma//[17]=>rc2//[18]=>tripledes//)$modes=@mcrypt_list_modes();print_r($modes);//数组//(//[0]=>cbc//[1]=>cfb//[2]=>ctr//[3]=>ecb//[4]=>ncfb//[5]=>nofb//[6]=>ofb//[7]=>stream//)mcrypt_list_algorithms()函数可以得到当前环境下所有支持的Mcrypt算法。而mcrypt_list_modes()打印出当前环境下所有支持的模块。注意,在某些版本的PHP或某些系统中,这些内容会有所不同。在使用Mcrypt相关的加密能力时,这两者是配合使用的。因此,我们有必要在需要运行Mcrypt的环境中预先确定当前环境支持的模块和算法。加密和解密数据$key=hash('sha256','secretkey',true);$input=json_encode(['id'=>1,'data'=>'测试mcrypt!']);$td=@mcrypt_module_open('rijndael-128','','cbc','');$iv=@mcrypt_create_iv(mcrypt_enc_get_iv_size($td),MCRYPT_DEV_URANDOM);@mcrypt_generic_init($td,$key,$iv);$encrypted_data=@mcrypt_generic($td,$input);@mcrypt_generic_deinit($td);@mcrypt_module_close($td);echo$encrypted_data,PHP_EOL;//??I$??3??gE???u(??9n??????//p??>P$td=@mcrypt_module_open('rijndael-128','','cbc','');@mcrypt_generic_init($td,$key,$iv);$data=@mdecrypt_generic($td,$encrypted_data);echo$data,PHP_EOL;//{"id":1,"data":"测试mcrypt!"}@mcrypt_generic_deinit($td);@mcrypt_module_close($td);代码很多,比较乱,我们一一来看。首先,我们确定一个加密密钥,然后输入的就是我们要加密的数据。比如我们要加密一个json数据,这个key其实可以是一个字符串,但是我们这里还需要对key进行一个hash处理,这个hash相关的内容我们在前面已经详细解释过了文章。下一步是使用mcrypt_module_open()打开一个加密模块句柄,这里我们使用rijndael-128算法和cbc模块。然后使用mcrypt_create_iv()创建一个iv,它是一个初始化向量。初始化向量的值根据密码算法而变化。最基本的要求是“唯一性”,即同一个key不会重复使用同一个初始化向量。这个特性无论在块加密还是流加密中都非常重要。相信大家如果做过微信或者支付宝相关的接口通信,在解密验证数据的时候肯定会看到这个iv属性。使用mcrypt_generic()生成加密结果,使用mcrypt_generic_deinit()结束生成的初始化,最后使用mcrypt_module_close()关闭加密模块句柄。这样就完成了一套Mcrypt加密过程。同样,解密过程与加密过程类似,只是我们使用mdecrypt_generic()函数进行解密。加密和解密数据的另一种方法。上述加密过程非常繁琐复杂。其实Mcrypt还提供了更简单的加密功能。$string='测试MCrypt2';$algorithm='rijndael-128';$key=md5("我的密码",true);$iv_length=@mcrypt_get_iv_size($algorithm,MCRYPT_MODE_CBC);$iv=@mcrypt_create_iv($iv_length,MCRYPT_RAND);$encrypted=@mcrypt_encrypt($algorithm,$key,$string,MCRYPT_MODE_CBC,$iv);$result=@mcrypt_decrypt($algorithm,$key,$encrypted,MCRYPT_MODE_CBC,$iv);echo$encrypted,PHP_EOL;//\?`?U??Uf)?Yecho$result,PHP_EOL;//测试MCrypt2我们还需要准备待加密的数据,算法,密钥,iv向量。那么直接使用mcrypt_encrypt()和mcrypt_decrypt()进行加密/解密,是不是方便多了?总结与Hash相比,Mcrypt是对称加密的一种可解密形式。关于什么是对称加密和非对称加密,我们会在OpenSSL的扩展学习中详细讲解,而Hash加密是一种单向加密形式,无法通过对加密数据进行逆向计算得到原始数据。它们都有不同的应用场景,但是正如PHP提醒的那样,Mcrypt已经是一个废弃的扩展,所以我们这里只是简单地进行了加解密测试。如果你有好用的小伙伴,可以按照手册进行更深入的学习。测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/202007/source/PHP%E7%9A%84Mcrypt%E5%8A%A0%E5%AF%86%E6%89%A9%E5%B1%95%E7%9F%A5%E8%AF%86%E4%BA%86%E8%A7%A3.php参考文档:https://www.php.net/manual/zh/book.mcrypt.phphttps://ask.csdn.net/questions/700696各媒体平台均可搜索【硬核项目经理】
