blockage_migration.rs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. /*! A module for the protocol for the user of trust level 3 or higher to
  2. migrate from one bucket to another because their current bucket has been
  3. blocked. Their trust level will go down by 2.
  4. The user presents their current Lox credential:
  5. - id: revealed
  6. - bucket: blinded
  7. - trust_level: revealed to be 3 or higher
  8. - level_since: blinded
  9. - invites_remaining: blinded
  10. - blockages: blinded
  11. and a Migration credential:
  12. - id: revealed as the same as the Lox credential id above
  13. - from_bucket: blinded, but proved in ZK that it's the same as the
  14. bucket in the Lox credential above
  15. - to_bucket: blinded
  16. and a new Lox credential to be issued:
  17. - id: jointly chosen by the user and BA
  18. - bucket: blinded, but proved in ZK that it's the same as the to_bucket
  19. in the Migration credential above
  20. - trust_level: revealed to be 2 less than the trust_level above
  21. - level_since: today
  22. - invites_remaining: revealed to be LEVEL_INVITATIONS for the new trust
  23. level [Actually, there's a bug in the zkp crate that's triggered when
  24. a public value is 0 (the identity element of the Ristretto group), so
  25. we treat this field as blinded, but the _server_ encrypts the value.]
  26. - blockages: blinded, but proved in ZK that it's one more than the
  27. blockages above
  28. */
  29. use curve25519_dalek::ristretto::RistrettoBasepointTable;
  30. use curve25519_dalek::ristretto::RistrettoPoint;
  31. use curve25519_dalek::scalar::Scalar;
  32. use curve25519_dalek::traits::IsIdentity;
  33. use zkp::CompactProof;
  34. use zkp::ProofError;
  35. use zkp::Transcript;
  36. use serde::{Deserialize, Serialize};
  37. use super::super::cred;
  38. use super::super::dup_filter::SeenType;
  39. use super::super::migration_table::MigrationType;
  40. use super::super::scalar_u32;
  41. use super::super::{BridgeAuth, IssuerPubKey};
  42. use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
  43. use super::check_blockage::MIN_TRUST_LEVEL;
  44. use super::level_up::LEVEL_INVITATIONS;
  45. #[derive(Serialize, Deserialize)]
  46. pub struct Request {
  47. // Fields for blind showing the Lox credential
  48. P_lox: RistrettoPoint,
  49. id: Scalar,
  50. CBucket: RistrettoPoint,
  51. trust_level: Scalar,
  52. CSince: RistrettoPoint,
  53. CInvRemain: RistrettoPoint,
  54. CBlockages: RistrettoPoint,
  55. CQ_lox: RistrettoPoint,
  56. // Fields for blind showing the Migration credential
  57. P_mig: RistrettoPoint,
  58. CFromBucket: RistrettoPoint,
  59. CToBucket: RistrettoPoint,
  60. CQ_mig: RistrettoPoint,
  61. // Fields for user blinding of the Lox credential to be issued
  62. D: RistrettoPoint,
  63. EncIdClient: (RistrettoPoint, RistrettoPoint),
  64. EncBucket: (RistrettoPoint, RistrettoPoint),
  65. EncBlockages: (RistrettoPoint, RistrettoPoint),
  66. // The combined ZKP
  67. piUser: CompactProof,
  68. }
  69. #[derive(Debug)]
  70. pub struct State {
  71. d: Scalar,
  72. D: RistrettoPoint,
  73. EncIdClient: (RistrettoPoint, RistrettoPoint),
  74. EncBucket: (RistrettoPoint, RistrettoPoint),
  75. EncBlockages: (RistrettoPoint, RistrettoPoint),
  76. id_client: Scalar,
  77. to_bucket: Scalar,
  78. trust_level: Scalar,
  79. blockages: Scalar,
  80. }
  81. #[derive(Serialize, Deserialize)]
  82. pub struct Response {
  83. // The new attributes; the trust_level and invites_remaining are
  84. // implicit
  85. level_since: Scalar,
  86. // The fields for the new Lox credential
  87. P: RistrettoPoint,
  88. EncQ: (RistrettoPoint, RistrettoPoint),
  89. EncInvRemain: (RistrettoPoint, RistrettoPoint),
  90. id_server: Scalar,
  91. TId: RistrettoPoint,
  92. TBucket: RistrettoPoint,
  93. TInvRemain: RistrettoPoint,
  94. TBlockages: RistrettoPoint,
  95. // The ZKP
  96. piBlindIssue: CompactProof,
  97. }
  98. define_proof! {
  99. requestproof,
  100. "Blockage Migration Request",
  101. (bucket, since, invremain, blockages, zbucket, zsince, zinvremain,
  102. zblockages, negzQ_lox,
  103. tobucket, zfrombucket, ztobucket, negzQ_mig,
  104. d, eid_client, ebucket, eblockages, id_client),
  105. (P_lox, CBucket, CSince, CInvRemain, CBlockages, V_lox, Xbucket,
  106. Xsince, Xinvremain, Xblockages,
  107. P_mig, CFromBucket, CToBucket, V_mig, Xfrombucket, Xtobucket,
  108. D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1,
  109. EncBlockages0, EncBlockages1_minus_B),
  110. (A, B):
  111. // Blind showing of the Lox credential
  112. CBucket = (bucket*P_lox + zbucket*A),
  113. CSince = (since*P_lox + zsince*A),
  114. CInvRemain = (invremain*P_lox + zinvremain*A),
  115. CBlockages = (blockages*P_lox + zblockages*A),
  116. V_lox = (zbucket*Xbucket + zsince*Xsince + zinvremain*Xinvremain
  117. + zblockages*Xblockages + negzQ_lox*A),
  118. // Blind showing of the Migration credential; note the use of the
  119. // same "bucket" secret variable
  120. CFromBucket = (bucket*P_mig + zfrombucket*A),
  121. CToBucket = (tobucket*P_mig + ztobucket*A),
  122. V_mig = (zfrombucket*Xfrombucket + ztobucket*Xtobucket + negzQ_mig*A),
  123. // User blinding of the Lox credential to be issued; note the use of
  124. // the same "tobucket" secret variable
  125. D = (d*B),
  126. EncIdClient0 = (eid_client*B),
  127. EncIdClient1 = (id_client*B + eid_client*D),
  128. EncBucket0 = (ebucket*B),
  129. EncBucket1 = (tobucket*B + ebucket*D),
  130. EncBlockages0 = (eblockages*B),
  131. EncBlockages1_minus_B = (blockages*B + eblockages*D)
  132. }
  133. define_proof! {
  134. blindissue,
  135. "Blockage Migration Blind Issuing",
  136. (x0, x0tilde, xid, xbucket, xlevel, xsince, xinvremain, xblockages,
  137. s, b, tid, tbucket, tinvremain, tblockages),
  138. (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Xinvremain,
  139. Xblockages, Plevel, Psince, TId, TBucket, TInvRemain, TBlockages,
  140. D, EncId0, EncId1, EncBucket0, EncBucket1, EncInvRemain0,
  141. EncInvRemain1, EncBlockages0, EncBlockages1),
  142. (A, B):
  143. Xid = (xid*A),
  144. Xlevel = (xlevel*A),
  145. Xbucket = (xbucket*A),
  146. Xsince = (xsince*A),
  147. Xinvremain = (xinvremain*A),
  148. Xblockages = (xblockages*A),
  149. X0 = (x0*B + x0tilde*A),
  150. P = (b*B),
  151. TId = (b*Xid),
  152. TId = (tid*A),
  153. TBucket = (b*Xbucket),
  154. TBucket = (tbucket*A),
  155. TInvRemain = (b*Xinvremain),
  156. TInvRemain = (tinvremain*A),
  157. TBlockages = (b*Xblockages),
  158. TBlockages = (tblockages*A),
  159. EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0
  160. + tinvremain*EncInvRemain0 + tblockages*EncBlockages0),
  161. EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1
  162. + tinvremain*EncInvRemain1 + tblockages*EncBlockages1
  163. + x0*P + xlevel*Plevel + xsince*Psince)
  164. }
  165. pub fn request(
  166. lox_cred: &cred::Lox,
  167. migration_cred: &cred::Migration,
  168. lox_pub: &IssuerPubKey,
  169. migration_pub: &IssuerPubKey,
  170. ) -> Result<(Request, State), ProofError> {
  171. let A: &RistrettoPoint = &CMZ_A;
  172. let B: &RistrettoPoint = &CMZ_B;
  173. let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
  174. let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
  175. // Ensure that the credenials can be correctly shown; that is, the
  176. // ids match and the Lox credential bucket matches the Migration
  177. // credential from_bucket
  178. if lox_cred.id != migration_cred.lox_id || lox_cred.bucket != migration_cred.from_bucket {
  179. return Err(ProofError::VerificationFailure);
  180. }
  181. // The trust level must be at least MIN_TRUST_LEVEL
  182. let level: u32 = match scalar_u32(&lox_cred.trust_level) {
  183. Some(v) => v,
  184. None => return Err(ProofError::VerificationFailure),
  185. };
  186. if level < MIN_TRUST_LEVEL {
  187. return Err(ProofError::VerificationFailure);
  188. }
  189. // Blind showing the Lox credential
  190. // Reblind P and Q
  191. let mut rng = rand::thread_rng();
  192. let t_lox = Scalar::random(&mut rng);
  193. let P_lox = t_lox * lox_cred.P;
  194. let Q_lox = t_lox * lox_cred.Q;
  195. // Form Pedersen commitments to the blinded attributes
  196. let zbucket = Scalar::random(&mut rng);
  197. let zsince = Scalar::random(&mut rng);
  198. let zinvremain = Scalar::random(&mut rng);
  199. let zblockages = Scalar::random(&mut rng);
  200. let CBucket = lox_cred.bucket * P_lox + &zbucket * Atable;
  201. let CSince = lox_cred.level_since * P_lox + &zsince * Atable;
  202. let CInvRemain = lox_cred.invites_remaining * P_lox + &zinvremain * Atable;
  203. let CBlockages = lox_cred.blockages * P_lox + &zblockages * Atable;
  204. // Form a Pedersen commitment to the MAC Q
  205. // We flip the sign of zQ from that of the Hyphae paper so that
  206. // the ZKP has a "+" instead of a "-", as that's what the zkp
  207. // macro supports.
  208. let negzQ_lox = Scalar::random(&mut rng);
  209. let CQ_lox = Q_lox - &negzQ_lox * Atable;
  210. // Compute the "error factor"
  211. let V_lox = zbucket * lox_pub.X[2]
  212. + zsince * lox_pub.X[4]
  213. + zinvremain * lox_pub.X[5]
  214. + zblockages * lox_pub.X[6]
  215. + &negzQ_lox * Atable;
  216. // Blind showing the Migration credential
  217. // Reblind P and Q
  218. let t_mig = Scalar::random(&mut rng);
  219. let P_mig = t_mig * migration_cred.P;
  220. let Q_mig = t_mig * migration_cred.Q;
  221. // Form Pedersen commitments to the blinded attributes
  222. let zfrombucket = Scalar::random(&mut rng);
  223. let ztobucket = Scalar::random(&mut rng);
  224. let CFromBucket = migration_cred.from_bucket * P_mig + &zfrombucket * Atable;
  225. let CToBucket = migration_cred.to_bucket * P_mig + &ztobucket * Atable;
  226. // Form a Pedersen commitment to the MAC Q
  227. // We flip the sign of zQ from that of the Hyphae paper so that
  228. // the ZKP has a "+" instead of a "-", as that's what the zkp
  229. // macro supports.
  230. let negzQ_mig = Scalar::random(&mut rng);
  231. let CQ_mig = Q_mig - &negzQ_mig * Atable;
  232. // Compute the "error factor"
  233. let V_mig =
  234. zfrombucket * migration_pub.X[2] + ztobucket * migration_pub.X[3] + &negzQ_mig * Atable;
  235. // User blinding for the Lox certificate to be issued
  236. // Pick an ElGamal keypair
  237. let d = Scalar::random(&mut rng);
  238. let D = &d * Btable;
  239. // Pick a random client component of the id
  240. let id_client = Scalar::random(&mut rng);
  241. // Encrypt it (times the basepoint B) to the ElGamal public key D we
  242. // just created
  243. let eid_client = Scalar::random(&mut rng);
  244. let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D);
  245. // Encrypt the other blinded attributes (times B) to D as well
  246. let ebucket = Scalar::random(&mut rng);
  247. let EncBucket = (
  248. &ebucket * Btable,
  249. &migration_cred.to_bucket * Btable + ebucket * D,
  250. );
  251. let eblockages = Scalar::random(&mut rng);
  252. let new_blockages = lox_cred.blockages + Scalar::one();
  253. let EncBlockages = (
  254. &eblockages * Btable,
  255. &new_blockages * Btable + eblockages * D,
  256. );
  257. // Construct the proof
  258. let mut transcript = Transcript::new(b"blockage migration request");
  259. let piUser = requestproof::prove_compact(
  260. &mut transcript,
  261. requestproof::ProveAssignments {
  262. A,
  263. B,
  264. P_lox: &P_lox,
  265. CBucket: &CBucket,
  266. CSince: &CSince,
  267. CInvRemain: &CInvRemain,
  268. CBlockages: &CBlockages,
  269. V_lox: &V_lox,
  270. Xbucket: &lox_pub.X[2],
  271. Xsince: &lox_pub.X[4],
  272. Xinvremain: &lox_pub.X[5],
  273. Xblockages: &lox_pub.X[6],
  274. P_mig: &P_mig,
  275. CFromBucket: &CFromBucket,
  276. CToBucket: &CToBucket,
  277. V_mig: &V_mig,
  278. Xfrombucket: &migration_pub.X[2],
  279. Xtobucket: &migration_pub.X[3],
  280. D: &D,
  281. EncIdClient0: &EncIdClient.0,
  282. EncIdClient1: &EncIdClient.1,
  283. EncBucket0: &EncBucket.0,
  284. EncBucket1: &EncBucket.1,
  285. EncBlockages0: &EncBlockages.0,
  286. EncBlockages1_minus_B: &(EncBlockages.1 - B),
  287. bucket: &lox_cred.bucket,
  288. since: &lox_cred.level_since,
  289. invremain: &lox_cred.invites_remaining,
  290. blockages: &lox_cred.blockages,
  291. zbucket: &zbucket,
  292. zsince: &zsince,
  293. zinvremain: &zinvremain,
  294. zblockages: &zblockages,
  295. negzQ_lox: &negzQ_lox,
  296. tobucket: &migration_cred.to_bucket,
  297. zfrombucket: &zfrombucket,
  298. ztobucket: &ztobucket,
  299. negzQ_mig: &negzQ_mig,
  300. d: &d,
  301. eid_client: &eid_client,
  302. ebucket: &ebucket,
  303. eblockages: &eblockages,
  304. id_client: &id_client,
  305. },
  306. )
  307. .0;
  308. Ok((
  309. Request {
  310. P_lox,
  311. id: lox_cred.id,
  312. CBucket,
  313. trust_level: lox_cred.trust_level,
  314. CSince,
  315. CInvRemain,
  316. CBlockages,
  317. CQ_lox,
  318. P_mig,
  319. CFromBucket,
  320. CToBucket,
  321. CQ_mig,
  322. D,
  323. EncIdClient,
  324. EncBucket,
  325. EncBlockages,
  326. piUser,
  327. },
  328. State {
  329. d,
  330. D,
  331. EncIdClient,
  332. EncBucket,
  333. EncBlockages,
  334. id_client,
  335. to_bucket: migration_cred.to_bucket,
  336. trust_level: (level - 2).into(),
  337. blockages: new_blockages,
  338. },
  339. ))
  340. }
  341. impl BridgeAuth {
  342. /// Receive a blockage migration request
  343. pub fn handle_blockage_migration(&mut self, req: Request) -> Result<Response, ProofError> {
  344. let A: &RistrettoPoint = &CMZ_A;
  345. let B: &RistrettoPoint = &CMZ_B;
  346. let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
  347. let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
  348. if req.P_lox.is_identity() || req.P_mig.is_identity() {
  349. return Err(ProofError::VerificationFailure);
  350. }
  351. // The trust level must be at least MIN_TRUST_LEVEL
  352. let level: u32 = match scalar_u32(&req.trust_level) {
  353. Some(v) => v,
  354. None => return Err(ProofError::VerificationFailure),
  355. };
  356. if level < MIN_TRUST_LEVEL {
  357. return Err(ProofError::VerificationFailure);
  358. }
  359. // Recompute the "error factors" using knowledge of our own
  360. // (the issuer's) private key instead of knowledge of the
  361. // hidden attributes
  362. let Vprime_lox = (self.lox_priv.x[0]
  363. + self.lox_priv.x[1] * req.id
  364. + self.lox_priv.x[3] * req.trust_level)
  365. * req.P_lox
  366. + self.lox_priv.x[2] * req.CBucket
  367. + self.lox_priv.x[4] * req.CSince
  368. + self.lox_priv.x[5] * req.CInvRemain
  369. + self.lox_priv.x[6] * req.CBlockages
  370. - req.CQ_lox;
  371. let migration_type: Scalar = MigrationType::Blockage.into();
  372. let Vprime_mig = (self.migration_priv.x[0]
  373. + self.migration_priv.x[1] * req.id
  374. + self.migration_priv.x[4] * migration_type)
  375. * req.P_mig
  376. + self.migration_priv.x[2] * req.CFromBucket
  377. + self.migration_priv.x[3] * req.CToBucket
  378. - req.CQ_mig;
  379. // Verify the ZKP
  380. let mut transcript = Transcript::new(b"blockage migration request");
  381. requestproof::verify_compact(
  382. &req.piUser,
  383. &mut transcript,
  384. requestproof::VerifyAssignments {
  385. A: &A.compress(),
  386. B: &B.compress(),
  387. P_lox: &req.P_lox.compress(),
  388. CBucket: &req.CBucket.compress(),
  389. CSince: &req.CSince.compress(),
  390. CInvRemain: &req.CInvRemain.compress(),
  391. CBlockages: &req.CBlockages.compress(),
  392. V_lox: &Vprime_lox.compress(),
  393. Xbucket: &self.lox_pub.X[2].compress(),
  394. Xsince: &self.lox_pub.X[4].compress(),
  395. Xinvremain: &self.lox_pub.X[5].compress(),
  396. Xblockages: &self.lox_pub.X[6].compress(),
  397. P_mig: &req.P_mig.compress(),
  398. CFromBucket: &req.CFromBucket.compress(),
  399. CToBucket: &req.CToBucket.compress(),
  400. V_mig: &Vprime_mig.compress(),
  401. Xfrombucket: &self.migration_pub.X[2].compress(),
  402. Xtobucket: &self.migration_pub.X[3].compress(),
  403. D: &req.D.compress(),
  404. EncIdClient0: &req.EncIdClient.0.compress(),
  405. EncIdClient1: &req.EncIdClient.1.compress(),
  406. EncBucket0: &req.EncBucket.0.compress(),
  407. EncBucket1: &req.EncBucket.1.compress(),
  408. EncBlockages0: &req.EncBlockages.0.compress(),
  409. EncBlockages1_minus_B: &(req.EncBlockages.1 - B).compress(),
  410. },
  411. )?;
  412. // Ensure the id has not been seen before, and add it to the
  413. // seen list.
  414. if self.id_filter.filter(&req.id) == SeenType::Seen {
  415. return Err(ProofError::VerificationFailure);
  416. }
  417. // Blind issuing of the new Lox credential
  418. // Choose a random server id component to add to the client's
  419. // (blinded) id component
  420. let mut rng = rand::thread_rng();
  421. let id_server = Scalar::random(&mut rng);
  422. let EncId = (req.EncIdClient.0, req.EncIdClient.1 + &id_server * Btable);
  423. // Create the trust_level attrubute (Scalar), which will be
  424. // 2 levels down from the one in the provided credential
  425. let trust_level: Scalar = (level - 2).into();
  426. // Create the level_since attribute (Scalar), which is today's
  427. // Julian date
  428. let level_since: Scalar = self.today().into();
  429. // The invites remaining is the appropriate number for the new
  430. // level (note that LEVEL_INVITATIONS[i] is the number of
  431. // invitations for moving from level i to level i+1)
  432. let invremain: Scalar = LEVEL_INVITATIONS[(level - 3) as usize].into();
  433. // Because of the bug in the zkp crate, encrypt the invites
  434. // remaining instead of sending it in the clear
  435. let sinvremain = Scalar::random(&mut rng);
  436. let EncInvRemain = (
  437. &sinvremain * Btable,
  438. &invremain * Btable + sinvremain * req.D,
  439. );
  440. // Compute the MAC on the visible attributes
  441. let b = Scalar::random(&mut rng);
  442. let P = &b * Btable;
  443. let QHc = (self.lox_priv.x[0]
  444. + self.lox_priv.x[3] * trust_level
  445. + self.lox_priv.x[4] * level_since)
  446. * P;
  447. // El Gamal encrypt it to the public key req.D
  448. let s = Scalar::random(&mut rng);
  449. let EncQHc = (&s * Btable, QHc + s * req.D);
  450. // Homomorphically compute the part of the MAC corresponding to
  451. // the blinded attributes
  452. let tid = self.lox_priv.x[1] * b;
  453. let TId = &tid * Atable;
  454. let EncQId = (tid * EncId.0, tid * EncId.1);
  455. let tbucket = self.lox_priv.x[2] * b;
  456. let TBucket = &tbucket * Atable;
  457. let EncQBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1);
  458. let tinvremain = self.lox_priv.x[5] * b;
  459. let TInvRemain = &tinvremain * Atable;
  460. let EncQInvRemain = (tinvremain * EncInvRemain.0, tinvremain * EncInvRemain.1);
  461. let tblockages = self.lox_priv.x[6] * b;
  462. let TBlockages = &tblockages * Atable;
  463. let EncQBlockages = (
  464. tblockages * req.EncBlockages.0,
  465. tblockages * req.EncBlockages.1,
  466. );
  467. let EncQ = (
  468. EncQHc.0 + EncQId.0 + EncQBucket.0 + EncQInvRemain.0 + EncQBlockages.0,
  469. EncQHc.1 + EncQId.1 + EncQBucket.1 + EncQInvRemain.1 + EncQBlockages.1,
  470. );
  471. let mut transcript = Transcript::new(b"blockage migration issuing");
  472. let piBlindIssue = blindissue::prove_compact(
  473. &mut transcript,
  474. blindissue::ProveAssignments {
  475. A,
  476. B,
  477. P: &P,
  478. EncQ0: &EncQ.0,
  479. EncQ1: &EncQ.1,
  480. X0: &self.lox_pub.X[0],
  481. Xid: &self.lox_pub.X[1],
  482. Xbucket: &self.lox_pub.X[2],
  483. Xlevel: &self.lox_pub.X[3],
  484. Xsince: &self.lox_pub.X[4],
  485. Xinvremain: &self.lox_pub.X[5],
  486. Xblockages: &self.lox_pub.X[6],
  487. Plevel: &(trust_level * P),
  488. Psince: &(level_since * P),
  489. TId: &TId,
  490. TBucket: &TBucket,
  491. TInvRemain: &TInvRemain,
  492. TBlockages: &TBlockages,
  493. D: &req.D,
  494. EncId0: &EncId.0,
  495. EncId1: &EncId.1,
  496. EncBucket0: &req.EncBucket.0,
  497. EncBucket1: &req.EncBucket.1,
  498. EncInvRemain0: &EncInvRemain.0,
  499. EncInvRemain1: &EncInvRemain.1,
  500. EncBlockages0: &req.EncBlockages.0,
  501. EncBlockages1: &req.EncBlockages.1,
  502. x0: &self.lox_priv.x[0],
  503. x0tilde: &self.lox_priv.x0tilde,
  504. xid: &self.lox_priv.x[1],
  505. xbucket: &self.lox_priv.x[2],
  506. xlevel: &self.lox_priv.x[3],
  507. xsince: &self.lox_priv.x[4],
  508. xinvremain: &self.lox_priv.x[5],
  509. xblockages: &self.lox_priv.x[6],
  510. s: &s,
  511. b: &b,
  512. tid: &tid,
  513. tbucket: &tbucket,
  514. tinvremain: &tinvremain,
  515. tblockages: &tblockages,
  516. },
  517. )
  518. .0;
  519. Ok(Response {
  520. level_since,
  521. P,
  522. EncQ,
  523. EncInvRemain,
  524. id_server,
  525. TId,
  526. TBucket,
  527. TInvRemain,
  528. TBlockages,
  529. piBlindIssue,
  530. })
  531. }
  532. }
  533. /// Handle the response to the request, producing the new Lox credential
  534. /// if successful.
  535. pub fn handle_response(
  536. state: State,
  537. resp: Response,
  538. lox_pub: &IssuerPubKey,
  539. ) -> Result<cred::Lox, ProofError> {
  540. let A: &RistrettoPoint = &CMZ_A;
  541. let B: &RistrettoPoint = &CMZ_B;
  542. let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
  543. if resp.P.is_identity() {
  544. return Err(ProofError::VerificationFailure);
  545. }
  546. // Add the server's contribution to the id to our own, both in plain
  547. // and encrypted form
  548. let id = state.id_client + resp.id_server;
  549. let EncId = (
  550. state.EncIdClient.0,
  551. state.EncIdClient.1 + &resp.id_server * Btable,
  552. );
  553. let new_level: u32 = match scalar_u32(&state.trust_level) {
  554. Some(v) => v,
  555. None => return Err(ProofError::VerificationFailure),
  556. };
  557. if new_level < 1 {
  558. return Err(ProofError::VerificationFailure);
  559. }
  560. // The invites remaining is the appropriate number for the new level
  561. // (note that LEVEL_INVITATIONS[i] is the number of invitations for
  562. // moving from level i to level i+1)
  563. let invremain: Scalar = LEVEL_INVITATIONS[(new_level - 1) as usize].into();
  564. // Decrypt EncInvRemain
  565. let recv_invremain = resp.EncInvRemain.1 - (state.d * resp.EncInvRemain.0);
  566. if recv_invremain != &invremain * Btable {
  567. return Err(ProofError::VerificationFailure);
  568. }
  569. // Verify the proof
  570. let mut transcript = Transcript::new(b"blockage migration issuing");
  571. blindissue::verify_compact(
  572. &resp.piBlindIssue,
  573. &mut transcript,
  574. blindissue::VerifyAssignments {
  575. A: &A.compress(),
  576. B: &B.compress(),
  577. P: &resp.P.compress(),
  578. EncQ0: &resp.EncQ.0.compress(),
  579. EncQ1: &resp.EncQ.1.compress(),
  580. X0: &lox_pub.X[0].compress(),
  581. Xid: &lox_pub.X[1].compress(),
  582. Xbucket: &lox_pub.X[2].compress(),
  583. Xlevel: &lox_pub.X[3].compress(),
  584. Xsince: &lox_pub.X[4].compress(),
  585. Xinvremain: &lox_pub.X[5].compress(),
  586. Xblockages: &lox_pub.X[6].compress(),
  587. Plevel: &(state.trust_level * resp.P).compress(),
  588. Psince: &(resp.level_since * resp.P).compress(),
  589. TId: &resp.TId.compress(),
  590. TBucket: &resp.TBucket.compress(),
  591. TInvRemain: &resp.TInvRemain.compress(),
  592. TBlockages: &resp.TBlockages.compress(),
  593. D: &state.D.compress(),
  594. EncId0: &EncId.0.compress(),
  595. EncId1: &EncId.1.compress(),
  596. EncBucket0: &state.EncBucket.0.compress(),
  597. EncBucket1: &state.EncBucket.1.compress(),
  598. EncInvRemain0: &resp.EncInvRemain.0.compress(),
  599. EncInvRemain1: &resp.EncInvRemain.1.compress(),
  600. EncBlockages0: &state.EncBlockages.0.compress(),
  601. EncBlockages1: &state.EncBlockages.1.compress(),
  602. },
  603. )?;
  604. // Decrypt EncQ
  605. let Q = resp.EncQ.1 - (state.d * resp.EncQ.0);
  606. Ok(cred::Lox {
  607. P: resp.P,
  608. Q,
  609. id,
  610. bucket: state.to_bucket,
  611. trust_level: new_level.into(),
  612. level_since: resp.level_since,
  613. invites_remaining: invremain,
  614. blockages: state.blockages,
  615. })
  616. }