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}