最近在使用Java实现QQ的基本通讯协议,QQ的通讯协议中使用MD5算法两次加密密码,并将通讯中的所有数据包使用TEA算法进行加密。MD5加密可以通过Java API提供的MessageDigest直接进行,而TEA加密则需自己编写。
TEA加密每次使用128bit密钥加密64bit数据,生成加密数据亦为64bit,为典型的对称加密算法。该算法使用C语言实现非常简单,但使用Java进行实现时,受制于Java的特性,在实现上稍有复杂。
代码如下:
public class TEA { /** * value is 0xffffffff * filter long to unsigned int */ public static Long UIFILTER = Long.decode("0xffffffff"); /** * value is 0xff * filter short to unsigned byte */ public static Short UBFILTER = Short.decode("0xff"); /** * Encipher method * 64bit plaintext, 128bit key * @param v Plaintext * @param k Key * @return */ public static Short[] encipher(Short [] v, Short [] k) { Long[] vL = shortToLong(v); Long[] kL = shortToLong(k); Long[] wL = new Long[vL.length]; Short[] w = null; long y = vL[0]; long z = vL[1]; long a = kL[0]; long b = kL[1]; long c = kL[2]; long d = kL[3]; long n = 0x10; /* do encrypt 16 (0x10) times */ long sum = 0; long delta = Long.decode("0x9E3779B9"); /* 0x9E3779B9 - 0x100000000 = -0x61C88647 */ while (n-- > 0) { sum += delta; sum &= UIFILTER; y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); y &= UIFILTER; z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); z &= UIFILTER; } wL[0] = y; wL[1] = z; w = longToShort(wL); return w; } /** * Decipher method * 64bit ciphertext, 128bit key * @param v Ciphertext * @param k Key * @return */ public static Short[] decipher(Short [] v, Short [] k) { Long[] vL = shortToLong(v); Long[] kL = shortToLong(k); Long[] wL = new Long[vL.length]; Short[] w = null; long y = vL[0]; long z = vL[1]; long a = kL[0]; long b = kL[1]; long c = kL[2]; long d = kL[3]; long n = 0x10; /* sum = delta << 4, in general sum = delta * n */ long sum = Long.decode("0xE3779B90"); long delta = Long.decode("0x9E3779B9"); // use filter to get unsigned int // use ~x +1 instead -x while (n-- > 0) { z += (~(((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d)) + 1); z &= UIFILTER; y += (~(((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b)) + 1); y &= UIFILTER; sum += ((~delta) + 1); sum &= UIFILTER; } wL[0] = y; wL[1] = z; w = longToShort(wL); return w; } /** * convert bytes to longs, put every 4 bytes to 1 long * use long instead unsigned int * use short instead unsigned byte * @param source - the Short [] that save unsigned bytes to convert * @return the Long [] save unsigned int */ public static Long [] shortToLong(Short [] source){ int sourlen = source.length; int turn = sourlen / 4; // how many turns int remainder = sourlen % 4; // how many bytes in first turn int tarlen = turn + (remainder == 0 ? 0 : 1); Long [] target = new Long[tarlen]; for(int i = 0; i < target.length; i++){ target[i] = Long.parseLong("0"); } int iter = 0; int turnIter = 0; for(turnIter = 0; turnIter < tarlen; turnIter++){ for(iter = 0; iter < 4; iter++){ target[turnIter] <<= 8; if((turnIter != turn - 1) || ((turnIter == turn - 1) && (iter < remainder || remainder == 0))) target[turnIter] += source[turnIter * 4 + iter]; } } return target; } /** * convert longs to bytes * cut 1 long(32bit valid to instead unsigned int) to 4 short(8bit valid to instead unsigned byte) * use long instead unsigned int * use short instead unsigned byte * @param source - the Long [] that save unsigned int to convert * @return the Short [] that save unsigned bytes */ public static Short [] longToShort(Long [] source){ int sourlen = source.length; Short [] target = new Short[sourlen * 4]; int turn = target.length % 4; int iter = 0; int move = 0; for(iter = 0; iter < target.length; iter++){ move = 8 * (3 - (iter % 4)); target[iter] = Short.parseShort(Long.toString((source[iter / 4] & (UBFILTER << move)) >> move)); } return target; } } [/code] 代码中需要注意的几点如下: 由于Java种没有无符号数的概念,故如int, long, byte等基础类型其最高位均为符号位,故不能使用该种类型进行无符号运算。本代码中使用long代替unsigned int,使用short代替unsigned byte。 相 对C语言代码,在解密时不使用减法,而是用取反加一的方式将减法转换为加法。这是由于Java中Long类型是有符号的,其进行的计算亦为有符号计算。若 被减数小于减数时,减法结果将为负数,这不符合无符号减法的规则。转化为加法运算后,将其高位溢出,则可得无符号减法的结果。 由于Java中不允许高位溢出,会抛出异常,故高位溢出需要手工完成,即将运算结果与0xffffffff或0xff进行与运算(视具体类型而定)。 测试类如下: [code=java] public class TestPoint { public static void main(String [] args){ Long[] keyLong = new Long[4]; //加密解密所用的KEY keyLong[0] = Long.decode("0x789f5645"); keyLong[1] = Long.decode("0xf68bd5a4"); keyLong[2] = Long.decode("0x81963ffa"); keyLong[3] = Long.decode("0x458fac58"); Short[] key = TEA.longToShort(keyLong); Short[] info = new Short[]{ 1, 2, 3, 4, 5, 6, 7, 8 }; System.out.print("原数据:"); for(Short i : info) System.out.print(i + " "); System.out.println(); Short[] secretInfo = TEA.encipher(info, key); System.out.print("加密后的数据:"); for(Short i : secretInfo) System.out.print(i + " "); System.out.println(); Short[] decryptInfo = TEA.decipher(secretInfo, key); System.out.print("解密后的数据:"); for(Short i : decryptInfo) System.out.print(i + " "); } }
相关推荐
TEA加密算法Java实现.txt
Tea加密算法的实现 一个类文件 简单版
用java实现了Tea加密,解密过程。经过C项目,java项目对接测试通过
Tea算法(java版本,带测试程序,二次封装)
经过封装和接口定义,直接可以使用。用在网络数据快速加密,比较适用。
delphi TEA 加密算法 源码 解压即可运行
TEA加密算法的C_C++实现
Java Tea加密实现
TEA算法由剑桥大学计算机实验室的David Wheeler和Roger Needham于1994年发明。...TEA算法利用不断增加的Delta(黄金分割率)值作为变化,使得每轮的加密是不同,该加密算法的迭代次数可以改变,建议的迭代次数为32轮。
delphi TEA 加密算法 源码 解压即可运行,经过自己加工
用c#做一个窗口程序,使用tea算法加密数据库中的数据
主要介绍了c++代码实现tea加密算法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
本例提供了TEA加解密算法的C++代码。其中加解密过程分别计时并精确到微秒。本例是《计算机密码学》一课重要实验内容。代码由西大2011级工硕赵某编写……
易语言16轮TEA加密算法汇编教程
tea加密算法具体过程
tea c加密算法源码,希望对大家有所帮助。
TEA介绍及数据加密算法之程序代码
TEA加密算法详述学习资料.pdf
TEA加密算法的加强版XTEA的实现,包含EBC-TEA和CBC-TEA两个模式的不同加密方式。可用于测试分组加密的ECB和CBC的优劣性。
因此,TEA 作为加密散列函数尤其糟糕。这个弱点导致了一种破解微软 Xbox 游戏机(我第一次遇到它的地方)的方法,其中密码被用作哈希函数。TEA 也容易受到相关密钥攻击,该攻击需要在相关密钥对下选择 2^23 个选择的...