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加密的更多相关文章

  1. 简易版DES加密和解密详解

    在DES密码里,是如何进行加密和解密的呢?这里采用DES的简易版来进行说明. 二进制数据的变换 由于不仅仅是DES密码,在其它的现代密码中也应用了二进制数据,所以无论是文章还是数字,都需要将明文变换为 ...

  2. OpenLdap的加密md5(Java+Python,同时提供明文-->密文,md5(名文)-->密文两种方法)

    # slappasswd -h {md5} -s "secret"{MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== import base64 import hashli ...

  3. PHP:使用Zend对源码加密、Zend Guard安装以及Zend Guard Run-time support missing的解决方法

    Zend Guard是目前市面上最成熟的PHP源码加密产品了.刚好需要对自己的产品进行加密,折腾了一晚上,终于搞定,将碰到的问题及解决方法记录下来,方便日后需要,也可以帮助其他人.我使用的是Wamps ...

  4. ioncube 加密软件 linux 使用方法

    https://www.ioncube.com/sa_encoder.php?page=pricing 购买成功后 解压文件包 装了一个linux 版的加密软件 目录:/webdata/soft/io ...

  5. 加密文件之Java改进版

    对应Python版:加密文件之Python版Java版比Python版要快得多,两个版本不在一个量级上.在加密解密1G大文件时,Java版花费的时间是秒级,而Python版花费的时间是10分钟级. i ...

  6. asp.net AES加密跟PHP的一致,将加密的2进制byte[]转换为16进制byte[] 的字符串获得

    <?php class AESUtil { public static function encrypt($input, $key) { $size = mcrypt_get_block_siz ...

  7. python爬虫---详解爬虫分类,HTTP和HTTPS的区别,证书加密,反爬机制和反反爬策略,requests模块的使用,常见的问题

    python爬虫---详解爬虫分类,HTTP和HTTPS的区别,证书加密,反爬机制和反反爬策略,requests模块的使用,常见的问题 一丶爬虫概述       通过编写程序'模拟浏览器'上网,然后通 ...

  8. robotframework 接口测试 +RSA 加密

    首先,实现RSA加密,需要用到pycrypto这个库,这个库又依赖openssl,所以需要先下载openssl,具体教程可以参考http://bbs.csdn.net/topics/392193545 ...

  9. Base64加密工具

    正常来讲加密基本上永远都要伴随着解密,所谓的加密或者解密,往往都需要有一些规则,在JDK1.8开始,提供有新的加密处理操作类,Base64处理类--Base64类 在该类之中存在两个内部类:Base6 ...

随机推荐

  1. java collection framework

    java collection framework Map

  2. http的无状态无连接到底是什么含义

    无连接:服务器处理完客户的请求,并收到客户的应答后,即断开连接. 早期这么做的原因是 HTTP协议产生于互联网,因此服务器需要处理同时面向全世界数十万.上百万客户端的网页访问,但每个客户端(即浏览器) ...

  3. Spring的AOP2

    本文是<AOP 那点事儿>的续集. 在上篇中,我们从写死代码,到使用代理:从编程式 Spring AOP 到声明式 Spring AOP.一切都朝着简单实用主义的方向在发展.沿着 Spri ...

  4. H5单页面架构:backbone + requirejs + zepto + underscore

    首先,来看看整个项目结构. 跟上一篇angular类似,libs里多了underscore和zepto.三个根目录文件: index.html:唯一的html main.js:requirejs的配置 ...

  5. JS实现给页面表单设置触发默认按钮

    var defaultBtnId; function setDefaultButton(id) { defaultBtnId = id; } document.onkeydown = function ...

  6. sql 随机数

    select FLOOR(rand()*16) 就是随机得到0到15之间的一个整数 select CEILING(rand()*15) 就是随机得到1到15之间的一个整数 FLOOR()为地板函数,取 ...

  7. UVALive 6959 - Judging Troubles

    给两组字符串,最多有多少对相同. map做映射判断一下. #include <iostream> #include <cstdio> #include <map> ...

  8. [Linked List]Insertion Sort List

    Total Accepted: 59422 Total Submissions: 213019 Difficulty: Medium Sort a linked list using insertio ...

  9. web.xml中<load-on-start>n</load-on-satrt>作用

    如下面一段配置,我们再熟悉不过了: 我们注意到它里面包含了这段配置:<load-on-startup>1</load-on-startup>,那么这个配置有什么作用呢? 作用如 ...

  10. 【搜索引擎Jediael开发笔记1】搜索引擎初步介绍及网络爬虫

    详细可参考 (1)书箱:<这就是搜索引擎><自己动手写网络爬虫><解密搜索引擎打桩实践> (2)[搜索引擎基础知识1]搜索引擎的技术架构 (3)[搜索引擎基础知识2 ...