要生成自定义长度、自定义进制的随机均匀短散列值,可以结合哈希函数和进制转换来实现。哈希函数可以将字符串映射为固定长度的二进制值,然后根据自定义的进制进行编码,生成你需要的短散列值。我们可以使用 PHP 来实现该功能,以下是具体的步骤:
实现步骤
- 输入字符串的哈希值:使用常见的哈希算法如 MD5 或 SHA-256 生成散列值。
- 转换哈希值为数字:将生成的哈希值转换为数字表示。
- 根据自定义进制转换:将数字转换为你想要的进制(例如 62 进制,包含数字、大小写字母)。
- 控制散列长度:生成的散列值可以根据需求来截断或补齐为特定长度。
代码实现
下面是使用 PHP 实现该逻辑的代码示例:
php
/**
* 生成自定义长度的自定义进制随机均匀短散列值
*
* @param string $inputStr 需要计算的字符串
* @param int $len 指定散列值字符长度(可取1~32位),默认32位(2:显示0~1;4:显示0~3;8:显示0~7;10:显示0~9;16:显示0~F;32:显示0~V;64:显示0~/)...")
* @param int $base 自定义的进制,默认16进制
* @return string
*/
public static function generateCustomShortHash($inputStr, $len=32, $base=16, $prefix='', $suffix='',$times=0){
$md5 = strtoupper(md5($prefix.$inputStr.$suffix));
$base_str = array (
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y' );//去除了I、L、O、Z四字母,(I、i、L、l与数字1相似,O、o与数字0相似,Z、z与数字2相似,1~F属于16进制常规范筹不宜删减);
$b_one = ceil(log($base,2));//每一位字符需要2进制字符长度
$h_one = ceil($b_one/4);//每一位字符需要16进制字符长度
$m_len = $b_one % 4;//非4的整数倍时高位丢弃,计算丢弃的位数
if(ceil(($b_one * $len) / 4) > strlen($md5)){//需要总16进制字符长度超过最大字符长度
return false;
}
for ($run_num=0; $run_num < 100; $run_num++) {
$hex = isset($hex)?strtoupper(md5($hex)):$md5;
$strabbr = '';
for ($i = 0; $i < $len; $i++) {//循环每一位目标字符生成工作
$subHex = substr($hex, $i*$h_one, $h_one);//按目标字符所需16进制字符长度进行截取
$b1_str = ($h_one - 1) * 4 + ($m_len?:4);//生成二进制位运算的1字符数
$b0_str = $m_len?(4-$m_len):0;//生成二进制位运算的0字符数
$b_str = $m_len?str_repeat('0',$b0_str).str_repeat('1',$b1_str):str_repeat('1',$b1_str);//拼接二进制位运算的字符串
$int = (bindec('0b'.$b_str)) & (hexdec('0x'.$subHex));//按位与保留有效位值
$strabbr .= $base_str[$int];//从数组中获取对应字符
}
//存表逻辑
if(Urlabbr::selectcount(['strabbr'=>$strabbr])==0){
$urlabbr_data = [
'str'=>$inputStrc,
'strmd5'=>md5($inputStr),
'strabbr'=>$strabbr,
'run_num'=>$run_num+1,
'views'=>0,
'createtime'=>$times?:time(),
'updatetime'=>$times?:time(),
'switch'=>1,
];
Urlabbr::addid($urlabbr_data);
break;
}
}
if($run_num >= 100){ //撞库次数超过100
return false;
}
//返回数据
return $strabbr;
}
代码说明
-
字符表定义 :我们使用 0123456789ABCDEFGHJKMNPQRSTUVWXY 作为 32 进制字符表,去除了I、L、O、Z四字母,(I、i、L、l与数字1相似,O、o与数字0相似,Z、z与数字2相似,1~F属于16进制常规范筹不宜删减);
-
哈希计算 :我们使用
hash('sha256', $inputStr)
来计算输入字符串的 SHA-256 哈希值。由于 SHA-256 生成 64 位的十六进制数(256 位),我们可以选取前 15 位哈希值转成十进制,以确保数值足够大且不会溢出。 -
进制转换 :将哈希值的十进制数字逐位转为 32 进制,通过
num % $base
计算余数,从而获得 32 进制字符,并将字符拼接到结果中。 -
结果处理 :使用
str_pad()
来确保最终生成的短散列值具有指定的长度,不足的部分以0
补齐。
运行结果
对于输入字符串 "example_string"
,生成了一个 8 位长度的 32 进制短散列值。
扩展
- 更大进制:如果需要更高的进制,可以扩展字符集。例如支持 95 个可打印字符(ASCII)。
- 随机性增强:可以在哈希值基础上添加时间戳、随机数等增强散列的随机性。
- 更长哈希:使用不同的哈希算法或截取更多位数,可以增加散列的多样性。