diff --git a/Cargo.lock b/Cargo.lock index 432943f..5d741aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,6 +98,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0d27fb6b6f1e43147af148af49d49329413ba781aa0d5e10979831c210173b5" +[[package]] +name = "bit-set" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.2.1" @@ -793,6 +808,18 @@ version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +[[package]] +name = "memoize" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb49e4361c7534fd1fd1d4a1da51b1bb4b254c5ebc519fc4e5dce578fd69f5d9" +dependencies = [ + "lazy_static 1.4.0", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "mime" version = "0.3.16" @@ -1148,6 +1175,26 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "proptest" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" +dependencies = [ + "bit-set", + "bitflags", + "byteorder", + "lazy_static 1.4.0", + "num-traits", + "quick-error 2.0.1", + "rand 0.8.4", + "rand_chacha 0.3.0", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", +] + [[package]] name = "publicsuffix" version = "1.5.6" @@ -1158,6 +1205,18 @@ dependencies = [ "url", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quote" version = "1.0.9" @@ -1286,6 +1345,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.2", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -1452,6 +1520,18 @@ dependencies = [ "semver 0.11.0", ] +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error 1.2.3", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.5" @@ -1783,6 +1863,8 @@ dependencies = [ "hmac-sha1", "lazy_static 1.4.0", "log", + "memoize", + "proptest", "rand 0.8.4", "regex", "reqwest", @@ -2210,6 +2292,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "want" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 2e1daea..d85bacd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,8 @@ ring = "0.16.20" aes = "0.7.4" block-modes = "0.8.1" thiserror = "1.0.26" +memoize = "0.1.9" [dev-dependencies] tempdir = "0.3" +proptest = "1" diff --git a/src/encryption.rs b/src/encryption.rs index f31a343..07fbdfc 100644 --- a/src/encryption.rs +++ b/src/encryption.rs @@ -182,6 +182,7 @@ impl From for EntryEncryptionError { #[cfg(test)] mod tests { use super::*; + use proptest::prelude::*; /// This test ensures compatibility with SteamDesktopAuthenticator and with previous versions of steamguard-cli #[test] @@ -202,4 +203,45 @@ mod tests { .as_slice() ); } + + #[test] + fn test_ensure_encryption_symmetric() -> anyhow::Result<()> { + let passkey = "password"; + let params = EntryEncryptionParams::generate(); + let orig = "{{tactical glizzy}}".as_bytes().to_vec(); + let encrypted = + LegacySdaCompatible::encrypt(&passkey.clone().into(), ¶ms, orig.clone()).unwrap(); + let result = LegacySdaCompatible::decrypt(&passkey.into(), ¶ms, encrypted).unwrap(); + assert_eq!(orig, result.to_vec()); + return Ok(()); + } + + prop_compose! { + /// An insecure but reproducible strategy for generating encryption params. + fn encryption_params()(salt in any::<[u8; SALT_LENGTH]>(), iv in any::<[u8; IV_LENGTH]>()) -> EntryEncryptionParams { + EntryEncryptionParams { + salt: base64::encode(&salt), + iv: base64::encode(&iv), + scheme: EncryptionScheme::LegacySdaCompatible, + } + } + } + + // proptest! { + // #[test] + // fn ensure_encryption_symmetric( + // passkey in ".{1,}", + // params in encryption_params(), + // data in any::>(), + // ) { + // prop_assume!(data.len() >= 2); + // let mut orig = data; + // orig[0] = '{' as u8; + // let n = orig.len() - 1; + // orig[n] = '}' as u8; + // let encrypted = LegacySdaCompatible::encrypt(&passkey.clone().into(), ¶ms, orig.clone()).unwrap(); + // let result = LegacySdaCompatible::decrypt(&passkey.into(), ¶ms, encrypted).unwrap(); + // prop_assert_eq!(orig, result.to_vec()); + // } + // } } diff --git a/src/main.rs b/src/main.rs index c4f3156..d6856bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,8 @@ extern crate lazy_static; extern crate anyhow; extern crate base64; extern crate dirs; +#[cfg(test)] +extern crate proptest; extern crate ring; mod accountmanager; mod demos;