|
6 | 6 | // accordance with one or both of these licenses. |
7 | 7 |
|
8 | 8 | use crate::io::utils::check_namespace_key_validity; |
9 | | -use bitcoin::bip32::{ChildNumber, Xpriv}; |
10 | | -use bitcoin::secp256k1::Secp256k1; |
11 | | -use bitcoin::Network; |
| 9 | +use bitcoin::hashes::{sha256, Hash, HashEngine, Hmac, HmacEngine}; |
12 | 10 | use lightning::io::{self, Error, ErrorKind}; |
13 | 11 | use lightning::util::persist::KVStore; |
14 | 12 | use prost::Message; |
@@ -48,27 +46,14 @@ pub struct VssStore { |
48 | 46 | key_obfuscator: KeyObfuscator, |
49 | 47 | } |
50 | 48 |
|
51 | | -// Used to derive `data_encryption_key` from `vss_seed`, which is then used by the `StorableBuilder`. |
52 | | -const DATA_ENCRYPTION_KEY_DERIVATION_INDEX: u32 = 1; |
53 | | - |
54 | | -// Used to derive `obfuscation_master_key` from `vss_seed`, which is then used by the `KeyObfuscator`. |
55 | | -const OBFUSCATION_KEY_DERIVATION_INDEX: u32 = 2; |
56 | | - |
57 | 49 | impl VssStore { |
58 | 50 | pub(crate) fn new( |
59 | 51 | base_url: String, store_id: String, vss_seed: [u8; 32], |
60 | 52 | header_provider: Arc<dyn VssHeaderProvider>, |
61 | 53 | ) -> io::Result<Self> { |
62 | 54 | let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build()?; |
63 | | - // The selected bitcoin network doesn't matter here. |
64 | | - let vss_master_xprv = Xpriv::new_master(Network::Bitcoin, &vss_seed).map_err(|e| { |
65 | | - let msg = format!("Failed to create Vss master key, error: {}", e); |
66 | | - io::Error::new(ErrorKind::Other, msg) |
67 | | - })?; |
68 | | - let data_encryption_key = |
69 | | - derive_hardened_key(&vss_master_xprv, DATA_ENCRYPTION_KEY_DERIVATION_INDEX)?; |
70 | | - let obfuscation_master_key = |
71 | | - derive_hardened_key(&vss_master_xprv, OBFUSCATION_KEY_DERIVATION_INDEX)?; |
| 55 | + let (data_encryption_key, obfuscation_master_key) = |
| 56 | + derive_data_encryption_and_obfuscation_keys(&vss_seed); |
72 | 57 | let key_obfuscator = KeyObfuscator::new(obfuscation_master_key); |
73 | 58 | let storable_builder = StorableBuilder::new(data_encryption_key, RandEntropySource); |
74 | 59 | let retry_policy = ExponentialBackoffRetryPolicy::new(Duration::from_millis(10)) |
@@ -248,18 +233,17 @@ impl KVStore for VssStore { |
248 | 233 | } |
249 | 234 | } |
250 | 235 |
|
251 | | -fn derive_hardened_key(vss_seed: &Xpriv, index: u32) -> io::Result<[u8; 32]> { |
252 | | - let derived_key_xprv = vss_seed |
253 | | - .derive_priv(&Secp256k1::new(), &[ChildNumber::Hardened { index }]) |
254 | | - .map_err(|e| { |
255 | | - let msg = format!( |
256 | | - "Failed to derive an extended private key from VSS seed with index: {}, error: {}", |
257 | | - index, e |
258 | | - ); |
259 | | - Error::new(ErrorKind::Other, msg) |
260 | | - })?; |
261 | | - let derived_key = derived_key_xprv.private_key.secret_bytes(); |
262 | | - Ok(derived_key) |
| 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, "pseudo_random_key".as_bytes()); |
| 244 | + let k1 = hkdf(&prk, "data_encryption_key".as_bytes()); |
| 245 | + let k2 = hkdf(&prk, &[&k1[..], "obfuscation_key".as_bytes()].concat()); |
| 246 | + (k1, k2) |
263 | 247 | } |
264 | 248 |
|
265 | 249 | /// A source for generating entropy/randomness using [`rand`]. |
|
0 commit comments