Skip to main content

confium_tc_cmp20/
gg18_mta.rs

1//! GG18 Paillier MtA integration.
2//!
3//! GG20 (the improved GG18) uses the same MtA sub-protocol as CMP20.
4//! This module re-exports the CMP20 Paillier MtA for GG20's use.
5
6pub use crate::paillier_mta::{
7    MtaProofError, ProvedMessage1, ProvedMessage2, full_mta_proved, party_i_finish_proved,
8    party_i_init_proved, party_j_respond_proved,
9};
10
11/// GG18-specific MtA with the Appendix A proofs on every ciphertext
12/// (identical sub-protocol to CMP20 — both per Gennaro-Goldfeder).
13pub fn gg18_mta_proved(
14    i_keypair: &confium_tc::paillier::PaillierKeypair,
15    ck_i: &crate::mta_proofs::CommitmentKey,
16    ck_j: &crate::mta_proofs::CommitmentKey,
17    q: &num_bigint::BigUint,
18    k_i: &num_bigint::BigUint,
19    x_j: &num_bigint::BigUint,
20) -> Result<(num_bigint::BigUint, num_bigint::BigUint), MtaProofError> {
21    full_mta_proved(i_keypair, ck_i, ck_j, q, k_i, x_j)
22}
23
24#[cfg(test)]
25mod tests {
26    use super::*;
27    use crate::mta_proofs::p256_order;
28    use confium_tc::paillier::generate_keypair;
29    use num_bigint::BigUint;
30    use std::sync::OnceLock;
31
32    #[allow(clippy::type_complexity)]
33    fn fixtures() -> &'static (
34        confium_tc::paillier::PaillierKeypair,
35        crate::mta_proofs::CommitmentKey,
36        crate::mta_proofs::CommitmentKey,
37        BigUint,
38    ) {
39        static FIX: OnceLock<(
40            confium_tc::paillier::PaillierKeypair,
41            crate::mta_proofs::CommitmentKey,
42            crate::mta_proofs::CommitmentKey,
43            BigUint,
44        )> = OnceLock::new();
45        FIX.get_or_init(|| {
46            // 642-bit primes: honest proofs need N > q⁵ + q².
47            (
48                generate_keypair(642),
49                crate::mta_proofs::generate_commitment_key(64),
50                crate::mta_proofs::generate_commitment_key(64),
51                p256_order(),
52            )
53        })
54    }
55
56    #[test]
57    fn gg18_mta_proved_works() {
58        let (kp, ck_i, ck_j, q) = fixtures();
59        let k = BigUint::from(42u32);
60        let x = BigUint::from(17u32);
61        let (alpha, beta) = gg18_mta_proved(kp, ck_i, ck_j, q, &k, &x).unwrap();
62        assert_eq!((&alpha - &beta) % q, (&k * &x) % q);
63    }
64
65    #[test]
66    fn gg18_mta_proved_shares_dont_reveal_product() {
67        let (kp, ck_i, ck_j, q) = fixtures();
68        let k = BigUint::from(42u32);
69        let x = BigUint::from(17u32);
70        let (alpha, beta) = gg18_mta_proved(kp, ck_i, ck_j, q, &k, &x).unwrap();
71        let product = &k * &x;
72        assert_ne!(alpha, product);
73        assert_ne!(beta, product);
74    }
75
76    #[test]
77    fn gg18_mta_proved_multiple_pairs() {
78        let (kp, ck_i, ck_j, q) = fixtures();
79        for (k, x) in [(10u32, 20u32), (100u32, 50u32), (7u32, 13u32)] {
80            let (alpha, beta) =
81                gg18_mta_proved(kp, ck_i, ck_j, q, &BigUint::from(k), &BigUint::from(x)).unwrap();
82            assert_eq!(
83                (&alpha - &beta) % q,
84                (BigUint::from(k) * BigUint::from(x)) % q
85            );
86        }
87    }
88}