near_api_types/crypto/
signature.rs

1use std::{
2    fmt::{Debug, Display, Formatter},
3    hash::{Hash, Hasher},
4    io::{Error, ErrorKind, Read, Write},
5    str::FromStr,
6};
7
8use borsh::{BorshDeserialize, BorshSerialize};
9use ed25519_dalek::Verifier;
10use primitive_types::U256;
11use secp256k1::Message;
12
13use crate::{
14    crypto::{
15        public_key::Secp256K1PublicKey, secret_key::SECP256K1, split_key_type_data, KeyType,
16        SECP256K1_SIGNATURE_LENGTH,
17    },
18    errors::{DataConversionError, SignatureErrors},
19    PublicKey,
20};
21
22/// Signature container supporting different curves.
23#[derive(Clone, PartialEq, Eq)]
24pub enum Signature {
25    ED25519(ed25519_dalek::Signature),
26    SECP256K1(Secp256K1Signature),
27}
28
29// This `Hash` implementation is safe since it retains the property
30// `k1 == k2 ⇒ hash(k1) == hash(k2)`.
31impl Hash for Signature {
32    fn hash<H: Hasher>(&self, state: &mut H) {
33        match self {
34            Self::ED25519(sig) => sig.to_bytes().hash(state),
35            Self::SECP256K1(sig) => sig.hash(state),
36        };
37    }
38}
39
40impl Signature {
41    /// Construct Signature from key type and raw signature blob
42    pub fn from_parts(
43        signature_type: KeyType,
44        signature_data: &[u8],
45    ) -> Result<Self, DataConversionError> {
46        match signature_type {
47            KeyType::ED25519 => Ok(Self::ED25519(ed25519_dalek::Signature::from_bytes(
48                <&[u8; ed25519_dalek::SIGNATURE_LENGTH]>::try_from(signature_data)?,
49            ))),
50            KeyType::SECP256K1 => Ok(Self::SECP256K1(Secp256K1Signature::try_from(
51                signature_data,
52            )?)),
53        }
54    }
55
56    /// Verifies that this signature is indeed signs the data with given public key.
57    /// Also if public key doesn't match on the curve returns `false`.
58    pub fn verify(&self, data: &[u8], public_key: &PublicKey) -> bool {
59        match (&self, public_key) {
60            (Self::ED25519(signature), PublicKey::ED25519(public_key)) => {
61                ed25519_dalek::VerifyingKey::from_bytes(&public_key.0)
62                    .is_ok_and(|public_key| public_key.verify(data, signature).is_ok())
63            }
64            (Self::SECP256K1(signature), PublicKey::SECP256K1(public_key)) => {
65                // cspell:ignore rsig pdata
66                let rec_id =
67                    match secp256k1::ecdsa::RecoveryId::from_i32(i32::from(signature.0[64])) {
68                        Ok(r) => r,
69                        Err(_) => return false,
70                    };
71                let rsig = match secp256k1::ecdsa::RecoverableSignature::from_compact(
72                    &signature.0[0..64],
73                    rec_id,
74                ) {
75                    Ok(r) => r,
76                    Err(_) => return false,
77                };
78                let sig = rsig.to_standard();
79                let pdata: [u8; 65] = {
80                    // code borrowed from https://github.com/openethereum/openethereum/blob/98b7c07171cd320f32877dfa5aa528f585dc9a72/ethkey/src/signature.rs#L210
81                    let mut temp = [4u8; 65];
82                    temp[1..65].copy_from_slice(&public_key.0);
83                    temp
84                };
85                let message = match secp256k1::Message::from_slice(data) {
86                    Ok(m) => m,
87                    Err(_) => return false,
88                };
89                let pub_key = match secp256k1::PublicKey::from_slice(&pdata) {
90                    Ok(p) => p,
91                    Err(_) => return false,
92                };
93                SECP256K1.verify_ecdsa(&message, &sig, &pub_key).is_ok()
94            }
95            _ => false,
96        }
97    }
98
99    pub const fn key_type(&self) -> KeyType {
100        match self {
101            Self::ED25519(_) => KeyType::ED25519,
102            Self::SECP256K1(_) => KeyType::SECP256K1,
103        }
104    }
105}
106
107impl BorshSerialize for Signature {
108    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
109        match self {
110            Self::ED25519(signature) => {
111                BorshSerialize::serialize(&0u8, writer)?;
112                writer.write_all(&signature.to_bytes())?;
113            }
114            Self::SECP256K1(signature) => {
115                BorshSerialize::serialize(&1u8, writer)?;
116                writer.write_all(&signature.0)?;
117            }
118        }
119        Ok(())
120    }
121}
122
123impl BorshDeserialize for Signature {
124    fn deserialize_reader<R: Read>(rd: &mut R) -> std::io::Result<Self> {
125        let key_type = KeyType::try_from(u8::deserialize_reader(rd)?)
126            .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string()))?;
127        match key_type {
128            KeyType::ED25519 => {
129                let array: [u8; ed25519_dalek::SIGNATURE_LENGTH] =
130                    BorshDeserialize::deserialize_reader(rd)?;
131                // Sanity-check that was performed by ed25519-dalek in from_bytes before version 2,
132                // but was removed with version 2. It is not actually any good a check, but we have
133                // it here in case we need to keep backward compatibility. Maybe this check is not
134                // actually required, but please think carefully before removing it.
135                if array[ed25519_dalek::SIGNATURE_LENGTH - 1] & 0b1110_0000 != 0 {
136                    return Err(Error::new(ErrorKind::InvalidData, "signature error"));
137                }
138                Ok(Self::ED25519(ed25519_dalek::Signature::from_bytes(&array)))
139            }
140            KeyType::SECP256K1 => {
141                let array: [u8; 65] = BorshDeserialize::deserialize_reader(rd)?;
142                Ok(Self::SECP256K1(Secp256K1Signature(array)))
143            }
144        }
145    }
146}
147
148impl Display for Signature {
149    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
150        let buf;
151        let (key_type, key_data) = match self {
152            Self::ED25519(signature) => {
153                buf = signature.to_bytes();
154                (KeyType::ED25519, &buf[..])
155            }
156            Self::SECP256K1(signature) => (KeyType::SECP256K1, &signature.0[..]),
157        };
158        write!(f, "{}:{}", key_type, bs58::encode(key_data).into_string())
159    }
160}
161
162impl Debug for Signature {
163    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
164        Display::fmt(self, f)
165    }
166}
167
168impl serde::Serialize for Signature {
169    fn serialize<S>(
170        &self,
171        serializer: S,
172    ) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error>
173    where
174        S: serde::Serializer,
175    {
176        serializer.serialize_str(&self.to_string())
177    }
178}
179
180impl FromStr for Signature {
181    type Err = DataConversionError;
182
183    fn from_str(value: &str) -> Result<Self, Self::Err> {
184        let (sig_type, sig_data) = split_key_type_data(value)?;
185        Ok(match sig_type {
186            KeyType::ED25519 => {
187                let data = bs58::decode(sig_data)
188                    .into_vec()
189                    .map_err(DataConversionError::from)?
190                    .try_into()?;
191                let sig = ed25519_dalek::Signature::from_bytes(&data);
192                Self::ED25519(sig)
193            }
194            KeyType::SECP256K1 => Self::SECP256K1(Secp256K1Signature(
195                bs58::decode(sig_data)
196                    .into_vec()
197                    .map_err(DataConversionError::from)?
198                    .try_into()?,
199            )),
200        })
201    }
202}
203
204impl<'de> serde::Deserialize<'de> for Signature {
205    fn deserialize<D>(deserializer: D) -> Result<Self, <D as serde::Deserializer<'de>>::Error>
206    where
207        D: serde::Deserializer<'de>,
208    {
209        let s = <String as serde::Deserialize>::deserialize(deserializer)?;
210        s.parse()
211            .map_err(|err: DataConversionError| serde::de::Error::custom(err.to_string()))
212    }
213}
214
215const SECP256K1_N: U256 = U256([
216    0xbfd25e8cd0364141,
217    0xbaaedce6af48a03b,
218    0xfffffffffffffffe,
219    0xffffffffffffffff,
220]);
221
222// Half of SECP256K1_N + 1.
223const SECP256K1_N_HALF_ONE: U256 = U256([
224    0xdfe92f46681b20a1,
225    0x5d576e7357a4501d,
226    0xffffffffffffffff,
227    0x7fffffffffffffff,
228]);
229
230#[derive(Clone, Eq, PartialEq, Hash)]
231pub struct Secp256K1Signature(pub [u8; SECP256K1_SIGNATURE_LENGTH]);
232
233impl Secp256K1Signature {
234    pub fn check_signature_values(&self, reject_upper: bool) -> bool {
235        let mut r_bytes = [0u8; 32];
236        r_bytes.copy_from_slice(&self.0[0..32]);
237        let r = U256::from(r_bytes);
238
239        let mut s_bytes = [0u8; 32];
240        s_bytes.copy_from_slice(&self.0[32..64]);
241        let s = U256::from(s_bytes);
242
243        let s_check = if reject_upper {
244            // Reject upper range of s values (ECDSA malleability)
245            SECP256K1_N_HALF_ONE
246        } else {
247            SECP256K1_N
248        };
249
250        r < SECP256K1_N && s < s_check
251    }
252
253    pub fn recover(&self, msg: [u8; 32]) -> Result<Secp256K1PublicKey, SignatureErrors> {
254        let recoverable_sig = secp256k1::ecdsa::RecoverableSignature::from_compact(
255            &self.0[0..64],
256            secp256k1::ecdsa::RecoveryId::from_i32(i32::from(self.0[64])).unwrap(),
257        )?;
258        let msg = Message::from_slice(&msg).unwrap();
259
260        let res = SECP256K1
261            .recover_ecdsa(&msg, &recoverable_sig)?
262            .serialize_uncompressed();
263
264        let pk = Secp256K1PublicKey::try_from(&res[1..65]).expect("cannot fail");
265
266        Ok(pk)
267    }
268}
269
270impl TryFrom<&[u8]> for Secp256K1Signature {
271    type Error = DataConversionError;
272
273    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
274        Ok(Self(
275            data.try_into()
276                .map_err(|_| Self::Error::IncorrectLength(data.len()))?,
277        ))
278    }
279}
280
281impl Debug for Secp256K1Signature {
282    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
283        Display::fmt(&bs58::encode(&self.0).into_string(), f)
284    }
285}