PHP利用32进制生成固定长度字符串对id加密解密

原创
2019/12/20 11:11
阅读数 3.6K

我们在实际项目运用中,难免会要求对ID进行加密,生成特定的字符串,比如生成用户邀请码,这样不用查数据库也可以反向解密到id

为什么使用32进制

因为数字加字母长度为36位,32位生成后不用区别用户输入不用区分大小写

<?php
class IDAES{
	$baseChar = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
}

加解密基础版,可以生成任意长度

不同的长度能容纳的位数不一样,可以容纳数字最大值为32的n次方,比如固定长度为6,那么最大值为1,073,741,824,如果长度为7,最大值为34,359,738,368

<?php
class IDAES{
	//32进制用来移位的字符串,顺序可以随机生成,提高强度
	static $baseChar = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
	//id起始值,保证id比较小时的密钥强度
	const CODESTART= 123456;
	//密钥长度,
	const CODELEN = 6;
	
	//加密
	static function idToString($id){
		$id += self::CODESTART;
		$str = '';
		while ($id!=0){//进制转换
			$tmp = $id % 32;
			$str .= self::$baseChar[$tmp];
			$id = intval($id/32);
		}
		$str = strrev($str);
		//位数如果不足用保留字母U填补,长度可以随意
		return str_pad($str, self::CODELEN, 'U', STR_PAD_LEFT);
	}
	
	//解密
	static function stringToId($str){
		$str = trim($str,'U');
		$charArr = array_flip(str_split(self::$baseChar));
		$num = 0;
		$strlen = strlen($str);
		for ($i=0;$i<=$strlen-1;$i++)
		{
			$_str = $str[$i];
			if(!isset($charArr[$_str])){
				return '';
			}
			$num += $charArr[$_str]*pow(32,$strlen-$i-1);
		}

		return intval($num - self::CODESTART);
	}
}

进一步思考,我们可以对最终生成的字符串进行再次替换进一步混淆,防止反破解,我们这里可以将固定填充位改成随机生成混淆字符串

<?php
	
	//... 省略代码
	//加密部位标识,这里根据生成自己的生成长度定,值任意排列
	static $tagChar = ['A','B','C','D','E','F','G','H'];

	//...继续省略,在加密的最后一段改成
	$difflen = self::CODELEN-strlen($str);
	$pre = self::$tagChar[$difflen];
	for ($i=0; $i<$difflen; $i++){
		$k = rand(0, 31);
		$pre .= self::$baseChar[$k];
	}
	$str = $pre.$str;
	return $str;

	//...日常省略,在解密的时先去掉混淆字符串
	$pos = $str{0};
	$start = array_search($pos, self::$tagChar);
	$str = substr($str, $start+1);
	//获取32进制字符串后,继续解密...

当然还可以复杂化处理,进行再次加密

声明:最初的代码参考自https://blog.csdn.net/weixin_30443731/article/details/97862594

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部