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,371 @@
|
|
|
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_ECDSA_VERIFY_CIRCUIT_H_
|
|
16
|
+
#define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_ECDSA_VERIFY_CIRCUIT_H_
|
|
17
|
+
|
|
18
|
+
#include <stddef.h>
|
|
19
|
+
|
|
20
|
+
#include "circuits/logic/bit_plucker.h"
|
|
21
|
+
|
|
22
|
+
namespace proofs {
|
|
23
|
+
// Verify ECDSA signature using triple scalar mult form.
|
|
24
|
+
//
|
|
25
|
+
// The field used by sumcheck is the base field of the elliptic curve.
|
|
26
|
+
// Compiled circuit: ecdsa verify
|
|
27
|
+
// d: 7 wires: 21099 in: 1038 out:764 use:13911 ovh:7188 t:42963 cse:11351
|
|
28
|
+
// notn:34724
|
|
29
|
+
//
|
|
30
|
+
template <class LogicCircuit, class Field, class EC>
|
|
31
|
+
class VerifyCircuit {
|
|
32
|
+
using EltW = typename LogicCircuit::EltW;
|
|
33
|
+
using BitW = typename LogicCircuit::BitW;
|
|
34
|
+
using Elt = typename LogicCircuit::Elt;
|
|
35
|
+
using Nat = typename Field::N;
|
|
36
|
+
static constexpr size_t kBits = EC::kBits;
|
|
37
|
+
using Bitvec = typename LogicCircuit::v256;
|
|
38
|
+
|
|
39
|
+
public:
|
|
40
|
+
struct Witness {
|
|
41
|
+
EltW rx, ry;
|
|
42
|
+
EltW pre[8];
|
|
43
|
+
EltW rx_inv, s_inv, pk_inv;
|
|
44
|
+
EltW bi[kBits];
|
|
45
|
+
EltW int_x[kBits - 1];
|
|
46
|
+
EltW int_y[kBits - 1];
|
|
47
|
+
EltW int_z[kBits - 1];
|
|
48
|
+
|
|
49
|
+
void input(const LogicCircuit& lc) {
|
|
50
|
+
rx = lc.eltw_input();
|
|
51
|
+
ry = lc.eltw_input();
|
|
52
|
+
rx_inv = lc.eltw_input();
|
|
53
|
+
s_inv = lc.eltw_input();
|
|
54
|
+
pk_inv = lc.eltw_input();
|
|
55
|
+
for (size_t i = 0; i < 8; ++i) {
|
|
56
|
+
pre[i] = lc.eltw_input();
|
|
57
|
+
}
|
|
58
|
+
for (size_t i = 0; i < kBits; ++i) {
|
|
59
|
+
bi[i] = lc.eltw_input();
|
|
60
|
+
if (i < kBits - 1) {
|
|
61
|
+
int_x[i] = lc.eltw_input();
|
|
62
|
+
int_y[i] = lc.eltw_input();
|
|
63
|
+
int_z[i] = lc.eltw_input();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
VerifyCircuit(const LogicCircuit& lc, const EC& ec, const Nat& order)
|
|
70
|
+
: lc_(lc), ec_(ec), k2_(lc_.elt(2)), k3_(lc_.elt(3)) {
|
|
71
|
+
// Compute the bit representation of the order of the curve.
|
|
72
|
+
for (size_t i = 0; i < ec.kBits; ++i) {
|
|
73
|
+
bits_n_[i] = lc_.bit(order.bit(i));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// This verify takes the triple (pkx,pky,e) and checks that there exists
|
|
78
|
+
// (r=rx, ry, s) such that:
|
|
79
|
+
// identity = g*e + pk*r + (rx,ry)*-s
|
|
80
|
+
// It performs this check using a witness table that includes
|
|
81
|
+
// (g+pk, g+r, r+pk, g+r+pk), a correction element,
|
|
82
|
+
// bits of exponents (e, r, -s) s.t. each triple of bits is packed into {0,7},
|
|
83
|
+
// and intermediate ec points in (x,y,z) form. The bits are used to index the
|
|
84
|
+
// witness table in order to compute the right-hand side in a loop. The loop
|
|
85
|
+
// is sliced by providing the intermediate results in order reduce depth.
|
|
86
|
+
//
|
|
87
|
+
// An external constraint will need to ensure that e \neq 0 (e.g.,
|
|
88
|
+
// either the verifier checks this as part of the public input, or
|
|
89
|
+
// the hash that defines e is produced in the circuit). In our mdoc case,
|
|
90
|
+
// we use the later checks for both signatures.
|
|
91
|
+
//
|
|
92
|
+
// Other checks:
|
|
93
|
+
// r is interpreted as both in the base field and the scalar field.
|
|
94
|
+
// As a result, rx_inv is provided to ensure that r != 0.
|
|
95
|
+
// Similarly, s_inv is provided to ensure that s != 0.
|
|
96
|
+
//
|
|
97
|
+
// (rx,ry) is verified to be on the curve.
|
|
98
|
+
//
|
|
99
|
+
// (pkx, pky) \neq identity, because we set pk_z=1, we verify that
|
|
100
|
+
// pkx != 0, and we ensure that (pkx,pky) is on the curve.
|
|
101
|
+
//
|
|
102
|
+
void verify_signature3(EltW pk_x, EltW pk_y, EltW e, const Witness& w) const {
|
|
103
|
+
EltW zero = lc_.konst(lc_.zero());
|
|
104
|
+
EltW one = lc_.konst(lc_.one());
|
|
105
|
+
EltW gx = lc_.konst(ec_.gx_), gy = lc_.konst(ec_.gy_);
|
|
106
|
+
|
|
107
|
+
// indices for the pre[] table, don't change order
|
|
108
|
+
enum PreIndex {
|
|
109
|
+
GPK_X = 0,
|
|
110
|
+
GPK_Y,
|
|
111
|
+
GR_X,
|
|
112
|
+
GR_Y,
|
|
113
|
+
RPK_X,
|
|
114
|
+
RPK_Y,
|
|
115
|
+
GRPK_X,
|
|
116
|
+
GRPK_Y
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// These variables hold the (e,r) exponents which are computed from the
|
|
120
|
+
// bits of advice (e,r,-s). They are compared with their expected values.
|
|
121
|
+
EltW est = zero, rst = zero, sst = zero;
|
|
122
|
+
|
|
123
|
+
// initialize at the 0 point, but these indices are reset on each loop
|
|
124
|
+
EltW ax = zero, ay = one, az = zero;
|
|
125
|
+
|
|
126
|
+
// =========
|
|
127
|
+
// Verify the values received in the table are correct.
|
|
128
|
+
// By verifying these values in parallel with using them, we can reduce
|
|
129
|
+
// the depth of the resulting circuit.
|
|
130
|
+
EltW cg_pkx, cg_pky, cg_pkz;
|
|
131
|
+
EltW cr_pkx, cr_pky, cr_pkz;
|
|
132
|
+
EltW cr_gx, cr_gy, cr_gz;
|
|
133
|
+
EltW cr_g_pkx, cr_g_pky, cr_g_pkz;
|
|
134
|
+
addE(cg_pkx, cg_pky, cg_pkz, gx, gy, one, pk_x, pk_y, one);
|
|
135
|
+
addE(cr_gx, cr_gy, cr_gz, w.rx, w.ry, one, gx, gy, one);
|
|
136
|
+
addE(cr_pkx, cr_pky, cr_pkz, w.rx, w.ry, one, pk_x, pk_y, one);
|
|
137
|
+
addE(cr_g_pkx, cr_g_pky, cr_g_pkz, gx, gy, one, w.pre[RPK_X], w.pre[RPK_Y],
|
|
138
|
+
one);
|
|
139
|
+
point_equality(cg_pkx, cg_pky, cg_pkz, w.pre[GPK_X], w.pre[GPK_Y]);
|
|
140
|
+
point_equality(cr_gx, cr_gy, cr_gz, w.pre[GR_X], w.pre[GR_Y]);
|
|
141
|
+
point_equality(cr_pkx, cr_pky, cr_pkz, w.pre[RPK_X], w.pre[RPK_Y]);
|
|
142
|
+
point_equality(cr_g_pkx, cr_g_pky, cr_g_pkz, w.pre[GRPK_X], w.pre[GRPK_Y]);
|
|
143
|
+
|
|
144
|
+
EltW arr_x[] = {zero, gx, pk_x, w.pre[GPK_X],
|
|
145
|
+
w.rx, w.pre[GR_X], w.pre[RPK_X], w.pre[GRPK_X]};
|
|
146
|
+
EltW arr_y[] = {one, gy, pk_y, w.pre[GPK_Y],
|
|
147
|
+
w.ry, w.pre[GR_Y], w.pre[RPK_Y], w.pre[GRPK_Y]};
|
|
148
|
+
EltW arr_z[] = {zero, one, one, one, one, one, one, one};
|
|
149
|
+
EltW arr_e[] = {zero, one, zero, one, zero, one, zero, one};
|
|
150
|
+
EltW arr_r[] = {zero, zero, one, one, zero, zero, one, one};
|
|
151
|
+
EltW arr_s[] = {zero, zero, zero, zero, one, one, one, one};
|
|
152
|
+
|
|
153
|
+
// To verify that the advice bit is in [0,7], we need to mux the point
|
|
154
|
+
// corresponding to the advice bit using degree 8 (9 points). We use the
|
|
155
|
+
// EltMuxer<LogicCircuit, 9, 8> to do this. See comments in EltMuxer.
|
|
156
|
+
EltW arr_v[] = {zero, zero, zero, zero, zero, zero, zero, zero, one};
|
|
157
|
+
|
|
158
|
+
EltMuxer<LogicCircuit, 8> xx(lc_, arr_x);
|
|
159
|
+
EltMuxer<LogicCircuit, 8> yy(lc_, arr_y);
|
|
160
|
+
EltMuxer<LogicCircuit, 8> zz(lc_, arr_z);
|
|
161
|
+
EltMuxer<LogicCircuit, 8> ee(lc_, arr_e);
|
|
162
|
+
EltMuxer<LogicCircuit, 8> rr(lc_, arr_r);
|
|
163
|
+
EltMuxer<LogicCircuit, 8> ss(lc_, arr_s);
|
|
164
|
+
EltMuxer<LogicCircuit, 9, 8> vv(lc_, arr_v);
|
|
165
|
+
|
|
166
|
+
Bitvec r_bits, s_bits;
|
|
167
|
+
|
|
168
|
+
// Traverses the bits of the scalar from high-order to low-order.
|
|
169
|
+
for (size_t i = 0; i < kBits; ++i) {
|
|
170
|
+
// Use the arr{X..V} arrays and the muxer to pick the correct point
|
|
171
|
+
// slice based on the bits of advice in the witness.
|
|
172
|
+
EltW tx = xx.mux(w.bi[i]);
|
|
173
|
+
EltW ty = yy.mux(w.bi[i]);
|
|
174
|
+
EltW tz = zz.mux(w.bi[i]);
|
|
175
|
+
|
|
176
|
+
// Update the exponent.
|
|
177
|
+
EltW e_bi = ee.mux(w.bi[i]);
|
|
178
|
+
EltW r_bi = rr.mux(w.bi[i]);
|
|
179
|
+
EltW s_bi = ss.mux(w.bi[i]);
|
|
180
|
+
auto k2 = lc_.konst(k2_);
|
|
181
|
+
est = lc_.add(e_bi, lc_.mul(k2, est));
|
|
182
|
+
rst = lc_.add(r_bi, lc_.mul(k2, rst));
|
|
183
|
+
sst = lc_.add(s_bi, lc_.mul(k2, sst));
|
|
184
|
+
r_bits[kBits - i - 1] = BitW(r_bi, ec_.f_);
|
|
185
|
+
s_bits[kBits - i - 1] = BitW(s_bi, ec_.f_);
|
|
186
|
+
|
|
187
|
+
// Verify that the advice bit is in [0,7].
|
|
188
|
+
EltW range = vv.mux(w.bi[i]);
|
|
189
|
+
lc_.assert0(range);
|
|
190
|
+
|
|
191
|
+
// Perform the basic add-dbl step in repeated squaring using the
|
|
192
|
+
// muxed point {tx, ty, tz}.
|
|
193
|
+
if (i > 0) {
|
|
194
|
+
doubleE(ax, ay, az, ax, ay, az);
|
|
195
|
+
}
|
|
196
|
+
addE(ax, ay, az, ax, ay, az, tx, ty, tz);
|
|
197
|
+
|
|
198
|
+
if (i < kBits - 1) {
|
|
199
|
+
// Ensure that the resulting point is equal to the intermediate
|
|
200
|
+
// point provided as input. Performing an explicit equality check
|
|
201
|
+
// ensures that all intermediate witness points are on the curve.
|
|
202
|
+
// This follows by induction. The first (ax,ay,az) is on the curve.
|
|
203
|
+
// The addition formula ensures that the i-th (ax,ay,az) is on the
|
|
204
|
+
// curve; equality ensures that the i-th witness is on the curve.
|
|
205
|
+
lc_.assert_eq(ax, w.int_x[i]);
|
|
206
|
+
lc_.assert_eq(ay, w.int_y[i]);
|
|
207
|
+
lc_.assert_eq(az, w.int_z[i]);
|
|
208
|
+
|
|
209
|
+
// Use the intermediate (x,y,z) point as the next input.
|
|
210
|
+
ax = w.int_x[i];
|
|
211
|
+
ay = w.int_y[i];
|
|
212
|
+
az = w.int_z[i];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Check that the aX,aZ points are 0.
|
|
217
|
+
lc_.assert0(ax);
|
|
218
|
+
lc_.assert0(az);
|
|
219
|
+
|
|
220
|
+
// Check that the bits used for {e,rx} correspond to the input {e, rx}.
|
|
221
|
+
lc_.assert_eq(est, e);
|
|
222
|
+
lc_.assert_eq(rst, w.rx);
|
|
223
|
+
|
|
224
|
+
// Check that (pk,py), (rx,ry) satisfy the curve equation.
|
|
225
|
+
is_on_curve(pk_x, pk_y);
|
|
226
|
+
is_on_curve(w.rx, w.ry);
|
|
227
|
+
|
|
228
|
+
// Verify that exponents (r,s) are not zero.
|
|
229
|
+
// A witness is provided to ensure that both values have inverses in F.
|
|
230
|
+
// A bitwise comparison is done to ensure both are < |order| of EC.
|
|
231
|
+
assert_nonzero(w.rx, w.rx_inv);
|
|
232
|
+
assert_nonzero(sst, w.s_inv);
|
|
233
|
+
assert_nonzero(pk_x, w.pk_inv);
|
|
234
|
+
auto r_range = lc_.vlt(r_bits, bits_n_);
|
|
235
|
+
auto s_range = lc_.vlt(s_bits, bits_n_);
|
|
236
|
+
lc_.assert1(r_range);
|
|
237
|
+
lc_.assert1(s_range);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
private:
|
|
241
|
+
void assert_nonzero(EltW x, EltW witness) const {
|
|
242
|
+
auto maybe_one = lc_.mul(x, witness);
|
|
243
|
+
auto one = lc_.konst(lc_.one());
|
|
244
|
+
lc_.assert_eq(maybe_one, one);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
void point_equality(EltW x, EltW y, EltW z, EltW p_x, EltW p_y) const {
|
|
248
|
+
lc_.assert_eq(x, lc_.mul(z, p_x));
|
|
249
|
+
lc_.assert_eq(y, lc_.mul(z, p_y));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
void is_on_curve(EltW x, EltW y) const {
|
|
253
|
+
// Check that y^2 = x^3 + ax + b
|
|
254
|
+
auto yy = lc_.mul(y, y);
|
|
255
|
+
auto xx = lc_.mul(x, x);
|
|
256
|
+
auto xxx = lc_.mul(x, xx);
|
|
257
|
+
auto ax = lc_.mul(ec_.a_, x);
|
|
258
|
+
auto b = lc_.konst(ec_.b_);
|
|
259
|
+
auto axb = lc_.add(ax, b);
|
|
260
|
+
auto rhs = lc_.add(axb, xxx);
|
|
261
|
+
lc_.assert_eq(yy, rhs);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
void addE(EltW& X3, EltW& Y3, EltW& Z3, EltW X1, EltW Y1, EltW Z1, EltW X2,
|
|
265
|
+
EltW Y2, EltW Z2) const {
|
|
266
|
+
// The general case.
|
|
267
|
+
// Algorithm 1: Complete, projective point addition for arbitrary prime
|
|
268
|
+
// order short Weierstrass curves E/Fq : y^2 = x^3 + ax + b
|
|
269
|
+
// The compiler seems to optimize the cases when Z1,Z2=1.
|
|
270
|
+
EltW t0 = lc_.mul(X1, X2);
|
|
271
|
+
EltW t1 = lc_.mul(Y1, Y2);
|
|
272
|
+
EltW t2 = lc_.mul(Z1, Z2);
|
|
273
|
+
EltW t3 = lc_.add(X1, Y1);
|
|
274
|
+
EltW t4 = lc_.add(X2, Y2);
|
|
275
|
+
t3 = lc_.mul(t3, t4);
|
|
276
|
+
t4 = lc_.add(t0, t1);
|
|
277
|
+
t3 = lc_.sub(t3, t4);
|
|
278
|
+
t4 = lc_.add(X1, Z1);
|
|
279
|
+
EltW t5 = lc_.add(X2, Z2);
|
|
280
|
+
t4 = lc_.mul(t4, t5);
|
|
281
|
+
t5 = lc_.add(t0, t2);
|
|
282
|
+
t4 = lc_.sub(t4, t5);
|
|
283
|
+
t5 = lc_.add(Y1, Z1);
|
|
284
|
+
EltW X3t = lc_.add(Y2, Z2);
|
|
285
|
+
t5 = lc_.mul(t5, X3t);
|
|
286
|
+
X3t = lc_.add(t1, t2);
|
|
287
|
+
t5 = lc_.sub(t5, X3t);
|
|
288
|
+
auto a = lc_.konst(ec_.a_);
|
|
289
|
+
EltW Z3t = lc_.mul(a, t4);
|
|
290
|
+
auto k3b = lc_.konst(ec_.k3b);
|
|
291
|
+
X3t = lc_.mul(k3b, t2);
|
|
292
|
+
Z3t = lc_.add(X3t, Z3t);
|
|
293
|
+
X3t = lc_.sub(t1, Z3t);
|
|
294
|
+
Z3t = lc_.add(t1, Z3t);
|
|
295
|
+
EltW Y3t = lc_.mul(X3t, Z3t);
|
|
296
|
+
t1 = lc_.add(t0, t0);
|
|
297
|
+
t1 = lc_.add(t1, t0);
|
|
298
|
+
t2 = lc_.mul(a, t2);
|
|
299
|
+
t4 = lc_.mul(k3b, t4);
|
|
300
|
+
t1 = lc_.add(t1, t2);
|
|
301
|
+
t2 = lc_.sub(t0, t2);
|
|
302
|
+
t2 = lc_.mul(a, t2);
|
|
303
|
+
t4 = lc_.add(t4, t2);
|
|
304
|
+
t0 = lc_.mul(t1, t4);
|
|
305
|
+
Y3t = lc_.add(Y3t, t0);
|
|
306
|
+
t0 = lc_.mul(t5, t4);
|
|
307
|
+
X3t = lc_.mul(t3, X3t);
|
|
308
|
+
X3t = lc_.sub(X3t, t0);
|
|
309
|
+
t0 = lc_.mul(t3, t1);
|
|
310
|
+
Z3t = lc_.mul(t5, Z3t);
|
|
311
|
+
Z3t = lc_.add(Z3t, t0);
|
|
312
|
+
|
|
313
|
+
X3 = X3t;
|
|
314
|
+
Y3 = Y3t;
|
|
315
|
+
Z3 = Z3t;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
void doubleE(EltW& X3, EltW& Y3, EltW& Z3, EltW X, EltW Y, EltW Z) const {
|
|
319
|
+
// The general case.
|
|
320
|
+
// Algorithm 3: Exception-free point doubling for arbitrary prime order
|
|
321
|
+
// short Weierstrass curves E/Fq : y^2 = x^3 + ax + b.
|
|
322
|
+
// The compiler will presumably optimize away 0 mults when a=0 and 1
|
|
323
|
+
// mults when Z = 1.
|
|
324
|
+
EltW t0 = lc_.mul(X, X);
|
|
325
|
+
EltW t1 = lc_.mul(Y, Y);
|
|
326
|
+
EltW t2 = lc_.mul(Z, Z);
|
|
327
|
+
EltW t3 = lc_.mul(X, Y);
|
|
328
|
+
t3 = lc_.add(t3, t3);
|
|
329
|
+
EltW Z3t = lc_.mul(X, Z);
|
|
330
|
+
Z3t = lc_.add(Z3t, Z3t);
|
|
331
|
+
auto a = lc_.konst(ec_.a_);
|
|
332
|
+
auto k3b = lc_.konst(ec_.k3b);
|
|
333
|
+
EltW X3t = lc_.mul(a, Z3t);
|
|
334
|
+
EltW Y3t = lc_.mul(k3b, t2);
|
|
335
|
+
Y3t = lc_.add(X3t, Y3t);
|
|
336
|
+
X3t = lc_.sub(t1, Y3t);
|
|
337
|
+
Y3t = lc_.add(t1, Y3t);
|
|
338
|
+
Y3t = lc_.mul(X3t, Y3t);
|
|
339
|
+
X3t = lc_.mul(t3, X3t);
|
|
340
|
+
Z3t = lc_.mul(k3b, Z3t);
|
|
341
|
+
t2 = lc_.mul(a, t2);
|
|
342
|
+
t3 = lc_.sub(t0, t2);
|
|
343
|
+
t3 = lc_.mul(a, t3);
|
|
344
|
+
t3 = lc_.add(t3, Z3t);
|
|
345
|
+
Z3t = lc_.add(t0, t0);
|
|
346
|
+
t0 = lc_.add(Z3t, t0);
|
|
347
|
+
t0 = lc_.add(t0, t2);
|
|
348
|
+
t0 = lc_.mul(t0, t3);
|
|
349
|
+
Y3t = lc_.add(Y3t, t0);
|
|
350
|
+
t2 = lc_.mul(Y, Z);
|
|
351
|
+
t2 = lc_.add(t2, t2);
|
|
352
|
+
t0 = lc_.mul(t2, t3);
|
|
353
|
+
X3t = lc_.sub(X3t, t0);
|
|
354
|
+
Z3t = lc_.mul(t2, t1);
|
|
355
|
+
Z3t = lc_.add(Z3t, Z3t);
|
|
356
|
+
Z3t = lc_.add(Z3t, Z3t);
|
|
357
|
+
|
|
358
|
+
X3 = X3t;
|
|
359
|
+
Y3 = Y3t;
|
|
360
|
+
Z3 = Z3t;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const LogicCircuit& lc_;
|
|
364
|
+
const EC& ec_;
|
|
365
|
+
|
|
366
|
+
Elt k2_, k3_;
|
|
367
|
+
Bitvec bits_n_;
|
|
368
|
+
};
|
|
369
|
+
} // namespace proofs
|
|
370
|
+
|
|
371
|
+
#endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_ECDSA_VERIFY_CIRCUIT_H_
|
|
@@ -0,0 +1,246 @@
|
|
|
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
|
+
#include <cctype>
|
|
16
|
+
#include <cstddef>
|
|
17
|
+
#include <cstdint>
|
|
18
|
+
#include <cstdio>
|
|
19
|
+
#include <cstring>
|
|
20
|
+
|
|
21
|
+
// This test is meant to run once for 10^k repetitions to "fuzz" for any
|
|
22
|
+
// possible error in completeness or soundness for our ecdsa verification
|
|
23
|
+
// circuit. The test works by generating a random key, message, and signature
|
|
24
|
+
// using openssl, and then verifying the signature using our circuit. Next, we
|
|
25
|
+
// maul the signature by twiddling a single hex digit in the original 5-tuple,
|
|
26
|
+
// and ensure that the resulting signature fails. Allthough this only checks
|
|
27
|
+
// that single edit distance changes cause failures, it is a basic test.
|
|
28
|
+
//
|
|
29
|
+
// $ blaze-bin/ecdsa/verify_external_test \
|
|
30
|
+
// --gunit_repeat 10000
|
|
31
|
+
|
|
32
|
+
#include "circuits/ecdsa/verify_circuit.h"
|
|
33
|
+
#include "circuits/ecdsa/verify_witness.h"
|
|
34
|
+
#include "circuits/logic/evaluation_backend.h"
|
|
35
|
+
#include "circuits/logic/logic.h"
|
|
36
|
+
#include "ec/p256.h"
|
|
37
|
+
#include "util/log.h"
|
|
38
|
+
#include "gtest/gtest.h"
|
|
39
|
+
#include "openssl/evp.h"
|
|
40
|
+
#include "openssl/bn.h"
|
|
41
|
+
#include "openssl/ec.h"
|
|
42
|
+
|
|
43
|
+
#include "openssl/ecdsa.h"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
#include "openssl/rand.h"
|
|
47
|
+
|
|
48
|
+
namespace proofs {
|
|
49
|
+
namespace {
|
|
50
|
+
|
|
51
|
+
// This test is specific to P256 via the external openssl dependencies.
|
|
52
|
+
// Therefore the types are globally defined for convenience.
|
|
53
|
+
using Field = Fp256Base;
|
|
54
|
+
using Nat = Field::N;
|
|
55
|
+
using Elt = Field::Elt;
|
|
56
|
+
using EvalBackend = EvaluationBackend<Field>;
|
|
57
|
+
using Logic = Logic<Field, EvalBackend>;
|
|
58
|
+
using Verc = VerifyCircuit<Logic, Field, P256>;
|
|
59
|
+
using Verw = VerifyWitness3<P256, Fp256Scalar>;
|
|
60
|
+
|
|
61
|
+
struct signature_tuple {
|
|
62
|
+
char pkx[67];
|
|
63
|
+
char pky[67];
|
|
64
|
+
char e[67];
|
|
65
|
+
char r[67];
|
|
66
|
+
char s[67];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
struct circuit_params {
|
|
70
|
+
Elt pkx, pky, e;
|
|
71
|
+
typename Verc::Witness vwc;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
class ecdsa_params {
|
|
75
|
+
public:
|
|
76
|
+
EC_KEY* eckey_;
|
|
77
|
+
EC_GROUP* group_;
|
|
78
|
+
|
|
79
|
+
ecdsa_params() : eckey_(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)),
|
|
80
|
+
group_(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) { }
|
|
81
|
+
|
|
82
|
+
~ecdsa_params() {
|
|
83
|
+
EC_KEY_free(eckey_);
|
|
84
|
+
EC_GROUP_free(group_);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Generates a random key (pkx,pky) and a signature (r,s) on a random message e
|
|
89
|
+
// using the openssl ECDSA implementation. These values are written as
|
|
90
|
+
// null-terminated strings in hex format to the buffers passed in. The caller
|
|
91
|
+
// must ensure that the buffers are at least 67 bytes long.
|
|
92
|
+
// The goal is to produce an externally verified testing tuple for our own
|
|
93
|
+
// implementation.
|
|
94
|
+
bool gensig(signature_tuple& st, const ecdsa_params& params) {
|
|
95
|
+
if (!EC_KEY_generate_key(params.eckey_)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Random message
|
|
100
|
+
unsigned char hash[32];
|
|
101
|
+
RAND_bytes(hash, sizeof(hash));
|
|
102
|
+
|
|
103
|
+
ECDSA_SIG* sig = ECDSA_do_sign(hash, sizeof(hash), params.eckey_);
|
|
104
|
+
if (!sig) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Get the signature components (r and s)
|
|
109
|
+
const BIGNUM* br = ECDSA_SIG_get0_r(sig);
|
|
110
|
+
const BIGNUM* bs = ECDSA_SIG_get0_s(sig);
|
|
111
|
+
char* r_hex = BN_bn2hex(br);
|
|
112
|
+
char* s_hex = BN_bn2hex(bs);
|
|
113
|
+
|
|
114
|
+
// Get the public key
|
|
115
|
+
const EC_POINT* pub_key = EC_KEY_get0_public_key(params.eckey_);
|
|
116
|
+
uint8_t buf[200];
|
|
117
|
+
EC_POINT_point2oct(params.group_, pub_key, POINT_CONVERSION_UNCOMPRESSED, buf,
|
|
118
|
+
sizeof(buf), nullptr);
|
|
119
|
+
|
|
120
|
+
// Easiest interface to our circuit library is via hex-formatted strings.
|
|
121
|
+
// NOLINTBEGIN(runtime/printf)
|
|
122
|
+
snprintf(st.pkx, 3, "0x");
|
|
123
|
+
snprintf(st.pky, 3, "0x");
|
|
124
|
+
snprintf(st.e, 3, "0x");
|
|
125
|
+
for (size_t i = 0; i < 32; ++i) {
|
|
126
|
+
snprintf(&st.pkx[2 + i * 2], 3, "%02x", buf[i + 1]);
|
|
127
|
+
snprintf(&st.pky[2 + i * 2], 3, "%02x", buf[i + 33]);
|
|
128
|
+
snprintf(&st.e[2 + i * 2], 3, "%02x", hash[i]);
|
|
129
|
+
}
|
|
130
|
+
// NOLINTEND(runtime/printf)
|
|
131
|
+
|
|
132
|
+
snprintf(st.r, sizeof(st.r), "0x%.64s", r_hex);
|
|
133
|
+
snprintf(st.s, sizeof(st.s), "0x%.64s", s_hex);
|
|
134
|
+
|
|
135
|
+
// Clean up
|
|
136
|
+
ECDSA_SIG_free(sig);
|
|
137
|
+
OPENSSL_free(r_hex);
|
|
138
|
+
OPENSSL_free(s_hex);
|
|
139
|
+
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
char twiddle(char in) {
|
|
144
|
+
char d[] = "0123456789abcdef";
|
|
145
|
+
static size_t cnt = 5;
|
|
146
|
+
while (tolower(in) == d[cnt]) {
|
|
147
|
+
cnt = (cnt + 1) % 16;
|
|
148
|
+
}
|
|
149
|
+
return d[cnt];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
void maulSignature(const signature_tuple& in, signature_tuple& out) {
|
|
153
|
+
out = in;
|
|
154
|
+
|
|
155
|
+
// Pick a (biased) random spot to twiddle.
|
|
156
|
+
uint8_t pos[2];
|
|
157
|
+
RAND_bytes(pos, 2);
|
|
158
|
+
char* fields[] = {out.r, out.s, out.e, out.pkx, out.pky};
|
|
159
|
+
size_t fi = pos[0] % 5;
|
|
160
|
+
size_t ind = (pos[1] % 62) + 2;
|
|
161
|
+
fields[fi][ind] = twiddle(fields[fi][ind]);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
void prepare_witness(const signature_tuple& st, circuit_params& in,
|
|
165
|
+
const Logic& l, const Field& F) {
|
|
166
|
+
Verw vw(p256_scalar, p256);
|
|
167
|
+
|
|
168
|
+
in.pkx = F.of_string(st.pkx);
|
|
169
|
+
in.pky = F.of_string(st.pky);
|
|
170
|
+
Nat e = Nat(st.e);
|
|
171
|
+
Nat r = Nat(st.r);
|
|
172
|
+
Nat s = Nat(st.s);
|
|
173
|
+
in.e = F.to_montgomery(e);
|
|
174
|
+
|
|
175
|
+
vw.compute_witness(in.pkx, in.pky, e, r, s);
|
|
176
|
+
|
|
177
|
+
in.vwc.rx = l.konst(vw.rx_);
|
|
178
|
+
in.vwc.ry = l.konst(vw.ry_);
|
|
179
|
+
in.vwc.rx_inv = l.konst(vw.rx_inv_);
|
|
180
|
+
in.vwc.s_inv = l.konst(vw.s_inv_);
|
|
181
|
+
in.vwc.pk_inv = l.konst(vw.pk_inv_);
|
|
182
|
+
for (size_t j = 0; j < 8; ++j) {
|
|
183
|
+
in.vwc.pre[j] = l.konst(vw.pre_[j]);
|
|
184
|
+
}
|
|
185
|
+
for (size_t j = 0; j < p256.kBits; j++) {
|
|
186
|
+
in.vwc.bi[j] = l.konst(vw.bi_[j]);
|
|
187
|
+
if (j < p256.kBits - 1) {
|
|
188
|
+
in.vwc.int_x[j] = l.konst(vw.int_x_[j]);
|
|
189
|
+
in.vwc.int_y[j] = l.konst(vw.int_y_[j]);
|
|
190
|
+
in.vwc.int_z[j] = l.konst(vw.int_z_[j]);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// This test verifies our ecdsa signature verification circuit against an
|
|
196
|
+
// external implementation over randomly generated keys and messages.
|
|
197
|
+
TEST(ECDSA, VerifyExternalP256) {
|
|
198
|
+
const Nat order =
|
|
199
|
+
Nat("0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
|
|
200
|
+
|
|
201
|
+
const Field& F = p256.f_;
|
|
202
|
+
const EvalBackend ebk(F, false);
|
|
203
|
+
const Logic l(&ebk, F);
|
|
204
|
+
|
|
205
|
+
Verc verc(l, p256, order);
|
|
206
|
+
|
|
207
|
+
ecdsa_params params;
|
|
208
|
+
|
|
209
|
+
for (size_t i = 0; i < 100; ++i) {
|
|
210
|
+
if (i % 10 == 0) {
|
|
211
|
+
log(INFO, "Iteration %zu", i);
|
|
212
|
+
}
|
|
213
|
+
signature_tuple st;
|
|
214
|
+
circuit_params in;
|
|
215
|
+
bool ok = gensig(st, params);
|
|
216
|
+
EXPECT_TRUE(ok);
|
|
217
|
+
|
|
218
|
+
prepare_witness(st, in, l, F);
|
|
219
|
+
|
|
220
|
+
verc.verify_signature3(l.konst(in.pkx), l.konst(in.pky), l.konst(in.e),
|
|
221
|
+
in.vwc);
|
|
222
|
+
|
|
223
|
+
bool failed = ebk.assertion_failed();
|
|
224
|
+
if (failed) {
|
|
225
|
+
log(ERROR,
|
|
226
|
+
"Failed verification on:\npkx:%s\npky:%s\n e:%s\n r:%s\n s:%s",
|
|
227
|
+
st.pkx, st.pky, st.e, st.r, st.s);
|
|
228
|
+
}
|
|
229
|
+
EXPECT_FALSE(failed);
|
|
230
|
+
|
|
231
|
+
// Modify one byte of the signature and ensure that it fails.
|
|
232
|
+
signature_tuple maul_st;
|
|
233
|
+
circuit_params maul_in;
|
|
234
|
+
for (size_t j = 0; j < 100; ++j) {
|
|
235
|
+
maulSignature(st, maul_st);
|
|
236
|
+
prepare_witness(maul_st, maul_in, l, F);
|
|
237
|
+
verc.verify_signature3(l.konst(maul_in.pkx), l.konst(maul_in.pky),
|
|
238
|
+
l.konst(maul_in.e), maul_in.vwc);
|
|
239
|
+
failed = ebk.assertion_failed();
|
|
240
|
+
EXPECT_TRUE(failed);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
} // namespace
|
|
246
|
+
} // namespace proofs
|