spark_rust/signer/traits/secp256k1.rs
1//! # Secp256k1 Keypair Management for Spark Wallet
2//!
3//! This module defines the trait for managing secp256k1 keypairs in the Spark wallet.
4//! Secp256k1 is the elliptic curve used by Bitcoin, and this module provides methods
5//! for generating, storing, retrieving, and manipulating secp256k1 keypairs.
6//!
7//! The Spark wallet uses several types of keypairs:
8//! - Identity keypairs for wallet identification and authentication
9//! - Leaf keypairs for individual UTXOs (leaves) in the wallet
10//! - Ephemeral keypairs for one-time operations like key exchange
11//!
12//! Proper keypair management is critical to the security of the wallet, as these
13//! keys control access to funds and provide cryptographic identity.
14
15use bitcoin::{
16 secp256k1::{PublicKey, SecretKey},
17 Network,
18};
19
20use crate::error::SparkSdkError;
21
22/// Trait for managing secp256k1 keypairs in the Spark wallet.
23///
24/// This trait provides methods for generating, retrieving, and manipulating
25/// secp256k1 keypairs used throughout the Spark wallet. These keypairs are
26/// fundamental to various cryptographic operations including:
27///
28/// - Wallet identification (via the identity key)
29/// - Signing Bitcoin transactions
30/// - Secure key exchange during transfers
31/// - FROST threshold signing (in conjunction with the FROST traits)
32///
33/// The implementation must ensure that:
34/// - Private keys are securely stored and never exposed unnecessarily
35/// - Keys are properly derived according to Spark's derivation scheme
36/// - Operations that expose secret key material are used with caution
37pub trait SparkSignerSecp256k1 {
38 /// Returns the identity public key of the signer.
39 ///
40 /// The identity keypair in Spark is the first derived key from the master seed
41 /// (using child index 0). This key serves as the cryptographic identity of the
42 /// wallet and is used for authentication and secure communication between wallets.
43 ///
44 /// # Arguments
45 /// * `account_index` - The account index to use for the keypair.
46 /// * `network` - The network to use for the keypair (affects derivation path).
47 ///
48 /// # Returns
49 /// * `Ok(PublicKey)` - The identity public key of the signer
50 /// * `Err(SparkSdkError)` - If key retrieval fails
51 ///
52 /// # Example
53 /// ```
54 /// # use bitcoin::Network;
55 /// # use spark_rust::error::SparkSdkError;
56 /// # use spark_rust::signer::traits::secp256k1::SparkSignerSecp256k1;
57 /// # fn example(signer: &impl SparkSignerSecp256k1) -> Result<(), SparkSdkError> {
58 /// let identity_pubkey = signer.get_identity_public_key(0, Network::Bitcoin)?;
59 /// // Use identity_pubkey for wallet identification
60 /// # Ok(())
61 /// # }
62 /// ```
63 fn get_identity_public_key(
64 &self,
65 account_index: u32,
66 network: Network,
67 ) -> Result<PublicKey, SparkSdkError>;
68
69 /// Inserts a keypair into the signer by providing the private key.
70 ///
71 /// This method derives the public key from the provided private key and
72 /// persists both in the signer's state. It is primarily used during the
73 /// transfer flow, when the receiver needs to store a secret key received
74 /// from the sender.
75 ///
76 /// # Arguments
77 /// * `secret_key` - The secret key to insert
78 ///
79 /// # Returns
80 /// * `Ok(PublicKey)` - The public key derived from the inserted secret key
81 /// * `Err(SparkSdkError)` - If key insertion fails
82 ///
83 /// # Example
84 /// ```
85 /// # use bitcoin::secp256k1::SecretKey;
86 /// # use spark_rust::error::SparkSdkError;
87 /// # use spark_rust::signer::traits::secp256k1::SparkSignerSecp256k1;
88 ///
89 /// # fn example(signer: &impl SparkSignerSecp256k1, secret_key: SecretKey) -> Result<(), SparkSdkError> {
90 /// // During transfer flow, when receiver gets a secret key from sender
91 /// let public_key = signer.insert_secp256k1_keypair_from_secret_key(&secret_key)?;
92 ///
93 /// # Ok(())
94 /// # }
95 /// ```
96 fn insert_secp256k1_keypair_from_secret_key(
97 &self,
98 secret_key: &SecretKey,
99 ) -> Result<PublicKey, SparkSdkError>;
100
101 /// Generates a new ephemeral keypair for one-time use.
102 ///
103 /// Ephemeral keypairs are typically used for temporary operations like
104 /// secure communication sessions or one-time signatures. They are not
105 /// derived from the wallet's seed but are generated randomly.
106 ///
107 /// # Returns
108 /// * `Ok(PublicKey)` - The public key of the generated ephemeral keypair
109 /// * `Err(SparkSdkError)` - If keypair generation fails
110 ///
111 /// # Security Considerations
112 /// Ephemeral keys should be properly erased after use to prevent key
113 /// material from being recovered.
114 fn new_ephemeral_keypair(&self) -> Result<PublicKey, SparkSdkError>;
115
116 /// Subtracts one secret key from another to derive a new key.
117 ///
118 /// This method performs the operation: `target_key - source_key = result_key`
119 /// using only the public keys to identify the secret keys stored in the signer.
120 /// This is useful for key tweaking operations in the Spark protocol.
121 ///
122 /// # Arguments
123 /// * `target_pubkey` - Public key identifying the target secret key
124 /// * `source_pubkey` - Public key identifying the source secret key to subtract
125 /// * `save_new_key` - Whether to save the newly derived keypair in the signer
126 ///
127 /// # Returns
128 /// * `Ok(PublicKey)` - The public key corresponding to the resulting secret key
129 /// * `Err(SparkSdkError)` - If the operation fails
130 ///
131 /// # Security Considerations
132 /// The implementation must ensure that both source and target secret keys
133 /// are available in the signer's storage and are properly authorized for use.
134 fn subtract_secret_keys_given_pubkeys(
135 &self,
136 target_pubkey: &PublicKey,
137 source_pubkey: &PublicKey,
138 save_new_key: bool,
139 ) -> Result<PublicKey, SparkSdkError>;
140
141 /// Exposes the secret key corresponding to a given public key.
142 ///
143 /// # Security Warning
144 /// This is a **highly sensitive** operation from a security perspective because
145 /// it reveals confidential key material. Improper handling of exposed secret keys
146 /// can lead to fund loss. Use it **only** when absolutely necessary, and handle
147 /// the returned secret key with extreme caution.
148 ///
149 /// # Arguments
150 /// * `public_key` - The public key for which to retrieve the corresponding secret key
151 /// * `delete_after_exposing` - Whether to delete the key from storage after retrieval
152 ///
153 /// # Returns
154 /// * `Ok(SecretKey)` - The secret key corresponding to the provided public key
155 /// * `Err(SparkSdkError)` - If the secret key cannot be found or another error occurs
156 ///
157 /// # Example
158 /// ```
159 /// # use bitcoin::secp256k1::PublicKey;
160 /// # use spark_rust::error::SparkSdkError;
161 /// # use spark_rust::signer::traits::secp256k1::SparkSignerSecp256k1;
162 /// # fn example(signer: &impl SparkSignerSecp256k1, public_key: PublicKey) -> Result<(), SparkSdkError> {
163 /// // This should be used only in exceptional circumstances
164 /// let secret_key = signer.sensitive_expose_secret_key_from_pubkey(&public_key, false)?;
165 /// // Use secret_key immediately and then ensure it's securely erased
166 /// # Ok(())
167 /// # }
168 /// ```
169 fn sensitive_expose_secret_key_from_pubkey(
170 &self,
171 public_key: &PublicKey,
172 delete_after_exposing: bool,
173 ) -> Result<SecretKey, SparkSdkError>;
174}