Skip to content

Commit

Permalink
Try fix padding
Browse files Browse the repository at this point in the history
  • Loading branch information
owent committed Jun 23, 2020
1 parent da812a3 commit aa5cc34
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 17 deletions.
87 changes: 87 additions & 0 deletions src/handles/robot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,90 @@ async fn dispatch_robot_message(

command_runtime::run(runtime).await
}

#[cfg(test)]
mod tests {

use super::super::super::wxwork_robot::base64;
use super::super::super::wxwork_robot::message;
use super::super::super::wxwork_robot::project::WXWorkProject;

const WXWORKROBOT_TEST_MSG_ORIGIN: &[u8] = b"<xml><Encrypt><![CDATA[FwydeYOgYQZ9k+kVyzxq0dnB4a/Pwn3MefyybYcZbsRJho83qzw1/UCX/5jlBxDxiPPOY1ai/f7x+dorMGFNweLsJxNiWT27Ov3eOWLuJrNmbDWt27KwnIeT4tgA5uzDVIZd8jF6i7GUD+kK2VuZe+wHu8TsCTDOngMJJ9bnDjzdCtgpgklm3jSgF4A+VViq2mPcEOcHfWsYOcjJLiiGggLI1xIIZqag/o8xw4HFi+O9R8E3wbWtnMyHSih+oW3ES+tHdv0nnYx6JqvTPMMZIQiNMx9AVyDn4ps88bEppHUw+Cda5/Uk6EwMGPCr/AMdBVFTtJow+CUyoO4T6g821v7hwivkxPEMsOUz6cSir4M5W7lRXkSTcyHuadr1V7fjR7luVLqA4sR6JTQEUBkude7kn1GX9JdJkddqqgZInX4hBXIPJ4h5UmJLxWUADrH8sPIpu32shvFEmzEcftcobgDIxBj9vhXBn9MfaiOYGMAAfQ3TZ0Cb9HmDW/hnA2RY1bHTf+UK7dSK+DyaVwgsmGfZsRhfpShCAvuRnOKUx1JWRDwEHyv5VxdCozPoOk4fjyLVB4HHigyd/jfuc3CYqGtJ+Gn0aKc8zqVgTHgS9q3LkfcalcFJ2pVGCRYGW8mTyTcjW627RhzYWN5qmzbFQzRHMBh8Z/9zdSmW+VxNOHfNZaLR5TPfITSDKeHH1NrISm06Xf3wjyRpUvt6t6BAsFfPJid44XjRgWk2tlmoTo7yDT24uZWWOIuczWsicXbMOWJjkJ3dSKopyfewF61MHcTHp8M3KcbAL1/48kP5vM2Gqp6WBrkAgJu17BJYqRn2yopNmCZdY5H4Hdfl9Eq+/MEUZsZS8NBVAkVgjYlP4p1eWKJFiKQohQWVAEgGWWVBED+52QrKZqmXgdVfQ3UzuHHheNrBf5y94b1wlU3crBh/Gpi1yYOd7UReYnmo4uOth1sSwcqQO1Fe+lUkW3JCbw==]]></Encrypt></xml>";
const WXWORKROBOT_TEST_MSG_REPLY: &str = "<xml><MsgType><![CDATA[markdown]]></MsgType><Markdown><Content><![CDATA[啦啦啦热热热]]></Content></Markdown></xml>";

#[test]
fn project_decode_and_verify() {
let encrypt_msg_b64_res =
message::get_msg_encrypt_from_bytes(bytes::Bytes::from(WXWORKROBOT_TEST_MSG_ORIGIN));
assert!(encrypt_msg_b64_res.is_some());

let json_value = serde_json::from_str("{ \"name\": \"test_proj\", \"token\": \"hJqcu3uJ9Tn2gXPmxx2w9kkCkCE2EPYo\", \"encodingAESKey\": \"6qkdMrq68nTKduznJYO1A37W2oEgpkMUvkttRToqhUt\", \"cmds\": {} }").unwrap();
let proj_obj_res = WXWorkProject::new(&json_value);
assert!(proj_obj_res.is_some());
if !proj_obj_res.is_some() {
return;
}
let proj_obj = proj_obj_res.unwrap();

let msg_dec: message::WXWorkMessageDec;
if let Some(encrypt_msg_b64) = encrypt_msg_b64_res {
assert!(proj_obj.check_msg_signature(
"8fa1a2c27ee20431b1f781600d0af971db3cc12b",
"1592905675",
"da455e270d961d94",
encrypt_msg_b64.as_str()
));

let msg_dec_res = proj_obj.decrypt_msg_raw_base64_content(encrypt_msg_b64.as_str());
assert!(msg_dec_res.is_ok());
msg_dec = if let Ok(x) = msg_dec_res {
x
} else {
return;
};
} else {
return;
}

// 提取数据
let msg_ntf_res = message::get_msg_from_str(msg_dec.content.as_str());
assert!(msg_ntf_res.is_some());
let msg_ntf = if let Some(x) = msg_ntf_res {
x
} else {
return;
};

assert_eq!(msg_ntf.content, "@测试机器人 说啦啦啦热热热");
}

#[test]
fn project_encode_reply() {
let json_value = serde_json::from_str("{ \"name\": \"test_proj\", \"token\": \"hJqcu3uJ9Tn2gXPmxx2w9kkCkCE2EPYo\", \"encodingAESKey\": \"6qkdMrq68nTKduznJYO1A37W2oEgpkMUvkttRToqhUt\", \"cmds\": {} }").unwrap();
let proj_obj_res = WXWorkProject::new(&json_value);
assert!(proj_obj_res.is_some());
if !proj_obj_res.is_some() {
return;
}
let proj_obj = proj_obj_res.unwrap();

let random_str = String::from("5377875643139089");
let encrypted_res =
proj_obj.encrypt_msg_raw(&WXWORKROBOT_TEST_MSG_REPLY.as_bytes(), &random_str);
assert!(encrypted_res.is_ok());

let encrypted_base64 = if let Ok(x) = encrypted_res {
match base64::STANDARD.encode(&x) {
Ok(v) => v,
Err(_) => {
assert!(false);
return;
}
}
} else {
return;
};

assert_eq!(encrypted_base64, "i84WNcyej8+Vo0tCZHLxCWt3ObZ2mvzs0cIGXLleX43mjd+TK1SYqdUOuPMS32ZJK0QyAq+Y6eVwqObEjrLTxGnlEeMOH2/f1CMxcPiRXUOTzOP4/qyeYI+PF9wAuJIajfJMHZCUiUSjS5cs18AS3XnO3VoP1hnGkMkxNy3CBFqQzgVkGsHhz3cQK94tzlkPWsveB8qQZjOJWxHst2Y+8Q==");
}
}
4 changes: 2 additions & 2 deletions src/wxwork_robot/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ pub fn pack_text_message(msg: WXWorkMessageTextRsp) -> Result<String, String> {

if let Ok(_) = writer.write_event(Event::Start(BytesStart::borrowed_name(b"xml"))) {
if let Ok(_) = writer.write_event(Event::Start(BytesStart::borrowed_name(b"MsgType"))) {
let _ = writer.write_event(Event::CData(BytesText::from_plain_str("text")));
let _ = writer.write_event(Event::Text(BytesText::from_plain_str("text")));
let _ = writer.write_event(Event::End(BytesEnd::borrowed(b"MsgType")));
}

Expand Down Expand Up @@ -603,7 +603,7 @@ pub fn pack_markdown_message(msg: WXWorkMessageMarkdownRsp) -> Result<String, St

if let Ok(_) = writer.write_event(Event::Start(BytesStart::borrowed_name(b"xml"))) {
if let Ok(_) = writer.write_event(Event::Start(BytesStart::borrowed_name(b"MsgType"))) {
let _ = writer.write_event(Event::CData(BytesText::from_plain_str("markdown")));
let _ = writer.write_event(Event::Text(BytesText::from_plain_str("markdown")));
let _ = writer.write_event(Event::End(BytesEnd::borrowed(b"MsgType")));
}

Expand Down
44 changes: 29 additions & 15 deletions src/wxwork_robot/project.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use actix_web::HttpResponse;
use aes::Aes256;
// use block_cipher::{BlockCipher, NewBlockCipher};
use block_modes::block_padding::Pkcs7;
use block_modes::block_padding::NoPadding;
use block_modes::{BlockMode, Cbc};
use byteorder::{BigEndian, ByteOrder};
// use openssl::symm::{Cipher, Crypter, Mode};
Expand All @@ -18,11 +18,11 @@ use std::time::SystemTime;

use super::{base64, command, message};

type Aes256CbcPkcs7 = Cbc<Aes256, Pkcs7>;
type Aes256CbcNoPadding = Cbc<Aes256, NoPadding>;

// #[derive(Clone)]
struct WXWorkProjectCipherInfo {
pub cipher: Aes256CbcPkcs7,
pub cipher: Aes256CbcNoPadding,
pub key: Vec<u8>,
pub iv: Vec<u8>,
}
Expand Down Expand Up @@ -200,14 +200,14 @@ impl WXWorkProject {
//let cipher_iv_len = <Aes256 as BlockCipher>::BlockSize::to_usize();
//let cipher_iv_len = U16::to_usize();
// According to https://en.wikipedia.org/wiki/Block_size_(cryptography)
// Block size of AES is always 128bits
// Block size of AES is always 128bits/16bytes
let cipher_iv_len: usize = 16;
let cipher_iv = if aes_key_bin.len() >= cipher_iv_len {
Vec::from(&aes_key_bin[0..cipher_iv_len])
} else {
Vec::new()
};
let cipher_ctx = match Aes256CbcPkcs7::new_var(&aes_key_bin, &cipher_iv) {
let cipher_ctx = match Aes256CbcNoPadding::new_var(&aes_key_bin, &cipher_iv) {
Ok(x) => x,
Err(e) => {
let err_msg = format!(
Expand Down Expand Up @@ -363,7 +363,7 @@ impl WXWorkProject {
match self.cipher_info.lock() {
Ok(c) => {
let ci = &*c;
decrypter = match Aes256CbcPkcs7::new_var(&ci.key, &ci.iv) {
decrypter = match Aes256CbcNoPadding::new_var(&ci.key, &ci.iv) {
Ok(x) => x,
Err(e) => {
let ret = format!(
Expand Down Expand Up @@ -463,7 +463,7 @@ impl WXWorkProject {
&self,
input: &str,
) -> Result<message::WXWorkMessageDec, String> {
let dec_bin_unpadding = match self.decrypt_msg_raw_base64(input) {
let dec_bin = match self.decrypt_msg_raw_base64(input) {
Ok(x) => x,
Err(e) => {
return Err(e);
Expand All @@ -475,7 +475,7 @@ impl WXWorkProject {
self.name(),
input
);
// let dec_bin_unpadding = self.pkcs7_decode(&dec_bin);
let dec_bin_unpadding = self.pkcs7_decode(&dec_bin);

if dec_bin_unpadding.len() <= 20 {
let err_msg = format!(
Expand Down Expand Up @@ -544,7 +544,7 @@ impl WXWorkProject {
})
}

pub fn encrypt_msg_raw(&self, input: &[u8]) -> Result<Vec<u8>, String> {
pub fn encrypt_msg_raw(&self, input: &[u8], random_str: &String) -> Result<Vec<u8>, String> {
// rand_msg=AES_Decrypt(aes_msg)
// 去掉rand_msg头部的16个随机字节和4个字节的msg_len,截取msg_len长度的部分即为msg,剩下的为尾部的receiveid
// 网络字节序,回包的receiveid直接为空即可
Expand All @@ -554,19 +554,19 @@ impl WXWorkProject {

let mut padded_plaintext: Vec<u8> = Vec::new();
padded_plaintext.reserve(64 + input.len());
padded_plaintext.extend_from_slice(self.alloc_random_str().as_bytes());
padded_plaintext.extend_from_slice(random_str.as_bytes());
padded_plaintext.extend_from_slice(&input_len_buf);
padded_plaintext.extend_from_slice(input);

// let padded_input = self.pkcs7_encode(&padded_plaintext);
let padded_input = self.pkcs7_encode(&padded_plaintext);

let encrypter;
// let block_size: usize;

match self.cipher_info.lock() {
Ok(c) => {
let ci = &*c;
encrypter = match Aes256CbcPkcs7::new_var(&ci.key, &ci.iv) {
encrypter = match Aes256CbcNoPadding::new_var(&ci.key, &ci.iv) {
Ok(x) => x,
Err(e) => {
let ret = format!(
Expand Down Expand Up @@ -609,7 +609,8 @@ impl WXWorkProject {
}
}

Ok(encrypter.encrypt_vec(&padded_plaintext))
let ret = encrypter.encrypt_vec(&padded_input);
Ok(ret)

/*
encrypter.pad(false);
Expand Down Expand Up @@ -649,9 +650,22 @@ impl WXWorkProject {

pub fn encrypt_msg_raw_base64(&self, input: &[u8]) -> Result<String, String> {
// msg_encrypt = Base64_Encode(AES_Encrypt(rand_msg))
match self.encrypt_msg_raw(&input) {
let random_str = self.alloc_random_str();
match self.encrypt_msg_raw(&input, &random_str) {
Ok(x) => match base64::STANDARD.encode(&x) {
Ok(v) => Ok(v),
Ok(v) => {
debug!(
"project \"{}\" use random string {} and encrypt \"{}\" to {}",
self.name(),
random_str,
match String::from_utf8(input.to_vec()) {
Ok(y) => y,
Err(_) => hex::encode(input),
},
v
);
Ok(v)
}
Err(e) => {
let ret = format!(
"project \"{}\" encrypt {} and encode to base64 failed, \n{:?}",
Expand Down

0 comments on commit aa5cc34

Please sign in to comment.