1#![allow(non_snake_case)]
7
8use curve25519_dalek_signal::constants::RISTRETTO_BASEPOINT_POINT;
9use curve25519_dalek_signal::ristretto::RistrettoPoint;
10use curve25519_dalek_signal::traits::Identity;
11use partial_default::PartialDefault;
12use serde::{Deserialize, Serialize};
13use zkcredential::attributes::Attribute;
14
15use crate::common::array_utils::OneBased;
16use crate::common::constants::*;
17use crate::common::errors::*;
18use crate::common::sho::*;
19use crate::common::simple_types::*;
20use crate::crypto::receipt_struct::ReceiptStruct;
21use crate::crypto::timestamp_struct::TimestampStruct;
22use crate::crypto::{
23 credentials, profile_key_commitment, profile_key_credential_request, profile_key_encryption,
24 profile_key_struct, receipt_credential_request, uid_encryption, uid_struct,
25};
26
27#[derive(Serialize, Deserialize, Clone, PartialDefault)]
28pub struct AuthCredentialWithPniIssuanceProof {
29 poksho_proof: Vec<u8>,
30}
31
32#[derive(Serialize, Deserialize, Clone, PartialDefault)]
33pub struct ProfileKeyCredentialRequestProof {
34 poksho_proof: Vec<u8>,
35}
36
37#[derive(Serialize, Deserialize, Clone, PartialDefault)]
38pub struct ExpiringProfileKeyCredentialIssuanceProof {
39 poksho_proof: Vec<u8>,
40}
41
42#[derive(Serialize, Deserialize, Clone, PartialDefault)]
43pub struct ReceiptCredentialIssuanceProof {
44 poksho_proof: Vec<u8>,
45}
46
47#[derive(Serialize, Deserialize, Clone, PartialDefault)]
48pub struct AuthCredentialWithPniPresentationProof {
49 C_x0: RistrettoPoint,
50 C_x1: RistrettoPoint,
51 C_y1: RistrettoPoint,
52 C_y2: RistrettoPoint,
53 C_y3: RistrettoPoint,
54 C_y4: RistrettoPoint,
55 C_y5: RistrettoPoint,
56 C_V: RistrettoPoint,
57 poksho_proof: Vec<u8>,
58}
59
60#[derive(Serialize, Deserialize, Clone, PartialDefault)]
65pub struct ProfileKeyCredentialPresentationProofV1 {
66 C_x0: RistrettoPoint,
67 C_x1: RistrettoPoint,
68 C_y1: RistrettoPoint,
69 C_y2: RistrettoPoint,
70 C_y3: RistrettoPoint,
71 C_y4: RistrettoPoint,
72 C_V: RistrettoPoint,
73 C_z: RistrettoPoint,
74 poksho_proof: Vec<u8>,
75}
76
77#[derive(Serialize, Deserialize, Clone, PartialDefault)]
82pub struct ProfileKeyCredentialPresentationProofV2 {
83 C_x0: RistrettoPoint,
84 C_x1: RistrettoPoint,
85 C_y1: RistrettoPoint,
86 C_y2: RistrettoPoint,
87 C_y3: RistrettoPoint,
88 C_y4: RistrettoPoint,
89 C_V: RistrettoPoint,
90 C_z: RistrettoPoint,
91 poksho_proof: Vec<u8>,
92}
93
94#[derive(Serialize, Deserialize, Clone, PartialDefault)]
95pub struct ExpiringProfileKeyCredentialPresentationProof {
96 C_x0: RistrettoPoint,
97 C_x1: RistrettoPoint,
98 C_y1: RistrettoPoint,
99 C_y2: RistrettoPoint,
100 C_y3: RistrettoPoint,
101 C_y4: RistrettoPoint,
102 C_y5: RistrettoPoint,
103 C_V: RistrettoPoint,
104 poksho_proof: Vec<u8>,
105}
106
107#[derive(Serialize, Deserialize, Clone, PartialDefault)]
108pub struct ReceiptCredentialPresentationProof {
109 C_x0: RistrettoPoint,
110 C_x1: RistrettoPoint,
111 C_y1: RistrettoPoint,
112 C_y2: RistrettoPoint,
113 C_V: RistrettoPoint,
114 poksho_proof: Vec<u8>,
115}
116
117impl AuthCredentialWithPniIssuanceProof {
118 pub fn get_poksho_statement() -> poksho::Statement {
119 let mut st = poksho::Statement::new();
120 st.add("C_W", &[("w", "G_w"), ("wprime", "G_wprime")]);
121 st.add(
122 "G_V-I",
123 &[
124 ("x0", "G_x0"),
125 ("x1", "G_x1"),
126 ("y1", "G_y1"),
127 ("y2", "G_y2"),
128 ("y3", "G_y3"),
129 ("y4", "G_y4"),
130 ("y5", "G_y5"),
131 ],
132 );
133 st.add(
134 "V",
135 &[
136 ("w", "G_w"),
137 ("x0", "U"),
138 ("x1", "tU"),
139 ("y1", "M1"),
140 ("y2", "M2"),
141 ("y3", "M3"),
142 ("y4", "M4"),
143 ("y5", "M5"),
144 ],
145 );
146 st
147 }
148
149 pub fn new(
150 key_pair: credentials::KeyPair<credentials::AuthCredentialWithPni>,
151 credential: credentials::AuthCredentialWithPni,
152 aci: uid_struct::UidStruct,
153 pni: uid_struct::UidStruct,
154 redemption_time: Timestamp,
155 sho: &mut Sho,
156 ) -> Self {
157 let system = credentials::SystemParams::get_hardcoded();
158
159 let M = OneBased(credentials::convert_to_points_aci_pni_timestamp(
160 aci,
161 pni,
162 redemption_time,
163 ));
164
165 let mut scalar_args = poksho::ScalarArgs::new();
166 scalar_args.add("w", key_pair.w);
167 scalar_args.add("wprime", key_pair.wprime);
168 scalar_args.add("x0", key_pair.x0);
169 scalar_args.add("x1", key_pair.x1);
170 scalar_args.add("y1", key_pair.y[1]);
171 scalar_args.add("y2", key_pair.y[2]);
172 scalar_args.add("y3", key_pair.y[3]);
173 scalar_args.add("y4", key_pair.y[4]);
174 scalar_args.add("y5", key_pair.y[5]);
175
176 let mut point_args = poksho::PointArgs::new();
177 point_args.add("C_W", key_pair.C_W);
178 point_args.add("G_w", system.G_w);
179 point_args.add("G_wprime", system.G_wprime);
180 point_args.add("G_V-I", system.G_V - key_pair.I);
181 point_args.add("G_x0", system.G_x0);
182 point_args.add("G_x1", system.G_x1);
183 point_args.add("G_y1", system.G_y[1]);
184 point_args.add("G_y2", system.G_y[2]);
185 point_args.add("G_y3", system.G_y[3]);
186 point_args.add("G_y4", system.G_y[4]);
187 point_args.add("G_y5", system.G_y[5]);
188 point_args.add("V", credential.V);
189 point_args.add("U", credential.U);
190 point_args.add("tU", credential.t * credential.U);
191 point_args.add("M1", M[1]);
192 point_args.add("M2", M[2]);
193 point_args.add("M3", M[3]);
194 point_args.add("M4", M[4]);
195 point_args.add("M5", M[5]);
196
197 let poksho_proof = Self::get_poksho_statement()
198 .prove(
199 &scalar_args,
200 &point_args,
201 &[],
202 &sho.squeeze(RANDOMNESS_LEN)[..],
203 )
204 .unwrap();
205 Self { poksho_proof }
206 }
207
208 pub fn verify(
209 &self,
210 public_key: credentials::PublicKey,
211 credential: credentials::AuthCredentialWithPni,
212 aci_struct: uid_struct::UidStruct,
213 pni_struct: uid_struct::UidStruct,
214 redemption_time: Timestamp,
215 ) -> Result<(), ZkGroupVerificationFailure> {
216 let system = credentials::SystemParams::get_hardcoded();
217
218 let M = OneBased(credentials::convert_to_points_aci_pni_timestamp(
219 aci_struct,
220 pni_struct,
221 redemption_time,
222 ));
223
224 let mut point_args = poksho::PointArgs::new();
225 point_args.add("C_W", public_key.C_W);
226 point_args.add("G_w", system.G_w);
227 point_args.add("G_wprime", system.G_wprime);
228 point_args.add("G_V-I", system.G_V - public_key.I);
229 point_args.add("G_x0", system.G_x0);
230 point_args.add("G_x1", system.G_x1);
231 point_args.add("G_y1", system.G_y[1]);
232 point_args.add("G_y2", system.G_y[2]);
233 point_args.add("G_y3", system.G_y[3]);
234 point_args.add("G_y4", system.G_y[4]);
235 point_args.add("G_y5", system.G_y[5]);
236 point_args.add("V", credential.V);
237 point_args.add("U", credential.U);
238 point_args.add("tU", credential.t * credential.U);
239 point_args.add("M1", M[1]);
240 point_args.add("M2", M[2]);
241 point_args.add("M3", M[3]);
242 point_args.add("M4", M[4]);
243 point_args.add("M5", M[5]);
244
245 match Self::get_poksho_statement().verify_proof(&self.poksho_proof, &point_args, &[]) {
246 Err(_) => Err(ZkGroupVerificationFailure),
247 Ok(_) => Ok(()),
248 }
249 }
250}
251
252impl ProfileKeyCredentialRequestProof {
253 pub fn get_poksho_statement() -> poksho::Statement {
254 let mut st = poksho::Statement::new();
255 st.add("Y", &[("y", "G")]);
256 st.add("D1", &[("r1", "G")]);
257 st.add("E1", &[("r2", "G")]);
258 st.add("J3", &[("j3", "G_j3")]);
259 st.add("D2-J1", &[("r1", "Y"), ("j3", "-G_j1")]);
260 st.add("E2-J2", &[("r2", "Y"), ("j3", "-G_j2")]);
261 st
262 }
263
264 pub fn new(
265 key_pair: profile_key_credential_request::KeyPair,
266 ciphertext: profile_key_credential_request::CiphertextWithSecretNonce,
267 commitment: profile_key_commitment::CommitmentWithSecretNonce,
268 sho: &mut Sho,
269 ) -> ProfileKeyCredentialRequestProof {
270 let commitment_system = profile_key_commitment::SystemParams::get_hardcoded();
271
272 let mut scalar_args = poksho::ScalarArgs::new();
273 scalar_args.add("y", key_pair.y);
274 scalar_args.add("r1", ciphertext.r1);
275 scalar_args.add("r2", ciphertext.r2);
276 scalar_args.add("j3", commitment.j3);
277
278 let mut point_args = poksho::PointArgs::new();
279 point_args.add("Y", key_pair.Y);
280 point_args.add("D1", ciphertext.D1);
281 point_args.add("E1", ciphertext.E1);
282 point_args.add("J3", commitment.J3);
283 point_args.add("G_j3", commitment_system.G_j3);
284 point_args.add("D2-J1", ciphertext.D2 - commitment.J1);
285 point_args.add("-G_j1", -commitment_system.G_j1);
286 point_args.add("E2-J2", ciphertext.E2 - commitment.J2);
287 point_args.add("-G_j2", -commitment_system.G_j2);
288
289 let poksho_proof = Self::get_poksho_statement()
290 .prove(
291 &scalar_args,
292 &point_args,
293 &[],
294 &sho.squeeze(RANDOMNESS_LEN)[..],
295 )
296 .unwrap();
297 ProfileKeyCredentialRequestProof { poksho_proof }
298 }
299
300 pub fn verify(
301 &self,
302 public_key: profile_key_credential_request::PublicKey,
303 ciphertext: profile_key_credential_request::Ciphertext,
304 commitment: profile_key_commitment::Commitment,
305 ) -> Result<(), ZkGroupVerificationFailure> {
306 let commitment_system = profile_key_commitment::SystemParams::get_hardcoded();
307
308 let mut point_args = poksho::PointArgs::new();
309 point_args.add("Y", public_key.Y);
310 point_args.add("D1", ciphertext.D1);
311 point_args.add("E1", ciphertext.E1);
312 point_args.add("J3", commitment.J3);
313 point_args.add("G_j3", commitment_system.G_j3);
314 point_args.add("D2-J1", ciphertext.D2 - commitment.J1);
315 point_args.add("-G_j1", -commitment_system.G_j1);
316 point_args.add("E2-J2", ciphertext.E2 - commitment.J2);
317 point_args.add("-G_j2", -commitment_system.G_j2);
318
319 match Self::get_poksho_statement().verify_proof(&self.poksho_proof, &point_args, &[]) {
320 Err(_) => Err(ZkGroupVerificationFailure),
321 Ok(_) => Ok(()),
322 }
323 }
324}
325
326impl ExpiringProfileKeyCredentialIssuanceProof {
327 pub fn get_poksho_statement() -> poksho::Statement {
328 let mut st = poksho::Statement::new();
329 st.add("C_W", &[("w", "G_w"), ("wprime", "G_wprime")]);
330 st.add(
331 "G_V-I",
332 &[
333 ("x0", "G_x0"),
334 ("x1", "G_x1"),
335 ("y1", "G_y1"),
336 ("y2", "G_y2"),
337 ("y3", "G_y3"),
338 ("y4", "G_y4"),
339 ("y5", "G_y5"),
340 ],
341 );
342 st.add("S1", &[("y3", "D1"), ("y4", "E1"), ("rprime", "G")]);
343 st.add(
344 "S2",
345 &[
346 ("y3", "D2"),
347 ("y4", "E2"),
348 ("rprime", "Y"),
349 ("w", "G_w"),
350 ("x0", "U"),
351 ("x1", "tU"),
352 ("y1", "M1"),
353 ("y2", "M2"),
354 ("y5", "M5"),
355 ],
356 );
357 st
358 }
359
360 pub fn new(
361 key_pair: credentials::KeyPair<credentials::ExpiringProfileKeyCredential>,
362 request_public_key: profile_key_credential_request::PublicKey,
363 request: profile_key_credential_request::Ciphertext,
364 blinded_credential: credentials::BlindedExpiringProfileKeyCredentialWithSecretNonce,
365 uid: uid_struct::UidStruct,
366 credential_expiration_time: Timestamp,
367 sho: &mut Sho,
368 ) -> Self {
369 let credentials_system = credentials::SystemParams::get_hardcoded();
370
371 let m5 = TimestampStruct::calc_m_from(credential_expiration_time);
372 let M5 = m5 * credentials_system.G_m5;
373
374 let mut scalar_args = poksho::ScalarArgs::new();
375 scalar_args.add("w", key_pair.w);
376 scalar_args.add("wprime", key_pair.wprime);
377 scalar_args.add("x0", key_pair.x0);
378 scalar_args.add("x1", key_pair.x1);
379 scalar_args.add("y1", key_pair.y[1]);
380 scalar_args.add("y2", key_pair.y[2]);
381 scalar_args.add("y3", key_pair.y[3]);
382 scalar_args.add("y4", key_pair.y[4]);
383 scalar_args.add("y5", key_pair.y[5]);
384 scalar_args.add("rprime", blinded_credential.rprime);
385
386 let mut point_args = poksho::PointArgs::new();
387 point_args.add("C_W", key_pair.C_W);
388 point_args.add("G_w", credentials_system.G_w);
389 point_args.add("G_wprime", credentials_system.G_wprime);
390 point_args.add("G_V-I", credentials_system.G_V - key_pair.I);
391 point_args.add("G_x0", credentials_system.G_x0);
392 point_args.add("G_x1", credentials_system.G_x1);
393 point_args.add("G_y1", credentials_system.G_y[1]);
394 point_args.add("G_y2", credentials_system.G_y[2]);
395 point_args.add("G_y3", credentials_system.G_y[3]);
396 point_args.add("G_y4", credentials_system.G_y[4]);
397 point_args.add("G_y5", credentials_system.G_y[5]);
398 point_args.add("S1", blinded_credential.S1);
399 point_args.add("D1", request.D1);
400 point_args.add("E1", request.E1);
401 point_args.add("S2", blinded_credential.S2);
402 point_args.add("D2", request.D2);
403 point_args.add("E2", request.E2);
404 point_args.add("Y", request_public_key.Y);
405 point_args.add("U", blinded_credential.U);
406 point_args.add("tU", blinded_credential.t * blinded_credential.U);
407 point_args.add("M1", uid.M1);
408 point_args.add("M2", uid.M2);
409 point_args.add("M5", M5);
410
411 let poksho_proof = Self::get_poksho_statement()
412 .prove(
413 &scalar_args,
414 &point_args,
415 &[],
416 &sho.squeeze(RANDOMNESS_LEN)[..],
417 )
418 .unwrap();
419 ExpiringProfileKeyCredentialIssuanceProof { poksho_proof }
420 }
421
422 pub fn verify(
423 &self,
424 credentials_public_key: credentials::PublicKey,
425 request_public_key: profile_key_credential_request::PublicKey,
426 aci_bytes: UidBytes,
427 request: profile_key_credential_request::Ciphertext,
428 blinded_credential: credentials::BlindedExpiringProfileKeyCredential,
429 credential_expiration_time: Timestamp,
430 ) -> Result<(), ZkGroupVerificationFailure> {
431 let credentials_system = credentials::SystemParams::get_hardcoded();
432 let aci = libsignal_core::Aci::from_uuid_bytes(aci_bytes);
433 let uid = uid_struct::UidStruct::from_service_id(aci.into());
434
435 let m5 = TimestampStruct::calc_m_from(credential_expiration_time);
436 let M5 = m5 * credentials_system.G_m5;
437
438 let mut point_args = poksho::PointArgs::new();
439 point_args.add("C_W", credentials_public_key.C_W);
440 point_args.add("G_w", credentials_system.G_w);
441 point_args.add("G_wprime", credentials_system.G_wprime);
442 point_args.add("G_V-I", credentials_system.G_V - credentials_public_key.I);
443 point_args.add("G_x0", credentials_system.G_x0);
444 point_args.add("G_x1", credentials_system.G_x1);
445 point_args.add("G_y1", credentials_system.G_y[1]);
446 point_args.add("G_y2", credentials_system.G_y[2]);
447 point_args.add("G_y3", credentials_system.G_y[3]);
448 point_args.add("G_y4", credentials_system.G_y[4]);
449 point_args.add("G_y5", credentials_system.G_y[5]);
450 point_args.add("S1", blinded_credential.S1);
451 point_args.add("D1", request.D1);
452 point_args.add("E1", request.E1);
453 point_args.add("S2", blinded_credential.S2);
454 point_args.add("D2", request.D2);
455 point_args.add("E2", request.E2);
456 point_args.add("Y", request_public_key.Y);
457 point_args.add("U", blinded_credential.U);
458 point_args.add("tU", blinded_credential.t * blinded_credential.U);
459 point_args.add("M1", uid.M1);
460 point_args.add("M2", uid.M2);
461 point_args.add("M5", M5);
462
463 match Self::get_poksho_statement().verify_proof(&self.poksho_proof, &point_args, &[]) {
464 Err(_) => Err(ZkGroupVerificationFailure),
465 Ok(_) => Ok(()),
466 }
467 }
468}
469
470impl ReceiptCredentialIssuanceProof {
471 pub fn get_poksho_statement() -> poksho::Statement {
472 let mut st = poksho::Statement::new();
473
474 st.add("C_W", &[("w", "G_w"), ("wprime", "G_wprime")]);
475 st.add(
476 "G_V-I",
477 &[
478 ("x0", "G_x0"),
479 ("x1", "G_x1"),
480 ("y1", "G_y1"),
481 ("y2", "G_y2"),
482 ],
483 );
484 st.add("S1", &[("y2", "D1"), ("rprime", "G")]);
485 st.add(
486 "S2",
487 &[
488 ("y2", "D2"),
489 ("rprime", "Y"),
490 ("w", "G_w"),
491 ("x0", "U"),
492 ("x1", "tU"),
493 ("y1", "M1"),
494 ],
495 );
496 st
497 }
498
499 pub fn new(
500 key_pair: credentials::KeyPair<credentials::ReceiptCredential>,
501 request_public_key: receipt_credential_request::PublicKey,
502 request: receipt_credential_request::Ciphertext,
503 blinded_credential: credentials::BlindedReceiptCredentialWithSecretNonce,
504 receipt_expiration_time: Timestamp,
505 receipt_level: ReceiptLevel,
506 sho: &mut Sho,
507 ) -> Self {
508 let credentials_system = credentials::SystemParams::get_hardcoded();
509
510 let m1 = ReceiptStruct::calc_m1_from(receipt_expiration_time, receipt_level);
511
512 let mut scalar_args = poksho::ScalarArgs::new();
513 scalar_args.add("w", key_pair.w);
514 scalar_args.add("wprime", key_pair.wprime);
515 scalar_args.add("x0", key_pair.x0);
516 scalar_args.add("x1", key_pair.x1);
517 scalar_args.add("y1", key_pair.y[1]);
518 scalar_args.add("y2", key_pair.y[2]);
519 scalar_args.add("rprime", blinded_credential.rprime);
520
521 let mut point_args = poksho::PointArgs::new();
522 point_args.add("C_W", key_pair.C_W);
523 point_args.add("G_w", credentials_system.G_w);
524 point_args.add("G_wprime", credentials_system.G_wprime);
525 point_args.add("G_V-I", credentials_system.G_V - key_pair.I);
526 point_args.add("G_x0", credentials_system.G_x0);
527 point_args.add("G_x1", credentials_system.G_x1);
528 point_args.add("G_y1", credentials_system.G_y[1]);
529 point_args.add("G_y2", credentials_system.G_y[2]);
530 point_args.add("S1", blinded_credential.S1);
531 point_args.add("D1", request.D1);
532 point_args.add("S2", blinded_credential.S2);
533 point_args.add("D2", request.D2);
534 point_args.add("Y", request_public_key.Y);
535 point_args.add("U", blinded_credential.U);
536 point_args.add("tU", blinded_credential.t * blinded_credential.U);
537 point_args.add("M1", m1 * credentials_system.G_m1);
538
539 let poksho_proof = Self::get_poksho_statement()
540 .prove(
541 &scalar_args,
542 &point_args,
543 &[],
544 &sho.squeeze(RANDOMNESS_LEN)[..],
545 )
546 .unwrap();
547 Self { poksho_proof }
548 }
549
550 pub fn verify(
551 &self,
552 credentials_public_key: credentials::PublicKey,
553 request_public_key: receipt_credential_request::PublicKey,
554 request: receipt_credential_request::Ciphertext,
555 blinded_credential: credentials::BlindedReceiptCredential,
556 receipt_struct: ReceiptStruct,
557 ) -> Result<(), ZkGroupVerificationFailure> {
558 let credentials_system = credentials::SystemParams::get_hardcoded();
559
560 let M = credentials::convert_to_points_receipt_struct(receipt_struct);
561
562 let mut point_args = poksho::PointArgs::new();
563 point_args.add("C_W", credentials_public_key.C_W);
564 point_args.add("G_w", credentials_system.G_w);
565 point_args.add("G_wprime", credentials_system.G_wprime);
566 point_args.add("G_V-I", credentials_system.G_V - credentials_public_key.I);
567 point_args.add("G_x0", credentials_system.G_x0);
568 point_args.add("G_x1", credentials_system.G_x1);
569 point_args.add("G_y1", credentials_system.G_y[1]);
570 point_args.add("G_y2", credentials_system.G_y[2]);
571 point_args.add("S1", blinded_credential.S1);
572 point_args.add("D1", request.D1);
573 point_args.add("S2", blinded_credential.S2);
574 point_args.add("D2", request.D2);
575 point_args.add("Y", request_public_key.Y);
576 point_args.add("U", blinded_credential.U);
577 point_args.add("tU", blinded_credential.t * blinded_credential.U);
578 point_args.add("M1", M[0]);
579
580 match Self::get_poksho_statement().verify_proof(&self.poksho_proof, &point_args, &[]) {
581 Err(_) => Err(ZkGroupVerificationFailure),
582 Ok(_) => Ok(()),
583 }
584 }
585}
586
587impl AuthCredentialWithPniPresentationProof {
588 pub fn get_poksho_statement() -> poksho::Statement {
589 let mut st = poksho::Statement::new();
590 st.add("Z", &[("z", "I")]);
591 st.add("C_x1", &[("t", "C_x0"), ("z0", "G_x0"), ("z", "G_x1")]);
592 st.add("A", &[("a1", "G_a1"), ("a2", "G_a2")]);
593 st.add("C_y2-E_A2", &[("z", "G_y2"), ("a2", "-E_A1")]);
594 st.add("E_A1", &[("a1", "C_y1"), ("z1", "G_y1")]);
595 st.add("C_y4-E_B2", &[("z", "G_y4"), ("a2", "-E_B1")]);
596 st.add("E_B1", &[("a1", "C_y3"), ("z1", "G_y3")]);
597 st.add("0", &[("z1", "I"), ("a1", "Z")]);
598 st
599 }
600
601 #[allow(clippy::too_many_arguments)]
602 pub fn new(
603 credentials_public_key: credentials::PublicKey,
604 uid_enc_key_pair: uid_encryption::KeyPair,
605 credential: credentials::AuthCredentialWithPni,
606 aci: uid_struct::UidStruct,
607 aci_ciphertext: uid_encryption::Ciphertext,
608 pni: uid_struct::UidStruct,
609 pni_ciphertext: uid_encryption::Ciphertext,
610 redemption_time: Timestamp,
611 sho: &mut Sho,
612 ) -> Self {
613 let credentials_system = credentials::SystemParams::get_hardcoded();
614 let uid_system = uid_encryption::SystemParams::get_hardcoded();
615 let M = OneBased(credentials::convert_to_points_aci_pni_timestamp(
616 aci,
617 pni,
618 redemption_time,
619 ));
620
621 let z = sho.get_scalar();
622
623 let C_y1 = z * credentials_system.G_y[1] + M[1];
624 let C_y2 = z * credentials_system.G_y[2] + M[2];
625 let C_y3 = z * credentials_system.G_y[3] + M[3];
626 let C_y4 = z * credentials_system.G_y[4] + M[4];
627 let C_y5 = z * credentials_system.G_y[5];
628
629 let C_x0 = z * credentials_system.G_x0 + credential.U;
630 let C_V = z * credentials_system.G_V + credential.V;
631 let C_x1 = z * credentials_system.G_x1 + credential.t * credential.U;
632
633 let z0 = -z * credential.t;
634 let z1 = -z * uid_enc_key_pair.a1;
635
636 let I = credentials_public_key.I;
637 let Z = z * I;
638
639 let [E_A1, E_A2] = aci_ciphertext.as_points();
640 let [E_B1, E_B2] = pni_ciphertext.as_points();
641
642 let mut scalar_args = poksho::ScalarArgs::new();
644 scalar_args.add("z", z);
645 scalar_args.add("t", credential.t);
646 scalar_args.add("z0", z0);
647 scalar_args.add("a1", uid_enc_key_pair.a1);
648 scalar_args.add("a2", uid_enc_key_pair.a2);
649 scalar_args.add("z1", z1);
650
651 let mut point_args = poksho::PointArgs::new();
653 point_args.add("Z", Z);
654 point_args.add("I", I);
655
656 point_args.add("C_x1", C_x1);
657 point_args.add("C_x0", C_x0);
658 point_args.add("G_x0", credentials_system.G_x0);
659 point_args.add("G_x1", credentials_system.G_x1);
660
661 point_args.add("A", uid_enc_key_pair.public_key.A);
662 point_args.add("G_a1", uid_system.G_a1);
663 point_args.add("G_a2", uid_system.G_a2);
664
665 point_args.add("C_y2-E_A2", C_y2 - E_A2);
666 point_args.add("G_y2", credentials_system.G_y[2]);
667 point_args.add("-E_A1", -E_A1);
668 point_args.add("E_A1", E_A1);
669 point_args.add("C_y1", C_y1);
670 point_args.add("G_y1", credentials_system.G_y[1]);
671
672 point_args.add("C_y4-E_B2", C_y4 - E_B2);
673 point_args.add("G_y4", credentials_system.G_y[4]);
674 point_args.add("-E_B1", -E_B1);
675 point_args.add("E_B1", E_B1);
676 point_args.add("C_y3", C_y3);
677 point_args.add("G_y3", credentials_system.G_y[3]);
678 point_args.add("0", RistrettoPoint::identity());
679
680 let poksho_proof = Self::get_poksho_statement()
681 .prove(
682 &scalar_args,
683 &point_args,
684 &[],
685 &sho.squeeze(RANDOMNESS_LEN)[..],
686 )
687 .unwrap();
688
689 Self {
690 C_x0,
691 C_x1,
692 C_y1,
693 C_y2,
694 C_y3,
695 C_y4,
696 C_y5,
697 C_V,
698 poksho_proof,
699 }
700 }
701
702 pub fn verify(
703 &self,
704 credentials_key_pair: credentials::KeyPair<credentials::AuthCredentialWithPni>,
705 uid_enc_public_key: uid_encryption::PublicKey,
706 aci_ciphertext: uid_encryption::Ciphertext,
707 pni_ciphertext: uid_encryption::Ciphertext,
708 redemption_time: Timestamp,
709 ) -> Result<(), ZkGroupVerificationFailure> {
710 let uid_enc_system = uid_encryption::SystemParams::get_hardcoded();
711 let credentials_system = credentials::SystemParams::get_hardcoded();
712
713 let Self {
714 C_x0,
715 C_x1,
716 C_y1,
717 C_y2,
718 C_y3,
719 C_y4,
720 C_y5,
721 C_V,
722 poksho_proof,
723 } = self;
724
725 let (C_x0, C_x1, C_y1, C_y2, C_y3, C_y4, C_y5, C_V) =
726 (*C_x0, *C_x1, *C_y1, *C_y2, *C_y3, *C_y4, *C_y5, *C_V);
727
728 let credentials::KeyPair {
729 W,
730 x0,
731 x1,
732 y: OneBased([y1, y2, y3, y4, y5]),
733 I,
734 ..
735 } = credentials_key_pair;
736
737 let [E_A1, E_A2] = aci_ciphertext.as_points();
738 let [E_B1, E_B2] = pni_ciphertext.as_points();
739 let m5 = TimestampStruct::calc_m_from(redemption_time);
740 let M5 = m5 * credentials_system.G_m5;
741 let Z = C_V
742 - W
743 - x0 * C_x0
744 - x1 * C_x1
745 - y1 * C_y1
746 - y2 * C_y2
747 - y3 * C_y3
748 - y4 * C_y4
749 - y5 * (C_y5 + M5);
750
751 let mut point_args = poksho::PointArgs::new();
753 point_args.add("Z", Z);
754 point_args.add("I", I);
755 point_args.add("C_x1", C_x1);
756 point_args.add("C_x0", C_x0);
757 point_args.add("G_x0", credentials_system.G_x0);
758 point_args.add("G_x1", credentials_system.G_x1);
759
760 point_args.add("A", uid_enc_public_key.A);
761 point_args.add("G_a1", uid_enc_system.G_a1);
762 point_args.add("G_a2", uid_enc_system.G_a2);
763
764 point_args.add("C_y2-E_A2", C_y2 - E_A2);
765 point_args.add("G_y2", credentials_system.G_y[2]);
766 point_args.add("-E_A1", -E_A1);
767 point_args.add("E_A1", E_A1);
768 point_args.add("C_y1", C_y1);
769 point_args.add("G_y1", credentials_system.G_y[1]);
770
771 point_args.add("C_y4-E_B2", C_y4 - E_B2);
772 point_args.add("G_y4", credentials_system.G_y[4]);
773 point_args.add("-E_B1", -E_B1);
774 point_args.add("E_B1", E_B1);
775 point_args.add("C_y3", C_y3);
776 point_args.add("G_y3", credentials_system.G_y[3]);
777 point_args.add("0", RistrettoPoint::identity());
778
779 match Self::get_poksho_statement().verify_proof(poksho_proof, &point_args, &[]) {
780 Err(_) => Err(ZkGroupVerificationFailure),
781 Ok(_) => Ok(()),
782 }
783 }
784}
785
786impl ProfileKeyCredentialPresentationProofV1 {
787 pub(crate) fn from_invalid_proof(poksho_proof: Vec<u8>) -> Self {
788 Self {
789 C_x0: RISTRETTO_BASEPOINT_POINT,
790 C_x1: RISTRETTO_BASEPOINT_POINT,
791 C_y1: RISTRETTO_BASEPOINT_POINT,
792 C_y2: RISTRETTO_BASEPOINT_POINT,
793 C_y3: RISTRETTO_BASEPOINT_POINT,
794 C_y4: RISTRETTO_BASEPOINT_POINT,
795 C_V: RISTRETTO_BASEPOINT_POINT,
796 C_z: RISTRETTO_BASEPOINT_POINT,
797 poksho_proof,
798 }
799 }
800}
801
802impl ExpiringProfileKeyCredentialPresentationProof {
803 pub fn get_poksho_statement() -> poksho::Statement {
804 let mut st = poksho::Statement::new();
805 st.add("Z", &[("z", "I")]);
806 st.add("C_x1", &[("t", "C_x0"), ("z0", "G_x0"), ("z", "G_x1")]);
807 st.add(
808 "A+B",
809 &[
810 ("a1", "G_a1"),
811 ("a2", "G_a2"),
812 ("b1", "G_b1"),
813 ("b2", "G_b2"),
814 ],
815 );
816 st.add("C_y2-E_A2", &[("z", "G_y2"), ("a2", "-E_A1")]);
817 st.add("E_A1", &[("a1", "C_y1"), ("z1", "G_y1")]);
818 st.add("C_y4-E_B2", &[("z", "G_y4"), ("b2", "-E_B1")]);
819 st.add("E_B1", &[("b1", "C_y3"), ("z2", "G_y3")]);
820 st.add("0", &[("z1", "I"), ("a1", "Z")]);
821 st.add("0", &[("z2", "I"), ("b1", "Z")]);
822 st
823 }
824
825 #[allow(clippy::too_many_arguments)]
826 pub fn new(
827 uid_enc_key_pair: uid_encryption::KeyPair,
828 profile_key_enc_key_pair: profile_key_encryption::KeyPair,
829 credentials_public_key: credentials::PublicKey,
830 credential: credentials::ExpiringProfileKeyCredential,
831 uid_ciphertext: uid_encryption::Ciphertext,
832 profile_key_ciphertext: profile_key_encryption::Ciphertext,
833 aci_bytes: UidBytes,
834 profile_key_bytes: ProfileKeyBytes,
835 sho: &mut Sho,
836 ) -> Self {
837 let credentials_system = credentials::SystemParams::get_hardcoded();
838 let uid_system = uid_encryption::SystemParams::get_hardcoded();
839 let profile_key_system = profile_key_encryption::SystemParams::get_hardcoded();
840 let aci = libsignal_core::Aci::from_uuid_bytes(aci_bytes);
841 let uid = uid_struct::UidStruct::from_service_id(aci.into());
842 let profile_key = profile_key_struct::ProfileKeyStruct::new(profile_key_bytes, aci_bytes);
843
844 let z = sho.get_scalar();
845
846 let C_y1 = z * credentials_system.G_y[1] + uid.M1;
847 let C_y2 = z * credentials_system.G_y[2] + uid.M2;
848 let C_y3 = z * credentials_system.G_y[3] + profile_key.M3;
849 let C_y4 = z * credentials_system.G_y[4] + profile_key.M4;
850 let C_y5 = z * credentials_system.G_y[5];
851
852 let C_x0 = z * credentials_system.G_x0 + credential.U;
853 let C_V = z * credentials_system.G_V + credential.V;
854 let C_x1 = z * credentials_system.G_x1 + credential.t * credential.U;
855
856 let z0 = -z * credential.t;
857 let z1 = -z * uid_enc_key_pair.a1;
858 let z2 = -z * profile_key_enc_key_pair.a1;
859
860 let I = credentials_public_key.I;
861 let Z = z * I;
862
863 let [E_A1, E_A2] = uid_ciphertext.as_points();
864 let [E_B1, E_B2] = profile_key_ciphertext.as_points();
865
866 let mut scalar_args = poksho::ScalarArgs::new();
868 scalar_args.add("z", z);
869 scalar_args.add("t", credential.t);
870 scalar_args.add("z0", z0);
871 scalar_args.add("a1", uid_enc_key_pair.a1);
872 scalar_args.add("a2", uid_enc_key_pair.a2);
873 scalar_args.add("b1", profile_key_enc_key_pair.a1);
874 scalar_args.add("b2", profile_key_enc_key_pair.a2);
875 scalar_args.add("z1", z1);
876 scalar_args.add("z2", z2);
877
878 let mut point_args = poksho::PointArgs::new();
880 point_args.add("Z", Z);
881 point_args.add("I", I);
882
883 point_args.add("C_x1", C_x1);
884 point_args.add("C_x0", C_x0);
885 point_args.add("G_x0", credentials_system.G_x0);
886 point_args.add("G_x1", credentials_system.G_x1);
887
888 point_args.add(
889 "A+B",
890 uid_enc_key_pair.public_key.A + profile_key_enc_key_pair.public_key.A,
891 );
892 point_args.add("G_a1", uid_system.G_a1);
893 point_args.add("G_a2", uid_system.G_a2);
894 point_args.add("G_b1", profile_key_system.G_b1);
895 point_args.add("G_b2", profile_key_system.G_b2);
896
897 point_args.add("C_y2-E_A2", C_y2 - E_A2);
898 point_args.add("G_y2", credentials_system.G_y[2]);
899 point_args.add("-E_A1", -E_A1);
900 point_args.add("E_A1", E_A1);
901 point_args.add("C_y1", C_y1);
902 point_args.add("G_y1", credentials_system.G_y[1]);
903
904 point_args.add("C_y4-E_B2", C_y4 - E_B2);
905 point_args.add("G_y4", credentials_system.G_y[4]);
906 point_args.add("-E_B1", -E_B1);
907 point_args.add("E_B1", E_B1);
908 point_args.add("C_y3", C_y3);
909 point_args.add("G_y3", credentials_system.G_y[3]);
910 point_args.add("0", RistrettoPoint::identity());
911
912 let poksho_proof = Self::get_poksho_statement()
913 .prove(
914 &scalar_args,
915 &point_args,
916 &[],
917 &sho.squeeze(RANDOMNESS_LEN)[..],
918 )
919 .unwrap();
920
921 ExpiringProfileKeyCredentialPresentationProof {
922 C_y1,
923 C_y2,
924 C_y3,
925 C_y4,
926 C_y5,
927 C_x0,
928 C_x1,
929 C_V,
930 poksho_proof,
931 }
932 }
933
934 pub fn verify(
935 &self,
936 credentials_key_pair: credentials::KeyPair<credentials::ExpiringProfileKeyCredential>,
937 uid_ciphertext: uid_encryption::Ciphertext,
938 uid_enc_public_key: uid_encryption::PublicKey,
939 profile_key_ciphertext: profile_key_encryption::Ciphertext,
940 profile_key_enc_public_key: profile_key_encryption::PublicKey,
941 credential_expiration_time: Timestamp,
942 ) -> Result<(), ZkGroupVerificationFailure> {
943 let uid_enc_system = uid_encryption::SystemParams::get_hardcoded();
944 let profile_key_enc_system = profile_key_encryption::SystemParams::get_hardcoded();
945 let credentials_system = credentials::SystemParams::get_hardcoded();
946
947 let Self {
948 C_x0,
949 C_x1,
950 C_y1,
951 C_y2,
952 C_y3,
953 C_y4,
954 C_y5,
955 C_V,
956 poksho_proof,
957 } = self;
958
959 let (C_x0, C_x1, C_y1, C_y2, C_y3, C_y4, C_V) =
960 (*C_x0, *C_x1, *C_y1, *C_y2, *C_y3, *C_y4, *C_V);
961
962 let credentials::KeyPair {
963 W,
964 x0,
965 x1,
966 y: OneBased([y1, y2, y3, y4, y5]),
967 I,
968 ..
969 } = credentials_key_pair;
970
971 let [E_A1, E_A2] = uid_ciphertext.as_points();
972 let [E_B1, E_B2] = profile_key_ciphertext.as_points();
973 let m5 = TimestampStruct::calc_m_from(credential_expiration_time);
974 let M5 = m5 * credentials_system.G_m5;
975
976 let Z = C_V
977 - W
978 - x0 * C_x0
979 - x1 * C_x1
980 - (y1 * C_y1)
981 - (y2 * C_y2)
982 - (y3 * C_y3)
983 - (y4 * C_y4)
984 - (y5 * (C_y5 + M5));
985
986 let mut point_args = poksho::PointArgs::new();
988 point_args.add("Z", Z);
989 point_args.add("I", I);
990 point_args.add("C_x1", C_x1);
991 point_args.add("C_x0", C_x0);
992 point_args.add("G_x0", credentials_system.G_x0);
993 point_args.add("G_x1", credentials_system.G_x1);
994
995 point_args.add("A+B", uid_enc_public_key.A + profile_key_enc_public_key.A);
996 point_args.add("G_a1", uid_enc_system.G_a1);
997 point_args.add("G_a2", uid_enc_system.G_a2);
998 point_args.add("G_b1", profile_key_enc_system.G_b1);
999 point_args.add("G_b2", profile_key_enc_system.G_b2);
1000
1001 point_args.add("C_y2-E_A2", C_y2 - E_A2);
1002 point_args.add("G_y2", credentials_system.G_y[2]);
1003 point_args.add("-E_A1", -E_A1);
1004 point_args.add("E_A1", E_A1);
1005 point_args.add("C_y1", C_y1);
1006 point_args.add("G_y1", credentials_system.G_y[1]);
1007
1008 point_args.add("C_y4-E_B2", C_y4 - E_B2);
1009 point_args.add("G_y4", credentials_system.G_y[4]);
1010 point_args.add("-E_B1", -E_B1);
1011 point_args.add("E_B1", E_B1);
1012 point_args.add("C_y3", C_y3);
1013 point_args.add("G_y3", credentials_system.G_y[3]);
1014 point_args.add("0", RistrettoPoint::identity());
1015
1016 match Self::get_poksho_statement().verify_proof(poksho_proof, &point_args, &[]) {
1017 Err(_) => Err(ZkGroupVerificationFailure),
1018 Ok(_) => Ok(()),
1019 }
1020 }
1021}
1022
1023impl ReceiptCredentialPresentationProof {
1024 pub fn get_poksho_statement() -> poksho::Statement {
1025 let mut st = poksho::Statement::new();
1026
1027 st.add("Z", &[("z", "I")]);
1028 st.add("C_x1", &[("t", "C_x0"), ("-zt", "G_x0"), ("z", "G_x1")]);
1029 st.add("C_y1", &[("z", "G_y1")]);
1030 st.add("C_y2", &[("z", "G_y2")]);
1031 st
1032 }
1033
1034 pub fn new(
1035 credentials_public_key: credentials::PublicKey,
1036 credential: credentials::ReceiptCredential,
1037 sho: &mut Sho,
1038 ) -> Self {
1039 let credentials_system = credentials::SystemParams::get_hardcoded();
1040
1041 let z = sho.get_scalar();
1042
1043 let C_y1 = z * credentials_system.G_y[1];
1044 let C_y2 = z * credentials_system.G_y[2];
1045
1046 let I = credentials_public_key.I;
1047 let Z = z * I;
1048 let C_x0 = z * credentials_system.G_x0 + credential.U;
1049 let C_x1 = z * credentials_system.G_x1 + credential.t * credential.U;
1050 let C_V = z * credentials_system.G_V + credential.V;
1051
1052 let mut scalar_args = poksho::ScalarArgs::new();
1054 scalar_args.add("z", z);
1055 scalar_args.add("t", credential.t);
1056 scalar_args.add("-zt", -z * credential.t);
1057
1058 let mut point_args = poksho::PointArgs::new();
1060 point_args.add("Z", Z);
1061 point_args.add("I", I);
1062 point_args.add("C_x0", C_x0);
1063 point_args.add("C_x1", C_x1);
1064 point_args.add("C_y1", C_y1);
1065 point_args.add("C_y2", C_y2);
1066 point_args.add("G_x0", credentials_system.G_x0);
1067 point_args.add("G_x1", credentials_system.G_x1);
1068 point_args.add("G_y1", credentials_system.G_y[1]);
1069 point_args.add("G_y2", credentials_system.G_y[2]);
1070
1071 let poksho_proof = Self::get_poksho_statement()
1072 .prove(
1073 &scalar_args,
1074 &point_args,
1075 &[],
1076 &sho.squeeze(RANDOMNESS_LEN)[..],
1077 )
1078 .unwrap();
1079
1080 Self {
1081 C_x0,
1082 C_x1,
1083 C_y1,
1084 C_y2,
1085 C_V,
1086 poksho_proof,
1087 }
1088 }
1089
1090 pub fn verify(
1091 &self,
1092 credentials_key_pair: credentials::KeyPair<credentials::ReceiptCredential>,
1093 receipt_struct: ReceiptStruct,
1094 ) -> Result<(), ZkGroupVerificationFailure> {
1095 let credentials_system = credentials::SystemParams::get_hardcoded();
1096 let M = credentials::convert_to_points_receipt_struct(receipt_struct);
1097
1098 let Self {
1099 C_x0,
1100 C_x1,
1101 C_y1,
1102 C_y2,
1103 C_V,
1104 poksho_proof,
1105 } = self;
1106 let (C_x0, C_x1, C_y1, C_y2, C_V) = (*C_x0, *C_x1, *C_y1, *C_y2, *C_V);
1107
1108 let credentials::KeyPair {
1109 W,
1110 x0,
1111 x1,
1112 y: OneBased([y1, y2, ..]),
1113 I,
1114 ..
1115 } = credentials_key_pair;
1116
1117 let Z = C_V - W - x0 * C_x0 - x1 * C_x1 - y1 * (C_y1 + M[0]) - y2 * (C_y2 + M[1]);
1118
1119 let mut point_args = poksho::PointArgs::new();
1121 point_args.add("Z", Z);
1122 point_args.add("I", I);
1123 point_args.add("C_x0", C_x0);
1124 point_args.add("C_x1", C_x1);
1125 point_args.add("C_y1", C_y1);
1126 point_args.add("C_y2", C_y2);
1127 point_args.add("G_x0", credentials_system.G_x0);
1128 point_args.add("G_x1", credentials_system.G_x1);
1129 point_args.add("G_y1", credentials_system.G_y[1]);
1130 point_args.add("G_y2", credentials_system.G_y[2]);
1131
1132 match Self::get_poksho_statement().verify_proof(poksho_proof, &point_args, &[]) {
1133 Err(_) => Err(ZkGroupVerificationFailure),
1134 Ok(_) => Ok(()),
1135 }
1136 }
1137}