1mod aux_only;
5
6use digest::Digest;
7use rand_core::{CryptoRng, RngCore};
8use round_based::Mpc;
9use thiserror::Error;
10
11use crate::backend::Integer;
12use crate::utils;
13use crate::{
14 errors::IoError, key_share::AuxInfo, progress::Tracer, security_level::SecurityLevel,
15 utils::AbortBlame, ExecutionId,
16};
17
18#[doc(no_inline)]
19pub use self::msg::Msg;
20
21#[doc = include_str!("../docs/mpc_message.md")]
22pub mod msg {
23 pub use crate::key_refresh::aux_only::{
24 Msg, MsgReliabilityCheck, MsgRound1, MsgRound2, MsgRound3,
25 };
26}
27
28#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
31pub struct PregeneratedPrimes<L = crate::default_choice::SecurityLevel> {
32 primes: [Integer; 4],
33 _phantom: std::marker::PhantomData<L>,
34}
35
36impl<L: SecurityLevel> TryFrom<[Integer; 4]> for PregeneratedPrimes<L> {
37 type Error = [Integer; 4];
38
39 fn try_from(primes: [Integer; 4]) -> Result<Self, Self::Error> {
46 if primes
47 .iter()
48 .any(|p| !crate::security_level::validate_secret_paillier_prime_size::<L>(p))
49 {
50 Err(primes)
51 } else {
52 Ok(Self {
53 primes,
54 _phantom: std::marker::PhantomData,
55 })
56 }
57 }
58}
59
60impl<L: SecurityLevel> PregeneratedPrimes<L> {
61 pub fn into_primes(self) -> [Integer; 4] {
63 self.primes
64 }
65
66 pub fn primes_ref(&self) -> &[Integer; 4] {
68 &self.primes
69 }
70
71 pub fn generate<R: RngCore>(rng: &mut R) -> Self {
73 Self {
74 primes: [(); 4].map(|_| Integer::generate_safe_prime(rng, L::RSA_PRIME_BITLEN)),
75 _phantom: std::marker::PhantomData,
76 }
77 }
78}
79
80pub struct AuxInfoBuilder<'a, L, D = crate::default_choice::Digest>
82where
83 L: SecurityLevel,
84 D: Digest,
85{
86 i: u16,
87 n: u16,
88 execution_id: ExecutionId<'a>,
89 pregenerated: PregeneratedPrimes<L>,
90 tracer: Option<&'a mut dyn Tracer>,
91 enforce_reliable_broadcast: bool,
92 precompute_multiexp_tables: bool,
93 _digest: std::marker::PhantomData<D>,
94}
95
96impl<'a, L, D> AuxInfoBuilder<'a, L, D>
97where
98 L: SecurityLevel,
99 D: Digest,
100{
101 pub fn new_aux_gen(
105 eid: ExecutionId<'a>,
106 i: u16,
107 n: u16,
108 pregenerated: PregeneratedPrimes<L>,
109 ) -> Self {
110 Self {
111 i,
112 n,
113 execution_id: eid,
114 pregenerated,
115 tracer: None,
116 enforce_reliable_broadcast: true,
117 precompute_multiexp_tables: false,
118 _digest: std::marker::PhantomData,
119 }
120 }
121
122 pub async fn start<R, M>(self, rng: &mut R, party: M) -> Result<AuxInfo<L>, KeyRefreshError>
124 where
125 R: RngCore + CryptoRng,
126 M: Mpc<ProtocolMessage = aux_only::Msg<D, L>>,
127 L: SecurityLevel,
128 D: Digest + Clone + 'static,
129 {
130 aux_only::run_aux_gen(
131 self.i,
132 self.n,
133 rng,
134 party,
135 self.execution_id,
136 self.pregenerated,
137 self.tracer,
138 self.enforce_reliable_broadcast,
139 self.precompute_multiexp_tables,
140 )
141 .await
142 }
143
144 #[cfg(feature = "state-machine")]
148 pub fn into_state_machine<R>(
149 self,
150 rng: &'a mut R,
151 ) -> impl round_based::state_machine::StateMachine<
152 Output = Result<AuxInfo<L>, KeyRefreshError>,
153 Msg = aux_only::Msg<D, L>,
154 > + 'a
155 where
156 R: RngCore + CryptoRng,
157 L: SecurityLevel,
158 D: Digest<OutputSize = digest::typenum::U32> + Clone + 'static,
159 {
160 round_based::state_machine::wrap_protocol(|party| self.start(rng, party))
161 }
162}
163
164impl<'a, L, D> AuxInfoBuilder<'a, L, D>
165where
166 L: SecurityLevel,
167 D: Digest,
168{
169 pub fn set_digest<D2: Digest>(self) -> AuxInfoBuilder<'a, L, D2> {
171 AuxInfoBuilder {
172 i: self.i,
173 n: self.n,
174 execution_id: self.execution_id,
175 pregenerated: self.pregenerated,
176 tracer: self.tracer,
177 enforce_reliable_broadcast: self.enforce_reliable_broadcast,
178 precompute_multiexp_tables: self.precompute_multiexp_tables,
179 _digest: std::marker::PhantomData,
180 }
181 }
182
183 pub fn set_progress_tracer(mut self, tracer: &'a mut dyn Tracer) -> Self {
185 self.tracer = Some(tracer);
186 self
187 }
188
189 #[doc = include_str!("../docs/enforce_reliable_broadcast.md")]
190 pub fn enforce_reliable_broadcast(self, v: bool) -> Self {
191 Self {
192 enforce_reliable_broadcast: v,
193 ..self
194 }
195 }
196
197 pub fn precompute_multiexp_tables(mut self, v: bool) -> Self {
203 self.precompute_multiexp_tables = v;
204 self
205 }
206}
207
208#[derive(Debug, Error)]
210#[error("key refresh protocol failed to complete")]
211pub struct KeyRefreshError(#[source] Reason);
212
213crate::errors::impl_from! {
214 impl From for KeyRefreshError {
215 err: ProtocolAborted => KeyRefreshError(Reason::Aborted(err)),
216 err: IoError => KeyRefreshError(Reason::IoError(err)),
217 err: Bug => KeyRefreshError(Reason::InternalError(err)),
218 err: utils::GenPedersenError => Bug::GenPedersen(err).into(),
219 }
220}
221
222#[derive(Debug, Error)]
223enum Reason {
224 #[error("protocol was aborted by malicious party")]
226 Aborted(#[source] ProtocolAborted),
227 #[error("i/o error")]
228 IoError(#[source] IoError),
229 #[error("internal error")]
230 InternalError(#[from] Bug),
231}
232
233#[derive(Debug, Error)]
235enum Bug {
236 #[error("Invalid key share geenrated")]
237 InvalidShareGenerated(#[source] crate::key_share::InvalidKeyShare),
238 #[error("couldn't prove a pi mod statement")]
239 PiMod(#[source] paillier_zk::Error),
240 #[error("couldn't prove a pi fac statement")]
241 PiFac(#[source] paillier_zk::Error),
242 #[error("couldn't prove prm statement")]
243 PiPrm(#[source] crate::zk::ring_pedersen_parameters::ZkError),
244 #[error("couldn't build multiexp tables")]
245 BuildMultiexpTables(#[source] crate::key_share::InvalidKeyShare),
246 #[error("generate pedersen params")]
247 GenPedersen(#[source] utils::GenPedersenError),
248 #[error("own modulus N is not positive")]
249 NegativeModulus,
250}
251
252#[derive(Debug, Error)]
256#[error("Protocol aborted; malicious parties: {parties:?}; reason: {reason}")]
257struct ProtocolAborted {
258 pub reason: ProtocolAbortReason,
259 pub parties: Vec<AbortBlame>,
260}
261
262#[derive(Debug, Error)]
264enum ProtocolAbortReason {
265 #[error("decommitment doesn't match commitment")]
266 InvalidDecommitment,
267 #[error("provided invalid proof for Rmod")]
268 InvalidModProof,
269 #[error("provided invalid proof for Rfac")]
270 InvalidFacProof,
271 #[error("N, s and t parameters are invalid")]
272 InvalidRingPedersenParameters,
273 #[error("round 1 was not reliable")]
274 Round1NotReliable,
275}
276
277macro_rules! make_factory {
278 ($function:ident, $reason:ident) => {
279 fn $function(parties: Vec<AbortBlame>) -> Self {
280 Self {
281 reason: ProtocolAbortReason::$reason,
282 parties,
283 }
284 }
285 };
286}
287impl ProtocolAborted {
288 make_factory!(invalid_decommitment, InvalidDecommitment);
289 make_factory!(invalid_mod_proof, InvalidModProof);
290 make_factory!(invalid_fac_proof, InvalidFacProof);
291 make_factory!(
292 invalid_ring_pedersen_parameters,
293 InvalidRingPedersenParameters
294 );
295 make_factory!(round1_not_reliable, Round1NotReliable);
296}