multi_party_ecdsa/utilities/mta/
mod.rs1use curv::arithmetic::traits::Samplable;
19use curv::cryptographic_primitives::proofs::sigma_dlog::DLogProof;
20use curv::elliptic::curves::{secp256_k1::Secp256k1, Point, Scalar};
21use curv::BigInt;
22use paillier::traits::EncryptWithChosenRandomness;
23use paillier::{Add, Decrypt, Mul};
24use paillier::{DecryptionKey, EncryptionKey, Paillier, Randomness, RawCiphertext, RawPlaintext};
25use zk_paillier::zkproofs::DLogStatement;
26
27use serde::{Deserialize, Serialize};
28use sha2::Sha256;
29
30use crate::protocols::multi_party_ecdsa::gg_2018::party_i::PartyPrivate;
31use crate::utilities::mta::range_proofs::AliceProof;
32use crate::Error::{self, InvalidKey};
33
34#[derive(Clone, Debug, Serialize, Deserialize)]
35pub struct MessageA {
36 pub c: BigInt, pub range_proofs: Vec<AliceProof>, }
39
40#[derive(Clone, Debug, Serialize, Deserialize)]
41pub struct MessageB {
42 pub c: BigInt, pub b_proof: DLogProof<Secp256k1, Sha256>,
44 pub beta_tag_proof: DLogProof<Secp256k1, Sha256>,
45}
46
47impl MessageA {
48 pub fn a(
53 a: &Scalar<Secp256k1>,
54 alice_ek: &EncryptionKey,
55 dlog_statements: &[DLogStatement],
56 ) -> (Self, BigInt) {
57 let randomness = BigInt::sample_below(&alice_ek.n);
58 let m_a = MessageA::a_with_predefined_randomness(a, alice_ek, &randomness, dlog_statements);
59 (m_a, randomness)
60 }
61
62 pub fn a_with_predefined_randomness(
63 a: &Scalar<Secp256k1>,
64 alice_ek: &EncryptionKey,
65 randomness: &BigInt,
66 dlog_statements: &[DLogStatement],
67 ) -> Self {
68 let c_a = Paillier::encrypt_with_chosen_randomness(
69 alice_ek,
70 RawPlaintext::from(a.to_bigint()),
71 &Randomness::from(randomness.clone()),
72 )
73 .0
74 .clone()
75 .into_owned();
76 let alice_range_proofs = dlog_statements
77 .iter()
78 .map(|dlog_statement| {
79 AliceProof::generate(&a.to_bigint(), &c_a, alice_ek, dlog_statement, randomness)
80 })
81 .collect::<Vec<AliceProof>>();
82
83 Self {
84 c: c_a,
85 range_proofs: alice_range_proofs,
86 }
87 }
88}
89
90impl MessageB {
91 pub fn b(
92 b: &Scalar<Secp256k1>,
93 alice_ek: &EncryptionKey,
94 m_a: MessageA,
95 dlog_statements: &[DLogStatement],
96 ) -> Result<(Self, Scalar<Secp256k1>, BigInt, BigInt), Error> {
97 let beta_tag = BigInt::sample_below(&alice_ek.n);
98 let randomness = BigInt::sample_below(&alice_ek.n);
99 let (m_b, beta) = MessageB::b_with_predefined_randomness(
100 b,
101 alice_ek,
102 m_a,
103 &randomness,
104 &beta_tag,
105 dlog_statements,
106 )?;
107
108 Ok((m_b, beta, randomness, beta_tag))
109 }
110
111 pub fn b_with_predefined_randomness(
112 b: &Scalar<Secp256k1>,
113 alice_ek: &EncryptionKey,
114 m_a: MessageA,
115 randomness: &BigInt,
116 beta_tag: &BigInt,
117 dlog_statements: &[DLogStatement],
118 ) -> Result<(Self, Scalar<Secp256k1>), Error> {
119 if m_a.range_proofs.len() != dlog_statements.len() {
120 return Err(InvalidKey);
121 }
122 if !m_a
124 .range_proofs
125 .iter()
126 .zip(dlog_statements)
127 .map(|(proof, dlog_statement)| proof.verify(&m_a.c, alice_ek, dlog_statement))
128 .all(|x| x)
129 {
130 return Err(InvalidKey);
131 };
132 let beta_tag_fe = Scalar::<Secp256k1>::from(beta_tag);
133 let c_beta_tag = Paillier::encrypt_with_chosen_randomness(
134 alice_ek,
135 RawPlaintext::from(beta_tag),
136 &Randomness::from(randomness.clone()),
137 );
138
139 let b_bn = b.to_bigint();
140 let b_c_a = Paillier::mul(
141 alice_ek,
142 RawCiphertext::from(m_a.c),
143 RawPlaintext::from(b_bn),
144 );
145 let c_b = Paillier::add(alice_ek, b_c_a, c_beta_tag);
146 let beta = Scalar::<Secp256k1>::zero() - &beta_tag_fe;
147 let dlog_proof_b = DLogProof::prove(b);
148 let dlog_proof_beta_tag = DLogProof::prove(&beta_tag_fe);
149
150 Ok((
151 Self {
152 c: c_b.0.clone().into_owned(),
153 b_proof: dlog_proof_b,
154 beta_tag_proof: dlog_proof_beta_tag,
155 },
156 beta,
157 ))
158 }
159
160 pub fn verify_proofs_get_alpha(
161 &self,
162 dk: &DecryptionKey,
163 a: &Scalar<Secp256k1>,
164 ) -> Result<(Scalar<Secp256k1>, BigInt), Error> {
165 let alice_share = Paillier::decrypt(dk, &RawCiphertext::from(self.c.clone()));
166 let g = Point::generator();
167 let alpha = Scalar::<Secp256k1>::from(alice_share.0.as_ref());
168 let g_alpha = g * α
169 let ba_btag = &self.b_proof.pk * a + &self.beta_tag_proof.pk;
170 if DLogProof::verify(&self.b_proof).is_ok()
171 && DLogProof::verify(&self.beta_tag_proof).is_ok()
172 && ba_btag == g_alpha
174 {
175 Ok((alpha, alice_share.0.into_owned()))
176 } else {
177 Err(InvalidKey)
178 }
179 }
180
181 pub fn verify_proofs_get_alpha_gg18(
184 &self,
185 private: &PartyPrivate,
186 a: &Scalar<Secp256k1>,
187 ) -> Result<Scalar<Secp256k1>, Error> {
188 let alice_share = private.decrypt(self.c.clone());
189 let g = Point::generator();
190 let alpha = Scalar::<Secp256k1>::from(alice_share.0.as_ref());
191 let g_alpha = g * α
192 let ba_btag = &self.b_proof.pk * a + &self.beta_tag_proof.pk;
193
194 if DLogProof::verify(&self.b_proof).is_ok()
195 && DLogProof::verify(&self.beta_tag_proof).is_ok()
196 && ba_btag == g_alpha
197 {
198 Ok(alpha)
199 } else {
200 Err(InvalidKey)
201 }
202 }
203
204 pub fn verify_b_against_public(
205 public_gb: &Point<Secp256k1>,
206 mta_gb: &Point<Secp256k1>,
207 ) -> bool {
208 public_gb == mta_gb
209 }
210}
211
212pub mod range_proofs;
213#[cfg(test)]
214mod test;