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
129
130
131
132
133
134
135
136
137
138
use crate::{MessageGenerators, PokSignatureProof, Signature};
use bls12_381_plus::{G1Affine, G1Projective, Scalar};
use core::ops::Neg;
use digest::Update;
use ff::Field;
use group::Curve;
use rand_core::{CryptoRng, RngCore};
use signature_core::{error::Error, lib::*};
pub struct PokSignature {
a_prime: G1Projective,
a_bar: G1Projective,
d: G1Projective,
proof1: ProofCommittedBuilder<G1Projective, G1Affine, 2, 2>,
secrets1: [Scalar; 2],
proof2: ProofCommittedBuilder<G1Projective, G1Affine, 130, 130>,
secrets2: Vec<Scalar, 130>,
}
impl PokSignature {
pub fn init(
signature: Signature,
generators: &MessageGenerators,
messages: &[ProofMessage],
mut rng: impl RngCore + CryptoRng,
) -> Result<Self, Error> {
if messages.len() != generators.len() {
return Err(Error::new(1, "mismatched messages with and generators"));
}
let r1 = Scalar::random(&mut rng);
let r2 = Scalar::random(&mut rng);
let r3 = r1.invert().unwrap();
let m = messages
.iter()
.map(|m| m.get_message())
.collect::<Vec<Message, 128>>();
let b = Signature::compute_b(signature.s, m.as_ref(), generators);
let a_prime = signature.a * r1;
let a_bar = b * r1 - a_prime * signature.e;
let d = G1Projective::sum_of_products_in_place(&[b, generators.h0], [r1, r2].as_mut());
let s_prime = signature.s + r2 * r3;
let mut proof1 = ProofCommittedBuilder::<G1Projective, G1Affine, 2, 2>::new(
G1Projective::sum_of_products_in_place,
);
proof1.commit_random(a_prime, &mut rng);
proof1.commit_random(generators.h0, &mut rng);
let secrets1 = [signature.e, r2];
let mut proof2 = ProofCommittedBuilder::<G1Projective, G1Affine, 130, 130>::new(
G1Projective::sum_of_products_in_place,
);
let mut secrets2 = Vec::new();
proof2.commit_random(d.neg(), &mut rng);
secrets2.push(r3).expect("allocate more space");
proof2.commit_random(generators.h0, &mut rng);
secrets2.push(s_prime).expect("allocate more space");
#[allow(clippy::needless_range_loop)]
for i in 0..generators.len() {
match messages[i] {
ProofMessage::Hidden(HiddenMessage::ProofSpecificBlinding(m)) => {
proof2.commit_random(generators.get(i), &mut rng);
secrets2.push(m.0).expect("allocate more space");
}
ProofMessage::Hidden(HiddenMessage::ExternalBlinding(m, e)) => {
proof2.commit(generators.get(i), e.0);
secrets2.push(m.0).expect("allocate more space");
}
_ => {}
}
}
Ok(Self {
a_prime,
a_bar,
d,
proof1,
secrets1,
proof2,
secrets2,
})
}
pub fn add_proof_contribution(&mut self, hasher: &mut impl Update) {
hasher.update(self.a_prime.to_affine().to_uncompressed());
hasher.update(self.a_bar.to_affine().to_uncompressed());
hasher.update(self.d.to_affine().to_uncompressed());
self.proof1.add_challenge_contribution(hasher);
self.proof2.add_challenge_contribution(hasher);
}
pub fn generate_proof(self, challenge: Challenge) -> Result<PokSignatureProof, Error> {
let proof1 = self
.proof1
.generate_proof(challenge.0, self.secrets1.as_ref())?;
let proofs1 = [Challenge(proof1[0]), Challenge(proof1[1])];
let proofs2: Vec<Challenge, 130> = self
.proof2
.generate_proof(challenge.0, self.secrets2.as_ref())?
.iter()
.map(|s| Challenge(*s))
.collect();
Ok(PokSignatureProof {
a_prime: self.a_prime,
a_bar: self.a_bar,
d: self.d,
proofs1,
proofs2,
})
}
}