use bitwarden_crypto::{
generate_versioned_sealable, key_slot_ids,
safe::{DataEnvelope, DataEnvelopeNamespace, SealableData, SealableVersionedData},
};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct MyItemV1 {
a: u32,
b: String,
}
impl SealableData for MyItemV1 {}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct MyItemV2 {
a: u32,
b: bool,
c: bool,
}
impl SealableData for MyItemV2 {}
generate_versioned_sealable!(
MyItem,
DataEnvelopeNamespace::VaultItem,
[
MyItemV1 => "1",
MyItemV2 => "2",
]
);
fn main() {
let store: bitwarden_crypto::KeyStore<ExampleIds> =
bitwarden_crypto::KeyStore::<ExampleIds>::default();
let mut ctx: bitwarden_crypto::KeyStoreContext<'_, ExampleIds> = store.context_mut();
let mut disk = MockDisk::new();
let my_item: MyItem = MyItemV1 {
a: 42,
b: "Hello, World!".to_string(),
}
.into();
let (sealed_item, cek) = DataEnvelope::seal(my_item, &mut ctx).expect("Sealing should work");
disk.save("sealed_item", (&sealed_item).into());
let sealed_item = disk
.load("sealed_item")
.expect("Failed to load sealed item")
.clone();
let sealed_item = DataEnvelope::from(sealed_item);
let my_item: MyItem = sealed_item
.unseal(cek, &mut ctx)
.expect("Unsealing should work");
assert!(matches!(my_item, MyItem::MyItemV1(item) if item.a == 42 && item.b == "Hello, World!"));
}
pub(crate) struct MockDisk {
map: std::collections::HashMap<String, Vec<u8>>,
}
impl MockDisk {
pub(crate) fn new() -> Self {
MockDisk {
map: std::collections::HashMap::new(),
}
}
pub(crate) fn save(&mut self, key: &str, value: Vec<u8>) {
self.map.insert(key.to_string(), value);
}
pub(crate) fn load(&self, key: &str) -> Option<&Vec<u8>> {
self.map.get(key)
}
}
key_slot_ids! {
#[symmetric]
pub enum ExampleSymmetricKey {
#[local]
ItemKey(LocalId)
}
#[private]
pub enum ExamplePrivateKey {
Key(u8),
#[local]
Local(LocalId),
}
#[signing]
pub enum ExampleSigningKey {
Key(u8),
#[local]
Local(LocalId),
}
pub ExampleIds => ExampleSymmetricKey, ExamplePrivateKey, ExampleSigningKey;
}