您现在的位置是:首页 > 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编辑器的步骤方法
前面讲了如何开发一个discuz的特殊主题插件,详情可在此查看discuz特殊主题插件开发步骤和犯的愚蠢错误。上一篇文章讲解的是一些简单的开发步骤,不涉及到具体的编码。
discuz!nt投票功能写法实例
可能要写一个投票系统,把discuz!net里面的代码放到这里来参考参考,感觉它的投票功能做的有点简单,数据库里面相关的就两个主从表,不过想想也可以理解
Discuz的NT2.0系统登录整合
在做Discuz!NT 2.0与自己的系统整合过程中,使用的是Discuz!NT 2.0的用户数据作为我的用户数据。把Discuz!NT 2.0文件存放入bbs目录,把bbs目录设置为虚拟目录。把DNT.config拷贝到根目录。
Discuz实现主题标题和正文同时显示的方法
本文实现功能:将主题标题和主题内容同时显示出来,如想直接看项目实现结果,可直接看解决问题的那个标题下的内容
相关源码
-
(自适应响应式)HTML5幕墙装饰工程建筑装修公司pbootcms模板下载基于PbootCMS开发的响应式模板,为幕墙工程、建筑装饰企业设计,通过数字化展示提升企业专业形象与项目展示能力。结构化数据标记增强项目案例收录,智能URL路由优化,支持每个工程案例独立设置关键词与描述查看源码 -
(自适应html5)自媒体运营培训教程个人博客pbootcms模板本模板基于PbootCMS系统开发,特别适合自媒体运营培训、知识付费类网站使用。采用响应式设计,能够适配各类终端设备,为内容创作者提供专业的内容展示平台。查看源码 -
帝国CMS7.5漫画网站模板带手机端源码免费下载本模板为漫画内容平台设计开发,采用帝国CMS7.5内核构建,深度优化漫画作品展示结构与章节管理模式。前端采用响应式布局设计,适配各类漫画阅读场景,提供作品分类、连载追踪、热度排行等垂直领域功能模块。查看源码 -
(PC+WAP)绣花刺绣传统手工工艺pbootcms网站源码下载这款基于PbootCMS的网站模板为刺绣和传统手工艺行业设计,采用优雅的布局和精致的细节处理,能够呈现手工艺品的独特韵味和文化内涵。模板结构合理,功能完善,是手工艺从业者展示作品的理想选择。查看源码 -
(自适应响应式)化妆美容口红唇膏化妆品模板pbootcms源码下载基于PbootCMS开发的响应式模板,为化妆品品牌、美容机构打造,通过优雅的视觉呈现提升产品展示效果与品牌调性。采用时尚杂志排版风格,色卡系统规范产品展示。微交互动画增强用户体验,智能推荐算法提升产品关联展示效果。查看源码 -
pbootcms模板(PC+WAP)火锅加盟餐饮美食类带留言源码基于PbootCMS内核深度开发,为火锅、餐饮品牌打造的营销型解决方案。采用红色主题传递行业活力,实现PC与WAP端适配。查看源码
| 分享笔记 (共有 篇笔记) |
