摘要:将转化为固定长度的进制字符串,并加上自己的算法。解密则是逆操作,反向操作即可。
前言
最近在项目中遇到一个问题,当前用户分享一个邀请码给好友,好友根据邀请码注册成为新用户之后,则成为当前用户的下级,特定条件下,可以得到下级用户的一系列返利。这里要实现的就是根据当前用户的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位的邀请码。
再次探索这里是在写文章之前对方法进行了封装,还是直接先上代码
"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值的时候,用的方法就很不灵活,一旦修改解密的地方也要跟着变动。这里只是分享一个思路,欢迎大家批评指正。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/29157.html
摘要:我们做程序的时候,加密解密是绕不开的话题,使用开发应用的时候,都内置了哪些有关加密解密安全方便的支持那本文将为你揭晓。函数声明为存在着第三个参数,比如我们可以传递会员的等,这样此信息将和一起作为加密解密的钥匙。 我们做程序的时候,加密解密是绕不开的话题,使用yii2开发应用的时候,都内置了哪些有关加密解密(安全)方便的支持那?本文将为你揭晓。 相关环境 操作系统及IDE macOS ...
摘要:加密算法以字符十六进制数字形式返回散列值。加密算法是加密是的干扰码,使编码更安全可选的盐值字符串。返回的数据可能是二进制的 数据加密可以简单的理解为:明文(文件或者数据)-->算法处理-->不可读的密文,进而达到加密的效果。 php中的几种加密方式 md5加密算法 crypt算法 sha1加密算法 URL编码技术编码 base64编码 其中 md5、crypt、sha1 都是单向加...
摘要:利用消息认证码可以确保消息不是被别人伪造的,消息认证码是带密钥的函数,由于有了一个,所以会比有更好的安全性。所以需要采用的就是算法,该算法主要利用的是不对称加密算法,利用私钥进行签名,公钥验证数据的完整性。 写在前面 本文会到你了解jwt的实现原理,以及base64编码的原理。同时本人也简单的实现了一下jwt的生成,点这里。 jwt是什么 本质上它是一段签名的 JSON 格式的数据。由...
阅读 2043·2023-04-25 19:15
阅读 2205·2021-11-23 09:51
阅读 1220·2021-11-17 09:33
阅读 2134·2021-08-26 14:15
阅读 2451·2019-08-30 15:54
阅读 1563·2019-08-30 15:54
阅读 2152·2019-08-30 12:50
阅读 1116·2019-08-29 17:08