bn254/
ecdsa.rs

1use bn::{pairing_batch, Group, Gt, G1, G2};
2
3use crate::{
4    error::{Error, Result},
5    hash,
6    PrivateKey,
7    PublicKey,
8    PublicKeyG1,
9    Signature,
10};
11
12/// ECDSA with curve `bn254`.
13pub struct ECDSA;
14
15impl ECDSA {
16    /// Function to sign a message given a private key (as a point in [G1]).
17    ///
18    /// # Arguments
19    ///
20    /// * `message`     - The message bytes
21    /// * `private_key` - The private key
22    ///
23    /// # Returns
24    ///
25    /// * If successful, the signature as a [G1] point
26    pub fn sign<T: AsRef<[u8]>>(message: T, private_key: &PrivateKey) -> Result<Signature> {
27        // 1. Hash_to_try_and_increment --> H(m) as point in G1 (only if it exists)
28        let hash_point = hash::hash_to_try_and_increment(message)?;
29
30        // 2. Multiply hash_point times private_key --> Signature in G1
31        let g1_point = hash_point * private_key.into();
32
33        // 3. Return signature
34        Ok(Signature(g1_point))
35    }
36
37    /// Function to verify a signature (point in [G1]) given a public key
38    /// (point in [G2]).
39    ///
40    /// # Arguments
41    ///
42    /// * `message`     - The message to be signed
43    /// * `signature`   - The signature
44    /// * `public_key`  - The public key
45    ///
46    /// # Returns
47    ///
48    /// * If successful, `Ok(())`; otherwise [Error]
49    pub fn verify<T: AsRef<[u8]>>(message: T, signature: &Signature, public_key: &PublicKey) -> Result<()> {
50        // Pairing batch with one negated point
51        let mut vals = Vec::new();
52        // First pairing input: e(H(m), PubKey)
53        let hash_point = hash::hash_to_try_and_increment(message)?;
54        vals.push((hash_point, public_key.into()));
55        // Second pairing input:  e(-Signature,G2::one())
56        vals.push((signature.into(), -G2::one()));
57        let mul = pairing_batch(&vals);
58
59        if mul == Gt::one() {
60            Ok(())
61        } else {
62            Err(Error::VerificationFailed)
63        }
64    }
65}
66
67/// Function to check if 2 Public Keys in [G1] and [G2] are valid
68///
69/// # Arguments
70///
71/// * `message`     - The message to be signed
72/// * `signature`   - The signature
73/// * `public_key`  - The public key
74///
75/// # Returns
76///
77/// * If successful, `Ok(())`; otherwise [Error]
78pub fn check_public_keys(public_key_g2: &PublicKey, public_key_g1: &PublicKeyG1) -> Result<()> {
79    // Pairing batch with one negated point
80    let vals = vec![
81        // First pairing input: e(H(m), PubKey)
82        (G1::one(), public_key_g2.into()),
83        // Second pairing input:  e(PubKey_G1, G2::one())
84        (public_key_g1.into(), -G2::one()),
85    ];
86    let mul = pairing_batch(&vals);
87
88    if mul == Gt::one() {
89        Ok(())
90    } else {
91        Err(Error::VerificationFailed)
92    }
93}