diff --git a/src/entry.rs b/src/entry.rs
index 52895f2..189b054 100644
--- a/src/entry.rs
+++ b/src/entry.rs
@@ -34,6 +34,7 @@ pub struct Entry {
 
 impl Entry {
     pub fn new<R: io::Read>(reader: &mut R, version: super::Version) -> Result<Self, super::Error> {
+        // since i need the compression flags, i have to store these as variables which is mildly annoying
         let offset = reader.read_u64::<LE>()?;
         let compressed = reader.read_u64::<LE>()?;
         let uncompressed = reader.read_u64::<LE>()?;
@@ -66,9 +67,10 @@ impl Entry {
     }
 
     pub fn read<R: io::Read + io::Seek>(
-        self,
+        &self,
         reader: &mut R,
         version: super::Version,
+        key: Option<&aes::Aes256Dec>,
     ) -> Result<Vec<u8>, super::Error> {
         let buf = io::BufWriter::new(Vec::new());
         todo!("read the stuff");
diff --git a/src/footer.rs b/src/footer.rs
index 747fd84..3798cd5 100644
--- a/src/footer.rs
+++ b/src/footer.rs
@@ -10,8 +10,8 @@ pub struct Footer {
     pub encrypted: bool,
     pub magic: u32,
     pub version: Version,
-    pub offset: u64,
-    pub size: u64,
+    pub index_offset: u64,
+    pub index_size: u64,
     pub hash: [u8; 20],
     pub frozen: bool,
     pub compression: Vec<Compression>,
@@ -27,8 +27,8 @@ impl Footer {
             encrypted: version >= Version::IndexEncryption && reader.read_bool()?,
             magic: reader.read_u32::<LE>()?,
             version: Version::from_repr(reader.read_u32::<LE>()?).unwrap_or(version),
-            offset: reader.read_u64::<LE>()?,
-            size: reader.read_u64::<LE>()?,
+            index_offset: reader.read_u64::<LE>()?,
+            index_size: reader.read_u64::<LE>()?,
             hash: reader.read_guid()?,
             frozen: version == Version::FrozenIndex && reader.read_bool()?,
             compression: {
diff --git a/src/pak.rs b/src/pak.rs
index 253c128..ab766ae 100644
--- a/src/pak.rs
+++ b/src/pak.rs
@@ -1,53 +1,76 @@
 use std::io;
 
-use super::ReadExt;
-use aes::cipher::{BlockDecrypt, KeyInit};
-use byteorder::{ReadBytesExt, LE};
-
 use super::Version;
 
 #[derive(Debug)]
-pub struct Pak {
-    pub version: Version,
-    pub footer: super::Footer,
-    pub mount_point: String,
-    pub entries: hashbrown::HashMap<String, super::Entry>,
+pub struct Pak<R: io::Read + io::Seek> {
+    version: Version,
+    mount_point: String,
+    key: Option<aes::Aes256Dec>,
+    entries: hashbrown::HashMap<String, super::Entry>,
+    reader: R,
 }
 
-impl Pak {
-    pub fn new<R: io::Read + io::Seek>(
+impl<R: io::Read + io::Seek> Pak<R> {
+    pub fn new(
         mut reader: R,
         version: super::Version,
-        key: Option<&[u8]>,
+        key_hash: Option<&[u8]>,
     ) -> Result<Self, super::Error> {
+        use super::ReadExt;
+        use byteorder::{ReadBytesExt, LE};
+        // read footer to get index, encryption & compression info
         reader.seek(io::SeekFrom::End(-version.size()))?;
         let footer = super::Footer::new(&mut reader, version)?;
-        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))
+        // 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 {
+            if let Some(hash) = key_hash {
+                use aes::cipher::{BlockDecrypt, KeyInit};
+                match aes::Aes256Dec::new_from_slice(hash) {
+                    Ok(decrypter) => {
+                        for chunk in index.chunks_mut(16) {
+                            decrypter.decrypt_block(aes::Block::from_mut_slice(chunk))
+                        }
+                        key = Some(decrypter);
                     }
+                    Err(_) => return Err(super::Error::Aes),
                 }
-                Err(_) => return Err(super::Error::Aes),
             }
         }
-        let mount_point = reader.read_string()?;
-        let len = reader.read_u32::<LE>()? as usize;
+        let mut index = io::Cursor::new(index);
+        let mount_point = index.read_string()?;
+        let len = index.read_u32::<LE>()? as usize;
         let mut entries = hashbrown::HashMap::with_capacity(len);
         for _ in 0..len {
             entries.insert(
-                reader.read_string()?,
-                super::Entry::new(&mut reader, version)?,
+                index.read_string()?,
+                super::Entry::new(&mut index, version)?,
             );
         }
         Ok(Self {
             version,
-            footer,
             mount_point,
+            key,
             entries,
+            reader,
         })
     }
+
+    pub fn version(&self) -> super::Version {
+        self.version
+    }
+
+    pub fn mount_point(&self) -> &str {
+        &self.mount_point
+    }
+
+    pub fn get(&mut self, path: &str) -> Option<Result<Vec<u8>, super::Error>> {
+        self.entries
+            .get(path)
+            .map(|entry| entry.read(&mut self.reader, self.version, self.key.as_ref()))
+    }
 }