使用openssl_encrypt加密后无法解密,URL无法显示目标值求助
问题分析与修复方案
你的代码存在三个核心问题,直接导致解密失败:
密钥无法跨请求复用
PHP是无状态脚本,每次加载页面都会重新生成$key和$iv。表单提交后,解密阶段用的是新生成的密钥,和加密时的密钥完全不同,自然解不开原内容。必须把密钥固定存储在服务器端(比如定义为常量、写入配置文件),不能每次请求都重新生成。输入框value未加引号导致内容截断
base64编码后的字符串可能包含+、/这类特殊字符,直接写value='.$newid.'会让浏览器解析时截断内容,提交的ID已经不完整,解密必然失败。必须给value值加上双引号包裹。AES密钥长度与加密算法不匹配
你用的是AES-128-CBC,该算法要求密钥长度为16字节,但代码里生成了32字节的$key。虽然OpenSSL会自动截断前16字节使用,但容易引发混淆,建议改用AES-256-CBC(对应32字节密钥),或者将密钥长度调整为16字节。
修复后的完整代码
<?php // 固定密钥(请自行生成并替换,不要直接使用示例内容) // 生成方式:执行一次openssl_random_pseudo_bytes(32),将结果转base64后保存 define('ENCRYPT_KEY', base64_decode('你的32字节密钥base64值')); $cipher = "AES-256-CBC"; $ivlen = openssl_cipher_iv_length($cipher); if (isset($_POST['submit'])) { $c = base64_decode($_POST['id']); $iv = substr($c, 0, $ivlen); $hmac = substr($c, $ivlen, 32); // SHA256二进制长度为32字节 $ciphertext_raw = substr($c, $ivlen + 32); // 使用固定密钥解密 $id = openssl_decrypt($ciphertext_raw, $cipher, ENCRYPT_KEY, OPENSSL_RAW_DATA, $iv); $calcmac = hash_hmac('sha256', $ciphertext_raw, ENCRYPT_KEY, true); if (hash_equals($hmac, $calcmac)) { header("location: radio.php?value=" . urlencode($id)); exit; // 跳转后必须终止脚本执行 } else { var_dump('HMAC验证失败,内容可能被篡改'); } } ?> <form method="post"> <?php $id = 1; $iv = openssl_random_pseudo_bytes($ivlen); // 每次加密生成新IV $ids = openssl_encrypt($id, $cipher, ENCRYPT_KEY, OPENSSL_RAW_DATA, $iv); $hmac = hash_hmac('sha256', $ids, ENCRYPT_KEY, true); $newid = base64_encode($iv . $hmac . $ids); // 给value加双引号,避免特殊字符截断 echo '<input type="text" name="id" value="'.$newid.'">'; ?> <input type="submit" name="submit"> </form>
额外注意事项
- 密钥必须安全存储,不能直接暴露在代码中(可存入环境变量或加密配置文件),绝对不能泄露给客户端。
- 跳转时用
urlencode($id)处理ID,避免URL中出现特殊字符导致参数解析错误。 - 每次加密生成新IV是正确做法,IV无需保密,随加密内容一起传递即可。
内容的提问来源于stack exchange,提问作者curious_coder
相关产品推荐
相关产品推荐

