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. GridBagLayout练习

    摘自http://blog.csdn.net/qq_18989901/article/details/52403737  GridBagLayout的用法 GridBagLayout是面板设计中最复杂 ...

  2. 3第一周课后练习&#183;阅读计划(3)-使用函数来访问私有数据成员

    /* * Copyright (c) 2015, 计算机科学学院,烟台大学 * All rights reserved. * 文件名:test.cpp * 作 靠:刘畅 * 完成日期:2015年 3 ...

  3. Html5 代码

      随着HTML5的流行,许多网站开始介绍HTML5元素和属性的用法,以及各种教程,并且越来越多老的浏览器开始兼容HTML5. 本文作者编译了10段非常实用的HTML5代码片段,开发者可以直接拿过去使 ...

  4. 跨服务器的sql使用

    由于想从别的服务器上的数据库导入一些数据过来 经网上查阅,得到 select * from openrowset( 'SQLOLEDB', '服务器名字'; '用户名'; '密码',数据库名字.dbo ...

  5. Unity IOC注入详细配置(MVC,WebApi)

    一直想写一篇关于unity 详细的配置信息的文章,也算是自我总结吧 先介绍了unity , Unity是微软官方推荐使用的轻型的IOC框架,支持各种方式的注入 ,使用来解耦的利器. 获取unity 的 ...

  6. 使用FMDB,libqrencode实现二维码的生成并且保存到数据库

    /**  * 1.首先导入第三方库FMDB和libqrencode,添加库libsqlite3.tbd     

  7. Eclipse MyEclipse 复制项目 复制现有项目 复制功能相似项目

    如果现在已经存在一个Java Web项目 ProjectA,现在想做另外一个项目,里面绝大部分功能和结构都可以复用,如果想通过复制的方法来,那么可以这么做: 1.到资源管理器中,将ProjectA文件 ...

  8. Java之定时任务详解

    在我们编程过程中如果需要执行一些简单的定时任务,无须做复杂的控制,我们可以考虑使用JDK中的Timer定时任务来实现.下面就其原理.实例以及Timer缺陷三个方面来解析java Timer定时器. 在 ...

  9. php 数组 array_values () array_key()

    <?php // array_unique($array) 去除重复 // array_unshif()向数组的顶部追加函数 // array_shif($a,"ss")向数 ...

  10. 1206: B.求和

    题目描述 点击这里 对于正整数n,k,我们定义这样一个函数f,它满足如下规律 现在给出n和k,你的任务就是要计算f(n,k)的值. 输入 首先是一个整数T,表示有T组数据 接下来每组数据是n和k(1& ...