pub mod shared;
pub mod v020;
pub mod v030;
pub mod v040;
pub mod v050;
pub mod v060;
pub mod v070;
pub mod v080;
pub mod v090;
pub use v090::{
decode_hashmap, default_metadata, default_secrets, key, new_tag, new_tags,
secrets_from_user_pass, types, DecryptedRecord, EncryptedRecord, HashMap, History, Kind,
Metadata, Secrets, Status, Tag, ANY_CATEGORY, DEFAULT_CATEGORY, VERSION,
};
pub fn version() -> versions::SemVer {
versions::SemVer::new(VERSION).expect("VERSION constant must be valid semver format")
}
pub fn decrypt_versioned(
encrypted: &EncryptedRecord,
store_pwd: String,
salt: String,
db_version: versions::SemVer,
) -> anyhow::Result<DecryptedRecord> {
use anyhow::anyhow;
use rucksack_lib::util;
let trimmed_version = shared::trim_version(db_version.clone());
log::debug!(db_version = db_version.to_string().as_str(), trimmed_version = trimmed_version.to_string().as_str(), operation = "decrypt_versioned"; "Decrypting versioned record");
let v070 = shared::version("0.7.0").map_err(|e| anyhow!("{}", e))?;
let v090 = shared::version("0.9.0").map_err(|e| anyhow!("{}", e))?;
if trimmed_version < v070 {
log::debug!(version_path = "v0.6.0", operation = "decrypt"; "Using v0.6.0 decrypt path for version < 0.7.0");
let old_record = v060::EncryptedRecord {
key: encrypted.key(),
value: encrypted.value(),
metadata: v060::Metadata {
kind: match encrypted.metadata().kind {
Kind::Password => v060::Kind::Password,
Kind::Account => v060::Kind::Account,
_ => v060::Kind::Password, },
url: encrypted.metadata().url.clone(),
created: encrypted.metadata().created.clone(),
imported: encrypted.metadata().imported.clone(),
updated: encrypted.metadata().updated.clone(),
password_changed: encrypted.metadata().password_changed.clone(),
last_used: encrypted.metadata().last_used.clone(),
access_count: encrypted.metadata().access_count,
},
};
log::debug!(version = "v0.6.0", operation = "decrypt"; "Calling v060::decrypt()");
let decrypted_v060 = old_record.decrypt(store_pwd, salt)?;
log::debug!(version = "v0.6.0", operation = "migrate"; "v060::decrypt() succeeded, migrating to current version");
let decrypted_v070 = v070::migrate_decrypted_record_from_v060(decrypted_v060);
let decrypted_v080 = v080::migrate_decrypted_record_from_v070(decrypted_v070);
Ok(v090::migrate_decrypted_record_from_v080(decrypted_v080))
} else if trimmed_version < v090 {
log::debug!(version_path = "v0.7.0/v0.8.0", operation = "decrypt"; "Using v0.7.0/v0.8.0 decrypt path for version < 0.9.0");
let decrypted_bytes = crate::crypto::decrypt(encrypted.value(), store_pwd, salt)?;
let (decoded_secrets, _len): (v070::Secrets, usize) =
bincode::decode_from_slice(&decrypted_bytes[..], util::bincode_cfg())
.map_err(|e| anyhow!("failed to decode v0.7.0/v0.8.0 secrets: {}", e))?;
let decrypted_v070 = v070::DecryptedRecord {
secrets: decoded_secrets,
metadata: encrypted.metadata(),
};
let decrypted_v080 = v080::migrate_decrypted_record_from_v070(decrypted_v070);
Ok(v090::migrate_decrypted_record_from_v080(decrypted_v080))
} else {
log::debug!(version = "v0.9.0+", operation = "decrypt"; "Using current decrypt path for version >= 0.9.0");
encrypted.decrypt(store_pwd, salt)
}
}