php利用32进制实现对id加密解密-php教程

资源魔 31 0
媒介

比来正在名目中遇到一个成绩,以后用户分享一个约请码给摰友,摰友依据约请码注册成为新用户之后,则成为以后用户的上级,特定前提下,能够失去上级用户的一系列返利。这里要完成的就是依据以后用户的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加密解密的具体内容,更多请存眷资源魔其它相干文章!

标签: php php开发教程 php开发资料 php开发自学

抱歉,评论功能暂时关闭!