longfellow 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +10 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +152 -0
  5. data/ext/longfellow/CMakeLists.txt +76 -0
  6. data/ext/longfellow/extconf.rb +77 -0
  7. data/lib/longfellow/attribute.rb +65 -0
  8. data/lib/longfellow/c.rb +105 -0
  9. data/lib/longfellow/errors.rb +78 -0
  10. data/lib/longfellow/version.rb +5 -0
  11. data/lib/longfellow/zk_spec.rb +40 -0
  12. data/lib/longfellow.rb +162 -0
  13. data/sig/longfellow.rbs +74 -0
  14. data/vendor/longfellow-zk/LICENSE +203 -0
  15. data/vendor/longfellow-zk/lib/algebra/blas.h +121 -0
  16. data/vendor/longfellow-zk/lib/algebra/bogorng.h +68 -0
  17. data/vendor/longfellow-zk/lib/algebra/compare.h +40 -0
  18. data/vendor/longfellow-zk/lib/algebra/convolution.h +219 -0
  19. data/vendor/longfellow-zk/lib/algebra/crt.cc +42 -0
  20. data/vendor/longfellow-zk/lib/algebra/crt.h +299 -0
  21. data/vendor/longfellow-zk/lib/algebra/crt_convolution.h +114 -0
  22. data/vendor/longfellow-zk/lib/algebra/crt_test.cc +371 -0
  23. data/vendor/longfellow-zk/lib/algebra/fft.h +104 -0
  24. data/vendor/longfellow-zk/lib/algebra/fft_interpolation.h +304 -0
  25. data/vendor/longfellow-zk/lib/algebra/fft_interpolation_test.cc +168 -0
  26. data/vendor/longfellow-zk/lib/algebra/fft_test.cc +257 -0
  27. data/vendor/longfellow-zk/lib/algebra/fp.h +59 -0
  28. data/vendor/longfellow-zk/lib/algebra/fp2.h +240 -0
  29. data/vendor/longfellow-zk/lib/algebra/fp24.h +342 -0
  30. data/vendor/longfellow-zk/lib/algebra/fp24_6.h +305 -0
  31. data/vendor/longfellow-zk/lib/algebra/fp24_6_test.cc +197 -0
  32. data/vendor/longfellow-zk/lib/algebra/fp2_test.cc +280 -0
  33. data/vendor/longfellow-zk/lib/algebra/fp_generic.h +533 -0
  34. data/vendor/longfellow-zk/lib/algebra/fp_p128.h +91 -0
  35. data/vendor/longfellow-zk/lib/algebra/fp_p256.h +68 -0
  36. data/vendor/longfellow-zk/lib/algebra/fp_p256k1.h +123 -0
  37. data/vendor/longfellow-zk/lib/algebra/fp_p384.h +65 -0
  38. data/vendor/longfellow-zk/lib/algebra/fp_p521.h +62 -0
  39. data/vendor/longfellow-zk/lib/algebra/fp_test.cc +522 -0
  40. data/vendor/longfellow-zk/lib/algebra/hash.h +39 -0
  41. data/vendor/longfellow-zk/lib/algebra/interpolation.h +117 -0
  42. data/vendor/longfellow-zk/lib/algebra/interpolation_test.cc +74 -0
  43. data/vendor/longfellow-zk/lib/algebra/limb.h +153 -0
  44. data/vendor/longfellow-zk/lib/algebra/limb_test.cc +75 -0
  45. data/vendor/longfellow-zk/lib/algebra/nat.cc +32 -0
  46. data/vendor/longfellow-zk/lib/algebra/nat.h +212 -0
  47. data/vendor/longfellow-zk/lib/algebra/nat_test.cc +183 -0
  48. data/vendor/longfellow-zk/lib/algebra/nussbaumer.h +400 -0
  49. data/vendor/longfellow-zk/lib/algebra/nussbaumer_test.cc +138 -0
  50. data/vendor/longfellow-zk/lib/algebra/nussbaumerfp2_test.cc +139 -0
  51. data/vendor/longfellow-zk/lib/algebra/permutations.h +79 -0
  52. data/vendor/longfellow-zk/lib/algebra/poly.h +240 -0
  53. data/vendor/longfellow-zk/lib/algebra/poly_test.cc +123 -0
  54. data/vendor/longfellow-zk/lib/algebra/reed_solomon.h +150 -0
  55. data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension.h +108 -0
  56. data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension_test.cc +76 -0
  57. data/vendor/longfellow-zk/lib/algebra/reed_solomon_test.cc +473 -0
  58. data/vendor/longfellow-zk/lib/algebra/rfft.h +400 -0
  59. data/vendor/longfellow-zk/lib/algebra/rfft_test.cc +102 -0
  60. data/vendor/longfellow-zk/lib/algebra/static_string.h +29 -0
  61. data/vendor/longfellow-zk/lib/algebra/sysdep.h +495 -0
  62. data/vendor/longfellow-zk/lib/algebra/sysdep_test.cc +41 -0
  63. data/vendor/longfellow-zk/lib/algebra/twiddle.h +59 -0
  64. data/vendor/longfellow-zk/lib/algebra/utility.h +86 -0
  65. data/vendor/longfellow-zk/lib/algebra/utility_test.cc +86 -0
  66. data/vendor/longfellow-zk/lib/arrays/affine.h +56 -0
  67. data/vendor/longfellow-zk/lib/arrays/affine_test.cc +220 -0
  68. data/vendor/longfellow-zk/lib/arrays/dense.h +210 -0
  69. data/vendor/longfellow-zk/lib/arrays/eq.h +75 -0
  70. data/vendor/longfellow-zk/lib/arrays/eqs.h +137 -0
  71. data/vendor/longfellow-zk/lib/arrays/eqs_test.cc +151 -0
  72. data/vendor/longfellow-zk/lib/arrays/sparse.h +192 -0
  73. data/vendor/longfellow-zk/lib/cbor/host_decoder.h +323 -0
  74. data/vendor/longfellow-zk/lib/cbor/host_decoder_test.cc +541 -0
  75. data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor.h +594 -0
  76. data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder.h +150 -0
  77. data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder_test.cc +147 -0
  78. data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_constants.h +27 -0
  79. data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck.h +110 -0
  80. data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck_test.cc +55 -0
  81. data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_test.cc +174 -0
  82. data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_testing.h +98 -0
  83. data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_witness.h +312 -0
  84. data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso2_test.cc +662 -0
  85. data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso_test.cc +485 -0
  86. data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan.h +104 -0
  87. data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan_test.cc +137 -0
  88. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor.h +640 -0
  89. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder.h +150 -0
  90. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder_test.cc +147 -0
  91. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_constants.h +27 -0
  92. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_testing.h +99 -0
  93. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_witness.h +319 -0
  94. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/lexer_test.cc +120 -0
  95. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/mdoc_examples_test.cc +89 -0
  96. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_circuit_test.cc +506 -0
  97. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_size_test.cc +79 -0
  98. data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_test.cc +473 -0
  99. data/vendor/longfellow-zk/lib/circuits/compiler/canonicalization_test.cc +185 -0
  100. data/vendor/longfellow-zk/lib/circuits/compiler/circuit_dump.h +65 -0
  101. data/vendor/longfellow-zk/lib/circuits/compiler/compiler.h +471 -0
  102. data/vendor/longfellow-zk/lib/circuits/compiler/compiler_test.cc +110 -0
  103. data/vendor/longfellow-zk/lib/circuits/compiler/node.h +176 -0
  104. data/vendor/longfellow-zk/lib/circuits/compiler/pdqhash.h +127 -0
  105. data/vendor/longfellow-zk/lib/circuits/compiler/schedule.h +435 -0
  106. data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_circuit.h +371 -0
  107. data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_external_test.cc +246 -0
  108. data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_test.cc +587 -0
  109. data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_witness.h +201 -0
  110. data/vendor/longfellow-zk/lib/circuits/logic/bit_adder.h +140 -0
  111. data/vendor/longfellow-zk/lib/circuits/logic/bit_adder_test.cc +64 -0
  112. data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker.h +247 -0
  113. data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_constants.h +35 -0
  114. data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_encoder.h +72 -0
  115. data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_test.cc +183 -0
  116. data/vendor/longfellow-zk/lib/circuits/logic/compiler_backend.h +62 -0
  117. data/vendor/longfellow-zk/lib/circuits/logic/counter.h +171 -0
  118. data/vendor/longfellow-zk/lib/circuits/logic/counter_test.cc +102 -0
  119. data/vendor/longfellow-zk/lib/circuits/logic/evaluation_backend.h +94 -0
  120. data/vendor/longfellow-zk/lib/circuits/logic/logic.h +1232 -0
  121. data/vendor/longfellow-zk/lib/circuits/logic/logic_circuit_test.cc +310 -0
  122. data/vendor/longfellow-zk/lib/circuits/logic/logic_test.cc +521 -0
  123. data/vendor/longfellow-zk/lib/circuits/logic/memcmp.h +68 -0
  124. data/vendor/longfellow-zk/lib/circuits/logic/memcmp_test.cc +148 -0
  125. data/vendor/longfellow-zk/lib/circuits/logic/polynomial.h +94 -0
  126. data/vendor/longfellow-zk/lib/circuits/logic/polynomial_test.cc +62 -0
  127. data/vendor/longfellow-zk/lib/circuits/logic/routing.h +445 -0
  128. data/vendor/longfellow-zk/lib/circuits/logic/routing_test.cc +241 -0
  129. data/vendor/longfellow-zk/lib/circuits/logic/unary.h +55 -0
  130. data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker.h +77 -0
  131. data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_constants.h +37 -0
  132. data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_test.cc +53 -0
  133. data/vendor/longfellow-zk/lib/circuits/logic/unary_size_test.cc +69 -0
  134. data/vendor/longfellow-zk/lib/circuits/logic/unary_test.cc +62 -0
  135. data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit.h +193 -0
  136. data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit_test.cc +223 -0
  137. data/vendor/longfellow-zk/lib/circuits/mac/mac_reference.h +72 -0
  138. data/vendor/longfellow-zk/lib/circuits/mac/mac_witness.h +94 -0
  139. data/vendor/longfellow-zk/lib/circuits/mdoc/circuit_maker.cc +242 -0
  140. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_ids.h +311 -0
  141. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_test.cc +64 -0
  142. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_circuit_id.cc +85 -0
  143. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_constants.h +85 -0
  144. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.cc +41 -0
  145. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.h +27 -0
  146. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_examples.h +5232 -0
  147. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_generate_circuit.cc +199 -0
  148. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_hash.h +554 -0
  149. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature.h +143 -0
  150. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature_test.cc +444 -0
  151. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_test_attributes.h +157 -0
  152. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_witness.h +863 -0
  153. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.cc +693 -0
  154. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.h +216 -0
  155. data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk_test.cc +724 -0
  156. data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec.cc +100 -0
  157. data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec_test.cc +155 -0
  158. data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit.h +330 -0
  159. data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit_test.cc +607 -0
  160. data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_io.h +26 -0
  161. data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.cc +163 -0
  162. data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.h +47 -0
  163. data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.cc +34 -0
  164. data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.h +27 -0
  165. data/vendor/longfellow-zk/lib/circuits/sha/sha256_test_values.h +389 -0
  166. data/vendor/longfellow-zk/lib/circuits/tests/anoncred/ptrcred.h +171 -0
  167. data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small.h +218 -0
  168. data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_examples.h +118 -0
  169. data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_io.h +25 -0
  170. data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_test.cc +208 -0
  171. data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_witness.h +130 -0
  172. data/vendor/longfellow-zk/lib/circuits/tests/base64/decode.h +508 -0
  173. data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_circuit_test.cc +95 -0
  174. data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_test.cc +119 -0
  175. data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.cc +47 -0
  176. data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.h +29 -0
  177. data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit.h +231 -0
  178. data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit_test.cc +428 -0
  179. data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_witness.h +102 -0
  180. data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt.h +190 -0
  181. data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_constants.h +26 -0
  182. data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_test.cc +559 -0
  183. data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_witness.h +315 -0
  184. data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f.h +411 -0
  185. data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_io.h +32 -0
  186. data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_test.cc +364 -0
  187. data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_witness.h +278 -0
  188. data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation.h +146 -0
  189. data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_constants.h +25 -0
  190. data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_test.cc +315 -0
  191. data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_witness.h +136 -0
  192. data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr.h +250 -0
  193. data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_test.cc +333 -0
  194. data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_witness.h +152 -0
  195. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44.h +903 -0
  196. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_circuit_test.cc +274 -0
  197. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_eval_test.cc +440 -0
  198. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.cc +8851 -0
  199. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.h +93 -0
  200. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.cc +24 -0
  201. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.h +118 -0
  202. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness.h +453 -0
  203. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness_test.cc +49 -0
  204. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.cc +458 -0
  205. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.h +150 -0
  206. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test.cc +398 -0
  207. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors.inc +3618 -0
  208. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_pkdecode.inc +689 -0
  209. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_sigdecode.inc +1501 -0
  210. data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/sigdecode_test_vectors.inc +540 -0
  211. data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit.h +394 -0
  212. data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit_test.cc +577 -0
  213. data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_constants.h +90 -0
  214. data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.cc +174 -0
  215. data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.h +140 -0
  216. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit.h +351 -0
  217. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit_test.cc +466 -0
  218. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.cc +207 -0
  219. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.h +59 -0
  220. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference_test.cc +153 -0
  221. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.cc +39 -0
  222. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.h +29 -0
  223. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_slicing.h +31 -0
  224. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.cc +83 -0
  225. data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.h +72 -0
  226. data/vendor/longfellow-zk/lib/circuits/tests/sha3/shake_test_vectors.h +477 -0
  227. data/vendor/longfellow-zk/lib/ec/elliptic_curve.h +596 -0
  228. data/vendor/longfellow-zk/lib/ec/elliptic_curve_test.cc +548 -0
  229. data/vendor/longfellow-zk/lib/ec/p256.cc +36 -0
  230. data/vendor/longfellow-zk/lib/ec/p256.h +60 -0
  231. data/vendor/longfellow-zk/lib/ec/p256k1.cc +34 -0
  232. data/vendor/longfellow-zk/lib/ec/p256k1.h +60 -0
  233. data/vendor/longfellow-zk/lib/gf2k/gf2_128.h +503 -0
  234. data/vendor/longfellow-zk/lib/gf2k/gf2_128_bench.cc +48 -0
  235. data/vendor/longfellow-zk/lib/gf2k/gf2_128_test.cc +416 -0
  236. data/vendor/longfellow-zk/lib/gf2k/gf2poly.h +74 -0
  237. data/vendor/longfellow-zk/lib/gf2k/lch14.h +242 -0
  238. data/vendor/longfellow-zk/lib/gf2k/lch14_bench.cc +75 -0
  239. data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon.h +127 -0
  240. data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon_test.cc +110 -0
  241. data/vendor/longfellow-zk/lib/gf2k/lch14_test.cc +246 -0
  242. data/vendor/longfellow-zk/lib/gf2k/sysdep.h +329 -0
  243. data/vendor/longfellow-zk/lib/ligero/ligero_param.h +449 -0
  244. data/vendor/longfellow-zk/lib/ligero/ligero_prover.h +354 -0
  245. data/vendor/longfellow-zk/lib/ligero/ligero_test.cc +136 -0
  246. data/vendor/longfellow-zk/lib/ligero/ligero_transcript.h +67 -0
  247. data/vendor/longfellow-zk/lib/ligero/ligero_verifier.h +272 -0
  248. data/vendor/longfellow-zk/lib/merkle/merkle_commitment.h +104 -0
  249. data/vendor/longfellow-zk/lib/merkle/merkle_tree.h +216 -0
  250. data/vendor/longfellow-zk/lib/merkle/merkle_tree_test.cc +240 -0
  251. data/vendor/longfellow-zk/lib/proto/circuit.h +354 -0
  252. data/vendor/longfellow-zk/lib/proto/circuit_test.cc +202 -0
  253. data/vendor/longfellow-zk/lib/random/random.h +119 -0
  254. data/vendor/longfellow-zk/lib/random/random_test.cc +189 -0
  255. data/vendor/longfellow-zk/lib/random/secure_random_engine.h +37 -0
  256. data/vendor/longfellow-zk/lib/random/transcript.h +193 -0
  257. data/vendor/longfellow-zk/lib/random/transcript_test.cc +344 -0
  258. data/vendor/longfellow-zk/lib/sumcheck/circuit.h +148 -0
  259. data/vendor/longfellow-zk/lib/sumcheck/circuit_id.h +71 -0
  260. data/vendor/longfellow-zk/lib/sumcheck/equad.h +126 -0
  261. data/vendor/longfellow-zk/lib/sumcheck/hquad.h +115 -0
  262. data/vendor/longfellow-zk/lib/sumcheck/prover.h +59 -0
  263. data/vendor/longfellow-zk/lib/sumcheck/prover_layers.h +362 -0
  264. data/vendor/longfellow-zk/lib/sumcheck/quad.h +227 -0
  265. data/vendor/longfellow-zk/lib/sumcheck/quad_builder.h +211 -0
  266. data/vendor/longfellow-zk/lib/sumcheck/quad_test.cc +169 -0
  267. data/vendor/longfellow-zk/lib/sumcheck/sumcheck_test.cc +324 -0
  268. data/vendor/longfellow-zk/lib/sumcheck/testing.h +69 -0
  269. data/vendor/longfellow-zk/lib/sumcheck/transcript_sumcheck.h +85 -0
  270. data/vendor/longfellow-zk/lib/sumcheck/verifier.h +84 -0
  271. data/vendor/longfellow-zk/lib/sumcheck/verifier_layers.h +221 -0
  272. data/vendor/longfellow-zk/lib/testing/test_main.cc +50 -0
  273. data/vendor/longfellow-zk/lib/util/ceildiv.h +164 -0
  274. data/vendor/longfellow-zk/lib/util/ceildiv_test.cc +152 -0
  275. data/vendor/longfellow-zk/lib/util/crc64.h +45 -0
  276. data/vendor/longfellow-zk/lib/util/crypto.cc +39 -0
  277. data/vendor/longfellow-zk/lib/util/crypto.h +108 -0
  278. data/vendor/longfellow-zk/lib/util/log.cc +110 -0
  279. data/vendor/longfellow-zk/lib/util/log.h +33 -0
  280. data/vendor/longfellow-zk/lib/util/panic.h +40 -0
  281. data/vendor/longfellow-zk/lib/util/readbuffer.h +67 -0
  282. data/vendor/longfellow-zk/lib/util/serialization.h +54 -0
  283. data/vendor/longfellow-zk/lib/zk/zk_common.h +455 -0
  284. data/vendor/longfellow-zk/lib/zk/zk_proof.h +378 -0
  285. data/vendor/longfellow-zk/lib/zk/zk_prover.h +202 -0
  286. data/vendor/longfellow-zk/lib/zk/zk_test.cc +340 -0
  287. data/vendor/longfellow-zk/lib/zk/zk_testing.h +154 -0
  288. data/vendor/longfellow-zk/lib/zk/zk_verifier.h +109 -0
  289. metadata +347 -0
