Files
im/support/Encrypt.php
T
2026-03-01 21:05:19 +08:00

231 lines
6.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace support;
class Encrypt
{
/**
* 类似QQ的非连续数字ID加密
* 使用可逆的位运算混淆算法
* 特点:
* 1. 连续输入产生非连续、看起来随机的输出
* 2. 加密解密完全可逆
* 3. 输出为8位纯数字(10000000 - 99999999),类似QQ号
* 4. 支持约9000万个ID (0 - 89999999)
*/
// 最大ID值(支持9000万个ID
private static $maxId = 90000000;
// 加密结果基数(确保8位数)
private static $baseValue = 10000000;
/**
* 加密连续数字ID为非连续数字ID
* 使用基于哈希的可逆映射
* @param int $plainId 原始连续ID (0 - 89999999)
* @param int $userKey 可选的额外密钥
* @return int 加密后的非连续ID8位数)
*/
static function userIDencode($userID,$key=0):string{
if(!is_numeric(($userID))){
return $userID;
}
$userID = intval($userID);
if($userID<=100234){
return $userID.'';
}
if($userID<=102028){
return id_encode($userID);
}
$key = intval($key);
$plainId = abs(intval($userID)) % self::$maxId;
// 使用哈希函数生成伪随机序列,然后建立双射映射
// 方法:使用线性同余生成器 (LCG) 的变体
// 公式:encrypted = (a * plainId + b) mod m
// 其中 a 和 m 互质,保证可逆
// 选择一个大质数作为乘数(与9000万互质)
$a = 15485863; // 大质数,与90000000互质
$b = 2038074743; // 大常数
$m = self::$maxId;
// 加密
$encrypted = ($a * $plainId + $b + $key) % $m;
// 确保结果是8位数(10000000 - 99999999
return (self::$baseValue + $encrypted).'';
}
/**
* 解密非连续数字ID为原始连续ID
* @param int $encryptedId 加密后的非连续ID8位数)
* @param int $userKey 可选的额外密钥
* @return int 原始连续ID
*/
static function userIDDecode($userID,$key=0):string{
if(!is_numeric(($userID))){
return id_decode($userID.'');
}
if($userID<=100234){
return $userID.'';
}
$key = intval($key);
// 去除基数,得到原始混淆值
$cipherId = ($userID - self::$baseValue + self::$maxId) % self::$maxId;
// LCG解密:plain = (encrypted - b) * a^-1 mod m
$a = 15485863;
$b = 2038074743;
$m = self::$maxId;
// 计算 a 的模逆元 (使用扩展欧几里得算法)
$aInv = self::modInverse($a, $m);
// 解密
$temp = ($cipherId - $b - $key) % $m;
if ($temp < 0) $temp += $m;
$plainId = ($aInv * $temp) % $m;
return $plainId.'';
}
/**
* 使用扩展欧几里得算法计算模逆元
* 返回 x 使得 (a * x) % m = 1
*/
private static function modInverse($a, $m) {
$m0 = $m;
$x0 = 0;
$x1 = 1;
if ($m == 1) return 0;
while ($a > 1) {
// q 是商
$q = intval($a / $m);
$t = $m;
// m 是余数,处理完后 a 和 m 互换
$m = $a % $m;
$a = $t;
// 更新 x0 和 x1
$t = $x0;
$x0 = $x1 - $q * $x0;
$x1 = $t;
}
// 确保 x1 是正数
if ($x1 < 0) $x1 += $m0;
return $x1;
}
static function generateShortUniqueID($length = 8)
{
// 生成指定长度的随机字节,转为 Base64 编码并去除不必要字符
return substr(bin2hex(random_bytes($length / 2)), 0, $length);
}
static function idEncode($id = '')
{
if ($id <= 100234) {
return $id . '';
}
return id_encode($id);
}
static function idDecode($id = '')
{
$_id = intval($id);
if ($_id == $id) {
return $id;
}
return id_decode($id);
}
/**
* 生成可逆的邀请码(8位,含校验位)
* @param int $id 用户ID(需≥1000
* @return string 大写字母+数字组合
*/
static function base62Encode(int $id, $secret = 'your_secret_salt'): string
{
// 添加校验位(防止篡改)
$hash = crc32($id . $secret) % 1000;
$code_num = $id * 1000 + $hash;
// Base62 编码(0-9A-Za-z
$base62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$code = '';
while ($code_num > 0) {
$code = $base62[$code_num % 62] . $code;
$code_num = (int) ($code_num / 62);
}
// 补全到8位
return str_pad($code, 8, '0', STR_PAD_LEFT);
}
/**
* 从邀请码解析用户ID
* @return int|false 成功返回id,失败返回false
*/
static function base62Decode(string $code, $secret = 'your_secret_salt'): int|false
{
$base62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$code_num = 0;
// Base62 解码
for ($i = 0; $i < strlen($code); $i++) {
$pos = strpos($base62, $code[$i]);
if ($pos === false)
return false;
$code_num = $code_num * 62 + $pos;
}
// 分离校验位
$id = (int) ($code_num / 1000);
$hash = $code_num % 1000;
// 校验
if (crc32($id . $secret) % 1000 != $hash) {
return false;
}
return $id;
}
/**
* Aes加密
* @param mixed $str
* @param mixed $key
* @return string
*/
static function aesencode($str, $key = '')
{
if (!$key) {
$key = Config('pay.api_token');
}
if (is_array($str) || is_object($str)) {
$str = json_encode($str, JSON_UNESCAPED_UNICODE);
}
$key = hash('sha256', $key, true);
$iv = substr($key, 0, 16);
$encrypted = openssl_encrypt($str, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
return base64_encode($encrypted);
}
/**
* Aes解密
* @param mixed $str
* @param mixed $key
* @return string
*/
static function aesdecode($str, $key = '')
{
if (!$key) {
$key = Config('pay.api_token');
}
$key = hash('sha256', $key, true);
$iv = substr($key, 0, 16);
$encrypted = base64_decode($str);
$decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
return $decrypted;
}
}