More connection testing
This commit is contained in:
parent
3122f03e9e
commit
1fdd2a3f1e
7 changed files with 141 additions and 57 deletions
|
@ -15,9 +15,10 @@ serde_json = "1.0.107"
|
||||||
reqwest = "0.11.20"
|
reqwest = "0.11.20"
|
||||||
tokio = { version = "1.32.0", features=["macros", "rt-multi-thread"] }
|
tokio = { version = "1.32.0", features=["macros", "rt-multi-thread"] }
|
||||||
futures = "0.3.28"
|
futures = "0.3.28"
|
||||||
|
serial_test = "2.0.0"
|
||||||
|
|
||||||
#crypto
|
#crypto
|
||||||
cbc = "0.1.2"
|
cbc = { version = "0.1.2", features = ["alloc"] }
|
||||||
md5 = "0.7.0"
|
md5 = "0.7.0"
|
||||||
base64 = "0.21.4"
|
base64 = "0.21.4"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
|
|
15
device.py
15
device.py
|
@ -151,9 +151,24 @@ class MiedaDevice(threading.Thread):
|
||||||
request = self._security.encode_8370(
|
request = self._security.encode_8370(
|
||||||
self._token, MSGTYPE_HANDSHAKE_REQUEST)
|
self._token, MSGTYPE_HANDSHAKE_REQUEST)
|
||||||
_LOGGER.debug(f"[{self._device_id}] Handshaking")
|
_LOGGER.debug(f"[{self._device_id}] Handshaking")
|
||||||
|
print("REQUEST")
|
||||||
print(request)
|
print(request)
|
||||||
|
|
||||||
|
req = bytearray([131, 112, 0, 64, 32, 0, 0, 0, 112, 43, 157, 252, 58, 198, 200, 41, 121, 152, 110, 227, 160, 83, 167, 111, 117, 249, 233, 199, 99, 206, 92, 37, 175, 92, 44, 201, 130, 247, 151, 169, 64, 154, 223, 243, 116, 94, 35, 254, 227, 164, 100, 215, 69, 224, 5, 200, 57, 239, 176, 184, 64, 130, 172, 201, 98, 229, 154, 184, 104, 62, 2, 153])
|
||||||
|
|
||||||
|
if (req == request):
|
||||||
|
print("both requests are the same")
|
||||||
|
|
||||||
|
self._socket.send(req)
|
||||||
|
response = self._socket.recv(512)
|
||||||
|
|
||||||
|
print(response)
|
||||||
|
|
||||||
self._socket.send(request)
|
self._socket.send(request)
|
||||||
response = self._socket.recv(512)
|
response = self._socket.recv(512)
|
||||||
|
|
||||||
|
print(response)
|
||||||
|
|
||||||
if len(response) < 20:
|
if len(response) < 20:
|
||||||
raise AuthException()
|
raise AuthException()
|
||||||
response = response[8: 72]
|
response = response[8: 72]
|
||||||
|
|
10
midea.py
10
midea.py
|
@ -17,8 +17,8 @@ async def test():
|
||||||
|
|
||||||
if len(devices) > 0:
|
if len(devices) > 0:
|
||||||
for device_id in devices:
|
for device_id in devices:
|
||||||
token = "06df24fc4e8e950c6d9783051b8e38d971e5fbc617da259459d30d5e7d7fc05b4ccb708fe3a085f6f0af0f8cc961fa39dabfd0746f7bbcfbf7404d9cc5c2b077"
|
token = "702b9dfc3ac6c82979986ee3a053a76f75f9e9c763ce5c25af5c2cc982f797a9409adff3745e23fee3a464d745e005c839efb0b84082acc962e59ab8683e0299"
|
||||||
key = "2a5b5200c2c04d4c811d0550e1dc5b31435436b95b774d2a88d7e46d61fd9669"
|
key = "52b2feee353841588994e630dcb59819ec71ce1ffacb48628f4f436f5c54f11e"
|
||||||
|
|
||||||
device_info = devices[device_id]
|
device_info = devices[device_id]
|
||||||
|
|
||||||
|
@ -35,7 +35,11 @@ async def test():
|
||||||
attributes={}
|
attributes={}
|
||||||
)
|
)
|
||||||
|
|
||||||
dev.connect(False)
|
if dev.connect(False):
|
||||||
|
print("success")
|
||||||
|
else:
|
||||||
|
print("fail")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# if await cl.login():
|
# if await cl.login():
|
||||||
|
|
21
src/cloud.rs
21
src/cloud.rs
|
@ -14,6 +14,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{from_str, to_string};
|
use serde_json::{from_str, to_string};
|
||||||
|
|
||||||
use crate::cloud_security::CloudSecurity;
|
use crate::cloud_security::CloudSecurity;
|
||||||
|
use crate::hex;
|
||||||
|
|
||||||
pub struct Cloud {
|
pub struct Cloud {
|
||||||
device_id: String,
|
device_id: String,
|
||||||
|
@ -238,7 +239,7 @@ impl Cloud {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn keys(&self, device_id: u64) -> Result<(String, String)> {
|
pub async fn keys(&self, device_id: u64) -> Result<(String, String)> {
|
||||||
for method in [1, 2] {
|
for method in [2] {
|
||||||
let udp_id = CloudSecurity::udp_id(device_id, method);
|
let udp_id = CloudSecurity::udp_id(device_id, method);
|
||||||
|
|
||||||
let mut data = self.make_general_data();
|
let mut data = self.make_general_data();
|
||||||
|
@ -252,13 +253,26 @@ impl Cloud {
|
||||||
|
|
||||||
for token in response.token_list() {
|
for token in response.token_list() {
|
||||||
if token.udpId == udp_id {
|
if token.udpId == udp_id {
|
||||||
return Ok((token.token.clone(), token.key.clone()));
|
return Ok((
|
||||||
|
Self::hex_to_lower(&token.token)?,
|
||||||
|
Self::hex_to_lower(&token.key)?,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bail!("no keys found")
|
bail!("no keys found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hex_to_lower(h: &str) -> Result<String> {
|
||||||
|
let lower = hex(h)?
|
||||||
|
.iter()
|
||||||
|
.map(|b| format!("{b:02x}"))
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("");
|
||||||
|
|
||||||
|
Ok(lower)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -453,6 +467,7 @@ struct Data<'a> {
|
||||||
mod test {
|
mod test {
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::future::try_join;
|
use futures::future::try_join;
|
||||||
|
use serial_test::serial;
|
||||||
|
|
||||||
use crate::Startup;
|
use crate::Startup;
|
||||||
|
|
||||||
|
@ -480,6 +495,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
#[serial]
|
||||||
async fn login() -> Result<()> {
|
async fn login() -> Result<()> {
|
||||||
let mut cloud = Cloud::new("michaelh.95@t-online.de", "Hoda.semi1")?;
|
let mut cloud = Cloud::new("michaelh.95@t-online.de", "Hoda.semi1")?;
|
||||||
|
|
||||||
|
@ -489,6 +505,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
#[serial]
|
||||||
async fn keys() -> Result<()> {
|
async fn keys() -> Result<()> {
|
||||||
let mut cloud = Cloud::new("michaelh.95@t-online.de", "Hoda.semi1")?;
|
let mut cloud = Cloud::new("michaelh.95@t-online.de", "Hoda.semi1")?;
|
||||||
|
|
||||||
|
|
|
@ -64,13 +64,21 @@ impl Device {
|
||||||
.security
|
.security
|
||||||
.encode_8370(&self.token, MsgType::HANDSHAKE_REQUEST)?;
|
.encode_8370(&self.token, MsgType::HANDSHAKE_REQUEST)?;
|
||||||
|
|
||||||
|
const PY_REQUEST :&[u8;72] = b"\x83p\x00@ \x00\x00\x00p+\x9d\xfc:\xc6\xc8)y\x98n\xe3\xa0S\xa7ou\xf9\xe9\xc7c\xce\\%\xaf\\,\xc9\x82\xf7\x97\xa9@\x9a\xdf\xf3t^#\xfe\xe3\xa4d\xd7E\xe0\x05\xc89\xef\xb0\xb8@\x82\xac\xc9b\xe5\x9a\xb8h>\x02\x99";
|
||||||
|
|
||||||
|
// assert_eq!(request, PY_REQUEST);
|
||||||
|
|
||||||
|
println!("writing request to stream: {request:?}");
|
||||||
self.socket.write(&request)?;
|
self.socket.write(&request)?;
|
||||||
|
|
||||||
let mut buffer = [0; 512];
|
let mut buffer = [0; 512];
|
||||||
let bytes_read = self.socket.read(&mut buffer)?;
|
let bytes_read = self.socket.read(&mut buffer)?;
|
||||||
|
|
||||||
if bytes_read < 20 {
|
if bytes_read < 20 {
|
||||||
bail!("Authentication failed!");
|
bail!(
|
||||||
|
"Authentication failed! (answer too short) {:?}",
|
||||||
|
&buffer[..bytes_read]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.security.tcp_key(&buffer[8..72], &self.key)?;
|
self.security.tcp_key(&buffer[8..72], &self.key)?;
|
||||||
|
@ -87,25 +95,24 @@ impl Device {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::net::UdpSocket;
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
use futures::future::try_join;
|
use futures::future::try_join;
|
||||||
|
use serial_test::serial;
|
||||||
|
|
||||||
use crate::{device::Device, Cloud, Startup};
|
use crate::{device::Device, Cloud, Startup};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn connect() -> Result<()> {
|
async fn verify_hex() -> Result<()> {
|
||||||
let devices = Startup::discover().await?;
|
let devices = Startup::discover().await?;
|
||||||
|
|
||||||
const TOKEN:&str = "06df24fc4e8e950c6d9783051b8e38d971e5fbc617da259459d30d5e7d7fc05b4ccb708fe3a085f6f0af0f8cc961fa39dabfd0746f7bbcfbf7404d9cc5c2b077";
|
const PY_TOKEN: &str = "06df24fc4e8e950c6d9783051b8e38d971e5fbc617da259459d30d5e7d7fc05b4ccb708fe3a085f6f0af0f8cc961fa39dabfd0746f7bbcfbf7404d9cc5c2b077";
|
||||||
const KEY: &str = "2a5b5200c2c04d4c811d0550e1dc5b31435436b95b774d2a88d7e46d61fd9669";
|
const PY_KEY: &str = "2a5b5200c2c04d4c811d0550e1dc5b31435436b95b774d2a88d7e46d61fd9669";
|
||||||
|
|
||||||
let token_hex = b"\x06\xdf$\xfcN\x8e\x95\x0cm\x97\x83\x05\x1b\x8e8\xd9q\xe5\xfb\xc6\x17\xda%\x94Y\xd3\r^}\x7f\xc0[L\xcbp\x8f\xe3\xa0\x85\xf6\xf0\xaf\x0f\x8c\xc9a\xfa9\xda\xbf\xd0to{\xbc\xfb\xf7@M\x9c\xc5\xc2\xb0w";
|
let token_hex = b"\x06\xdf$\xfcN\x8e\x95\x0cm\x97\x83\x05\x1b\x8e8\xd9q\xe5\xfb\xc6\x17\xda%\x94Y\xd3\r^}\x7f\xc0[L\xcbp\x8f\xe3\xa0\x85\xf6\xf0\xaf\x0f\x8c\xc9a\xfa9\xda\xbf\xd0to{\xbc\xfb\xf7@M\x9c\xc5\xc2\xb0w";
|
||||||
let key_hex = b"*[R\x00\xc2\xc0ML\x81\x1d\x05P\xe1\xdc[1CT6\xb9[wM*\x88\xd7\xe4ma\xfd\x96i";
|
let key_hex = b"*[R\x00\xc2\xc0ML\x81\x1d\x05P\xe1\xdc[1CT6\xb9[wM*\x88\xd7\xe4ma\xfd\x96i";
|
||||||
|
|
||||||
for device_info in devices {
|
for device_info in devices {
|
||||||
let device = Device::connect(device_info, TOKEN, KEY)?;
|
let device = Device::connect(device_info, PY_TOKEN, PY_KEY)?;
|
||||||
|
|
||||||
assert_eq!(&device.token, token_hex);
|
assert_eq!(&device.token, token_hex);
|
||||||
assert_eq!(&device.key, key_hex);
|
assert_eq!(&device.key, key_hex);
|
||||||
|
@ -115,6 +122,35 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
async fn connect_py_token() -> Result<()> {
|
||||||
|
let devices = Startup::discover().await?;
|
||||||
|
|
||||||
|
const PY_TOKEN: &str = "18a821cb88293c6552dc576f0672d8b9445205f74b636764929de5e8badfa48a24caa9d741f632a18e1a9fee67c40b0b40edc21ac7c4c40b6352181cd4000203";
|
||||||
|
const PY_KEY: &str = "0fc0c56ea8124414a362e6449ee45ba92558a54f159d4937af697e405f2326b9";
|
||||||
|
|
||||||
|
for device_info in devices {
|
||||||
|
Device::connect(device_info, PY_TOKEN, PY_KEY)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn connect_rust_token() -> Result<()> {
|
||||||
|
let devices = Startup::discover().await?;
|
||||||
|
|
||||||
|
const TOKEN: &str = "702b9dfc3ac6c82979986ee3a053a76f75f9e9c763ce5c25af5c2cc982f797a9409adff3745e23fee3a464d745e005c839efb0b84082acc962e59ab8683e0299";
|
||||||
|
const KEY: &str = "52b2feee353841588994e630dcb59819ec71ce1ffacb48628f4f436f5c54f11e";
|
||||||
|
|
||||||
|
for device_info in devices {
|
||||||
|
Device::connect(device_info, TOKEN, KEY)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
#[serial]
|
||||||
async fn full_flow() -> Result<()> {
|
async fn full_flow() -> Result<()> {
|
||||||
let mut cloud = Cloud::new("michaelh.95@t-online.de", "Hoda.semi1")?;
|
let mut cloud = Cloud::new("michaelh.95@t-online.de", "Hoda.semi1")?;
|
||||||
|
|
||||||
|
@ -123,22 +159,10 @@ mod test {
|
||||||
for device_info in devices {
|
for device_info in devices {
|
||||||
let (token, key) = cloud.keys(device_info.id).await?;
|
let (token, key) = cloud.keys(device_info.id).await?;
|
||||||
|
|
||||||
Device::connect(device_info, &token, &key)?;
|
Device::connect(device_info, &token, &key)
|
||||||
|
.context(format!("\ntoken: {token}\nkey: {key}"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn local_socket() -> Result<()> {
|
|
||||||
let socket = UdpSocket::bind("0.0.0.0:0")?;
|
|
||||||
socket.connect("192.168.178.94:6445")?;
|
|
||||||
|
|
||||||
socket.send(b"test")?;
|
|
||||||
|
|
||||||
let mut buffer = [0; 512];
|
|
||||||
let bytes_read = socket.recv(&mut buffer)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,9 +176,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn discover() -> Result<()> {
|
async fn discover() -> Result<()> {
|
||||||
let devices = Startup::discover().await?;
|
Startup::discover().await?;
|
||||||
|
|
||||||
println!("{devices:#?}");
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use aes::{
|
use aes::{
|
||||||
cipher::{
|
cipher::{
|
||||||
block_padding::Pkcs7, generic_array::GenericArray, BlockDecrypt, BlockDecryptMut,
|
block_padding::NoPadding, generic_array::GenericArray, BlockDecrypt, BlockDecryptMut,
|
||||||
BlockEncryptMut, KeyInit, KeyIvInit,
|
BlockEncryptMut, KeyInit, KeyIvInit,
|
||||||
},
|
},
|
||||||
Aes128,
|
Aes128,
|
||||||
|
@ -16,7 +16,7 @@ use crate::hex;
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||||
pub enum MsgType {
|
pub enum MsgType {
|
||||||
HANDSHAKE_REQUEST = 0x0,
|
HANDSHAKE_REQUEST = 0x0,
|
||||||
ANDSHAKE_RESPONSE = 0x1,
|
HANDSHAKE_RESPONSE = 0x1,
|
||||||
ENCRYPTED_RESPONSE = 0x3,
|
ENCRYPTED_RESPONSE = 0x3,
|
||||||
ENCRYPTED_REQUEST = 0x6,
|
ENCRYPTED_REQUEST = 0x6,
|
||||||
}
|
}
|
||||||
|
@ -46,47 +46,45 @@ impl Security {
|
||||||
data
|
data
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_cbc_encrypt(&self, raw: &[u8], key: &[u8; 32]) -> Vec<u8> {
|
pub fn aes_cbc_encrypt(&self, raw: [u8; 32], key: &[u8; 32]) -> [u8; 32] {
|
||||||
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
|
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
|
||||||
|
|
||||||
let mut buf = vec![0; raw.len()];
|
|
||||||
buf.copy_from_slice(raw);
|
|
||||||
|
|
||||||
Aes256CbcEnc::new(key.into(), &Self::IV.into())
|
Aes256CbcEnc::new(key.into(), &Self::IV.into())
|
||||||
.encrypt_padded_mut::<Pkcs7>(&mut buf, raw.len())
|
.encrypt_padded_vec_mut::<NoPadding>(&raw)
|
||||||
.unwrap();
|
.try_into()
|
||||||
|
.unwrap()
|
||||||
buf
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aes_cbc_decrypt(&self, raw: &[u8], key: &[u8; 32]) -> Vec<u8> {
|
pub fn aes_cbc_decrypt(&self, raw: [u8; 32], key: &[u8; 32]) -> [u8; 32] {
|
||||||
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
|
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
|
||||||
|
|
||||||
let mut buf = vec![0; raw.len()];
|
|
||||||
buf.copy_from_slice(raw);
|
|
||||||
|
|
||||||
Aes256CbcDec::new(key.into(), &Self::IV.into())
|
Aes256CbcDec::new(key.into(), &Self::IV.into())
|
||||||
.decrypt_padded_mut::<Pkcs7>(&mut buf)
|
.decrypt_padded_vec_mut::<NoPadding>(&raw)
|
||||||
.unwrap();
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
buf
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tcp_key(&mut self, response: &[u8], key: &[u8; 32]) -> Result<()> {
|
pub fn tcp_key(&mut self, response: &[u8], key: &[u8; 32]) -> Result<()> {
|
||||||
if response == b"ERROR" {
|
if response == b"ERROR" {
|
||||||
bail!("authentication failed!");
|
bail!("authentication failed! (code ERROR)");
|
||||||
}
|
}
|
||||||
|
|
||||||
let payload = &response[0..32];
|
let payload: [u8; 32] = response[0..32]
|
||||||
|
.iter()
|
||||||
|
.map(|&b| b)
|
||||||
|
.collect::<Vec<u8>>()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let sign = &response[32..];
|
let sign = &response[32..];
|
||||||
|
let result = self.aes_cbc_decrypt(payload, &key);
|
||||||
|
|
||||||
let plain = self.aes_cbc_decrypt(payload, &key);
|
if Sha256::digest(&result).into_iter().collect::<Vec<u8>>() != sign {
|
||||||
|
|
||||||
if Sha256::digest(&plain).into_iter().collect::<Vec<u8>>() != sign {
|
|
||||||
bail!("sign does not match");
|
bail!("sign does not match");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tcp_key = Some(Self::xorstr(&plain, key).try_into().unwrap());
|
self.tcp_key = Some(Self::xorstr(&result, key).try_into().unwrap());
|
||||||
self.request_count = 0;
|
self.request_count = 0;
|
||||||
self.response_count = 0;
|
self.response_count = 0;
|
||||||
|
|
||||||
|
@ -94,7 +92,7 @@ impl Security {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn xorstr(lhs: &[u8], rhs: &[u8]) -> Vec<u8> {
|
fn xorstr(lhs: &[u8], rhs: &[u8]) -> Vec<u8> {
|
||||||
assert_eq!(lhs.len(), rhs.len());
|
debug_assert_eq!(lhs.len(), rhs.len());
|
||||||
|
|
||||||
lhs.iter().zip(rhs.iter()).map(|(&l, &r)| l ^ r).collect()
|
lhs.iter().zip(rhs.iter()).map(|(&l, &r)| l ^ r).collect()
|
||||||
}
|
}
|
||||||
|
@ -135,7 +133,9 @@ impl Security {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
data = self.aes_cbc_encrypt(&data, self.tcp_key.as_ref().unwrap());
|
data = self
|
||||||
|
.aes_cbc_encrypt(data.try_into().unwrap(), self.tcp_key.as_ref().unwrap())
|
||||||
|
.to_vec();
|
||||||
data.extend(sign);
|
data.extend(sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,3 +148,28 @@ impl Security {
|
||||||
lhs
|
lhs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn aes_cbc_decrypt() {
|
||||||
|
let payload: [u8; 32] =
|
||||||
|
b",\xcbq_T\x81L\x96\xfa\xe7\xe4\xa7\xc5\xabU \r\xf5x\xd6\x08\x94_\\\xce\x8br\x1b\xa5\xbe\xc6\x1a"
|
||||||
|
.iter()
|
||||||
|
.map(|&b| b)
|
||||||
|
.collect::<Vec<u8>>()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let key = b"*[R\x00\xc2\xc0ML\x81\x1d\x05P\xe1\xdc[1CT6\xb9[wM*\x88\xd7\xe4ma\xfd\x96i";
|
||||||
|
let plain = b"\x9b\xaa\xdf\xff\x07\x1a\xd2\xe4\xb7TY\xe2\xf9\x8c\xdf\xe7!+\xda\xe4\x86GY\xe6j\x94\xdb\xe7\xb9b\xda\xe6";
|
||||||
|
|
||||||
|
let security = Security::default();
|
||||||
|
|
||||||
|
let result = security.aes_cbc_decrypt(payload, key);
|
||||||
|
|
||||||
|
assert_eq!(&result, plain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue