defuse_crypto/curve/
secp256k1.rs

1use crate::{CryptoHash, Curve};
2
3pub struct Secp256k1;
4
5impl Curve for Secp256k1 {
6    type PublicKey = [u8; 64];
7
8    /// Concatenated `r`, `s` and `v` (recovery byte).
9    ///
10    /// Note: Ethereum clients shift the recovery byte and this
11    /// logic might depend on chain id, so clients must rollback
12    /// these changes to v ∈ {0, 1}.
13    /// References:
14    /// * <https://github.com/ethereumjs/ethereumjs-monorepo/blob/dc7169c16df6d36adeb6e234fcc66eb6cfc5ea3f/packages/util/src/signature.ts#L31-L62>
15    /// * <https://github.com/ethereum/go-ethereum/issues/19751#issuecomment-504900739>
16    type Signature = [u8; 65];
17
18    // Output of cryptographic hash function
19    type Message = CryptoHash;
20
21    /// ECDSA signatures are recoverable, so you don't need a verifying key
22    type VerifyingKey = ();
23}
24
25#[cfg(feature = "near-contract")]
26impl crate::VerifiableCurve for Secp256k1 {
27    #[inline]
28    fn verify(
29        [signature @ .., v]: &Self::Signature,
30        hash: &Self::Message,
31        _verifying_key: &(),
32    ) -> Option<Self::PublicKey> {
33        near_sdk::env::ecrecover(
34            hash, signature, *v,
35            // Do not accept malleable signatures:
36            // https://github.com/near/nearcore/blob/d73041cc1d1a70af4456fceefaceb1bf7f684fde/core/crypto/src/signature.rs#L448-L455
37            true,
38        )
39    }
40}
41
42impl crate::TypedCurve for Secp256k1 {
43    const CURVE_TYPE: crate::CurveType = crate::CurveType::Secp256k1;
44}
45
46#[cfg_attr(any(feature = "arbitrary", test), derive(arbitrary::Arbitrary))]
47#[cfg_attr(
48    feature = "borsh",
49    derive(::borsh::BorshSerialize, ::borsh::BorshDeserialize),
50    cfg_attr(feature = "abi", derive(::borsh::BorshSchema))
51)]
52#[cfg_attr(
53    feature = "serde",
54    derive(::serde_with::SerializeDisplay, ::serde_with::DeserializeFromStr),
55    cfg_attr(feature = "abi", derive(::schemars::JsonSchema))
56)]
57#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
58#[repr(transparent)]
59pub struct Secp256k1PublicKey(
60    // schemars ignores `with` at struct level for newtypes; must be on the field
61    #[cfg_attr(all(feature = "abi", feature = "serde"), schemars(with = "String"))]
62    pub  <Secp256k1 as Curve>::PublicKey,
63);
64
65#[cfg(feature = "parse")]
66const _: () = {
67    use crate::{ParseCurveError, TypedCurve};
68    use core::fmt::{self, Debug, Display};
69    use std::str::FromStr;
70
71    impl Debug for Secp256k1PublicKey {
72        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73            Display::fmt(self, f)
74        }
75    }
76
77    impl Display for Secp256k1PublicKey {
78        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79            f.write_str(&<Secp256k1 as TypedCurve>::to_base58(self.0))
80        }
81    }
82
83    impl FromStr for Secp256k1PublicKey {
84        type Err = ParseCurveError;
85
86        fn from_str(s: &str) -> Result<Self, Self::Err> {
87            Secp256k1::parse_base58(s).map(Self)
88        }
89    }
90};
91
92#[cfg_attr(any(feature = "arbitrary", test), derive(arbitrary::Arbitrary))]
93#[cfg_attr(
94    feature = "borsh",
95    derive(::borsh::BorshSerialize, ::borsh::BorshDeserialize),
96    cfg_attr(feature = "abi", derive(::borsh::BorshSchema))
97)]
98#[cfg_attr(
99    feature = "serde",
100    derive(::serde_with::SerializeDisplay, ::serde_with::DeserializeFromStr),
101    cfg_attr(feature = "abi", derive(::schemars::JsonSchema))
102)]
103#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
104#[repr(transparent)]
105pub struct Secp256k1Signature(
106    // schemars ignores `with` at struct level for newtypes; must be on the field
107    #[cfg_attr(all(feature = "abi", feature = "serde"), schemars(with = "String"))]
108    pub  <Secp256k1 as Curve>::Signature,
109);
110
111#[cfg(feature = "parse")]
112const _: () = {
113    use crate::{ParseCurveError, TypedCurve};
114    use core::fmt::{self, Debug, Display};
115    use std::str::FromStr;
116
117    impl Debug for Secp256k1Signature {
118        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119            Display::fmt(self, f)
120        }
121    }
122
123    impl Display for Secp256k1Signature {
124        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125            f.write_str(&<Secp256k1 as TypedCurve>::to_base58(self.0))
126        }
127    }
128
129    impl FromStr for Secp256k1Signature {
130        type Err = ParseCurveError;
131
132        fn from_str(s: &str) -> Result<Self, Self::Err> {
133            Secp256k1::parse_base58(s).map(Self)
134        }
135    }
136};