simperby_core/
crypto.rs

1//! A set of types and functions related to cryptography, that are widely used in the entire Simperby project.
2use secp256k1::{
3    ecdsa::{RecoverableSignature, RecoveryId},
4    Message, Secp256k1, SecretKey,
5};
6use serde::{ser::SerializeTuple, Deserialize, Serialize};
7use sha3::{Digest, Keccak256};
8use std::fmt;
9use thiserror::Error;
10
11const EVM_EC_RECOVERY_OFFSET: u8 = 27;
12
13#[derive(Error, Debug, Clone)]
14pub enum CryptoError {
15    /// When the data format is not valid.
16    #[error("invalid format: {0}")]
17    InvalidFormat(String),
18    #[error("verification failed")]
19    VerificationFailed,
20}
21
22type Error = CryptoError;
23
24pub trait ToHash256 {
25    fn to_hash256(&self) -> Hash256;
26}
27
28#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Copy)]
29pub struct HexSerializedBytes<const N: usize> {
30    pub data: [u8; N],
31}
32
33impl<const N: usize> HexSerializedBytes<N> {
34    const fn zero() -> Self {
35        Self { data: [0; N] }
36    }
37}
38
39impl<const N: usize> Serialize for HexSerializedBytes<N> {
40    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
41    where
42        S: serde::ser::Serializer,
43    {
44        if serializer.is_human_readable() {
45            serializer.serialize_str(hex::encode(self.data).as_str())
46        } else {
47            let mut seq = serializer.serialize_tuple(N)?;
48            for e in self.data {
49                seq.serialize_element(&e)?;
50            }
51            seq.end()
52        }
53    }
54}
55
56impl<const N: usize> fmt::Debug for HexSerializedBytes<N> {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(f, "{}", hex::encode(self.data).as_str())
59    }
60}
61
62impl<const N: usize> fmt::Display for HexSerializedBytes<N> {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        write!(f, "{}", hex::encode(self.data).as_str())
65    }
66}
67
68impl<'de, const N: usize> Deserialize<'de> for HexSerializedBytes<N> {
69    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
70    where
71        D: serde::de::Deserializer<'de>,
72    {
73        if deserializer.is_human_readable() {
74            let s: String = Deserialize::deserialize(deserializer)?;
75            let bytes = hex::decode(s).map_err(|e| serde::de::Error::custom(e.to_string()))?;
76            if bytes.len() != N {
77                return Err(serde::de::Error::custom("invalid length"));
78            }
79            let mut data = [0; N];
80            data.copy_from_slice(&bytes);
81            Ok(HexSerializedBytes { data })
82        } else {
83            struct V<const M: usize>;
84            impl<'de, const M: usize> serde::de::Visitor<'de> for V<M> {
85                type Value = [u8; M];
86
87                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
88                    formatter.write_str("byte")
89                }
90
91                fn visit_seq<S: serde::de::SeqAccess<'de>>(
92                    self,
93                    mut seq: S,
94                ) -> Result<Self::Value, S::Error> {
95                    let mut data = [0; M];
96                    for (i, x) in data.iter_mut().enumerate() {
97                        *x = seq
98                            .next_element()?
99                            .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;
100                    }
101                    Ok(data)
102                }
103            }
104            let data = deserializer.deserialize_tuple(N, V::<N>)?;
105            Ok(HexSerializedBytes { data })
106        }
107    }
108}
109
110#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
111pub struct HexSerializedVec {
112    pub data: Vec<u8>,
113}
114
115impl From<Vec<u8>> for HexSerializedVec {
116    fn from(data: Vec<u8>) -> Self {
117        Self { data }
118    }
119}
120
121impl<const N: usize> From<[u8; N]> for HexSerializedVec {
122    fn from(data: [u8; N]) -> Self {
123        Self {
124            data: data.to_vec(),
125        }
126    }
127}
128
129impl<const N: usize> From<HexSerializedBytes<N>> for HexSerializedVec {
130    fn from(data: HexSerializedBytes<N>) -> Self {
131        Self {
132            data: data.data.to_vec(),
133        }
134    }
135}
136
137impl Serialize for HexSerializedVec {
138    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139    where
140        S: serde::ser::Serializer,
141    {
142        if serializer.is_human_readable() {
143            serializer.serialize_str(hex::encode(&self.data).as_str())
144        } else {
145            let mut seq = serializer.serialize_tuple(self.data.len())?;
146            for e in &self.data {
147                seq.serialize_element(&e)?;
148            }
149            seq.end()
150        }
151    }
152}
153
154impl fmt::Debug for HexSerializedVec {
155    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156        write!(f, "{}", hex::encode(&self.data).as_str())
157    }
158}
159
160impl fmt::Display for HexSerializedVec {
161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162        write!(f, "{}", hex::encode(&self.data).as_str())
163    }
164}
165
166impl<'de> Deserialize<'de> for HexSerializedVec {
167    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
168    where
169        D: serde::de::Deserializer<'de>,
170    {
171        if deserializer.is_human_readable() {
172            let s: String = Deserialize::deserialize(deserializer)?;
173            let data = hex::decode(s).map_err(|e| serde::de::Error::custom(e.to_string()))?;
174            Ok(HexSerializedVec { data })
175        } else {
176            let data: Vec<u8> = Deserialize::deserialize(deserializer)?;
177            Ok(HexSerializedVec { data })
178        }
179    }
180}
181
182/// A cryptographic hash.
183#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Copy, Serialize, Deserialize)]
184#[serde(transparent)]
185pub struct Hash256 {
186    pub hash: HexSerializedBytes<32>,
187}
188
189impl Hash256 {
190    pub const fn zero() -> Self {
191        Hash256 {
192            hash: HexSerializedBytes::zero(),
193        }
194    }
195
196    /// Hashes the given data.
197    pub fn hash(data: impl AsRef<[u8]>) -> Self {
198        let mut hasher = Keccak256::new();
199        hasher.update(data);
200        let result = hasher.finalize();
201        Hash256 {
202            hash: HexSerializedBytes {
203                data: result.as_slice().try_into().unwrap(),
204            },
205        }
206    }
207
208    pub fn from_array(data: [u8; 32]) -> Self {
209        Hash256 {
210            hash: HexSerializedBytes { data },
211        }
212    }
213
214    pub fn aggregate(&self, other: &Self) -> Self {
215        Self::hash([self.hash.data, other.hash.data].concat())
216    }
217}
218
219impl std::convert::AsRef<[u8]> for Hash256 {
220    fn as_ref(&self) -> &[u8] {
221        &self.hash.data
222    }
223}
224
225impl fmt::Display for Hash256 {
226    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227        write!(f, "{}", self.hash)
228    }
229}
230
231/// A cryptographic signature.
232#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Serialize, Deserialize)]
233#[serde(transparent)]
234pub struct Signature {
235    signature: HexSerializedBytes<65>,
236}
237
238impl Signature {
239    pub const fn zero() -> Self {
240        Signature {
241            signature: HexSerializedBytes { data: [0; 65] },
242        }
243    }
244
245    /// Creates a new signature from the given data and keys.
246    pub fn sign(data: Hash256, private_key: &PrivateKey) -> Result<Self, Error> {
247        let private_key = secp256k1::SecretKey::from_slice(&private_key.key.data)
248            .map_err(|_| Error::InvalidFormat("private key: [omitted]".to_owned()))?;
249        let message = Message::from_slice(data.as_ref()).unwrap();
250        let (recovery_id, rs) = Secp256k1::signing_only()
251            .sign_ecdsa_recoverable(&message, &private_key)
252            .serialize_compact();
253        let v = recovery_id.to_i32() as u8;
254        let bytes: [u8; 65] = {
255            let mut whole: [u8; 65] = [0; 65];
256            let (left, right) = whole.split_at_mut(rs.len());
257            left.copy_from_slice(&rs);
258            right.copy_from_slice(&[v + EVM_EC_RECOVERY_OFFSET; 1]);
259            whole
260        };
261        Ok(Signature {
262            signature: HexSerializedBytes { data: bytes },
263        })
264    }
265
266    /// Verifies the signature against the given data and public key.
267    pub fn verify(&self, data: Hash256, public_key: &PublicKey) -> Result<(), Error> {
268        let signature = secp256k1::ecdsa::Signature::from_compact(&self.signature.data[0..64])
269            .map_err(|_| Error::InvalidFormat(format!("signature: {self}")))?;
270        let public_key = secp256k1::PublicKey::from_slice(&public_key.key.data)
271            .map_err(|_| Error::InvalidFormat(format!("public_key: {public_key}")))?;
272        let message = Message::from_slice(data.as_ref()).unwrap();
273        Secp256k1::verification_only()
274            .verify_ecdsa(&message, &signature, &public_key)
275            .map_err(|_| Error::VerificationFailed)
276    }
277
278    /// Recover a public key from the given signature.
279    pub fn recover(&self, data: Hash256) -> Result<PublicKey, Error> {
280        let message = Message::from_slice(data.as_ref()).unwrap();
281        let recovery_id = RecoveryId::from_i32(
282            self.signature.data[64..65][0] as i32 - EVM_EC_RECOVERY_OFFSET as i32,
283        )
284        .map_err(|e| Error::InvalidFormat(e.to_string()))?;
285        if recovery_id.to_i32() != 0 && recovery_id.to_i32() != 1 {
286            return Err(Error::VerificationFailed);
287        }
288        let signature =
289            RecoverableSignature::from_compact(&self.signature.data[0..64], recovery_id)
290                .map_err(|e| Error::InvalidFormat(e.to_string()))?;
291        let secp = Secp256k1::new();
292        let public_key = secp
293            .recover_ecdsa(&message, &signature)
294            .map_err(|e| Error::InvalidFormat(e.to_string()))?
295            .serialize();
296        PublicKey::from_array(public_key)
297    }
298
299    /// Constructs a signature from the given bytes, but does not verify its validity.
300    pub fn from_array(bytes: [u8; 65]) -> Self {
301        Signature {
302            signature: HexSerializedBytes { data: bytes },
303        }
304    }
305}
306
307/// A signature that is explicitly marked with the type of the signed data.
308///
309/// This implies that the signature is created on `Hash256::hash(serde_spb::to_vec(T).unwrap())`.
310#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Serialize, Deserialize)]
311pub struct TypedSignature<T> {
312    signature: Signature,
313    signer: PublicKey,
314    #[serde(skip)]
315    _mark: std::marker::PhantomData<T>,
316}
317
318impl<T: ToHash256> TypedSignature<T> {
319    /// Creates a new signature from the given data and keys.
320    pub fn sign(data: &T, private_key: &PrivateKey) -> Result<Self, Error> {
321        let data = data.to_hash256();
322        Signature::sign(data, private_key).map(|signature| TypedSignature {
323            signature,
324            signer: private_key.public_key(),
325            _mark: std::marker::PhantomData,
326        })
327    }
328
329    pub fn new(signature: Signature, signer: PublicKey) -> Self {
330        TypedSignature {
331            signature,
332            signer,
333            _mark: std::marker::PhantomData,
334        }
335    }
336
337    pub fn signer(&self) -> &PublicKey {
338        &self.signer
339    }
340
341    /// Verifies the signature against the given data and public key.
342    pub fn verify(&self, data: &T) -> Result<(), Error> {
343        let data = data.to_hash256();
344        self.signature.verify(data, &self.signer)
345    }
346
347    pub fn get_raw_signature(&self) -> Signature {
348        self.signature.clone()
349    }
350}
351
352impl std::convert::AsRef<[u8]> for Signature {
353    fn as_ref(&self) -> &[u8] {
354        &self.signature.data
355    }
356}
357
358impl fmt::Display for Signature {
359    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360        write!(f, "{}", self.signature)
361    }
362}
363
364/// A public key.
365#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Serialize, Deserialize)]
366#[serde(transparent)]
367pub struct PublicKey {
368    key: HexSerializedBytes<65>,
369}
370
371impl std::convert::AsRef<[u8]> for PublicKey {
372    fn as_ref(&self) -> &[u8] {
373        &self.key.data
374    }
375}
376
377impl fmt::Display for PublicKey {
378    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379        write!(f, "{}", self.key)
380    }
381}
382
383impl PublicKey {
384    pub fn zero() -> Self {
385        Self {
386            key: HexSerializedBytes::zero(),
387        }
388    }
389
390    pub fn from_array_uncompressed(array: [u8; 65]) -> Result<Self, Error> {
391        let key = secp256k1::PublicKey::from_slice(array.as_ref())
392            .map_err(|_| Error::InvalidFormat(format!("given bytes: {}", hex::encode(array))))?
393            .serialize_uncompressed();
394        Ok(PublicKey {
395            key: HexSerializedBytes { data: key },
396        })
397    }
398
399    pub fn from_array(array: [u8; 33]) -> Result<Self, Error> {
400        let key = secp256k1::PublicKey::from_slice(array.as_ref())
401            .map_err(|_| Error::InvalidFormat(format!("given bytes: {}", hex::encode(array))))?
402            .serialize_uncompressed();
403        Ok(PublicKey {
404            key: HexSerializedBytes { data: key },
405        })
406    }
407}
408
409/// A private key.
410#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Serialize, Deserialize)]
411#[serde(transparent)]
412pub struct PrivateKey {
413    pub key: HexSerializedBytes<32>,
414}
415
416impl std::convert::AsRef<[u8]> for PrivateKey {
417    fn as_ref(&self) -> &[u8] {
418        &self.key.data
419    }
420}
421
422impl PrivateKey {
423    pub fn zero() -> Self {
424        Self {
425            key: HexSerializedBytes::zero(),
426        }
427    }
428
429    pub fn from_array(array: [u8; 32]) -> Result<Self, Error> {
430        let key = secp256k1::SecretKey::from_slice(&array)
431            .map_err(|_| Error::InvalidFormat(format!("given bytes: {}", hex::encode(array))))?
432            .secret_bytes();
433        Ok(PrivateKey {
434            key: HexSerializedBytes { data: key },
435        })
436    }
437
438    pub fn public_key(&self) -> PublicKey {
439        let private_key = SecretKey::from_slice(&self.key.data).expect("invalid private key");
440        let secp = Secp256k1::new();
441        let public_key = private_key.public_key(&secp);
442        PublicKey::from_array(public_key.serialize()).expect("invalid public key")
443    }
444}
445
446/// Checks whether the given public and private keys match.
447pub fn check_keypair_match(public_key: &PublicKey, private_key: &PrivateKey) -> Result<(), Error> {
448    let msg = "Some Random Message".as_bytes();
449    let signature = Signature::sign(Hash256::hash(msg), private_key)?;
450    signature.verify(Hash256::hash(msg), public_key)
451}
452
453/// Generates a new keypair using the seed.
454pub fn generate_keypair(seed: impl AsRef<[u8]>) -> (PublicKey, PrivateKey) {
455    let mut seed_: [u8; 32] = [0; 32];
456    for (i, x) in Hash256::hash(seed).as_ref()[0..32].iter().enumerate() {
457        seed_[i] = *x;
458    }
459    use secp256k1::rand::SeedableRng;
460    let mut rng = secp256k1::rand::rngs::StdRng::from_seed(seed_);
461    let secp = Secp256k1::new();
462    let (private_key, public_key) = secp.generate_keypair(&mut rng);
463    (
464        PublicKey::from_array(public_key.serialize()).expect("invalid public key"),
465        PrivateKey::from_array(private_key.secret_bytes()).expect("invalid private key"),
466    )
467}
468
469/// Generates a new keypair randomly
470pub fn generate_keypair_random() -> (PublicKey, PrivateKey) {
471    use secp256k1::rand::SeedableRng;
472    let mut rng = secp256k1::rand::rngs::StdRng::from_entropy();
473    let secp = Secp256k1::new();
474    let (private_key, public_key) = secp.generate_keypair(&mut rng);
475    (
476        PublicKey::from_array(public_key.serialize()).expect("invalid public key"),
477        PrivateKey::from_array(private_key.secret_bytes()).expect("invalid private key"),
478    )
479}
480
481#[cfg(test)]
482mod tests {
483    use super::*;
484    use crate::serde_spb;
485
486    #[test]
487    fn pretty_format() {
488        let hash = Hash256::hash("hello world");
489        assert_eq!(hash.to_string().len(), 64);
490        let encoded = serde_spb::to_string(&hash).unwrap();
491        assert_eq!(encoded.len(), 66);
492        let (public_key, private_key) = generate_keypair("hello world");
493        let signature = Signature::sign(hash, &private_key).unwrap();
494        let encoded = serde_spb::to_string(&signature).unwrap();
495        assert_eq!(encoded.len(), 132);
496        let encoded = serde_spb::to_string(&public_key).unwrap();
497        assert_eq!(encoded.len(), 132);
498        let encoded = serde_spb::to_string(&private_key).unwrap();
499        assert_eq!(encoded.len(), 66);
500    }
501
502    #[test]
503    fn hash_encode_decode() {
504        let hash = Hash256::hash("hello world");
505        let encoded = serde_spb::to_string(&hash).unwrap();
506        let decoded = serde_spb::from_str(&encoded).unwrap();
507        assert_eq!(hash, decoded);
508    }
509
510    #[test]
511    fn hash_encode_decode_zero() {
512        let hash = Hash256::zero();
513        let encoded = serde_spb::to_string(&hash).unwrap();
514        let decoded = serde_spb::from_str(&encoded).unwrap();
515        assert_eq!(hash, decoded);
516    }
517
518    #[test]
519    fn key_encode_decode() {
520        let (public_key, private_key) = generate_keypair("hello world");
521        let encoded = serde_spb::to_string(&public_key).unwrap();
522        let decoded = serde_spb::from_str(&encoded).unwrap();
523        assert_eq!(public_key, decoded);
524        let encoded = serde_spb::to_string(&private_key).unwrap();
525        let decoded = serde_spb::from_str(&encoded).unwrap();
526        assert_eq!(private_key, decoded);
527    }
528
529    #[test]
530    fn signature_encode_decode() {
531        let (public_key, private_key) = generate_keypair("hello world");
532        let signature = Signature::sign(Hash256::hash("hello world"), &private_key).unwrap();
533        let encoded = serde_spb::to_string(&signature).unwrap();
534        let decoded = serde_spb::from_str(&encoded).unwrap();
535        assert_eq!(signature, decoded);
536        signature
537            .verify(Hash256::hash("hello world"), &public_key)
538            .unwrap();
539    }
540
541    #[test]
542    fn signature_verify() {
543        let (public_key, private_key) = generate_keypair("hello world");
544        let signature = Signature::sign(Hash256::hash("hello world"), &private_key).unwrap();
545        signature
546            .verify(Hash256::hash("hello world"), &public_key)
547            .unwrap();
548    }
549
550    #[test]
551    fn signature_verify_invalid() {
552        let (public_key, private_key) = generate_keypair("hello world");
553        let signature = Signature::sign(Hash256::hash("hello world2"), &private_key).unwrap();
554        signature
555            .verify(Hash256::hash("hello world"), &public_key)
556            .unwrap_err();
557    }
558
559    #[test]
560    fn compressed() {
561        let public_key = "0479c0e6973634b801da80fdf9274c13e327880e6360ca7735877f16e6a903c811afc2f0bb2c17de59110b022956dee0d625a694132b0da03fbba8ccdca219657c";
562        let private_key = "f54a850441ef31968ffda8ea2ebdd831f0764c6bd52cd5185c8cb35d407201a4";
563        let public_key = hex::decode(public_key).unwrap();
564        let private_key = hex::decode(private_key).unwrap();
565        let public_key =
566            PublicKey::from_array_uncompressed(public_key.as_slice().try_into().unwrap()).unwrap();
567        let private_key =
568            PrivateKey::from_array(private_key.as_slice().try_into().unwrap()).unwrap();
569        check_keypair_match(&public_key, &private_key).unwrap();
570    }
571
572    #[test]
573    fn recover_public_key() {
574        let (public_key, private_key) = generate_keypair("hello world");
575        let signature = Signature::sign(Hash256::hash("hello world2"), &private_key).unwrap();
576        let recovered = signature.recover(Hash256::hash("hello world2")).unwrap();
577        assert_eq!(
578            hex::encode(public_key.as_ref()),
579            hex::encode(recovered.as_ref())
580        );
581    }
582}