转自知乎的一位大佬:
<?php
/**
* 整型数字对称加密,使用场景:对ID加密后展示
* 只适用整型数字
* 使用时请重新生成密钥
*/
class IntCode
{
// 密钥(0-9A-Za-z)打乱,可使用str_shuffle()函数重新生成
private $key = 'PTvNKJdjOyB3niF891XCsp7IrHQMIkELVqYbm20ZUGWfhze5xtSRowgu4DA6ac';
public function encode($int)
{
//判断是否为整型
if (! is_int($int)) {
return '不是整型';
}
//将传入数字转换成十六进制分割成数组
$hexArr = str_split(dechex($int));
//将密钥分割成数组
$keyArr = str_split($this->key);
//密钥长度,推荐62
$keyLen = count($keyArr);
//随机数字
$rand = mt_rand(0, $keyLen - 1);
//将随机值压入结果开头
$str = $keyArr[$rand];
//验证码
$verfy = $keyArr[($keyLen - $rand + strlen($int)) % $keyLen];
//循环十六进制每一位数字,替换成密钥里的值
foreach ($hexArr as $v) {
$offset = hexdec($v) + $rand;
$str .= $keyArr[$offset % $keyLen];
}
//将验证码压入结果末尾并返回
return $str . $verfy;
}
public function decode($str)
{
//验证$str是否合法
if (! preg_match('/^[0-9a-zA-Z]{2,10}$/', $str)) {
return '字符不合法';
}
//将传入字符串分割成数组
$strArr = str_split($str);
//密钥
$key = $this->key;
//将密钥分割成数组
$keyArr = str_split($this->key);
//密钥长度
$keyLen = count($keyArr);
//十六进制数值
$hex = '';
//获取随机数
$rand = strpos($key, array_shift($strArr));
//获取验证码
$verfy = array_pop($strArr);
//循环每一个字串并转换成十六进制
foreach ($strArr as $k => $v) {
if (strpos($key, $v) >= $rand) {
$hex .= dechex(strpos($key, $v) - $rand);
} else {
$hex .= dechex($keyLen - $rand + strpos($key, $v));
}
}
//十六进制转换成十进制
$dec = hexdec($hex);
//判断验证码是否正确
if ($verfy !== $keyArr[($keyLen - $rand + strlen($dec)) % $keyLen]) {
return '校验错误,给定字符串不合法';
}
return $dec;
}
}
//以下为测试内容
$intCode = new IntCode();
// echo $intCode->encode(98445);
// echo $intCode->decode('h1xss');
for ($i=9865; $i<19800; $i++) {
$str = $intCode->encode($i);
$int = $intCode->decode($str);
echo $i . ' | ' . $int . ' | ' . $str . '<br>';
}
?>
亲测可用!