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

使用uri_escape_utf8后无法解码字符串的Perl技术问题

解决方案

核心问题出在加密后的二进制数据被当成UTF-8字符串处理了。

加密函数encrypter返回的是Blowfish加密后的二进制字节流,不是合法的UTF-8字符串。当你用uri_escape_utf8处理它时,Perl会把这个二进制数据当作UTF-8编码的字符串来转义,但二进制数据大概率包含无效的UTF-8序列,转义后再通过Encode::decode('utf8', ...)还原时,会因为无效序列导致数据损坏,最终解密失败返回空值。而uri_escape是直接对字节进行转义,不会假设数据是UTF-8,所以能正常工作。

要解决这个问题,你需要:

  • 加密后先把二进制数据转换成安全的文本格式(比如Base64),再用uri_escape_utf8处理;
  • 解密前先反转义,再解码Base64得到原始二进制密文,最后解密。

修改后的加密端代码

use MIME::Base64;

# 加密后转Base64(第二个参数为空字符串避免换行),再执行uri_escape_utf8
$encodedUsername = uri_escape_utf8(encode_base64(encrypter($u), ''));

修改后的解密端代码

use MIME::Base64;

# 先反转义URL编码,再解码Base64得到二进制密文,最后解密
$enc = decode_base64(uri_unescape($encodedUsername));
$final = unencrypter($enc);

为什么这样可行?因为Base64会把任意二进制数据转换成仅包含ASCII字符的字符串,这样uri_escape_utf8处理时不会出现UTF-8无效序列的问题,JavaScript的encodeURIComponent处理Base64字符串也完全兼容,传输后能完整还原原始密文。

另外补充:你的加密函数里用pack('A8', $val)会用空格填充不足8位的字符串,解密后用unpack('A8', $val)会截断末尾空格,这个逻辑没问题,但如果原始字符串本身末尾有空格,会被截断,若不符合需求可以调整填充方式(比如用pack('a8', $val)用null字节填充)。


内容的提问来源于stack exchange,提问作者Jon Schlossberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 16:22:06