use crate::crypto::digest::*;
use crate::crypto::key::*;
use crate::crypto::keystore::*;
use crate::crypto::secret::Secret;
use crate::testing::temp;
use std::fs;
fn new_password(password: &str) -> Secret {
let bytes = password.as_bytes();
let mut s = Secret::with_len(bytes.len()).unwrap();
unsafe { s.as_mut_slice() }.copy_from_slice(bytes);
s
}
fn new_password_key(password: &str, salt: &Salt) -> Key {
Key::new_password(
&new_password(password),
salt,
OPS_LIMIT_INTERACTIVE,
MEM_LIMIT_INTERACTIVE,
)
.unwrap()
}
#[test]
fn test_keystore_save_round_trip() {
crate::init().unwrap();
let file = temp::File::new_file().unwrap();
let wrap_key = Key::new_random().unwrap();
let master_digest: Option<Digest>;
{
let mut keystore = DiskKeyStore::new(file.path(), false).unwrap();
assert!(keystore.add_key(&wrap_key).unwrap());
master_digest = Some(keystore.get_master_key().unwrap().get_digest());
}
{
let mut keystore = DiskKeyStore::new(file.path(), false).unwrap();
keystore.open(&wrap_key).unwrap();
assert_eq!(
master_digest.unwrap(),
keystore.get_master_key().unwrap().get_digest()
);
}
}
#[test]
fn test_keystore_open_with_added_key() {
crate::init().unwrap();
let file = temp::File::new_file().unwrap();
let salt = Salt::default();
let keya = new_password_key("foo", &salt);
let keyb = new_password_key("bar", &salt);
assert_ne!(keya.get_digest(), keyb.get_digest());
let master_digest: Option<Digest>;
{
let mut keystore = DiskKeyStore::new(file.path(), false).unwrap();
assert!(keystore.add_key(&keya).unwrap());
master_digest = Some(keystore.get_master_key().unwrap().get_digest());
assert!(keystore.add_key(&keyb).unwrap());
}
{
let mut keystore = DiskKeyStore::new(file.path(), false).unwrap();
keystore.open(&keyb).unwrap();
assert_eq!(
master_digest.unwrap(),
keystore.get_master_key().unwrap().get_digest()
);
}
}
#[test]
fn test_add_duplicate_key() {
crate::init().unwrap();
let file = temp::File::new_file().unwrap();
let wrap_key = Key::new_random().unwrap();
let mut keystore = DiskKeyStore::new(file.path(), false).unwrap();
keystore.add_key(&wrap_key).unwrap();
assert!(!keystore.add_key(&wrap_key).unwrap());
}
#[test]
fn test_remove_unused_key() {
crate::init().unwrap();
let file = temp::File::new_file().unwrap();
let salt = Salt::default();
let keya = new_password_key("foo", &salt);
let keyb = new_password_key("bar", &salt);
assert_ne!(keya.get_digest(), keyb.get_digest());
let mut keystore = DiskKeyStore::new(file.path(), false).unwrap();
keystore.add_key(&keya).unwrap();
assert!(!keystore.remove_key(&keyb).unwrap());
}
#[test]
fn test_remove_only_key() {
crate::init().unwrap();
let file = temp::File::new_file().unwrap();
let key = Key::new_random().unwrap();
let mut keystore = DiskKeyStore::new(file.path(), false).unwrap();
keystore.add_key(&key).unwrap();
assert!(keystore.remove_key(&key).is_err());
}
#[test]
fn test_remove_first_key() {
crate::init().unwrap();
let file = temp::File::new_file().unwrap();
let key_a = Key::new_random().unwrap();
let key_b = Key::new_random().unwrap();
let mut keystore = DiskKeyStore::new(file.path(), false).unwrap();
keystore.add_key(&key_a).unwrap();
assert!(keystore.add_key(&key_b).unwrap());
assert!(keystore.remove_key(&key_a).unwrap());
}
#[test]
fn test_keystore_state_after_new() {
crate::init().unwrap();
let ks = KeyStore::new().unwrap();
assert!(ks.is_open());
assert!(!ks.is_persistable());
}
#[test]
fn test_keystore_get_id_is_hex() {
crate::init().unwrap();
let ks = KeyStore::new().unwrap();
let id = ks.get_id();
assert!(!id.is_empty());
assert_eq!(0, id.len() % 2);
assert!(
id.chars()
.all(|c| c.is_ascii_hexdigit() && !c.is_uppercase())
);
}
#[test]
fn test_keystore_iter_wrapped_keys() {
crate::init().unwrap();
let mut ks = KeyStore::new().unwrap();
assert_eq!(0, ks.iter_wrapped_keys().count());
let key_a = Key::new_random().unwrap();
let key_b = Key::new_random().unwrap();
ks.add_key(&key_a).unwrap();
assert_eq!(1, ks.iter_wrapped_keys().count());
ks.add_key(&key_b).unwrap();
assert_eq!(2, ks.iter_wrapped_keys().count());
}
#[test]
fn test_get_master_key_requires_open() {
crate::init().unwrap();
let wrap_key = Key::new_random().unwrap();
let bytes = {
let mut ks = KeyStore::new().unwrap();
ks.add_key(&wrap_key).unwrap();
ks.to_vec().unwrap()
};
let ks = KeyStore::load_slice(&bytes).unwrap();
assert!(!ks.is_open());
assert!(ks.get_master_key().is_err());
}
#[test]
fn test_add_key_without_master_key() {
crate::init().unwrap();
let wrap_key = Key::new_random().unwrap();
let bytes = {
let mut ks = KeyStore::new().unwrap();
ks.add_key(&wrap_key).unwrap();
ks.to_vec().unwrap()
};
let mut ks = KeyStore::load_slice(&bytes).unwrap();
assert!(ks.add_key(&Key::new_random().unwrap()).is_err());
}
#[test]
fn test_open_already_open_is_noop() {
crate::init().unwrap();
let mut ks = KeyStore::new().unwrap();
assert!(ks.is_open());
let any_key = Key::new_random().unwrap();
ks.open(&any_key).unwrap();
assert!(ks.is_open());
}
#[test]
fn test_open_with_unknown_key() {
crate::init().unwrap();
let real = Key::new_random().unwrap();
let other = Key::new_random().unwrap();
let bytes = {
let mut ks = KeyStore::new().unwrap();
ks.add_key(&real).unwrap();
ks.to_vec().unwrap()
};
let mut ks = KeyStore::load_slice(&bytes).unwrap();
assert!(ks.open(&other).is_err());
assert!(!ks.is_open());
}
#[test]
fn test_disk_keystore_force_overwrite() {
crate::init().unwrap();
let file = temp::File::new_file().unwrap();
fs::remove_file(file.path()).unwrap();
let wrap_key = Key::new_random().unwrap();
{
let mut ks = DiskKeyStore::new(file.path(), false).unwrap();
ks.add_key(&wrap_key).unwrap();
}
let first_bytes = fs::read(file.path()).unwrap();
assert!(!first_bytes.is_empty());
let new_key = Key::new_random().unwrap();
{
let mut ks = DiskKeyStore::new(file.path(), true).unwrap();
assert_eq!(0, ks.iter_wrapped_keys().count());
ks.add_key(&new_key).unwrap();
}
let second_bytes = fs::read(file.path()).unwrap();
assert_ne!(first_bytes, second_bytes);
{
let mut ks = DiskKeyStore::new(file.path(), false).unwrap();
assert!(ks.open(&new_key).is_ok());
}
}
#[test]
fn test_keystore_load_slice_and_load_read() {
crate::init().unwrap();
let file = temp::File::new_file().unwrap();
fs::remove_file(file.path()).unwrap();
let wrap_key = Key::new_random().unwrap();
{
let mut ks = DiskKeyStore::new(file.path(), false).unwrap();
ks.add_key(&wrap_key).unwrap();
}
let bytes = fs::read(file.path()).unwrap();
let mut ks = KeyStore::load_slice(&bytes).unwrap();
ks.open(&wrap_key).unwrap();
let f = fs::File::open(file.path()).unwrap();
let mut ks2 = KeyStore::load_read(f).unwrap();
ks2.open(&wrap_key).unwrap();
}
#[test]
fn test_unpersistable() {
crate::init().unwrap();
let file = temp::File::new_file().unwrap();
fs::remove_file(file.path()).unwrap();
assert!(!file.path().exists());
{
let keystore = DiskKeyStore::new(file.path(), false).unwrap();
assert!(!keystore.is_persistable());
}
assert!(!file.path().exists());
}