旧版短链接还原失败主因是加密规则不兼容,常见于简单进制转换、异或掩码或固定偏移,需确认字符映射表、手动解码、逆向运算并注意PHP版本兼容性及多层嵌套顺序。

旧版短链接还原失败的典型表现
调用新版解码函数返回 null 或空字符串,或解出错误 ID(比如远超业务范围的数值),基本可判定是加密规则不兼容。老系统常见用法:对原始 ID 做简单进制转换(如 10 进制转 62 进制)、异或掩码、固定偏移加减,而非现代标准的 Base64Url 或 Hashids。
base_convert() 无法直接还原 62 进制短码?
很多旧版 PHP 短链用 base_convert($id, 10, 62) 编码,但还原时不能直接反向调用 base_convert($short, 62, 10) —— 因为 PHP 的 base_convert() 使用字符集 0-9a-zA-Z(共 62 字符),而部分老实现自定义了顺序,比如把大写字母放前面、或跳过易混淆字符(0OIl)。必须确认原始字符映射表。
- 先检查老代码中是否定义了类似
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';的变量 - 若无源码,可尝试枚举常见变体:
0-9A-Za-z、abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ、去除了0O1l的 56 进制表 - 手动实现解码比依赖
base_convert()更可靠:
function decodeBase62($short, $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
$base = strlen($chars);
$id = 0;
for ($i = 0; $i < strlen($short); $i++) {
$c = $short[$i];
$pos = strpos($chars, $c);
if ($pos === false) return false;
$id = $id * $base + $pos;
}
return $id;
}遇到异或(XOR)或偏移加减怎么逆推?
若短码长度固定(如 4 位),且解码后 ID 呈规律性偏移(比如所有 ID 比真实值大 10000),大概率用了线性变换。常见组合有:$id ^ 0x5a5a、($id + 12345) & 0xffffff、($id > 22)(循环移位)。
- 优先尝试加减逆运算:
$real_id = $decoded_id - $offset,$offset 可从已知几组明文/密文对中算出 - 异或可自逆:
$real_id = $decoded_id ^ $mask,只需找到 mask(试0xff、0xffff、0x5a5a等常见值) - 位运算需结合长度判断:若短码对应 32 位整数,但解出值总在
0x00ffffff范围内,可能是低位截断,需补高位再还原
PHP 版本低于 5.6 时注意 hex2bin() 和 base64_decode() 兼容性
老系统常混用编码层:先 md5($id) 取前 8 字节,再 bin2hex() 或 base64_encode()。但 PHP 5.4 以下 hex2bin() 不支持非偶数长度字符串;PHP 5.2 中 base64_decode() 对非法字符静默失败,不报错也不返回 false。
立即学习“PHP免费学习笔记(深入)”;
- 避免直接传入未经清洗的短码到
base64_decode(),先用正则过滤:preg_replace('/[^a-zA-Z0-9_\-]/', '', $short) - 对 hex 字符串,用
str_pad($hex, strlen($hex) % 2 ? strlen($hex) + 1 : strlen($hex), '0', STR_PAD_RIGHT)补零再解 - 若怀疑是 URL 安全 Base64(
_/-替代+//),需先替换:strtr($short, '-_', '+/')
最麻烦的情况是多层嵌套:62 进制 → 异或 → base64url → 截取前 6 位。还原时必须严格按原顺序逆向执行,漏一层就彻底错乱。











