fedimint_client/
secret.rs1use std::fmt::Debug;
2use std::io::{Read, Write};
3
4use fedimint_core::config::FederationId;
5use fedimint_core::core::ModuleInstanceId;
6use fedimint_core::encoding::{Decodable, DecodeError, Encodable};
7use fedimint_core::module::registry::ModuleRegistry;
8use fedimint_derive_secret::{ChildId, DerivableSecret};
9use rand::{CryptoRng, Rng, RngCore};
10
11const TYPE_PRE_ROOT_SECRET_HASH: ChildId = ChildId(0);
13
14const TYPE_MODULE: ChildId = ChildId(0);
16const TYPE_BACKUP: ChildId = ChildId(1);
17
18pub trait DeriveableSecretClientExt {
19 fn derive_module_secret(&self, module_instance_id: ModuleInstanceId) -> DerivableSecret;
20 fn derive_backup_secret(&self) -> DerivableSecret;
21 fn derive_pre_root_secret_hash(&self) -> [u8; 8];
22}
23
24impl DeriveableSecretClientExt for DerivableSecret {
25 fn derive_module_secret(&self, module_instance_id: ModuleInstanceId) -> DerivableSecret {
26 assert_eq!(self.level(), 0);
27 self.child_key(TYPE_MODULE)
28 .child_key(ChildId(u64::from(module_instance_id)))
29 }
30
31 fn derive_backup_secret(&self) -> DerivableSecret {
32 assert_eq!(self.level(), 0);
33 self.child_key(TYPE_BACKUP)
34 }
35
36 fn derive_pre_root_secret_hash(&self) -> [u8; 8] {
37 self.child_key(TYPE_PRE_ROOT_SECRET_HASH).to_random_bytes()
42 }
43}
44
45pub trait RootSecretStrategy: Debug {
55 type Encoding: Clone;
57
58 fn to_root_secret(secret: &Self::Encoding) -> DerivableSecret;
60
61 fn consensus_encode(
63 secret: &Self::Encoding,
64 writer: &mut impl std::io::Write,
65 ) -> std::io::Result<usize>;
66
67 fn consensus_decode(reader: &mut impl std::io::Read) -> Result<Self::Encoding, DecodeError>;
69
70 fn random<R>(rng: &mut R) -> Self::Encoding
72 where
73 R: rand::RngCore + rand::CryptoRng;
74}
75
76#[derive(Debug)]
78pub struct PlainRootSecretStrategy;
79
80impl RootSecretStrategy for PlainRootSecretStrategy {
81 type Encoding = [u8; 64];
82
83 fn to_root_secret(secret: &Self::Encoding) -> DerivableSecret {
84 const FEDIMINT_CLIENT_NONCE: &[u8] = b"Fedimint Client Salt";
85 DerivableSecret::new_root(secret.as_ref(), FEDIMINT_CLIENT_NONCE)
86 }
87
88 fn consensus_encode(
89 secret: &Self::Encoding,
90 writer: &mut impl Write,
91 ) -> std::io::Result<usize> {
92 secret.consensus_encode(writer)
93 }
94
95 fn consensus_decode(reader: &mut impl Read) -> Result<Self::Encoding, DecodeError> {
96 Self::Encoding::consensus_decode(reader, &ModuleRegistry::default())
97 }
98
99 fn random<R>(rng: &mut R) -> Self::Encoding
100 where
101 R: RngCore + CryptoRng,
102 {
103 let mut secret = [0u8; 64];
104 rng.fill(&mut secret);
105 secret
106 }
107}
108
109pub fn get_default_client_secret(
118 global_root_secret: &DerivableSecret,
119 federation_id: &FederationId,
120) -> DerivableSecret {
121 let multi_federation_root_secret = global_root_secret.child_key(ChildId(0));
122 let federation_root_secret = multi_federation_root_secret.federation_key(federation_id);
123 let federation_wallet_root_secret = federation_root_secret.child_key(ChildId(0)); federation_wallet_root_secret.child_key(ChildId(0)) }