spark_rust/signer/traits/
ecdsa.rs

1//! # ECDSA signing operations for Spark wallet
2//!
3//! This module defines the ECDSA signing capabilities required for the Spark wallet.
4//! ECDSA signatures are used for wallet authentication, identity verification,
5//! and other operations that don't require threshold signing.
6//!
7//! The trait provides methods for:
8//! - Signing messages with the wallet's identity key
9//! - Signing messages with any key in the wallet given its public key
10//!
11//! These signing operations support both direct signing and SHA256 hashing
12//! of the message before signing.
13
14use bitcoin::{
15    secp256k1::{ecdsa::Signature, PublicKey},
16    Network,
17};
18
19use crate::error::SparkSdkError;
20
21/// Trait for ECDSA signing operations in the Spark wallet.
22///
23/// This trait provides methods for creating ECDSA signatures using
24/// different keys in the wallet. ECDSA signatures are used for wallet
25/// authentication, identity verification, and operations that don't
26/// require threshold signing with Spark Operators.
27///
28/// The trait supports signing with:
29/// - The wallet's identity key (derived at fixed path m/8797555'/account'/0')
30/// - Any key in the wallet identified by its public key
31///
32/// All signing methods can optionally apply SHA256 hashing to the message
33/// before signing, which is useful for ensuring consistent message format.
34pub trait SparkSignerEcdsa {
35    /// Signs a message using the wallet's identity private key.
36    ///
37    /// The identity key is the first derived key from the master seed
38    /// (using derivation path m/8797555'/account'/0'). This key is used
39    /// for wallet authentication and identity verification with Spark Operators.
40    ///
41    /// # Arguments
42    /// * `message` - The message to sign. Can be any type that implements `AsRef<[u8]>`,
43    ///               such as `Vec<u8>`, `&[u8]`, `String`, etc.
44    /// * `apply_hashing` - If true, the message will be hashed using SHA256 before signing.
45    ///                     If false, the message will be signed directly, which requires
46    ///                     that the message already be 32 bytes.
47    /// * `network` - The Bitcoin network to use, which affects the derivation path.
48    ///
49    /// # Returns
50    /// * `Ok(Signature)` - The DER-serialized (non-compact) ECDSA signature
51    /// * `Err(SparkSdkError)` - If signing fails for any reason
52    ///
53    /// # Example
54    /// ```no_run
55    /// # use spark_rust::signer::traits::ecdsa::SparkSignerEcdsa;
56    /// # use spark_rust::signer::default_signer::DefaultSigner;
57    /// # use bitcoin::Network;
58    /// # async fn example(signer: DefaultSigner) -> Result<(), Box<dyn std::error::Error>> {
59    /// // Sign a message with the identity key
60    /// let message = "Authenticate wallet";
61    /// let signature = signer.sign_message_ecdsa_with_identity_key(
62    ///     message,
63    ///     true, // Apply SHA256 hashing
64    ///     Network::Bitcoin
65    /// )?;
66    /// # Ok(())
67    /// # }
68    /// ```
69    fn sign_message_ecdsa_with_identity_key<T: AsRef<[u8]>>(
70        &self,
71        message: T,
72        apply_hashing: bool,
73        network: Network,
74    ) -> Result<Signature, SparkSdkError>;
75
76    /// Signs a message using a specified key in the wallet.
77    ///
78    /// This method allows signing with any key in the wallet for which
79    /// you have the public key. The signer implementation will locate
80    /// the corresponding private key and use it for signing.
81    ///
82    /// # Arguments
83    /// * `message` - The message to sign. Can be any type that implements `AsRef<[u8]>`,
84    ///               such as `Vec<u8>`, `&[u8]`, `String`, etc.
85    /// * `public_key_for_signing_key` - The public key corresponding to the private key
86    ///                                  that should be used for signing. The signer must
87    ///                                  have access to this private key.
88    /// * `apply_hashing` - If true, the message will be hashed using SHA256 before signing.
89    ///                     If false, the message will be signed directly, which requires
90    ///                     that the message already be 32 bytes.
91    ///
92    /// # Returns
93    /// * `Ok(Signature)` - The DER-serialized (non-compact) ECDSA signature
94    /// * `Err(SparkSdkError)` - If signing fails, typically because the private key
95    ///                         corresponding to the public key cannot be found
96    ///
97    /// # Example
98    /// ```no_run
99    /// # use spark_rust::signer::traits::ecdsa::SparkSignerEcdsa;
100    /// # use spark_rust::signer::default_signer::DefaultSigner;
101    /// # use bitcoin::secp256k1::PublicKey;
102    /// # async fn example(signer: DefaultSigner, public_key: PublicKey) -> Result<(), Box<dyn std::error::Error>> {
103    /// // Sign a message with a specific key
104    /// let message = "Custom message to sign";
105    /// let signature = signer.sign_message_ecdsa_with_key(
106    ///     message,
107    ///     &public_key,
108    ///     true // Apply SHA256 hashing
109    /// )?;
110    /// # Ok(())
111    /// # }
112    /// ```
113    fn sign_message_ecdsa_with_key<T: AsRef<[u8]>>(
114        &self,
115        message: T,
116        public_key_for_signing_key: &PublicKey,
117        apply_hashing: bool,
118    ) -> Result<Signature, SparkSdkError>;
119}