You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP 7中mcrypt加解密函数无法运行,IV生成代码疑有误怎么办?

解决PHP 7中Blowfish加解密函数失效的问题

首先,你的代码最大的问题是**mcrypt扩展在PHP 7.1及以上版本已经被官方弃用,PHP 7.2直接移除了这个扩展**——这就是函数无法正常运行的核心原因,哪怕没有抛出警告,底层的加密解密逻辑已经无法执行。另外你怀疑的IV生成部分确实也存在细节问题,下面给你两种可行的解决方案:

方案一:迁移到OpenSSL扩展(推荐,符合PHP现代标准)

OpenSSL是PHP官方主推的加密扩展,稳定性、安全性和兼容性都远优于已废弃的mcrypt。下面是适配Blowfish(对应OpenSSL的BF-CFB模式)的加解密实现:

function encrypt_data($key, $plain_text) {
    $plain_text = trim($plain_text);
    // 获取Blowfish CFB模式下的标准IV长度(固定8字节)
    $iv_length = openssl_cipher_iv_length('BF-CFB');
    // 生成安全的随机IV(不要从key的哈希值生成,避免IV可预测的风险)
    $iv = openssl_random_pseudo_bytes($iv_length);
    
    // 执行加密,使用RAW_DATA模式保证输出是二进制原始内容
    $cipher_text = openssl_encrypt(
        $plain_text,
        'BF-CFB',
        $key,
        OPENSSL_RAW_DATA,
        $iv
    );
    
    // 将IV和密文拼接后再base64编码(IV不需要保密,但解密时必须和加密时一致)
    return base64_encode($iv . $cipher_text);
}

function decrypt_data($key, $cipher_text_base64) {
    $cipher_text_raw = base64_decode($cipher_text_base64);
    $iv_length = openssl_cipher_iv_length('BF-CFB');
    // 从编码内容中拆分出IV和实际密文
    $iv = substr($cipher_text_raw, 0, $iv_length);
    $cipher_text = substr($cipher_text_raw, $iv_length);
    
    // 执行解密,参数和加密时保持一致
    $plain_text = openssl_decrypt(
        $cipher_text,
        'BF-CFB',
        $key,
        OPENSSL_RAW_DATA,
        $iv
    );
    
    return trim($plain_text);
}

关键改进点:

  • 用openssl_random_pseudo_bytes生成安全的随机IV,避免原方案中IV可预测的安全隐患
  • 将IV与密文一起存储,解密时再拆分,确保加密解密使用完全一致的IV
  • 采用PHP官方长期支持的OpenSSL扩展,兼容PHP7+及所有后续版本

方案二:修复原mcrypt代码(仅兼容PHP7.0及以下,不推荐)

如果你暂时只能在PHP7.0环境下运行代码,可以调整IV的生成逻辑来修复问题:

function encrypt_data($key, $plain_text) {
    $plain_text = trim($plain_text);
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CFB);
    // 注意md5的第二个参数设为true,返回二进制原始哈希值(而非十六进制字符串)
    $iv = substr(md5($key, true), 0, $iv_size);
    $c_t = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $plain_text, MCRYPT_MODE_CFB, $iv);
    return base64_encode($c_t);
}

function decrypt_data($key, $c_t) {
    $c_t = base64_decode($c_t);
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CFB);
    $iv = substr(md5($key, true), 0, $iv_size);
    $p_t = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $c_t, MCRYPT_MODE_CFB, $iv);
    return trim($p_t);
}

原代码的问题:

你之前的md5($key)返回的是32位十六进制字符串,而mcrypt需要的是二进制格式的IV。直接截取字符串的字符数,会导致IV的实际二进制长度不符合要求;加上md5($key, true)后,返回的是16字节的二进制原始哈希值,这样截取的IV长度才完全匹配mcrypt的要求。

但必须强调:mcrypt已经被PHP官方彻底废弃,这个方案只是临时过渡方案,强烈建议尽快迁移到OpenSSL实现。

内容的提问来源于stack exchange,提问作者Matti Kiviharju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:55:52