Check / stable / fmt (push) Successful in 9m55s
Check / beta / clippy (push) Failing after 38s
Check / stable / clippy (push) Failing after 39s
Check / nightly / doc (push) Failing after 37s
Check / 1.89.0 / check (push) Failing after 38s
Test Suite / ubuntu / beta (push) Failing after 38s
Test Suite / ubuntu / stable (push) Failing after 39s
Test Suite / ubuntu / stable / coverage (push) Failing after 1m28s
Test Suite / macos-latest / stable (push) Has been cancelled
Test Suite / windows-latest / stable (push) Has been cancelled
36 lines
1.3 KiB
Rust
36 lines
1.3 KiB
Rust
use base64::Engine;
|
|
use gman::{decrypt_string, encrypt_string};
|
|
use proptest::prelude::*;
|
|
use secrecy::SecretString;
|
|
|
|
proptest! {
|
|
// Reduced case count because Argon2 key derivation is intentionally slow
|
|
// (65 MiB memory, 3 iterations per encryption/decryption)
|
|
#![proptest_config(ProptestConfig::with_cases(4))]
|
|
|
|
#[test]
|
|
fn prop_encrypt_decrypt_roundtrip(password in ".{1,64}", msg in ".{0,512}") {
|
|
let pw = SecretString::new(password.into());
|
|
let env = encrypt_string(pw.clone(), &msg).unwrap();
|
|
let out = decrypt_string(pw, &env).unwrap();
|
|
|
|
prop_assert_eq!(out, msg);
|
|
}
|
|
|
|
#[test]
|
|
fn prop_tamper_ciphertext_detected(password in ".{1,32}", msg in ".{1,128}") {
|
|
let pw = SecretString::new(password.into());
|
|
let env = encrypt_string(pw.clone(), &msg).unwrap();
|
|
let mut parts: Vec<&str> = env.split(';').collect();
|
|
let ct_b64 = parts[6].strip_prefix("ct=").unwrap();
|
|
let mut ct = base64::engine::general_purpose::STANDARD.decode(ct_b64).unwrap();
|
|
ct[0] ^= 0x1;
|
|
let new_ct_b64 = base64::engine::general_purpose::STANDARD.encode(&ct);
|
|
let new_ct = format!("ct={}", new_ct_b64);
|
|
parts[6] = Box::leak(new_ct.into_boxed_str());
|
|
let tampered = parts.join(";");
|
|
|
|
prop_assert!(decrypt_string(pw, &tampered).is_err());
|
|
}
|
|
}
|