mirror of
https://github.com/xavo95/repak.git
synced 2025-01-18 10:54:38 +00:00
Handle AES key parsing outside of pak
This commit is contained in:
parent
6c2fe4dfb7
commit
d62915ec16
8 changed files with 29 additions and 20 deletions
|
@ -18,3 +18,4 @@ aes = "0.8"
|
|||
flate2 = "1.0"
|
||||
hashbrown = "0.13"
|
||||
thiserror = "1.0"
|
||||
base64 = "0.21.0"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub fn list(path: String, key: String) -> Result<(), unpak::Error> {
|
||||
pub fn list(path: String, key: Option<String>) -> Result<(), unpak::Error> {
|
||||
for file in super::load_pak(path, key)?.files() {
|
||||
println!("{file}");
|
||||
}
|
||||
|
|
|
@ -5,16 +5,27 @@ pub use {list::list, unpack::unpack, version::version};
|
|||
|
||||
fn load_pak(
|
||||
path: String,
|
||||
key: String,
|
||||
key: Option<String>,
|
||||
) -> Result<unpak::Pak<std::io::BufReader<std::fs::File>>, unpak::Error> {
|
||||
use aes::cipher::KeyInit;
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
let key = key
|
||||
.map(|k| {
|
||||
general_purpose::STANDARD
|
||||
.decode(k)
|
||||
.as_ref()
|
||||
.map_err(|_| unpak::Error::Base64)
|
||||
.and_then(|bytes| {
|
||||
aes::Aes256Dec::new_from_slice(bytes).map_err(|_| unpak::Error::Aes)
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
for ver in unpak::Version::iter() {
|
||||
match unpak::Pak::new(
|
||||
std::io::BufReader::new(std::fs::OpenOptions::new().read(true).open(&path)?),
|
||||
ver,
|
||||
match key.as_bytes() {
|
||||
&[] => None,
|
||||
key => Some(key),
|
||||
},
|
||||
key.clone(),
|
||||
) {
|
||||
Ok(pak) => {
|
||||
return Ok(pak);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub fn unpack(path: String, key: String) -> Result<(), unpak::Error> {
|
||||
pub fn unpack(path: String, key: Option<String>) -> Result<(), unpak::Error> {
|
||||
let folder = std::path::Path::new(
|
||||
std::path::Path::new(&path)
|
||||
.file_stem()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub fn version(path: String, key: String) -> Result<(), unpak::Error> {
|
||||
pub fn version(path: String, key: Option<String>) -> Result<(), unpak::Error> {
|
||||
println!("{}", super::load_pak(path, key)?.version());
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ fn main() {
|
|||
};
|
||||
// can't map key to &[u8] because refers to owned data
|
||||
if let Err(e) = match args.next().unwrap_or_default().as_str() {
|
||||
"version" => subcommands::version(path, args.next().unwrap_or_default()),
|
||||
"list" => subcommands::list(path, args.next().unwrap_or_default()),
|
||||
"unpack" | "" => subcommands::unpack(path, args.next().unwrap_or_default()),
|
||||
"version" => subcommands::version(path, args.next()),
|
||||
"list" => subcommands::list(path, args.next()),
|
||||
"unpack" | "" => subcommands::unpack(path, args.next()),
|
||||
"help" | _ => help(),
|
||||
} {
|
||||
eprintln!("{e}")
|
||||
|
|
|
@ -5,6 +5,8 @@ pub enum Error {
|
|||
Strum(#[from] strum::ParseError),
|
||||
#[error("key hash is an incorrect length")]
|
||||
Aes,
|
||||
#[error("malformed base64")]
|
||||
Base64,
|
||||
// std errors
|
||||
#[error("io error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
|
13
src/pak.rs
13
src/pak.rs
|
@ -14,7 +14,7 @@ impl<R: io::Read + io::Seek> Pak<R> {
|
|||
pub fn new(
|
||||
mut reader: R,
|
||||
version: super::Version,
|
||||
key_hash: Option<&[u8]>,
|
||||
key: Option<aes::Aes256Dec>,
|
||||
) -> Result<Self, super::Error> {
|
||||
use super::ext::ReadExt;
|
||||
use byteorder::{ReadBytesExt, LE};
|
||||
|
@ -24,20 +24,15 @@ impl<R: io::Read + io::Seek> Pak<R> {
|
|||
// read index to get all the entry info
|
||||
reader.seek(io::SeekFrom::Start(footer.index_offset))?;
|
||||
let mut index = reader.read_len(footer.index_size as usize)?;
|
||||
let mut key = None;
|
||||
// decrypt index if needed
|
||||
if footer.encrypted {
|
||||
let Some(hash) = key_hash else {
|
||||
let Some(key) = &key else {
|
||||
return Err(super::Error::Encrypted);
|
||||
};
|
||||
use aes::cipher::{BlockDecrypt, KeyInit};
|
||||
let Ok(decrypter)= aes::Aes256Dec::new_from_slice(hash) else {
|
||||
return Err(super::Error::Aes)
|
||||
};
|
||||
use aes::cipher::BlockDecrypt;
|
||||
for chunk in index.chunks_mut(16) {
|
||||
decrypter.decrypt_block(aes::Block::from_mut_slice(chunk))
|
||||
key.decrypt_block(aes::Block::from_mut_slice(chunk))
|
||||
}
|
||||
key = Some(decrypter);
|
||||
}
|
||||
let mut index = io::Cursor::new(index);
|
||||
let mount_point = index.read_string()?;
|
||||
|
|
Loading…
Reference in a new issue