@@ -0,0 +1,863 @@
1
+ // Copyright 2026 Google LLC.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #ifndef PRIVACY_PROOFS_ZK_LIB_CIRCUITS_MDOC_MDOC_WITNESS_H_
16
+ #define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_MDOC_MDOC_WITNESS_H_
17
+
18
+ #include <stddef.h>
19
+ #include <string.h>
20
+
21
+ #include <algorithm>
22
+ #include <array>
23
+ #include <cstdint>
24
+ #include <cstdlib>
25
+ #include <iterator>
26
+ #include <vector>
27
+
28
+ #include "arrays/dense.h"
29
+ #include "cbor/host_decoder.h"
30
+ #include "circuits/ecdsa/verify_witness.h"
31
+ #include "circuits/logic/bit_plucker_encoder.h"
32
+ #include "circuits/mac/mac_witness.h"
33
+ #include "circuits/mdoc/mdoc_attribute_ids.h"
34
+ #include "circuits/mdoc/mdoc_constants.h"
35
+ #include "circuits/mdoc/mdoc_hash.h"
36
+ #include "circuits/mdoc/mdoc_zk.h"
37
+ #include "circuits/sha/flatsha256_witness.h"
38
+ #include "gf2k/gf2_128.h"
39
+ #include "util/crypto.h"
40
+ #include "util/log.h"
41
+ #include "util/panic.h"
42
+
43
+ namespace proofs {
44
+
45
+ struct CborIndex {
46
+ size_t k, v, ndx;
47
+ size_t pos, len; /* optional fields for string/byte values */
48
+ };
49
+
50
+ struct AttrShift {
51
+ size_t offset, len;
52
+ };
53
+
54
+ struct SaltedHash {
55
+ size_t i1;
56
+ size_t i2;
57
+ size_t i3;
58
+ size_t l[4];
59
+ size_t perm;
60
+ };
61
+
62
+ struct pos {
63
+ size_t i, l, p, ord;
64
+ };
65
+
66
+ // This class represents an attribute that is parsed out of the deviceResponse
67
+ // data structure. It includes offsets into the original mdoc which can be used
68
+ // to construct SHA witnesses for disclosing the value of an attribute.
69
+ struct FullAttribute {
70
+ // Offset and length of the attribute identifier and attribute value.
71
+ size_t id_ind;
72
+ size_t id_len;
73
+ size_t val_ind;
74
+ size_t val_len;
75
+
76
+ // For version 7+ circuits.
77
+ size_t dig_ind, dig_len;
78
+ size_t rand_ind, rand_len;
79
+
80
+ const uint8_t* mdl_ns; // mdl namespace for the attribute
81
+
82
+ // Index for this attribute among all attributes in the mdoc hash list.
83
+ size_t digest_id;
84
+ CborIndex mso;
85
+
86
+ // Offset and length of the attribute tag.
87
+ size_t tag_ind;
88
+ size_t tag_len;
89
+
90
+ // The original mdoc into which all offsets point.
91
+ const uint8_t* doc;
92
+
93
+ bool operator==(const RequestedAttribute& y) const {
94
+ return y.id_len == id_len && memcmp(y.id, &doc[id_ind], id_len) == 0;
95
+ }
96
+
97
+ size_t witness_length(const RequestedAttribute& attr) {
98
+ return id_len + val_len + 1 + 12;
99
+ }
100
+ };
101
+
102
+ class ParsedMdoc {
103
+ public:
104
+ // Various cbor indices/witnesses for intermediate structures.
105
+ CborIndex t_mso_, sig_, dksig_;
106
+ CborIndex valid_, valid_from_, valid_until_;
107
+ CborIndex dev_key_info_, dev_key_, dev_key_pkx_, dev_key_pky_;
108
+ CborIndex value_digests_, org_;
109
+ std::vector<FullAttribute> attributes_;
110
+ std::vector<uint8_t> doc_type_;
111
+
112
+ // These are the exact bytes which produce the hash that is signed.
113
+ std::vector<uint8_t> tagged_mso_bytes_;
114
+
115
+ /*
116
+ Parses a byte representation of the "DeviceResponse" string from a phone.
117
+ This contains all of the information needed to respond to an mdoc verifier.
118
+ This method attempts to construct a witness from this.
119
+
120
+ 8.3.2.1.2.2: first field is "version", 2nd optional field is "documents"
121
+ [documents][0][issuerSigned][issuerAuth]{2} --> tagged mso
122
+ [documents][0][issuerSigned][issuerAuth]{3} --> issuer sig
123
+ [documents][0][issuerSigned][nameSpaces][ns][index-of-attr] --> enc attr
124
+ [documents][0][deviceSigned][deviceAuth][deviceSignature][3] --> sig
125
+
126
+ This method produces indices into doc as state.
127
+ */
128
+ MdocProverErrorCode parse_device_response(size_t len,
129
+ const uint8_t resp[/* len */]) {
130
+ size_t np = 0;
131
+ // When this object falls out of scope, all parsing objects will be
132
+ // garbage collected.
133
+ CborDoc root;
134
+ bool ok = root.decode(resp, len, np, 0);
135
+ if (!ok) {
136
+ log(ERROR, "Failed to decode root");
137
+ return MDOC_PROVER_ROOT_DECODING_FAILURE;
138
+ }
139
+
140
+ size_t di;
141
+ auto docs = root.lookup(resp, 9, (uint8_t*)"documents", di);
142
+ if (docs == nullptr) return MDOC_PROVER_DOCUMENTS_MISSING;
143
+ // Fields of Document are "docType", "issuerSigned", "deviceSigned", ?errors
144
+
145
+ auto docs0 = docs[1].index(0);
146
+ if (docs0 == nullptr) return MDOC_PROVER_DOCUMENT_0_MISSING;
147
+
148
+ auto dt = docs0[0].lookup(resp, 7, (uint8_t*)"docType", di);
149
+ if (dt == nullptr) return MDOC_PROVER_DOCTYPE_MISSING;
150
+ doc_type_.insert(doc_type_.begin(), resp + dt[1].u_.string.pos,
151
+ resp + dt[1].u_.string.pos + dt[1].u_.string.len);
152
+
153
+ // The returned docs0 is the map, so index at [0].
154
+ auto is = docs0[0].lookup(resp, 12, (uint8_t*)"issuerSigned", di);
155
+ if (is == nullptr) return MDOC_PROVER_ISSUER_SIGNED_MISSING;
156
+
157
+ auto ia = is[1].lookup(resp, 10, (uint8_t*)"issuerAuth", di);
158
+ if (ia == nullptr) return MDOC_PROVER_ISSUER_AUTH_MISSING;
159
+
160
+ auto tmso = ia[1].index(2);
161
+ if (tmso == nullptr) return MDOC_PROVER_MSO_MISSING;
162
+ copy_header(t_mso_, tmso);
163
+ auto nsig = ia[1].index(3);
164
+ if (nsig == nullptr) return MDOC_PROVER_NSIG_MISSING;
165
+ copy_header(sig_, nsig);
166
+
167
+ auto ns = is[1].lookup(resp, 10, (uint8_t*)"nameSpaces", di);
168
+ if (ns == nullptr) return MDOC_PROVER_NAMESPACES_MISSING;
169
+
170
+ // Find the attribute witness we need from here.
171
+ for (const char* sn : kSupportedNamespaces) {
172
+ auto mldns = ns[1].lookup(resp, strlen(sn), (const uint8_t*)sn, di);
173
+ if (mldns == nullptr) continue;
174
+ size_t ai = 0;
175
+ auto tattr = mldns[1].index(ai++);
176
+ while (tattr != nullptr) {
177
+ CborDoc er;
178
+ // Decode the map in this tagged attribute.
179
+ size_t pos = tattr->children_[0].u_.string.pos;
180
+ size_t end = pos + tattr->children_[0].u_.string.len;
181
+ if (!er.decode(resp, end, pos, 0)) {
182
+ return MDOC_PROVER_ATTRIBUTE_DECODE_FAILURE;
183
+ }
184
+
185
+ auto ei = er.lookup(resp, 17, (uint8_t*)"elementIdentifier", di);
186
+ if (ei == nullptr) return MDOC_PROVER_ATTRIBUTE_EI_MISSING;
187
+ auto ev = er.lookup(resp, 12, (uint8_t*)"elementValue", di);
188
+ if (ev == nullptr) return MDOC_PROVER_ATTRIBUTE_EV_MISSING;
189
+ auto digid = er.lookup(resp, 8, (uint8_t*)"digestID", di);
190
+ if (digid == nullptr) return MDOC_PROVER_ATTRIBUTE_DID_MISSING;
191
+ auto rand = er.lookup(resp, 6, (uint8_t*)"random", di);
192
+ if (rand == nullptr) return MDOC_PROVER_ATTRIBUTE_RANDOM_MISSING;
193
+
194
+ attributes_.push_back((FullAttribute){
195
+ // For the elementIdentifier, the [1] index is the position and
196
+ // length of the value.
197
+ ei[1].position(),
198
+ ei[1].length(),
199
+ // For version 7, record the index of the elementValue key, i.e.,
200
+ // ev[0], instead of the value. This makes it easier to handle
201
+ // different orderings of the elementIdentifier and elementValue
202
+ // keys in the CBOR encoding. Previous versions of the circuit did
203
+ // not use the ev[1] index, because they assumed canonical order.
204
+ ev[0].position(),
205
+ ev[1].length(),
206
+ digid[0].position(),
207
+ digid[0].length() + digid[1].length() + 1,
208
+ rand[0].position(),
209
+ rand[0].length() + rand[1].length() + 1 +
210
+ (rand[1].length() < 24 ? 1 : 2),
211
+ (const uint8_t*)sn,
212
+ static_cast<size_t>(digid[1].u_.u64), /* digest_id */
213
+ {0, 0, 0}, /* default mso_ind */
214
+ tattr->header_pos_, /* tag_ind */
215
+ tattr->children_[0].u_.string.len +
216
+ 4, /* +4 for the D8 18 58 <> prefix */
217
+ resp});
218
+
219
+ tattr = mldns[1].index(ai++);
220
+ }
221
+ }
222
+
223
+ auto ds = docs0[0].lookup(resp, 12, (uint8_t*)"deviceSigned", di);
224
+ if (ds == nullptr) return MDOC_PROVER_DEVICE_SIGNED_MISSING;
225
+ auto da = ds[1].lookup(resp, 10, (uint8_t*)"deviceAuth", di);
226
+ if (da == nullptr) return MDOC_PROVER_DEVICE_AUTH_MISSING;
227
+ auto dsi = da[1].lookup(resp, 15, (uint8_t*)"deviceSignature", di);
228
+ if (dsi == nullptr) return MDOC_PROVER_DEVICE_SIGNATURE_MISSING;
229
+ auto ndksig = dsi[1].index(3);
230
+ if (ndksig == nullptr) return MDOC_PROVER_DEVICE_SIGNATURE_MISSING;
231
+ copy_header(dksig_, ndksig);
232
+
233
+ // Then parse tagged mso. Skip 5 bytes to skip the D8 18 59 <len2>.
234
+ const uint8_t* pmso = resp + tmso->u_.string.pos + 5;
235
+ size_t pos = 0;
236
+ CborDoc mso;
237
+ if (!mso.decode(pmso, tmso->u_.string.len - 5, pos, 0))
238
+ return MDOC_PROVER_MSO_DECODING_FAILURE;
239
+ auto nv = mso.lookup(pmso, kValidityInfoLen, kValidityInfoID, valid_.ndx);
240
+ if (nv == nullptr) return MDOC_PROVER_VALIDITY_INFO_MISSING;
241
+ copy_kv_header(valid_, nv);
242
+
243
+ auto nvf = nv[1].lookup(pmso, kValidFromLen, kValidFromID, valid_from_.ndx);
244
+ if (nvf == nullptr) return MDOC_PROVER_VALIDITY_INFO_MISSING;
245
+ copy_kv_header(valid_from_, nvf);
246
+
247
+ auto nvu =
248
+ nv[1].lookup(pmso, kValidUntilLen, kValidUntilID, valid_until_.ndx);
249
+ if (nvu == nullptr) return MDOC_PROVER_VALIDITY_INFO_MISSING;
250
+ copy_kv_header(valid_until_, nvu);
251
+
252
+ auto ndki = mso.lookup(pmso, kDeviceKeyInfoLen, kDeviceKeyInfoID,
253
+ dev_key_info_.ndx);
254
+ if (ndki == nullptr) return MDOC_PROVER_DEVICE_KEY_INFO_MISSING;
255
+ copy_kv_header(dev_key_info_, ndki);
256
+
257
+ auto ndk = ndki[1].lookup(pmso, kDeviceKeyLen, kDeviceKeyID, dev_key_.ndx);
258
+ if (ndk == nullptr) return MDOC_PROVER_DEVICE_KEY_MISSING;
259
+ copy_kv_header(dev_key_, ndk);
260
+
261
+ auto npkx = ndk[1].lookup_negative(-1, dev_key_pkx_.ndx);
262
+ if (npkx == nullptr) return MDOC_PROVER_DEVICE_KEY_MISSING;
263
+ copy_kv_header(dev_key_pkx_, npkx);
264
+
265
+ auto npky = ndk[1].lookup_negative(-2, dev_key_pky_.ndx);
266
+ if (npky == nullptr) return MDOC_PROVER_DEVICE_KEY_MISSING;
267
+ copy_kv_header(dev_key_pky_, npky);
268
+
269
+ auto nvd =
270
+ mso.lookup(pmso, kValueDigestsLen, kValueDigestsID, value_digests_.ndx);
271
+ if (nvd == nullptr) return MDOC_PROVER_MSO_DECODING_FAILURE;
272
+ copy_kv_header(value_digests_, nvd);
273
+
274
+ // For backwards compatibility with 1f circuits, copy the hard-coded org_ if
275
+ // it is present. TODO(shelat): Remove this once all 1f circuits have
276
+ // been updated.
277
+ auto norg = nvd[1].lookup(pmso, kOrgLen, kOrgID, org_.ndx);
278
+ if (norg != nullptr) {
279
+ copy_kv_header(org_, norg);
280
+ }
281
+
282
+ for (auto& attr : attributes_) {
283
+ size_t index;
284
+ auto nss = nvd[1].lookup(pmso, strlen((const char*)attr.mdl_ns),
285
+ attr.mdl_ns, index);
286
+ if (nss == nullptr) return MDOC_PROVER_MSO_DECODING_FAILURE;
287
+ uint64_t hi = (uint64_t)attr.digest_id;
288
+ auto hattr = nss[1].lookup_unsigned(hi, attr.mso.ndx);
289
+ if (hattr == nullptr) return MDOC_PROVER_MSO_DECODING_FAILURE;
290
+ copy_kv_header(attr.mso, hattr);
291
+ }
292
+
293
+ tagged_mso_bytes_.assign(std::begin(kCose1Prefix), std::end(kCose1Prefix));
294
+ // Add 2-byte length
295
+ tagged_mso_bytes_.push_back((t_mso_.len >> 8) & 0xff);
296
+ tagged_mso_bytes_.push_back(t_mso_.len & 0xff);
297
+ for (size_t i = 0; i < t_mso_.len; ++i) {
298
+ tagged_mso_bytes_.push_back(resp[t_mso_.pos + i]);
299
+ }
300
+
301
+ return MDOC_PROVER_SUCCESS;
302
+ }
303
+
304
+ private:
305
+ // Used to copy the results of a map lookup.
306
+ static void copy_kv_header(CborIndex& ind, const CborDoc* n) {
307
+ ind.k = n[0].header_pos_;
308
+ ind.v = n[1].header_pos_;
309
+
310
+ if (n[1].t_ == TEXT || n[1].t_ == BYTES) {
311
+ ind.pos = n[1].u_.string.pos;
312
+ ind.len = n[1].u_.string.len;
313
+ }
314
+ }
315
+
316
+ // Used to copy the results of an index lookup.
317
+ static void copy_header(CborIndex& ind, const CborDoc* n) {
318
+ ind.k = n->header_pos_;
319
+ ind.pos = n->u_.string.pos;
320
+ ind.len = n->u_.string.len;
321
+ }
322
+ };
323
+
324
+ // Transform from u8 be (i.e., be[31] is the most significant byte) into
325
+ // nat form, which requires first converting to le byte order.
326
+ template <class Nat>
327
+ Nat nat_from_be(const uint8_t be[/* Nat::kBytes */]) {
328
+ uint8_t tmp[Nat::kBytes];
329
+ // Transform into byte-wise le representation.
330
+ for (size_t i = 0; i < Nat::kBytes; ++i) {
331
+ tmp[i] = be[Nat::kBytes - i - 1];
332
+ }
333
+ return Nat::of_bytes(tmp);
334
+ }
335
+
336
+ // Transform from u32 be (i.e., be[0] is the most significant nibble)
337
+ // into nat form, which requires first converting to le byte order.
338
+ template <class Nat>
339
+ Nat nat_from_u32(const uint32_t be[]) {
340
+ uint8_t tmp[Nat::kBytes];
341
+ const size_t top = Nat::kBytes / 4;
342
+ for (size_t i = 0; i < Nat::kBytes; ++i) {
343
+ tmp[i] = (be[top - i / 4 - 1] >> ((i % 4) * 8)) & 0xff;
344
+ }
345
+ return Nat::of_bytes(tmp);
346
+ }
347
+
348
+ template <typename Nat>
349
+ Nat nat_from_hash(const uint8_t data[], size_t len) {
350
+ uint8_t hash[kSHA256DigestSize];
351
+ SHA256 sha;
352
+ sha.Update(data, len);
353
+ sha.DigestData(hash);
354
+ Nat ne = nat_from_be<Nat>(hash);
355
+ return ne;
356
+ }
357
+
358
+ // Append the cbor encoding of the length of a bytestring to buf.
359
+ // This method handles bytestrings that are up to 255 bytes long.
360
+ static inline void append_bytes_len(std::vector<uint8_t>& buf, size_t len) {
361
+ check(len < 65536, "Bytestring length too large");
362
+ if (len < 24) {
363
+ buf.push_back(0x40 + len);
364
+ } else if (len < 256) {
365
+ uint8_t ll[] = {0x58, static_cast<uint8_t>(len & 0xff)};
366
+ buf.insert(buf.end(), ll, ll + 2);
367
+ } else {
368
+ uint8_t ll[] = {0x59, (uint8_t)((len >> 8) & 0xff), (uint8_t)(len & 0xff)};
369
+ buf.insert(buf.end(), ll, ll + 3);
370
+ }
371
+ }
372
+
373
+ // Append the cbor encoding of the length of a text string to buf.
374
+ // This method handles text strings that are up to 255 bytes long.
375
+ static inline void append_text_len(std::vector<uint8_t>& buf, size_t len) {
376
+ check(len < 256, "Text length too large");
377
+ if (len < 24) {
378
+ buf.push_back(0x60 + len);
379
+ } else if (len < 256) {
380
+ buf.push_back(0x78);
381
+ buf.push_back(len);
382
+ }
383
+ }
384
+
385
+ // Form the COSE1 encoding of the DeviceAuthenticationBytes,
386
+ // then compute its SHA-256 hash, and cast into a Nat.
387
+ // The original form follows S9.1.3.4 of the mdoc spec and
388
+ // assumed that the transcript was a simple string.
389
+ // The Jan'2024 demo requires using the "AndroidHandover" version
390
+ // of the DeviceAuthenticationBytes formatting, which is not
391
+ // specified in the spec. As a result, this function is a hack
392
+ // that mimics the bytes produced by the Android com.android.identity.wallet
393
+ // library.
394
+ template <class Nat>
395
+ static Nat compute_transcript_hash(
396
+ const uint8_t transcript[], size_t len,
397
+ const std::vector<uint8_t>* docType = nullptr) {
398
+ // The DeviceAuthenticationBytes is defined in 9.1.3.4 as:
399
+ // DeviceAuthentication = [
400
+ // "DeviceAuthentication",
401
+ // SessionTranscript,
402
+ // DocType, ; Same as in mdoc response
403
+ // DeviceNameSpacesBytes ; Same as in mdoc response
404
+ // ]
405
+ std::vector<uint8_t> deviceAuthentication = {
406
+ 0x84, 0x74, 'D', 'e', 'v', 'i', 'c', 'e', 'A', 'u', 't',
407
+ 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'i', 'o', 'n',
408
+ };
409
+ std::vector<uint8_t> docTypeBytes = {
410
+ 0x75, 'o', 'r', 'g', '.', 'i', 's', 'o', '.', '1', '8',
411
+ '0', '1', '3', '.', '5', '.', '1', '.', 'm', 'D', 'L',
412
+ };
413
+ std::vector<uint8_t> deviceNameSpacesBytes = {0xD8, 0x18, 0x41, 0xA0};
414
+
415
+ if (docType != nullptr && docType->size() < 256) {
416
+ docTypeBytes.clear();
417
+ append_text_len(docTypeBytes, docType->size());
418
+ docTypeBytes.insert(docTypeBytes.end(), docType->begin(), docType->end());
419
+ }
420
+
421
+ // Provide the DeviceAuthentication bytes
422
+ std::vector<uint8_t> da(deviceAuthentication);
423
+ da.insert(da.end(), transcript, transcript + len);
424
+ da.insert(da.end(), docTypeBytes.begin(), docTypeBytes.end());
425
+ da.insert(da.end(), deviceNameSpacesBytes.begin(),
426
+ deviceNameSpacesBytes.end());
427
+
428
+ // Form the COSE1 encoding of the DeviceAuthenticationBytes.
429
+ std::vector<uint8_t> cose1{0x84, 0x6A, 0x53, 0x69, 0x67, 0x6E,
430
+ 0x61, 0x74, 0x75, 0x72, 0x65, 0x31,
431
+ 0x43, 0xA1, 0x01, 0x26, 0x40};
432
+ uint8_t tag[] = {0xD8, 0x18};
433
+
434
+ size_t l1 = da.size();
435
+ size_t l2 = l1 + (l1 < 256 ? 4 : 5); /* Tagged array length. */
436
+ append_bytes_len(cose1, l2);
437
+ cose1.insert(cose1.end(), tag, tag + 2);
438
+ append_bytes_len(cose1, l1);
439
+ cose1.insert(cose1.end(), da.begin(), da.end());
440
+
441
+ return nat_from_hash<Nat>(cose1.data(), cose1.size());
442
+ }
443
+
444
+ // Interpret input s as an len*8-bit string, and use it to fill max*8 bits
445
+ // in the dense filler.
446
+ // Pad the input with the Field value 2 to indicate the positions
447
+ // that are not part of the string.
448
+ template <class Field>
449
+ void fill_bit_string(DenseFiller<Field>& filler, const uint8_t s[/*len*/],
450
+ size_t len, size_t max, const Field& Fs) {
451
+ std::vector<typename Field::Elt> v(max * 8, Fs.of_scalar(2));
452
+ for (size_t i = 0; i < max && i < len; ++i) {
453
+ fill_byte(v, s[i], i, Fs);
454
+ }
455
+ filler.push_back(v);
456
+ }
457
+
458
+ template <class Field>
459
+ void fill_byte(std::vector<typename Field::Elt>& v, uint8_t b, size_t i,
460
+ const Field& F) {
461
+ for (size_t j = 0; j < 8; ++j) {
462
+ v[i * 8 + j] = (b >> j & 0x1) ? F.one() : F.zero();
463
+ }
464
+ }
465
+
466
+ template <class Field>
467
+ MdocProverErrorCode fill_attribute(DenseFiller<Field>& filler,
468
+ const RequestedAttribute& attr,
469
+ const Field& F, size_t version) {
470
+ // In version >= 4, the attribute is encoded as
471
+ // <len(identifier)> <name of identifier> <elementValue> <attributeValue>.
472
+ // This extra length field distinguishes the two attributes:
473
+ // "aamva/domestic_driving_privileges" from "iso/driving_privileges." No
474
+ // other valid attribute name is a proper suffix of another. See the
475
+ // mdoc_attribute_ids.h file for the full list of attribute names and our
476
+ // restrictions.
477
+ // In version >= 7, the attribute is encoded in two parts:
478
+ // The first 32 bytes of the ei are "<len> <ei value>" padded to 32
479
+ // The next 64 bytes of the ev are "<ev value>"
480
+
481
+ // Both cases rely on the zero-padding of v.
482
+ std::vector<typename Field::Elt> v(96 * 8, F.zero());
483
+
484
+ if (version >= 7) {
485
+ std::vector<uint8_t> vbuf;
486
+ append_text_len(vbuf, attr.id_len);
487
+ vbuf.insert(vbuf.end(), attr.id, attr.id + attr.id_len);
488
+ for (size_t j = 0; j < vbuf.size() && j < 32; ++j) {
489
+ fill_byte(v, vbuf[j], j, F);
490
+ }
491
+
492
+ // Now fill the value
493
+ for (size_t j = 0; j < 64 && j < attr.cbor_value_len; ++j) {
494
+ fill_byte(v, attr.cbor_value[j], 32 + j, F);
495
+ }
496
+
497
+ filler.push_back(v);
498
+
499
+ // The v7 circuit use "<17> elementIdentifier <32 b of above>"
500
+ // to form the string that it compares against.
501
+ filler.push_back(1 + 17 + 1 + attr.id_len, 8, F);
502
+
503
+ // For the value, the v7 circuit uses "<12> elementValue <cbor_value>"
504
+ // as the comparison string.
505
+ size_t vlen = attr.cbor_value_len + 12 + 1;
506
+
507
+ filler.push_back(vlen, 8, F);
508
+ } else {
509
+ // version < 7
510
+ // Append the length of the elementIdentifier.
511
+ std::vector<uint8_t> vbuf;
512
+ append_text_len(vbuf, attr.id_len);
513
+ vbuf.insert(vbuf.end(), attr.id, attr.id + attr.id_len);
514
+ append_text_len(vbuf, 12); // len of "elementValue"
515
+ const char* ev = "elementValue";
516
+ vbuf.insert(vbuf.end(), ev, ev + 12);
517
+
518
+ vbuf.insert(vbuf.end(), attr.cbor_value,
519
+ attr.cbor_value + attr.cbor_value_len);
520
+
521
+ if (vbuf.size() > 96) {
522
+ log(ERROR, "Attribute %s is too long: %zu", attr.id, vbuf.size());
523
+ return MDOC_PROVER_ATTRIBUTE_TOO_LONG;
524
+ }
525
+ size_t len = 0;
526
+ for (size_t j = 0; j < vbuf.size() && len < 96; ++j, ++len) {
527
+ fill_byte(v, vbuf[j], len, F);
528
+ }
529
+ filler.push_back(v);
530
+ filler.push_back(len, 8, F);
531
+ }
532
+ return MDOC_PROVER_SUCCESS;
533
+ }
534
+
535
+ template <class EC, class ScalarField>
536
+ class MdocSignatureWitness {
537
+ using Field = typename EC::Field;
538
+ using Elt = typename Field::Elt;
539
+ using Nat = typename Field::N;
540
+ using EcdsaWitness = VerifyWitness3<EC, ScalarField>;
541
+ using MacWitnessF = MacWitness<Field>;
542
+ using f_128 = GF2_128<>;
543
+ const EC& ec_;
544
+ const f_128& gf_;
545
+
546
+ public:
547
+ Elt e_, e2_; /* Issuer signature values. */
548
+ Elt dpkx_, dpky_; /* device key */
549
+ EcdsaWitness ew_, dkw_;
550
+ MacWitnessF macs_[3]; /* macs for e_, dpkx_, dpky_ */
551
+
552
+ explicit MdocSignatureWitness(const EC& ec, const ScalarField& Fn,
553
+ const f_128& gf)
554
+ : ec_(ec),
555
+ gf_(gf),
556
+ ew_(Fn, ec),
557
+ dkw_(Fn, ec),
558
+ macs_{MacWitnessF(ec.f_, gf_), MacWitnessF(ec.f_, gf_),
559
+ MacWitnessF(ec.f_, gf_)} {}
560
+
561
+ void fill_witness(DenseFiller<Field>& filler) const {
562
+ filler.push_back(e_);
563
+ filler.push_back(dpkx_);
564
+ filler.push_back(dpky_);
565
+
566
+ ew_.fill_witness(filler);
567
+ dkw_.fill_witness(filler);
568
+ for (auto& mac : macs_) {
569
+ mac.fill_witness(filler);
570
+ }
571
+ }
572
+
573
+ MdocProverErrorCode compute_witness(Elt pkX, Elt pkY,
574
+ const uint8_t mdoc[/* len */], size_t len,
575
+ const uint8_t transcript[/* tlen */],
576
+ size_t tlen) {
577
+ ParsedMdoc pm;
578
+
579
+ MdocProverErrorCode err = pm.parse_device_response(len, mdoc);
580
+ if (err != MDOC_PROVER_SUCCESS) {
581
+ return err;
582
+ }
583
+
584
+ Nat ne = nat_from_hash<Nat>(pm.tagged_mso_bytes_.data(),
585
+ pm.tagged_mso_bytes_.size());
586
+ e_ = ec_.f_.to_montgomery(ne);
587
+
588
+ // Parse (r,s).
589
+ const size_t l = pm.sig_.len;
590
+ Nat nr = nat_from_be<Nat>(&mdoc[pm.sig_.pos]);
591
+ Nat ns = nat_from_be<Nat>(&mdoc[pm.sig_.pos + l / 2]);
592
+ bool sig_ok = ew_.compute_witness(pkX, pkY, ne, nr, ns);
593
+ if (!sig_ok) {
594
+ return MDOC_PROVER_SIGNATURE_FAILURE;
595
+ }
596
+
597
+ Nat ne2 = compute_transcript_hash<Nat>(transcript, tlen, &pm.doc_type_);
598
+ const size_t l2 = pm.dksig_.len;
599
+ Nat nr2 = nat_from_be<Nat>(&mdoc[pm.dksig_.pos]);
600
+ Nat ns2 = nat_from_be<Nat>(&mdoc[pm.dksig_.pos + l2 / 2]);
601
+ size_t pmso = pm.t_mso_.pos + 5; /* skip the tag */
602
+ dpkx_ = ec_.f_.to_montgomery(
603
+ nat_from_be<Nat>(&mdoc[pmso + pm.dev_key_pkx_.pos]));
604
+ dpky_ = ec_.f_.to_montgomery(
605
+ nat_from_be<Nat>(&mdoc[pmso + pm.dev_key_pky_.pos]));
606
+ e2_ = ec_.f_.to_montgomery(ne2);
607
+ bool dksig_ok = dkw_.compute_witness(dpkx_, dpky_, ne2, nr2, ns2);
608
+ if (!dksig_ok) {
609
+ return MDOC_PROVER_DEVICE_SIGNATURE_FAILURE;
610
+ }
611
+ return MDOC_PROVER_SUCCESS;
612
+ }
613
+ };
614
+
615
+ // EC: implements the elliptic curve for the mdoc
616
+ // Field: implements the field used to define the sumcheck circuit, which can
617
+ // be smaller than the EC field
618
+ template <typename EC, typename Field>
619
+ class MdocHashWitness {
620
+ using ECField = typename EC::Field;
621
+ using ECElt = typename ECField::Elt;
622
+ using ECNat = typename ECField::N;
623
+ using Elt = typename Field::Elt;
624
+ using vindex = std::array<Elt, kCborIndexBits>;
625
+
626
+ const EC& ec_;
627
+ const Field& fn_;
628
+
629
+ public:
630
+ ECElt e_; /* Issuer signature values. */
631
+ ECElt dpkx_, dpky_; /* device key */
632
+ uint8_t signed_bytes_[kMaxSHABlocks * 64];
633
+ uint8_t numb_; /* Number of the correct sha block. */
634
+
635
+ size_t num_attr_;
636
+ std::vector<std::vector<uint8_t>> attr_bytes_;
637
+ std::vector<std::vector<FlatSHA256Witness::BlockWitness>> atw_;
638
+
639
+ std::vector<uint8_t> attr_n_; /* All attributes currently require 2 SHA. */
640
+ std::vector<CborIndex> attr_mso_; /* The cbor indices of the attributes. */
641
+ std::vector<AttrShift> attr_ei_;
642
+ std::vector<AttrShift> attr_ev_;
643
+ std::vector<SaltedHash> attr_sh_;
644
+
645
+ FlatSHA256Witness::BlockWitness bw_[kMaxSHABlocks];
646
+
647
+ ParsedMdoc pm_;
648
+
649
+ explicit MdocHashWitness(size_t num_attr, const EC& ec, const Field& Fn)
650
+ : ec_(ec), fn_(Fn), num_attr_(num_attr) {}
651
+
652
+ void fill_cbor_index(DenseFiller<Field>& df, const CborIndex& ind) const {
653
+ df.push_back(ind.k, kCborIndexBits, fn_);
654
+ }
655
+
656
+ void fill_attr_shift(DenseFiller<Field>& df, const AttrShift& attr) const {
657
+ df.push_back(attr.offset, kCborIndexBits, fn_);
658
+ df.push_back(attr.len, kCborIndexBits, fn_);
659
+ }
660
+
661
+ void fill_salted_attr(DenseFiller<Field>& df, const SaltedHash& sh) const {
662
+ df.push_back(sh.i1, kCborIndexBits, fn_);
663
+ df.push_back(sh.i2, kCborIndexBits, fn_);
664
+ df.push_back(sh.i3, kCborIndexBits, fn_);
665
+ df.push_back(sh.l[0], kCborIndexBits, fn_);
666
+ df.push_back(sh.l[1], kCborIndexBits, fn_);
667
+ df.push_back(sh.l[2], kCborIndexBits, fn_);
668
+ df.push_back(sh.l[3], kCborIndexBits, fn_);
669
+ df.push_back(sh.perm, 8, fn_);
670
+ }
671
+
672
+ void fill_sha(DenseFiller<Field>& filler,
673
+ const FlatSHA256Witness::BlockWitness& bw) const {
674
+ BitPluckerEncoder<Field, kSHAPluckerBits> BPENC(fn_);
675
+ for (size_t k = 0; k < 48; ++k) {
676
+ filler.push_back(BPENC.mkpacked_v32(bw.outw[k]));
677
+ }
678
+ for (size_t k = 0; k < 64; ++k) {
679
+ filler.push_back(BPENC.mkpacked_v32(bw.oute[k]));
680
+ filler.push_back(BPENC.mkpacked_v32(bw.outa[k]));
681
+ }
682
+ for (size_t k = 0; k < 8; ++k) {
683
+ filler.push_back(BPENC.mkpacked_v32(bw.h1[k]));
684
+ }
685
+ }
686
+
687
+ void fill_witness(DenseFiller<Field>& filler, size_t version = 7) const {
688
+ // Fill sha of main mso.
689
+ filler.push_back(numb_, 8, fn_);
690
+ // Don't push the prefix. Version <=7 has a 35-block limit.
691
+ for (size_t i = kCose1PrefixLen; i < max_shablocks(version) * 64; ++i) {
692
+ filler.push_back(signed_bytes_[i], 8, fn_);
693
+ }
694
+ for (size_t j = 0; j < max_shablocks(version); j++) {
695
+ fill_sha(filler, bw_[j]);
696
+ }
697
+ // === done with sha
698
+
699
+ fill_cbor_index(filler, pm_.valid_from_);
700
+ fill_cbor_index(filler, pm_.valid_until_);
701
+ fill_cbor_index(filler, pm_.dev_key_info_);
702
+ fill_cbor_index(filler, pm_.value_digests_);
703
+
704
+ // Fill all attribute witnesses.
705
+ for (size_t ai = 0; ai < num_attr_; ++ai) {
706
+ for (size_t i = 0; i < 2 * 64; ++i) {
707
+ filler.push_back(attr_bytes_[ai][i], 8, fn_);
708
+ }
709
+ for (size_t j = 0; j < 2; j++) {
710
+ fill_sha(filler, atw_[ai][j]);
711
+ }
712
+
713
+ // In the case of attribute mso, push the value to avoid having to
714
+ // deal with 1- or 2- byte key length.
715
+ filler.push_back(attr_mso_[ai].v, kCborIndexBits, fn_);
716
+ fill_attr_shift(filler, attr_ei_[ai]);
717
+ fill_attr_shift(filler, attr_ev_[ai]);
718
+
719
+ if (version >= 7) {
720
+ fill_salted_attr(filler, attr_sh_[ai]);
721
+ }
722
+ }
723
+ }
724
+
725
+ size_t max_shablocks(size_t version) const {
726
+ if (version <= 6) return 35;
727
+ return kMaxSHABlocks;
728
+ }
729
+
730
+ MdocProverErrorCode compute_witness(const uint8_t mdoc[/* len */], size_t len,
731
+ const uint8_t transcript[/* tlen */],
732
+ size_t tlen,
733
+ const RequestedAttribute attrs[],
734
+ size_t attrs_len, size_t version) {
735
+ MdocProverErrorCode err = pm_.parse_device_response(len, mdoc);
736
+ if (err != MDOC_PROVER_SUCCESS) {
737
+ log(ERROR, "Failed to parse device response");
738
+ return err;
739
+ }
740
+
741
+ if (version < 4) return MDOC_PROVER_VERSION_NOT_SUPPORTED;
742
+
743
+ std::vector<uint8_t> buf;
744
+ if (pm_.t_mso_.len >= max_shablocks(version) * 64 - 9 - kCose1PrefixLen) {
745
+ log(ERROR, "tagged mso is too big: %zu", pm_.t_mso_.len);
746
+ return MDOC_PROVER_TAGGED_MSO_TOO_BIG;
747
+ }
748
+
749
+ buf.assign(std::begin(kCose1Prefix), std::end(kCose1Prefix));
750
+ // Add 2-byte length
751
+ buf.push_back((pm_.t_mso_.len >> 8) & 0xff);
752
+ buf.push_back(pm_.t_mso_.len & 0xff);
753
+ for (size_t i = 0; i < pm_.t_mso_.len; ++i) {
754
+ buf.push_back(mdoc[pm_.t_mso_.pos + i]);
755
+ }
756
+
757
+ FlatSHA256Witness::transform_and_witness_message(buf.size(), buf.data(),
758
+ max_shablocks(version),
759
+ numb_, signed_bytes_, bw_);
760
+
761
+ ECNat ne = nat_from_u32<ECNat>(bw_[numb_ - 1].h1);
762
+ e_ = ec_.f_.to_montgomery(ne);
763
+
764
+ size_t pmso = pm_.t_mso_.pos + 5; /* +5 to skip the tag */
765
+ dpkx_ = ec_.f_.to_montgomery(
766
+ nat_from_be<ECNat>(&mdoc[pmso + pm_.dev_key_pkx_.pos]));
767
+ dpky_ = ec_.f_.to_montgomery(
768
+ nat_from_be<ECNat>(&mdoc[pmso + pm_.dev_key_pky_.pos]));
769
+
770
+ // initialize variables
771
+ attr_n_.resize(attrs_len);
772
+ attr_mso_.resize(attrs_len);
773
+ attr_ev_.resize(attrs_len);
774
+ attr_ei_.resize(attrs_len);
775
+ attr_bytes_.resize(attrs_len);
776
+ atw_.resize(attrs_len);
777
+ attr_sh_.resize(attrs_len);
778
+
779
+ // Match the attributes with the witnesses from the deviceResponse.
780
+ for (size_t i = 0; i < attrs_len; ++i) {
781
+ attr_bytes_[i].resize(128);
782
+ atw_[i].resize(2);
783
+ bool found = false;
784
+ for (auto fa : pm_.attributes_) {
785
+ if (fa == attrs[i]) {
786
+ FlatSHA256Witness::transform_and_witness_message(
787
+ fa.tag_len, &fa.doc[fa.tag_ind], 2, attr_n_[i],
788
+ &attr_bytes_[i][0], &atw_[i][0]);
789
+ attr_mso_[i] = fa.mso;
790
+ // In version >= 4, the attribute id is encoded as the length of the
791
+ // id followed by the id. The witness starts at the id, so we
792
+ // subtract 1 or 2 to get the offset, depending on the id length.
793
+ attr_ei_[i].offset = fa.id_ind - fa.tag_ind - 1;
794
+ if (fa.id_len > 23) {
795
+ attr_ei_[i].offset -= 1;
796
+ }
797
+ attr_ei_[i].len = fa.witness_length(attrs[i]);
798
+
799
+ attr_ev_[i].offset = fa.val_ind - fa.tag_ind;
800
+ attr_ev_[i].len = fa.val_len;
801
+
802
+ // Version 7+ circuits support salted hashes in which ev may occur
803
+ // before ei. In this case, we provide two separate indices for the ev
804
+ // and ei. The circuit augments the check buffer with the
805
+ // "elementValue" and "elementIdentifier" prefixes respectively.
806
+ if (version >= 7) {
807
+ attr_ei_[i].offset =
808
+ fa.id_ind - fa.tag_ind; // points to name of attribute
809
+ attr_ei_[i].offset -=
810
+ fa.id_len < 24 ? 1 : 2; // subtract length of name
811
+ attr_ei_[i].offset -=
812
+ (17 + 1); // subtract "elementIdentifier" & length
813
+ attr_ei_[i].len = 17 + 1 + fa.id_len + (fa.id_len < 24 ? 1 : 2);
814
+
815
+ // -1 for len of elementValue
816
+ attr_ev_[i].offset = fa.val_ind - fa.tag_ind - 1;
817
+ attr_ev_[i].len = attrs[i].cbor_value_len + 12 + 1;
818
+
819
+ pos triples[4] = {
820
+ {fa.dig_ind - fa.tag_ind - 1, fa.dig_len, 0},
821
+ {fa.rand_ind - fa.tag_ind - 1, fa.rand_len, 1},
822
+ {attr_ei_[i].offset, attr_ei_[i].len, 2},
823
+ {attr_ev_[i].offset, attr_ev_[i].len, 3},
824
+ };
825
+ std::sort(triples, triples + 4,
826
+ [](const pos& a, const pos& b) { return a.i < b.i; });
827
+
828
+ attr_sh_[i].l[0] = triples[0].l;
829
+ attr_sh_[i].i1 = triples[1].i;
830
+ attr_sh_[i].l[1] = triples[1].l;
831
+ attr_sh_[i].i2 = triples[2].i;
832
+ attr_sh_[i].l[2] = triples[2].l;
833
+ attr_sh_[i].i3 = triples[3].i;
834
+ attr_sh_[i].l[3] = triples[3].l;
835
+ triples[0].ord = 0;
836
+ triples[1].ord = 1;
837
+ triples[2].ord = 2;
838
+ triples[3].ord = 3;
839
+
840
+ std::sort(triples, triples + 4,
841
+ [](const pos& a, const pos& b) { return a.p < b.p; });
842
+ attr_sh_[i].perm = triples[0].ord;
843
+ attr_sh_[i].perm |= triples[1].ord << 2;
844
+ attr_sh_[i].perm |= triples[2].ord << 4;
845
+ attr_sh_[i].perm |= triples[3].ord << 6;
846
+ }
847
+
848
+ found = true;
849
+ break;
850
+ }
851
+ }
852
+ if (!found) {
853
+ log(ERROR, "Could not find attribute %.*s", attrs[i].id_len,
854
+ attrs[i].id);
855
+ return MDOC_PROVER_ATTRIBUTE_NOT_FOUND;
856
+ }
857
+ }
858
+ return MDOC_PROVER_SUCCESS;
859
+ }
860
+ };
861
+ } // namespace proofs
862
+
863
+ #endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_MDOC_MDOC_WITNESS_H_