PHP使用mcrypt扩展进行AES-256加密解密及URL安全处理

一颗松果
一颗松果
发布时间:2026-10-13 | 5人浏览过
原创

在PHP开发中,为了保障参数传输安全,常需对敏感数据进行加密处理。本文将演示如何利用经典的 mcrypt 扩展结合AES-256算法实现字符串加解密,并解决因密文包含非URL安全字符而导致传输失败的问题。

环境准备与注意事项

重要提示: mcrypt 扩展自 PHP 7.1 起已被标记为过时,并在 PHP 7.2 及更高版本中被完全移除。若您的运行环境为现代PHP版本(PHP 8.x),建议迁移至 OpenSSL 或 sodium 扩展。本文代码仅适用于仍在使用 PHP 7.0 或更早版本(且安装了 mcrypt)的传统服务器环境,用于理解原理或在旧系统中维护代码。

该方案的核心逻辑如下:

  • 使用 MD5 哈希生成的密钥作为对称加密密钥。
  • 采用 Rijndael-256 (AES) 算法和 CBC 模式进行加密。
  • 对加密后的二进制数据进行 Base64 编码以转为文本。
  • 对 Base64 结果进行二次替换,确保字符串在 URL 中安全传递。

第1步:实现URL安全的Base64编码

标准的 Base64 编码包含 +、/ 和 = 符号,这些符号在 URL 查询参数中具有特殊含义或会被自动转义,可能导致解密时数据解析错误。因此需要编写辅助函数对其进行替换。

// 将标准 Base64 转换为 URL 安全格式
class CryptoHelper {
    public static function safe_b64encode($string) {
        $data = base64_encode($string);
        // 将 +/= 替换为 -_ 以便在 URL 中安全传输
        $data = str_replace(array('+','/','='),array('-','_',''),$data);
        return $data;
    }

    // 将 URL 安全格式还原为标准 Base64 并进行解码
    public static function safe_b64decode($string) {
        $data = str_replace(array('-','_'),array('+','/'),$string);
        // 计算缺失的填充字符
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }
}

第2步:执行加密操作

定义明文、密钥以及 IV(初始化向量)。为了确保安全性,密钥和 IV 通常由原始密钥通过 MD5 哈希固定长度得到。加密过程调用 mcrypt_encrypt 并使用我们上一步定义的编码函数处理结果。

$key = "secret_key";       // 用户自定义密钥
$string = "Sensitive Data"; // 需要加密的明文字符串

// 1. 生成固定的密钥字节 (32字节对应Rijndael-256)
$key_bytes = md5($key, true); 

// 2. 生成固定的IV字节 (通常为块大小大小)
$iv_bytes = md5(md5($key), true); 

// 3. 执行加密
$raw_crypted = mcrypt_encrypt(
    MCRYPT_RIJNDAEL_256,
    $key_bytes,
    $string,
    MCRYPT_MODE_CBC,
    $iv_bytes
);

// 4. 先Base64编码,再转换为URL安全字符串
$url_safe_encrypted = CryptoHelper::safe_b64encode($raw_crypted);

// 此时 $url_safe_encrypted 可直接放入 URL 参数中传递
echo "加密后的URL安全字符串: " . $url_safe_encrypted;

第3步:执行解密操作

接收端获取 URL 安全的加密字符串后,首先将其恢复为原始的二进制数据,然后使用相同的密钥和 IV 调用 mcrypt_decrypt 进行解密。最后注意去除解密结果中可能存在的空字符填充。

// 假设从 URL 接收到以下字符串
$url_received = "eJy...(模拟长字符串)"; 

// 1. 还原为标准Base64并解码为二进制
$raw_crypted_data = CryptoHelper::safe_b64decode($url_received);

// 2. 执行解密
// 注意:必须传入与加密时相同的 key_bytes 和 iv_bytes
$decrypted_raw = mcrypt_decrypt(
    MCRYPT_RIJNDAEL_256,
    $key_bytes,
    $raw_crypted_data,
    MCRYPT_MODE_CBC,
    $iv_bytes
);

// 3. 去除右侧可能的 \0 填充字符
$decrypted_string = rtrim($decrypted_raw, "\0");

echo "解密后的明文: " . $decrypted_string;

完成判断与排错

验证操作是否成功的标志是:加密后的 URL 安全字符串能够在浏览器地址栏或通过 API 请求正常传输而不报错;解密输出的内容与原明文完全一致,无乱码或缺失字符。

若解密出现错误或乱码,常见原因包括:

  1. Key 或 IV 不一致: 确保服务端生成 Key/IV 的逻辑与加密端完全相同。
  2. URL 编码问题: 虽然使用了安全替换,但在某些极端情况下,建议还是对最终字符串进行一次 urlencode() 处理后再拼入 URL,接收端需用 urldecode() 解析。
  3. 依赖缺失: 确认 PHP 环境已安装且启用 mcrypt.so 模块。

简要总结

通过组合使用 mcrypt 扩展、MD5 派生密钥策略以及自定义的 Base64 安全映射,可以在传统 PHP 环境中实现兼顾安全性与传输便利性的字符串加密方案。尽管 mcrypt 已停止维护,但该逻辑展示了密码学应用中对“编码”与“加密”两层解耦处理的典型思维。以上就是php基于mcrypt_encrypt和mcrypt_decrypt实现字符串加密解密方法的详细内容,更多关于php mcrypt加密的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表