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