add broken encrypted maFiles test
This commit is contained in:
parent
edb2663baf
commit
7d7dd6701e
4 changed files with 158 additions and 6 deletions
80
Cargo.lock
generated
80
Cargo.lock
generated
|
@ -8,6 +8,18 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
|
@ -92,6 +104,22 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.1"
|
||||
|
@ -135,6 +163,15 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
|
@ -211,6 +248,15 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.2.1"
|
||||
|
@ -690,9 +736,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.90"
|
||||
version = "0.2.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae"
|
||||
checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
|
@ -896,6 +942,12 @@ version = "1.7.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.33"
|
||||
|
@ -1337,6 +1389,21 @@ dependencies = [
|
|||
"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]]
|
||||
name = "rpassword"
|
||||
version = "5.0.1"
|
||||
|
@ -1706,8 +1773,10 @@ dependencies = [
|
|||
name = "steamguard-cli"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"anyhow",
|
||||
"base64",
|
||||
"block-modes",
|
||||
"clap",
|
||||
"cookie",
|
||||
"dirs",
|
||||
|
@ -1717,6 +1786,7 @@ dependencies = [
|
|||
"rand 0.8.4",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"ring",
|
||||
"rpassword",
|
||||
"rsa",
|
||||
"serde",
|
||||
|
@ -2082,6 +2152,12 @@ dependencies = [
|
|||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.2.1"
|
||||
|
|
|
@ -34,6 +34,9 @@ uuid = { version = "0.8", features = ["v4"] }
|
|||
termion = "1.5.6"
|
||||
steamguard = { path = "./steamguard" }
|
||||
dirs = "3.0.2"
|
||||
ring = "0.16.20"
|
||||
aes = "0.7.4"
|
||||
block-modes = "0.8.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3"
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
use aes::Aes256;
|
||||
use block_modes::block_padding::Pkcs7;
|
||||
use block_modes::{BlockMode, Cbc};
|
||||
use log::*;
|
||||
use ring::pbkdf2;
|
||||
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::sync::{Arc, Mutex};
|
||||
use std::{cell::Cell, fs::File};
|
||||
use steamguard::SteamGuardAccount;
|
||||
|
||||
type Aes256Cbc = Cbc<Aes256, Pkcs7>;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Manifest {
|
||||
pub encrypted: bool,
|
||||
|
@ -89,8 +95,25 @@ impl Manifest {
|
|||
let path = Path::new(&self.folder).join(&entry.filename);
|
||||
debug!("loading account: {:?}", path);
|
||||
let file = File::open(path)?;
|
||||
let reader = BufReader::new(file);
|
||||
let account: SteamGuardAccount = serde_json::from_reader(reader)?;
|
||||
let mut reader = BufReader::new(file);
|
||||
let account: SteamGuardAccount;
|
||||
match (passkey, entry.encryption.as_ref()) {
|
||||
(Some(passkey), Some(params)) => {
|
||||
let key = get_encryption_key(&passkey.into(), ¶ms.salt)?;
|
||||
let iv = base64::decode(¶ms.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();
|
||||
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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -269,4 +311,33 @@ mod tests {
|
|||
.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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,9 @@ use steamguard::{
|
|||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate anyhow;
|
||||
extern crate base64;
|
||||
extern crate dirs;
|
||||
extern crate ring;
|
||||
mod accountmanager;
|
||||
mod demos;
|
||||
mod tui;
|
||||
|
|
Loading…
Reference in a new issue