This commit is contained in:
ColorSky 2024-09-06 01:19:05 +08:00
commit 1352ef8ec8
9 changed files with 341 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

23
Cargo.lock generated Normal file
View File

@ -0,0 +1,23 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "reuqm"
version = "0.1.0"
dependencies = [
"anyhow",
"base64",
]

8
Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "reuqm"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.86"
base64 = "0.22.1"

93
src/decrypto/cipher.rs Normal file
View File

@ -0,0 +1,93 @@
use std::cmp::min;
use crate::{decrypto::rc4, key::read_key};
use anyhow::{Error, Result};
const FIRST_SEGMENT_SIZE: usize = 128;
const OTHER_SEGMENT_SIZE: usize = 5120;
pub struct Cipher {
hash: f64,
key: Vec<u8>,
key_stream: Vec<u8>,
}
impl Cipher {
pub fn new(raw_key: &str) -> Result<Self, Error> {
let key = read_key(raw_key)?;
let key_stream = rc4::new(&key);
let hash = hash(&key);
Ok(Self {
hash,
key,
key_stream,
})
}
pub fn decrypt(&mut self, mut offset: usize, mut buffer: &mut [u8]) {
if offset < FIRST_SEGMENT_SIZE {
let n = min(FIRST_SEGMENT_SIZE - offset, buffer.len());
let (block, rest) = buffer.split_at_mut(n);
buffer = rest;
self.decrypt_first_block(offset, block);
offset += n;
}
match offset % OTHER_SEGMENT_SIZE {
0 => {}
excess => {
let n = min(OTHER_SEGMENT_SIZE - excess, buffer.len());
let (block, rest) = buffer.split_at_mut(n);
buffer = rest;
self.decrypt_other_block(offset, block);
offset += n;
}
};
while !buffer.is_empty() {
let n: usize = min(OTHER_SEGMENT_SIZE, buffer.len());
let (block, rest) = buffer.split_at_mut(n);
buffer = rest;
self.decrypt_other_block(offset, block);
offset += n;
}
}
fn decrypt_first_block(&mut self, offset: usize, dst: &mut [u8]) {
let n = self.key.len();
for (value, offset) in dst.iter_mut().zip(offset..) {
*value ^= self.key[idx(offset as u64, self.key[offset % n], self.hash) as usize % n];
}
}
fn decrypt_other_block(&mut self, offset: usize, dst: &mut [u8]) {
let n = self.key.len();
let id = offset / OTHER_SEGMENT_SIZE;
let block_offset = offset % OTHER_SEGMENT_SIZE;
let seed = self.key[id % n];
let skip = idx(id as u64, seed, self.hash) % 512;
let key_stream = self.key_stream.iter().skip(skip as usize + block_offset);
for (datum, &key) in dst.iter_mut().zip(key_stream) {
*datum ^= key;
}
}
}
fn hash(key: &Vec<u8>) -> f64 {
let mut hash = 1u32;
for v in key.iter() {
if *v == 0 {
continue;
}
let next_hash = hash.wrapping_mul(*v as u32);
if next_hash == 0 || next_hash <= hash {
break;
}
hash = next_hash;
}
hash.into()
}
fn idx(id: u64, seed: u8, hash: f64) -> u32 {
match seed {
0 => 0,
seed => (hash / ((id + 1).wrapping_mul(seed.into()) as f64) * 100.0) as u32,
}
}

2
src/decrypto/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod cipher;
mod rc4;

62
src/decrypto/rc4.rs Normal file
View File

