|
分享源码
界面截图: |
- |
是否带模块: |
- |
备注说明: |
- |
本帖最后由 懒鸟 于 2024-9-6 16:30 编辑
分享这个是感觉这个加密也挺好用的,易语言的QQTEA加密解密应该一堆,用这个方法来跟服务器对接挺好哈,加密出来的内容每次都不一样。这源码还的PYTHON的,
易语言的代码就不贴了,直接去前辈帖子复制:https://bbs.125.la/forum.php?mod ... 180&highlight=QQTEA
Javascript代码:
[JavaScript] 纯文本查看 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TEA Encryption/Decryption</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
input, button {
margin-top: 10px;
display: block;
width: calc(100% - 22px);
box-sizing: border-box;
}
.error {
color: red;
font-size: 0.9em;
}
</style>
</head>
<body>
<h1>TEA Encryption/Decryption</h1>
<label for="cleartext">Cleartext (Hex):</label>
<input type="text" id="cleartext" value="5e65e7c7bf7d2c043a">
<label for="key">Key (Hex):</label>
<input type="text" id="key" value="00000000000000000000000000000000">
<button>Encrypt</button>
<button>Decrypt</button>
<h2>Results</h2>
<div>
<label for="encrypted">Encrypted (Hex):</label>
<input type="text" id="encrypted">
</div>
<div>
<label for="decrypted">Decrypted (Hex):</label>
<input type="text" id="decrypted">
</div>
<div id="error-message" class="error"></div>
<script>
function QQTEA() {
this.delta = 0x9E3779B9;
this.round = 16;
this.op = 0xFFFFFFFF;
this.xorBytes = function(a, b) {
if (a.length !== b.length) {
throw new Error('Invalid input lengths for XOR');
}
return new Uint8Array(a.length).map((_, i) => a ^ b);
};
this.encipher = function(t, keys) {
if (t.length !== 8 || keys.length !== 16) {
throw new Error('Invalid input length for encipher');
}
let sum = this.delta;
let uint32_1 = (t[0] << 24) | (t[1] << 16) | (t[2] << 8) | t[3];
let uint32_2 = (t[4] << 24) | (t[5] << 16) | (t[6] << 8) | t[7];
let keyArray = [
(keys[0] << 24) | (keys[1] << 16) | (keys[2] << 8) | keys[3],
(keys[4] << 24) | (keys[5] << 16) | (keys[6] << 8) | keys[7],
(keys[8] << 24) | (keys[9] << 16) | (keys[10] << 8) | keys[11],
(keys[12] << 24) | (keys[13] << 16) | (keys[14] << 8) | keys[15]
];
for (let i = 0; i < this.round; i++) {
uint32_1 += (((uint32_2 << 4) + keyArray[1]) ^ (uint32_2 + sum)) ^ (((uint32_2 >>> 5) + keyArray[2]));
uint32_2 += (((uint32_1 << 4) + keyArray[3]) ^ (uint32_1 + sum)) ^ (((uint32_1 >>> 5) + keyArray[0]));
sum += this.delta;
}
uint32_1 &= this.op;
uint32_2 &= this.op;
return new Uint8Array([
(uint32_1 >>> 24) & 0xFF,
(uint32_1 >>> 16) & 0xFF,
(uint32_1 >>> 8) & 0xFF,
uint32_1 & 0xFF,
(uint32_2 >>> 24) & 0xFF,
(uint32_2 >>> 16) & 0xFF,
(uint32_2 >>> 8) & 0xFF,
uint32_2 & 0xFF
]);
};
this.decipher = function(t, keys) {
if (t.length !== 8 || keys.length !== 16) {
throw new Error('Invalid input length for decipher');
}
let sum = (this.delta << 4) & this.op;
let uint32_1 = (t[0] << 24) | (t[1] << 16) | (t[2] << 8) | t[3];
let uint32_2 = (t[4] << 24) | (t[5] << 16) | (t[6] << 8) | t[7];
let keyArray = [
(keys[0] << 24) | (keys[1] << 16) | (keys[2] << 8) | keys[3],
(keys[4] << 24) | (keys[5] << 16) | (keys[6] << 8) | keys[7],
(keys[8] << 24) | (keys[9] << 16) | (keys[10] << 8) | keys[11],
(keys[12] << 24) | (keys[13] << 16) | (keys[14] << 8) | keys[15]
];
for (let i = 0; i < this.round; i++) {
uint32_2 -= (((uint32_1 << 4) + keyArray[3]) ^ (uint32_1 + sum)) ^ (((uint32_1 >>> 5) + keyArray[0]));
uint32_1 -= (((uint32_2 << 4) + keyArray[1]) ^ (uint32_2 + sum)) ^ (((uint32_2 >>> 5) + keyArray[2]));
sum -= this.delta;
}
uint32_1 &= this.op;
uint32_2 &= this.op;
return new Uint8Array([
(uint32_1 >>> 24) & 0xFF,
(uint32_1 >>> 16) & 0xFF,
(uint32_1 >>> 8) & 0xFF,
uint32_1 & 0xFF,
(uint32_2 >>> 24) & 0xFF,
(uint32_2 >>> 16) & 0xFF,
(uint32_2 >>> 8) & 0xFF,
uint32_2 & 0xFF
]);
};
this.cleanHexInput = function(hex) {
return hex.replace(/\s+/g, '');
};
this.hexToBytes = function(hex) {
if (hex.length % 2 !== 0) {
throw new Error('Invalid hex input');
}
let bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < bytes.length; i++) {
bytes = parseInt(hex.substr(i * 2, 2), 16);
}
return bytes;
};
this.bytesToHex = function(bytes) {
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
};
this.encrypt = function(cleartext_hex, share_key_hex) {
cleartext_hex = this.cleanHexInput(cleartext_hex);
share_key_hex = this.cleanHexInput(share_key_hex);
let cleartext = this.hexToBytes(cleartext_hex);
let share_key = this.hexToBytes(share_key_hex);
if (share_key.length !== 16) {
throw new Error('Invalid key length');
}
let cleartext_length = cleartext.length;
let padding_length = (8 - ((cleartext_length + 2) % 8)) % 8;
padding_length += 2 + (padding_length < 0 ? 8 : 0);
let padding_data = new Uint8Array(padding_length);
padding_data[0] = (padding_length - 2) | 0xF8;
for (let i = 1; i < padding_length; i++) {
padding_data = Math.floor(Math.random() * 253) + 1;
}
let padded_cleartext = new Uint8Array(padding_data.length + cleartext.length);
padded_cleartext.set(padding_data);
padded_cleartext.set(cleartext, padding_data.length);
let b1 = new Uint8Array(8);
let b2 = new Uint8Array(8);
let result = [];
for (let i = 0; i < padded_cleartext.length; i += 8) {
let chunk = padded_cleartext.slice(i, i + 8);
chunk = this.xorBytes(chunk, b1);
b1 = this.xorBytes(this.encipher(chunk, share_key), b2);
b2 = chunk;
result.push(...b1);
}
return this.bytesToHex(new Uint8Array(result));
};
this.decrypt = function(ciphertext_hex, share_key_hex) {
ciphertext_hex = this.cleanHexInput(ciphertext_hex);
share_key_hex = this.cleanHexInput(share_key_hex);
let ciphertext = this.hexToBytes(ciphertext_hex);
let share_key = this.hexToBytes(share_key_hex);
if (share_key.length !== 16) {
throw new Error('Invalid key length');
}
let result = [];
let pre_crypt = ciphertext.slice(0, 8);
let pre_plain = this.decipher(pre_crypt, share_key);
result.push(...pre_plain);
for (let i = 8; i < ciphertext.length; i += 8) {
let chunk = ciphertext.slice(i, i + 8);
let a = this.xorBytes(this.decipher(this.xorBytes(chunk, pre_plain), share_key), pre_crypt);
pre_plain = this.xorBytes(a, pre_crypt);
pre_crypt = chunk;
result.push(...a);
}
let padding_length = result[0] & 0x07;
result = result.slice(2 + padding_length);
return this.bytesToHex(new Uint8Array(result));
};
}
function encryptText() {
try {
let cleartext = document.getElementById('cleartext').value;
let key = document.getElementById('key').value;
let tea = new QQTEA();
let encrypted = tea.encrypt(cleartext, key);
document.getElementById('encrypted').value = encrypted;
document.getElementById('decrypted').value = ''; // Clear the decrypted field
document.getElementById('error-message').textContent = '';
} catch (e) {
document.getElementById('error-message').textContent = 'Encryption error: ' + e.message;
}
}
function decryptText() {
try {
let encrypted = document.getElementById('encrypted').value;
let key = document.getElementById('key').value;
let tea = new QQTEA();
let decrypted = tea.decrypt(encrypted, key);
document.getElementById('decrypted').value = decrypted;
document.getElementById('error-message').textContent = '';
} catch (e) {
document.getElementById('error-message').textContent = 'Decryption error: ' + e.message;
}
}
</script>
</body>
</html>
php代码:
[PHP] 纯文本查看 复制代码 <?php
class QQTEA
{
// TEA 算法的 Delta 常量
private $delta = 0x9E3779B9;
// TEA 算法的轮数
private $round = 16;
// TEA 算法的掩码,用于保证 32 位操作
private $op = 0xFFFFFFFF;
// 填充标记,默认 7 个零字节
private $flag = "\0\0\0\0\0\0\0";
// 执行 XOR 操作
private function xorBytes($a, $b)
{
return $a ^ $b;
}
// TEA 加密过程
private function encipher($t, $share_key)
{
$sum = $this->delta;
$keys = unpack('N4', $share_key); // 将密钥从二进制数据转换为四个 32 位无符号整数
if (strlen($t) != 8) {
throw new Exception('Input length is not 8 bytes for encipher');
}
// 将输入数据分割成两个 32 位的整数
$uint32_1 = unpack('N', substr($t, 0, 4))[1];
$uint32_2 = unpack('N', substr($t, 4, 4))[1];
// TEA 加密的主要计算循环
for ($i = 0; $i < $this->round; $i++) {
$uint32_1 += (((($uint32_2 << 4) & 0xFFFFFFF0) + $keys[1]) ^ ($uint32_2 + $sum)) ^ (((($uint32_2 >> 5) & 0x07FFFFFF) + $keys[2]));
$uint32_2 += (((($uint32_1 << 4) & 0xFFFFFFF0) + $keys[3]) ^ ($uint32_1 + $sum)) ^ (((($uint32_1 >> 5) & 0x07FFFFFF) + $keys[4]));
$sum += $this->delta;
}
// 进行 32 位掩码处理,确保结果在 32 位范围内
$uint32_1 &= $this->op;
$uint32_2 &= $this->op;
// 将两个 32 位整数打包成二进制数据
return pack('NN', $uint32_1, $uint32_2);
}
// TEA 解密过程
private function decipher($t, $share_key)
{
$sum = ($this->delta << 4) & $this->op;
$keys = unpack('N4', $share_key); // 将密钥从二进制数据转换为四个 32 位无符号整数
if (strlen($t) != 8) {
throw new Exception('Input length is not 8 bytes for decipher');
}
// 将输入数据分割成两个 32 位的整数
$uint32_1 = unpack('N', substr($t, 0, 4))[1];
$uint32_2 = unpack('N', substr($t, 4, 4))[1];
// TEA 解密的主要计算循环
for ($i = 0; $i < $this->round; $i++) {
$uint32_2 -= (((($uint32_1 << 4) & 0xFFFFFFF0) + $keys[3]) ^ ($uint32_1 + $sum)) ^ (((($uint32_1 >> 5) & 0x07FFFFFF) + $keys[4]));
$uint32_1 -= (((($uint32_2 << 4) & 0xFFFFFFF0) + $keys[1]) ^ ($uint32_2 + $sum)) ^ (((($uint32_2 >> 5) & 0x07FFFFFF) + $keys[2]));
$sum -= $this->delta;
}
// 进行 32 位掩码处理,确保结果在 32 位范围内
$uint32_1 &= $this->op;
$uint32_2 &= $this->op;
// 将两个 32 位整数打包成二进制数据
return pack('NN', $uint32_1, $uint32_2);
}
// 清理十六进制输入中的空格
private function cleanHexInput($hex)
{
return str_replace(' ', '', $hex); // 去除输入中的空格
}
// 加密函数
public function encrypt($cleartext_hex, $share_key_hex)
{
// 清理输入数据中的空格
$cleartext_hex = $this->cleanHexInput($cleartext_hex);
$share_key_hex = $this->cleanHexInput($share_key_hex);
// 将十六进制文本转换为二进制数据
$cleartext = hex2bin($cleartext_hex);
$share_key = hex2bin($share_key_hex);
// 计算填充长度
$cleartext_length = strlen($cleartext);
$padding_length = (8 - (($cleartext_length + 2) % 8)) % 8;
$padding_length += 2 + ($padding_length < 0 ? 8 : 0);
// 生成填充数据
$padding_data = chr(($padding_length - 2) | 0xF8);
for ($i = 0; $i < ($padding_length - 1); $i++) {
$padding_data .= chr(rand(1, 253)); // 随机填充字节
}
// 拼接填充数据和明文
$padded_cleartext = $padding_data . $cleartext;
// TEA 加密
$b1 = $b2 = str_repeat("\0", 8); // 初始化两个 8 字节的块
$result = '';
for ($i = 0; $i < strlen($padded_cleartext); $i += 8) {
$t = substr($padded_cleartext, $i, 8);
$t = str_pad($t, 8, "\0"); // 确保每个数据块的长度为 8 字节
$t = $this->xorBytes($t, $b1);
$b1 = $this->xorBytes($this->encipher($t, $share_key), $b2);
$b2 = $t;
$result .= $b1;
}
// 返回加密结果的十六进制表示
return bin2hex($result);
}
// 解密函数
public function decrypt($ciphertext_hex, $share_key_hex)
{
// 清理输入数据中的空格
$ciphertext_hex = $this->cleanHexInput($ciphertext_hex);
$share_key_hex = $this->cleanHexInput($share_key_hex);
// 将十六进制文本转换为二进制数据
$ciphertext = hex2bin($ciphertext_hex);
$share_key = hex2bin($share_key_hex);
// 解密过程
$ciphertext_len = strlen($ciphertext);
if ($ciphertext_len < 8) {
throw new Exception('Ciphertext length is too short for decryption');
}
$pre_crypt = substr($ciphertext, 0, 8);
$pre_plain = $this->decipher($pre_crypt, $share_key);
$result = $pre_plain;
for ($i = 8; $i < $ciphertext_len; $i += 8) {
$a = $this->xorBytes($this->decipher($this->xorBytes(substr($ciphertext, $i, 8), $pre_plain), $share_key), $pre_crypt);
$pre_plain = $this->xorBytes($a, $pre_crypt);
$pre_crypt = substr($ciphertext, $i, 8);
$result .= $a;
}
// 去除填充
$padding_length = ord($result[0]) & 0x07; // 计算填充长度
$result = substr($result, 2 + $padding_length); // 去掉填充字段和填充数据
// 返回解密结果的十六进制表示
return bin2hex($result);
}
}
// 使用示例 参数都是使用的16进制文本,秘钥也是16进制文本
$tea = new QQTEA;
$jiami = $tea->encrypt("5e65e7c7bf7d2c043a", "00000000000000000000000000000000");
echo "加密内容:" . $jiami . "</br>";
$jiemi = $tea->decrypt($jiami, "00000000000000000000000000000000");
echo "解密内容:" . $jiemi . "</br>";
?>
PYTHON代码:
[Python] 纯文本查看 复制代码
#!/usr/bin/env python
import struct
import random
import binascii
class QQTEA(object):
def __init__(self):
# key schedule constant
self.delta = 0x9E3779B9
self.round = 16
self.op = 0xFFFFFFFF
# append 7 '\0' in the end of the message.
self.flag = bytes(7)
# xor per 8 bytes
def __xor(self, a, b):
block = b''
for i in range(8):
block += struct.pack("B", a ^ b)
return block
def __encipher(self, t, share_key):
sum = self.delta
keys = struct.unpack(">LLLL", share_key)
uint32_1, uint32_2 = struct.unpack(">LL", t)
for _ in range(self.round):
uint32_1 += (((uint32_2 << 4) & 0xFFFFFFF0) + keys[0]) ^ (
uint32_2 + sum) ^ (((uint32_2 >> 5) & 0x07ffffff) + keys[1])
uint32_2 += (((uint32_1 << 4) & 0xFFFFFFF0) + keys[2]) ^ (
uint32_1 + sum) ^ (((uint32_1 >> 5) & 0x07ffffff) + keys[3])
sum += self.delta
uint32_1 &= self.op
uint32_2 &= self.op
return struct.pack(">LL", uint32_1, uint32_2)
def __decipher(self, t, share_key):
sum = (self.delta << 4) & self.op
keys = struct.unpack(">LLLL", share_key)
uint32_1, uint32_2 = struct.unpack(">LL", t)
for _ in range(self.round):
uint32_2 -= (((uint32_1 << 4) & 0xFFFFFFF0) + keys[2]) ^ (
uint32_1 + sum) ^ (((uint32_1 >> 5) & 0x07ffffff) + keys[3])
uint32_1 -= (((uint32_2 << 4) & 0xFFFFFFF0) + keys[0]) ^ (
uint32_2 + sum) ^ (((uint32_2 >> 5) & 0x07ffffff) + keys[1])
sum -= self.delta
uint32_1 &= self.op
uint32_2 &= self.op
return struct.pack(">LL", uint32_1, uint32_2)
def encrypt(self, cleartext, share_key):
cleartext_length = len(cleartext)
# to count the number of fill bytes.
padding_length = (8 - (cleartext_length + 2)) % 8
padding_length += 2 + (8 if (padding_length < 0) else 0)
# filling the random bytes
padding_hex = b''
for _ in range(0, padding_length):
padding_hex += struct.pack("B", random.randrange(1, 254))
# merge
padded_cleartext = struct.pack(
"B", (padding_length - 2) | 0xF8) + padding_hex + cleartext + self.flag
b1 = b2 = bytes(8)
result = b''
# xor per 8 bytes
for i in range(0, len(padded_cleartext), 8):
t = self.__xor(padded_cleartext[i:i + 8], b1)
b1 = self.__xor(self.__encipher(t, share_key), b2)
b2 = t
result += b1
return result
def decrypt(self, ciphertext, share_key):
ciphertext_len = len(ciphertext)
# print('ciphertext_len', len(ciphertext))
pre_crypt = ciphertext[0:8]
pre_plain = self.__decipher(pre_crypt, share_key)
# print('pre_plain', str(binascii.b2a_hex(pre_plain)))
pos = (pre_plain[0] & 0x07) + 2
result = pre_plain
for i in range(8, ciphertext_len, 8):
# print('ciphertext', i, str(binascii.b2a_hex(ciphertext[i:i+8])))
a = self.__xor(self.__decipher(self.__xor(
ciphertext[i:i + 8], pre_plain), share_key), pre_crypt)
pre_plain = self.__xor(a, pre_crypt)
pre_crypt = ciphertext[i:i + 8]
result += a
# print('result2', str(binascii.b2a_hex(result)))
# print('result3', result)
if result[-7:] == b'\0' * 7:
# print('decrypt result: ', str(binascii.b2a_hex(result[pos+1:-7])))
return result[pos + 1:-7]
else:
return result
补充内容 (2024-9-7 13:39):
PHP JS代码错误有更新,可以去https://github.com/joyi911/QQTEA 获取最新代码 |
评分
-
查看全部评分
|