使用openssl_encrypt()和openssl_decrypt()实现加密和解密功能

<?php
declare(strict_types=1);
ini_set('display_errors', 'On');
error_reporting(-1);

/**
 * 加解密工具类
 */
class Cipher
{
    private const KEY = 'www.manong.life'; // 加密或解密所需的密钥

    private const METHOD = 'AES-128-CBC-HMAC-SHA256'; // 加密算法,可通过openssl_get_cipher_methods()获取可用的加密算法

    private const OPTIONS = OPENSSL_RAW_DATA; // 选项,可选值:OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING

    /**
     * 加密函数
     *
     * @param string $plaintext 明文
     * @return string|false 密文,若加密失败则返回false
     */
    public static function encrypt(string $plaintext): string|false
    {
        $length = self::opensslCipherIvLength();

        $ok = true;

        try {
            $iv = random_bytes($length);
        } catch (Exception) {
            $ok = false;
        }

        if ($ok) {
            $ciphertext = openssl_encrypt($plaintext, self::METHOD, self::KEY, self::OPTIONS, $iv); // 加密
        } else {
            $ciphertext = false;
        }

        if (is_string($ciphertext)) {
            // 说明①:加密函数openssl_encrypt()返回的是一堆乱码,故对其进行base64编码方便传输和保存。
            // 说明②:初始化向量{$iv}是解密函数openssl_decrypt()的必填参数,故将其附加在密文后。
            $ciphertext = base64_encode("$ciphertext$iv");
        }

        return $ciphertext;
    }

    /**
     * 解密函数
     *
     * @param string $ciphertext 密文
     * @return string|false 明文,若解密失败则返回false
     */
    public static function decrypt(string $ciphertext): string|false
    {
        $length = self::opensslCipherIvLength();

        $plaintext = false;

        $ciphertext = base64_decode($ciphertext, true);
        if (is_string($ciphertext)) {
            $iv = substr($ciphertext, -1 * $length); // 提取出初始化向量部分
            $ciphertext = substr($ciphertext, 0, strlen($ciphertext) - $length); // 提取出密文部分
            $plaintext = openssl_decrypt($ciphertext, self::METHOD, self::KEY, self::OPTIONS, $iv); // 解密
        }

        return $plaintext;
    }

    /**
     * 根据使用的加密算法计算出初始化向量的长度,即加解密时用到的$iv的strlen()值
     *
     * @return int 初始化向量的长度
     */
    private static function opensslCipherIvLength(): int
    {
        return openssl_cipher_iv_length(self::METHOD);
    }
}

$data = 'PHP是世界上最好の语言'; // 要加密的数据(明文)

$ciphertext = Cipher::encrypt($data); // 加密(每次加密得到的密文都是不同的)
echo "加密结果:$ciphertext" . PHP_EOL;

$plaintext = Cipher::decrypt($ciphertext); // 解密
echo "解密结果:$plaintext" . PHP_EOL;

// 加密结果:2CXJBnlmq1i2VSn8bIypKwpSffdde3Gn8UC1gAFRwfA4Apvfy1GixZBrUpYi3Kzl
// 解密结果:PHP是世界上最好の语言

Copyright © 2024 码农人生. All Rights Reserved