mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-08 22:08:47 +08:00
Add Support for muisca paz archive
This commit is contained in:
@@ -168,6 +168,7 @@ mod consts {
|
||||
|
||||
use anyhow::Result;
|
||||
use byteorder::{BE, ByteOrder, LE};
|
||||
use std::io::{Read, Seek};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Blowfish variant which uses Little Endian byte order read/writes.s.
|
||||
@@ -181,15 +182,9 @@ pub struct Blowfish<T: ByteOrder = BE> {
|
||||
_pd: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Blowfish<BE> {
|
||||
impl<T: ByteOrder> std::fmt::Debug for Blowfish<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("Blowfish<BE> { ... }")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Blowfish<LE> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("Blowfish<LE> { ... }")
|
||||
f.write_str("Blowfish { ... }")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,3 +285,106 @@ impl<T: ByteOrder> Blowfish<T> {
|
||||
Ok(blowfish)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Blowfish decryption stream wrapper.
|
||||
pub struct BlowfishDecryptor<B: ByteOrder, T> {
|
||||
cipher: Blowfish<B>,
|
||||
buffer: [u8; 8],
|
||||
buffer_len: usize,
|
||||
buffer_is_decrypted: bool,
|
||||
stream: T,
|
||||
}
|
||||
|
||||
impl<B: ByteOrder, T: std::io::Read> BlowfishDecryptor<B, T> {
|
||||
pub fn new(cipher: Blowfish<B>, stream: T) -> Self {
|
||||
Self {
|
||||
cipher,
|
||||
buffer: [0u8; 8],
|
||||
buffer_len: 0,
|
||||
buffer_is_decrypted: false,
|
||||
stream,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_key(key: &[u8], stream: T) -> Result<Self> {
|
||||
let cipher = Blowfish::new(key)?;
|
||||
Ok(Self::new(cipher, stream))
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: ByteOrder, T: Read> Read for BlowfishDecryptor<B, T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
if self.buffer_is_decrypted && self.buffer_len > 0 {
|
||||
let to_copy = std::cmp::min(buf.len(), self.buffer_len);
|
||||
buf[..to_copy].copy_from_slice(&self.buffer[..to_copy]);
|
||||
if to_copy < self.buffer_len {
|
||||
for i in 0..(self.buffer_len - to_copy) {
|
||||
self.buffer[i] = self.buffer[to_copy + i];
|
||||
}
|
||||
}
|
||||
self.buffer_len -= to_copy;
|
||||
self.buffer_is_decrypted = self.buffer_len > 0;
|
||||
return Ok(to_copy);
|
||||
}
|
||||
if buf.len() < 8 {
|
||||
if self.buffer_len < 8 {
|
||||
self.stream
|
||||
.read_exact(&mut self.buffer[self.buffer_len..])?;
|
||||
}
|
||||
self.cipher.decrypt_block(&mut self.buffer);
|
||||
self.buffer_len = 8;
|
||||
self.buffer_is_decrypted = true;
|
||||
let to_copy = std::cmp::min(buf.len(), self.buffer_len);
|
||||
buf[..to_copy].copy_from_slice(&self.buffer[..to_copy]);
|
||||
if to_copy < self.buffer_len {
|
||||
for i in 0..(self.buffer_len - to_copy) {
|
||||
self.buffer[i] = self.buffer[to_copy + i];
|
||||
}
|
||||
}
|
||||
self.buffer_len -= to_copy;
|
||||
self.buffer_is_decrypted = self.buffer_len > 0;
|
||||
return Ok(to_copy);
|
||||
}
|
||||
let mut start_index = 0;
|
||||
if self.buffer_len > 0 {
|
||||
buf[..self.buffer_len].copy_from_slice(&self.buffer[..self.buffer_len]);
|
||||
start_index += self.buffer_len;
|
||||
}
|
||||
let readed = self.stream.read(&mut buf[start_index..])?;
|
||||
let total_readed = start_index + readed;
|
||||
let total_decrypted = total_readed - (total_readed % 8);
|
||||
self.cipher.decrypt_block(&mut buf[..total_decrypted]);
|
||||
if total_readed != total_decrypted {
|
||||
self.buffer_len = total_readed - total_decrypted;
|
||||
self.buffer[..self.buffer_len].copy_from_slice(&buf[total_decrypted..total_readed]);
|
||||
} else {
|
||||
self.buffer_len = 0;
|
||||
}
|
||||
self.buffer_is_decrypted = false;
|
||||
Ok(total_decrypted)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read + Seek, B: ByteOrder> Seek for BlowfishDecryptor<B, T> {
|
||||
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||
if matches!(pos, std::io::SeekFrom::End(0)) {
|
||||
let newpos = self.stream.seek(pos)?;
|
||||
self.buffer_len = 0;
|
||||
self.buffer_is_decrypted = false;
|
||||
return Ok(newpos);
|
||||
}
|
||||
let newpos = self.stream.seek(pos)?;
|
||||
if newpos % 8 != 0 {
|
||||
let block_start = newpos - (newpos % 8);
|
||||
self.stream.seek(std::io::SeekFrom::Start(block_start))?;
|
||||
self.buffer_len = (newpos - block_start) as usize;
|
||||
self.stream
|
||||
.read_exact(&mut self.buffer[..self.buffer_len])?;
|
||||
} else {
|
||||
self.buffer_len = 0;
|
||||
}
|
||||
self.buffer_is_decrypted = false;
|
||||
Ok(newpos)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,16 @@ pub mod name_replacement;
|
||||
pub mod num_range;
|
||||
#[cfg(feature = "utils-pcm")]
|
||||
pub mod pcm;
|
||||
#[cfg(feature = "utils-rc4")]
|
||||
pub mod rc4;
|
||||
#[cfg(feature = "utils-serde-base64bytes")]
|
||||
pub mod serde_base64bytes;
|
||||
#[cfg(feature = "utils-str")]
|
||||
pub mod str;
|
||||
pub mod struct_pack;
|
||||
pub mod threadpool;
|
||||
#[cfg(feature = "utils-xored-stream")]
|
||||
pub mod xored_stream;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub use encoding_win::WinError;
|
||||
|
||||
87
src/utils/rc4.rs
Normal file
87
src/utils/rc4.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use std::io::{Read, Write};
|
||||
|
||||
pub struct Rc4 {
|
||||
state: [u8; 256],
|
||||
i: u8,
|
||||
j: u8,
|
||||
}
|
||||
|
||||
impl Rc4 {
|
||||
pub fn new(key: &[u8]) -> Self {
|
||||
let mut state = [0u8; 256];
|
||||
for i in 0..256 {
|
||||
state[i] = i as u8;
|
||||
}
|
||||
|
||||
let mut j: u8 = 0;
|
||||
for i in 0..256 {
|
||||
j = j.wrapping_add(state[i]).wrapping_add(key[i % key.len()]);
|
||||
state.swap(i, j as usize);
|
||||
}
|
||||
|
||||
Rc4 { state, i: 0, j: 0 }
|
||||
}
|
||||
|
||||
pub fn next_byte(&mut self) -> u8 {
|
||||
self.i = self.i.wrapping_add(1);
|
||||
self.j = self.j.wrapping_add(self.state[self.i as usize]);
|
||||
self.state.swap(self.i as usize, self.j as usize);
|
||||
let k = self.state
|
||||
[(self.state[self.i as usize].wrapping_add(self.state[self.j as usize])) as usize];
|
||||
k
|
||||
}
|
||||
|
||||
pub fn skip_bytes(&mut self, n: usize) {
|
||||
for _ in 0..n {
|
||||
self.next_byte();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_block(&mut self, len: usize) -> Vec<u8> {
|
||||
(0..len).map(|_| self.next_byte()).collect()
|
||||
}
|
||||
|
||||
pub fn process_block(&mut self, data: &mut [u8]) {
|
||||
for byte in data.iter_mut() {
|
||||
*byte ^= self.next_byte();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Rc4Stream<T> {
|
||||
inner: T,
|
||||
rc4: Rc4,
|
||||
}
|
||||
|
||||
impl<T> Rc4Stream<T> {
|
||||
pub fn new(inner: T, rc4: Rc4) -> Self {
|
||||
Rc4Stream { inner, rc4 }
|
||||
}
|
||||
|
||||
pub fn new_with_key(inner: T, key: &[u8]) -> Self {
|
||||
Rc4Stream {
|
||||
inner,
|
||||
rc4: Rc4::new(key),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read> Read for Rc4Stream<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
let n = self.inner.read(buf)?;
|
||||
self.rc4.process_block(&mut buf[..n]);
|
||||
Ok(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Write> Write for Rc4Stream<T> {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
let mut data = buf.to_vec();
|
||||
self.rc4.process_block(&mut data);
|
||||
self.inner.write(&data)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
45
src/utils/serde_base64bytes.rs
Normal file
45
src/utils/serde_base64bytes.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use base64::Engine;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Base64Bytes {
|
||||
pub bytes: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Deref for Base64Bytes {
|
||||
type Target = Vec<u8>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Base64Bytes {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Base64Bytes {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let encoded = base64::engine::general_purpose::STANDARD.encode(&self.bytes);
|
||||
serializer.serialize_str(&encoded)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Base64Bytes {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let s: &str = Deserialize::deserialize(deserializer)?;
|
||||
let decoded = base64::engine::general_purpose::STANDARD
|
||||
.decode(s)
|
||||
.map_err(serde::de::Error::custom)?;
|
||||
Ok(Base64Bytes { bytes: decoded })
|
||||
}
|
||||
}
|
||||
59
src/utils/xored_stream.rs
Normal file
59
src/utils/xored_stream.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
use std::io::{Read, Seek, Write};
|
||||
|
||||
pub struct XoredStream<T> {
|
||||
reader: T,
|
||||
key: u8,
|
||||
}
|
||||
|
||||
impl<T> XoredStream<T> {
|
||||
pub fn new(reader: T, key: u8) -> Self {
|
||||
XoredStream { reader, key }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read> Read for XoredStream<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
let read_bytes = self.reader.read(buf)?;
|
||||
for byte in &mut buf[..read_bytes] {
|
||||
*byte ^= self.key;
|
||||
}
|
||||
Ok(read_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Seek> Seek for XoredStream<T> {
|
||||
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||
self.reader.seek(pos)
|
||||
}
|
||||
|
||||
fn rewind(&mut self) -> std::io::Result<()> {
|
||||
self.reader.rewind()
|
||||
}
|
||||
|
||||
fn stream_position(&mut self) -> std::io::Result<u64> {
|
||||
self.reader.stream_position()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Write> Write for XoredStream<T> {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
let mut encrypted_buf = buf.to_vec();
|
||||
for byte in &mut encrypted_buf {
|
||||
*byte ^= self.key;
|
||||
}
|
||||
self.reader.write(&encrypted_buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
self.reader.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: std::fmt::Debug> std::fmt::Debug for XoredStream<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("XoredStream")
|
||||
.field("reader", &self.reader)
|
||||
.field("key", &self.key)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user