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_partial(
69 reader: &mut impl std::io::Read,
70 ) -> Result<Self::Encoding, DecodeError>;
71
72 fn random<R>(rng: &mut R) -> Self::Encoding
74 where
75 R: rand::RngCore + rand::CryptoRng;
76}
77
78#[derive(Debug)]
80pub struct PlainRootSecretStrategy;
81
82impl RootSecretStrategy for PlainRootSecretStrategy {
83 type Encoding = [u8; 64];
84
85 fn to_root_secret(secret: &Self::Encoding) -> DerivableSecret {
86 const FEDIMINT_CLIENT_NONCE: &[u8] = b"Fedimint Client Salt";
87 DerivableSecret::new_root(secret.as_ref(), FEDIMINT_CLIENT_NONCE)
88 }
89
90 fn consensus_encode(
91 secret: &Self::Encoding,
92 writer: &mut impl Write,
93 ) -> std::io::Result<usize> {
94 secret.consensus_encode(writer)
95 }
96
97 fn consensus_decode_partial(reader: &mut impl Read) -> Result<Self::Encoding, DecodeError> {
98 Self::Encoding::consensus_decode_partial(reader, &ModuleRegistry::default())
99 }
100
101 fn random<R>(rng: &mut R) -> Self::Encoding
102 where
103 R: RngCore + CryptoRng,
104 {
105 let mut secret = [0u8; 64];
106 rng.fill(&mut secret);
107 secret
108 }
109}
110
111pub fn get_default_client_secret(
120 global_root_secret: &DerivableSecret,
121 federation_id: &FederationId,
122) -> DerivableSecret {
123 let multi_federation_root_secret = global_root_secret.child_key(ChildId(0));
124 let federation_root_secret = multi_federation_root_secret.federation_key(federation_id);
125 let federation_wallet_root_secret = federation_root_secret.child_key(ChildId(0)); federation_wallet_root_secret.child_key(ChildId(0)) }