@ -0,0 +1,62 @@
pub fn new(key: &Vec<u8>) -> Vec<u8> {
let key_lenght = key.len();
// init
let mut s_box = Vec::new();
let mut t_box = Vec::new();
for i in 0..key_lenght {
s_box.push(i as u8);
t_box.push(key[i % key_lenght]);
}
// init S box
let mut j = 0;
for i in 0..key_lenght {
j = (j + s_box[i] as usize + t_box[i] as usize) % 512;
s_box.swap(i, j);
}
let mut i = 0;
let mut j = 0;
let mut ks = Vec::new();
for _ in 0..(5120 + 512) {
i = (i + 1) % key_lenght;
j = (j + s_box[i] as usize) % key_lenght;
s_box.swap(i, j);
let t = (s_box[i] as usize + s_box[j] as usize) % key_lenght;
ks.push(0 ^ s_box[t]);
}
ks
}
#[test]
fn test() {
let k = vec![
102, 121, 54, 88, 65, 52, 108, 55, 49, 87, 86, 79, 104, 83, 52, 106, 107, 50, 113, 54, 83,
82, 100, 99, 56, 103, 112, 78, 51, 56, 52, 112, 77, 53, 57, 56, 119, 49, 99, 117, 51, 76,
120, 121, 49, 109, 83, 73, 49, 74, 56, 52, 55, 110, 99, 98, 77, 114, 112, 90, 72, 65, 82,
48, 53, 50, 68, 48, 49, 108, 114, 97, 67, 82, 73, 83, 103, 116, 101, 53, 120, 121, 81, 73,
89, 76, 53, 88, 100, 53, 53, 100, 116, 111, 97, 83, 119, 51, 104, 109, 48, 55, 75, 102,
110, 66, 110, 76, 53, 49, 97, 102, 112, 76, 115, 104, 56, 113, 57, 89, 74, 81, 57, 103, 99,
55, 77, 99, 51, 68, 50, 72, 48, 51, 86, 114, 121, 100, 75, 87, 66, 48, 54, 116, 107, 118,
105, 76, 67, 65, 51, 68, 68, 51, 56, 103, 49, 52, 89, 87, 54, 76, 52, 81, 104, 66, 79, 52,
112, 75, 49, 73, 114, 98, 68, 67, 84, 50, 50, 87, 74, 76, 104, 57, 102, 52, 119, 109, 116,
51, 75, 71, 56, 65, 86, 80, 52, 53, 100, 71, 101, 69, 113, 81, 49, 75, 77, 54, 120, 102,
85, 89, 121, 65, 101, 79, 101, 76, 74, 104, 99, 49, 75, 102, 55, 98, 55, 48, 71, 110, 98,
48, 120, 57, 78, 120, 68, 73, 49, 52, 55, 103, 99, 89, 112, 97, 57, 88, 72, 51, 48, 75, 70,
72, 106, 122, 72, 98, 100, 48, 113, 77, 56, 50, 108, 50, 65, 113, 69, 88, 102, 99, 70, 49,
103, 54, 50, 103, 98, 90, 50, 112, 75, 116, 57, 103, 80, 97, 55, 54, 118, 57, 101, 57, 57,
88, 57, 48, 49, 54, 115, 56, 52, 53, 79, 87, 66, 102, 116, 111, 54, 89, 51, 122, 102, 53,
116, 50, 101, 56, 101, 102, 83, 111, 74, 81, 110, 50, 85, 56, 55, 51, 84, 81, 54, 51, 86,
82, 51, 50, 72, 120, 56, 54, 115, 56, 117, 87, 122, 79, 56, 56, 105, 83, 53, 54, 82, 82,
50, 103, 81, 119, 99, 56, 103, 54, 97, 83, 54, 107, 52, 102, 105, 68, 54, 108, 99, 66, 99,
70, 122, 97, 101, 109, 72, 53, 105, 88, 55, 55, 111, 73, 50, 88, 114, 103, 82, 50, 99, 99,
48, 57, 113, 106, 100, 72, 107, 109, 100, 54, 84, 51, 79, 106, 86, 97, 102, 118, 105, 76,
56, 104, 107, 56, 53, 79, 67, 75, 50, 103, 53, 56, 112, 111, 117, 108, 54, 98, 110, 119,
118, 118, 49, 80, 69, 119, 102, 101, 56, 51, 116, 71, 48, 86, 106, 104, 103, 71, 77, 72,
52, 54, 117, 88, 67, 54, 86, 55, 48, 102, 67, 51, 49, 74, 57, 52, 119, 56, 54, 111, 119,
108, 48, 79, 55, 72, 73, 57, 49, 72, 51, 81, 70, 74, 99, 55, 78, 53, 82, 84, 103, 52, 50,
115, 112, 54, 54, 50, 52, 65, 114, 122,
];
let rs4 = new(&k);
println!("{:?}", rs4);
}

91
src/key/mod.rs Normal file
View File

