C#版QQTea加密
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace WindowsFormsApplication1
{
/// <summary>
/// 加密解密QQ消息包的工具类.
/// </summary>
public static class QQCrypter
{
private static void code(byte[] In, int inOffset, int inPos, byte[] Out, int outOffset, int outPos, byte[] key)
{
if (outPos > )
{
for (int i = ; i < ; i++)
{
In[outOffset + outPos + i] = (byte)(In[inOffset + inPos + i] ^ Out[outOffset + outPos + i - ]);
}
}
uint[] formattedKey = FormatKey(key);
uint y = ConvertByteArrayToUInt(In, outOffset + outPos);
uint z = ConvertByteArrayToUInt(In, outOffset + outPos + );
uint sum = ;
uint delta = 0x9e3779b9;
uint n = ; while (n-- > )
{
sum += delta;
y += ((z << ) + formattedKey[]) ^ (z + sum) ^ ((z >> ) + formattedKey[]);
z += ((y << ) + formattedKey[]) ^ (y + sum) ^ ((y >> ) + formattedKey[]);
}
Array.Copy(ConvertUIntToByteArray(y), , Out, outOffset + outPos, );
Array.Copy(ConvertUIntToByteArray(z), , Out, outOffset + outPos + , );
if (inPos > )
{
for (int i = ; i < ; i++)
{
Out[outOffset + outPos + i] = (byte)(Out[outOffset + outPos + i] ^ In[inOffset + inPos + i - ]);
}
}
} private static void decode(byte[] In, int inOffset, int inPos, byte[] Out, int outOffset, int outPos, byte[] key)
{
if (outPos > )
{
for (int i = ; i < ; i++)
{
Out[outOffset + outPos + i] = (byte)(In[inOffset + inPos + i] ^ Out[outOffset + outPos + i - ]);
}
}
else
{
Array.Copy(In, inOffset, Out, outOffset, );
}
uint[] formattedKey = FormatKey(key);
uint y = ConvertByteArrayToUInt(Out, outOffset + outPos);
uint z = ConvertByteArrayToUInt(Out, outOffset + outPos + );
uint sum = 0xE3779B90;
uint delta = 0x9e3779b9;
uint n = ; while (n-- > )
{
z -= ((y << ) + formattedKey[]) ^ (y + sum) ^ ((y >> ) + formattedKey[]);
y -= ((z << ) + formattedKey[]) ^ (z + sum) ^ ((z >> ) + formattedKey[]);
sum -= delta;
}
Array.Copy(ConvertUIntToByteArray(y), , Out, outOffset + outPos, );
Array.Copy(ConvertUIntToByteArray(z), , Out, outOffset + outPos + , );
} /**/
/// <summary>
/// 解密
/// </summary>
/// <param name="In">密文</param>
/// <param name="offset">密文开始的位置</param>
/// <param name="len">密文长度</param>
/// <param name="key">密钥</param>
/// <returns>返回明文</returns>
public static byte[] Decrypt(byte[] In, int offset, int len, byte[] key)
{
// 因为QQ消息加密之后至少是16字节,并且肯定是8的倍数,这里检查这种情况
if ((len % != ) || (len < ))
{
return null;
}
byte[] Out = new byte[len];
for (int i = ; i < len; i += )
{
decode(In, offset, i, Out, , i, key);
}
for (int i = ; i < len; i++)
{
Out[i] = (byte)(Out[i] ^ In[offset + i - ]);
}
int pos = Out[] & 0x07;
len = len - pos - ;
byte[] res = new byte[len];
Array.Copy(Out, pos + , res, , len);
return res;
} public static byte[] Encrypt(byte[] In, int offset, int len, byte[] key)
{
// 计算头部填充字节数
int pos = (len + ) % ;
if (pos != )
{
pos = - pos;
}
byte[] plain = new byte[len + pos + ];
Random Rnd = new Random();
plain[] = (byte)((Rnd.Next() & 0xF8) | pos);
for (int i = ; i < pos + ; i++)
{
plain[i] = (byte)(Rnd.Next() & 0xFF);
}
Array.Copy(In, , plain, pos + , len);
for (int i = pos + + len; i < plain.Length; i++)
{
plain[i] = 0x0;
}
// 定义输出流
byte[] outer = new byte[len + pos + ];
for (int i = ; i < outer.Length; i += )
{
code(plain, , i, outer, , i, key);
}
return outer;
} private static uint[] FormatKey(byte[] key)
{
if (key.Length == )
{
throw new ArgumentException("Key must be between 1 and 16 characters in length");
}
byte[] refineKey = new byte[];
if (key.Length < )
{
Array.Copy(key, , refineKey, , key.Length);
for (int k = key.Length; k < ; k++)
{
refineKey[k] = 0x20;
}
}
else
{
Array.Copy(key, , refineKey, , );
}
uint[] formattedKey = new uint[];
int j = ;
for (int i = ; i < refineKey.Length; i += )
{
formattedKey[j++] = ConvertByteArrayToUInt(refineKey, i);
}
return formattedKey;
} private static byte[] ConvertUIntToByteArray(uint v)
{
byte[] result = new byte[];
result[] = (byte)((v >> ) & 0xFF);
result[] = (byte)((v >> ) & 0xFF);
result[] = (byte)((v >> ) & 0xFF);
result[] = (byte)((v >> ) & 0xFF);
return result;
} private static uint ConvertByteArrayToUInt(byte[] v, int offset)
{
if (offset + > v.Length)
{
return ;
}
uint output;
output = (uint)(v[offset] << );
output |= (uint)(v[offset + ] << );
output |= (uint)(v[offset + ] << );
output |= (uint)(v[offset + ] << );
return output;
}
} }
C#版QQTea加密的更多相关文章
- 简易版DES加密和解密详解
在DES密码里,是如何进行加密和解密的呢?这里采用DES的简易版来进行说明. 二进制数据的变换 由于不仅仅是DES密码,在其它的现代密码中也应用了二进制数据,所以无论是文章还是数字,都需要将明文变换为 ...
- OpenLdap的加密md5(Java+Python,同时提供明文-->密文,md5(名文)-->密文两种方法)
# slappasswd -h {md5} -s "secret"{MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== import base64 import hashli ...
- PHP:使用Zend对源码加密、Zend Guard安装以及Zend Guard Run-time support missing的解决方法
Zend Guard是目前市面上最成熟的PHP源码加密产品了.刚好需要对自己的产品进行加密,折腾了一晚上,终于搞定,将碰到的问题及解决方法记录下来,方便日后需要,也可以帮助其他人.我使用的是Wamps ...
- ioncube 加密软件 linux 使用方法
https://www.ioncube.com/sa_encoder.php?page=pricing 购买成功后 解压文件包 装了一个linux 版的加密软件 目录:/webdata/soft/io ...
- 加密文件之Java改进版
对应Python版:加密文件之Python版Java版比Python版要快得多,两个版本不在一个量级上.在加密解密1G大文件时,Java版花费的时间是秒级,而Python版花费的时间是10分钟级. i ...
- asp.net AES加密跟PHP的一致,将加密的2进制byte[]转换为16进制byte[] 的字符串获得
<?php class AESUtil { public static function encrypt($input, $key) { $size = mcrypt_get_block_siz ...
- python爬虫---详解爬虫分类,HTTP和HTTPS的区别,证书加密,反爬机制和反反爬策略,requests模块的使用,常见的问题
python爬虫---详解爬虫分类,HTTP和HTTPS的区别,证书加密,反爬机制和反反爬策略,requests模块的使用,常见的问题 一丶爬虫概述 通过编写程序'模拟浏览器'上网,然后通 ...
- robotframework 接口测试 +RSA 加密
首先,实现RSA加密,需要用到pycrypto这个库,这个库又依赖openssl,所以需要先下载openssl,具体教程可以参考http://bbs.csdn.net/topics/392193545 ...
- Base64加密工具
正常来讲加密基本上永远都要伴随着解密,所谓的加密或者解密,往往都需要有一些规则,在JDK1.8开始,提供有新的加密处理操作类,Base64处理类--Base64类 在该类之中存在两个内部类:Base6 ...
随机推荐
- Difference Between Mod_Python & Mod_Wsgi | eHow
Difference Between Mod_Python & Mod_Wsgi | eHow x YES NO Why not? Thanks for he ...
- find -exec
find -exec 的标准写法 find ./ -name "*.tmp" -exec rm -rf "{}" \; find -exec 这个命令组合很好用 ...
- 云脉提供表单识别API接口自助接入
如今随着信息化.数字化时代的到来,利用纯人工进行数据录入已经不能满足海量信息数字化的需求.这时候有OCR表单识别技术,一切问题都能够迎刃而解了.云脉表单识别SDK采用成熟的OCR技术,通过创建票据的模 ...
- navigationBar 背景色
if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 7.0) { [[UINavigationBar appearance] s ...
- IOS 快速排序法
- (NSMutableArray *)QuickSort:(NSMutableArray *)list StartIndex:(NSInteger)startIndex EndIndex:(NSIn ...
- dojo事件
dojo.connect 和 dojo.disconnect /*建立连接*/ dojo.connect(/*Object|null*/ obj, /*String*/ event, /*Object ...
- LINQ 操作符
using System; using System.Collections.Generic; using System.Text; using System.Linq; namespace LinQ ...
- Sql Server 2012启动存储过程
可以通过如下步骤创建 1.打开show advanced options reconfigure 2.打开scan for startup procs,使得sql server在启动时扫描需要运行的p ...
- html 基础之 <link>标签
实例 链接一个外部样式表: <head> <link rel="stylesheet" type="text/css" href=" ...
- 2Sum,3Sum,4Sum,kSum,3Sum Closest系列
1).2sum 1.题意:找出数组中和为target的所有数对 2.思路:排序数组,然后用两个指针i.j,一前一后,计算两个指针所指内容的和与target的关系,如果小于target,i右移,如果大于 ...