【后端开辟】php应用32进制完成对id加密解密
2019-11-19后端开发搜奇网55°c
A+ A-最近在项目中碰到一个题目,当前用户分享一个约请码给挚友,挚友依据约请码注册成为新用户以后,则成为当前用户的下级,特定条件下,能够获得下级用户的一系列返利。这里要完成的就是依据当前用户的id,生成一个加密串,而且能够反向解密。经由不停的测试调解,终究获得了末了的效果。如:
id = 12 code = 85U43DM
首次完成
先上代码,以下:
/** * 加密解密用户约请码, * @param unknown $string * @param string $action encode|decode * @return string */ function endecodeUserId($string, $action = 'encode') { $startLen = 13; $endLen = 8; $coderes = ''; #TOD 暂设定uid字符长度最大到9 if ($action=='encode') { $uidlen = strlen($string); $salt = 'yourself_code'; $codestr = $string.$salt; $encodestr = hash('md4', $codestr); $coderes = $uidlen.substr($encodestr, 5,$startLen-$uidlen).$string.substr($encodestr, -12,$endLen); $coderes = strtoupper($coderes); }elseif($action=='decode'){ $strlen = strlen($string); $uidlen = $string[0]; $coderes = substr($string, $startLen-$uidlen+1,$uidlen); } return $coderes; }
思绪引见:
设定一个盐值,$salt,和id拼接后构成一个新的字符串,该盐值可用于后期对约请码举行平安校验。对该字符串举行md4加密(考虑到比拟md5,md4速率更快,而且平安性也并不弱),获得$encodestr,对该字符串举行拆分,分为前后两部份,第一部份$startLen,13个字符串;第二部份$endLen,8个字符串。将$string,这里指传入的id,和$uidlen,混入前一部份字符串。因这里现在仅支撑id最大长度为9,因而$uidlen长度为1,如许末了我们便获得了一个长度为22的字符串。
加密的历程当中,我们现实上是把id的数值和id的长度,混入到了加密串中,加密的时刻我们依据存入的这些信息找到对应的位置,即可获得id。
这里,我们对平安性并没有请求很高,为了使顺序运转速率更快,因而在解密的时刻并没有考证。
测试,对id加密:
echo endecodeUserId(12);
输出效果:
23471DC2352712F34D6780
测试,对约请码解密
echo endecodeUserId('23471DC2352712F34D6780','decode');
输出效果:
12
获得的效果看上去并没有题目,然则现实测试中发明如许一个题目,关于普通用户可能会存在这类状况,挚友发到他手机微信上一个约请码,然后他想要用电脑举行注册,但他并不知道该怎样把约请码从手机传到电脑上或许嫌贫苦,这时刻他就要在电脑最先手动输入约请码了,天哪,22位啊,照样大写字母加数字夹杂,预计他要摒弃注册了。
因而,我们举行了调解,改成7位的约请码。
再次探究
这里是在写文章之前对要领举行了封装,照样直接先上代码
<?php class convert { /** * 初始数字,自定义 */ const INIT_NUM = 123456789; /** * @var 进制的基础字符串 */ private $baseChar; /** * @var 进制范例 */ private $type; /** * @var array 各进制字符串列表 */ private static $convertList = array( '32' => '0123456789ABCDEFGHJKMNPQRSTVWXYZ',//不含ILOU ); public function __construct($type='32') { $this->type = $type; $this->baseChar = self::$convertList[$type]; } /** * 公用要领,数字举行进制转换 * @param $num * @return string */ private function _idToString($num){ $str = ''; while ($num!=0){ $tmp = $num % $this->type; $str .= $this->baseChar[$tmp]; $num = intval($num/$this->type); } return $str; } /** * @desc im:十机制数转换成三十二进制数 * @param (string)$char 三十二进制数 * return 返回:十进制数 */ public function idToString($id){//10位内id 返回7位字母数字 //数组 增添备用数值 $id += self::INIT_NUM; //左补0 补齐10位 $str = str_pad($id,10,'0',STR_PAD_LEFT); //按位 拆分 4 6位(32进制 4 6位离别) $num1 = intval($str[0].$str[2].$str[6].$str[9]); $num2 = intval($str[1].$str[3].$str[4].$str[5].$str[7].$str[8]); $str1 = $str2 = ''; $str1 = $this->_idToString($num1); $str1 = strrev($str1); $str2 = $this->_idToString($num2); $str2 = strrev($str2); //4 补足 3 4位 U L return str_pad($str1,3,'U',STR_PAD_RIGHT).str_pad($str2,4,'L',STR_PAD_RIGHT); } /** * @desc im:三十二进制数转换成十机制数 * @param (string)$char 三十二进制数 * return 返回:十进制数 */ public function stringToId($str){ //1 消灭 3 4 位补足位 $str1 = trim(substr($str,0,3),'U'); $str2 = trim(substr($str,3,4),'L'); $num1 = $this->_stringToId($str1); $num2 = $this->_stringToId($str2); //补位拼接 $str1 = str_pad($num1,4,'0',STR_PAD_LEFT); $str2 = str_pad($num2,6,'0',STR_PAD_LEFT); $id = ltrim($str1[0].$str2[0].$str1[1].$str2[1].$str2[2].$str2[3].$str1[2].$str2[4].$str2[5].$str1[3],'0'); //减去 备用数值 $id -= self::INIT_NUM; return $id; } /** * 公用要领字符串转数字 * @param $str * @return float|int|string */ private function _stringToId($str){ //转换为数组 $charArr = array_flip(str_split($this->baseChar)); $num = 0; for ($i=0;$i<=strlen($str)-1;$i++) { $linshi = substr($str,$i,1); if(!isset($charArr[$linshi])){ return ''; } $num += $charArr[$linshi]*pow($this->type,strlen($str)-$i-1); } return $num; } }
思绪引见
在一名事情多年的大神的指导下,采纳了这类要领。将id转化为牢固长度的32进制字符串,并加上本身的算法。为何这里采纳32进制,而不是其他进制呢?32进制能够包括足够多的英文字符,生成的加密串看起来会更范例,另一方面,消除一些不容易辨认的英文字符(这里消除ILOU),因而采纳了32进制,而并没有采纳36进制。
加密历程,要领idToString(),因考虑到刚最先id比较小的时刻,转为32进制会涌现比较多的0,看起来很不范例,因而设定一个初始值INIT_NUM,这个能够自定义。依据传过来的id,加上初始值后获得一个长度为10位的数值,将这个数值距离位拆开分为长度为4位的$num1和长度为6位的$num2,两个数值离别转换为32进制,$num1转化后获得长度为3的字符串,不足的用U补足,$num2获得长度为4的字符串,不足的用L来补足。
解密则是逆操纵,反向操纵即可。
测试:生成
$obj = new convert(32); $res1 = $obj->idToString(12);
效果:
85U43DM
解密:
$obj = new convert(32); $res1 = $obj->stringToId('85U43DM');
效果:
12
总结
固然,纵然末了的这个要领中也存在有不足的处所,比方在对加密数值拆分为2个num值的时刻,用的要领就很不天真,一旦修正解密的处所也要随着更改。这里只是分享一个思绪,迎接人人批评指正。
以上就是php应用32进制完成对id加密解密的细致内容,更多请关注ki4网别的相干文章!