您现在的位置是:首页 > cms教程 > Discuz教程Discuz教程
discuz加密解密算法介绍
幻灵2025-07-04Discuz教程已有人查阅
导读今天和大家分享一下discuz的加密和解密算法研究了一个星期了,总结了这个算法有三个特点1,动态性,同一字符串每次加密的密文都不一样2,时间性,可以自己加一个限期参数,以秒为单位
今天和大家分享一下discuz的加密和解密算法研究了一个星期了,总结了这个算法有三个特点
1,动态性,同一字符串每次加密的密文都不一样
2,时间性,可以自己加一个限期参数,以秒为单位
3,统一性,加密和解密都用同一个函数
大家可以想一想
要想每次加密后的密文都不一样,而密钥是同一个,那解密只有一个办法,
就是把解密的信息肯定放到密文上面,从而解密
就像你跟不同的人下棋,对手有很多个,如果你想赢,肯定跟不同的人下就用不同的棋
法,而至于用什么棋法,就要看你的对手是个什么样的人,有急躁的,粗心的,等等
第二时间有限性
这个大家肯定一眼就能看出来如果我判断一个缓存过期了没有我可以通过它的创建时间和现在时间对比一下,用这个差值和租期比较有没有过期,那肯定这个也要放在密文里面第三的话统一性的该函数就用到异或算法,比较简单
例如 明文是01,密钥是10,两个异或完之后密文就是11,
而密文再和密钥异或就可以得到明文,也就是01
而密文和明文异或之后就可以得到密钥10,是不是很神奇
连我自己都不相信,但事实上就是这样,其实计算机还有很多
这样类似的规律
就是简单的吧密钥用md5加密,没有密钥的话就用uckey
得到一串32个位加密后的密钥
$keya 作为密码本(就是一推打乱的数字)来用
$keyb参与加密这个跟密钥有关,解密用来验证的
$ckey_length = 4;
然后就是ckey_length的用处就是为了
就是限制一下加密的后的字符串长度
读者可以自己亲自试一下改变 ckey_length
看看输出来的密文一不一样
可以看看代码之后一句
请分析这一行
就是利用了时间的唯一性,上面是返回毫秒数再用Md5返回 0到32位的字符串给keyc
好接着分析
我们在这里可以得出这时候的长度由
rand(0,52)
你可以循环52次来洗牌如果重复的话再来一次rand但这样的效率不高而是用
其实上面也是打乱算法,再一次打乱,好像没什么用但我自己想啊如果把他注释掉执行第一句执行后 也能加密也能机密,如果读者看懂的话告诉我一声,后来想想可能是因为,我们第一次生成了0到255的随机数,而$string_length这个可能没有这么长可能长度只有40,50啊,60啊,如果要加密的字符串很短的话,那密码本大于长度的那些元素就用不上
啦,那就浪费啦
我想可能是这个原因吧
呵呵,因为异或后的字符不一定是可以打印的字符,所以要用base64来加密一下,后面有时间我说一说base64的原理和用Php亲自写一下之后用keyc连接呵呵,还记得我开始说的话吗,慢慢理解一下下面就开始分析解密的过程上面讲过的那些就不讲啦
1,动态性,同一字符串每次加密的密文都不一样
2,时间性,可以自己加一个限期参数,以秒为单位
3,统一性,加密和解密都用同一个函数
大家可以想一想
要想每次加密后的密文都不一样,而密钥是同一个,那解密只有一个办法,
就是把解密的信息肯定放到密文上面,从而解密
就像你跟不同的人下棋,对手有很多个,如果你想赢,肯定跟不同的人下就用不同的棋
法,而至于用什么棋法,就要看你的对手是个什么样的人,有急躁的,粗心的,等等
第二时间有限性
这个大家肯定一眼就能看出来如果我判断一个缓存过期了没有我可以通过它的创建时间和现在时间对比一下,用这个差值和租期比较有没有过期,那肯定这个也要放在密文里面第三的话统一性的该函数就用到异或算法,比较简单
例如 明文是01,密钥是10,两个异或完之后密文就是11,
而密文再和密钥异或就可以得到明文,也就是01
而密文和明文异或之后就可以得到密钥10,是不是很神奇
连我自己都不相信,但事实上就是这样,其实计算机还有很多
这样类似的规律
function uc_authcode($string, $operation = 'DECODE', $key = '123', $expiry = 0) {
$ckey_length = 4;
$key = md5($key ? $key : UC_KEY); //加密解密时这个是不变的
$keya = md5(substr($key, 0, 16)); //加密解密时这个是不变的
$keyb = md5(substr($key, 16, 16)); //加密解密时这个是不变的
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya . md5($keya . $keyc); //64
$key_length = strlen($cryptkey); //64
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for ($i = 0; $i <= 255; $i++) { //字母表 64位后重复 数列 范围为48~122
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for ($j = $i = 0; $i < 256; $i++) { //这里是一个打乱算法
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for ($a = $j = $i = 0; $i < $string_length; $i++) {
$result .= chr(ord($string[$i]) ^ ($box[$i]));
/* $a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
*/
}
if ($operation == 'DECODE') {
if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc . str_replace('=', '', base64_encode($result));
}
}
分析一下1到5行就是简单的吧密钥用md5加密,没有密钥的话就用uckey
得到一串32个位加密后的密钥
$keya 作为密码本(就是一推打乱的数字)来用
$keyb参与加密这个跟密钥有关,解密用来验证的
$ckey_length = 4;
然后就是ckey_length的用处就是为了
就是限制一下加密的后的字符串长度
读者可以自己亲自试一下改变 ckey_length
看看输出来的密文一不一样
可以看看代码之后一句
return $keyc . str_replace('=', '', base64_encode($result));
下面分析keyc请分析这一行
substr(md5(microtime()), -$ckey_length)) : '';
这就是为什么同一字符串加密后的密文都不一样就是利用了时间的唯一性,上面是返回毫秒数再用Md5返回 0到32位的字符串给keyc
好接着分析
$cryptkey = $keya . md5($keya . $keyc); //64
$key_length = strlen($cryptkey); //64
这个 生成64位的密码本后面会用到
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
$string_length = strlen($string);
到这里啦先不看解密的就是会执行这句
sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
// 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb的
如果没有租期的话前十位是0的我们在这里可以得出这时候的长度由
$ckey_length+10时间位+16位的$keyb+明文的长度
$result = '';
$box = range(0, 255);
$rndkey = array();
for ($i = 0; $i <= 255; $i++) { //字母表 64位后重复 数列 范围为48~122
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for ($j = $i = 0; $i < 256; $i++) { //这里是一个打乱算法
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
上面是生成256一个随机数组就像洗牌算法一样rand(0,52)
你可以循环52次来洗牌如果重复的话再来一次rand但这样的效率不高而是用
for ($i = 0; $i < 52; $i++) {
$j = rand(0,52);
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
这样就算重复了随机数,但每个数在其他位置还是相等的概率,读者可以自己想一下而上面用了
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
这句增加加了随机性,就是什么牌一样,第一个变了,其他也跟着变了,可以这样说吧第一个数随机了,而后面的数也随机啦,而且随机性会越来愈大不用rand(0,52)是为了保持加密和解密的密码本是一样的
for ($a = $j = $i = 0; $i < $string_length; $i++) {
$result .= chr(ord($string[$i]) ^ ($box[$i]));//先不要看这一句
/* $a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
*/
}
然后到了这里啦其实上面也是打乱算法,再一次打乱,好像没什么用但我自己想啊如果把他注释掉执行第一句执行后 也能加密也能机密,如果读者看懂的话告诉我一声,后来想想可能是因为,我们第一次生成了0到255的随机数,而$string_length这个可能没有这么长可能长度只有40,50啊,60啊,如果要加密的字符串很短的话,那密码本大于长度的那些元素就用不上
啦,那就浪费啦
我想可能是这个原因吧
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
这一句就是异或的作用啦,用ascci码异或后再转字符,函数可以自己查查是什么比如 chr(ord('a')) 还是 a
return $keyc . str_replace('=', '', base64_encode($result));
之后来到这句就完成了加密啦为什么要用base64呢呵呵,因为异或后的字符不一定是可以打印的字符,所以要用base64来加密一下,后面有时间我说一说base64的原理和用Php亲自写一下之后用keyc连接呵呵,还记得我开始说的话吗,慢慢理解一下下面就开始分析解密的过程上面讲过的那些就不讲啦
$key = md5($key ? $key : UC_KEY); //加密解密时这个是不变的
$keya = md5(substr($key, 0, 16)); //加密解密时这个是不变的
$keyb = md5(substr($key, 16, 16)); //加密解密时这个是不变的
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) :
作用是为了保证加密和加密用的那个密码本是一样的
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length))
这里取出后$ckey_length个字符10时间位+16位的$keyb+明文的长度
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
如果密码本加密和解密的一样 那么 这句就会变回明文啦,如果不清楚异或的看上面我介绍的
if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
好了,终于来到这里啦,先验证时间有效性,和KeyB是不是用这个密钥生成的,如果是就返回明文给他Ok,终于分析完其实我还有一个问题还没有明白就是为什么密码本长度是256个,我猜的话,因为ascii码两个相加不超过255看看这句话$box[($box[$a] + $box[$j]) % 256],真的发觉discuz这个函数写的太精彩啦。
本文标签:
很赞哦! ()
相关教程
图文教程
Discuz重写的TextBox控件分析
Discuz重写的TextBox控件,非常好用,就是看不懂,有高手能看懂的,给解释下!using System;using System.Collections;using System.Web.UI;
Discuz!NT初始化过程代码分析
Discuz!NT论坛程序具有强大的配置功能 :从论坛的标题到论坛各个地方的显示,论坛模板的使用等等。要弄明白DNT页面的显示过程,首先应知道ASP.NET页面事件的引发顺序。
Discuz论坛中回复帖子并参与讨论的方法
1. 点击帖子下方的“回复”按钮,2. 输入你的内容,3. 点击“提交”即可。你还可以使用bbcode或html插入多媒体内容,引用其他用户的回复,确保遵守论坛规则并优化你的回复以提升用户体验。
Discuz x3 UCenter实现同步登陆的方法
1、Discuz x3 的登录页面URL是:/member.php?mod=logging&action=login2、这个登录页面,登录提交的地址是:在/member.php文件中,我们可以看到对应的加载的mod文件:
相关源码
-
(PC+WAP)货物运输快递物流汽车贸易pbootcms模板下载为货运代理、汽车贸易及快递企业设计的全终端适配网站系统,整合运单追踪与车辆展示核心功能模块原生开发的DIV+CSS架构,支持WebP图像压缩技术。查看源码 -
响应式高端家居家具装修类pbootcms模板网站源码家居装修、空间设计企业打造的营销型网站解决方案,基于PbootCMS内核深度开发。采用前沿响应式架构,适配手机端与PC端浏览体验查看源码 -
帝国CMS7.5漫画网站模板带手机端源码免费下载本模板为漫画内容平台设计开发,采用帝国CMS7.5内核构建,深度优化漫画作品展示结构与章节管理模式。前端采用响应式布局设计,适配各类漫画阅读场景,提供作品分类、连载追踪、热度排行等垂直领域功能模块。查看源码 -
pbootcms模板(PC+WAP)APP应用软件下载类官网源码为APP应用软件官网打造的响应式解决方案,PC端与移动端(WAP)数据实时同步,一次更新全网生效,满足多终端用户无缝体验需求。查看源码 -
(自适应)物流运输快递仓储货运网站模板免费下载基于PbootCMS内核开发的物流运输行业专用模板,深度适配仓储货运企业的业务展示需求。前端采用响应式布局,自动适配手机端访问,后台数据实时同步更新,帮助企业高效展示运输网络、仓储设施、服务流程等核心业务模块。查看源码 -
(自适应)品牌创意设计作品工作室pbootcms模板下载该模板适用于品牌策划、艺术设计、广告创意公司官网,亦可通过替换图文快速适配其他行;高端创意设计公司工作室网站源码极简代码架构、艺术化视觉布局、企业级功能扩展性。查看源码
| 分享笔记 (共有 篇笔记) |