Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ serde = { version = "1.0.210", default-features = false, features = ["std", "der
serde_json = { version = "1.0.128", default-features = false, features = ["std"] }
log = { version = "0.4.22", default-features = false, features = ["std"]}

vss-client = "0.3"
#vss-client = "0.3"
vss-client = { git = "https://github.com/tnull/vss-rust-client", rev = "03ca9d99f70387aabec225020e46434cda8d18ff" }
prost = { version = "0.11.6", default-features = false}

[target.'cfg(windows)'.dependencies]
Expand Down
37 changes: 27 additions & 10 deletions src/io/vss_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ type CustomRetryPolicy = FilteredRetryPolicy<
Box<dyn Fn(&VssError) -> bool + 'static + Send + Sync>,
>;

const KEY_LENGTH: usize = 32;

/// A [`KVStore`] implementation that writes to and reads from a [VSS](https://github.com/lightningdevkit/vss-server/blob/main/README.md) backend.
pub struct VssStore {
client: VssClient<CustomRetryPolicy>,
store_id: String,
runtime: Arc<Runtime>,
storable_builder: StorableBuilder<RandEntropySource>,
data_encryption_key: [u8; KEY_LENGTH],
key_obfuscator: KeyObfuscator,
}

Expand All @@ -55,7 +57,6 @@ impl VssStore {
let (data_encryption_key, obfuscation_master_key) =
derive_data_encryption_and_obfuscation_keys(&vss_seed);
let key_obfuscator = KeyObfuscator::new(obfuscation_master_key);
let storable_builder = StorableBuilder::new(data_encryption_key, RandEntropySource);
let retry_policy = ExponentialBackoffRetryPolicy::new(Duration::from_millis(10))
.with_max_attempts(10)
.with_max_total_delay(Duration::from_secs(15))
Expand All @@ -70,7 +71,7 @@ impl VssStore {
}) as _);

let client = VssClient::new_with_headers(base_url, retry_policy, header_provider);
Self { client, store_id, runtime, storable_builder, key_obfuscator }
Self { client, store_id, runtime, data_encryption_key, key_obfuscator }
}

fn build_key(
Expand Down Expand Up @@ -132,10 +133,9 @@ impl KVStore for VssStore {
&self, primary_namespace: &str, secondary_namespace: &str, key: &str,
) -> io::Result<Vec<u8>> {
check_namespace_key_validity(primary_namespace, secondary_namespace, Some(key), "read")?;
let request = GetObjectRequest {
store_id: self.store_id.clone(),
key: self.build_key(primary_namespace, secondary_namespace, key)?,
};

let store_key = self.build_key(primary_namespace, secondary_namespace, key)?;
let request = GetObjectRequest { store_id: self.store_id.clone(), key: store_key.clone() };
let resp = self.runtime.block_on(self.client.get_object(&request)).map_err(|e| {
let msg = format!(
"Failed to read from key {}/{}/{}: {}",
Expand All @@ -156,20 +156,31 @@ impl KVStore for VssStore {
Error::new(ErrorKind::Other, msg)
})?;

Ok(self.storable_builder.deconstruct(storable)?.0)
let storable_builder = StorableBuilder::new(RandEntropySource);
let decrypted = storable_builder
.deconstruct(storable, &self.data_encryption_key, store_key.as_bytes())?
.0;
Ok(decrypted)
}

fn write(
&self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: &[u8],
) -> io::Result<()> {
check_namespace_key_validity(primary_namespace, secondary_namespace, Some(key), "write")?;
let store_key = self.build_key(primary_namespace, secondary_namespace, key)?;
let version = -1;
let storable = self.storable_builder.build(buf.to_vec(), version);
let storable_builder = StorableBuilder::new(RandEntropySource);
let storable = storable_builder.build(
buf.to_vec(),
version,
&&self.data_encryption_key,
store_key.as_bytes(),
);
let request = PutObjectRequest {
store_id: self.store_id.clone(),
global_version: None,
transaction_items: vec![KeyValue {
key: self.build_key(primary_namespace, secondary_namespace, key)?,
key: store_key,
version,
value: storable.encode_to_vec(),
}],
Expand Down Expand Up @@ -228,6 +239,12 @@ impl KVStore for VssStore {
}
}

impl Drop for VssStore {
fn drop(&mut self) {
self.data_encryption_key.copy_from_slice(&[0u8; KEY_LENGTH]);
}
}

fn derive_data_encryption_and_obfuscation_keys(vss_seed: &[u8; 32]) -> ([u8; 32], [u8; 32]) {
let hkdf = |initial_key_material: &[u8], salt: &[u8]| -> [u8; 32] {
let mut engine = HmacEngine::<sha256::Hash>::new(salt);
Expand Down
Loading