目录

AES算法(十二) PHP 实战

本篇将对之前所述的 AES 算法基于 PHP 语言做实战讲解,由于 ECB 工作模式相对其他工作模式安全性低(不推荐使用),本文将不对其进行展示,如在工作中确实需要使用,请自行实现。由于篇幅限制,所有的演示代码将只展示关键步骤,如果想要直接上手使用,请移步:https://github.com/aurthurxlc/php-utils 。

本示例仅演示了 PHP7+ 的加密解密方式,PHP 5.6 及以下请参考理论知识自行查找相关函数实现。

PHP7+ AES 加解密要点

  • 使用 openssl_encrypt() 函数实现加密,官方文档地址:https://www.php.net/manual/zh/function.openssl-encrypt.php
  • 使用 openssl_decrypt() 函数实现解密,官方文档地址:https://www.php.net/manual/zh/function.openssl-decrypt.php
  • 官方文档中还有很多其他的 openssl 函数,可以自行查阅
  • 如果对某些参数有看不明白的地方,请先查看一下前面的理论篇章

实战演示

加密工具类代码如下:


class AESUtil
{
    /**
     * PHP 7+ 适用
     *
     * $cipher 加密方法,可选参数:aes-{keySize}-{aesMode},其中 keySize 可选 128、192、256(需要与 $key 长度对应),aesMode 可选:cbc、cfb、ofb...
     * $key 密钥
     */
    private $cipher;
    private $key;

    function __construct($cipher, $key)
    {
        $this->cipher = $cipher;
        $this->key = $key;
    }

    /**
     * @param $plainText string 待加密明文字符串
     * @param $iv string 初始向量
     */
    public function encryptWithIV(string $plainText, string $iv)
    {
        // OPENSSL_RAW_DATA 默认采用 PKCS#7 数据填充模式
        return openssl_encrypt($plainText, $this->cipher, $this->key, OPENSSL_RAW_DATA, $iv);
    }

    /**
     * @param $cipherText string 待解密明文字符串
     * @param $iv string 初始向量
     */
    public function decryptWithIV(string $cipherText, string $iv)
    {
        // OPENSSL_RAW_DATA 默认采用 PKCS#7 数据填充模式
        return openssl_decrypt($cipherText, $this->cipher, $this->key, OPENSSL_RAW_DATA, $iv);
    }
}

加密解密函数调用示例:

print PHP_EOL . "======== 创建密钥及 IV 进行加密案例 ========" . PHP_EOL;
$key = AESTool::generateKey(16);
$iv = AESTool::generateIV();
$pText = "创建密钥及 IV 进行加密案例";

print "key: " . bin2hex($key) . PHP_EOL;
print "iv: " . bin2hex($iv) . PHP_EOL;
print "pText: " . $pText . PHP_EOL;

$aes = new AESUtil("aes-128-cbc", $key);

$cText = bin2hex($aes->encryptWithIV($pText, $iv));
print "加密后: " . $cText . PHP_EOL;

$deText = $aes->decryptWithIV(hex2bin($cText), $iv);
print "解密后: " . $deText . PHP_EOL;

输出信息如下:

======== PHP 7+ 创建密钥及 IV 进行加密案例 ========
key: 0b6a97084132430fd61d4e4261ef2331
iv: 25509492f298179cff3f6f9dd4105b8c
pText: PHP 7+ 创建密钥及 IV 进行加密案例
加密后: 5a1ce8610f4e85652001f090f76d5394d0fb4c495b823f72cc79fda927a8c2c67380cc49b3534eba0d9893f08bba768a
解密后: PHP 7+ 创建密钥及 IV 进行加密案例

现实中常见的加密需求可能是需要多平台联动的,这里就以之前的 Java 实战篇所使用的参数相同为基础,来看看我们是否能得到相同的加密字符串,并且同样也能解密出来:

print PHP_EOL . "======== 测试跟 Java 加密后数据是否一致 ========" . PHP_EOL;
print "======== 期望加密后数据是:e8aa678c21aa028988cd74ee2835344519014a4e9365cb8dda7cf24bfe95dfdf0e047cf979587b02500ccad15415b1c3 ========" . PHP_EOL;
// 测试跟 Java 加密是否一致
$key = hex2bin('e43ee68382dc550fbd1d329486febdd4');
$iv = hex2bin('ddffc44a93503156abb36e9bbca876f8');
$pText = "AES 算法基于 Java 实战演示";

print "key: " . bin2hex($key) . PHP_EOL;
print "iv: " . bin2hex($iv) . PHP_EOL;
print "pText: " . $pText . PHP_EOL;

$aes = new AESUtil("aes-128-cbc", $key);

$cText = bin2hex($aes->encryptWithIV($pText, $iv));
print "加密后: " . $cText . PHP_EOL;

$deText = $aes->decryptWithIV(hex2bin($cText), $iv);
print "解密后: " . $deText . PHP_EOL;

输出信息如下:

======== 测试跟 Java 加密后数据是否一致 ========
======== 期望加密后数据是:e8aa678c21aa028988cd74ee2835344519014a4e9365cb8dda7cf24bfe95dfdf0e047cf979587b02500ccad15415b1c3 ========
key: e43ee68382dc550fbd1d329486febdd4
iv: ddffc44a93503156abb36e9bbca876f8
pText: AES 算法基于 Java 实战演示
加密后: e8aa678c21aa028988cd74ee2835344519014a4e9365cb8dda7cf24bfe95dfdf0e047cf979587b02500ccad15415b1c3
解密后: AES 算法基于 Java 实战演示

其他

可以通过函数 openssl_get_cipher_methods() 查看 PHP 支持哪些加密算法:

print PHP_EOL . "======== 支持的加密算法 ========" . PHP_EOL;
print implode(PHP_EOL,openssl_get_cipher_methods());

输出:
======== 支持的加密算法 ========
aes-128-cbc
aes-128-cbc-hmac-sha1
aes-128-cbc-hmac-sha256
aes-128-ccm
aes-128-cfb
aes-128-cfb1
aes-128-cfb8
aes-128-ctr
aes-128-ecb
aes-128-gcm
aes-128-ocb
aes-128-ofb
aes-128-xts
aes-192-cbc
aes-192-ccm
aes-192-cfb
aes-192-cfb1
aes-192-cfb8
aes-192-ctr
aes-192-ecb
aes-192-gcm
aes-192-ocb
aes-192-ofb
aes-256-cbc
aes-256-cbc-hmac-sha1
aes-256-cbc-hmac-sha256
aes-256-ccm
aes-256-cfb
aes-256-cfb1
aes-256-cfb8
aes-256-ctr
aes-256-ecb
aes-256-gcm
aes-256-ocb
aes-256-ofb
aes-256-xts
// ... 还有其他很多非 AES 算法的函数