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

Stella981
• 阅读 477

我们在实际项目运用中,难免会要求对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

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
2年前
MongoDB 数据类型
一.MongoDB之数据类型Object ID:Documents自动生成的\_id,插入数据时候会生成 \_id,唯一字段String:字符串,必须是utf8Boolean:布尔值,true或者falseInteger:整数(Int32Int64你们就知道有个Int就行了,一般我们用Int32)Doub
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
ES6 新增的数组的方法
给定一个数组letlist\//wu:武力zhi:智力{id:1,name:'张飞',wu:97,zhi:10},{id:2,name:'诸葛亮',wu:55,zhi:99},{id:3,name:'赵云',wu:97,zhi:66},{id:4,na
京东云开发者 京东云开发者
6个月前
分布式系统的主键生成方案对比 | 京东云技术团队
UUID​UUID(通用唯一识别码)是由32个十六进制数组成的无序字符串,通过一定的算法计算出来。为了保证其唯一性,UUID规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。