breez_sdk_spark/signer/
breez.rs

1use crate::{Seed, error::SdkError, models::Config};
2use bitcoin::bip32::DerivationPath;
3use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine, sha256};
4use bitcoin::secp256k1::{self, Message, Secp256k1, rand::thread_rng};
5use spark_wallet::{DefaultSigner, KeySet, KeySetType, Signer};
6
7use super::BreezSigner;
8
9pub struct BreezSignerImpl {
10    key_set: KeySet,
11    secp: Secp256k1<secp256k1::All>,
12    spark_signer: DefaultSigner,
13}
14
15impl BreezSignerImpl {
16    pub fn new(
17        config: &Config,
18        seed: &Seed,
19        key_set_type: KeySetType,
20        use_address_index: bool,
21        account_number: Option<u32>,
22    ) -> Result<Self, SdkError> {
23        let seed_bytes = seed.to_bytes()?;
24        let key_set = KeySet::new(
25            &seed_bytes,
26            config.network.into(),
27            key_set_type,
28            use_address_index,
29            account_number,
30        )
31        .map_err(|e| SdkError::Generic(e.to_string()))?;
32
33        Ok(Self {
34            key_set: key_set.clone(),
35            secp: Secp256k1::new(),
36            spark_signer: DefaultSigner::from_key_set(key_set),
37        })
38    }
39}
40
41#[macros::async_trait]
42impl BreezSigner for BreezSignerImpl {
43    fn identity_public_key(&self) -> Result<secp256k1::PublicKey, SdkError> {
44        Ok(self.key_set.identity_key_pair.public_key())
45    }
46
47    async fn derive_public_key(
48        &self,
49        path: &DerivationPath,
50    ) -> Result<secp256k1::PublicKey, SdkError> {
51        let derived = self
52            .key_set
53            .identity_master_key
54            .derive_priv(&self.secp, path)
55            .map_err(|e| SdkError::Generic(e.to_string()))?;
56        Ok(derived.private_key.public_key(&self.secp))
57    }
58
59    async fn sign_ecdsa(
60        &self,
61        message: Message,
62        path: &DerivationPath,
63    ) -> Result<secp256k1::ecdsa::Signature, SdkError> {
64        let derived = self
65            .key_set
66            .identity_master_key
67            .derive_priv(&self.secp, path)
68            .map_err(|e| SdkError::Generic(e.to_string()))?;
69        Ok(self.secp.sign_ecdsa_low_r(&message, &derived.private_key))
70    }
71
72    async fn sign_ecdsa_recoverable(
73        &self,
74        message: Message,
75        path: &DerivationPath,
76    ) -> Result<secp256k1::ecdsa::RecoverableSignature, SdkError> {
77        let derived = self
78            .key_set
79            .identity_master_key
80            .derive_priv(&self.secp, path)
81            .map_err(|e| SdkError::Generic(e.to_string()))?;
82        Ok(self
83            .secp
84            .sign_ecdsa_recoverable(&message, &derived.private_key))
85    }
86
87    async fn encrypt_ecies(
88        &self,
89        message: &[u8],
90        path: &DerivationPath,
91    ) -> Result<Vec<u8>, SdkError> {
92        let derived = self
93            .key_set
94            .identity_master_key
95            .derive_priv(&self.secp, path)
96            .map_err(|e| SdkError::Generic(e.to_string()))?;
97        let rc_pub = derived.private_key.public_key(&self.secp).serialize();
98        ecies::encrypt(&rc_pub, message)
99            .map_err(|err| SdkError::Generic(format!("Could not encrypt data: {err}")))
100    }
101
102    async fn decrypt_ecies(
103        &self,
104        message: &[u8],
105        path: &DerivationPath,
106    ) -> Result<Vec<u8>, SdkError> {
107        let derived = self
108            .key_set
109            .identity_master_key
110            .derive_priv(&self.secp, path)
111            .map_err(|e| SdkError::Generic(e.to_string()))?;
112        let rc_prv = derived.private_key.secret_bytes();
113        ecies::decrypt(&rc_prv, message)
114            .map_err(|err| SdkError::Generic(format!("Could not decrypt data: {err}")))
115    }
116
117    async fn sign_hash_schnorr(
118        &self,
119        hash: &[u8],
120        path: &DerivationPath,
121    ) -> Result<secp256k1::schnorr::Signature, SdkError> {
122        let derived = self
123            .key_set
124            .identity_master_key
125            .derive_priv(&self.secp, path)
126            .map_err(|e| SdkError::Generic(e.to_string()))?;
127        let message =
128            Message::from_digest_slice(hash).map_err(|e| SdkError::Generic(e.to_string()))?;
129        let keypair = derived.private_key.keypair(&self.secp);
130
131        // Always use auxiliary randomness for enhanced security
132        let mut rng = thread_rng();
133        Ok(self
134            .secp
135            .sign_schnorr_with_rng(&message, &keypair, &mut rng))
136    }
137
138    async fn generate_random_signing_commitment(
139        &self,
140    ) -> Result<spark_wallet::FrostSigningCommitmentsWithNonces, SdkError> {
141        self.spark_signer
142            .generate_random_signing_commitment()
143            .await
144            .map_err(|e| SdkError::Generic(e.to_string()))
145    }
146
147    async fn get_public_key_for_node(
148        &self,
149        id: &spark_wallet::TreeNodeId,
150    ) -> Result<secp256k1::PublicKey, SdkError> {
151        self.spark_signer
152            .get_public_key_for_node(id)
153            .await
154            .map_err(|e| SdkError::Generic(e.to_string()))
155    }
156
157    async fn generate_random_secret(&self) -> Result<spark_wallet::EncryptedSecret, SdkError> {
158        self.spark_signer
159            .generate_random_secret()
160            .await
161            .map_err(|e| SdkError::Generic(e.to_string()))
162    }
163
164    async fn static_deposit_secret_encrypted(
165        &self,
166        index: u32,
167    ) -> Result<spark_wallet::SecretSource, SdkError> {
168        self.spark_signer
169            .static_deposit_secret_encrypted(index)
170            .await
171            .map_err(|e| SdkError::Generic(e.to_string()))
172    }
173
174    async fn static_deposit_secret(&self, index: u32) -> Result<secp256k1::SecretKey, SdkError> {
175        self.spark_signer
176            .static_deposit_secret(index)
177            .await
178            .map_err(|e| SdkError::Generic(e.to_string()))
179    }
180
181    async fn static_deposit_signing_key(
182        &self,
183        index: u32,
184    ) -> Result<secp256k1::PublicKey, SdkError> {
185        self.spark_signer
186            .static_deposit_signing_key(index)
187            .await
188            .map_err(|e| SdkError::Generic(e.to_string()))
189    }
190
191    async fn subtract_secrets(
192        &self,
193        signing_key: &spark_wallet::SecretSource,
194        new_signing_key: &spark_wallet::SecretSource,
195    ) -> Result<spark_wallet::SecretSource, SdkError> {
196        self.spark_signer
197            .subtract_secrets(signing_key, new_signing_key)
198            .await
199            .map_err(|e| SdkError::Generic(e.to_string()))
200    }
201
202    async fn split_secret_with_proofs(
203        &self,
204        secret: &spark_wallet::SecretToSplit,
205        threshold: u32,
206        num_shares: usize,
207    ) -> Result<Vec<spark_wallet::VerifiableSecretShare>, SdkError> {
208        self.spark_signer
209            .split_secret_with_proofs(secret, threshold, num_shares)
210            .await
211            .map_err(|e| SdkError::Generic(e.to_string()))
212    }
213
214    async fn encrypt_secret_for_receiver(
215        &self,
216        private_key: &spark_wallet::EncryptedSecret,
217        receiver_public_key: &secp256k1::PublicKey,
218    ) -> Result<Vec<u8>, SdkError> {
219        self.spark_signer
220            .encrypt_secret_for_receiver(private_key, receiver_public_key)
221            .await
222            .map_err(|e| SdkError::Generic(e.to_string()))
223    }
224
225    async fn public_key_from_secret(
226        &self,
227        private_key: &spark_wallet::SecretSource,
228    ) -> Result<secp256k1::PublicKey, SdkError> {
229        self.spark_signer
230            .public_key_from_secret(private_key)
231            .await
232            .map_err(|e| SdkError::Generic(e.to_string()))
233    }
234
235    async fn sign_frost<'a>(
236        &self,
237        request: spark_wallet::SignFrostRequest<'a>,
238    ) -> Result<frost_secp256k1_tr::round2::SignatureShare, SdkError> {
239        self.spark_signer
240            .sign_frost(request)
241            .await
242            .map_err(|e| SdkError::Generic(e.to_string()))
243    }
244
245    async fn aggregate_frost<'a>(
246        &self,
247        request: spark_wallet::AggregateFrostRequest<'a>,
248    ) -> Result<frost_secp256k1_tr::Signature, SdkError> {
249        self.spark_signer
250            .aggregate_frost(request)
251            .await
252            .map_err(|e| SdkError::Generic(e.to_string()))
253    }
254
255    async fn hmac_sha256(
256        &self,
257        key_path: &DerivationPath,
258        input: &[u8],
259    ) -> Result<Hmac<sha256::Hash>, SdkError> {
260        let derived = self
261            .key_set
262            .identity_master_key
263            .derive_priv(&self.secp, key_path)
264            .map_err(|e| SdkError::Generic(e.to_string()))?;
265
266        let mut engine = HmacEngine::<sha256::Hash>::new(&derived.private_key.secret_bytes());
267        engine.input(input);
268        Ok(Hmac::<sha256::Hash>::from_engine(engine))
269    }
270}