add broken encrypted maFiles test

This commit is contained in:
Carson McManus 2021-08-15 11:52:54 -04:00
parent edb2663baf
commit 7d7dd6701e
4 changed files with 158 additions and 6 deletions

80
Cargo.lock generated
View file

@ -8,6 +8,18 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aes"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "495ee669413bfbe9e8cace80f4d3d78e6d8c8d99579f97fb93bde351b185f2d4"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"opaque-debug",
]
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.15" version = "0.7.15"
@ -92,6 +104,22 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "block-modes"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e"
dependencies = [
"block-padding",
"cipher",
]
[[package]]
name = "block-padding"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.6.1" version = "3.6.1"
@ -135,6 +163,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "cipher"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.33.3" version = "2.33.3"
@ -211,6 +248,15 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
[[package]]
name = "cpufeatures"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.2.1" version = "1.2.1"
@ -690,9 +736,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.90" version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae" checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
[[package]] [[package]]
name = "libm" name = "libm"
@ -896,6 +942,12 @@ version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.33" version = "0.10.33"
@ -1337,6 +1389,21 @@ dependencies = [
"winreg", "winreg",
] ]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]] [[package]]
name = "rpassword" name = "rpassword"
version = "5.0.1" version = "5.0.1"
@ -1706,8 +1773,10 @@ dependencies = [
name = "steamguard-cli" name = "steamguard-cli"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"aes",
"anyhow", "anyhow",
"base64", "base64",
"block-modes",
"clap", "clap",
"cookie", "cookie",
"dirs", "dirs",
@ -1717,6 +1786,7 @@ dependencies = [
"rand 0.8.4", "rand 0.8.4",
"regex", "regex",
"reqwest", "reqwest",
"ring",
"rpassword", "rpassword",
"rsa", "rsa",
"serde", "serde",
@ -2082,6 +2152,12 @@ dependencies = [
"void", "void",
] ]
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]] [[package]]
name = "url" name = "url"
version = "2.2.1" version = "2.2.1"

View file

@ -34,6 +34,9 @@ uuid = { version = "0.8", features = ["v4"] }
termion = "1.5.6" termion = "1.5.6"
steamguard = { path = "./steamguard" } steamguard = { path = "./steamguard" }
dirs = "3.0.2" dirs = "3.0.2"
ring = "0.16.20"
aes = "0.7.4"
block-modes = "0.8.1"
[dev-dependencies] [dev-dependencies]
tempdir = "0.3" tempdir = "0.3"

View file

@ -1,11 +1,17 @@
use aes::Aes256;
use block_modes::block_padding::Pkcs7;
use block_modes::{BlockMode, Cbc};
use log::*; use log::*;
use ring::pbkdf2;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::io::{BufReader, Write}; use std::fs::File;
use std::io::{BufReader, Read, Write};
use std::path::Path; use std::path::Path;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::{cell::Cell, fs::File};
use steamguard::SteamGuardAccount; use steamguard::SteamGuardAccount;
type Aes256Cbc = Cbc<Aes256, Pkcs7>;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Manifest { pub struct Manifest {
pub encrypted: bool, pub encrypted: bool,
@ -89,8 +95,25 @@ impl Manifest {
let path = Path::new(&self.folder).join(&entry.filename); let path = Path::new(&self.folder).join(&entry.filename);
debug!("loading account: {:?}", path); debug!("loading account: {:?}", path);
let file = File::open(path)?; let file = File::open(path)?;
let reader = BufReader::new(file); let mut reader = BufReader::new(file);
let account: SteamGuardAccount = serde_json::from_reader(reader)?; let account: SteamGuardAccount;
match (passkey, entry.encryption.as_ref()) {
(Some(passkey), Some(params)) => {
let key = get_encryption_key(&passkey.into(), &params.salt)?;
let iv = base64::decode(&params.iv)?;
let cipher = Aes256Cbc::new_from_slices(&key, &iv)?;
let mut ciphertext: Vec<u8> = vec![];
reader.read_to_end(&mut ciphertext)?;
let decrypted = cipher.decrypt(&mut ciphertext)?;
account = serde_json::from_slice(decrypted)?;
}
(None, Some(_)) => {
bail!("maFiles are encrypted, but no passkey was provided.");
}
(_, None) => {
account = serde_json::from_reader(reader)?;
}
};
entry.account_name = account.account_name.clone(); entry.account_name = account.account_name.clone();
self.accounts.push(Arc::new(Mutex::new(account))); self.accounts.push(Arc::new(Mutex::new(account)));
} }
@ -159,6 +182,25 @@ impl Manifest {
} }
} }
const PBKDF2_ITERATIONS: u32 = 50000;
const SALT_LENGTH: usize = 8;
const KEY_SIZE_BYTES: usize = 32;
const IV_LENGTH: usize = 16;
fn get_encryption_key(passkey: &String, salt: &String) -> anyhow::Result<[u8; KEY_SIZE_BYTES]> {
let password_bytes = passkey.as_bytes();
let salt_bytes = base64::decode(salt)?;
let mut full_key: [u8; KEY_SIZE_BYTES] = [0u8; KEY_SIZE_BYTES];
pbkdf2::derive(
pbkdf2::PBKDF2_HMAC_SHA256,
std::num::NonZeroU32::new(PBKDF2_ITERATIONS).unwrap(),
&salt_bytes,
password_bytes,
&mut full_key,
);
return Ok(full_key);
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -269,4 +311,33 @@ mod tests {
.account_name .account_name
); );
} }
#[test]
fn test_sda_compatibility_1_encrypted() {
let path = Path::new("src/fixtures/maFiles/1-account-encrypted/manifest.json");
assert!(path.is_file());
let result = Manifest::load(path);
assert!(matches!(result, Ok(_)));
let mut manifest = result.unwrap();
assert!(matches!(
manifest.entries.last().unwrap().encryption,
Some(_)
));
let result = manifest.load_accounts(Some("password"));
assert!(
matches!(result, Ok(_)),
"error when loading accounts: {:?}",
result.unwrap_err()
);
assert_eq!(
manifest.entries.last().unwrap().account_name,
manifest
.accounts
.last()
.unwrap()
.lock()
.unwrap()
.account_name
);
}
} }

View file

@ -16,7 +16,9 @@ use steamguard::{
extern crate lazy_static; extern crate lazy_static;
#[macro_use] #[macro_use]
extern crate anyhow; extern crate anyhow;
extern crate base64;
extern crate dirs; extern crate dirs;
extern crate ring;
mod accountmanager; mod accountmanager;
mod demos; mod demos;
mod tui; mod tui;