admin 管理员组文章数量: 1087139
2024年4月25日发(作者:html框架布局)
网上找到的qq协议的TEA加密和解密说明如下: 也有很多源代码,但是感觉上代码比
较复杂,不容易看。我用C#重写了下。 基于2008协议
* QQ消息的加密算法是一个16次的迭代过程,并且是反馈的,每一个加密单元是
8字节,输出也是8字节,密钥是16字节
* 我们以prePlain表示前一个明文块,plain表示当前明文块,crypt表示当前
明文块加密得到的密文块,preCrypt表示前一个密文块
* f表示加密算法,d表示解密算法 那么从plain得到crypt的过程是:
* crypt = f(plain ^ preCrypt) ^ prePlain
* 所以,从crypt得到plain的过程自然是
* plain = d(crypt ^ prePlain) ^ preCrypt
* 此外,算法有它的填充机制,其会在明文前和明文后分别填充一定的字节数,以保
证明文长度是8字节的倍数
* 填充的字节数与原始明文长度有关,填充的方法是:
*
* ------- 消息填充算法 -----------
* a = (明文长度 + 10) mod 8
* if(a 不等于 0) a = 8 - a;
* b = 随机数 & 0xF8 | a; 这个的作用是把a的值保存了下
来
* plain[0] = b; 然后把b做为明文的第0个字节,这样第0
个字节就保存了a的信息,这个信息在解密时就要用来找到真正明文的起始位置
* plain[1 至 a+2] = 随机数 & 0xFF; 这里用随机数填充明文的第1到
第a+2个字节
* plain[a+3 至 a+3+明文长度-1] = 明文; 从a+3字节开始才是真正的明文
* plain[a+3+明文长度, 最后] = 0; 在最后,填充0,填充到总长度为8
的整数为止。到此为止,结束了,这就是最后得到的要加密的明文内容
* ------- 消息填充算法 ------------
///
public static class QQCrypter { private static void code(byte[] In, int inOffset,
int inPos, byte[] Out, int outOffset, int outPos, byte[] key) { if
(outPos > 0) { for (int i = 0; i < 8; i++)
{ In[outOffset + outPos + i] = (byte)(In[inOffset + inPos + i] ^
Out[outOffset + outPos + i - 8]); } } uint[]
formattedKey = FormatKey(key); uint y = ConvertByteArrayToUInt(In, outOffset
+ outPos); uint z = ConvertByteArrayToUInt(In, outOffset + outPos + 4);
uint sum = 0; uint delta = 0x9e3779b9; uint n = 16;
while (n-- > 0) { sum += delta; y += ((z
<< 4) + formattedKey[0]) ^ (z + sum) ^ ((z >> 5) + formattedKey[1]); z +=
((y << 4) + formattedKey[2]) ^ (y + sum) ^ ((y >> 5) + formattedKey[3]); }
(ConvertUIntToByteArray(y), 0, Out, outOffset + outPos, 4);
(ConvertUIntToByteArray(z), 0, Out, outOffset + outPos + 4, 4); if
(inPos > 0) { for (int i = 0; i < 8; i++)
{ Out[outOffset + outPos + i] = (byte)(Out[outOffset + outPos + i] ^
In[inOffset + inPos + i - 8]); } } }
private static void decode(byte[] In, int inOffset, int inPos, byte[] Out, int outOffset, int outPos,
byte[] key) { if (outPos > 0) { for
(int i = 0; i < 8; i++) { Out[outOffset + outPos + i] =
(byte)(In[inOffset + inPos + i] ^ Out[outOffset + outPos + i -
8]); } } else
{ (In, inOffset, Out, outOffset, 8); }
uint[] formattedKey = FormatKey(key); uint y = ConvertByteArrayToUInt(Out,
outOffset + outPos); uint z = ConvertByteArrayToUInt(Out, outOffset + outPos +
4); uint sum = 0xE3779B90; uint delta = 0x9e3779b9;
uint n = 16; while (n-- > 0) { z -= ((y << 4) +
formattedKey[2]) ^ (y + sum) ^ ((y >> 5) + formattedKey[3]); y -= ((z << 4)
+ formattedKey[0]) ^ (z + sum) ^ ((z >> 5) + formattedKey[1]); sum -=
delta; } (ConvertUIntToByteArray(y), 0, Out, outOffset
+ outPos, 4); (ConvertUIntToByteArray(z), 0, Out, outOffset + outPos
+ 4, 4); } /**////
/// 密文 /// 密文开始的位置
/// 密文长度 ///
name="key">密钥 ///
byte[] Decrypt(byte[] In, int offset, int len, byte[] key) { // 因为QQ消
息加密之后至少是16字节,并且肯定是8的倍数,这里检查这种情况 if ((len %
8 != 0) || (len < 16)) { return null; }
byte[] Out = new byte[len]; for (int i = 0; i < len; i += 8)
{ decode(In, offset, i, Out, 0, i, key); } for (int
i = 8; i < len; i++) { Out[i] = (byte)(Out[i] ^ In[offset + i -
8]); } int pos = Out[0] & 0x07; len = len - pos - 10;
byte[] res = new byte[len]; (Out, pos + 3, res, 0, len);
return res; } public static byte[] Encrypt(byte[] In, int offset, int len, byte[]
key) { // 计算头部填充字节数 int pos = (len + 10) % 8;
if (pos != 0) { pos = 8 - pos; } byte[]
plain = new byte[len + pos + 10]; plain[0] = (byte)((() & 0xF8) | pos);
for (int i = 1; i < pos + 3; i++) { plain[i] = (byte)(() &
0xFF); } (In, 0, plain, pos + 3, len); for (int
i = pos + 3 + len; i < ; i++) { plain[i] =
/a/biancheng/jmjm/wzsf/2012/0915/
版权声明:本文标题:QQ协议TEA加密解密代码 C# 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/b/1714031446a662321.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论