You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
4.0 KiB

  1. pragma circom 2.1.6;
  2. include "node_modules/circomlib/circuits/poseidon.circom";
  3. include "node_modules/circomlib/circuits/mux1.circom";
  4. include "node_modules/circomlib/circuits/comparators.circom";
  5. include "node_modules/circomlib/circuits/gates.circom";
  6. include "./templates/chaff.circom";
  7. template grapevine(num_felts) {
  8. // in_out schema
  9. // 0: degrees of separation
  10. // 1: secret hash from previous step
  11. // 2: hash of username + secret hash from previous step
  12. // 3: chaff
  13. signal input ivc_input[4];
  14. signal output ivc_output[4];
  15. // private inputs
  16. signal input phrase[num_felts]; // secret phrase, if first iteration
  17. signal input usernames[2]; // prev username, current username
  18. signal input auth_secrets[2]; // prev degree's user secret, current degree's user secret
  19. // name inputs from step_in
  20. signal degrees_of_separation <== ivc_input[0];
  21. signal given_phrase_hash <== ivc_input[1];
  22. signal given_degree_secret_hash <== ivc_input[2];
  23. signal is_chaff_step <== ivc_input[3];
  24. // determine whether degrees of separation from secret is zero
  25. component is_degree_zero = IsZero();
  26. is_degree_zero.in <== degrees_of_separation;
  27. // compute poseidon hash of secret
  28. // same as the word essentially
  29. component phrase_hasher = Poseidon(num_felts);
  30. phrase_hasher.inputs <== phrase;
  31. // mux between computed hash and previous iteration's hash to get phrase hash to use
  32. // if degrees of separation = 0 use computed hash, else use hash from previous step
  33. component phrase_mux = Mux1();
  34. phrase_mux.c[0] <== given_phrase_hash;
  35. phrase_mux.c[1] <== phrase_hasher.out;
  36. phrase_mux.s <== is_degree_zero.out;
  37. // compute hash of given degree secret
  38. // H(H(preimage), username, auth_secret[0])
  39. // where preimage is muxed depending on whether degree N is 1 or > 1
  40. component degree_secret_hasher = Poseidon(3);
  41. degree_secret_hasher.inputs[0] <== phrase_mux.out;
  42. degree_secret_hasher.inputs[1] <== usernames[0];
  43. degree_secret_hasher.inputs[2] <== auth_secrets[0];
  44. // compare computed degree secret hash to prev degree secret hash
  45. component degree_secret_hash_match = IsEqual();
  46. degree_secret_hash_match.in[0] <== degree_secret_hasher.out;
  47. degree_secret_hash_match.in[1] <== given_degree_secret_hash;
  48. // create boolean that is true if either is true:
  49. // - given degree secret hash matches computed hash
  50. // - is a chaff step
  51. component degree_secret_match_or_chaff = OR();
  52. degree_secret_match_or_chaff.a <== degree_secret_hash_match.out;
  53. degree_secret_match_or_chaff.b <== is_chaff_step;
  54. // create boolean that is muxes according to:
  55. // - if degrees of separation = 0, always true (no check needed)
  56. // - if degree of separation > 0, return output of degree_secret_match_or_chaff
  57. component degree_secret_satisfied_mux = Mux1();
  58. degree_secret_satisfied_mux.c[0] <== degree_secret_match_or_chaff.out;
  59. degree_secret_satisfied_mux.c[1] <== 1;
  60. degree_secret_satisfied_mux.s <== is_degree_zero.out;
  61. // constrain degree_secret_satisfied_mux to be true
  62. degree_secret_satisfied_mux.out === 1;
  63. // compute the next username hash
  64. component next_degree_secret_hash = Poseidon(3);
  65. next_degree_secret_hash.inputs[0] <== phrase_mux.out;
  66. next_degree_secret_hash.inputs[1] <== usernames[1];
  67. next_degree_secret_hash.inputs[2] <== auth_secrets[1];
  68. // mux step_out signal according to whether or not this is a chaff step
  69. component chaff_mux = ChaffMux();
  70. chaff_mux.degrees_of_separation <== degrees_of_separation;
  71. chaff_mux.given_phrase_hash <== given_phrase_hash;
  72. chaff_mux.given_degree_secret_hash <== given_degree_secret_hash;
  73. chaff_mux.is_chaff_step <== is_chaff_step;
  74. chaff_mux.computed_phrase_hash <== phrase_mux.out;
  75. chaff_mux.computed_degree_secret_hash <== next_degree_secret_hash.out;
  76. // wire output signals
  77. ivc_output <== chaff_mux.out;
  78. }
  79. component main { public [ivc_input] } = grapevine(6);