1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use bytes::{Buf, BufMut, Bytes, BytesMut};
use rand::Rng;
use crate::binary::BinaryWriter;
use crate::crypto::{qqtea_decrypt, EncryptECDH};
use crate::{RQError, RQResult};
#[derive(Debug, derivative::Derivative)]
#[derivative(Default)]
pub enum EncryptionMethod {
#[derivative(Default)]
ECDH,
ST,
}
#[derive(Default)]
pub struct Message {
pub uin: u32,
pub command: u16,
pub body: Bytes,
pub encryption_method: EncryptionMethod,
}
pub struct Codec {
pub ecdh: EncryptECDH,
pub random_key: Bytes,
pub wt_session_ticket_key: Bytes,
}
impl Default for Codec {
fn default() -> Self {
Self {
ecdh: Default::default(),
random_key: Bytes::from(rand::thread_rng().gen::<[u8; 16]>().to_vec()),
wt_session_ticket_key: Default::default(),
}
}
}
impl Codec {
pub fn encode(&self, m: Message) -> Bytes {
let mut w = BytesMut::new();
w.put_u8(0x02);
w.put_u16(0); w.put_u16(8001);
w.put_u16(m.command);
w.put_u16(1);
w.put_u32(m.uin);
w.put_u8(0x03);
match m.encryption_method {
EncryptionMethod::ECDH => w.put_u8(0x87),
EncryptionMethod::ST => w.put_u8(0x45),
}
w.put_u8(0);
w.put_u32(2);
w.put_u32(0);
w.put_u32(0);
match m.encryption_method {
EncryptionMethod::ECDH => {
w.put_u8(0x02);
w.put_u8(0x01);
w.put_slice(&self.random_key);
w.put_u16(0x01_31);
w.put_u16(self.ecdh.public_key_ver);
w.put_u16(self.ecdh.public_key.len() as u16);
w.put_slice(&self.ecdh.public_key);
w.encrypt_and_write(&self.ecdh.initial_share_key, &m.body);
}
EncryptionMethod::ST => {
w.put_u8(0x01);
w.put_u8(0x03);
w.put_slice(&self.random_key);
w.put_u16(0x0102);
w.put_u16(0x0000);
w.encrypt_and_write(&self.random_key, &m.body);
}
}
w.put_u8(0x03);
let len = w.len();
w[1..3].as_mut().put_u16(len as u16);
w.freeze()
}
pub fn decode<B>(&self, mut reader: B) -> RQResult<Message>
where
B: Buf,
{
let flag = reader.get_u8();
if flag != 2 {
return Err(RQError::UnknownFlag(flag));
}
let mut m = Message::default();
reader.get_u16(); reader.get_u16(); m.command = reader.get_u16();
reader.get_u16(); m.uin = reader.get_i32() as u32;
reader.get_u8();
let encrypt_type = reader.get_u8();
reader.get_u8();
match encrypt_type {
0 => {
let len = reader.remaining() - 1;
let d = reader.copy_to_bytes(len);
m.body = Bytes::from(qqtea_decrypt(&d, &self.ecdh.initial_share_key));
}
3 => {
let len = reader.remaining() - 1;
let d = reader.copy_to_bytes(len);
m.body = Bytes::from(qqtea_decrypt(&d, &self.wt_session_ticket_key));
}
_ => return Err(RQError::UnknownEncryptType),
}
Ok(m)
}
}