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 ...
随机推荐
- canvas arcTo()用法详解 – CodePlayer
canvas arcTo()用法详解 – CodePlayer canvas arcTo()用法详解
- Java菜鸟学习笔记--数组篇(三):二维数组
定义 //1.二维数组的定义 //2.二维数组的内存空间 //3.不规则数组 package me.array; public class Array2Demo{ public static void ...
- IOS 计算密码强度
+ (BOOL) judgeRange:(NSArray*)conditionArr Password:(NSString*)password { NSRange range; BOOL result ...
- kettle工具二次开发-代码启动JOB
kettle工具是一款优秀的数据同步.数据处理的BI工具,收到了很多人的青睐.kettle软件通过可视化的图标可以让我们很轻易的能完成数据同步.处理的开发工作.但是使用kettle可视化界面在跑JOB ...
- 使用 React和webpack开发和打包发布
建议在 React 中使用 CommonJS 模块系统,比如 browserify 或 webpack,本次使用 webpack. 第一步.安装全局包 $ npm install babel -g $ ...
- UGUI实现的虚拟摇杆,可改变摇杆位置
实现方式主要参考这篇文章:http://www.cnblogs.com/plateFace/p/4687896.html. 主要代码如下: using UnityEngine; using Syste ...
- GCC、GDB、Makefile
1.GCC程序编译 Linux系统下的gcc(GNUCCompiler)是GNU推出的功能强大.性能优越的多平台编译器,是GNU的代表作之一.gcc可以在多种硬体平台上编译出可执行程序,其执行效率与一 ...
- RMAN备份各种物理文件
RMAN运行脚本的方式:RMAN TARGET / @backup_db.rmanRMAN TARGET / cmdfile=backup_db.rman在RMAN中执行操作系统中保存的脚本:RMAN ...
- SpringMVC+JPA+Hibernate配置
首先,Spring配置文件 <?xml version="1.0" encoding="UTF-8"?><beans xmlns=" ...
- UIView的clipsTobounds属性
这里的clip是修剪的意思,bounds是边界的意思,合起来就是:如果子视图的范围超出了父视图的边界,那么超出的部分就会被裁剪掉.该属性在实际工程中还是非常实用的,必须要了解清楚.