Skip to content

Commit 0ae0fc1

Browse files
committed
Use KeyObfuscator in VssStore.
For client-side key obfuscation, improving privacy and security.
1 parent 9ba95be commit 0ae0fc1

File tree

2 files changed

+43
-17
lines changed

2 files changed

+43
-17
lines changed

src/builder.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,15 +477,19 @@ impl NodeBuilder {
477477

478478
let vss_seed_bytes: [u8; 32] = vss_xprv.private_key.secret_bytes();
479479

480-
let vss_store = Arc::new(VssStore::new(vss_url, store_id, vss_seed_bytes, header_provider));
480+
let vss_store =
481+
VssStore::new(vss_url, store_id, vss_seed_bytes, header_provider).map_err(|e| {
482+
log_error!(logger, "Failed to setup VssStore: {}", e);
483+
BuildError::KVStoreSetupFailed
484+
})?;
481485
build_with_store_internal(
482486
config,
483487
self.chain_data_source_config.as_ref(),
484488
self.gossip_source_config.as_ref(),
485489
self.liquidity_source_config.as_ref(),
486490
seed_bytes,
487491
logger,
488-
vss_store,
492+
Arc::new(vss_store),
489493
)
490494
}
491495

src/io/vss_store.rs

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in
66
// accordance with one or both of these licenses.
77

8+
use crate::io::utils::check_namespace_key_validity;
9+
use bitcoin::hashes::{sha256, Hash, HashEngine, Hmac, HmacEngine};
810
use lightning::io::{self, Error, ErrorKind};
11+
use lightning::util::persist::KVStore;
12+
use prost::Message;
13+
use rand::RngCore;
914
#[cfg(test)]
1015
use std::panic::RefUnwindSafe;
1116
use std::sync::Arc;
1217
use std::time::Duration;
13-
14-
use crate::io::utils::check_namespace_key_validity;
15-
use lightning::util::persist::KVStore;
16-
use prost::Message;
17-
use rand::RngCore;
1818
use tokio::runtime::Runtime;
1919
use vss_client::client::VssClient;
2020
use vss_client::error::VssError;
@@ -23,6 +23,7 @@ use vss_client::types::{
2323
DeleteObjectRequest, GetObjectRequest, KeyValue, ListKeyVersionsRequest, PutObjectRequest,
2424
Storable,
2525
};
26+
use vss_client::util::key_obfuscator::KeyObfuscator;
2627
use vss_client::util::retry::{
2728
ExponentialBackoffRetryPolicy, FilteredRetryPolicy, JitteredRetryPolicy,
2829
MaxAttemptsRetryPolicy, MaxTotalDelayRetryPolicy, RetryPolicy,
@@ -42,14 +43,18 @@ pub struct VssStore {
4243
store_id: String,
4344
runtime: Runtime,
4445
storable_builder: StorableBuilder<RandEntropySource>,
46+
key_obfuscator: KeyObfuscator,
4547
}
4648

4749
impl VssStore {
4850
pub(crate) fn new(
49-
base_url: String, store_id: String, data_encryption_key: [u8; 32],
51+
base_url: String, store_id: String, vss_seed: [u8; 32],
5052
header_provider: Arc<dyn VssHeaderProvider>,
51-
) -> Self {
52-
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
53+
) -> io::Result<Self> {
54+
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build()?;
55+
let (data_encryption_key, obfuscation_master_key) =
56+
derive_data_encryption_and_obfuscation_keys(&vss_seed);
57+
let key_obfuscator = KeyObfuscator::new(obfuscation_master_key);
5358
let storable_builder = StorableBuilder::new(data_encryption_key, RandEntropySource);
5459
let retry_policy = ExponentialBackoffRetryPolicy::new(Duration::from_millis(10))
5560
.with_max_attempts(10)
@@ -65,24 +70,28 @@ impl VssStore {
6570
}) as _);
6671

6772
let client = VssClient::new_with_headers(base_url, retry_policy, header_provider);
68-
Self { client, store_id, runtime, storable_builder }
73+
Ok(Self { client, store_id, runtime, storable_builder, key_obfuscator })
6974
}
7075

7176
fn build_key(
7277
&self, primary_namespace: &str, secondary_namespace: &str, key: &str,
7378
) -> io::Result<String> {
79+
let obfuscated_key = self.key_obfuscator.obfuscate(key);
7480
if primary_namespace.is_empty() {
75-
Ok(key.to_string())
81+
Ok(obfuscated_key)
7682
} else {
77-
Ok(format!("{}#{}#{}", primary_namespace, secondary_namespace, key))
83+
Ok(format!("{}#{}#{}", primary_namespace, secondary_namespace, obfuscated_key))
7884
}
7985
}
8086

8187
fn extract_key(&self, unified_key: &str) -> io::Result<String> {
8288
let mut parts = unified_key.splitn(3, '#');
8389
let (_primary_namespace, _secondary_namespace) = (parts.next(), parts.next());
8490
match parts.next() {
85-
Some(actual_key) => Ok(actual_key.to_string()),
91+
Some(obfuscated_key) => {
92+
let actual_key = self.key_obfuscator.deobfuscate(obfuscated_key)?;
93+
Ok(actual_key)
94+
},
8695
None => Err(Error::new(ErrorKind::InvalidData, "Invalid key format")),
8796
}
8897
}
@@ -224,6 +233,19 @@ impl KVStore for VssStore {
224233
}
225234
}
226235

236+
fn derive_data_encryption_and_obfuscation_keys(vss_seed: &[u8; 32]) -> ([u8; 32], [u8; 32]) {
237+
let hkdf = |initial_key_material: &[u8], salt: &[u8]| -> [u8; 32] {
238+
let mut engine = HmacEngine::<sha256::Hash>::new(salt);
239+
engine.input(initial_key_material);
240+
Hmac::from_engine(engine).to_byte_array()
241+
};
242+
243+
let prk = hkdf(vss_seed, b"pseudo_random_key");
244+
let k1 = hkdf(&prk, b"data_encryption_key");
245+
let k2 = hkdf(&prk, &[&k1[..], b"obfuscation_key"].concat());
246+
(k1, k2)
247+
}
248+
227249
/// A source for generating entropy/randomness using [`rand`].
228250
pub(crate) struct RandEntropySource;
229251

@@ -251,11 +273,11 @@ mod tests {
251273
let vss_base_url = std::env::var("TEST_VSS_BASE_URL").unwrap();
252274
let mut rng = thread_rng();
253275
let rand_store_id: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
254-
let mut data_encryption_key = [0u8; 32];
255-
rng.fill_bytes(&mut data_encryption_key);
276+
let mut vss_seed = [0u8; 32];
277+
rng.fill_bytes(&mut vss_seed);
256278
let header_provider = Arc::new(FixedHeaders::new(HashMap::new()));
257279
let vss_store =
258-
VssStore::new(vss_base_url, rand_store_id, data_encryption_key, header_provider);
280+
VssStore::new(vss_base_url, rand_store_id, vss_seed, header_provider).unwrap();
259281

260282
do_read_write_remove_list_persist(&vss_store);
261283
}

0 commit comments

Comments
 (0)