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    CryptoHash, 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: CryptoHash, 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.0.as_ref(), 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 = secp256k1::Message::from(data);
86                let pub_key = match secp256k1::PublicKey::from_slice(&pdata) {
87                    Ok(p) => p,
88                    Err(_) => return false,
89                };
90                SECP256K1.verify_ecdsa(&message, &sig, &pub_key).is_ok()
91            }
92            _ => false,
93        }
94    }
95
96    pub const fn key_type(&self) -> KeyType {
97        match self {
98            Self::ED25519(_) => KeyType::ED25519,
99            Self::SECP256K1(_) => KeyType::SECP256K1,
100        }
101    }
102}
103
104impl BorshSerialize for Signature {
105    fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
106        match self {
107            Self::ED25519(signature) => {
108                BorshSerialize::serialize(&0u8, writer)?;
109                writer.write_all(&signature.to_bytes())?;
110            }
111            Self::SECP256K1(signature) => {
112                BorshSerialize::serialize(&1u8, writer)?;
113                writer.write_all(&signature.0)?;
114            }
115        }
116        Ok(())
117    }
118}
119
120impl BorshDeserialize for Signature {
121    fn deserialize_reader<R: Read>(rd: &mut R) -> std::io::Result<Self> {
122        let key_type = KeyType::try_from(u8::deserialize_reader(rd)?)
123            .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string()))?;
124        match key_type {
125            KeyType::ED25519 => {
126                let array: [u8; ed25519_dalek::SIGNATURE_LENGTH] =
127                    BorshDeserialize::deserialize_reader(rd)?;
128                // Sanity-check that was performed by ed25519-dalek in from_bytes before version 2,
129                // but was removed with version 2. It is not actually any good a check, but we have
130                // it here in case we need to keep backward compatibility. Maybe this check is not
131                // actually required, but please think carefully before removing it.
132                if array[ed25519_dalek::SIGNATURE_LENGTH - 1] & 0b1110_0000 != 0 {
133                    return Err(Error::new(ErrorKind::InvalidData, "signature error"));
134                }
135                Ok(Self::ED25519(ed25519_dalek::Signature::from_bytes(&array)))
136            }
137            KeyType::SECP256K1 => {
138                let array: [u8; 65] = BorshDeserialize::deserialize_reader(rd)?;
139                Ok(Self::SECP256K1(Secp256K1Signature(array)))
140            }
141        }
142    }
143}
144
145impl Display for Signature {
146    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
147        let buf;
148        let (key_type, key_data) = match self {
149            Self::ED25519(signature) => {
150                buf = signature.to_bytes();
151                (KeyType::ED25519, &buf[..])
152            }
153            Self::SECP256K1(signature) => (KeyType::SECP256K1, &signature.0[..]),
154        };
155        write!(f, "{}:{}", key_type, bs58::encode(key_data).into_string())
156    }
157}
158
159impl Debug for Signature {
160    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
161        Display::fmt(self, f)
162    }
163}
164
165impl serde::Serialize for Signature {
166    fn serialize<S>(
167        &self,
168        serializer: S,
169    ) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error>
170    where
171        S: serde::Serializer,
172    {
173        serializer.serialize_str(&self.to_string())
174    }
175}
176
177impl FromStr for Signature {
178    type Err = DataConversionError;
179
180    fn from_str(value: &str) -> Result<Self, Self::Err> {
181        let (sig_type, sig_data) = split_key_type_data(value)?;
182        Ok(match sig_type {
183            KeyType::ED25519 => {
184                let data = bs58::decode(sig_data)
185                    .into_vec()
186                    .map_err(DataConversionError::from)?
187                    .try_into()?;
188                let sig = ed25519_dalek::Signature::from_bytes(&data);
189                Self::ED25519(sig)
190            }
191            KeyType::SECP256K1 => Self::SECP256K1(Secp256K1Signature(
192                bs58::decode(sig_data)
193                    .into_vec()
194                    .map_err(DataConversionError::from)?
195                    .try_into()?,
196            )),
197        })
198    }
199}
200
201impl<'de> serde::Deserialize<'de> for Signature {
202    fn deserialize<D>(deserializer: D) -> Result<Self, <D as serde::Deserializer<'de>>::Error>
203    where
204        D: serde::Deserializer<'de>,
205    {
206        let s = <String as serde::Deserialize>::deserialize(deserializer)?;
207        s.parse()
208            .map_err(|err: DataConversionError| serde::de::Error::custom(err.to_string()))
209    }
210}
211
212const SECP256K1_N: U256 = U256([
213    0xbfd25e8cd0364141,
214    0xbaaedce6af48a03b,
215    0xfffffffffffffffe,
216    0xffffffffffffffff,
217]);
218
219// Half of SECP256K1_N + 1.
220const SECP256K1_N_HALF_ONE: U256 = U256([
221    0xdfe92f46681b20a1,
222    0x5d576e7357a4501d,
223    0xffffffffffffffff,
224    0x7fffffffffffffff,
225]);
226
227#[derive(Clone, Eq, PartialEq, Hash)]
228pub struct Secp256K1Signature(pub [u8; SECP256K1_SIGNATURE_LENGTH]);
229
230impl Secp256K1Signature {
231    pub fn check_signature_values(&self, reject_upper: bool) -> bool {
232        let mut r_bytes = [0u8; 32];
233        r_bytes.copy_from_slice(&self.0[0..32]);
234        let r = U256::from(r_bytes);
235
236        let mut s_bytes = [0u8; 32];
237        s_bytes.copy_from_slice(&self.0[32..64]);
238        let s = U256::from(s_bytes);
239
240        let s_check = if reject_upper {
241            // Reject upper range of s values (ECDSA malleability)
242            SECP256K1_N_HALF_ONE
243        } else {
244            SECP256K1_N
245        };
246
247        r < SECP256K1_N && s < s_check
248    }
249
250    pub fn recover(&self, msg: CryptoHash) -> Result<Secp256K1PublicKey, SignatureErrors> {
251        let recovery_id = secp256k1::ecdsa::RecoveryId::from_i32(i32::from(self.0[64]))?;
252
253        let recoverable_sig =
254            secp256k1::ecdsa::RecoverableSignature::from_compact(&self.0[0..64], recovery_id)?;
255        let msg = Message::from_slice(&msg.0)?;
256
257        let res = SECP256K1
258            .recover_ecdsa(&msg, &recoverable_sig)?
259            .serialize_uncompressed();
260        let mut pk = [0u8; 64];
261        pk.copy_from_slice(&res[1..65]);
262
263        Ok(Secp256K1PublicKey(pk))
264    }
265}
266
267impl TryFrom<&[u8]> for Secp256K1Signature {
268    type Error = DataConversionError;
269
270    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
271        Ok(Self(
272            data.try_into()
273                .map_err(|_| Self::Error::IncorrectLength(data.len()))?,
274        ))
275    }
276}
277
278impl Debug for Secp256K1Signature {
279    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
280        Display::fmt(&bs58::encode(&self.0).into_string(), f)
281    }
282}