add encryption support

This commit is contained in:
spuds 2023-01-13 12:12:39 +00:00
parent 07bbbbc5ed
commit c440ca6707
No known key found for this signature in database
GPG key ID: 0B6CA6068E827C8F
5 changed files with 23 additions and 2 deletions

View file

@ -11,6 +11,7 @@ edition = "2021"
[dependencies] [dependencies]
byteorder = "*" byteorder = "*"
strum = { version = "*", features = ["derive"] } strum = { version = "*", features = ["derive"] }
aes = "*"
hashbrown = "*" hashbrown = "*"
thiserror = "*" thiserror = "*"

View file

@ -2,6 +2,7 @@ fn main() -> Result<(), un_pak::Error> {
let pak = un_pak::Pak::new( let pak = un_pak::Pak::new(
std::io::BufReader::new(std::io::Cursor::new(include_bytes!("rando_p.pak"))), std::io::BufReader::new(std::io::Cursor::new(include_bytes!("rando_p.pak"))),
un_pak::Version::CompressionEncryption, un_pak::Version::CompressionEncryption,
None,
)?; )?;
for file in pak.entries.keys() { for file in pak.entries.keys() {
println!("{file}") println!("{file}")

View file

@ -5,6 +5,7 @@ fn main() -> Result<(), un_pak::Error> {
match un_pak::Pak::new( match un_pak::Pak::new(
std::io::BufReader::new(std::fs::OpenOptions::new().read(true).open(&path)?), std::io::BufReader::new(std::fs::OpenOptions::new().read(true).open(&path)?),
ver, ver,
None,
) { ) {
Ok(un_pak::Pak { version, .. }) | Err(un_pak::Error::Version { version, .. }) => { Ok(un_pak::Pak { version, .. }) | Err(un_pak::Error::Version { version, .. }) => {
println!("{}", version); println!("{}", version);

View file

@ -1,9 +1,13 @@
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum Error { pub enum Error {
#[error("io error: {0}")] // dependency errors
Io(#[from] std::io::Error),
#[error("enum conversion: {0}")] #[error("enum conversion: {0}")]
Strum(#[from] strum::ParseError), Strum(#[from] strum::ParseError),
#[error("key hash is an incorrect length")]
Aes,
// std errors
#[error("io error: {0}")]
Io(#[from] std::io::Error),
#[error("utf8 conversion: {0}")] #[error("utf8 conversion: {0}")]
Utf8(#[from] std::string::FromUtf8Error), Utf8(#[from] std::string::FromUtf8Error),
#[error("utf16 conversion: {0}")] #[error("utf16 conversion: {0}")]
@ -11,6 +15,7 @@ pub enum Error {
#[error("bufwriter dereference: {0}")] #[error("bufwriter dereference: {0}")]
IntoInner(#[from] std::io::IntoInnerError<std::io::BufWriter<Vec<u8>>>), IntoInner(#[from] std::io::IntoInnerError<std::io::BufWriter<Vec<u8>>>),
#[error("found magic of {0:#x} instead of {:#x}", super::MAGIC)] #[error("found magic of {0:#x} instead of {:#x}", super::MAGIC)]
// crate errors
Magic(u32), Magic(u32),
#[error("used version {used} but pak is version {version}")] #[error("used version {used} but pak is version {version}")]
Version { Version {

View file

@ -1,6 +1,7 @@
use std::io; use std::io;
use super::ReadExt; use super::ReadExt;
use aes::cipher::{BlockDecrypt, KeyInit};
use byteorder::{ReadBytesExt, LE}; use byteorder::{ReadBytesExt, LE};
use super::Version; use super::Version;
@ -17,10 +18,22 @@ impl Pak {
pub fn new<R: io::Read + io::Seek>( pub fn new<R: io::Read + io::Seek>(
mut reader: R, mut reader: R,
version: super::Version, version: super::Version,
key: Option<&[u8]>,
) -> Result<Self, super::Error> { ) -> Result<Self, super::Error> {
reader.seek(io::SeekFrom::End(-version.size()))?; reader.seek(io::SeekFrom::End(-version.size()))?;
let footer = super::Footer::new(&mut reader, version)?; let footer = super::Footer::new(&mut reader, version)?;
reader.seek(io::SeekFrom::Start(footer.offset))?; reader.seek(io::SeekFrom::Start(footer.offset))?;
let mut index = reader.read_len(footer.size as usize)?;
if let Some(key) = key {
match aes::Aes256Dec::new_from_slice(key) {
Ok(key) => {
for chunk in index.chunks_mut(16) {
key.decrypt_block(aes::Block::from_mut_slice(chunk))
}
}
Err(_) => return Err(super::Error::Aes),
}
}
let mount_point = reader.read_string()?; let mount_point = reader.read_string()?;
let len = reader.read_u32::<LE>()? as usize; let len = reader.read_u32::<LE>()? as usize;
let mut entries = hashbrown::HashMap::with_capacity(len); let mut entries = hashbrown::HashMap::with_capacity(len);