网站首页 > 基础教程 正文
1. 介绍
1.1 介绍
福哥需要在php里使用AES加密解密功能,今天整理出来和大家分享一下。
早期的PHP实现AES借助的是mcrypt扩展,后来在PHP7之后就换成了openssl扩展来实现了。mcrypt版本代码比较复杂且需要自己实现PKCS7补位的逻辑,而openssl版本则默认使用了PKCS7补位不需要自己来编写代码实现了。
2. 通过openssl实现
2.1 安装openssl扩展
需要安装php扩展openssl,具体方法就不提供了,php的扩展的安装方式都一样,php7.1以上的版本支持了openssl模块。
2.2 加密解密对象
加密解密对象,默认 AES-256-CBC 方法。
class AES_Encrypt{
const BLOCK_SIZE = 32;
private string $method;
public function __construct(string $method = null){
if($method == null){
$method = "AES-256-CBC";
}
$this->method = $method;
}
public function pkcs7Pad($str){
$len = mb_strlen($str, '8bit');
$c = 16 - ($len % 16);
$str .= str_repeat(chr($c), $c);
return $str;
}
private function pkcs7Encode($text){
$text_length = strlen($text);
$amount_to_pad = AES_Encrypt::BLOCK_SIZE - ($text_length % AES_Encrypt::BLOCK_SIZE);
if ($amount_to_pad == 0) {
$amount_to_pad = AES_Encrypt::BLOCK_SIZE;
}
$pad_chr = chr($amount_to_pad);
$tmp = "";
for ($index = 0; $index < $amount_to_pad; $index++) {
$tmp .= $pad_chr;
}
return $text . $tmp;
}
private function pkcs7Decode($text){
$pad = ord(substr($text, -1));
if ($pad < 1 || $pad > 32) {
$pad = 0;
}
return substr($text, 0, (strlen($text) - $pad));
}
public function encrypt(string $data, string $key, string $iv):string {
$data = $this->pkcs7Encode($data);
$encrypted = openssl_encrypt($data, $this->method, $key,OPENSSL_ZERO_PADDING, $iv);
return $encrypted;
}
public function decrypt(string $data, string $key, string $iv):string {
$decrypted = openssl_decrypt($data, $this->method, $key,OPENSSL_ZERO_PADDING, $iv);
$data = $this->pkcs7Decode($decrypted);
return $data;
}
}
2.3 options
openssl_encrypt和openssl_decrypt的第三个参数是options,它有着很重要的作用,我们来了解一下。
- 0:默认模式,自动进行 pkcs7 补位,同时自动进行 base64 编码
- 1:OPENSSL_RAW_DATA,自动进行 pkcs7 补位, 但是不自动进行 base64 编码
- 2:OPENSSL_ZERO_PADDING,需要自己进行 pkcs7 补位,同时自动进行 base64 编码
3. 通过mcrypt实现
3.1 安装mcrypt扩展
需要安装php扩展mcrypt,具体方法就不提供了,php的扩展的安装方式都一样,php7.1以下的版本支持mcrypt模块。
3.2 加密解密对象
加密解密对象,默认 AES-128-CBC 方法。
class AES_Encrypt{
const BLOCK_SIZE = 32;
private $RIJNDAEL;
private $MODE;
public function __construct($method = null){
if($method == null){
$method = "AES-128-CBC";
}
$this->RIJNDAEL = null;
$this->MODE = null;
$this->methodArr = explode("-", $method);
switch($this->methodArr[1]){
case "128":
$this->RIJNDAEL = MCRYPT_RIJNDAEL_128;
break;
case "192":
$this->RIJNDAEL = MCRYPT_RIJNDAEL_192;
break;
case "256":
$this->RIJNDAEL = MCRYPT_RIJNDAEL_256;
break;
}
switch($this->methodArr[2]){
case "CBC":
$this->MODE = MCRYPT_MODE_CBC;
break;
case "CFB":
$this->MODE = MCRYPT_MODE_CFB;
break;
case "ECB":
$this->MODE = MCRYPT_MODE_ECB;
break;
case "NOFB":
$this->MODE = MCRYPT_MODE_NOFB;
break;
case "OFB":
$this->MODE = MCRYPT_MODE_OFB;
break;
case "STREAM":
$this->MODE = MCRYPT_MODE_STREAM;
break;
}
if($this->RIJNDAEL == null || $this->MODE == null){
throw new Exception("invalid RIJNDAEL or MODE about '". $method. "'", 2000100);
}
}
public function pkcs7Pad($str){
$len = mb_strlen($str, '8bit');
$c = 16 - ($len % 16);
$str .= str_repeat(chr($c), $c);
return $str;
}
private function pkcs7Encode($text){
$text_length = strlen($text);
$amount_to_pad = AES_Encrypt::BLOCK_SIZE - ($text_length % AES_Encrypt::BLOCK_SIZE);
if ($amount_to_pad == 0) {
$amount_to_pad = AES_Encrypt::BLOCK_SIZE;
}
$pad_chr = chr($amount_to_pad);
$tmp = "";
for ($index = 0; $index < $amount_to_pad; $index++) {
$tmp .= $pad_chr;
}
return $text . $tmp;
}
private function pkcs7Decode($text){
$pad = ord(substr($text, -1));
if ($pad < 1 || $pad > 32) {
$pad = 0;
}
return substr($text, 0, (strlen($text) - $pad));
}
public function encrypt($data, $key, $iv){
$data = $this->pkcs7Encode($data);
$encrypted = mcrypt_encrypt($this->RIJNDAEL, $key, $data, $this->MODE, $iv);
$based_encrypted = base64_encode($encrypted);
return $based_encrypted;
}
public function decrypt($data, $key, $iv){
$data = base64_decode($data);
$encrypted = mcrypt_decrypt($this->RIJNDAEL, $key, $data, $this->MODE, $iv);
$encrypted = $this->pkcs7Decode($encrypted);
return $encrypted;
}
}
4. 使用
使用AES加密需要原数据、AES私钥、令牌,下面给出一个例子。
注意:在openssl版本里的AES-256-CBC方法对应mcrypt版本里的AES-128-CBC,也是微信公众号服务器接口使用的AES算法的方法
4.1 示例
准备一个字符串,加密后再解密,最后如果和原字符串相同,证明函数工作正常。
$dataOrg = "我是福哥,I like coding!!!";
$AESKey = "rN6LfP9qbILPabc938IixdFds3s5ksIqjcPyYxOPx4v";
$iv = "";
// 初始化
$myAES_Encrypt = new AES_Encrypt();
// 加密字符串
$dataEncrypted = $myAES_Encrypt->encrypt($dataOrg, $AESKey, $iv);
// 解密字符串
$dataDecrypted = $myAES_Encrypt->decrypt($dataEncrypted, $AESKey, $iv);
// 比较
var_dump($dataOrg == $dataDecrypted);
5. 总结
福哥今天给出了两个使用PHP实现AES的加密算法功能的方法,新版本的openssl效率更高、代码更简单,福哥推荐这种方法~~
https://m.tongfu.net/home/35/blog/512693.html
猜你喜欢
- 2024-10-12 Linux库函数调用工具—ltrace命令
- 2024-10-12 C/C++恶意代码盘点(二):后门丨文件监控丨自删除功能
- 2024-10-12 C语言文件的随机读写、块读写、行、字符读写以及格式化输入输出
- 2024-10-12 C/C++恶意代码盘点(一):进程遍历丨木马病毒丨密码记录
- 2024-10-12 C/C++连接MySql数据库使用总结 c++连接数据库sqlserver
- 2024-10-12 MySQL:字符集问题 mysql字符集设置命令
- 2024-10-12 CAD常用语言函数 cad常用语言函数有哪些
- 2024-10-12 PHP压缩ZIP中文注释乱码问题解决办法
- 2024-10-12 Android Dalvik 使用详解 android dac
- 2024-10-12 C++|整型的最值、上溢、下溢、截断、类型提升和转换
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)