一、前言。
先简单说下概念。加密分为以下几种:对称式加密算法、非对称式加密算法。这2个概念,这里就不细说了。简单说下,我们经常遇到的单向加密、双向加密。
单向加密,通常认为在单位有效时间内无法解密,属于单向加密的算法。双向加密就是可以同时解密。
所以,下面我们不会讲解对称加密算法、非对称加密算法了。只从是否可以有效时间内解密这个维度来讲。
二、单向加密算法。
2.1、MD5。
我们通常存储在数据库中的密码,是通过MD5加密的。有些接口请求,也是采用MD5进行签名再加密。
$str = 'ligang';
// c513dea20611d0ce598bf6f93fb4bed5
echo 'MD5加密后的字符串:'. MD5($str), PHP_EOL;
// len = 32
echo strlen(MD5($str));
md5加密后的字符串都是32位长度的,包含大小写字母、数字的字符串。
2.2、Sha1。
$str = 'ligang';
// 879e6a8cc4b8f0fca34b20faaa7f0edb6ac2f3bc
echo 'sha1加密后的字符串:'. sha1($str), PHP_EOL;
// len = 40
echo strlen(sha1($str));
我们可以看到sha1函数加密后的字符串长度更长,有40位。
更多关于PHP中sha1函数,请看:sha1散列函数详解
三、双向加密算法。
3.1、URL编码加密。
$str = 'ligang\124234';
// ligang%5C124234
echo 'url加密后的字符串:'. urlencode($str), PHP_EOL;
// ligang\124234
echo urldecode(urlencode($str));
我们可以看到,这个函数实际上对于普通的字符、数字,没有做什么处理。只是对于有关url的特殊字符串进行了编码。
所以,当我们传输给后端的参数里如果带有特殊字符,需要进行urlencode编码。
3.2、base64编码加密。
$data="I am king";
// SSBhbSBraW5n
echo base64_encode($data);
echo PHP_EOL;
// I am king
echo base64_decode(base64_encode($data));
这个编码函数通常用在对于长字符串、图片进行编码。可以反向解码。有点类似于压缩函数。
3.3、mcrypt_encrypt、mcrypt_decrypt加密、解密函数。
$cipher = MCRYPT_DES;
$modes = MCRYPT_MODE_ECB;
$key = 'F293N@#!';
$iv = mcrypt_create_iv(mcrypt_get_iv_size($cipher, $modes), MCRYPT_RAND);//初始化向量
$token = urlencode(mcrypt_encrypt($cipher, $key, $token, $modes,$iv)); //加密函数
PubFileLog::writeDebugInfo('加密密文:' . $token);
$str_decrypt = mcrypt_decrypt($cipher, $key, urldecode($token), $modes,$iv); //解密函数
PubFileLog::writeDebugInfo('解密密文:' . $str_decrypt);
以上,加密、解密函数的使用流程,在PHP5.6、PHP5.3中,都可以兼容使用。
注意:mcrypt_encrypt这个函数在PHP7.1中,已经删除了,具体请看:mcrypt_encrypt函数详解
Warning: This function has been DEPRECATED as of PHP 7.1.0. Relying on this function is highly discouraged.
5.6.0 Invalid key and iv sizes are no longer accepted. mcrypt_encrypt() will now throw a warning and return FALSE if the inputs are invalid. Previously keys and IVs were padded with '\0' bytes to the next valid size.
在5.6中,key的字符串长度不要超过8。
3.4、在PHP7.1中,3.3中加密函数已经没有了,现在怎么办呢。我们可以自己写。
下面的链接是开发微信公众号时,官方提供的加密解密函数的文档(百度云链接)。具体官方的链接已经难以找到了。
链接:进入百度网盘 密码:o4a7
其实,我们弄懂了几种非对称、对称加密算法后,可以自己写。
AES加密算法详解 、微信公众平台开发者中心安全模式消息体加解密实现
3.5、PHP7.1中,丢弃了mcrypt_encrypt,但是新加入了openssl_encrypt。这个扩展在某些低版本中也是存在的。
(1)简单应用,不使用iv的情况。
$textToEncrypt = "My super secret information.";
$encryptionMethod = "AES-256-CBC"; // AES is used by the U.S. gov't to encrypt top secret documents.
$secretHash = "25c6c7ff35b9979b151f2136cd13b0ff";
//To encrypt
$encryptedMessage = openssl_encrypt($textToEncrypt, $encryptionMethod, $secretHash);
//To Decrypt
$decryptedMessage = openssl_decrypt($encryptedMessage, $encryptionMethod, $secretHash);
//Result
echo "加密: $encryptedMessage \n原文: $decryptedMessage";
(2)使用iv的情况。iv有点类似于掩码,可以做到随机,每次都不一样。
$textToEncrypt = "My super secret information.";
$encryptionMethod = "AES-256-CBC"; // AES is used by the U.S. gov't to encrypt top secret documents.
$secretHash = "25c6c7ff35b9979b151f2136cd13b0ff";
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
//To encrypt
$encryptedMessage = openssl_encrypt($textToEncrypt, $encryptionMethod, $secretHash, 0, $iv);
$encryptedMessage = $iv . $encryptedMessage; // union and save to the db
//To Decrypt
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = substr($encryptedMessage, 0, $iv_size);
$decryptedMessage = openssl_decrypt(substr($encryptedMessage, $iv_size), $encryptionMethod, $secretHash, 0, $iv);
//Result
echo strlen($encryptedMessage), PHP_EOL;
echo "加密: $encryptedMessage \n原文: $decryptedMessage";
下面代码是我的写法,再存入数据库时最好是用base64_encode加密下,要不然'乱码'可能存不了数据库。
function myEncrypt($str, $hash='25c6c7ff35b9979b151f2136cd13b0ff', $method='AES-256-CBC') {
if ( !function_exists('openssl_encrypt') ) {
throw new RuntimeException('不存在openssl模块', PubReCode::$IllegalParametersError);
}
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
// To encrypt
$encrypted_message = openssl_encrypt($str, $method, $hash, 0, $iv);
// union and save to the db or file
$encrypted_message = $iv . $encrypted_message;
return base64_encode($encrypted_message);
}
function myDecrypt($str, $hash='25c6c7ff35b9979b151f2136cd13b0ff', $method='AES-256-CBC') {
if ( !function_exists('openssl_encrypt') ) {
throw new RuntimeException('不存在openssl模块', PubReCode::$IllegalParametersError);
}
$str = base64_decode($str);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = substr($str, 0, $iv_size);
// To Decrypt
$decrypted_message = openssl_decrypt(substr($str, $iv_size), $method, $hash, 0, $iv);
return $decrypted_message;
}
四、总结。
其实,严格意义上来讲,2.1、2.2、3.1、3.2都算不上是加密函数。
2.1、2.2严格以上来讲是属于散列(hash)函数。3.1、3.2属于一种编码手段。
真正意义上的加密解密函数,是必须是一对的,而且,有秘钥的情况下,是可以解密的。
只是这种秘钥分为两种情况,就是前言里说的,对称加密、非对称加密的区别。