fuel_crypto/secp256/
signature.rs

1use super::backend::k1;
2use crate::{
3    Error,
4    Message,
5    PublicKey,
6    SecretKey,
7};
8
9use fuel_types::Bytes64;
10
11use core::{
12    fmt,
13    ops::Deref,
14    str,
15};
16
17/// Compressed-form Secp256k1 signature.
18#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20#[repr(transparent)]
21pub struct Signature(Bytes64);
22
23impl Signature {
24    /// Memory length of the type in bytes.
25    pub const LEN: usize = Bytes64::LEN;
26
27    /// Construct a `Signature` directly from its bytes.
28    ///
29    /// This constructor expects the given bytes to be a valid signature. No signing is
30    /// performed.
31    pub fn from_bytes(bytes: [u8; Self::LEN]) -> Self {
32        Self(bytes.into())
33    }
34
35    /// Construct a `Signature` reference directly from a reference to its bytes.
36    ///
37    /// This constructor expects the given bytes to be a valid signature. No signing is
38    /// performed.
39    pub fn from_bytes_ref(bytes: &[u8; Self::LEN]) -> &Self {
40        // TODO: Wrap this unsafe conversion safely in `fuel_types::Bytes64`.
41        #[allow(unsafe_code)]
42        unsafe {
43            &*(bytes.as_ptr() as *const Self)
44        }
45    }
46
47    /// Kept temporarily for backwards compatibility.
48    #[deprecated = "Use `Signature::from_bytes` instead"]
49    pub fn from_bytes_unchecked(bytes: [u8; Self::LEN]) -> Self {
50        Self::from_bytes(bytes)
51    }
52}
53
54impl Deref for Signature {
55    type Target = [u8; Signature::LEN];
56
57    fn deref(&self) -> &[u8; Signature::LEN] {
58        self.0.deref()
59    }
60}
61
62impl AsRef<[u8]> for Signature {
63    fn as_ref(&self) -> &[u8] {
64        self.0.as_ref()
65    }
66}
67
68impl AsMut<[u8]> for Signature {
69    fn as_mut(&mut self) -> &mut [u8] {
70        self.0.as_mut()
71    }
72}
73
74impl fmt::LowerHex for Signature {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        self.0.fmt(f)
77    }
78}
79
80impl fmt::UpperHex for Signature {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        self.0.fmt(f)
83    }
84}
85
86impl fmt::Debug for Signature {
87    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88        self.0.fmt(f)
89    }
90}
91
92impl fmt::Display for Signature {
93    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94        self.0.fmt(f)
95    }
96}
97
98impl From<Signature> for [u8; Signature::LEN] {
99    fn from(salt: Signature) -> [u8; Signature::LEN] {
100        salt.0.into()
101    }
102}
103
104impl From<Signature> for Bytes64 {
105    fn from(s: Signature) -> Self {
106        s.0
107    }
108}
109
110impl str::FromStr for Signature {
111    type Err = Error;
112
113    /// Parse a `Signature` directly from its bytes encoded as hex in a string.
114    ///
115    /// This constructor does not perform any signing.
116    fn from_str(s: &str) -> Result<Self, Self::Err> {
117        Bytes64::from_str(s)
118            .map_err(|_| Error::InvalidSignature)
119            .map(|s| Self::from_bytes(s.into()))
120    }
121}
122
123/// Secp256k1 methods
124impl Signature {
125    /// Produce secp256k1 signature
126    pub fn sign(secret: &SecretKey, message: &Message) -> Self {
127        Self(Bytes64::from(k1::sign(secret, message)))
128    }
129
130    /// Recover secp256k1 public key from a signature performed with
131    pub fn recover(&self, message: &Message) -> Result<PublicKey, Error> {
132        k1::recover(*self.0, message)
133    }
134
135    /// Verify that a signature matches given public key
136    pub fn verify(&self, public_key: &PublicKey, message: &Message) -> Result<(), Error> {
137        k1::verify(*self.0, **public_key, message)
138    }
139}