1use alloc::vec::Vec;
3use k256::ProjectivePoint;
4use rand_core::CryptoRng;
5use zeroize::ZeroizeOnDrop;
6
7use super::{ServerKeyShare, commitment, decode_client_tuple, tx_base};
8use crate::{
9 arith::sbig::{SBig, SRange},
10 curve::{decode_point, encode_point, sbig_to_scalar},
11 error::Result,
12 messages::{KgMsg1, KgMsg2, KgMsg3},
13 paillier::PaillierPk,
14 params::Params,
15 setup::SetupData,
16 ssid::Ssid,
17 transcript::uint_to_be,
18 zk::{
19 df_star::DfStarProof,
20 dlenc::{DlencProof, DlencStatement, DlencWitness},
21 dlog::DlogProof,
22 },
23};
24
25pub struct ServerKeygen0;
27
28impl ServerKeygen0 {
29 pub fn start<R: CryptoRng + ?Sized>(
31 rng: &mut R,
32 params: &Params,
33 setup: &SetupData,
34 client_id: &[u8],
35 ) -> Result<(ServerKeygen1, Vec<u8>)> {
36 let pk = setup.paillier_pk()?;
37 let mut nonce = [0u8; 32];
38 rng.fill_bytes(&mut nonce);
39 let ssid = Ssid::keygen(setup.hash()?, &setup.server_id, client_id, &nonce)?;
40 let x2p = SBig::random_in(rng, SRange::pm_pow2(params.n_x()));
41 let x2_pub = ProjectivePoint::GENERATOR * sbig_to_scalar(&x2p)?;
42 let b = commitment(params, &ssid, &x2_pub);
43 let msg = KgMsg1 {
44 kg_nonce: nonce.to_vec(),
45 b: b.to_vec(),
46 }
47 .encode(params)?;
48 Ok((
49 ServerKeygen1 {
50 params: *params,
51 ssid,
52 pk,
53 x2p,
54 x2_pub,
55 },
56 msg,
57 ))
58 }
59}
60
61#[derive(ZeroizeOnDrop)]
63pub struct ServerKeygen1 {
64 #[zeroize(skip)]
65 params: Params,
66 #[zeroize(skip)]
67 ssid: Ssid,
68 #[zeroize(skip)]
69 pk: PaillierPk,
70 x2p: SBig,
71 #[zeroize(skip)]
72 x2_pub: ProjectivePoint,
73}
74
75impl ServerKeygen1 {
76 pub fn on_msg2<R: CryptoRng + ?Sized>(
78 self,
79 rng: &mut R,
80 msg2: &[u8],
81 ) -> Result<(ServerKeyShare, Vec<u8>)> {
82 let params = &self.params;
83 let m = KgMsg2::decode(msg2, params)?;
84 let x1_pub = decode_point(&m.x1)?;
85 let client = decode_client_tuple(params, &m.m_hat, &m.v, &m.u1, &m.u2)?;
86 let psi_df = DfStarProof::decode(&m.psi_df_star, params)?;
87 let psi_dlog = DlogProof::decode(&m.psi_dlog, params)?;
88
89 let tx_c = tx_base(params, &self.ssid, "C");
90 psi_df.verify(&tx_c, params, &client)?;
91 psi_dlog.verify(&tx_c, params, &x1_pub)?;
92
93 let beta = SBig::random_in(rng, SRange::pm_pow2(params.n_lambda()));
94 let e_ct = self.pk.enc(&self.x2p, &beta, params.n_lambda())?;
95 let tx_s = tx_base(params, &self.ssid, "S");
96 let stmt = DlencStatement {
97 x_pub: &self.x2_pub,
98 e_ct: &e_ct,
99 pk: &self.pk,
100 client: &client,
101 };
102 let psi = DlencProof::prove(
103 rng,
104 &tx_s,
105 params,
106 &stmt,
107 &DlencWitness::new(self.x2p.clone(), beta),
108 )?;
109
110 let e_len = (2 * params.n_rsa as usize).div_ceil(8);
111 let e_bytes = uint_to_be(&e_ct.retrieve(), e_len)?;
112 let msg3 = KgMsg3 {
113 x2: encode_point(&self.x2_pub).to_vec(),
114 e: e_bytes.clone(),
115 psi_dlenc: psi.encode(params)?,
116 }
117 .encode(params)?;
118 let share = ServerKeyShare::new(sbig_to_scalar(&self.x2p)?, x1_pub + self.x2_pub, e_bytes);
119 Ok((share, msg3))
120 }
121}
122
123#[cfg(test)]
124impl ServerKeygen1 {
125 pub(crate) fn test_clone(&self) -> Self {
126 Self {
127 params: self.params,
128 ssid: self.ssid.clone(),
129 pk: self.pk.clone(),
130 x2p: self.x2p.clone(),
131 x2_pub: self.x2_pub,
132 }
133 }
134}