
在php中使用openssl对数据进行blowfish加密后,密文常含+、/、=等特殊字符,直接拼入url会导致+被$_get或$_request误作空格解析。正确做法是对密文执行urlencode()编码后再传参,并在接收端用urldecode()还原,而非更换加密算法。
当使用 openssl_encrypt()(如 Blowfish/CBC 模式)生成密文时,其默认输出为 Base64 编码格式(RFC 4648 §4),而 Base64 字符集包含 +、/ 和 = —— 这些字符在 URL 中具有特殊含义:+ 被传统表单编码(application/x-www-form-urlencoded)解释为空格,/ 可能干扰路径,= 常用于参数分隔。因此,问题根源并非加密算法本身,而是未对密文做 URL 安全转义。
✅ 正确处理流程如下:
-
加密后立即 URL 编码(发送端):
$passphrase = "testte@t"; $cipher = "bf-cbc"; // 推荐显式指定模式,如 bf-cbc(Blowfish-CBC) $id = "20220228-12";
// 注意:openssl_encrypt 需 IV(推荐随机生成并附带传输) $ivlen = openssl_cipher_iv_length($cipher); $iv = openssl_random_pseudo_bytes($ivlen); $enc_str = openssl_encrypt($id, $cipher, $passphrase, OPENSSL_RAW_DATA, $iv);
// 将二进制密文 + IV 组合成可传输结构(如 base64(iv.enc)),再 URL 编码 $payload = base64_encode($iv . $enc_str); $encoded_payload = urlencode($payload);
$url = "https://www.php.cn/link/ee373cca919c768548f9461eb171a6c7}"; echo $url; // 输出示例:https://www.php.cn/link/04ee08ead1a259009cab6b2198fb6d93 (含 %2B, %2F, %3D 等)
2. **接收端先 URL 解码,再 Base64 解码与解密**(服务端):
```php
$encoded_payload = $_GET['p'] ?? '';
$payload = urldecode($encoded_payload); // 还原原始 base64 字符串
$data = base64_decode($payload);
if ($data === false) {
die('Invalid payload');
}
$ivlen = openssl_cipher_iv_length('bf-cbc');
$iv = substr($data, 0, $ivlen);
$enc_data = substr($data, $ivlen);
$decrypted = openssl_decrypt($enc_data, 'bf-cbc', $passphrase, OPENSSL_RAW_DATA, $iv);
if ($decrypted === false) {
die('Decryption failed: ' . openssl_error_string());
}
echo "Decrypted ID: " . $decrypted; // → "20220228-12"⚠️ 关键注意事项:
- 不要改用其他“不产生+的算法”(如 AES-GCM 或 ChaCha20)来规避此问题——它们的 Base64 输出同样含 +//;本质是编码层问题,非算法缺陷。
- 若需更高兼容性与简洁性,可考虑 base64url 编码(RFC 4648 §5):将 +→-、/→_、去掉填充 =,PHP 8.1+ 可用 base64_encode($data, true),旧版本需手动替换:
$base64url = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($iv . $enc_str));
- 始终使用随机 IV 并与密文一同传输(不可硬编码),确保语义安全性;密钥(passphrase)应通过 PBKDF2 衍生(如 hash_pbkdf2()),而非直接用作加密密钥。
总结:无需更换加密算法。urlencode() / urldecode() 是标准、可靠且零成本的解决方案;配合合理的 IV 管理与密钥派生,即可在保持 Blowfish(或任何 OpenSSL 支持算法)安全性的同时,实现 URL 安全传输。










