您现在的位置是:首页 > 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这个函数写的太精彩啦。
本文标签:
很赞哦! ()
相关教程
图文教程
freebsd+apache+mysql+php+phpmyadmin+zend+discuz傻瓜式教程
刚接触linux是今年4月的事情,装过不少linux发行版本,最终还是选择了unix中的freebsd,喜欢它的简洁。不过我也是初学者,将这10多天学freebsd的经验总结给大家分享
Discuz论坛怎么样?有哪些优势
Crossday Discuz! Board 论坛系统(简称 Discuz! 论坛,我国国家版权局著作权登记号 2006SR11895)是一个采用 PHP 和 MySQL 等其他多种数据库构建的高效论坛解决方案.作为商业
Discuz的NT前台模型架构MVC分析
通过前几个月我介绍了一些在项目中边边角角的类和项目。当然这种介绍只是前期热身准备。因为从这篇文章开始,本人将跟大家聊一聊关于这个产品架构上面的东西
discuz目录结构文件说明示例
| -- admin.php 管理员入口| -- api.php 接口文件| -- category.php 分类入口| -- cp.php 个人资料设置入口| -- crossdomain.xml FLASH跨域传输文件| -- favicon.ico
相关源码
-
(自适应响应式)装修装潢设计公司网站源码下载本模板为装修设计企业打造,采用PbootCMS内核开发,整体设计突出空间美学与功能性结合。首页采用大图轮播展示工程案例,服务项目模块支持三维效果展示,呈现装修设计企业的专业形象与技术实力。查看源码 -
(自适应)帝国cms7.5文章新闻博客整站源码( 带会员中心)本模板基于帝国CMS内核开发,为新闻资讯、个人博客及作品展示类网站设计。采用响应式布局技术,确保在手机、平板和电脑等不同设备上都能获得良好的浏览体验。查看源码 -
(自适应)蓝色五金制品配件管件pbootcms网站源码下载基于PbootCMS内核开发的五金行业专用模板,采用响应式设计架构,确保产品展示在各类移动设备上的呈现。通过模块化布局与工业风视觉设计,帮助五金企业高效展示产品规格、应用场景及技术支持,建立专业可靠的行业形象。查看源码 -
(自适应)行业协会工会机构单位pbootcms网站源码本模板基于PbootCMS内核开发,为行业协会、工会组织及机构单位量身打造。采用响应式布局设计,可自动适配手机、平板等移动设备,数据实时同步更新。模板包含行业资讯查看源码 -
(PC+WAP)地暖热水器烘干机节能设备网站模板下载为地暖热水器及节能设备企业设计的PbootCMS网站模板,集成产品展示、节能方案介绍、技术参数说明等专业模块。采用PC与移动端同步响应架构查看源码 -
宽屏自适应搬家家政快递物流公司网站模板该宽屏大气的响应式网站模板专为搬家公司、家政服务及物流快递企业设计,基于PbootCMS内核开发,通过自适应布局确保手机、PC等多终端体验一致,助力企业高效构建专业在线服务平台。查看源码
| 分享笔记 (共有 篇笔记) |
