1use alloc::vec::Vec;
3use crypto_bigint::{BoxedUint, NonZero};
4use k256::{ProjectivePoint, Scalar, ecdsa::VerifyingKey};
5use rand_core::CryptoRng;
6
7use super::{
8 Signature, decode_signature, digest_scalar, ecdsa_verify, hedged_nonce, nonce_challenge,
9 tx_base,
10};
11use crate::{
12 arith::{
13 monty::Residue,
14 sbig::{SBig, SRange, resized},
15 },
16 curve::{decode_point, encode_point, encode_scalar, order, x_coord},
17 error::{Error, Result},
18 hd::HdPath,
19 keygen::{ClientKeyShare, canonical_uint},
20 messages::{SignMsg1, SignMsg2, SignMsg3},
21 params::Params,
22 setup::VerifiedSetup,
23 ssid::Ssid,
24 transcript::{uint_from_be, uint_to_be},
25 zk::sig::{SigProof, SigStatement, SigWitness},
26};
27
28const MAX_RESAMPLE: usize = 64;
29
30pub struct ClientSign;
32
33fn scalar_to_sbig(s: &Scalar) -> Result<SBig> {
34 Ok(SBig::from_uint(uint_from_be(&encode_scalar(s), 256)?))
35}
36
37fn mask_interval(bits: u32) -> Result<BoxedUint> {
39 let q = order();
40 let prec = bits.max(q.bits_precision()) + 64;
41 let num = BoxedUint::one_with_precision(prec).shl(bits);
42 let qnz = Option::<NonZero<BoxedUint>>::from(resized(&q, prec).to_nz())
43 .ok_or(Error::InvalidModulus)?;
44 Ok(num.div_rem_vartime(&qnz).0)
45}
46
47impl ClientSign {
48 pub fn respond<R: CryptoRng + ?Sized>(
51 rng: &mut R,
52 setup: &VerifiedSetup,
53 share: &ClientKeyShare,
54 client_id: &[u8],
55 digest: &[u8; 32],
56 msg1: &[u8],
57 hd: Option<&HdPath>,
58 ) -> Result<Vec<u8>> {
59 let params = setup.params();
60 super::check_digest(digest)?;
61 let m1 = SignMsg1::decode(msg1, params)?;
62 let r2 = decode_point(&m1.r2)?;
63 let y = decode_point(&m1.y)?;
64 let (x_pub, delta) = super::signing_key(share.public_key(), hd)?;
65 let x1 = *share.secret() + delta; if r2 * x1 != y {
67 return Err(Error::VerificationFailed);
68 }
69 let ssid = Ssid::sign(
70 setup.hash(),
71 setup.server_id(),
72 client_id,
73 &share.key_id(),
74 digest,
75 &encode_point(&r2),
76 &encode_point(&x_pub),
77 )?;
78
79 let mut ctx = Vec::with_capacity(96);
80 ctx.extend_from_slice(&ssid.encode());
81 let k1 = hedged_nonce(rng, "k1", &x1, &ctx);
82 let r1 = ProjectivePoint::GENERATOR * k1;
83 let r_pt = r2 * k1;
84 let e = nonce_challenge(params, &ssid, &x_pub, &r1, &r_pt, digest);
85 let r = x_coord(&((r2 + ProjectivePoint::GENERATOR * e) * k1));
86 let m = digest_scalar(digest);
87 let k1_inv = Option::<Scalar>::from(k256::elliptic_curve::Field::invert(&k1))
88 .ok_or(Error::VerificationFailed)?;
89 let t1 = scalar_to_sbig(&(k1_inv * (m + r * x1)))?;
90 let t2 = scalar_to_sbig(&(k1_inv * r))?;
91 let q = SBig::from_uint(order());
92
93 let (size_a, size_b) = (mask_interval(params.n_a())?, mask_interval(params.n_b())?);
95 let (a_range, b_range) = (SRange::pm_pow2(params.n_a()), SRange::pm_pow2(params.n_b()));
96 let (mut u, mut v) = (SBig::zero(64), SBig::zero(64));
97 for i in 0..MAX_RESAMPLE {
98 u = t1.add(&SBig::random_in_size(rng, &size_a)?.mul(&q));
99 v = t2.add(&SBig::random_in_size(rng, &size_b)?.mul(&q));
100 if u.in_range(a_range) && v.in_range(b_range) {
101 break;
102 }
103 if i + 1 == MAX_RESAMPLE {
104 return Err(Error::OutOfRange);
105 }
106 }
107 let lambda0 = SBig::random_in(rng, SRange::pm_pow2(params.n_lambda0()));
108
109 let pk = setup.paillier_pk();
111 let s_len = (2 * params.n_rsa as usize).div_ceil(8);
112 let e_int = canonical_uint(share.e_bytes(), s_len, pk.mod_n2().modulus().as_ref())?;
113 let e_ct = pk.check_ciphertext(&e_int)?;
114 let rho_pow: Residue = match setup.rho_table() {
115 Some(t) if t.max_bits() >= params.n_lambda0() => t.pow_ct(&lambda0)?,
116 _ => pk.mod_n2().pow_ct(pk.rho(), &lambda0, params.n_lambda0())?,
117 };
118 let s_ct = pk
119 .g_pow(&u)
120 .mul(&rho_pow)
121 .mul(&pk.scale(&e_ct, &v, params.n_b())?);
122
123 let stmt = SigStatement {
124 h: setup.h(),
125 f: setup.f(),
126 pk,
127 df: setup.df(),
128 e_ct: &e_ct,
129 s_ct: &s_ct,
130 rho_table: setup.rho_table(),
131 };
132 let psi = SigProof::prove(
133 rng,
134 &tx_base(params, &ssid, "C"),
135 params,
136 &stmt,
137 &SigWitness {
138 a: u,
139 b: v,
140 lambda0,
141 },
142 )?;
143 SignMsg2 {
144 r1: encode_point(&r1).to_vec(),
145 r: encode_point(&r_pt).to_vec(),
146 s_ct: uint_to_be(&s_ct.retrieve(), s_len)?,
147 psi_sig: psi.encode(params)?,
148 }
149 .encode(params)
150 }
151
152 pub fn verify_final(
154 params: &Params,
155 share: &ClientKeyShare,
156 digest: &[u8; 32],
157 msg3: &[u8],
158 hd: Option<&HdPath>,
159 ) -> Result<Signature> {
160 let m = SignMsg3::decode(msg3, params)?;
161 let sig = decode_signature(&m.r, &m.s, m.recid)?;
162 let (x_sign, _) = super::signing_key(share.public_key(), hd)?;
163 ecdsa_verify(&x_sign, digest, &sig)?;
164 let vk = k256::ecdsa::VerifyingKey::recover_from_prehash(
166 digest,
167 &sig.to_ecdsa()?,
168 sig.recovery_id()?,
169 )
170 .map_err(|_| Error::VerificationFailed)?;
171 if VerifyingKey::from_affine(x_sign.to_affine()).ok() != Some(vk) {
172 return Err(Error::VerificationFailed);
173 }
174 Ok(sig)
175 }
176}