cry/schnorr/
mod.rs

1//! Schnorr signature and schnorr multi-signature.
2
3use crate::key::{BarePublicKey, Keypair};
4use crate::primitive::bytes::{Bytes, FromBytesRef};
5use crate::primitive::point::{DisLogPoint, Point};
6use crate::primitive::scalar::{Scalar, ScalarNumber};
7use digest::Digest;
8
9/// Schorr Signature
10#[allow(non_snake_case)]
11#[derive(Debug, Clone)]
12pub struct Signature<P: DisLogPoint<Scalar = S>, S: ScalarNumber> {
13    pub R: Point<P>,
14    pub s: Scalar<S>,
15}
16
17impl<P: DisLogPoint<Scalar = S>, S: ScalarNumber> Signature<P, S> {
18    /// Create signature from keypair and message.
19    #[allow(non_snake_case)]
20    pub fn sign<D: Digest, M: AsRef<[u8]>>(sk: &Keypair<P, S>, message: &M) -> Signature<P, S> {
21        let mut hasher_r = D::new();
22        hasher_r.update(&sk.code);
23        hasher_r.update(message.as_ref());
24        let r = hasher_r.finalize();
25        let r_scalar = Scalar::from_bytes_ref(&r).unwrap();
26        let R = Point::basepoint() * &r_scalar;
27
28        let mut hasher_s = D::new();
29        hasher_s.update(R.to_bytes());
30        hasher_s.update(sk.public.to_bytes());
31        hasher_s.update(message.as_ref());
32        let s_bytes = hasher_s.finalize();
33        let a = Scalar::from_bytes_ref(&s_bytes).unwrap();
34
35        let s = r_scalar + a * &sk.secret;
36
37        Signature { R, s }
38    }
39
40    #[allow(non_snake_case)]
41    pub fn sign_multi_party<D: Digest, M: AsRef<[u8]>>(
42        sk: &Keypair<P, S>,
43        rs: &[Point<P>],
44        ps: &[BarePublicKey<P>],
45        message: &M,
46    ) -> (Signature<P, S>, BarePublicKey<P>) {
47        let mut hasher_r = D::new();
48        hasher_r.update(&sk.code);
49        hasher_r.update(message.as_ref());
50        let r_i = hasher_r.finalize();
51        let r_scalar = Scalar::from_bytes_ref(&r_i).unwrap();
52        let R_i = Point::basepoint() * &r_scalar;
53
54        let mut hasher_a_i = D::new();
55        for p in ps {
56            hasher_a_i.update(p.public.to_bytes());
57        }
58        hasher_a_i.update(sk.public.to_bytes());
59        let a_i = hasher_a_i.finalize();
60        let a_scalar = Scalar::from_bytes_ref(&a_i).unwrap();
61
62        let mut R = R_i.clone();
63        for r in rs {
64            R += r;
65        }
66
67        let mut X = Point::zero();
68        for p in ps {
69            X += &p.public;
70        }
71
72        let mut hasher_c = D::new();
73        hasher_c.update(X.to_bytes());
74        hasher_c.update(R.to_bytes());
75        hasher_c.update(message.as_ref());
76        let c = hasher_c.finalize();
77        let c_scalar = Scalar::from_bytes_ref(&c).unwrap();
78
79        let s = r_scalar + c_scalar * a_scalar * &sk.secret;
80        let sign = Signature { R, s };
81        let pk = BarePublicKey { public: X };
82        (sign, pk)
83    }
84
85    pub fn sign_multi_party_complete(&mut self, signatures: &[Self]) {
86        for signature in signatures {
87            assert_eq!(self.R, signature.R);
88            self.s += &signature.s;
89        }
90    }
91
92    /// Verify signature
93    pub fn verify<D: Digest, M: AsRef<[u8]>>(&self, pk: &BarePublicKey<P>, message: &M) -> bool {
94        let s_g = &self.s * Point::<P>::basepoint();
95
96        let mut hasher = D::new();
97        hasher.update(self.R.to_bytes());
98        hasher.update(pk.public.to_bytes());
99        hasher.update(message.as_ref());
100        let s_bytes = hasher.finalize();
101        let a = Scalar::from_bytes_ref(&s_bytes).unwrap();
102
103        let rp = &self.R + a * &pk.public;
104
105        s_g == rp
106    }
107}
108
109#[cfg(test)]
110mod tests {
111
112    use super::*;
113    use crate::ristretto255;
114    use rand::RngCore;
115    use sha3::Sha3_512;
116
117    #[test]
118    fn test_schnorr() {
119        let mut rng = rand::thread_rng();
120        let mut seed = [0u8; 32];
121        rng.fill_bytes(&mut seed);
122        let keypair =
123            Keypair::<ristretto255::Point, ristretto255::Scalar>::new::<Sha3_512>(seed.into());
124        let signature = Signature::sign::<Sha3_512, _>(&keypair, b"asda");
125        let res = signature.verify::<Sha3_512, _>(&keypair.to_bare_public(), b"asda");
126        assert!(res);
127    }
128}