根据腾讯公开的JS文件分析QQTEA算法
来源:互联网 发布:数控冲床编程教程 编辑:程序博客网 时间:2024/06/11 03:45
前言
根据网上的众多分析来看,很多QQTEA算法要么是反编译分析的,要么是根据其他版本改写的,很少有直接根据源码分析改写的,而且很多分析体现在源码里,梳理性的内容不多。后面的人去看又要重新梳理。
一、寻找函数
这里根据腾讯公开的JS文件分析,比反编译简单一些,至少能直接看到源码,JS文件:c_login_2.js
首先,看到这个JS很多人可能无从下手,首先要做的就是下载下来然后格式化
需要注意的是,网上大多数在线格式化网站不能正确的处理自执行函数,建议使用eclipse或者webstorm
eclipse格式化之后,有5639行,那么怎么才能找到TEA算法所在函数呢,搜索即可,不过我已经找好了
在notepad++下,Alt+0折叠所有,找到带一个参数的自执行函数,展开就可以了,注意:这个js文件一共有两个自执行函数,找不准的搜索关键字tea吧
找到之后,我们把这个函数单独拷贝出来调试,具体内容这里就不贴了,太长了
二、调用函数
接下来我们来看一下这个函数的加密解密效果,可能有人不知道怎么调,这里介绍两种方法
F12控制台法:Chrome或者Firefox打开一个空页面,复制这个函数,直接粘贴到控制台,回车,
然后复制如下语句
TEA.initkey("111");var jiamihou = TEA.encrypt("8888999911112222");console.log(jiamihou);var jiemihou = TEA.decrypt(jiamihou);console.log(jiemihou);效果如下
JS文件法:新建一个js文件如tea.js,复制前面那个函数,然后在函数结束的分号后面再加一段
TEA.initkey("111");var jiamihou = TEA.encrypt("8888999911112222");alert(jiamihou);var jiemihou = TEA.decrypt(jiamihou);alert(jiemihou);之后新建一个空白的html页面,在页面的,head>标签里面引用这个js
<script src="qqtea.js"></script>之后用浏览器打开这个页面就能看到两个弹窗效果了。
三、分析函数(加密篇)
上面只是演示这个函数的效果,下面才是重头戏,分析这个js的加密解密过程
加密方法:
encrypt: function (E, D) { var C = q(E, D); var B = j(C); return y(B) },其中q(E, D)方法是转码用的,方法如下
//转码,如果E参数存在,直接转ascii码存入数组,如果不存在,每两位当做16进制转ASCII码//D数组的长度取决于传入F的长度 function q(F, E) { var D = [ ]; if (E) { for (var C = 0; C < F.length; C++) { D[C] = F.charCodeAt(C) & 255 //取ASCII码,只取8位 } } else { var B = 0; for (var C = 0; C < F.length; C += 2) { D[B++] = parseInt(F.substr(C, 2), 16) //把F当做16进制的字符串,每取两位存一下 } } return D }j(C)方法才是用来加密的
//加密函数 function j(D) { h = new Array(8); z = new Array(8); A = w = 0; p = true; a = 0; var B = D.length; //获取要加密字符串的长度 var E = 0; a = (B + 10) % 8; if (a != 0) { a = 8 - a } //a为需要填充的字符个数 o = new Array(B + a + 10); //填充为8的整数倍数组 h[0] = ((f() & 248) | a) & 255; //取f()的3~8位与a做或运算,这里把a存进去了,解密的时候可以推算出填充个数 for (var C = 1; C <= a; C++) { h[C] = f() & 255 //取f()的8位存入,填充用的,可以不管 } a++; for (var C = 0; C < 8; C++) { //初始化数组z z[C] = 0 } E = 1; while (E <= 2) { if (a < 8) { h[a++] = f() & 255; //继续填充 E++ } if (a == 8) { r() //每次执行r(),a会重置为0 } } var C = 0; while (B > 0) { if (a < 8) { h[a++] = D[C++]; //把D数组的内容复制到h数组后面 B-- } if (a == 8) { r() //每次取出待加密数据的一个块,h[0]~h[7],送到r()处理 } } E = 1; while (E <= 7) { if (a < 8) { h[a++] = 0; //填充0 E++ } if (a == 8) { r() } } return o }加密总体思路:填充算法-->QQCBC交织算法-->TEA算法,先看填充算法
(一)填充算法
参考这张图说明一下:
因为TEA加密只能加密定长的数据,所以QQ这里先分组,分组后给TEA加密,一个分组大小是8字节,所以填充完要是8字节的倍数
QQ在填充后的数据长度=原始数据长度+a+10
其中a的算法: 如果(B + 10) % 8=0,则a=0,如果(B + 10) % 8=!0则a=8-((B + 10) % 8)
整个数据区概况:1个字节标识a的长度(低位填充a,高位填充随机数)+a个字节的随机数填充+2位随机数填充+原始数据+7个字节0填充
数据区每取到8个字节就用r()函数加密一次
(二)、QQCBC交织算法
r()函数采用类似CBC模式
为什么是类似CBC,因为QQ的CBC模式比标准多了一步异或
QQCBC模式是这样的
与标准CBC多出来的异或在下图用红框标注出来了
QQCBC对应的代码如下:
//交织算法CBC加密 function r() { for (var B = 0; B < 8; B++) { if (p) { h[B] ^= z[B] } else { h[B] ^= o[w + B] } } var C = l(h); //CBC算法使用的加密器,TEA加密 for (var B = 0; B < 8; B++) { o[A + B] = C[B] ^ z[B]; //这里比标准的CBC算法多了一步异或 z[B] = h[B] } w = A; A += 8; a = 0; p = false }
图中的加密器使用的是16轮标准TEA加密,这个QQ没有改
(三)、TEA算法
标准TEA算法的图可以参考我之前写过的:TEA、XTEA、XXTEA加密解密算法
为了文章的完整性,这里也贴一下,图是一轮加密的描述
QQ的TEA用的16轮加密,标准用的32轮,常数delta=0x9e3779b9十进制就是2654435769,存储加密结果的时候使用的是网络序,代码如下
//tea加密算法主体 function l(B) { //u是CBC算法加密器对应的key,也就是tea对应的key var C = 16; //16轮 var H = k(B, 0, 4); //取B[0]~B[3],形成字符串,B[0]在前,TEA算法左边v0 var G = k(B, 4, 4); //TEA算法右边v1 var J = k(u, 0, 4); //TEA秘钥k1 var I = k(u, 4, 4); //TEA秘钥k2 var F = k(u, 8, 4); //TEA秘钥k3 var E = k(u, 12, 4); //TEA秘钥k4 var D = 0; var K = 2654435769 >>> 0; //无符号右移,TEA算法的delta常数 while (C-- > 0) { D += K; D = (D & 4294967295) >>> 0; H += ((G << 4) + J) ^ (G + D) ^ ((G >>> 5) + I); //计算TEA左边 H = (H & 4294967295) >>> 0; G += ((H << 4) + F) ^ (H + D) ^ ((H >>> 5) + E); G = (G & 4294967295) >>> 0 } var L = new Array(8); b(L, 0, H); b(L, 4, G); return L }
(四)、常见问题
4.自匿名函数中几个全局变量的作用
var u = '',a = 0, h = [],z = [], A = 0,w = 0,o = [], v = [], p = true; //u是初始秘钥,由initkey方法负责初始化,用于tea算法加密使用//z为交织算法CBC中的初始向量IV或上一个密文块//h为交织算法CBC中的明文块,计算过程中没有存所有明文h[0]~h[7]只存当前要计算的明文块//o为交织算法CBC中的密文,其中o[w + 0] ~o[w + 7]为第w个密文块//p标识是否为CBC中的明文块的第一块5.自匿名函数的其他调用方法
TEA.initkey("111")可以改写为window.TEA.initkey("111"),其他以此类推。因为自匿名函数传了window参数进去,所以这些方法也是window对象的函数。
- 根据腾讯公开的JS文件分析QQTEA算法
- 根据红黑树的算法来分析TreeMap的实现
- 最强的公开文件方法
- js 根据屏幕大小调用不同的css文件
- js 根据屏幕大小调用不同的css文件
- 根据浏览器语言,页面动态加载对应的js文件
- TEA、QQTEA
- 公开密钥和公开算法的密码机制到底是什么意思
- 普林斯顿公开课 算法1-1:算法分析
- MIT公开课《算法导论》笔记一:算法分析
- DTD分析与总结(根据struts2的dtd文件)
- JS判断各种浏览器,根据判断动态引入不同的CSS文件、JS文件
- JS判断各种浏览器,根据判断动态引入不同的CSS文件、JS文件
- Node.js腾讯云COS文件上传
- 最大的背景差算法公开库
- 采集腾讯天气的js
- 大数乘法的几种算法分析及比较(2014腾讯南京笔试题)
- 大数乘法的几种算法分析及比较(2014腾讯南京笔试题)
- 最长公共子序列 LCS 【长度及打印】
- JSP页-servlet-JSP页
- 用div绘制箭头
- vue.js分页中单击页码更换页面内容(配合spring springmvc)
- HDU_1231 最大连续子序列 【动态规划】
- 根据腾讯公开的JS文件分析QQTEA算法
- (转)Git Cheat Sheet 中文版
- VBA编程实现EXECL根据表2数据修改表1
- Android使用Intent传递对象的两种方式
- BZOJ3450: Tyvj1952 Easy
- Android Studio项目 目录含义
- Android 多线程编程
- NYOJ-37-回文字符串【LCS】
- Android 使用网络技术