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.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +152 -0
- data/ext/longfellow/CMakeLists.txt +76 -0
- data/ext/longfellow/extconf.rb +77 -0
- data/lib/longfellow/attribute.rb +65 -0
- data/lib/longfellow/c.rb +105 -0
- data/lib/longfellow/errors.rb +78 -0
- data/lib/longfellow/version.rb +5 -0
- data/lib/longfellow/zk_spec.rb +40 -0
- data/lib/longfellow.rb +162 -0
- data/sig/longfellow.rbs +74 -0
- data/vendor/longfellow-zk/LICENSE +203 -0
- data/vendor/longfellow-zk/lib/algebra/blas.h +121 -0
- data/vendor/longfellow-zk/lib/algebra/bogorng.h +68 -0
- data/vendor/longfellow-zk/lib/algebra/compare.h +40 -0
- data/vendor/longfellow-zk/lib/algebra/convolution.h +219 -0
- data/vendor/longfellow-zk/lib/algebra/crt.cc +42 -0
- data/vendor/longfellow-zk/lib/algebra/crt.h +299 -0
- data/vendor/longfellow-zk/lib/algebra/crt_convolution.h +114 -0
- data/vendor/longfellow-zk/lib/algebra/crt_test.cc +371 -0
- data/vendor/longfellow-zk/lib/algebra/fft.h +104 -0
- data/vendor/longfellow-zk/lib/algebra/fft_interpolation.h +304 -0
- data/vendor/longfellow-zk/lib/algebra/fft_interpolation_test.cc +168 -0
- data/vendor/longfellow-zk/lib/algebra/fft_test.cc +257 -0
- data/vendor/longfellow-zk/lib/algebra/fp.h +59 -0
- data/vendor/longfellow-zk/lib/algebra/fp2.h +240 -0
- data/vendor/longfellow-zk/lib/algebra/fp24.h +342 -0
- data/vendor/longfellow-zk/lib/algebra/fp24_6.h +305 -0
- data/vendor/longfellow-zk/lib/algebra/fp24_6_test.cc +197 -0
- data/vendor/longfellow-zk/lib/algebra/fp2_test.cc +280 -0
- data/vendor/longfellow-zk/lib/algebra/fp_generic.h +533 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p128.h +91 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p256.h +68 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p256k1.h +123 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p384.h +65 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p521.h +62 -0
- data/vendor/longfellow-zk/lib/algebra/fp_test.cc +522 -0
- data/vendor/longfellow-zk/lib/algebra/hash.h +39 -0
- data/vendor/longfellow-zk/lib/algebra/interpolation.h +117 -0
- data/vendor/longfellow-zk/lib/algebra/interpolation_test.cc +74 -0
- data/vendor/longfellow-zk/lib/algebra/limb.h +153 -0
- data/vendor/longfellow-zk/lib/algebra/limb_test.cc +75 -0
- data/vendor/longfellow-zk/lib/algebra/nat.cc +32 -0
- data/vendor/longfellow-zk/lib/algebra/nat.h +212 -0
- data/vendor/longfellow-zk/lib/algebra/nat_test.cc +183 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumer.h +400 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumer_test.cc +138 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumerfp2_test.cc +139 -0
- data/vendor/longfellow-zk/lib/algebra/permutations.h +79 -0
- data/vendor/longfellow-zk/lib/algebra/poly.h +240 -0
- data/vendor/longfellow-zk/lib/algebra/poly_test.cc +123 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon.h +150 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension.h +108 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension_test.cc +76 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_test.cc +473 -0
- data/vendor/longfellow-zk/lib/algebra/rfft.h +400 -0
- data/vendor/longfellow-zk/lib/algebra/rfft_test.cc +102 -0
- data/vendor/longfellow-zk/lib/algebra/static_string.h +29 -0
- data/vendor/longfellow-zk/lib/algebra/sysdep.h +495 -0
- data/vendor/longfellow-zk/lib/algebra/sysdep_test.cc +41 -0
- data/vendor/longfellow-zk/lib/algebra/twiddle.h +59 -0
- data/vendor/longfellow-zk/lib/algebra/utility.h +86 -0
- data/vendor/longfellow-zk/lib/algebra/utility_test.cc +86 -0
- data/vendor/longfellow-zk/lib/arrays/affine.h +56 -0
- data/vendor/longfellow-zk/lib/arrays/affine_test.cc +220 -0
- data/vendor/longfellow-zk/lib/arrays/dense.h +210 -0
- data/vendor/longfellow-zk/lib/arrays/eq.h +75 -0
- data/vendor/longfellow-zk/lib/arrays/eqs.h +137 -0
- data/vendor/longfellow-zk/lib/arrays/eqs_test.cc +151 -0
- data/vendor/longfellow-zk/lib/arrays/sparse.h +192 -0
- data/vendor/longfellow-zk/lib/cbor/host_decoder.h +323 -0
- data/vendor/longfellow-zk/lib/cbor/host_decoder_test.cc +541 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor.h +594 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder_test.cc +147 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck.h +110 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck_test.cc +55 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_test.cc +174 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_testing.h +98 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_witness.h +312 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso2_test.cc +662 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso_test.cc +485 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan.h +104 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan_test.cc +137 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor.h +640 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder_test.cc +147 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_testing.h +99 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_witness.h +319 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/lexer_test.cc +120 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/mdoc_examples_test.cc +89 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_circuit_test.cc +506 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_size_test.cc +79 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_test.cc +473 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/canonicalization_test.cc +185 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/circuit_dump.h +65 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/compiler.h +471 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/compiler_test.cc +110 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/node.h +176 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/pdqhash.h +127 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/schedule.h +435 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_circuit.h +371 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_external_test.cc +246 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_test.cc +587 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_witness.h +201 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_adder.h +140 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_adder_test.cc +64 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker.h +247 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_constants.h +35 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_encoder.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_test.cc +183 -0
- data/vendor/longfellow-zk/lib/circuits/logic/compiler_backend.h +62 -0
- data/vendor/longfellow-zk/lib/circuits/logic/counter.h +171 -0
- data/vendor/longfellow-zk/lib/circuits/logic/counter_test.cc +102 -0
- data/vendor/longfellow-zk/lib/circuits/logic/evaluation_backend.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic.h +1232 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic_circuit_test.cc +310 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic_test.cc +521 -0
- data/vendor/longfellow-zk/lib/circuits/logic/memcmp.h +68 -0
- data/vendor/longfellow-zk/lib/circuits/logic/memcmp_test.cc +148 -0
- data/vendor/longfellow-zk/lib/circuits/logic/polynomial.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/logic/polynomial_test.cc +62 -0
- data/vendor/longfellow-zk/lib/circuits/logic/routing.h +445 -0
- data/vendor/longfellow-zk/lib/circuits/logic/routing_test.cc +241 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary.h +55 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker.h +77 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_constants.h +37 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_test.cc +53 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_size_test.cc +69 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_test.cc +62 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit.h +193 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit_test.cc +223 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_reference.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_witness.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/circuit_maker.cc +242 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_ids.h +311 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_test.cc +64 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_circuit_id.cc +85 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_constants.h +85 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.cc +41 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_examples.h +5232 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_generate_circuit.cc +199 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_hash.h +554 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature.h +143 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature_test.cc +444 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_test_attributes.h +157 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_witness.h +863 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.cc +693 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.h +216 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk_test.cc +724 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec.cc +100 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec_test.cc +155 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit.h +330 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit_test.cc +607 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_io.h +26 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.cc +163 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.h +47 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.cc +34 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_test_values.h +389 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/ptrcred.h +171 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small.h +218 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_examples.h +118 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_io.h +25 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_test.cc +208 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_witness.h +130 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode.h +508 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_circuit_test.cc +95 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_test.cc +119 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.cc +47 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.h +29 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit.h +231 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit_test.cc +428 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_witness.h +102 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt.h +190 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_constants.h +26 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_test.cc +559 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_witness.h +315 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f.h +411 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_io.h +32 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_test.cc +364 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_witness.h +278 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation.h +146 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_constants.h +25 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_test.cc +315 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_witness.h +136 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr.h +250 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_test.cc +333 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_witness.h +152 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44.h +903 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_circuit_test.cc +274 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_eval_test.cc +440 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.cc +8851 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.h +93 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.cc +24 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.h +118 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness.h +453 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness_test.cc +49 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.cc +458 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test.cc +398 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors.inc +3618 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_pkdecode.inc +689 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_sigdecode.inc +1501 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/sigdecode_test_vectors.inc +540 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit.h +394 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit_test.cc +577 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_constants.h +90 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.cc +174 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.h +140 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit.h +351 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit_test.cc +466 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.cc +207 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.h +59 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference_test.cc +153 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.cc +39 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.h +29 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_slicing.h +31 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.cc +83 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/shake_test_vectors.h +477 -0
- data/vendor/longfellow-zk/lib/ec/elliptic_curve.h +596 -0
- data/vendor/longfellow-zk/lib/ec/elliptic_curve_test.cc +548 -0
- data/vendor/longfellow-zk/lib/ec/p256.cc +36 -0
- data/vendor/longfellow-zk/lib/ec/p256.h +60 -0
- data/vendor/longfellow-zk/lib/ec/p256k1.cc +34 -0
- data/vendor/longfellow-zk/lib/ec/p256k1.h +60 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128.h +503 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128_bench.cc +48 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128_test.cc +416 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2poly.h +74 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14.h +242 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_bench.cc +75 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon.h +127 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon_test.cc +110 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_test.cc +246 -0
- data/vendor/longfellow-zk/lib/gf2k/sysdep.h +329 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_param.h +449 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_prover.h +354 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_test.cc +136 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_transcript.h +67 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_verifier.h +272 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_commitment.h +104 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_tree.h +216 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_tree_test.cc +240 -0
- data/vendor/longfellow-zk/lib/proto/circuit.h +354 -0
- data/vendor/longfellow-zk/lib/proto/circuit_test.cc +202 -0
- data/vendor/longfellow-zk/lib/random/random.h +119 -0
- data/vendor/longfellow-zk/lib/random/random_test.cc +189 -0
- data/vendor/longfellow-zk/lib/random/secure_random_engine.h +37 -0
- data/vendor/longfellow-zk/lib/random/transcript.h +193 -0
- data/vendor/longfellow-zk/lib/random/transcript_test.cc +344 -0
- data/vendor/longfellow-zk/lib/sumcheck/circuit.h +148 -0
- data/vendor/longfellow-zk/lib/sumcheck/circuit_id.h +71 -0
- data/vendor/longfellow-zk/lib/sumcheck/equad.h +126 -0
- data/vendor/longfellow-zk/lib/sumcheck/hquad.h +115 -0
- data/vendor/longfellow-zk/lib/sumcheck/prover.h +59 -0
- data/vendor/longfellow-zk/lib/sumcheck/prover_layers.h +362 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad.h +227 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad_builder.h +211 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad_test.cc +169 -0
- data/vendor/longfellow-zk/lib/sumcheck/sumcheck_test.cc +324 -0
- data/vendor/longfellow-zk/lib/sumcheck/testing.h +69 -0
- data/vendor/longfellow-zk/lib/sumcheck/transcript_sumcheck.h +85 -0
- data/vendor/longfellow-zk/lib/sumcheck/verifier.h +84 -0
- data/vendor/longfellow-zk/lib/sumcheck/verifier_layers.h +221 -0
- data/vendor/longfellow-zk/lib/testing/test_main.cc +50 -0
- data/vendor/longfellow-zk/lib/util/ceildiv.h +164 -0
- data/vendor/longfellow-zk/lib/util/ceildiv_test.cc +152 -0
- data/vendor/longfellow-zk/lib/util/crc64.h +45 -0
- data/vendor/longfellow-zk/lib/util/crypto.cc +39 -0
- data/vendor/longfellow-zk/lib/util/crypto.h +108 -0
- data/vendor/longfellow-zk/lib/util/log.cc +110 -0
- data/vendor/longfellow-zk/lib/util/log.h +33 -0
- data/vendor/longfellow-zk/lib/util/panic.h +40 -0
- data/vendor/longfellow-zk/lib/util/readbuffer.h +67 -0
- data/vendor/longfellow-zk/lib/util/serialization.h +54 -0
- data/vendor/longfellow-zk/lib/zk/zk_common.h +455 -0
- data/vendor/longfellow-zk/lib/zk/zk_proof.h +378 -0
- data/vendor/longfellow-zk/lib/zk/zk_prover.h +202 -0
- data/vendor/longfellow-zk/lib/zk/zk_test.cc +340 -0
- data/vendor/longfellow-zk/lib/zk/zk_testing.h +154 -0
- data/vendor/longfellow-zk/lib/zk/zk_verifier.h +109 -0
- 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_
|