33//!
44
55use kaspa_hashes:: { Hash , PersonalMessageSigningHash } ;
6- use secp256k1:: { Error , XOnlyPublicKey } ;
6+ use secp256k1:: { Error , PublicKey , XOnlyPublicKey } ;
77
88/// A personal message (text) that can be signed.
99#[ derive( Clone ) ]
@@ -15,6 +15,12 @@ impl AsRef<[u8]> for PersonalMessage<'_> {
1515 }
1616}
1717
18+ #[ derive( Clone , Debug , PartialEq ) ]
19+ pub enum SignatureType {
20+ Schnorr ,
21+ ECDSA ,
22+ }
23+
1824#[ derive( Clone ) ]
1925pub struct SignMessageOptions {
2026 /// The auxiliary randomness exists only to mitigate specific kinds of power analysis
@@ -23,25 +29,38 @@ pub struct SignMessageOptions {
2329 /// mitigations against such attacks. To read more about the relevant discussions that
2430 /// arose in adding this randomness please see: <https://github.com/sipa/bips/issues/195>
2531 pub no_aux_rand : bool ,
32+ /// Signature type to use for signing
33+ pub signature_type : SignatureType ,
2634}
2735
2836/// Sign a message with the given private key
2937pub fn sign_message ( msg : & PersonalMessage , privkey : & [ u8 ; 32 ] , options : & SignMessageOptions ) -> Result < Vec < u8 > , Error > {
3038 let hash = calc_personal_message_hash ( msg) ;
31-
3239 let msg = secp256k1:: Message :: from_digest_slice ( hash. as_bytes ( ) . as_slice ( ) ) ?;
33- let schnorr_key = secp256k1:: Keypair :: from_seckey_slice ( secp256k1:: SECP256K1 , privkey) ?;
34-
35- let sig: [ u8 ; 64 ] = if options. no_aux_rand {
36- * secp256k1:: SECP256K1 . sign_schnorr_no_aux_rand ( & msg, & schnorr_key) . as_ref ( )
37- } else {
38- * schnorr_key. sign_schnorr ( msg) . as_ref ( )
39- } ;
4040
41- Ok ( sig. to_vec ( ) )
41+ match options. signature_type {
42+ SignatureType :: Schnorr => {
43+ let schnorr_key = secp256k1:: Keypair :: from_seckey_slice ( secp256k1:: SECP256K1 , privkey) ?;
44+ let sig: [ u8 ; 64 ] = if options. no_aux_rand {
45+ * secp256k1:: SECP256K1 . sign_schnorr_no_aux_rand ( & msg, & schnorr_key) . as_ref ( )
46+ } else {
47+ * schnorr_key. sign_schnorr ( msg) . as_ref ( )
48+ } ;
49+ Ok ( sig. to_vec ( ) )
50+ }
51+ SignatureType :: ECDSA => {
52+ let secret_key = secp256k1:: SecretKey :: from_slice ( privkey) ?;
53+ let sig = if options. no_aux_rand {
54+ secp256k1:: SECP256K1 . sign_ecdsa ( & msg, & secret_key)
55+ } else {
56+ secp256k1:: SECP256K1 . sign_ecdsa ( & msg, & secret_key)
57+ } ;
58+ Ok ( sig. serialize_compact ( ) . to_vec ( ) )
59+ }
60+ }
4261}
4362
44- /// Verifies signed message.
63+ /// Verifies Schnorr signed message.
4564///
4665/// Produces `Ok(())` if the signature matches the given message and [`secp256k1::Error`]
4766/// if any of the inputs are incorrect, or the signature is invalid.
@@ -53,6 +72,18 @@ pub fn verify_message(msg: &PersonalMessage, signature: &Vec<u8>, pubkey: &XOnly
5372 sig. verify ( & msg, pubkey)
5473}
5574
75+ /// Verifies ECDSA signed message.
76+ ///
77+ /// Produces `Ok(())` if the signature matches the given message and [`secp256k1::Error`]
78+ /// if any of the inputs are incorrect, or the signature is invalid.
79+ ///
80+ pub fn verify_message_ecdsa ( msg : & PersonalMessage , signature : & Vec < u8 > , pubkey : & PublicKey ) -> Result < ( ) , Error > {
81+ let hash = calc_personal_message_hash ( msg) ;
82+ let msg = secp256k1:: Message :: from_digest_slice ( hash. as_bytes ( ) . as_slice ( ) ) ?;
83+ let sig = secp256k1:: ecdsa:: Signature :: from_compact ( signature. as_slice ( ) ) ?;
84+ sig. verify ( & msg, pubkey)
85+ }
86+
5687fn calc_personal_message_hash ( msg : & PersonalMessage ) -> Hash {
5788 let mut hasher = PersonalMessageSigningHash :: new ( ) ;
5889 hasher. write ( msg) ;
@@ -89,8 +120,8 @@ mod tests {
89120 ] )
90121 . unwrap ( ) ;
91122
92- let sign_with_aux_rand = SignMessageOptions { no_aux_rand : false } ;
93- let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand : true } ;
123+ let sign_with_aux_rand = SignMessageOptions { no_aux_rand : false , signature_type : SignatureType :: Schnorr } ;
124+ let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand : true , signature_type : SignatureType :: Schnorr } ;
94125 verify_message ( & pm, & sign_message ( & pm, & privkey, & sign_with_aux_rand) . expect ( "sign_message failed" ) , & pubkey)
95126 . expect ( "verify_message failed" ) ;
96127 verify_message ( & pm, & sign_message ( & pm, & privkey, & sign_with_no_aux_rand) . expect ( "sign_message failed" ) , & pubkey)
@@ -105,7 +136,7 @@ mod tests {
105136 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x03 ,
106137 ] ;
107138
108- let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand : true } ;
139+ let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand : true , signature_type : SignatureType :: Schnorr } ;
109140 let signature = sign_message ( & pm, & privkey, & sign_with_no_aux_rand) . expect ( "sign_message failed" ) ;
110141 let signature_twice = sign_message ( & pm, & privkey, & sign_with_no_aux_rand) . expect ( "sign_message failed" ) ;
111142 assert_eq ! ( signature, signature_twice) ;
@@ -124,8 +155,8 @@ mod tests {
124155 ] )
125156 . unwrap ( ) ;
126157
127- let sign_with_aux_rand = SignMessageOptions { no_aux_rand : false } ;
128- let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand : true } ;
158+ let sign_with_aux_rand = SignMessageOptions { no_aux_rand : false , signature_type : SignatureType :: Schnorr } ;
159+ let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand : true , signature_type : SignatureType :: Schnorr } ;
129160 verify_message ( & pm, & sign_message ( & pm, & privkey, & sign_with_aux_rand) . expect ( "sign_message failed" ) , & pubkey)
130161 . expect ( "verify_message failed" ) ;
131162 verify_message ( & pm, & sign_message ( & pm, & privkey, & sign_with_no_aux_rand) . expect ( "sign_message failed" ) , & pubkey)
@@ -149,8 +180,8 @@ Ut omnis magnam et accusamus earum rem impedit provident eum commodi repellat qu
149180 ] )
150181 . unwrap ( ) ;
151182
152- let sign_with_aux_rand = SignMessageOptions { no_aux_rand : false } ;
153- let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand : true } ;
183+ let sign_with_aux_rand = SignMessageOptions { no_aux_rand : false , signature_type : SignatureType :: Schnorr } ;
184+ let sign_with_no_aux_rand = SignMessageOptions { no_aux_rand : true , signature_type : SignatureType :: Schnorr } ;
154185 verify_message ( & pm, & sign_message ( & pm, & privkey, & sign_with_aux_rand) . expect ( "sign_message failed" ) , & pubkey)
155186 . expect ( "verify_message failed" ) ;
156187 verify_message ( & pm, & sign_message ( & pm, & privkey, & sign_with_no_aux_rand) . expect ( "sign_message failed" ) , & pubkey)
0 commit comments