Skip to main content

rings_core/ecc/
mod.rs

1//! ECDSA, EdDSA, and ElGamal
2use std::convert::TryFrom;
3use std::ops::Deref;
4use std::str::FromStr;
5
6use ethereum_types::H160;
7use hex;
8use rand::SeedableRng;
9use rand_hc::Hc128Rng;
10use serde::Deserialize;
11use serde::Serialize;
12use sha1::Digest;
13use sha1::Sha1;
14use subtle::CtOption;
15
16use crate::error::Error;
17use crate::error::Result;
18pub mod elgamal;
19pub mod group;
20pub mod keys;
21pub mod signers;
22mod types;
23use elliptic_curve::generic_array::typenum::U32;
24use elliptic_curve::generic_array::GenericArray;
25use elliptic_curve::point::AffineCoordinates;
26use elliptic_curve::point::DecompressPoint;
27use elliptic_curve::FieldBytes;
28pub use group::*;
29pub use keys::*;
30use p256::NistP256;
31use subtle::Choice;
32pub use types::PublicKey;
33
34/// ref <https://docs.rs/web3/0.18.0/src/web3/signing.rs.html#69>
35///
36/// length r: 32, length s: 32, length v(recovery_id): 1
37pub type SigBytes = [u8; 65];
38/// Alias PublicKey.
39pub type CurveEle<const SIZE: usize> = PublicKey<SIZE>;
40/// PublicKeyAddress is H160.
41pub type PublicKeyAddress = H160;
42
43/// Wrap libsecp256k1::SecretKey.
44/// which is a A 256-bit scalar value, present as [u32; 4]
45#[derive(PartialEq, Eq, Debug, Clone, Copy)]
46pub struct SecretKey(libsecp256k1::SecretKey);
47
48/// Wrap String into HashStr.
49#[derive(Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
50pub struct HashStr(String);
51
52/// Compute the Keccak-256 hash of input bytes.
53pub fn keccak256(bytes: &[u8]) -> [u8; 32] {
54    use tiny_keccak::Hasher;
55    use tiny_keccak::Keccak;
56    let mut output = [0u8; 32];
57    let mut hasher = Keccak::v256();
58    hasher.update(bytes);
59    hasher.finalize(&mut output);
60    output
61}
62
63impl HashStr {
64    pub fn new<T: Into<String>>(s: T) -> Self {
65        HashStr(s.into())
66    }
67
68    /// Compute the SHA-1 digest of raw bytes and encode it as lowercase hex.
69    pub fn from_bytes(bytes: &[u8]) -> Self {
70        let mut hasher = Sha1::new();
71        hasher.update(bytes);
72        HashStr(hex::encode(hasher.finalize()))
73    }
74
75    pub fn inner(&self) -> String {
76        self.0.clone()
77    }
78}
79
80impl Deref for SecretKey {
81    type Target = libsecp256k1::SecretKey;
82    fn deref(&self) -> &Self::Target {
83        &self.0
84    }
85}
86
87impl From<SecretKey> for libsecp256k1::SecretKey {
88    fn from(key: SecretKey) -> Self {
89        *key.deref()
90    }
91}
92
93impl TryFrom<PublicKey<33>> for libsecp256k1::PublicKey {
94    type Error = Error;
95    fn try_from(key: PublicKey<33>) -> Result<Self> {
96        let data: [u8; 33] = key.0;
97        Self::parse_compressed(&data).map_err(|_| Error::ECDSAPublicKeyBadFormat)
98    }
99}
100
101impl TryFrom<PublicKey<33>> for ed25519_dalek::VerifyingKey {
102    type Error = Error;
103    fn try_from(key: PublicKey<33>) -> Result<Self> {
104        // pubkey[0] == 0
105        let [_, bytes @ ..] = key.0;
106        Self::from_bytes(&bytes).map_err(|_| Error::EdDSAPublicKeyBadFormat)
107    }
108}
109
110impl AffineCoordinates for PublicKey<33> {
111    type FieldRepr = GenericArray<u8, U32>;
112
113    fn x(&self) -> Self::FieldRepr {
114        let [_, x @ ..] = self.0;
115        GenericArray::<u8, U32>::from(x)
116    }
117
118    fn y_is_odd(&self) -> subtle::Choice {
119        let [prefix, ..] = self.0;
120        match prefix {
121            2u8 => Choice::from(1),
122            3u8 => Choice::from(0),
123            _ => Choice::from(0),
124        }
125    }
126}
127
128impl PublicKey<33> {
129    /// Map a PublicKey into secp256r1 affine point,
130    /// This function is an constant-time cryptographic implementations
131    pub fn ct_into_secp256r1_affine(self) -> CtOption<primeorder::AffinePoint<NistP256>> {
132        primeorder::AffinePoint::<NistP256>::decompress(&self.x(), self.y_is_odd())
133    }
134
135    /// Map a PublicKey into secp256r1 public key,
136    /// This function is an constant-time cryptographic implementations
137    pub fn ct_try_into_secp256r1_pubkey(self) -> CtOption<Result<ecdsa::VerifyingKey<NistP256>>> {
138        let opt_affine: CtOption<primeorder::AffinePoint<NistP256>> =
139            self.ct_into_secp256r1_affine();
140        opt_affine.and_then(|affine| {
141            let ret =
142                ecdsa::VerifyingKey::<NistP256>::from_affine(affine).map_err(Error::ECDSAError);
143            match ret {
144                Ok(_r) => CtOption::new(ret, Choice::from(1)),
145                Err(_) => CtOption::new(ret, Choice::from(0)),
146            }
147        })
148    }
149}
150
151impl From<SecretKey> for FieldBytes<NistP256> {
152    fn from(val: SecretKey) -> Self {
153        GenericArray::<u8, U32>::from(val.ser())
154    }
155}
156
157impl From<ed25519_dalek::VerifyingKey> for PublicKey<33> {
158    fn from(key: ed25519_dalek::VerifyingKey) -> Self {
159        // [u8;32] here
160        // ref: https://docs.rs/ed25519-dalek/latest/ed25519_dalek/struct.VerifyingKey.html
161        let mut data = [0u8; 33];
162        let key_bytes = key.to_bytes();
163        if let Some(suffix) = data.get_mut(1..) {
164            suffix.copy_from_slice(&key_bytes);
165        }
166        Self(data)
167    }
168}
169
170impl TryFrom<PublicKey<33>> for libsecp256k1::curve::Affine {
171    type Error = Error;
172    fn try_from(key: PublicKey<33>) -> Result<Self> {
173        Ok(TryInto::<libsecp256k1::PublicKey>::try_into(key)?.into())
174    }
175}
176
177impl TryFrom<libsecp256k1::curve::Affine> for PublicKey<33> {
178    type Error = Error;
179    fn try_from(a: libsecp256k1::curve::Affine) -> Result<Self> {
180        let pubkey: libsecp256k1::PublicKey = a.try_into().map_err(|_| Error::InvalidPublicKey)?;
181        Ok(pubkey.into())
182    }
183}
184
185impl From<SecretKey> for libsecp256k1::curve::Scalar {
186    fn from(key: SecretKey) -> libsecp256k1::curve::Scalar {
187        key.0.into()
188    }
189}
190
191impl From<libsecp256k1::SecretKey> for SecretKey {
192    fn from(key: libsecp256k1::SecretKey) -> Self {
193        Self(key)
194    }
195}
196
197impl From<libsecp256k1::PublicKey> for PublicKey<33> {
198    fn from(key: libsecp256k1::PublicKey) -> Self {
199        Self(key.serialize_compressed())
200    }
201}
202
203impl From<SecretKey> for PublicKey<33> {
204    fn from(secret_key: SecretKey) -> Self {
205        libsecp256k1::PublicKey::from_secret_key(&secret_key.0).into()
206    }
207}
208
209impl<T> From<T> for HashStr
210where T: Into<String>
211{
212    fn from(s: T) -> Self {
213        let inputs = s.into();
214        HashStr::from_bytes(inputs.as_bytes())
215    }
216}
217
218impl TryFrom<&str> for SecretKey {
219    type Error = Error;
220    fn try_from(s: &str) -> Result<Self> {
221        let key = hex::decode(s)?;
222        let key_arr: [u8; 32] = key.as_slice().try_into()?;
223        Ok(libsecp256k1::SecretKey::parse(&key_arr)?.into())
224    }
225}
226
227impl std::str::FromStr for SecretKey {
228    type Err = Error;
229
230    fn from_str(s: &str) -> Result<Self> {
231        Self::try_from(s)
232    }
233}
234
235#[allow(clippy::to_string_trait_impl)]
236impl ToString for SecretKey {
237    fn to_string(&self) -> String {
238        hex::encode(self.0.serialize())
239    }
240}
241
242struct SecretKeyVisitor;
243
244impl<'de> serde::de::Visitor<'de> for SecretKeyVisitor {
245    type Value = SecretKey;
246
247    fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
248        formatter.write_str("SecretKey deserializer")
249    }
250    fn visit_str<E>(self, value: &str) -> std::result::Result<Self::Value, E>
251    where E: serde::de::Error {
252        SecretKey::from_str(value).map_err(|e| serde::de::Error::custom(e))
253    }
254}
255
256impl<'de> Deserialize<'de> for SecretKey {
257    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
258    where D: serde::Deserializer<'de> {
259        deserializer.deserialize_str(SecretKeyVisitor)
260    }
261}
262
263impl Serialize for SecretKey {
264    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
265    where S: serde::Serializer {
266        serializer.serialize_str(self.to_string().as_str())
267    }
268}
269
270fn public_key_address(pubkey: &PublicKey<33>) -> PublicKeyAddress {
271    let hash = match TryInto::<libsecp256k1::PublicKey>::try_into(*pubkey) {
272        // if pubkey is ecdsa key
273        Ok(pk) => {
274            let data = pk.serialize();
275            debug_assert_eq!(data[0], 0x04);
276            keccak256(&data[1..])
277        }
278        // if pubkey is eddsa key
279        Err(_) => keccak256(&pubkey.0[1..]),
280    };
281    PublicKeyAddress::from_slice(&hash[12..])
282}
283
284fn secret_key_address(secret_key: &SecretKey) -> PublicKeyAddress {
285    let public_key = libsecp256k1::PublicKey::from_secret_key(secret_key);
286    public_key_address(&public_key.into())
287}
288
289impl SecretKey {
290    pub fn random() -> Self {
291        let mut rng = Hc128Rng::from_entropy();
292        Self(libsecp256k1::SecretKey::random(&mut rng))
293    }
294
295    pub fn address(&self) -> PublicKeyAddress {
296        secret_key_address(self)
297    }
298
299    pub fn sign(&self, message: &str) -> SigBytes {
300        self.sign_raw(message.as_bytes())
301    }
302
303    pub fn sign_raw(&self, message: &[u8]) -> SigBytes {
304        let message_hash = keccak256(message);
305        self.sign_hash(&message_hash)
306    }
307
308    pub fn sign_hash(&self, message_hash: &[u8; 32]) -> SigBytes {
309        let (signature, recover_id) =
310            libsecp256k1::sign(&libsecp256k1::Message::parse(message_hash), self);
311        let mut sig_bytes: SigBytes = [0u8; 65];
312        sig_bytes[0..32].copy_from_slice(&signature.r.b32());
313        sig_bytes[32..64].copy_from_slice(&signature.s.b32());
314        sig_bytes[64] = recover_id.serialize();
315        sig_bytes
316    }
317
318    pub fn pubkey(&self) -> PublicKey<33> {
319        libsecp256k1::PublicKey::from_secret_key(&(*self).into()).into()
320    }
321
322    pub fn ser(&self) -> [u8; 32] {
323        self.0.serialize()
324    }
325}
326
327impl PublicKey<33> {
328    pub fn address(&self) -> PublicKeyAddress {
329        public_key_address(self)
330    }
331}
332
333/// Recover PublicKey from RawMessage using signature.
334pub fn recover<S>(message: &[u8], signature: S) -> Result<PublicKey<33>>
335where S: AsRef<[u8]> {
336    let sig_bytes: SigBytes = signature.as_ref().try_into()?;
337    let message_hash: [u8; 32] = keccak256(message);
338    recover_hash(&message_hash, &sig_bytes)
339}
340
341/// Recover PublicKey from HashMessage using signature.
342pub fn recover_hash(message_hash: &[u8; 32], sig: &[u8; 65]) -> Result<PublicKey<33>> {
343    let r_s_signature: [u8; 64] = sig[..64].try_into()?;
344    let recovery_id: u8 = sig[64];
345    Ok(libsecp256k1::recover(
346        &libsecp256k1::Message::parse(message_hash),
347        &libsecp256k1::Signature::parse_standard(&r_s_signature)
348            .map_err(|e| Error::Libsecp256k1SignatureParseStandard(e.to_string()))?,
349        &libsecp256k1::RecoveryId::parse(recovery_id)
350            .map_err(|e| Error::Libsecp256k1RecoverIdParse(e.to_string()))?,
351    )
352    .map_err(|_| Error::Libsecp256k1Recover)?
353    .into())
354}
355
356#[cfg(test)]
357pub mod tests {
358    use hex::FromHex;
359
360    use super::*;
361
362    #[test]
363    fn test_parse_to_string_with_sha10x00() {
364        let s = "65860affb4b570dba06db294aa7c676f68e04a5bf2721243ad3cbc05a79c68c0";
365        let t: HashStr = s.into();
366        assert_eq!(t.0.len(), 40);
367    }
368
369    #[test]
370    fn test_parse_to_string_with_sha10x01() {
371        let s = "hello";
372        let t: HashStr = s.into();
373        assert_eq!(t.0.len(), 40);
374    }
375
376    #[test]
377    fn test_metamask_sign_for_debug() {
378        let key = &SecretKey::try_from(
379            "65860affb4b570dba06db294aa7c676f68e04a5bf2721243ad3cbc05a79c68c0",
380        )
381        .unwrap();
382        let sig_hash =
383            Vec::from_hex("4a5c5d454721bbbb25540c3317521e71c373ae36458f960d2ad46ef088110e95")
384                .unwrap();
385        let msg = "test";
386        // https://docs.rs/web3/latest/src/web3/signing.rs.html#221
387        let prefix_msg_ret = "\x19Ethereum Signed Message:\n4test"
388            .to_string()
389            .into_bytes();
390        let mut prefix_msg = format!("\x19Ethereum Signed Message:\n{}", msg.len()).into_bytes();
391        prefix_msg.extend_from_slice(msg.as_bytes());
392        assert_eq!(
393            prefix_msg,
394            prefix_msg_ret,
395            "{}",
396            String::from_utf8(prefix_msg.clone()).unwrap()
397        );
398        //        let hash = hash_message(msg.as_bytes()).0;
399        assert_eq!(keccak256(prefix_msg_ret.as_slice()), sig_hash.as_slice());
400        // window.ethereum.request({method: "personal_sign", params: ["test", "0x11E807fcc88dD319270493fB2e822e388Fe36ab0"]})
401        let metamask_sig = Vec::from_hex("724fc31d9272b34d8406e2e3a12a182e72510b008de6cc44684577e31e20d9626fb760d6a0badd79a6cf4cd56b2fc0fbd60c438b809aa7d29bfb598c13e7b50e1b").unwrap();
402        assert_eq!(metamask_sig.len(), 65);
403        let h: [u8; 32] = sig_hash.as_slice().try_into().unwrap();
404        let (_, recover_id) = libsecp256k1::sign(&libsecp256k1::Message::parse(&h), key);
405        assert_eq!(recover_id.serialize(), 0);
406        let mut sig = key.sign_raw(&prefix_msg);
407        sig[64] = 27;
408        assert_eq!(sig, metamask_sig.as_slice());
409    }
410
411    #[test]
412    fn test_recover() {
413        let key = SecretKey::random();
414        let pubkey1 = key.pubkey();
415        let pubkey2 = recover("hello".as_bytes(), key.sign("hello")).unwrap();
416        assert_eq!(pubkey1, pubkey2);
417    }
418
419    pub fn gen_ordered_keys(n: usize) -> Vec<SecretKey> {
420        let mut keys = Vec::from_iter(std::iter::repeat_with(SecretKey::random).take(n));
421        keys.sort_by(|a, b| {
422            if a.address() < b.address() {
423                std::cmp::Ordering::Less
424            } else {
425                std::cmp::Ordering::Greater
426            }
427        });
428        keys
429    }
430}