@ -0,0 +1,91 @@
mod tea;
use anyhow::{Error, Result};
use base64::prelude::{Engine, BASE64_STANDARD as base64};
pub fn read_key(raw_key: &str) -> Result<Vec<u8>> {
let base64_key = match base64.decode(raw_key) {
Ok(k) => k,
Err(err) => {
return Err(Error::msg(format!(
"use base64 decode raw key Failed,{err}"
)))
}
};
let simple_key: [u8; 8] = [105, 86, 70, 56, 43, 32, 21, 11];
let mut tea_key = vec![0; 16];
for i in 0..8 {
tea_key[i << 1] = simple_key[i];
tea_key[(i << 1) + 1] = base64_key[i];
}
let mut rs = decrypt_tencent_tea(base64_key[8..].to_owned(), tea_key)?;
let mut dkv1 = base64_key[..8].to_owned();
dkv1.append(&mut rs);
Ok(dkv1.into())
}
fn decrypt_tencent_tea(in_buf: Vec<u8>, key: Vec<u8>) -> Result<Vec<u8>, Error> {
const SALTLEN: usize = 2;
const ZEROEN: usize = 7;
if in_buf.len() % 8 != 0 {
return Err(Error::msg("inBuf size not a multiple of the block size"));
}
if in_buf.len() < 16 {
return Err(Error::msg("inBuf size too small"));
}
let key = key[0..16].try_into().unwrap();
let blk = tea::Tea::new(key, 32);
let mut dst = blk.decrypt(in_buf[0..8].to_owned());
let pad_len = &dst[0] & 0x7;
let out_len = in_buf.len() - 1 - pad_len as usize - SALTLEN - ZEROEN;
let mut out = vec![0; out_len];
let mut iv_prev = vec![0; 8];
let mut iv_cur = in_buf[0..8].to_owned();
let mut in_buf_pos = 8;
let mut dst_idx = 1 + pad_len;
let mut i = 1;
while i <= SALTLEN {
if dst_idx < 8 {
dst_idx += 1;
i += 1;
} else if dst_idx == 8 {
iv_prev = iv_cur.clone()[0..8].to_owned();
iv_cur = in_buf[in_buf_pos..(in_buf_pos + 8)].to_owned();
dst = xor_8bytes(dst.clone(), in_buf[in_buf_pos..(in_buf_pos + 8)].to_owned());
dst = blk.decrypt(dst.clone());
in_buf_pos += 8;
dst_idx = 0;
}
}
let mut out_pos = 0;
while out_pos < out_len {
if dst_idx < 8 {
out[out_pos] = dst[dst_idx as usize] ^ iv_prev[dst_idx as usize];
dst_idx += 1;
out_pos += 1;
continue;
}
iv_prev = iv_cur.clone()[0..8].to_owned();
iv_cur = in_buf[in_buf_pos..(in_buf_pos + 8)].to_owned();
dst = xor_8bytes(dst.clone(), in_buf[in_buf_pos..(in_buf_pos + 8)].to_owned());
dst = blk.decrypt(dst.clone());
in_buf_pos += 8;
dst_idx = 0;
}
let mut i = 1;
while i <= ZEROEN {
i += 1;
if dst[dst_idx as usize] != iv_prev[dst_idx as usize] {
return Err(Error::msg("zero check failed"));
}
}
Ok(out)
}
pub fn xor_8bytes(a: Vec<u8>, b: Vec<u8>) -> Vec<u8> {
let mut dst = vec![0; 8];
for i in 0..8 {
dst[i] = a[i] ^ b[i];
}
dst
}

51
src/key/tea.rs Normal file
View File

@ -0,0 +1,51 @@
pub struct Tea {
key: [u32; 4],
rounds: u32,
}
impl Tea {
pub fn new(key: [u8; 16], rounds: u32) -> Self {
let key = [
u32::from_be_bytes(key[0..4].try_into().unwrap()),
u32::from_be_bytes(key[4..8].try_into().unwrap()),
u32::from_be_bytes(key[8..12].try_into().unwrap()),
u32::from_be_bytes(key[12..16].try_into().unwrap()),
];
Self { key, rounds }
}
pub fn decrypt(&self, bl: Vec<u8>) -> Vec<u8> {
let delta = 0x9E3779b9;
let decrypto = |v: [u32; 2], k: [u32; 4]| -> (u32, u32) {
let mut sum: u32 = (self.rounds / 2).wrapping_mul(delta);
let mut v0 = v[0];
let mut v1 = v[1];
for _ in 0..(self.rounds / 2) {
v1 = v1.wrapping_sub(
((v0 << 4).wrapping_add(k[2]))
^ (v0.wrapping_add(sum))
^ ((v0 >> 5).wrapping_add(k[3])),
);
v0 = v0.wrapping_sub(
((v1 << 4).wrapping_add(k[0]))
^ (v1.wrapping_add(sum))
^ ((v1 >> 5).wrapping_add(k[1])),
);
sum = sum.wrapping_sub(delta);
}
(v0, v1)
};
let v0 = u32::from_be_bytes(bl[0..4].try_into().unwrap());
let v1 = u32::from_be_bytes(bl[4..8].try_into().unwrap());
let (v0, v1) = decrypto([v0, v1], self.key);
[v0.to_be_bytes(), v1.to_be_bytes()].concat()
}
}
#[test]
fn test() {
let v: [u8; 16] = [
33, 14, 26, 47, 81, 10, 19, 22, 47, 35, 88, 21, 45, 23, 44, 55,
];
let k1 = u32::from_be_bytes(v[0..4].try_into().unwrap());
assert_eq!(k1, 554572335);
}

10
src/lib.rs Normal file
View File

@ -0,0 +1,10 @@
pub mod decrypto;
mod key;
use anyhow::{Error, Result};
pub fn decrypt(filename: &str, raw_key: &str) -> Result<Vec<u8>, Error> {
let mut audio = std::fs::read(filename)?;
let mut cipher = decrypto::cipher::Cipher::new(raw_key)?;
cipher.decrypt(0, &mut audio);
Ok(audio)
}