Skip to main content

primitives/correlated_randomness/triples/
random.rs

1use crate::{
2    algebra::field::{FieldExtension, SubfieldElement},
3    correlated_randomness::triples::{
4        Triple,
5        Triples,
6        UnauthenticatedTriple,
7        UnauthenticatedTriples,
8    },
9    izip_eq,
10    random::{CryptoRngCore, Random, RandomWith},
11    sharing::{unauthenticated::AdditiveShares, FieldShare, FieldShares, GlobalFieldKey},
12    types::{heap_array::SubfieldElements, Positive},
13    utils::IntoExactSizeIterator,
14};
15// -------------------------
16// |   Random Generation   |
17// -------------------------
18
19impl<F: FieldExtension> Random for UnauthenticatedTriple<F> {
20    fn random(_rng: impl CryptoRngCore) -> Self {
21        unimplemented!("UnauthenticatedTriple is correlated randomness. Use `random_n` to establish correlation for n_parties")
22    }
23
24    /// Generates random triples for all the parties requested.
25    fn random_n<Container: FromIterator<Self>>(
26        mut rng: impl CryptoRngCore,
27        n_parties: usize,
28    ) -> Container {
29        let a = SubfieldElement::random(&mut rng);
30        let b = SubfieldElement::random(&mut rng);
31        let c = a * b;
32
33        let a_shares = a.to_additive_shares(n_parties, &mut rng);
34        let b_shares = b.to_additive_shares(n_parties, &mut rng);
35        let c_shares = c.to_additive_shares(n_parties, &mut rng);
36
37        izip_eq!(a_shares, b_shares, c_shares)
38            .map(|(a, b, c)| UnauthenticatedTriple { a, b, c })
39            .collect()
40    }
41}
42
43impl<F: FieldExtension, M: Positive> Random for UnauthenticatedTriples<F, M> {
44    fn random(_rng: impl CryptoRngCore) -> Self {
45        unimplemented!("UnauthenticatedTriples are correlated randomness. Use `random_n` to establish correlation for n_parties")
46    }
47
48    /// Generates random triples for all the parties requested.
49    fn random_n<Container: FromIterator<Self>>(
50        mut rng: impl CryptoRngCore,
51        n_parties: usize,
52    ) -> Container {
53        let a = SubfieldElements::random(&mut rng);
54        let b = SubfieldElements::random(&mut rng);
55        let c = &a * &b;
56
57        let a_shares = a.to_additive_shares(n_parties, &mut rng);
58        let b_shares = b.to_additive_shares(n_parties, &mut rng);
59        let c_shares = c.to_additive_shares(n_parties, &mut rng);
60
61        izip_eq!(a_shares, b_shares, c_shares)
62            .map(|(a, b, c)| UnauthenticatedTriples { a, b, c })
63            .collect()
64    }
65}
66
67impl<F: FieldExtension, M: Positive> Random for Triples<F, M> {
68    fn random(_rng: impl CryptoRngCore) -> Self {
69        unimplemented!("Triples are correlated randomness. Use `random_n` to establish correlation for n_parties")
70    }
71
72    /// Generates random triples for all the parties requested.
73    fn random_n<Container: FromIterator<Self>>(
74        mut rng: impl CryptoRngCore,
75        n_parties: usize,
76    ) -> Container {
77        let a = SubfieldElements::random(&mut rng);
78        let b = SubfieldElements::random(&mut rng);
79        let c = &a * &b;
80
81        let a_shares: Vec<_> = FieldShares::random_n_with(&mut rng, n_parties, a);
82        let b_shares: Vec<_> = FieldShares::random_n_with(&mut rng, n_parties, b);
83        let c_shares: Vec<_> = FieldShares::random_n_with(&mut rng, n_parties, c);
84
85        izip_eq!(a_shares, b_shares, c_shares)
86            .map(|(a, b, c)| Triples { a, b, c })
87            .collect()
88    }
89}
90
91impl<F: FieldExtension, M: Positive> RandomWith<Vec<GlobalFieldKey<F>>> for Triples<F, M> {
92    /// Generate a single random triple share for the global keys of a single party.
93    ///
94    /// WARNING: This does not establish correlation with other parties! Use only to mock a single
95    /// party's triple.
96    #[allow(unused_mut)]
97    fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalFieldKey<F>>) -> Self {
98        #[cfg(any(test, feature = "dev"))]
99        {
100            Triples {
101                a: FieldShares::<F, M>::random_with(&mut rng, alphas.clone()),
102                b: FieldShares::<F, M>::random_with(&mut rng, alphas.clone()),
103                c: FieldShares::<F, M>::random_with(&mut rng, alphas),
104            }
105        }
106
107        #[cfg(not(any(test, feature = "dev")))]
108        unimplemented!(
109            "Triples are correlated randomness. Use `random_n_with_each({}, Vec<{}>)` to establish correlation for n_parties", std::any::type_name_of_val(&rng),
110            std::any::type_name_of_val(&alphas)
111        );
112    }
113
114    /// Generate random triples given the global keys (alphas) for all parties.
115    fn random_n_with_each<Container: FromIterator<Self>>(
116        mut rng: impl CryptoRngCore,
117        all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalFieldKey<F>>>,
118    ) -> Container {
119        let all_alphas = all_alphas.into_iter().collect::<Vec<_>>();
120        let a = SubfieldElements::random(&mut rng);
121        let b = SubfieldElements::random(&mut rng);
122        let c = &a * &b;
123
124        let n_parties = all_alphas.len();
125        let a_shares: Vec<_> =
126            FieldShares::random_n_with(&mut rng, n_parties, (a, all_alphas.clone()));
127        let b_shares: Vec<_> =
128            FieldShares::random_n_with(&mut rng, n_parties, (b, all_alphas.clone()));
129        let c_shares: Vec<_> = FieldShares::random_n_with(&mut rng, n_parties, (c, all_alphas));
130
131        izip_eq!(a_shares, b_shares, c_shares)
132            .map(|(a, b, c)| Triples { a, b, c })
133            .collect()
134    }
135}
136
137impl<F: FieldExtension> Random for Triple<F> {
138    fn random(_rng: impl CryptoRngCore) -> Self {
139        unimplemented!("Triples are correlated randomness. Use `random_n`/`random_n_with`` to establish correlation for n_parties")
140    }
141
142    /// Generates random triples for all the parties requested.
143    fn random_n<Container: FromIterator<Self>>(
144        mut rng: impl CryptoRngCore,
145        n_parties: usize,
146    ) -> Container {
147        let a = SubfieldElement::random(&mut rng);
148        let b = SubfieldElement::random(&mut rng);
149        let c = a * b;
150
151        let a_shares: Vec<_> = FieldShare::random_n_with(&mut rng, n_parties, a);
152        let b_shares: Vec<_> = FieldShare::random_n_with(&mut rng, n_parties, b);
153        let c_shares: Vec<_> = FieldShare::random_n_with(&mut rng, n_parties, c);
154
155        izip_eq!(a_shares, b_shares, c_shares)
156            .map(|(a, b, c)| Triple { a, b, c })
157            .collect()
158    }
159}
160
161impl<F: FieldExtension> RandomWith<Vec<GlobalFieldKey<F>>> for Triple<F> {
162    /// Generate a single random triple share for the global keys of a single party.
163    #[allow(unused_mut)]
164    fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalFieldKey<F>>) -> Self {
165        #[cfg(any(test, feature = "dev"))]
166        {
167            Triple {
168                a: FieldShare::random_with(&mut rng, alphas.clone()),
169                b: FieldShare::random_with(&mut rng, alphas.clone()),
170                c: FieldShare::random_with(&mut rng, alphas),
171            }
172        }
173
174        #[cfg(not(any(test, feature = "dev")))]
175        unimplemented!(
176            "Triples are correlated randomness. Use `random_n_with_each({}, Vec<{}>)` to establish correlation for n_parties", std::any::type_name_of_val(&rng),
177            std::any::type_name_of_val(&alphas)
178        );
179    }
180
181    /// Generate random triples given the global keys (alphas) for all parties.
182    fn random_n_with_each<Container: FromIterator<Self>>(
183        mut rng: impl CryptoRngCore,
184        all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalFieldKey<F>>>,
185    ) -> Container {
186        let all_alphas = all_alphas.into_iter().collect::<Vec<_>>();
187        let a = SubfieldElement::random(&mut rng);
188        let b = SubfieldElement::random(&mut rng);
189        let c = a * b;
190
191        let n_parties = all_alphas.len();
192        let a_shares: Vec<_> =
193            FieldShare::random_n_with(&mut rng, n_parties, (a, all_alphas.clone()));
194        let b_shares: Vec<_> =
195            FieldShare::random_n_with(&mut rng, n_parties, (b, all_alphas.clone()));
196        let c_shares: Vec<_> = FieldShare::random_n_with(&mut rng, n_parties, (c, all_alphas));
197
198        izip_eq!(a_shares, b_shares, c_shares)
199            .map(|(a, b, c)| Triple { a, b, c })
200            .collect()
201    }
202}