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}