p256k1/
ecdsa.rs

1use core::fmt::{Debug, Display, Formatter, Result as FmtResult};
2use serde::{
3    de::{self, Visitor},
4    Deserialize, Deserializer, Serialize, Serializer,
5};
6use std::{array::TryFromSliceError, hash::Hash};
7
8use crate::_rename::{
9    secp256k1_ecdsa_sign, secp256k1_ecdsa_signature_parse_compact,
10    secp256k1_ecdsa_signature_serialize_compact, secp256k1_ecdsa_verify,
11};
12use crate::{
13    bindings::secp256k1_ecdsa_signature, context::Context, errors::ConversionError, scalar::Scalar,
14};
15
16pub use crate::keys::{Error as KeyError, PublicKey};
17
18#[derive(Debug, Clone)]
19/// Errors in ECDSA signature operations
20pub enum Error {
21    /// Error with key operations
22    Key(KeyError),
23    /// Error occurred during a try from operation
24    TryFrom(String),
25    /// Error converting a scalar
26    Conversion(ConversionError),
27}
28
29impl Display for Error {
30    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
31        write!(f, "{:?}", self)
32    }
33}
34
35impl std::error::Error for Error {}
36
37impl From<TryFromSliceError> for Error {
38    fn from(e: TryFromSliceError) -> Self {
39        Error::TryFrom(e.to_string())
40    }
41}
42
43/**
44Signature is a wrapper around libsecp256k1's secp256k1_ecdsa_signature struct.
45*/
46#[derive(Debug, Clone)]
47pub struct Signature {
48    /// The wrapped libsecp256k1 signature
49    pub signature: secp256k1_ecdsa_signature,
50}
51
52impl Signature {
53    /// Construct an ECDSA signature
54    pub fn new(hash: &[u8], sec_key: &Scalar) -> Result<Self, Error> {
55        let context = Context::default();
56        let mut sig = Self {
57            signature: secp256k1_ecdsa_signature { data: [0; 64] },
58        };
59        if unsafe {
60            secp256k1_ecdsa_sign(
61                context.context,
62                &mut sig.signature,
63                hash.as_ptr(),
64                sec_key.to_bytes().as_ptr(),
65                None,
66                std::ptr::null_mut::<::std::os::raw::c_void>(),
67            )
68        } == 0
69        {
70            return Err(Error::Key(KeyError::InvalidSecretKey));
71        }
72        Ok(sig)
73    }
74
75    /// Verify an ECDSA signature
76    pub fn verify(&self, hash: &[u8], pub_key: &PublicKey) -> bool {
77        let context = Context::default();
78
79        1 == unsafe {
80            secp256k1_ecdsa_verify(
81                context.context,
82                &self.signature,
83                hash.as_ptr(),
84                &pub_key.key,
85            )
86        }
87    }
88
89    /// Returns the signature's deserialized underlying data
90    pub fn to_bytes(&self) -> [u8; 64] {
91        let context = Context::default();
92        let mut bytes = [0u8; 64];
93        //Deserialize the signature's data
94        unsafe {
95            secp256k1_ecdsa_signature_serialize_compact(
96                context.context,
97                bytes.as_mut_ptr(),
98                &self.signature,
99            );
100        }
101        bytes
102    }
103}
104
105impl Display for Signature {
106    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
107        write!(f, "{}", bs58::encode(self.to_bytes()).into_string())
108    }
109}
110
111impl PartialEq for Signature {
112    fn eq(&self, other: &Self) -> bool {
113        self.to_bytes().eq(&other.to_bytes())
114    }
115}
116
117impl Eq for Signature {}
118
119impl PartialOrd for Signature {
120    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
121        Some(self.cmp(other))
122    }
123}
124
125impl Ord for Signature {
126    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
127        self.to_bytes().cmp(&other.to_bytes())
128    }
129}
130
131impl Hash for Signature {
132    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
133        state.write(&self.to_bytes())
134    }
135}
136
137impl Serialize for Signature {
138    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139    where
140        S: Serializer,
141    {
142        serializer.serialize_bytes(&self.to_bytes())
143    }
144}
145
146struct SignatureVisitor;
147
148impl<'de> Visitor<'de> for SignatureVisitor {
149    type Value = Signature;
150
151    fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
152        formatter.write_str("an array of bytes which represents two scalars on the secp256k1 curve")
153    }
154
155    fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
156    where
157        E: de::Error,
158    {
159        match Signature::try_from(value) {
160            Ok(s) => Ok(s),
161            Err(e) => Err(E::custom(format!("{:?}", e))),
162        }
163    }
164
165    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
166    where
167        A: de::SeqAccess<'de>,
168    {
169        let mut v = Vec::new();
170
171        while let Ok(Some(x)) = seq.next_element() {
172            v.push(x);
173        }
174
175        self.visit_bytes(&v)
176    }
177}
178
179impl<'de> Deserialize<'de> for Signature {
180    fn deserialize<D>(deserializer: D) -> Result<Signature, D::Error>
181    where
182        D: Deserializer<'de>,
183    {
184        deserializer.deserialize_bytes(SignatureVisitor)
185    }
186}
187
188impl TryFrom<&[u8]> for Signature {
189    type Error = Error;
190    /// Create an ECDSA signature given a slice of signed data.
191    /// Note it also serializes the data in compact (64 byte) format
192    fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
193        let data: [u8; 64] = input[0..].try_into()?;
194        Signature::try_from(data)
195    }
196}
197
198impl TryFrom<[u8; 64]> for Signature {
199    type Error = Error;
200    /// Create an ECDSA signature given an array of signed data.
201    /// Note it also serializes the data in compact (64 byte) format
202    fn try_from(input: [u8; 64]) -> Result<Self, Self::Error> {
203        let context = Context::default();
204        let mut sig = Self {
205            signature: secp256k1_ecdsa_signature { data: [0u8; 64] },
206        };
207        //Attempt to serialize the data into the signature
208        let parsed = unsafe {
209            secp256k1_ecdsa_signature_parse_compact(
210                context.context,
211                &mut sig.signature,
212                input.as_ptr(),
213            )
214        };
215        if parsed == 0 {
216            return Err(Error::TryFrom(
217                "Failed to serialize input data into compact (64 byte) form.".to_string(),
218            ));
219        }
220        Ok(sig)
221    }
222}
223
224#[cfg(test)]
225mod tests {
226    use super::*;
227    use rand_core::{OsRng, RngCore};
228    use sha2::{Digest, Sha256};
229    use std::{collections::HashSet, thread};
230
231    #[test]
232    fn signature_generation() {
233        // Generate a secret and public key
234        let mut rnd = OsRng::default();
235        let sec_key = Scalar::random(&mut rnd);
236        let pub_key = PublicKey::new(&sec_key).unwrap();
237
238        // Instead of signing a message directly, must sign a 32-byte hash of it.
239        let msg = b"Hello, world!";
240        let mut hasher = Sha256::new();
241        hasher.update(msg);
242        let msg_hash = hasher.finalize();
243        // Generate a ECDSA signature
244        let sig = Signature::new(&msg_hash, &sec_key).unwrap();
245
246        // Verify the generated signature is valid using the msg_hash and corresponding public key
247        assert!(sig.verify(&msg_hash, &pub_key));
248    }
249
250    #[test]
251    fn signature_generation_threaded() {
252        // Generate a secret and public key
253        let mut rnd = OsRng::default();
254        let sec_key = Scalar::random(&mut rnd);
255        let pub_key = PublicKey::new(&sec_key).unwrap();
256
257        // Instead of signing a message directly, must sign a 32-byte hash of it.
258        let msg = b"Hello, world!";
259        let mut hasher = Sha256::new();
260        hasher.update(msg);
261        let msg_hash = hasher.finalize();
262
263        let mut handles = Vec::new();
264        for _ in 0..64 {
265            let sec_key = sec_key.clone();
266            let pub_key = pub_key.clone();
267            let msg_hash = msg_hash.clone();
268            handles.push(thread::spawn(move || {
269                // Generate a ECDSA signature
270                let sig = Signature::new(&msg_hash, &sec_key).unwrap();
271
272                // Verify the generated signature is valid using the msg_hash and corresponding public key
273                assert!(sig.verify(&msg_hash, &pub_key));
274            }));
275        }
276
277        for handle in handles {
278            handle.join().unwrap();
279        }
280    }
281
282    #[test]
283    fn signature_from() {
284        // Create random data bytes to serialize
285        let mut rng = OsRng::default();
286        let mut bytes = [0u8; 64];
287        rng.fill_bytes(&mut bytes);
288
289        let sig_from_struct = Signature {
290            signature: secp256k1_ecdsa_signature { data: bytes },
291        };
292        let sig_from_slice = Signature::try_from(bytes.as_slice()).unwrap();
293        let sig_from_array = Signature::try_from(bytes).unwrap();
294
295        assert_ne!(sig_from_struct.to_bytes(), sig_from_slice.to_bytes());
296        assert_ne!(sig_from_struct.to_bytes(), sig_from_array.to_bytes());
297        assert_eq!(sig_from_array.to_bytes(), sig_from_slice.to_bytes());
298
299        let mut too_small = [0u8; 63];
300        rng.fill_bytes(&mut too_small);
301        assert!(Signature::try_from(too_small.as_slice()).is_err());
302
303        let mut too_big = [0u8; 65];
304        rng.fill_bytes(&mut too_big);
305        assert!(Signature::try_from(too_big.as_slice()).is_err());
306    }
307
308    #[test]
309    fn manual_serde() {
310        // Generate random data bytes
311        let mut rng = OsRng::default();
312        let mut bytes = [0u8; 64];
313        rng.fill_bytes(&mut bytes);
314
315        //Serialize with try_from and deserialize with to_bytes
316        let sig = Signature::try_from(bytes).unwrap();
317        assert_ne!(sig.signature.data, bytes);
318        assert_eq!(sig.to_bytes(), bytes);
319    }
320
321    #[test]
322    fn custom_serde() {
323        let mut rng = OsRng::default();
324        let mut hash = [0u8; 32];
325        rng.fill_bytes(&mut hash);
326        let private_key = Scalar::random(&mut rng);
327        let public_key = PublicKey::new(&private_key).expect("failed to create public key");
328        let sig = Signature::new(&hash, &private_key).expect("failed to create sig");
329
330        assert!(sig.verify(&hash, &public_key));
331
332        let ssig = serde_json::to_string(&sig).expect("failed to serialize");
333        let dsig: Signature = serde_json::from_str(&ssig).expect("failed to deserialize");
334
335        assert!(dsig.verify(&hash, &public_key));
336    }
337
338    #[test]
339    fn hash() {
340        let msg = [0u8; 32];
341        let private_keys = [1, 2, 3, 4, 5].map(Scalar::from);
342        let signatures = private_keys.map(|pk| Signature::new(&msg, &pk).unwrap());
343
344        let signatures_hash_set: HashSet<_> = signatures.into();
345
346        assert_eq!(signatures_hash_set.len(), 5);
347    }
348
349    #[test]
350    fn sort() {
351        let msg = [0u8; 32];
352        let private_keys = [1, 2, 3, 4, 5].map(Scalar::from);
353        let mut signatures = private_keys.map(|pk| Signature::new(&msg, &pk).unwrap());
354        signatures.sort();
355
356        for idx in 0..4 {
357            assert!(signatures[idx] < signatures[idx + 1]);
358        }
359    }
360}