From 3336a4d780a88f42e8f9e1e30d969c83e7cf548a Mon Sep 17 00:00:00 2001 From: Michael Straka Date: Mon, 4 Nov 2024 15:05:01 -0600 Subject: [PATCH] remove keyless circuit --- Cargo.lock | 54 - Cargo.toml | 2 - keyless/circuit/.circuit-root | 0 keyless/circuit/.gitignore | 4 - keyless/circuit/Cargo.toml | 36 - keyless/circuit/LICENSE | 201 --- keyless/circuit/README.md | 51 - keyless/circuit/package.json | 7 - keyless/circuit/src/arrays.rs | 1259 ----------------- keyless/circuit/src/base64.rs | 159 --- keyless/circuit/src/bigint.rs | 138 -- keyless/circuit/src/hash_to_field.rs | 245 ---- keyless/circuit/src/jwt_field_parsing.rs | 436 ------ keyless/circuit/src/lib.rs | 105 -- keyless/circuit/src/misc.rs | 350 ----- keyless/circuit/src/packing.rs | 150 -- keyless/circuit/src/rsa.rs | 135 -- keyless/circuit/src/sha.rs | 95 -- keyless/circuit/templates/.gitignore | 2 - .../circuit/templates/helpers/arrays.circom | 323 ----- .../circuit/templates/helpers/base64.circom | 145 -- .../templates/helpers/hashtofield.circom | 208 --- .../helpers/jwt_field_parsing.circom | 186 --- keyless/circuit/templates/helpers/misc.circom | 179 --- .../circuit/templates/helpers/packing.circom | 93 -- .../templates/helpers/rsa/bigint.circom | 563 -------- .../templates/helpers/rsa/bigint_func.circom | 444 ------ .../circuit/templates/helpers/rsa/fp.circom | 86 -- .../templates/helpers/rsa/rsa_verify.circom | 111 -- keyless/circuit/templates/helpers/sha.circom | 112 -- keyless/circuit/templates/main.circom | 28 - keyless/circuit/templates/mainTemplate.circom | 334 ----- .../tests/array_selector_test.circom | 21 - .../array_selector_complex_large_test.circom | 16 - .../array_selector_complex_small_test.circom | 16 - .../arrays/array_selector_complex_test.circom | 16 - .../tests/arrays/array_selector_test.circom | 16 - .../arrays/array_selector_test_large.circom | 16 - .../arrays/array_selector_test_small.circom | 16 - .../ascii_digits_to_field_large_test.circom | 16 - .../ascii_digits_to_field_small_test.circom | 16 - .../arrays/ascii_digits_to_field_test.circom | 16 - .../check_are_ascii_digits_large_test.circom | 14 - ...check_are_ascii_digits_max_len_test.circom | 14 - .../arrays/check_are_ascii_digits_test.circom | 14 - ...r_inclusion_poly_boolean_large_test.circom | 19 - ...lusion_poly_boolean_no_padding_test.circom | 19 - ...r_inclusion_poly_boolean_small_test.circom | 19 - ..._substr_inclusion_poly_boolean_test.circom | 19 - ...ck_substr_inclusion_poly_large_test.circom | 17 - ...bstr_inclusion_poly_no_padding_test.circom | 17 - .../check_substr_inclusion_poly_test.circom | 17 - .../concatenation_check_large_test.circom | 18 - .../concatenation_check_small_test.circom | 17 - .../arrays/concatenation_check_test.circom | 17 - .../left_array_selector_large_test.circom | 15 - .../left_array_selector_small_test.circom | 15 - .../arrays/left_array_selector_test.circom | 15 - .../right_array_selector_large_test.circom | 15 - .../right_array_selector_small_test.circom | 15 - .../arrays/right_array_selector_test.circom | 15 - .../select_array_value_large_test.circom | 16 - .../select_array_value_small_test.circom | 16 - .../arrays/select_array_value_test.circom | 16 - .../single_neg_one_array_large_test.circom | 15 - .../single_neg_one_array_small_test.circom | 15 - .../arrays/single_neg_one_array_test.circom | 15 - .../arrays/single_one_array_large_test.circom | 15 - .../arrays/single_one_array_small_test.circom | 15 - .../tests/arrays/single_one_array_test.circom | 15 - .../templates/tests/base64_decode_test.circom | 17 - .../tests/base64_decode_test_short.circom | 17 - .../templates/tests/base64_lookup_test.circom | 15 - .../tests/bigint/big_less_than_test.circom | 16 - ..._substr_inclusion_poly_boolean_test.circom | 28 - .../check_substr_inclusion_poly_test.circom | 25 - .../parse_email_verified_field_test.circom | 7 - .../parse_quoted_test.circom | 6 - .../parse_unquoted_test.circom | 6 - .../misc/assert_equal_if_true_test.circom | 7 - .../tests/misc/calculate_total_test.circom | 17 - .../misc/email_verified_check_test.circom | 29 - .../tests/misc/is_whitespace_test.circom | 16 - .../tests/misc/string_bodies_test.circom | 18 - .../packing/bits2num_big_endian_test.circom | 21 - .../packing/bits_to_field_elems_test.circom | 18 - .../tests/packing/bytes_to_bits_test.circom | 16 - .../tests/packing/num2bits_be_test.circom | 16 - .../templates/tests/rsa_verify_test.circom | 5 - .../tests/sha2_padding_verify_test.circom | 5 - .../circuit/templates/tests/sha_test.circom | 15 - keyless/circuit/templates/update_ctags.sh | 3 - .../tools/create-proofs-for-testing.sh | 126 -- keyless/circuit/tools/input_gen.py | 618 -------- keyless/circuit/tools/install-deps.sh | 65 - keyless/circuit/tools/test_rsa_privkey.pem | 28 - keyless/circuit/tools/trusted-setup.sh | 84 -- keyless/common/Cargo.toml | 26 - keyless/common/src/api.rs | 46 - keyless/common/src/input_processing/bits.rs | 100 -- .../input_processing/circuit_input_signals.rs | 237 ---- keyless/common/src/input_processing/config.rs | 24 - .../common/src/input_processing/encoding.rs | 213 --- keyless/common/src/input_processing/mod.rs | 9 - keyless/common/src/input_processing/sha.rs | 75 - .../src/input_processing/witness_gen.rs | 69 - keyless/common/src/lib.rs | 5 - 107 files changed, 8903 deletions(-) delete mode 100644 keyless/circuit/.circuit-root delete mode 100644 keyless/circuit/.gitignore delete mode 100644 keyless/circuit/Cargo.toml delete mode 100644 keyless/circuit/LICENSE delete mode 100644 keyless/circuit/README.md delete mode 100644 keyless/circuit/package.json delete mode 100644 keyless/circuit/src/arrays.rs delete mode 100644 keyless/circuit/src/base64.rs delete mode 100644 keyless/circuit/src/bigint.rs delete mode 100644 keyless/circuit/src/hash_to_field.rs delete mode 100644 keyless/circuit/src/jwt_field_parsing.rs delete mode 100644 keyless/circuit/src/lib.rs delete mode 100644 keyless/circuit/src/misc.rs delete mode 100644 keyless/circuit/src/packing.rs delete mode 100644 keyless/circuit/src/rsa.rs delete mode 100644 keyless/circuit/src/sha.rs delete mode 100644 keyless/circuit/templates/.gitignore delete mode 100644 keyless/circuit/templates/helpers/arrays.circom delete mode 100644 keyless/circuit/templates/helpers/base64.circom delete mode 100644 keyless/circuit/templates/helpers/hashtofield.circom delete mode 100644 keyless/circuit/templates/helpers/jwt_field_parsing.circom delete mode 100644 keyless/circuit/templates/helpers/misc.circom delete mode 100644 keyless/circuit/templates/helpers/packing.circom delete mode 100644 keyless/circuit/templates/helpers/rsa/bigint.circom delete mode 100644 keyless/circuit/templates/helpers/rsa/bigint_func.circom delete mode 100644 keyless/circuit/templates/helpers/rsa/fp.circom delete mode 100644 keyless/circuit/templates/helpers/rsa/rsa_verify.circom delete mode 100644 keyless/circuit/templates/helpers/sha.circom delete mode 100644 keyless/circuit/templates/main.circom delete mode 100644 keyless/circuit/templates/mainTemplate.circom delete mode 100644 keyless/circuit/templates/tests/array_selector_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/array_selector_complex_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/array_selector_complex_small_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/array_selector_complex_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/array_selector_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/array_selector_test_large.circom delete mode 100644 keyless/circuit/templates/tests/arrays/array_selector_test_small.circom delete mode 100644 keyless/circuit/templates/tests/arrays/ascii_digits_to_field_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/ascii_digits_to_field_small_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/ascii_digits_to_field_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_are_ascii_digits_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_are_ascii_digits_max_len_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_are_ascii_digits_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_no_padding_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_small_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_no_padding_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/concatenation_check_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/concatenation_check_small_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/concatenation_check_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/left_array_selector_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/left_array_selector_small_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/left_array_selector_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/right_array_selector_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/right_array_selector_small_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/right_array_selector_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/select_array_value_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/select_array_value_small_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/select_array_value_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/single_neg_one_array_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/single_neg_one_array_small_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/single_neg_one_array_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/single_one_array_large_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/single_one_array_small_test.circom delete mode 100644 keyless/circuit/templates/tests/arrays/single_one_array_test.circom delete mode 100644 keyless/circuit/templates/tests/base64_decode_test.circom delete mode 100644 keyless/circuit/templates/tests/base64_decode_test_short.circom delete mode 100644 keyless/circuit/templates/tests/base64_lookup_test.circom delete mode 100644 keyless/circuit/templates/tests/bigint/big_less_than_test.circom delete mode 100644 keyless/circuit/templates/tests/check_substr_inclusion_poly_boolean_test.circom delete mode 100644 keyless/circuit/templates/tests/check_substr_inclusion_poly_test.circom delete mode 100644 keyless/circuit/templates/tests/jwt_field_parsing/parse_email_verified_field_test.circom delete mode 100644 keyless/circuit/templates/tests/jwt_field_parsing/parse_quoted_test.circom delete mode 100644 keyless/circuit/templates/tests/jwt_field_parsing/parse_unquoted_test.circom delete mode 100644 keyless/circuit/templates/tests/misc/assert_equal_if_true_test.circom delete mode 100644 keyless/circuit/templates/tests/misc/calculate_total_test.circom delete mode 100644 keyless/circuit/templates/tests/misc/email_verified_check_test.circom delete mode 100644 keyless/circuit/templates/tests/misc/is_whitespace_test.circom delete mode 100644 keyless/circuit/templates/tests/misc/string_bodies_test.circom delete mode 100644 keyless/circuit/templates/tests/packing/bits2num_big_endian_test.circom delete mode 100644 keyless/circuit/templates/tests/packing/bits_to_field_elems_test.circom delete mode 100644 keyless/circuit/templates/tests/packing/bytes_to_bits_test.circom delete mode 100644 keyless/circuit/templates/tests/packing/num2bits_be_test.circom delete mode 100644 keyless/circuit/templates/tests/rsa_verify_test.circom delete mode 100644 keyless/circuit/templates/tests/sha2_padding_verify_test.circom delete mode 100644 keyless/circuit/templates/tests/sha_test.circom delete mode 100755 keyless/circuit/templates/update_ctags.sh delete mode 100755 keyless/circuit/tools/create-proofs-for-testing.sh delete mode 100755 keyless/circuit/tools/input_gen.py delete mode 100755 keyless/circuit/tools/install-deps.sh delete mode 100644 keyless/circuit/tools/test_rsa_privkey.pem delete mode 100755 keyless/circuit/tools/trusted-setup.sh delete mode 100644 keyless/common/Cargo.toml delete mode 100644 keyless/common/src/api.rs delete mode 100644 keyless/common/src/input_processing/bits.rs delete mode 100644 keyless/common/src/input_processing/circuit_input_signals.rs delete mode 100644 keyless/common/src/input_processing/config.rs delete mode 100644 keyless/common/src/input_processing/encoding.rs delete mode 100644 keyless/common/src/input_processing/mod.rs delete mode 100644 keyless/common/src/input_processing/sha.rs delete mode 100644 keyless/common/src/input_processing/witness_gen.rs delete mode 100644 keyless/common/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 350afd064842b..fa0e56a9e3823 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2567,48 +2567,6 @@ dependencies = [ "rand 0.7.3", ] -[[package]] -name = "aptos-keyless-circuit" -version = "0.1.0" -dependencies = [ - "anyhow", - "aptos-crypto", - "aptos-keyless-common", - "aptos-logger", - "ark-bn254", - "ark-ff", - "base64 0.13.1", - "hex", - "itertools 0.13.0", - "num-bigint 0.3.3", - "num-modular", - "num-traits", - "rand 0.7.3", - "rand_chacha 0.3.1", - "rsa 0.9.6", - "serde_json", - "sha2 0.9.9", - "tempfile", - "tokio", -] - -[[package]] -name = "aptos-keyless-common" -version = "0.1.0" -dependencies = [ - "anyhow", - "aptos-types", - "ark-bn254", - "ark-ff", - "base64 0.13.1", - "hex", - "num-bigint 0.3.3", - "serde", - "serde_json", - "tempfile", - "tracing", -] - [[package]] name = "aptos-keyless-pepper-common" version = "0.1.0" @@ -12286,17 +12244,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-modular" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" -dependencies = [ - "num-bigint 0.4.4", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.3.2" @@ -14638,7 +14585,6 @@ dependencies = [ "pkcs1 0.7.5", "pkcs8 0.10.2", "rand_core 0.6.4", - "sha2 0.10.8", "signature 2.2.0", "spki 0.7.3", "subtle", diff --git a/Cargo.toml b/Cargo.toml index 315ce1e09fb6a..1ae37eabb8c0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -142,8 +142,6 @@ members = [ "experimental/runtimes", "experimental/storage/hexy", "experimental/storage/layered-map", - "keyless/circuit", - "keyless/common", "keyless/pepper/common", "keyless/pepper/example-client-rust", "keyless/pepper/service", diff --git a/keyless/circuit/.circuit-root b/keyless/circuit/.circuit-root deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/keyless/circuit/.gitignore b/keyless/circuit/.gitignore deleted file mode 100644 index fe28d346d0ade..0000000000000 --- a/keyless/circuit/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -aptos-keyless-trusted-setup-contributions-may-2024 -templates/main.r1cs -templates/main.sym -templates/main_js diff --git a/keyless/circuit/Cargo.toml b/keyless/circuit/Cargo.toml deleted file mode 100644 index 662d69d6fee95..0000000000000 --- a/keyless/circuit/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "aptos-keyless-circuit" -description = "Aptos Keyless circuit" -version = "0.1.0" - -# Workspace inherited keys -authors = { workspace = true } -edition = { workspace = true } -homepage = { workspace = true } -license = { workspace = true } -publish = { workspace = true } -repository = { workspace = true } -rust-version = { workspace = true } - -[dependencies] -anyhow = { workspace = true } -aptos-crypto = { workspace = true } -aptos-keyless-common = { workspace = true } -aptos-logger = { workspace = true } -ark-bn254 = { workspace = true } -ark-ff = { workspace = true } -base64 = { workspace = true } -itertools = { workspace = true } -num-traits = { workspace = true } -rand = { workspace = true } -serde_json = { workspace = true } -sha2 = { workspace = true } -tempfile = { workspace = true } - -[dev-dependencies] -hex = { workspace = true } -num-bigint = { workspace = true } -num-modular = { version = "0.6.1", features = ["num-bigint", "num-integer", "num-traits", "std"] } -rand_chacha = "0.3.1" -rsa = { version = "0.9.6", features = ["sha2"] } -tokio = { workspace = true } diff --git a/keyless/circuit/LICENSE b/keyless/circuit/LICENSE deleted file mode 100644 index 2abe7dd0a5b4f..0000000000000 --- a/keyless/circuit/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2024 Aptos Foundation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/keyless/circuit/README.md b/keyless/circuit/README.md deleted file mode 100644 index c62c9dcd31c7b..0000000000000 --- a/keyless/circuit/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# Aptos Keyless circuit - -## Installing dependencies - -The scripts in this repository will not work without installing the dependencies. - -To install, please run: - -``` -. ./tools/install-deps.sh -``` - -## Run sub-circuit unittests - -```bash -cargo test -p aptos-keyless-circuit -``` - -## Generating the proving key - -To generate a sample prover and verifier key pair, run the following commands: - -``` -./tools/trusted-setup.sh sample_keypair -``` - -## Testing - -Unit testing located in `src` may be run using `cargo test`. - -## Generating a sample proof - -TODO: update `create-proofs-for-testing.sh` to match the latest circuit, then provide instructions. - -## Circuit stats - -Command: -``` -circom -l `npm root -g` templates/main.circom --r1cs -``` - -Output: -``` -non-linear constraints: 1376867 -linear constraints: 0 -public inputs: 1 -private inputs: 7858 (7745 belong to witness) -public outputs: 0 -wires: 1343588 -labels: 6286968 -``` diff --git a/keyless/circuit/package.json b/keyless/circuit/package.json deleted file mode 100644 index 61aeb916ca844..0000000000000 --- a/keyless/circuit/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "tools", - "version": "1.0.0", - "type": "commonjs", - "dependencies": { - } -} diff --git a/keyless/circuit/src/arrays.rs b/keyless/circuit/src/arrays.rs deleted file mode 100644 index 69d7ab73d66b1..0000000000000 --- a/keyless/circuit/src/arrays.rs +++ /dev/null @@ -1,1259 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::TestCircuitHandle; -use aptos_crypto::poseidon_bn254; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::CircuitInputSignals, config::CircuitPaddingConfig, -}; -use ark_bn254::Fr; -use ark_ff::{One, Zero}; -use rand::{thread_rng, Rng}; - -fn build_array_selector_output(len: u32, start: u32, end: u32) -> Vec { - let len = len as usize; - let start = start as usize; - let end = end as usize; - [vec![0; start], vec![1; end - start], vec![0; len - end]].concat() -} - -#[test] -fn array_selector_test() { - let circuit_handle = TestCircuitHandle::new("arrays/array_selector_test.circom").unwrap(); - let out_len = 8; - for start in 0..out_len { - for end in start + 1..=out_len { - let output = build_array_selector_output(out_len, start, end); - let config = - CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("start_index", start as u64) - .u64_input("end_index", end as u64) - .bytes_input("expected_output", &output[..]) - .pad(&config) - .unwrap(); - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } - } -} - -#[test] -fn array_selector_test_large() { - let circuit_handle = TestCircuitHandle::new("arrays/array_selector_test_large.circom").unwrap(); - for _i in 0..10 { - let mut rng = thread_rng(); - - let out_len = 2000; - let start = rng.gen_range(0, 2000); - let end = rng.gen_range(start + 1, 2001); - - let output = build_array_selector_output(out_len, start, end); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("start_index", start as u64) - .u64_input("end_index", end as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -fn array_selector_test_small() { - let circuit_handle = TestCircuitHandle::new("arrays/array_selector_test_small.circom").unwrap(); - let out_len = 2; - let start = 0; - let end = 1; - let output = build_array_selector_output(out_len, start, end); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("start_index", start as u64) - .u64_input("end_index", end as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -#[should_panic] -fn array_selector_test_wrong_start() { - let circuit_handle = TestCircuitHandle::new("arrays/array_selector_test.circom").unwrap(); - let out_len = 8; - let start = 3; - let end = 3; - let output = build_array_selector_output(out_len, start, end); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("start_index", start as u64) - .u64_input("end_index", end as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn array_selector_test_complex() { - let circuit_handle = - TestCircuitHandle::new("arrays/array_selector_complex_test.circom").unwrap(); - let out_len = 8; - // Fails when start = 0 by design - for start in 1..out_len { - for end in start + 1..=out_len { - let output = build_array_selector_output(out_len, start, end); - let config = - CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("start_index", start as u64) - .u64_input("end_index", end as u64) - .bytes_input("expected_output", &output[..]) - .pad(&config) - .unwrap(); - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } - } -} - -#[test] -fn array_selector_test_complex_large() { - let circuit_handle = - TestCircuitHandle::new("arrays/array_selector_complex_large_test.circom").unwrap(); - let out_len = 2000; - let start = 157; - let end = 1143; - let output = build_array_selector_output(out_len, start, end); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("start_index", start as u64) - .u64_input("end_index", end as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn array_selector_test_complex_small() { - let circuit_handle = - TestCircuitHandle::new("arrays/array_selector_complex_small_test.circom").unwrap(); - let out_len = 3; - let start = 1; - let end = 2; - let output = build_array_selector_output(out_len, start, end); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("start_index", start as u64) - .u64_input("end_index", end as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -#[should_panic] -fn array_selector_test_complex_wrong_start() { - let circuit_handle = TestCircuitHandle::new("arrays/array_selector_test.circom").unwrap(); - let out_len = 8; - let start = 3; - let end = 3; - let output = build_array_selector_output(out_len, start, end); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("start_index", start as u64) - .u64_input("end_index", end as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -fn build_left_array_selector_output(len: u32, index: u32) -> Vec { - let len = len as usize; - let index = index as usize; - [vec![1; index], vec![0; len - index]].concat() -} - -#[test] -fn left_array_selector_test() { - let circuit_handle = TestCircuitHandle::new("arrays/left_array_selector_test.circom").unwrap(); - let out_len = 8; - for index in 0..=out_len { - let output = build_left_array_selector_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output[..]) - .pad(&config) - .unwrap(); - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -fn left_array_selector_test_large() { - let circuit_handle = - TestCircuitHandle::new("arrays/left_array_selector_large_test.circom").unwrap(); - let out_len = 2000; - let mut rng = thread_rng(); - let index = rng.gen_range(0, 2000); - let output = build_left_array_selector_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn left_array_selector_test_small() { - let circuit_handle = - TestCircuitHandle::new("arrays/left_array_selector_small_test.circom").unwrap(); - let out_len = 1; - let index = 0; - let output = build_left_array_selector_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -fn build_right_array_selector_output(len: usize, index: usize) -> Vec { - if index < len { - [vec![0; index + 1], vec![1; len - index - 1]].concat() - } else { - vec![0; len] - } -} - -#[test] -fn right_array_selector_test() { - let circuit_handle = TestCircuitHandle::new("arrays/right_array_selector_test.circom").unwrap(); - let out_len = 8; - for index in 0..=out_len { - let output = build_right_array_selector_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output[..]) - .pad(&config) - .unwrap(); - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -fn right_array_selector_test_large() { - let circuit_handle = - TestCircuitHandle::new("arrays/right_array_selector_large_test.circom").unwrap(); - let out_len = 2000; - let mut rng = rand::thread_rng(); - let index = rng.gen_range(0, 2001); - let output = build_right_array_selector_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn right_array_selector_test_small() { - let circuit_handle = - TestCircuitHandle::new("arrays/right_array_selector_small_test.circom").unwrap(); - let out_len = 1; - let index = 0; - let output = build_left_array_selector_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -fn build_single_one_array_output(len: usize, index: usize) -> Vec { - let mut output = vec![0; len]; - - if index < len { - output[index] = 1; - } - output -} - -#[test] -fn single_one_array_test() { - let circuit_handle = TestCircuitHandle::new("arrays/single_one_array_test.circom").unwrap(); - let out_len = 8; - for index in 0..=out_len { - let output = build_single_one_array_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -fn single_one_array_large_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/single_one_array_large_test.circom").unwrap(); - let out_len = 2000; - let mut rng = rand::thread_rng(); - let index = rng.gen_range(0, 2001); - let output = build_single_one_array_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn single_one_array_small_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/single_one_array_small_test.circom").unwrap(); - let out_len = 1; - let index = 0; - let output = build_single_one_array_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn select_array_value_test() { - let circuit_handle = TestCircuitHandle::new("arrays/select_array_value_test.circom").unwrap(); - let mut rng = rand::thread_rng(); - let array: Vec = (0..8).map(|_| rng.gen_range(0, 250)).collect(); - - let in_len = array.len(); - for index in 0..in_len { - let output = array[index]; - let config = CircuitPaddingConfig::new().max_length("array", in_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("array", &array[..]) - .u64_input("expected_output", output as u64) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -fn select_array_value_large_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/select_array_value_large_test.circom").unwrap(); - let mut rng = rand::thread_rng(); - let input: Vec = (0..2000).map(|_| rng.gen_range(0, 250)).collect(); - - let index = 1567; - let in_len = input.len(); - let output = input[index]; - let config = CircuitPaddingConfig::new().max_length("array", in_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("array", &input) - .u64_input("expected_output", output as u64) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn select_array_value_small_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/select_array_value_small_test.circom").unwrap(); - let mut rng = rand::thread_rng(); - let array: Vec = (0..1).map(|_| rng.gen_range(0, 250)).collect(); - let index = 0; - let in_len = array.len(); - let output = array[index]; - let config = CircuitPaddingConfig::new().max_length("array", in_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("array", &array) - .u64_input("expected_output", output as u64) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -#[should_panic] -fn select_array_value_test_wrong_index() { - let circuit_handle = TestCircuitHandle::new("arrays/select_array_value_test.circom").unwrap(); - let out_len = 8; - let index = 8; - let mut rng = rand::thread_rng(); - let output: Vec = (0..8).map(|_| rng.gen_range(0, 250)).collect(); - - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len as usize); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .bytes_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -fn build_single_neg_one_array_output(len: usize, index: usize) -> Vec { - let mut output = vec![Fr::zero(); len]; - if index < len { - output[index] = Fr::zero() - Fr::one(); - } - output -} - -#[test] -fn single_neg_one_array_test() { - let circuit_handle = TestCircuitHandle::new("arrays/single_neg_one_array_test.circom").unwrap(); - let out_len = 8; - for index in 0..=out_len { - let output = build_single_neg_one_array_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .frs_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -fn single_neg_one_array_large_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/single_neg_one_array_large_test.circom").unwrap(); - let out_len = 2000; - let mut rng = rand::thread_rng(); - let index = rng.gen_range(0, 2001); - let output = build_single_neg_one_array_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .frs_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn single_neg_one_array_small_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/single_neg_one_array_small_test.circom").unwrap(); - let out_len = 1; - let index = 0; - let output = build_single_neg_one_array_output(out_len, index); - let config = CircuitPaddingConfig::new().max_length("expected_output", out_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("index", index as u64) - .frs_input("expected_output", &output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_substr_inclusion_poly_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_test.circom").unwrap(); - - let max_str_len = 100; - let max_substr_len = 20; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string = "Hello World!"; - let string_len = string.len(); - let string_hash = poseidon_bn254::pad_and_hash_string(string, max_str_len).unwrap(); - for substring_len in 1..string_len { - for start_index in 0..string_len - substring_len { - let substring = &string[start_index..start_index + substring_len]; //"lo Wor"; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index as u64) - .fr_input("str_hash", string_hash) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } - } -} - -#[test] -fn check_substr_inclusion_poly_no_padding_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_no_padding_test.circom") - .unwrap(); - - let string = "Hello World!"; - let max_str_len = string.len(); - let max_substr_len = 11; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string_len = string.len(); - let string_hash = poseidon_bn254::pad_and_hash_string(string, max_str_len).unwrap(); - let substring_len = 3; - for start_index in 0..string_len - substring_len { - let substring = &string[start_index..start_index + substring_len]; //"lo Wor"; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index as u64) - .fr_input("str_hash", string_hash) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -fn check_substr_inclusion_poly_same_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_test.circom").unwrap(); - - let string = "Hello World!"; - let max_str_len = 100; - let max_substr_len = 20; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string_hash = poseidon_bn254::pad_and_hash_string(string, max_str_len).unwrap(); - let substring = string; - let substring_len = substring.len(); - let start_index = 0; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index as u64) - .fr_input("str_hash", string_hash) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_substr_inclusion_poly_large_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_large_test.circom").unwrap(); - - let max_str_len = 2000; - let max_substr_len = 1000; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string = "Once upon a midnight dreary, while I pondered, weak and weary, -Over many a quaint and curious volume of forgotten lore— - While I nodded, nearly napping, suddenly there came a tapping, -As of some one gently rapping, rapping at my chamber door. -“’Tis some visitor,” I muttered, “tapping at my chamber door—"; - let string_hash = poseidon_bn254::pad_and_hash_string("dummy string", 30).unwrap(); // Hash is not checked in the substring inclusion protocol and so can be arbitrary here - let substring = &string[45..70]; - let substring_len = substring.len(); - let start_index = 45; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index) - .fr_input("str_hash", string_hash) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_substr_inclusion_poly_small_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_test.circom").unwrap(); - - let max_str_len = 100; - let max_substr_len = 20; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string = "a"; - let string_hash = poseidon_bn254::pad_and_hash_string("dummy string", 30).unwrap(); // Hash is not checked in the substring inclusion protocol and so can be arbitrary here - let substring = "a"; - let substring_len = substring.len(); - let start_index = 0; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index) - .fr_input("str_hash", string_hash) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_substr_inclusion_poly_edge_case_test() { - let circuit_handle = TestCircuitHandle::new("check_substr_inclusion_poly_test.circom").unwrap(); - - let test_str: &'static [u8] = &[ - 4u8, 233, 24, 159, 105, 83, 145, 69, 245, 99, 150, 28, 197, 219, 186, 204, 47, 219, 5, 139, - 89, 15, 216, 169, 206, 145, 224, 32, 59, 0, 178, 44, 116, 149, 61, 64, 149, 134, 204, 103, - 18, 57, 87, 168, 144, 26, 173, 48, 219, 125, 64, 211, 131, 159, 76, 29, 154, 118, 163, 18, - 38, 24, 44, 191, 196, 36, 240, 250, 82, 176, 94, 86, 202, 67, 142, 19, 115, 237, 104, 190, - 28, 122, 44, 252, 139, 106, 125, 145, 135, 1, 181, 127, 0, 242, 187, 80, 208, 51, 22, 1, - 194, 159, 218, 16, 33, 113, 220, 214, 209, 168, 195, 83, 177, 149, 74, 20, 7, 28, 124, 175, - 212, 240, 55, 96, 155, 163, 158, 94, 64, 141, 154, 111, 89, 219, 90, 16, 142, 139, 215, - 124, 141, 19, 94, 73, 24, 213, 204, 15, 221, 86, 52, 132, 246, 58, 133, 94, 193, 36, 12, - 232, 37, 209, 171, 118, 85, 13, 154, 180, 124, 188, 81, 235, 254, 114, 114, 101, 75, 161, - 208, 227, 71, 22, 48, 204, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 192, - ]; - let str_hash = poseidon_bn254::pad_and_hash_bytes_with_len(test_str, 256).unwrap(); - let substr: &'static [u8] = &[0u8, 0, 0, 0, 0, 0, 5, 192]; - let start_index = 248; - - let config = CircuitPaddingConfig::new() - .max_length("str", 256) - .max_length("substr", 8); - - let circuit_input_signals = CircuitInputSignals::new() - .bytes_input("str", test_str) - .fr_input("str_hash", str_hash) - .bytes_input("substr", substr) - .usize_input("substr_len", substr.len()) - .usize_input("start_index", start_index) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - - assert!(result.is_ok()); -} - -#[test] -fn check_substr_inclusion_poly_boolean_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_boolean_test.circom").unwrap(); - - let max_str_len = 100; - let max_substr_len = 20; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string = "Hello World!"; - let string_len = string.len(); - let string_hash = poseidon_bn254::pad_and_hash_string(string, max_str_len).unwrap(); - for substring_len in 1..string_len { - for start_index in 0..string_len - substring_len { - let substring = &string[start_index..start_index + substring_len]; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index as u64) - .fr_input("str_hash", string_hash) - .u64_input("expected_output", 1) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } - } -} - -#[test] -fn check_substr_inclusion_poly_no_padding_boolean_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_boolean_no_padding_test.circom") - .unwrap(); - - let string = "Hello World!"; - let max_str_len = string.len(); - let max_substr_len = 11; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string_len = string.len(); - let string_hash = poseidon_bn254::pad_and_hash_string(string, max_str_len).unwrap(); - let substring_len = 3; - for start_index in 0..string_len - substring_len { - let substring = &string[start_index..start_index + substring_len]; //"lo Wor"; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index as u64) - .fr_input("str_hash", string_hash) - .u64_input("expected_output", 1) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -fn check_substr_inclusion_poly_same_boolean_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_boolean_test.circom").unwrap(); - - let string = "Hello World!"; - let max_str_len = 100; - let max_substr_len = 20; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string_hash = poseidon_bn254::pad_and_hash_string(string, max_str_len).unwrap(); - let substring = string; - let substring_len = substring.len(); - let start_index = 0; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index as u64) - .fr_input("str_hash", string_hash) - .u64_input("expected_output", 1) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_substr_inclusion_poly_large_boolean_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_boolean_large_test.circom") - .unwrap(); - - let max_str_len = 2000; - let max_substr_len = 1000; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string = "Once upon a midnight dreary, while I pondered, weak and weary, -Over many a quaint and curious volume of forgotten lore— - While I nodded, nearly napping, suddenly there came a tapping, -As of some one gently rapping, rapping at my chamber door. -“’Tis some visitor,” I muttered, “tapping at my chamber door—"; - let string_hash = poseidon_bn254::pad_and_hash_string("dummy string", 30).unwrap(); // Hash is not checked in the substring inclusion protocol and so can be arbitrary here - let substring = &string[45..70]; - let substring_len = substring.len(); - let start_index = 45; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index) - .fr_input("str_hash", string_hash) - .u64_input("expected_output", 1) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_substr_inclusion_poly_small_boolean_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_substr_inclusion_poly_boolean_test.circom").unwrap(); - - let max_str_len = 100; - let max_substr_len = 20; - let config = CircuitPaddingConfig::new() - .max_length("str", max_str_len) - .max_length("substr", max_substr_len); - let string = "a"; - let string_hash = poseidon_bn254::pad_and_hash_string("dummy string", 30).unwrap(); // Hash is not checked in the substring inclusion protocol and so can be arbitrary here - let substring = "a"; - let substring_len = substring.len(); - let start_index = 0; - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("str", string) - .str_input("substr", substring) - .u64_input("substr_len", substring_len as u64) - .u64_input("start_index", start_index) - .fr_input("str_hash", string_hash) - .u64_input("expected_output", 1) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn concatenation_check_test() { - let circuit_handle = TestCircuitHandle::new("arrays/concatenation_check_test.circom").unwrap(); - - let max_full_str_len = 100; - let max_left_str_len = 70; - let max_right_str_len = 70; - let config = CircuitPaddingConfig::new() - .max_length("full_string", max_full_str_len) - .max_length("left", max_left_str_len) - .max_length("right", max_right_str_len); - let full_string = "Hello World!"; - let str_len = full_string.len(); - // Subcircuit fails if the left string is empty - for sep_index in 1..str_len { - let left_string = &full_string[0..sep_index]; - let right_string = &full_string[sep_index..full_string.len()]; - let left_len = left_string.len(); - let right_len = right_string.len(); - let circuit_input_signals = CircuitInputSignals::new() - .str_input("full_string", full_string) - .str_input("left", left_string) - .str_input("right", right_string) - .u64_input("left_len", left_len as u64) - .u64_input("right_len", right_len as u64) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -#[should_panic] -fn concatenation_check_left_len_wrong_test() { - let circuit_handle = TestCircuitHandle::new("arrays/concatenation_check_test.circom").unwrap(); - - let max_full_str_len = 100; - let max_left_str_len = 70; - let max_right_str_len = 70; - let config = CircuitPaddingConfig::new() - .max_length("full_string", max_full_str_len) - .max_length("left", max_left_str_len) - .max_length("right", max_right_str_len); - let full_string = "Hello World!"; - let str_len = full_string.len(); - let sep_index = 3; - let left_string = &full_string[0..sep_index]; - let right_string = &full_string[sep_index..str_len]; - let left_len = 72; - let right_len = right_string.len(); - let circuit_input_signals = CircuitInputSignals::new() - .str_input("full_string", full_string) - .str_input("left", left_string) - .str_input("right", right_string) - .u64_input("left_len", left_len as u64) - .u64_input("right_len", right_len as u64) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -#[should_panic] -fn concatenation_check_left_string_wrong_test() { - let circuit_handle = TestCircuitHandle::new("arrays/concatenation_check_test.circom").unwrap(); - - let max_full_str_len = 100; - let max_left_str_len = 70; - let max_right_str_len = 70; - let config = CircuitPaddingConfig::new() - .max_length("full_string", max_full_str_len) - .max_length("left", max_left_str_len) - .max_length("right", max_right_str_len); - let full_string = "Hello World!"; - let str_len = full_string.len(); - let sep_index = 3; - let left_string = &full_string[0..sep_index - 1]; - let right_string = &full_string[sep_index..str_len]; - let left_len = left_string.len(); - let right_len = right_string.len(); - let circuit_input_signals = CircuitInputSignals::new() - .str_input("full_string", full_string) - .str_input("left", left_string) - .str_input("right", right_string) - .u64_input("left_len", left_len as u64) - .u64_input("right_len", right_len as u64) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -#[should_panic] -fn concatenation_check_right_string_wrong_test() { - let circuit_handle = TestCircuitHandle::new("arrays/concatenation_check_test.circom").unwrap(); - - let max_full_str_len = 100; - let max_left_str_len = 70; - let max_right_str_len = 70; - let config = CircuitPaddingConfig::new() - .max_length("full_string", max_full_str_len) - .max_length("left", max_left_str_len) - .max_length("right", max_right_str_len); - let full_string = "Hello World!"; - let str_len = full_string.len(); - // Subcircuit fails if the left string is empty - let sep_index = 3; - let left_string = &full_string[0..sep_index]; - let right_string = &full_string[sep_index..str_len - 1]; - let left_len = left_string.len(); - let right_len = right_string.len(); - let circuit_input_signals = CircuitInputSignals::new() - .str_input("full_string", full_string) - .str_input("left", left_string) - .str_input("right", right_string) - .u64_input("left_len", left_len as u64) - .u64_input("right_len", right_len as u64) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn concatenation_check_small_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/concatenation_check_small_test.circom").unwrap(); - - let max_full_str_len = 2; - let max_left_str_len = 1; - let max_right_str_len = 1; - let config = CircuitPaddingConfig::new() - .max_length("full_string", max_full_str_len) - .max_length("left", max_left_str_len) - .max_length("right", max_right_str_len); - let full_string = "ab"; - let str_len = full_string.len(); - let sep_index = 1; - let left_string = &full_string[0..sep_index]; - let right_string = &full_string[sep_index..str_len]; - let left_len = left_string.len(); - let right_len = right_string.len(); - let circuit_input_signals = CircuitInputSignals::new() - .str_input("full_string", full_string) - .str_input("left", left_string) - .str_input("right", right_string) - .u64_input("left_len", left_len as u64) - .u64_input("right_len", right_len as u64) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn concatenation_check_large_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/concatenation_check_large_test.circom").unwrap(); - - let max_full_str_len = 1600; - let max_left_str_len = 1000; - let max_right_str_len = 1000; - let config = CircuitPaddingConfig::new() - .max_length("full_string", max_full_str_len) - .max_length("left", max_left_str_len) - .max_length("right", max_right_str_len); - let full_string = "Once upon a midnight dreary, while I pondered, weak and weary, - Over many a quaint and curious volume of forgotten lore— - While I nodded, nearly napping, suddenly there came a tapping, - As of some one gently rapping, rapping at my chamber door. - “’Tis some visitor,” I muttered, “tapping at my chamber door—"; - let str_len = full_string.len(); - let sep_index = 31; - let left_string = &full_string[0..sep_index]; - let right_string = &full_string[sep_index..str_len]; - let left_len = left_string.len(); - let right_len = right_string.len(); - let circuit_input_signals = CircuitInputSignals::new() - .str_input("full_string", full_string) - .str_input("left", left_string) - .str_input("right", right_string) - .u64_input("left_len", left_len as u64) - .u64_input("right_len", right_len as u64) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_are_ascii_digits_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_are_ascii_digits_test.circom").unwrap(); - let max_input_len = 20; - - let mut rng = rand::thread_rng(); - let digits: Vec = (0..5).map(|_| rng.gen_range(0, 9)).collect(); - let mut input_arr = digits_to_ascii_digits(digits.to_vec()); - let mut not_digits: Vec = (0..8 - 5).map(|_| rng.gen_range(0, 250)).collect(); - input_arr.append(&mut not_digits); - - let len = 5; - let config = CircuitPaddingConfig::new().max_length("in", max_input_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("len", len) - .bytes_input("in", &input_arr) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_are_ascii_digits_max_len_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_are_ascii_digits_max_len_test.circom").unwrap(); - let max_input_len = 8; - let mut rng = rand::thread_rng(); - let digits: Vec = (0..8).map(|_| rng.gen_range(0, 9)).collect(); - let input_arr = digits_to_ascii_digits(digits.to_vec()); - let len = input_arr.len(); - let config = CircuitPaddingConfig::new().max_length("in", max_input_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("len", len as u64) - .bytes_input("in", &input_arr) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_are_ascii_digits_small_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_are_ascii_digits_test.circom").unwrap(); - let max_input_len = 20; - let mut rng = rand::thread_rng(); - let digits: Vec = (0..1).map(|_| rng.gen_range(0, 9)).collect(); - let input_arr = digits_to_ascii_digits(digits.to_vec()); - let len = 1; - let config = CircuitPaddingConfig::new().max_length("in", max_input_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("len", len) - .bytes_input("in", &input_arr) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn check_are_ascii_digits_large_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/check_are_ascii_digits_large_test.circom").unwrap(); - let max_input_len = 2000; - let mut rng = rand::thread_rng(); - let digits: Vec = (0..1523).map(|_| rng.gen_range(0, 9)).collect(); - let input_arr = digits_to_ascii_digits(digits.to_vec()); - - let len = input_arr.len(); - let config = CircuitPaddingConfig::new().max_length("in", max_input_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("len", len as u64) - .bytes_input("in", &input_arr) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -fn digits_to_ascii_digits(digits: Vec) -> Vec { - let mut result = digits.clone(); - for digit in &mut result { - *digit += 48; - } - result -} - -#[test] -fn ascii_digits_to_field_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/ascii_digits_to_field_test.circom").unwrap(); - let max_input_len = 20; - let digits = [2, 1, 2, 4, 7]; - - let ascii_digits = digits_to_ascii_digits(digits.to_vec()); - let len = 5; - let expected_output = 21247; - let config = CircuitPaddingConfig::new().max_length("digits", max_input_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("len", len) - .bytes_input("digits", &ascii_digits) - .u64_input("expected_output", expected_output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn ascii_digits_to_field_small_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/ascii_digits_to_field_small_test.circom").unwrap(); - let max_input_len = 2; - let digits = [7, 89]; - let ascii_digits = digits_to_ascii_digits(digits.to_vec()); - let len = 1; - let expected_output = 7; - let config = CircuitPaddingConfig::new().max_length("digits", max_input_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("len", len) - .bytes_input("digits", &ascii_digits) - .u64_input("expected_output", expected_output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn ascii_digits_to_field_large_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/ascii_digits_to_field_large_test.circom").unwrap(); - let max_input_len = 2000; - // let mut rng = rand::thread_rng(); - // let digits: Vec = (0..19).map(|_| rng.gen_range(0, 9)).collect(); - - let digits = [ - 2, 1, 2, 4, 7, 4, 8, 0, 1, 9, 2, 1, 8, 3, 6, 7, 4, 1, 5, 14, 41, 180, 1, 31, 47, 2, 3, 6, - 7, 31, 35, - ]; - let ascii_digits = digits_to_ascii_digits(digits.to_vec()); - - let len = 19; - let expected_output = 2124748019218367415; - let config = CircuitPaddingConfig::new().max_length("digits", max_input_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("len", len) - .bytes_input("digits", &ascii_digits) - .u64_input("expected_output", expected_output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -#[should_panic] -fn ascii_digits_to_field_not_ascii_digits_test() { - let circuit_handle = - TestCircuitHandle::new("arrays/ascii_digits_to_field_test.circom").unwrap(); - let max_input_len = 20; - let digits = [2, 1, 24, 4, 7]; - let ascii_digits = digits_to_ascii_digits(digits.to_vec()); - let len = 5; - let expected_output = 21247; - let config = CircuitPaddingConfig::new().max_length("digits", max_input_len); - let circuit_input_signals = CircuitInputSignals::new() - .u64_input("len", len) - .bytes_input("digits", &ascii_digits) - .u64_input("expected_output", expected_output) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} diff --git a/keyless/circuit/src/base64.rs b/keyless/circuit/src/base64.rs deleted file mode 100644 index 7464b551a4854..0000000000000 --- a/keyless/circuit/src/base64.rs +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::TestCircuitHandle; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::CircuitInputSignals, config::CircuitPaddingConfig, -}; -use itertools::*; - -fn expected_decoded(b64: &str) -> Vec { - base64::decode_config(b64, base64::URL_SAFE_NO_PAD).unwrap() -} - -fn expected_lookup(b64_char: u8) -> u8 { - match b64_char { - b'A'..=b'Z' => b64_char - b'A', - b'a'..=b'z' => b64_char - b'a' + 26, - b'0'..=b'9' => b64_char - b'0' + 52, - b'-' => 62, - b'_' => 63, - _ => panic!("Tried to lookup a non-base64 char."), - } -} - -#[test] -fn base64_decode_test() { - let circuit_handle = TestCircuitHandle::new("base64_decode_test.circom").unwrap(); - - let jwt_payload = "eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhenAiOiI1MTEyNzY0NTY4ODAtaTdpNDc4N2MxODYzZGFtdG82ODk5dHM5ODlqMmUzNXIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI1MTEyNzY0NTY4ODAtaTdpNDc4N2MxODYzZGFtdG82ODk5dHM5ODlqMmUzNXIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDI5MDQ2MzAxNzE1OTI1MjA1OTIiLCJlbWFpbCI6Imhlcm8xMjAwMDkxQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJub25jZSI6IjEyNzcyMTIzMTUwODA5NDk2ODYwMTkzNDU3OTc2OTM3MTgyOTY0Mjk3MjgzNjMzNzA1ODcyMzkxNTM0OTQ2ODY2NzE5NjgxOTA0MzExIiwibmJmIjoxNzExNTUyMzMwLCJuYW1lIjoi44Kz44Oz44OJ44Km44OP44Or44KtIiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hL0FDZzhvY0lNWmZJa05XR1JCVEQ5MjR4bF9pZWZwTWNjTGd1d2RNSWluTVB6YWo1TDRRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IuODq-OCrSIsImZhbWlseV9uYW1lIjoi44Kz44Oz44OJ44KmIiwiaWF0IjoxNzExNTUyNjMwLCJleHAiOjE5MTE1NTYyMzB9"; - - let ascii_jwt_payload = expected_decoded(jwt_payload); - - let max_jwt_payload_len = 192 * 8 - 64; - let max_ascii_jwt_payload_len = 3 * max_jwt_payload_len / 4; - let config = CircuitPaddingConfig::new() - .max_length("jwt_payload", max_jwt_payload_len) - .max_length("ascii_jwt_payload", max_ascii_jwt_payload_len); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("jwt_payload", jwt_payload) - .bytes_input("ascii_jwt_payload", &ascii_jwt_payload) - .pad(&config) - .unwrap(); - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("result={:?}", result); - assert!(result.is_ok()); -} - -#[test] -fn base64_lookup_test() { - let circuit_handle = TestCircuitHandle::new("base64_lookup_test.circom").unwrap(); - - let base64_chars = (b'A'..=b'Z') - .chain(b'a'..=b'z') - .chain(b'0'..=b'9') - .chain([b'-', b'_']); - - for in_b64_char in base64_chars { - let config = CircuitPaddingConfig::new(); - - let circuit_input_signals = CircuitInputSignals::new() - .byte_input("in_b64_char", in_b64_char) - .byte_input("out_num", expected_lookup(in_b64_char)) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} - -#[test] -fn base64_decode_test_short_all_dashes() { - let circuit_handle = TestCircuitHandle::new("base64_decode_test_short.circom").unwrap(); - - let jwt_payload = "----"; - - let ascii_jwt_payload = expected_decoded(jwt_payload); - - let max_jwt_payload_len = 4; - let max_ascii_jwt_payload_len = 3 * max_jwt_payload_len / 4; - let config = CircuitPaddingConfig::new() - .max_length("jwt_payload", max_jwt_payload_len) - .max_length("ascii_jwt_payload", max_ascii_jwt_payload_len); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("jwt_payload", jwt_payload) - .bytes_input("ascii_jwt_payload", &ascii_jwt_payload) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -#[test] -fn base64_decode_test_short_three_chars() { - let circuit_handle = TestCircuitHandle::new("base64_decode_test_short.circom").unwrap(); - - // Last character must have ascii encoding with two trailing zeros, since we are encoding - // 16 bits - let jwt_payload = "--E"; - - let ascii_jwt_payload = expected_decoded(jwt_payload); - - let max_jwt_payload_len = 4; - let max_ascii_jwt_payload_len = 3 * max_jwt_payload_len / 4; - let config = CircuitPaddingConfig::new() - .max_length("jwt_payload", max_jwt_payload_len) - .max_length("ascii_jwt_payload", max_ascii_jwt_payload_len); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("jwt_payload", jwt_payload) - .bytes_input("ascii_jwt_payload", &ascii_jwt_payload) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); -} - -// ignoring b/c takes forever -#[test] -#[ignore] -fn base64_decode_test_short_exhaustive() { - let circuit_handle = TestCircuitHandle::new("base64_decode_test_short.circom").unwrap(); - - let base64_chars = ('A'..='Z') - .chain('a'..='z') - .chain('0'..='9') - .chain(['-', '_']); - - let exhaustive_iter = (0..=3) - .map(|_| base64_chars.clone()) - .multi_cartesian_product() - .map(|s| s.into_iter().collect::()); - //.collect(); - - for jwt_payload in exhaustive_iter { - println!("{jwt_payload}"); - - let ascii_jwt_payload = expected_decoded(&jwt_payload); - - let max_jwt_payload_len = 4; - let max_ascii_jwt_payload_len = 3 * max_jwt_payload_len / 4; - let config = CircuitPaddingConfig::new() - .max_length("jwt_payload", max_jwt_payload_len) - .max_length("ascii_jwt_payload", max_ascii_jwt_payload_len); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("jwt_payload", &jwt_payload) - .bytes_input("ascii_jwt_payload", &ascii_jwt_payload) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - assert!(result.is_ok()); - } -} diff --git a/keyless/circuit/src/bigint.rs b/keyless/circuit/src/bigint.rs deleted file mode 100644 index 827cabbabce5f..0000000000000 --- a/keyless/circuit/src/bigint.rs +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::TestCircuitHandle; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::CircuitInputSignals, config::CircuitPaddingConfig, -}; -use aptos_logger::info; -use rand::{thread_rng, Rng}; - -/// Given a non-negative integer `x`, generate a non-negative integer `y` that satisfies `y < x`. -/// `x` and `y` are both encoded to byte array with the most significant byte first. -fn rand_big(rng: &mut R, x_bytes_be: &[u8]) -> Vec { - let n = x_bytes_be.len(); - let non_zero_idxs: Vec = x_bytes_be - .iter() - .copied() - .enumerate() - .filter_map(|(idx, byte)| if byte == 0 { None } else { Some(idx) }) - .collect(); - let diff_idx = non_zero_idxs[rng.gen_range(0, non_zero_idxs.len())]; // will be the first byte in y that's smaller than the same position in x. - - let y_diff_byte = rng.gen_range(0, x_bytes_be[diff_idx]); - - let mut random_bytes = vec![0; n - (diff_idx + 1)]; - rng.fill_bytes(random_bytes.as_mut_slice()); - - [ - x_bytes_be[0..diff_idx].to_vec(), - vec![y_diff_byte], - random_bytes, - ] - .concat() -} - -fn bytes_le_into_limbs_le(mut bytes: Vec) -> Vec { - let num_bytes = bytes.len(); - let num_limbs = num_bytes.div_ceil(8); - let num_pad_zeros = num_limbs * 8 - num_bytes; - bytes.extend(vec![0; num_pad_zeros]); - let mut ret = vec![0; num_limbs]; - for i in 0..num_limbs { - let arr = <[u8; 8]>::try_from(bytes[i * 8..(i + 1) * 8].to_vec()).unwrap(); - ret[i] = u64::from_le_bytes(arr); - } - ret -} - -/// Sample a random integer in range [0, 2^2048) and return its big-endian byte representation. -/// Some special ranges get higher weight. -fn sample_big_be(rng: &mut R) -> Vec { - let byte_len: usize = { - let sample = rng.gen_range(0.0, 1.0); - if sample < 0.2 { - rng.gen_range(1, 9) - } else if sample < 0.4 { - rng.gen_range(248, 257) - } else { - rng.gen_range(1, 33) * 8 - } - }; - let mut ret: Vec = vec![0; byte_len]; - rng.fill_bytes(ret.as_mut_slice()); - if let Some(byte) = ret.first_mut() { - *byte = rng.gen_range(0, 255) + 1; - } - ret -} - -fn common (Vec, Vec)>(mut a_b_provider: F, expected_output: bool) { - let circuit = TestCircuitHandle::new("bigint/big_less_than_test.circom").unwrap(); - let num_iterations = std::env::var("NUM_ITERATIONS") - .unwrap_or("100".to_string()) - .parse::() - .unwrap_or(100); - for i in 0..num_iterations { - info!("Iteration {i} starts. Generate big numbers."); - let (a_bytes_be, b_bytes_be) = a_b_provider(); - println!("a_hex={}", hex::encode(&a_bytes_be)); - println!("b_hex={}", hex::encode(&b_bytes_be)); - let a_bytes_le: Vec = a_bytes_be.into_iter().rev().collect(); - let a_limbs_le = bytes_le_into_limbs_le(a_bytes_le); - let b_bytes_le: Vec = b_bytes_be.into_iter().rev().collect(); - let b_limbs_le = bytes_le_into_limbs_le(b_bytes_le); - - let config = CircuitPaddingConfig::new() - .max_length("a", 32) - .max_length("b", 32); - let circuit_input_signals = CircuitInputSignals::new() - .limbs_input("a", a_limbs_le.as_slice()) - .limbs_input("b", b_limbs_le.as_slice()) - .bool_input("expected_output", expected_output) - .pad(&config) - .unwrap(); - let result = circuit.gen_witness(circuit_input_signals); - println!("result={:?}", result); - assert!(result.is_ok()); - } -} - -#[test] -fn big_less_than_should_return_1_if_a_lt_b() { - let mut rng = thread_rng(); - common( - || { - let b_bytes_be = sample_big_be(&mut rng); - let a_bytes_be = rand_big(&mut rng, b_bytes_be.as_slice()); - (a_bytes_be, b_bytes_be) - }, - true, - ); -} - -#[test] -fn big_less_than_should_return_0_if_a_gt_b() { - let mut rng = thread_rng(); - common( - || { - let a_bytes_be = sample_big_be(&mut rng); - let b_bytes_be = rand_big(&mut rng, a_bytes_be.as_slice()); - (a_bytes_be, b_bytes_be) - }, - false, - ); -} - -#[test] -fn big_less_than_should_return_0_if_a_eq_b() { - let mut rng = thread_rng(); - common( - || { - let b_bytes_be = sample_big_be(&mut rng); - let a_bytes_be = b_bytes_be.clone(); - (a_bytes_be, b_bytes_be) - }, - false, - ); -} diff --git a/keyless/circuit/src/hash_to_field.rs b/keyless/circuit/src/hash_to_field.rs deleted file mode 100644 index 98e43cbfbb18f..0000000000000 --- a/keyless/circuit/src/hash_to_field.rs +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::TestCircuitHandle; -use aptos_crypto::{ - poseidon_bn254::{ - keyless::{pad_and_hash_limbs_with_len, BYTES_PACKED_PER_SCALAR, LIMBS_PACKED_PER_SCALAR}, - pad_and_hash_bytes_no_len, pad_and_hash_bytes_with_len, MAX_NUM_INPUT_SCALARS, - }, - test_utils::random_bytes, -}; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::CircuitInputSignals, config::CircuitPaddingConfig, -}; -use ark_bn254::Fr; -use ark_ff::Field; -use rand::{thread_rng, Rng}; - -#[test] -fn hash_bytes_to_field_with_len() { - let circuit_src_template = r#" -pragma circom 2.1.3; - -include "helpers/hashtofield.circom"; - -template hash_bytes_to_field_with_len_test(max_len) { - signal input in[max_len]; - signal input len; - signal input expected_output; - component c1 = HashBytesToFieldWithLen(max_len); - c1.in <== in; - c1.len <== len; - expected_output === c1.hash; -} - -component main = hash_bytes_to_field_with_len_test(__MAX_LEN__); -"#; - - // Have to save 1 scalar slot for the length. - let max_supported_byte_len = (MAX_NUM_INPUT_SCALARS - 1) * BYTES_PACKED_PER_SCALAR; - - let mut rng = thread_rng(); - let num_iterations = std::env::var("NUM_ITERATIONS") - .unwrap_or("10".to_string()) - .parse::() - .unwrap_or(10); - - //TODO: hardcode some interesting circuit dimensions that's widely used in keyless. - - for i in 0..num_iterations { - println!(); - println!("Iteration {} starts.", i); - let num_bytes_circuit_capacity: usize = rng.gen_range(1, max_supported_byte_len); - println!("num_bytes_circuit_capacity={}", num_bytes_circuit_capacity); - let circuit_src = circuit_src_template.replace( - "__MAX_LEN__", - num_bytes_circuit_capacity.to_string().as_str(), - ); - let circuit = TestCircuitHandle::new_from_str(circuit_src.as_str()).unwrap(); - let input_len = rng.gen_range(0, num_bytes_circuit_capacity + 1); - println!("input_len={}", input_len); - let msg = random_bytes(&mut rng, input_len); - let expected_output = - pad_and_hash_bytes_with_len(msg.as_slice(), num_bytes_circuit_capacity).unwrap(); - println!("expected_output={}", expected_output); - let config = CircuitPaddingConfig::new().max_length("in", num_bytes_circuit_capacity); - let circuit_input_signals = CircuitInputSignals::new() - .bytes_input("in", msg.as_slice()) - .usize_input("len", msg.len()) - .fr_input("expected_output", expected_output) - .pad(&config) - .unwrap(); - let result = circuit.gen_witness(circuit_input_signals); - println!("gen_witness_result={:?}", result); - assert!(result.is_ok()); - } -} - -#[test] -fn hash_bytes_to_field_no_len() { - let circuit_src_template = r#" -pragma circom 2.1.3; - -include "helpers/hashtofield.circom"; - -template HashBytesToFieldTest(max_len) { - signal input in[max_len]; - signal input expected_output; - component c1 = HashBytesToField(max_len); - c1.in <== in; - expected_output === c1.hash; -} - -component main = HashBytesToFieldTest(__MAX_LEN__); -"#; - - let max_supported_byte_len = MAX_NUM_INPUT_SCALARS * BYTES_PACKED_PER_SCALAR; - - let mut rng = thread_rng(); - let num_iterations = std::env::var("NUM_ITERATIONS") - .unwrap_or("10".to_string()) - .parse::() - .unwrap_or(10); - - //TODO: hardcode some interesting circuit dimensions that's widely used in keyless. - - for i in 0..num_iterations { - println!(); - println!("Iteration {} starts.", i); - let num_bytes_circuit_capacity: usize = rng.gen_range(1, max_supported_byte_len); - println!("num_bytes_circuit_capacity={}", num_bytes_circuit_capacity); - let circuit_src = circuit_src_template.replace( - "__MAX_LEN__", - num_bytes_circuit_capacity.to_string().as_str(), - ); - let circuit = TestCircuitHandle::new_from_str(circuit_src.as_str()).unwrap(); - let input_len = rng.gen_range(0, num_bytes_circuit_capacity + 1); - println!("input_len={}", input_len); - let msg = random_bytes(&mut rng, input_len); - let expected_output = - pad_and_hash_bytes_no_len(msg.as_slice(), num_bytes_circuit_capacity).unwrap(); - println!("expected_output={}", expected_output); - let config = CircuitPaddingConfig::new().max_length("in", num_bytes_circuit_capacity); - let circuit_input_signals = CircuitInputSignals::new() - .bytes_input("in", msg.as_slice()) - .fr_input("expected_output", expected_output) - .pad(&config) - .unwrap(); - let result = circuit.gen_witness(circuit_input_signals); - println!("gen_witness_result={:?}", result); - assert!(result.is_ok()); - } -} - -#[test] -fn hash_limbs_to_field_with_len() { - let circuit_src_template = r#" -pragma circom 2.1.3; - -include "helpers/hashtofield.circom"; - -template Hash64BitLimbsToFieldWithLenTest(max_len) { - signal input in[max_len]; - signal input len; - signal input expected_output; - component c1 = Hash64BitLimbsToFieldWithLen(max_len); - c1.in <== in; - c1.len <== len; - expected_output === c1.hash; -} - -component main = Hash64BitLimbsToFieldWithLenTest(__MAX_LEN__); -"#; - - // Have to save 1 scalar slot for the length. - let max_supported_limb_len = (MAX_NUM_INPUT_SCALARS - 1) * LIMBS_PACKED_PER_SCALAR; - - let mut rng = thread_rng(); - let num_iterations = std::env::var("NUM_ITERATIONS") - .unwrap_or("10".to_string()) - .parse::() - .unwrap_or(10); - - //TODO: hardcode some interesting circuit dimensions that's widely used in keyless. - - for i in 0..num_iterations { - println!(); - println!("Iteration {} starts.", i); - let num_limbs_circuit_capacity: usize = rng.gen_range(1, max_supported_limb_len); - println!("num_limbs_circuit_capacity={}", num_limbs_circuit_capacity); - let circuit_src = circuit_src_template.replace( - "__MAX_LEN__", - num_limbs_circuit_capacity.to_string().as_str(), - ); - let circuit = TestCircuitHandle::new_from_str(circuit_src.as_str()).unwrap(); - let input_len = rng.gen_range(0, num_limbs_circuit_capacity + 1); - println!("input_len={}", input_len); - let limbs: Vec = (0..input_len).map(|_| rng.gen()).collect(); - let expected_output = - pad_and_hash_limbs_with_len(limbs.as_slice(), num_limbs_circuit_capacity).unwrap(); - println!("expected_output={}", expected_output); - let config = CircuitPaddingConfig::new().max_length("in", num_limbs_circuit_capacity); - let circuit_input_signals = CircuitInputSignals::new() - .limbs_input("in", limbs.as_slice()) - .usize_input("len", limbs.len()) - .fr_input("expected_output", expected_output) - .pad(&config) - .unwrap(); - let result = circuit.gen_witness(circuit_input_signals); - println!("gen_witness_result={:?}", result); - assert!(result.is_ok()); - } -} - -#[test] -fn check_are_64bit_limbs_should_pass_with_valid_limbs() { - let mut rng = thread_rng(); - let circuit_src_template = r#" -pragma circom 2.1.3; -include "helpers/hashtofield.circom"; -component main = CheckAre64BitLimbs(__NUM_LIMBS__); -"#; - - for num_limbs in 0..60 { - println!(); - println!("Iteration {} starts.", num_limbs); - let circuit_src = - circuit_src_template.replace("__NUM_LIMBS__", num_limbs.to_string().as_str()); - let circuit = TestCircuitHandle::new_from_str(circuit_src.as_str()).unwrap(); - let limbs: Vec = (0..num_limbs).map(|_| rng.gen()).collect(); - let config = CircuitPaddingConfig::new().max_length("in", num_limbs); - let circuit_input_signals = CircuitInputSignals::new() - .limbs_input("in", limbs.as_slice()) - .pad(&config) - .unwrap(); - let result = circuit.gen_witness(circuit_input_signals); - println!("gen_witness_result={:?}", result); - assert!(result.is_ok()); - } -} - -#[test] -fn check_are_64bit_limbs_should_fail_with_invalid_limbs() { - let circuit_src_template = r#" -pragma circom 2.1.3; -include "helpers/hashtofield.circom"; -component main = CheckAre64BitLimbs(__NUM_LIMBS__); -"#; - - for num_limbs in 1..60 { - let circuit_src = - circuit_src_template.replace("__NUM_LIMBS__", num_limbs.to_string().as_str()); - let circuit = TestCircuitHandle::new_from_str(circuit_src.as_str()).unwrap(); - let invalid_limb_value = Fr::from(u64::MAX) + Fr::ONE; - let frs = vec![invalid_limb_value; num_limbs]; - let config = CircuitPaddingConfig::new().max_length("in", num_limbs); - let circuit_input_signals = CircuitInputSignals::new() - .frs_input("in", frs.as_slice()) - .pad(&config) - .unwrap(); - let result = circuit.gen_witness(circuit_input_signals); - println!("gen_witness_result={:?}", result); - assert!(result.is_err()); - } -} diff --git a/keyless/circuit/src/jwt_field_parsing.rs b/keyless/circuit/src/jwt_field_parsing.rs deleted file mode 100644 index ad70343f391cb..0000000000000 --- a/keyless/circuit/src/jwt_field_parsing.rs +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::{misc::calc_string_bodies, TestCircuitHandle}; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::CircuitInputSignals, config::CircuitPaddingConfig, -}; - -struct JWTField { - whole_field: T, - name: T, - value: T, -} - -struct JWTFieldMaliciousIndices { - whole_field: T, - name: T, - value: T, - whole_field_len: usize, - name_len: usize, - value_index: usize, - value_len: usize, - colon_index: usize, -} - -trait JWTFieldIndices { - fn whole_field_len(&self) -> usize; - fn name_len(&self) -> usize; - fn value_index(&self) -> usize; - fn value_len(&self) -> usize; - fn colon_index(&self) -> usize; -} - -trait JWTFieldStr { - fn whole_field(&self) -> &str; - fn name(&self) -> &str; - fn value(&self) -> &str; -} - -impl JWTFieldIndices for JWTField { - fn whole_field_len(&self) -> usize { - self.whole_field.len() - } - - fn name_len(&self) -> usize { - self.name.len() - } - - fn value_index(&self) -> usize { - self.whole_field.find(&self.value).unwrap() - } - - fn value_len(&self) -> usize { - self.value.len() - } - - fn colon_index(&self) -> usize { - self.whole_field.find(':').unwrap() - } -} - -impl JWTFieldStr for JWTField { - fn whole_field(&self) -> &str { - &self.whole_field - } - - fn name(&self) -> &str { - &self.name - } - - fn value(&self) -> &str { - &self.value - } -} - -impl JWTFieldIndices for JWTFieldMaliciousIndices { - fn whole_field_len(&self) -> usize { - self.whole_field_len - } - - fn name_len(&self) -> usize { - self.name_len - } - - fn value_index(&self) -> usize { - self.value_index - } - - fn value_len(&self) -> usize { - self.value_len - } - - fn colon_index(&self) -> usize { - self.colon_index - } -} - -impl JWTFieldStr for JWTFieldMaliciousIndices { - fn whole_field(&self) -> &str { - &self.whole_field - } - - fn name(&self) -> &str { - &self.name - } - - fn value(&self) -> &str { - &self.value - } -} - -fn jwt_field_str(whole_field: &str, name: &str, value: &str) -> JWTField { - JWTField { - whole_field: String::from(whole_field), - name: String::from(name), - value: String::from(value), - } -} - -fn jwt_field_str_malicious_indices( - whole_field: &str, - name: &str, - value: &str, -) -> JWTFieldMaliciousIndices { - JWTFieldMaliciousIndices { - whole_field: String::from(whole_field), - name: String::from(name), - value: String::from(value), - whole_field_len: whole_field.len(), - name_len: name.len(), - value_index: whole_field.find(value).unwrap_or(0), - value_len: value.len(), - colon_index: whole_field.find(':').unwrap(), - } -} - -fn email_verified_test( - field: T, - test_circom_file: &str, -) -> Result { - let circuit_handle = TestCircuitHandle::new(test_circom_file).unwrap(); - - let config = CircuitPaddingConfig::new() - .max_length("field", 30) - .max_length("name", 20) - .max_length("value", 10); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("field", field.whole_field()) - .str_input("name", field.name()) - .str_input("value", field.value()) - .usize_input("field_len", field.whole_field_len()) - .usize_input("name_len", field.name_len()) - .usize_input("value_index", field.value_index()) - .usize_input("value_len", field.value_len()) - .usize_input("colon_index", field.colon_index()) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - result -} - -fn unquoted_test( - field: T, - test_circom_file: &str, -) -> Result { - let circuit_handle = TestCircuitHandle::new(test_circom_file).unwrap(); - - let config = CircuitPaddingConfig::new() - .max_length("field", 60) - .max_length("name", 30) - .max_length("value", 30); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("field", field.whole_field()) - .str_input("name", field.name()) - .str_input("value", field.value()) - .usize_input("field_len", field.whole_field_len()) - .usize_input("name_len", field.name_len()) - .usize_input("value_index", field.value_index()) - .usize_input("value_len", field.value_len()) - .usize_input("colon_index", field.colon_index()) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - result -} - -fn quoted_test( - field: T, - test_circom_file: &str, -) -> Result { - let circuit_handle = TestCircuitHandle::new(test_circom_file).unwrap(); - - let config = CircuitPaddingConfig::new() - .max_length("field", 60) - .max_length("field_string_bodies", 60) - .max_length("name", 30) - .max_length("value", 30); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("field", field.whole_field()) - .str_input("name", field.name()) - .str_input("value", field.value()) - .usize_input("field_len", field.whole_field_len()) - .bools_input( - "field_string_bodies", - &calc_string_bodies(field.whole_field()), - ) - .usize_input("name_len", field.name_len()) - .usize_input("value_index", field.value_index()) - .usize_input("value_len", field.value_len()) - .usize_input("colon_index", field.colon_index()) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - result -} - -fn should_pass_quoted(field: T) { - assert!(quoted_test(field, "jwt_field_parsing/parse_quoted_test.circom").is_ok()); -} - -fn should_pass_unquoted(field: T) { - assert!(unquoted_test(field, "jwt_field_parsing/parse_unquoted_test.circom").is_ok()); -} - -fn should_pass_ev(field: T) { - assert!(email_verified_test( - field, - "jwt_field_parsing/parse_email_verified_field_test.circom" - ) - .is_ok()); -} - -fn should_fail_quoted(field: T) { - assert!(quoted_test(field, "jwt_field_parsing/parse_quoted_test.circom").is_err()); -} - -fn should_fail_unquoted(field: T) { - assert!(unquoted_test(field, "jwt_field_parsing/parse_unquoted_test.circom").is_err()); -} - -#[allow(dead_code)] -fn should_fail_ev(field: T) { - assert!(email_verified_test( - field, - "jwt_field_parsing/parse_email_verified_field_test.circom" - ) - .is_err()); -} - -// The tests - -#[test] -fn simple_quoted() { - should_pass_quoted(jwt_field_str("\"name\": \"value\",", "name", "value")); -} - -#[test] -fn simple_unquoted() { - should_pass_unquoted(jwt_field_str("\"name\": value,", "name", "value")); -} - -#[test] -fn no_whitespace_quoted() { - should_pass_quoted(jwt_field_str("\"name\":\"value\",", "name", "value")); -} - -#[test] -fn no_whitespace_unquoted() { - should_pass_unquoted(jwt_field_str("\"name\":value,", "name", "value")); -} - -// fails to parse now with StringBodies logic -#[test] -fn malicious_value_1() { - let mut field = jwt_field_str_malicious_indices("\"sub\": \"a\\\",b\",", "sub", "a\\"); - field.whole_field_len = field.whole_field.find(',').unwrap() + 1; - should_fail_quoted(field); -} - -// fails to parse now with StringBodies logic -#[test] -fn malicious_value_2() { - should_fail_quoted(jwt_field_str( - "\"name1\":\"value1\",\"name2\":\"value2\",", - "name1", - "value1\",\"name2\":\"value2", - )); -} - -#[test] -fn end_with_curly_bracket() { - should_pass_quoted(jwt_field_str("\"name\": \"value\"}", "name", "value")); -} - -#[test] -fn end_with_curly_bracket_unquoted() { - should_pass_unquoted(jwt_field_str("\"name\": value}", "name", "value")); -} - -#[test] -fn should_fail_when_name_has_no_first_quote() { - should_fail_quoted(jwt_field_str("name\": \"value\",", "name", "value")); -} - -#[test] -fn should_fail_when_name_has_no_second_quote() { - should_fail_quoted(jwt_field_str("\"name: \"value\",", "name", "value")); -} - -#[test] -fn should_fail_when_name_has_no_quotes() { - should_fail_quoted(jwt_field_str("name: \"value\",", "name", "value")); -} - -#[test] -fn should_fail_when_name_not_equal_quoted() { - should_fail_quoted(jwt_field_str("\"name\": \"value\",", "fake", "value")); -} - -#[test] -fn should_fail_when_name_not_equal_unquoted() { - should_fail_unquoted(jwt_field_str("\"name\": value,", "fake", "value")); -} - -#[test] -fn should_fail_when_value_not_equal_quoted() { - let mut field = jwt_field_str_malicious_indices("\"name\": \"value\",", "name", "fake"); - field.whole_field_len = field.whole_field.len(); - field.value_index = field.whole_field.find("value").unwrap(); - should_fail_quoted(field); -} - -#[test] -fn should_fail_when_value_not_equal_unquoted() { - let mut field = jwt_field_str_malicious_indices("\"name\": value,", "name", "fake"); - field.whole_field_len = field.whole_field.len(); - field.value_index = field.whole_field.find("value").unwrap(); - should_fail_unquoted(field); -} - -// ref: Circuit Bug #3, https://www.notion.so/aptoslabs/JWTFieldCheck-does-not-properly-constrain-field_len-which-can-cause-the-circuit-to-accept-field-val-9943c152e7274f35a1669a6cb416c7bf?pvs=4 -#[test] -fn malicious_field_len() { - let mut field = jwt_field_str_malicious_indices("\"name\":\",value\"", "name", ",value"); - field.whole_field_len = field.whole_field.find(',').unwrap() + 1; - field.value_index = field.whole_field.find(',').unwrap(); - assert_ne!(field.whole_field_len, field.whole_field.len()); - - should_fail_quoted(field); -} - -// ref: Circuit Bug #4, https://www.notion.so/aptoslabs/JWTFieldCheck-allows-for-maliciously-truncating-field-values-at-any-character-f8695dcd397a4bc2b66d52349388499f?pvs=4 -#[test] -fn malicious_value_len_1() { - let mut field = jwt_field_str_malicious_indices("\"sub\":\"user,fake\",", "sub", "user"); - - field.whole_field_len = field.whole_field.find(',').unwrap() + 1; - - should_fail_quoted(field); -} - -#[test] -fn malicious_value_len_2() { - let mut field = jwt_field_str_malicious_indices("\"sub\":user,fake,", "sub", "user"); - - field.whole_field_len = field.whole_field.find(',').unwrap() + 1; - - should_pass_unquoted(field); - - let field = jwt_field_str_malicious_indices("\"sub\":user,fake,", "sub", "user,fake"); - - should_fail_unquoted(field); -} - -#[test] -fn ev_unquoted_no_spaces() { - should_pass_ev(jwt_field_str( - "\"email_verified\":true,", - "email_verified", - "true", - )); -} - -#[test] -fn ev_unquoted_spaces() { - should_pass_ev(jwt_field_str( - "\"email_verified\": true ,", - "email_verified", - "true", - )); -} - -#[test] -fn ev_unquoted_spaces_2() { - should_pass_ev(jwt_field_str( - "\"email_verified\": true ,", - "email_verified", - "true", - )); -} - -#[test] -fn ev_quoted_no_spaces() { - should_pass_ev(jwt_field_str( - "\"email_verified\":\"true\",", - "email_verified", - "true", - )); -} - -#[test] -fn ev_quoted_spaces() { - should_pass_ev(jwt_field_str( - "\"email_verified\": \"true\" ,", - "email_verified", - "true", - )); -} - -#[test] -fn ev_quoted_spaces_2() { - should_pass_ev(jwt_field_str( - "\"email_verified\": \"true\" ,", - "email_verified", - "true", - )); -} diff --git a/keyless/circuit/src/lib.rs b/keyless/circuit/src/lib.rs deleted file mode 100644 index 7f7bd7ebf48c8..0000000000000 --- a/keyless/circuit/src/lib.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -extern crate core; - -use anyhow::ensure; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::{CircuitInputSignals, Padded}, - witness_gen::witness_gen, -}; -use std::{env, fs, fs::File, io::Write, path::PathBuf, process::Command}; -use tempfile::{tempdir, NamedTempFile, TempDir}; - -#[cfg(test)] -mod arrays; -#[cfg(test)] -mod base64; -#[cfg(test)] -mod bigint; -#[cfg(test)] -mod hash_to_field; -#[cfg(test)] -mod jwt_field_parsing; -#[cfg(test)] -mod misc; -#[cfg(test)] -mod packing; -#[cfg(test)] -mod rsa; -#[cfg(test)] -mod sha; - -pub struct TestCircuitHandle { - dir: TempDir, -} - -impl TestCircuitHandle { - /// Compile the circuit in the given file using BN254 as the underlying curve. - pub fn new(file_name: &str) -> anyhow::Result { - let cargo_manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - let include_root_dir = cargo_manifest_dir.join("./templates"); - let src_circuit_path = include_root_dir.join("tests").join(file_name); - let content = fs::read_to_string(src_circuit_path)?; - Self::new_from_str(content.as_str()) - } - - pub fn new_from_str(circuit_src: &str) -> anyhow::Result { - let dir = tempdir()?; - let cargo_manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - let include_root_dir = cargo_manifest_dir.join("./templates"); - let tmp_circuit_path = dir.path().to_owned().join("circuit.circom"); - let mut tmp_circuit_file = File::create(&tmp_circuit_path)?; - let global_node_modules_path = - String::from_utf8(Command::new("npm").args(["root", "-g"]).output()?.stdout).unwrap(); - tmp_circuit_file.write_all(circuit_src.as_bytes())?; - let output = Command::new("circom") - .args([ - "-l", - include_root_dir.to_str().unwrap(), - "-l", - global_node_modules_path.trim(), - tmp_circuit_path.to_str().unwrap(), - "--c", - "--wasm", - "-o", - dir.path().to_str().unwrap(), - ]) - .output()?; - println!("{}", String::from_utf8_lossy(&output.stdout)); - println!("{}", String::from_utf8_lossy(&output.stderr)); - ensure!(output.status.success()); - Ok(Self { dir }) - } - - pub fn gen_witness( - &self, - input_signals: CircuitInputSignals, - ) -> anyhow::Result { - let formatted_input_str = serde_json::to_string(&input_signals.to_json_value())?; - witness_gen( - self.witness_gen_js_path().to_str().unwrap(), - self.witness_gen_wasm_path().to_str().unwrap(), - &formatted_input_str, - ) - } - - fn witness_gen_js_path(&self) -> PathBuf { - self.dir - .path() - .to_owned() - .join("circuit_js/generate_witness.js") - } - - fn witness_gen_wasm_path(&self) -> PathBuf { - self.dir.path().to_owned().join("circuit_js/circuit.wasm") - } -} - -// pub fn run_circuit_test(circuit_name: &str, circuit_input_signals: CircuitInputSignals) { -// // compute circuit input signals (input.json) -// let formatted_input_str = serde_json::to_string(&circuit_input_signals.to_json_value()).unwrap(); -// // run witness generation phase for `circuit_name` -// let compile_circuit(); -// witness_gen(witness_gen_js_path, witness_gen_wasm_path, &formatted_input_str).unwrap(); -// } diff --git a/keyless/circuit/src/misc.rs b/keyless/circuit/src/misc.rs deleted file mode 100644 index 3454bce37fac4..0000000000000 --- a/keyless/circuit/src/misc.rs +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::TestCircuitHandle; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::CircuitInputSignals, config::CircuitPaddingConfig, -}; -use ark_bn254::Fr; -use ark_ff::PrimeField; -use rand::{distributions::Alphanumeric, rngs::ThreadRng, Rng}; // 0.8 -use std::iter::zip; - -fn generate_string_bodies_input() -> String { - let mut rng = rand::thread_rng(); - - let len = 13; - - let mut s: Vec = rng - .sample_iter(&Alphanumeric) - .take(len) - .collect::() - .as_bytes() - .into(); - - let num_to_replace = rng.gen_range(0, len); - let to_replace: Vec = (0..num_to_replace).map(|_| rng.gen_range(0, len)).collect(); - let replace_with_escaped_quote: Vec = - (0..num_to_replace).map(|_| rng.gen_bool(0.5)).collect(); - - for (i, should_replace_with_escaped_quote) in zip(to_replace, replace_with_escaped_quote) { - if should_replace_with_escaped_quote && i > 0 { - s[i - 1] = b'\\'; - s[i] = b'"'; - } else { - s[i] = b'"'; - } - } - - String::from_utf8_lossy(&s).into_owned() -} - -fn format_quotes_array(q: &[bool]) -> String { - q.iter() - .map(|b| match b { - true => "1", - false => "0", - }) - .collect::>() - .concat() -} - -pub fn calc_string_bodies(s: &str) -> Vec { - let bytes = s.as_bytes(); - let mut string_bodies = vec![false; s.len()]; - let mut quotes = vec![false; s.len()]; - let mut quote_parity = vec![false; s.len()]; - - quotes[0] = bytes[0] == b'"'; - quote_parity[0] = bytes[0] == b'"'; - for i in 1..bytes.len() { - let mut prev_is_odd_backslash = false; - for j in (0..i).rev() { - if bytes[j] != b'\\' { - break; - } - println!("{}: {}", j, bytes[j]); - prev_is_odd_backslash = !prev_is_odd_backslash; - } - quotes[i] = bytes[i] == b'"' && !prev_is_odd_backslash; - quote_parity[i] = if quotes[i] { - !quote_parity[i - 1] - } else { - quote_parity[i - 1] - }; - } - - string_bodies[0] = false; - for i in 1..bytes.len() { - string_bodies[i] = quote_parity[i] && quote_parity[i - 1]; - } - - println!("string : {}", s); - println!("quote_parity : {}", format_quotes_array("e_parity)); - println!("string_bodies: {}", format_quotes_array(&string_bodies)); - - string_bodies -} - -#[test] -fn is_whitespace_test() { - let circuit_handle = TestCircuitHandle::new("misc/is_whitespace_test.circom").unwrap(); - - for c in 0u8..=127u8 { - let config = CircuitPaddingConfig::new(); - - let circuit_input_signals = CircuitInputSignals::new() - .byte_input("char", c) - .bool_input("result", (c as char).is_whitespace()) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{}: {:?}", c, result); - assert!(result.is_ok()); - } -} - -#[test] -fn string_bodies_test() { - let circuit_handle = TestCircuitHandle::new("misc/string_bodies_test.circom").unwrap(); - - let s = "\"123\" 456 \"7\""; - let quotes = &[0u8, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0]; - let quotes_b: Vec = quotes.iter().map(|b| b == &1u8).collect(); - - assert_eq!(quotes_b, calc_string_bodies(s)); - - let config = CircuitPaddingConfig::new() - .max_length("in", 13) - .max_length("out", 13); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("in", s) - .bytes_input("out", quotes) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - assert!(result.is_ok()); -} - -#[test] -fn string_bodies_test_2() { - let circuit_handle = TestCircuitHandle::new("misc/string_bodies_test.circom").unwrap(); - - let s = "\"12\\\"456\" \"7\""; - let quotes = &[0u8, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0]; - let quotes_b: Vec = quotes.iter().map(|b| b == &1u8).collect(); - - assert_eq!(quotes_b, calc_string_bodies(s)); - - let config = CircuitPaddingConfig::new() - .max_length("in", 13) - .max_length("out", 13); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("in", s) - .bytes_input("out", quotes) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - assert!(result.is_ok()); -} - -#[test] -fn string_bodies_test_random() { - let circuit_handle = TestCircuitHandle::new("misc/string_bodies_test.circom").unwrap(); - - for _iter in 0..128 { - let s = generate_string_bodies_input(); - let quotes = calc_string_bodies(&s); - - let config = CircuitPaddingConfig::new() - .max_length("in", 13) - .max_length("out", 13); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("in", &s) - .bools_input("out", "es) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - assert!(result.is_ok()); - } -} - -#[test] -fn string_bodies_test_prefix_quotes() { - let circuit_handle = TestCircuitHandle::new("misc/string_bodies_test.circom").unwrap(); - - for i in 0..13 { - let mut bytes = vec![b'a'; 13]; - for byte in bytes.iter_mut().take(i) { - *byte = b'"'; - } - let s = String::from_utf8_lossy(&bytes); - - let quotes = calc_string_bodies(&s); - - let config = CircuitPaddingConfig::new() - .max_length("in", 13) - .max_length("out", 13); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("in", &s) - .bools_input("out", "es) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - assert!(result.is_ok()); - } -} - -#[test] -fn string_bodies_test_zjma() { - let circuit_handle = TestCircuitHandle::new("misc/string_bodies_test.circom").unwrap(); - - let s = "\"abc\\\\\""; - let quotes = calc_string_bodies(s); - - let config = CircuitPaddingConfig::new() - .max_length("in", 13) - .max_length("out", 13); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("in", s) - .bools_input("out", "es) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - assert!(result.is_ok()); -} - -#[test] -fn calculate_total_test() { - let circuit_handle = TestCircuitHandle::new("misc/calculate_total_test.circom").unwrap(); - - let mut rng = rand::thread_rng(); - - for _i in 0..256 { - let nums: Vec = (0..10).map(|_| Fr::from(rng.gen::())).collect(); - - let sum: Fr = nums.iter().sum(); - - let config = CircuitPaddingConfig::new().max_length("nums", 10); - - let circuit_input_signals = CircuitInputSignals::new() - .frs_input("nums", &nums) - .fr_input("sum", sum) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - assert!(result.is_ok()); - } -} - -#[test] -fn assert_equal_if_true_test() { - fn rand_fr(rng: &mut ThreadRng) -> Fr { - let bytes: [u8; 32] = rng.gen(); - Fr::from_le_bytes_mod_order(&bytes) - } - - let circuit_handle = TestCircuitHandle::new("misc/assert_equal_if_true_test.circom").unwrap(); - - let mut rng = rand::thread_rng(); - - for _i in 0..256 { - let (nums, are_equal) = if rng.gen_bool(0.5) { - let nums: Vec = (0..2).map(|_| rand_fr(&mut rng)).collect(); - - let mut are_equal = nums[0] == nums[1]; - - if rng.gen_bool(0.5) { - are_equal = true; - } - - (nums, are_equal) - } else { - let num = rand_fr(&mut rng); - let nums: Vec = vec![num, num]; - - (nums, true) - }; - - let config = CircuitPaddingConfig::new().max_length("in", 2); - - let circuit_input_signals = CircuitInputSignals::new() - .frs_input("in", &nums) - .bool_input("bool", are_equal) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - if are_equal == (nums[0] == nums[1]) { - assert!(result.is_ok()); - } else { - assert!(result.is_err()); - } - } -} - -#[test] -fn email_verified_check_test() { - let circuit_handle = TestCircuitHandle::new("misc/email_verified_check_test.circom").unwrap(); - - let testcases = [ - ("email_verified", "true", "email", true, true), - // Note that this template doesn't actually check that ev_name is exactly equal to - // "email_verified". It only checks that it starts with this string. I believe that this - // is not an issue because ParseEmailVerifiedField enforces that ev_name has len == 14. - ("email_verified000", "true", "email", true, true), - ("email_verified", "false", "email", true, false), - ("email_verified", "true", "sub", false, true), - ("email_verified", "false", "sub", false, true), - ]; - - for t in testcases { - let ev_name = t.0; - let ev_value = t.1; - let uid_name = t.2; - let expected_uid_is_email = t.3; - let test_should_pass = t.4; - - let config = CircuitPaddingConfig::new() - .max_length("ev_name", 20) - .max_length("ev_value", 10) - .max_length("uid_name", 30); - - let circuit_input_signals = CircuitInputSignals::new() - .str_input("ev_name", ev_name) - .str_input("ev_value", ev_value) - .str_input("uid_name", uid_name) - .usize_input("ev_value_len", ev_value.len()) - .usize_input("uid_name_len", uid_name.len()) - .bool_input("uid_is_email", expected_uid_is_email) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("{:?}", result); - if test_should_pass { - assert!(result.is_ok()); - } else { - assert!(result.is_err()); - } - } -} diff --git a/keyless/circuit/src/packing.rs b/keyless/circuit/src/packing.rs deleted file mode 100644 index 00ec0339621d2..0000000000000 --- a/keyless/circuit/src/packing.rs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::TestCircuitHandle; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::CircuitInputSignals, config::CircuitPaddingConfig, -}; -use ark_bn254::Fr; -use ark_ff::{BigInteger, PrimeField}; -use rand_chacha::{ - rand_core::{RngCore as _, SeedableRng as _}, - ChaCha20Rng, -}; - -const TEST_RNG_SEED: u64 = 6896401633680249901; - -fn expected_num2bits_be(n: u64, size: usize) -> Vec { - let mut bits_le = Vec::new(); - for i in 0..size { - bits_le.push(((n >> i) & 1) == 1); - } - bits_le.into_iter().rev().collect() -} - -fn bits_to_field_elems(bits: &[bool], bits_per_field_elem: usize) -> Vec { - bits.chunks(bits_per_field_elem) - .map(bits_to_field_elem) - .collect() -} - -fn bits_to_field_elem(bits: &[bool]) -> Fr { - let bigint = BigInteger::from_bits_be(bits); - Fr::from_bigint(bigint).unwrap() -} - -#[test] -fn num2bits_be_test() { - let circuit_handle = TestCircuitHandle::new("packing/num2bits_be_test.circom").unwrap(); - let bits_max_size = 8; - - for n in 0..=255 { - let config = CircuitPaddingConfig::new().max_length("bits_out", bits_max_size); - - let circuit_input_signals = CircuitInputSignals::new() - .byte_input("num_in", n) - .bools_input("bits_out", &expected_num2bits_be(n as u64, bits_max_size)) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("n: {}, {:?}", n, result); - assert!(result.is_ok()); - } -} - -#[test] -fn bits2num_big_endian_test() { - let circuit_handle = TestCircuitHandle::new("packing/bits2num_big_endian_test.circom").unwrap(); - let mut rng = ChaCha20Rng::seed_from_u64(TEST_RNG_SEED); - let bits_max_size = 64; - - for i in 0..=255 { - let expected_n = rng.next_u64(); - - let config = CircuitPaddingConfig::new().max_length("bits_in", bits_max_size); - - let circuit_input_signals = CircuitInputSignals::new() - .bools_input("bits_in", &expected_num2bits_be(expected_n, bits_max_size)) - .u64_input("num_out", expected_n) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("i: {}, {:?}", i, result); - assert!(result.is_ok()); - } -} - -#[test] -fn bytes_to_bits_test() { - let circuit_handle = TestCircuitHandle::new("packing/bytes_to_bits_test.circom").unwrap(); - - let mut rng = ChaCha20Rng::seed_from_u64(TEST_RNG_SEED); - const BYTES_MAX_SIZE: usize = 10; - const BITS_MAX_SIZE: usize = BYTES_MAX_SIZE * 8; - - for i in 0..=255 { - let bytes: &mut [u8] = &mut [0u8; BYTES_MAX_SIZE]; - rng.fill_bytes(bytes); - - let expected_bits: Vec = bytes - .iter() - .flat_map(|byte| expected_num2bits_be(*byte as u64, 8)) - .collect(); - - let config = CircuitPaddingConfig::new() - .max_length("bytes_in", BYTES_MAX_SIZE) - .max_length("bits_out", BITS_MAX_SIZE); - - let circuit_input_signals = CircuitInputSignals::new() - .bytes_input("bytes_in", bytes) - .bools_input("bits_out", &expected_bits) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("i: {}, {:?}", i, result); - assert!(result.is_ok()); - } -} - -#[test] -fn bits_to_field_elems_test() { - let circuit_handle = TestCircuitHandle::new("packing/bits_to_field_elems_test.circom").unwrap(); - - let mut rng = ChaCha20Rng::seed_from_u64(TEST_RNG_SEED); - - // Keeping both of these constant makes sense here, since the circuit only ever uses these two - // particular parameters when calling this template - const MAX_BITS_LEN: usize = 256; - const BITS_PER_FIELD_ELEM: usize = 64; - let num_field_elems = MAX_BITS_LEN.div_ceil(BITS_PER_FIELD_ELEM); - - for i in 0..=255 { - let bytes: &mut [u8] = &mut [0u8; MAX_BITS_LEN / 8]; - rng.fill_bytes(bytes); - - let bits: Vec = bytes - .iter() - .flat_map(|byte| expected_num2bits_be(*byte as u64, 8)) - .collect(); - - let expected_field_elems = bits_to_field_elems(&bits, BITS_PER_FIELD_ELEM); - println!("{}", expected_field_elems.len()); - - let config = CircuitPaddingConfig::new() - .max_length("bits_in", MAX_BITS_LEN) - .max_length("field_elems_out", num_field_elems); - - let circuit_input_signals = CircuitInputSignals::new() - .bools_input("bits_in", &bits) - .frs_input("field_elems_out", &expected_field_elems) - .pad(&config) - .unwrap(); - - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("i: {}, {:?}", i, result); - assert!(result.is_ok()); - } -} diff --git a/keyless/circuit/src/rsa.rs b/keyless/circuit/src/rsa.rs deleted file mode 100644 index 33905f3832e4f..0000000000000 --- a/keyless/circuit/src/rsa.rs +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::TestCircuitHandle; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::CircuitInputSignals, config::CircuitPaddingConfig, -}; -use aptos_logger::info; -use num_bigint::BigUint; -use num_traits::FromPrimitive; -use rand::{thread_rng, Rng}; -use rsa::{ - pkcs1v15::SigningKey, - sha2::{Digest, Sha256}, - signature::{RandomizedSigner, SignatureEncoding}, - traits::{PrivateKeyParts, PublicKeyParts}, - RsaPrivateKey, -}; -use std::convert::TryInto; - -const EXPONENT: u64 = 65537; - -#[test] -fn rsa_verify_should_pass_with_valid_input() { - common(|_, _, _| {}, true) -} - -#[test] -fn rsa_verify_should_fail_with_invalid_signature() { - common( - |sig_limbs, _, _| { - flip_random_bit(sig_limbs); - }, - false, - ); -} - -#[test] -fn rsa_verify_should_fail_with_invalid_modulus() { - common( - |_, modulus_limbs, _| { - flip_random_bit(modulus_limbs); - }, - false, - ); -} - -#[test] -fn rsa_verify_should_fail_with_invalid_hased_msg() { - common( - |_, _, hashed_msg_limbs| { - flip_random_bit(hashed_msg_limbs); - }, - false, - ); -} - -fn common, &mut Vec, &mut Vec)>( - update_signals: F, - witness_gen_should_pass: bool, -) { - // Default #iterations to 1 but allow customization. - let num_iterations = std::env::var("NUM_ITERATIONS") - .unwrap_or("1".to_string()) - .parse::() - .unwrap_or(1); - - let circuit = TestCircuitHandle::new("rsa_verify_test.circom").unwrap(); - let mut rng = thread_rng(); - let e = rsa::BigUint::from_u64(EXPONENT).unwrap(); - - for i in 0..num_iterations { - info!("Iteration {i} starts. Generate RSA key pairs."); - let private_key = - RsaPrivateKey::new_with_exp(&mut rand_chacha::rand_core::OsRng, 2048, &e).unwrap(); - info!( - "Key pair generated, d={:?}, n={:?}.", - private_key.d(), - private_key.n() - ); - let modulus = BigUint::from_bytes_be(&private_key.to_public_key().n().to_bytes_be()); - let mut modulus_limbs = modulus.to_u64_digits(); - let signing_key = SigningKey::::new(private_key); - - info!("Generate a random message."); - let msg_len: usize = rng.gen_range(0, 9999); - let message: Vec = vec![0; msg_len]; - - info!("Message generated, msg_hex={}", hex::encode(&message)); - let mut hasher = Sha256::new(); - hasher.update(&message); - let hashed_msg = hasher.finalize().to_vec(); - - let mut hashed_msg_limbs: Vec = hashed_msg - .chunks(8) - .map(|bytes| bytes.try_into()) - .collect::, _>>() - .unwrap() - .into_iter() - .map(u64::from_be_bytes) - .rev() - .collect(); - - let signature = BigUint::from_bytes_be( - &signing_key - .sign_with_rng(&mut rand_chacha::rand_core::OsRng, message.as_slice()) - .to_bytes(), - ); - let mut signature_limbs = signature.to_u64_digits(); - - let config = CircuitPaddingConfig::new(); - - update_signals( - &mut signature_limbs, - &mut modulus_limbs, - &mut hashed_msg_limbs, - ); - - let circuit_input_signals = CircuitInputSignals::new() - .limbs_input("sign", signature_limbs.as_slice()) - .limbs_input("modulus", modulus_limbs.as_slice()) - .limbs_input("hashed", hashed_msg_limbs.as_slice()) - .pad(&config) - .unwrap(); - let result = circuit.gen_witness(circuit_input_signals); - assert_eq!(witness_gen_should_pass, result.is_ok()); - } -} - -fn flip_random_bit(limbs: &mut [u64]) { - let mut rng = thread_rng(); - let limb_idx = rng.gen_range(0, limbs.len()); - let bit_idx = rng.gen_range(0, 64); - *limbs.get_mut(limb_idx).unwrap() ^= 1_u64 << bit_idx; -} diff --git a/keyless/circuit/src/sha.rs b/keyless/circuit/src/sha.rs deleted file mode 100644 index 0349b331dd6b1..0000000000000 --- a/keyless/circuit/src/sha.rs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::TestCircuitHandle; -use aptos_keyless_common::input_processing::{ - circuit_input_signals::CircuitInputSignals, config::CircuitPaddingConfig, sha, -}; -use rand_chacha::{ - rand_core::{RngCore as _, SeedableRng as _}, - ChaCha20Rng, -}; -use sha2::Digest; -use std::sync::Arc; - -const TEST_RNG_SEED: u64 = 13673030044145830633; - -fn byte_to_bits_msb(byte: u8) -> Vec { - (0..8).map(|i| (byte >> (7 - i)) & 1 != 0).collect() -} - -pub fn bytes_to_bits_msb(msg: Vec) -> Vec { - msg.into_iter().flat_map(byte_to_bits_msb).collect() -} - -#[test] -fn sha_test() { - let mut rng = ChaCha20Rng::seed_from_u64(TEST_RNG_SEED); - let circuit_handle = Arc::new(TestCircuitHandle::new("sha_test.circom").unwrap()); - - // TODO: figure out how to parallelize and why `tokio::task::spawn()` does not work. - // Is it supported to do multiple `node generate_witness.js xxx` in parallel at all? - for input_byte_len in 0..248 { - let mut input = vec![0; input_byte_len]; - rng.fill_bytes(&mut input); - let padded_input = sha::with_sha_padding_bytes(&input); - let padded_input_bits = bytes_to_bits_msb(padded_input); - - let mut hasher = sha2::Sha256::new(); - hasher.update(input); - let expected_output = hasher.finalize().to_vec(); - let expected_output_bits = bytes_to_bits_msb(expected_output); - - let config = CircuitPaddingConfig::new() - .max_length("padded_input_bits", 2048) // should align with the `max_num_blocks=4` in `sha_test.circom`. - .max_length("expected_digest_bits", 256); - - let circuit_input_signals = CircuitInputSignals::new() - .bits_input("padded_input_bits", padded_input_bits.as_slice()) - .usize_input("input_bit_len", padded_input_bits.len()) - .bits_input("expected_digest_bits", expected_output_bits.as_slice()) - .pad(&config) - .unwrap(); - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("input_byte_len={}, result={:?}", input_byte_len, result); - assert!(result.is_ok()); - } -} - -#[test] -fn sha_padding_verify_test() { - let mut rng = ChaCha20Rng::seed_from_u64(TEST_RNG_SEED); - let circuit_handle = - Arc::new(TestCircuitHandle::new("sha2_padding_verify_test.circom").unwrap()); - - for input_byte_len in 180..248 { - let input_bit_len = input_byte_len * 8; - let mut input = vec![0; input_byte_len]; - rng.fill_bytes(&mut input); - let padded_input = sha::with_sha_padding_bytes(&input); - let padded_input_byte_len = padded_input.len(); - let config = CircuitPaddingConfig::new() - .max_length("in", 256) - .max_length("L_byte_encoded", 8) - .max_length("padding_without_len", 64); - - let circuit_input_signals = CircuitInputSignals::new() - .bytes_input("in", padded_input.as_slice()) - .usize_input("num_blocks", padded_input_byte_len / 64) - .usize_input("padding_start", input_byte_len) - .bytes_input( - "L_byte_encoded", - (input_bit_len as u64).to_be_bytes().as_slice(), - ) - .bytes_input( - "padding_without_len", - &padded_input[input_byte_len..(padded_input_byte_len - 8)], - ) - .pad(&config) - .unwrap(); - println!("circuit_input_signals={:?}", circuit_input_signals); - let result = circuit_handle.gen_witness(circuit_input_signals); - println!("input_byte_len={}, result={:?}", input_byte_len, result); - assert!(result.is_ok()); - } -} diff --git a/keyless/circuit/templates/.gitignore b/keyless/circuit/templates/.gitignore deleted file mode 100644 index 9f9eea6064653..0000000000000 --- a/keyless/circuit/templates/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tags -*.swp diff --git a/keyless/circuit/templates/helpers/arrays.circom b/keyless/circuit/templates/helpers/arrays.circom deleted file mode 100644 index 54fe02a449b12..0000000000000 --- a/keyless/circuit/templates/helpers/arrays.circom +++ /dev/null @@ -1,323 +0,0 @@ -pragma circom 2.1.3; - -include "circomlib/circuits/multiplexer.circom"; -include "circomlib/circuits/comparators.circom"; -include "./hashtofield.circom"; -include "./misc.circom"; - -// Outputs a bit array where indices [start_index, end_index) (inclusive of start_index, exclusive of end_index) are all 1, and all other bits are 0. Does not work if end_index is greater than `len` -template ArraySelector(len) { - signal input start_index; - signal input end_index; - signal output out[len]; - assert(end_index > start_index); - - signal start_selector[len] <== SingleOneArray(len)(start_index); - signal end_selector[len] <== SingleNegOneArray(len)(end_index); - - out[0] <== start_selector[0]; - for (var i = 1; i < len; i++) { - out[i] <== out[i-1] + start_selector[i] + end_selector[i]; - } -} - -// Similar to ArraySelector, but works when end_index > start_index is not satisfied, in which -// case an array of all 0s is returned. Does not work when start_index is 0 -template ArraySelectorComplex(len) { - signal input start_index; - signal input end_index; - signal output out[len]; - - signal right_bits[len] <== RightArraySelector(len)(start_index-1); - signal left_bits[len] <== LeftArraySelector(len)(end_index); - - for (var i = 0; i < len; i++) { - out[i] <== right_bits[i] * left_bits[i]; - } - -} - -// Outputs a bit array where all bits to the right of `index` are 0, and all other bits are 1 -template LeftArraySelector(len) { - signal input index; - signal output out[len]; - - signal bits[len] <== SingleOneArray(len)(index); - var sum; - for (var i = 0; i < len; i++) { - sum = sum + bits[i]; - } - - out[len-1] <== 1 - sum; - for (var i = len-2; i >= 0; i--) { - out[i] <== out[i+1] + bits[i+1]; - } -} - -// Outputs a bit array where all bits to the left of `index` are 0, and all other bits are 1 -template RightArraySelector(len) { - signal input index; - signal output out[len]; - - signal bits[len] <== SingleOneArray(len)(index); - - out[0] <== 0; - for (var i = 1; i < len; i++) { - out[i] <== out[i-1] + bits[i-1]; - } -} - -// Similar to Decoder template from circomlib/circuits/multiplexer.circom -// Returns a bit array `out` with a 1 at index `index`, and 0s everywhere else -template SingleOneArray(len) { - signal input index; - - signal output out[len]; - signal success; - var lc = 0; - - for (var i = 0; i < len; i++) { - out[i] <-- (index == i) ? 1 : 0; - out[i] * (index-i) === 0; - lc = lc + out[i]; - } - lc ==> success; - // support array sizes up to a million. Being conservative here b/c according to Michael this template is very cheap - signal should_be_all_zeros <== GreaterEqThan(20)([index, len]); - success === 1 * (1 - should_be_all_zeros); -} - -// Given an array 'arr', returns the value at index `index` -template SelectArrayValue(len) { - signal input arr[len]; - signal input index; - signal output out; - - signal selector[len] <== SingleOneArray(len)(index); - - out <== EscalarProduct(len)(arr, selector); -} - -// Similar to Decoder template from circomlib/circuits/multiplexer.circom -// Returns a bit array `out` with a -1 at index `index`, and 0s everywhere else -template SingleNegOneArray(len) { - signal input index; - signal output out[len]; - signal success; - var lc = 0; - - for (var i = 0; i < len; i++) { - out[i] <-- (index == i) ? -1 : 0; - out[i] * (index-i) === 0; - lc = lc + out[i]; - } - lc ==> success; - // support array sizes up to a million. Being conservative here b/c according to Michael this template is very cheap - signal should_be_all_zeros <== GreaterEqThan(20)([index, len]); - success === -1 * (1 - should_be_all_zeros); -} - -// Checks that `substr` of length `substr_len` matches `str` beginning at `start_index` -// Assumes `random_challenge` is computed by the Fiat-Shamir transform -// Takes in hash of the full string as an optimization, to prevent it being hashed -// multiple times if the template is invoked on that string more than once -template CheckSubstrInclusionPoly(maxStrLen, maxSubstrLen) { - signal input str[maxStrLen]; - signal input str_hash; - signal input substr[maxSubstrLen]; - signal input substr_len; - signal input start_index; - - signal substr_hash <== HashBytesToFieldWithLen(maxSubstrLen)(substr, substr_len); - signal random_challenge <== Poseidon(4)([str_hash, substr_hash, substr_len, start_index]); - - signal challenge_powers[maxStrLen]; - challenge_powers[0] <== 1; - challenge_powers[1] <== random_challenge; - for (var i = 2; i < maxStrLen; i++) { - challenge_powers[i] <== challenge_powers[i-1] * random_challenge; - } - - signal selector_bits[maxStrLen] <== ArraySelector(maxStrLen)(start_index, start_index+substr_len); - - signal selected_str[maxStrLen]; - for (var i = 0; i < maxStrLen; i++) { - selected_str[i] <== selector_bits[i] * str[i]; - } - - signal str_poly[maxStrLen]; - for (var i = 0; i < maxStrLen; i++) { - str_poly[i] <== selected_str[i] * challenge_powers[i]; - } - - signal substr_poly[maxSubstrLen]; - for (var i = 0; i < maxSubstrLen; i++) { - substr_poly[i] <== substr[i] * challenge_powers[i]; - } - - signal str_poly_eval <== CalculateTotal(maxStrLen)(str_poly); - signal substr_poly_eval <== CalculateTotal(maxSubstrLen)(substr_poly); - - var distinguishing_value = SelectArrayValue(maxStrLen)(challenge_powers, start_index); - - str_poly_eval === distinguishing_value * substr_poly_eval; -} - -// Checks that `substr` of length `substr_len` matches `str` beginning at `start_index` -// Assumes `random_challenge` is computed by the Fiat-Shamir transform -// Takes in hash of the full string as an optimization, to prevent it being hashed -// multiple times if the template is invoked on that string more than once -// Returns '1' if the check passes, '0' otherwise -template CheckSubstrInclusionPolyBoolean(maxStrLen, maxSubstrLen) { - signal input str[maxStrLen]; - signal input str_hash; - signal input substr[maxSubstrLen]; - signal input substr_len; - signal input start_index; - signal output check_passes; - - signal substr_hash <== HashBytesToFieldWithLen(maxSubstrLen)(substr, substr_len); - signal random_challenge <== Poseidon(4)([str_hash, substr_hash, substr_len, start_index]); - - signal challenge_powers[maxStrLen]; - challenge_powers[0] <== 1; - challenge_powers[1] <== random_challenge; - for (var i = 2; i < maxStrLen; i++) { - challenge_powers[i] <== challenge_powers[i-1] * random_challenge; - } - signal selector_bits[maxStrLen] <== ArraySelector(maxStrLen)(start_index, start_index+substr_len); - - signal selected_str[maxStrLen]; - for (var i = 0; i < maxStrLen; i++) { - selected_str[i] <== selector_bits[i] * str[i]; - } - - signal str_poly[maxStrLen]; - for (var i = 0; i < maxStrLen; i++) { - str_poly[i] <== selected_str[i] * challenge_powers[i]; - } - - signal substr_poly[maxSubstrLen]; - for (var i = 0; i < maxSubstrLen; i++) { - substr_poly[i] <== substr[i] * challenge_powers[i]; - } - - signal str_poly_eval <== CalculateTotal(maxStrLen)(str_poly); - signal substr_poly_eval <== CalculateTotal(maxSubstrLen)(substr_poly); - - var distinguishing_value = SelectArrayValue(maxStrLen)(challenge_powers, start_index); - - signal right_eq <== distinguishing_value * substr_poly_eval; - check_passes <== IsEqual()([str_poly_eval, right_eq]); -} - -// Given `full_string`, `left`, and `right`, checks that full_string = left || right -// `random_challenge` is expected to be computed by the Fiat-Shamir transform -// Assumes `right_len` has been validated to be correct outside of this subcircuit -template ConcatenationCheck(maxFullStringLen, maxLeftStringLen, maxRightStringLen) { - signal input full_string[maxFullStringLen]; - signal input left[maxLeftStringLen]; - signal input right[maxRightStringLen]; - signal input left_len; - signal input right_len; - - signal left_hash <== HashBytesToFieldWithLen(maxLeftStringLen)(left, left_len); - signal right_hash <== HashBytesToFieldWithLen(maxRightStringLen)(right, right_len); - signal full_hash <== HashBytesToFieldWithLen(maxFullStringLen)(full_string, left_len+right_len); - signal random_challenge <== Poseidon(4)([left_hash, right_hash, full_hash, left_len]); - - // Enforce that all values to the right of `left_len` in `left` are 0-padding. Otherwise an attacker could place the leftmost part of `right` at the end of `left` and still have the polynomial check pass - signal left_selector[maxLeftStringLen] <== RightArraySelector(maxLeftStringLen)(left_len-1); - for (var i = 0; i < maxLeftStringLen; i++) { - left_selector[i] * left[i] === 0; - } - - - signal challenge_powers[maxFullStringLen]; - challenge_powers[0] <== 1; - challenge_powers[1] <== random_challenge; - for (var i = 2; i < maxFullStringLen; i++) { - challenge_powers[i] <== challenge_powers[i-1] * random_challenge; - } - - signal left_poly[maxLeftStringLen]; - for (var i = 0; i < maxLeftStringLen; i++) { - left_poly[i] <== left[i] * challenge_powers[i]; - } - - signal right_poly[maxRightStringLen]; - for (var i = 0; i < maxRightStringLen; i++) { - right_poly[i] <== right[i] * challenge_powers[i]; - } - - signal full_poly[maxFullStringLen]; - for (var i = 0; i < maxFullStringLen; i++) { - full_poly[i] <== full_string[i] * challenge_powers[i]; - } - - signal left_poly_eval <== CalculateTotal(maxLeftStringLen)(left_poly); - signal right_poly_eval <== CalculateTotal(maxRightStringLen)(right_poly); - signal full_poly_eval <== CalculateTotal(maxFullStringLen)(full_poly); - - var distinguishing_value = SelectArrayValue(maxFullStringLen)(challenge_powers, left_len); - - full_poly_eval === left_poly_eval + distinguishing_value * right_poly_eval; -} - -// Checks every scalar in `in` between 0 and len-1 are valid ASCII digits, i.e. are between -// 48 and 57 inclusive -template CheckAreASCIIDigits(maxNumDigits) { - signal input in[maxNumDigits]; - signal input len; - - signal selector[maxNumDigits] <== ArraySelector(maxNumDigits)(0, len); - for (var i = 0; i < maxNumDigits; i++) { - var is_less_than_max = LessThan(9)([in[i], 58]); - var is_greater_than_min = GreaterThan(9)([in[i], 47]); - var is_ascii_digit = AND()(is_less_than_max, is_greater_than_min); - (1-is_ascii_digit) * selector[i] === 0; - } -} - -// Given a string of digits in ASCII format, returns the digits represented as a single field element -// Assumes the number represented by the ASCII digits is smaller than the scalar field used by the circuit -// Does not work when maxLen = 1 -template ASCIIDigitsToField(maxLen) { - signal input digits[maxLen]; - signal input len; - signal output out; - - CheckAreASCIIDigits(maxLen)(digits, len); - // Set to 0 everywhere except len-1, which is 1 - signal index_eq[maxLen - 1]; - - // For ASCII digits ['1','2','3','4','5'], acc_shifts[0..3] is [12,123,1234] - signal acc_shifts[maxLen - 1]; - // accumulators[i] = acc_shifts[i-1] for all i < len, otherwise accumulators[i] = accumulators[i-1] - signal accumulators[maxLen]; - - signal success; - var index_eq_sum = 0; - // `s` is initally set to 1 and is 0 after len == i - var s = 1; - - accumulators[0] <== digits[0]-48; - for (var i=1; i success; - // Guarantee at most one element of index_eq is equal to 1 - success === 1; - - out <== accumulators[maxLen - 1]; -} - diff --git a/keyless/circuit/templates/helpers/base64.circom b/keyless/circuit/templates/helpers/base64.circom deleted file mode 100644 index b6793e8d6f1f1..0000000000000 --- a/keyless/circuit/templates/helpers/base64.circom +++ /dev/null @@ -1,145 +0,0 @@ -pragma circom 2.1.3; - -// File taken from https://github.com/zkemail/zk-email-verify/blob/main/packages/circuits/helpers/base64.circom - -include "circomlib/circuits/comparators.circom"; - -// http://0x80.pl/notesen/2016-01-17-sse-base64-decoding.html#vector-lookup-base -// Modified to support Base64URL format instead of Base64 -// Also accepts zero padding, which is not in the Base64/Base64URL format -template Base64URLLookup() { - signal input in; - signal output out; - - // ['A', 'Z'] - component le_Z = LessThan(8); - le_Z.in[0] <== in; - le_Z.in[1] <== 90+1; - - component ge_A = GreaterThan(8); - ge_A.in[0] <== in; - ge_A.in[1] <== 65-1; - - signal range_AZ <== ge_A.out * le_Z.out; - signal sum_AZ <== range_AZ * (in - 65); - - // ['a', 'z'] - component le_z = LessThan(8); - le_z.in[0] <== in; - le_z.in[1] <== 122+1; - - component ge_a = GreaterThan(8); - ge_a.in[0] <== in; - ge_a.in[1] <== 97-1; - - signal range_az <== ge_a.out * le_z.out; - signal sum_az <== sum_AZ + range_az * (in - 71); - - // ['0', '9'] - component le_9 = LessThan(8); - le_9.in[0] <== in; - le_9.in[1] <== 57+1; - - component ge_0 = GreaterThan(8); - ge_0.in[0] <== in; - ge_0.in[1] <== 48-1; - - signal range_09 <== ge_0.out * le_9.out; - signal sum_09 <== sum_az + range_09 * (in + 4); - - // '-' - component equal_minus = IsZero(); - equal_minus.in <== in - 45; - // https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html ascii '-' (45) - // https://base64.guru/learn/base64-characters == 62 in base64 - signal sum_minus <== sum_09 + equal_minus.out * 62; - - // '_' - component equal_underscore = IsZero(); - equal_underscore.in <== in - 95; - // https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html ascii '_' (95) - // https://base64.guru/learn/base64-characters == 63 in base64 - signal sum_underscore <== sum_minus + equal_underscore.out * 63; - - out <== sum_underscore; - //log("sum_underscore (out): ", out); - - // '=' - component equal_eqsign = IsZero(); - equal_eqsign.in <== in - 61; - - // Also decode zero padding as zero padding - component zero_padding = IsZero(); - zero_padding.in <== in; - - - //log("zero_padding.out: ", zero_padding.out); - //log("equal_eqsign.out: ", equal_eqsign.out); - //log("equal_underscore.out: ", equal_underscore.out); - //log("equal_minus.out: ", equal_minus.out); - //log("range_09: ", range_09); - //log("range_az: ", range_az); - //log("range_AZ: ", range_AZ); - //log("< end Base64URLLookup"); - - signal result <== range_AZ + range_az + range_09 + equal_minus.out + equal_underscore.out + equal_eqsign.out + zero_padding.out; - 1 === result; -} - -template Base64Decode(N) { - //var N = ((3*M)\4)+2; // TODO: Make sure this is ok - var M = 4*((N+2)\3); - signal input in[M]; - signal output out[N]; - - component bits_in[M\4][4]; - component bits_out[M\4][3]; - component translate[M\4][4]; - - var idx = 0; - for (var i = 0; i < M; i += 4) { - for (var j = 0; j < 3; j++) { - bits_out[i\4][j] = Bits2Num(8); - } - - - // log("range_AZ: ", range_AZ); - for (var j = 0; j < 4; j++) { - bits_in[i\4][j] = Num2Bits(6); - - //log(">> calling into Base64URLLookup"); - //log("translate[i\\4][j].in: ", in[i+j]); - - translate[i\4][j] = Base64URLLookup(); - translate[i\4][j].in <== in[i+j]; - translate[i\4][j].out ==> bits_in[i\4][j].in; - } - - // Do the re-packing from four 6-bit words to three 8-bit words. - for (var j = 0; j < 6; j++) { - bits_out[i\4][0].in[j+2] <== bits_in[i\4][0].out[j]; - } - bits_out[i\4][0].in[0] <== bits_in[i\4][1].out[4]; - bits_out[i\4][0].in[1] <== bits_in[i\4][1].out[5]; - - for (var j = 0; j < 4; j++) { - bits_out[i\4][1].in[j+4] <== bits_in[i\4][1].out[j]; - } - for (var j = 0; j < 4; j++) { - bits_out[i\4][1].in[j] <== bits_in[i\4][2].out[j+2]; - } - - bits_out[i\4][2].in[6] <== bits_in[i\4][2].out[0]; - bits_out[i\4][2].in[7] <== bits_in[i\4][2].out[1]; - for (var j = 0; j < 6; j++) { - bits_out[i\4][2].in[j] <== bits_in[i\4][3].out[j]; - } - - for (var j = 0; j < 3; j++) { - if (idx+j < N) { - out[idx+j] <== bits_out[i\4][j].out; - } - } - idx += 3; - } -} diff --git a/keyless/circuit/templates/helpers/hashtofield.circom b/keyless/circuit/templates/helpers/hashtofield.circom deleted file mode 100644 index ebd53322e370a..0000000000000 --- a/keyless/circuit/templates/helpers/hashtofield.circom +++ /dev/null @@ -1,208 +0,0 @@ -pragma circom 2.1.3; - -include "circomlib/circuits/poseidon.circom"; -include "circomlib/circuits/comparators.circom"; - -// Enforces that each scalar in the input array `in` will fit in a byte -template CheckAreBytes(numBytes) { - signal input in[numBytes]; - - for (var i = 0; i < numBytes; i++) { - var is_byte = LessThan(9)([in[i], 256]); - is_byte === 1; - } -} - -// Enforces that each scalar in the input array `in` will fit in a limb of size 64 -template CheckAre64BitLimbs(numLimbs) { - signal input in[numLimbs]; - - for (var i = 0; i < numLimbs; i++) { - var is_byte = LessThan(65)([in[i], 2**64]); - is_byte === 1; - } -} - -// Hashes multiple bytes to one field element using a Poseidon hash -// We hash the length of the input as well to prevent collisions -// Currently does not work with greater than 64*31=1984 bytes -// -// Warning: `numBytes` cannot be 0. -template HashBytesToFieldWithLen(numBytes) { - signal input in[numBytes]; - signal input len; - signal output hash; - - CheckAreBytes(numBytes)(in); - - var num_elems = numBytes%31 == 0 ? numBytes\31 : numBytes\31 + 1; - - signal input_packed[num_elems] <== ChunksToFieldElems(numBytes, 31, 8)(in); // Pack 31 bytes per field element - - signal input_with_len[num_elems+1]; - for (var i = 0; i < num_elems; i++) { - input_with_len[i] <== input_packed[i]; - } - input_with_len[num_elems] <== len; - - hash <== HashElemsToField(num_elems+1)(input_with_len); -} - -// Hashes multiple bytes to one field element using a Poseidon hash -// We hash the length of the input as well to prevent collisions -// Currently does not work with greater than 64*31=1984 bytes -// -// Warning: `numBytes` cannot be 0. -template HashBytesToField(numBytes) { - signal input in[numBytes]; - signal output hash; - - CheckAreBytes(numBytes)(in); - - var num_elems = numBytes%31 == 0 ? numBytes\31 : numBytes\31 + 1; - - signal input_packed[num_elems] <== ChunksToFieldElems(numBytes, 31, 8)(in); // Pack 31 bytes per field element - - hash <== HashElemsToField(num_elems)(input_packed); -} - -// Hashes multiple field elements to one using Poseidon. Works up to 64 input elements -template HashElemsToField(numElems) { - signal input in[numElems]; - signal output hash; - - if (numElems <= 16) { - hash <== Poseidon(numElems)(in); - } else if (numElems <= 32) { - signal inputs_one[16]; - for (var i = 0; i < 16; i++) { - inputs_one[i] <== in[i]; - } - signal inputs_two[numElems-16]; - for (var i = 16; i < numElems; i++) { - inputs_two[i-16] <== in[i]; - } - signal h1 <== Poseidon(16)(inputs_one); - signal h2 <== Poseidon(numElems-16)(inputs_two); - hash <== Poseidon(2)([h1, h2]); - } else if (numElems <= 48) { - signal inputs_one[16]; - for (var i = 0; i < 16; i++) { - inputs_one[i] <== in[i]; - } - signal inputs_two[16]; - for (var i = 16; i < 32; i++) { - inputs_two[i-16] <== in[i]; - } - signal inputs_three[numElems-32]; - for (var i = 32; i < numElems; i++) { - inputs_three[i-32] <== in[i]; - } - signal h1 <== Poseidon(16)(inputs_one); - signal h2 <== Poseidon(16)(inputs_two); - signal h3 <== Poseidon(numElems-32)(inputs_three); - hash <== Poseidon(3)([h1, h2, h3]); - } else if (numElems <= 64) { - signal inputs_one[16]; - for (var i = 0; i < 16; i++) { - inputs_one[i] <== in[i]; - } - signal inputs_two[16]; - for (var i = 16; i < 32; i++) { - inputs_two[i-16] <== in[i]; - } - signal inputs_three[16]; - for (var i = 32; i < 48; i++) { - inputs_three[i-32] <== in[i]; - } - signal inputs_four[numElems-48]; - for (var i = 48; i < numElems; i++) { - inputs_four[i-48] <== in[i]; - } - signal h1 <== Poseidon(16)(inputs_one); - signal h2 <== Poseidon(16)(inputs_two); - signal h3 <== Poseidon(16)(inputs_three); - signal h4 <== Poseidon(numElems-48)(inputs_four); - hash <== Poseidon(4)([h1, h2, h3, h4]); - } else { - 1 === 0; - } - -} - -// Hashes multiple 64 bit limbs to one field element using a Poseidon hash -// We hash the length of the input as well to avoid collisions -// -// Warning: `numLimbs` cannot be 0. -template Hash64BitLimbsToFieldWithLen(numLimbs) { - signal input in[numLimbs]; - signal input len; - - CheckAre64BitLimbs(numLimbs)(in); - - var num_elems = numLimbs%3 == 0 ? numLimbs\3 : numLimbs\3 + 1; - - signal input_packed[num_elems] <== ChunksToFieldElems(numLimbs, 3, 64)(in); // Pack 3 64-bit limbs per field element - - signal input_with_len[num_elems+1]; - for (var i = 0; i < num_elems; i++) { - input_with_len[i] <== input_packed[i]; - } - input_with_len[num_elems] <== len; - - signal output hash <== Poseidon(num_elems+1)(input_with_len); -} - -// Inspired by `Bits2Num` in circomlib. Packs chunks of bits into a single field element -template ChunksToFieldElem(numChunks, bitsPerChunk) { - signal input in[numChunks]; - - signal output out; - var lc1 = in[0]; - - var e2 = 2**bitsPerChunk; - for (var i = 1; i out; -} - -// Packs chunks into multiple field elements -// `inputLen` cannot be 0. -template ChunksToFieldElems(inputLen, chunksPerFieldElem, bitsPerChunk) { - signal input in[inputLen]; - var num_elems = inputLen%chunksPerFieldElem == 0 ? inputLen \ chunksPerFieldElem : (inputLen\chunksPerFieldElem) + 1; // '\' is the quotient operation - we add 1 if there are extra bits past the full chunks - signal output elems[num_elems]; - component chunks_2_field[num_elems]; - for (var i = 0; i < num_elems-1; i++) { - chunks_2_field[i] = ChunksToFieldElem(chunksPerFieldElem, bitsPerChunk); // assign circuit component - } - - // If we have an extra chunk that isn't full of bits, we truncate the Bits2NumBigEndian component size for that chunk. This is equivalent to 0 padding the end of the array - var num_extra_chunks = inputLen % chunksPerFieldElem; - if (num_extra_chunks == 0) { - num_extra_chunks = chunksPerFieldElem; // The last field element is full - chunks_2_field[num_elems-1] = ChunksToFieldElem(chunksPerFieldElem, bitsPerChunk); - } else { - chunks_2_field[num_elems-1] = ChunksToFieldElem(num_extra_chunks, bitsPerChunk); - } - - // Assign all but the last field element - for (var i = 0; i < num_elems-1; i++) { - for (var j = 0; j < chunksPerFieldElem; j++) { - var index = (i * chunksPerFieldElem) + j; - chunks_2_field[i].in[j] <== in[index]; - } - chunks_2_field[i].out ==> elems[i]; - } - - // Assign the last field element - var i = num_elems-1; - for (var j = 0; j < num_extra_chunks; j++) { - var index = (i*chunksPerFieldElem) + j; - chunks_2_field[num_elems-1].in[j] <== in[index]; - } - chunks_2_field[i].out ==> elems[i]; -} diff --git a/keyless/circuit/templates/helpers/jwt_field_parsing.circom b/keyless/circuit/templates/helpers/jwt_field_parsing.circom deleted file mode 100644 index 7cd3ccb9b993b..0000000000000 --- a/keyless/circuit/templates/helpers/jwt_field_parsing.circom +++ /dev/null @@ -1,186 +0,0 @@ -pragma circom 2.1.3; - -include "./misc.circom"; -include "./arrays.circom"; -include "./hashtofield.circom"; -include "./packing.circom"; -include "circomlib/circuits/gates.circom"; -include "circomlib/circuits/bitify.circom"; - -template ParseJWTFieldSharedLogic(maxKVPairLen, maxNameLen, maxValueLen) { - signal input field[maxKVPairLen]; // ASCII - signal input name[maxNameLen]; - signal input value[maxValueLen]; - signal input field_len; // ASCII - signal input name_len; - signal input value_index; // index of value within `field` - signal input value_len; - signal input colon_index; // index of colon within `field` - - // Enforce that end of name < colon < start of value and that field_len >= - // name_len + value_len + 1 (where the +1 is for the colon), so that the - // parts of the JWT field are in the correct order - signal colon_greater_name <== LessThan(20)([name_len, colon_index]); - colon_greater_name === 1; - signal colon_less_value <== LessThan(20)([colon_index, value_index]); - colon_less_value === 1; - signal field_len_ok <== GreaterEqThan(20)([field_len, name_len + value_len + 1]); - field_len_ok === 1; - - signal field_hash <== HashBytesToFieldWithLen(maxKVPairLen)(field, field_len); - - signal name_first_quote <== SelectArrayValue(maxKVPairLen)(field, 0); - name_first_quote === 34; // '"' - CheckSubstrInclusionPoly(maxKVPairLen, maxNameLen)(field, field_hash, name, name_len, 1); - signal name_second_quote <== SelectArrayValue(maxKVPairLen)(field, name_len+1); - name_second_quote === 34; // '"' - - signal colon <== SelectArrayValue(maxKVPairLen)(field, colon_index); - colon === 58; // ':' - - CheckSubstrInclusionPoly(maxKVPairLen, maxValueLen)(field, field_hash, value, value_len, value_index); - - // Enforce last character of `field` is comma or end brace - signal last_char <== SelectArrayValue(maxKVPairLen)(field, field_len-1); - (last_char - 44) * (last_char - 125) === 0; // ',' or '}' -} - -// Checks the given jwt key value pair has a colon in between the name and value, a comma or endbrace at the end, and only whitespace in between the name and colon, colon and value, and value and end character. Returns the name and value fields -// We did this instead of a polynomial concatenation check to avoid having to implement a multi-variable concatenation check -template ParseJWTFieldWithQuotedValue(maxKVPairLen, maxNameLen, maxValueLen) { - signal input field[maxKVPairLen]; // ASCII - signal input name[maxNameLen]; - signal input value[maxValueLen]; - signal input field_string_bodies[maxKVPairLen]; - signal input field_len; // ASCII - signal input name_len; - signal input value_index; // index of value within `field` - signal input value_len; - signal input colon_index; // index of colon within `field` - - ParseJWTFieldSharedLogic(maxKVPairLen, maxNameLen, maxValueLen)(field, name, value, field_len, name_len, value_index, value_len, colon_index); - - signal value_first_quote <== SelectArrayValue(maxKVPairLen)(field, value_index-1); - value_first_quote === 34; // '"' - signal value_second_quote <== SelectArrayValue(maxKVPairLen)(field, value_index+value_len); - value_second_quote === 34; // '"' - - - // Verify whitespace is in right places, and that only name and value are inside string bodies - signal is_whitespace[maxKVPairLen]; - for (var i = 0; i < maxKVPairLen; i++) { - is_whitespace[i] <== isWhitespace()(field[i]); - } - - signal whitespace_selector_one[maxKVPairLen] <== ArraySelectorComplex(maxKVPairLen)(name_len+2, colon_index); // Skip 2 quotes around name, stop 1 index before the colon - signal whitespace_selector_two[maxKVPairLen] <== ArraySelectorComplex(maxKVPairLen)(colon_index+1, value_index-1); // Skip 2 quotes around value, stop 1 index before the value - signal whitespace_selector_three[maxKVPairLen] <== ArraySelectorComplex(maxKVPairLen)(value_index+value_len+1, field_len-1); // Skip 2 quotes in the value, stop just before the comma/end brace - signal name_selector[maxKVPairLen] <== ArraySelector(maxKVPairLen)(1, name_len+1); - signal value_selector[maxKVPairLen] <== ArraySelector(maxKVPairLen)(value_index, value_index+value_len); - - - for (var i = 0; i < maxKVPairLen; i++) { - (whitespace_selector_one[i] + whitespace_selector_two[i] + whitespace_selector_three[i]) * (1 - is_whitespace[i]) === 0; - - // Check that only the name and value parts of the field are inside string bodies, and nothing else is - (name_selector[i] + value_selector[i]) * (1 - field_string_bodies[i]) === 0; - (1 - (name_selector[i] + value_selector[i])) * field_string_bodies[i] === 0; - } - - - -} - -template ParseJWTFieldWithUnquotedValue(maxKVPairLen, maxNameLen, maxValueLen) { - signal input field[maxKVPairLen]; // ASCII - signal input name[maxNameLen]; - signal input value[maxValueLen]; - signal input field_len; // ASCII - signal input name_len; - signal input value_index; // index of value within `field` - signal input value_len; - signal input colon_index; // index of colon within `field` - - ParseJWTFieldSharedLogic(maxKVPairLen, maxNameLen, maxValueLen)(field, name, value, field_len, name_len, value_index, value_len, colon_index); - - // Verify whitespace is in right places - signal is_whitespace[maxKVPairLen]; - for (var i = 0; i < maxKVPairLen; i++) { - is_whitespace[i] <== isWhitespace()(field[i]); - } - - signal whitespace_selector_one[maxKVPairLen] <== ArraySelectorComplex(maxKVPairLen)(name_len+2, colon_index); // Skip 2 quotes around name, stop 1 index before the colon - signal whitespace_selector_two[maxKVPairLen] <== ArraySelectorComplex(maxKVPairLen)(colon_index+1, value_index); // no quote this time, so check whitespace until the value start - signal whitespace_selector_three[maxKVPairLen] <== ArraySelectorComplex(maxKVPairLen)(value_index+value_len, field_len-1); // and directly after the value end - - for (var i = 0; i < maxKVPairLen; i++) { - (whitespace_selector_one[i] + whitespace_selector_two[i] + whitespace_selector_three[i]) * (1 - is_whitespace[i]) === 0; - } - - // Verify value does not contain comma, end brace, or quote - signal value_selector[maxKVPairLen] <== ArraySelector(maxKVPairLen)(value_index, value_index+value_len); - - for (var i = 0; i < maxKVPairLen; i++) { - var is_comma = IsEqual()([field[i], 44]); - var is_end_brace = IsEqual()([field[i], 125]); - var is_quote = IsEqual()([field[i], 34]); - value_selector[i] * (is_comma + is_end_brace + is_quote) === 0; - } -} - -template ParseEmailVerifiedField(maxKVPairLen, maxNameLen, maxValueLen) { - signal input field[maxKVPairLen]; // ASCII - signal input name[maxNameLen]; - signal input value[maxValueLen]; - signal input field_len; // ASCII - signal input name_len; - signal input value_index; // index of value within `field` - signal input value_len; - signal input colon_index; // index of colon within `field` - - - ParseJWTFieldSharedLogic(maxKVPairLen, maxNameLen, maxValueLen)(field, name, value, field_len, name_len, value_index, value_len, colon_index); - - - signal char_before_value <== SelectArrayValue(maxKVPairLen)(field, value_index-1); - signal before_is_quote <== IsEqual()([char_before_value, 34]); - signal before_is_whitespace <== isWhitespace()(char_before_value); - signal before_is_whitespace_or_quote <== OR()(before_is_quote, before_is_whitespace); - // Check the char before is either quote or whitespace, OR that it is the colon - (1 - before_is_whitespace_or_quote)*(value_index-1-colon_index) === 0; - signal char_after_value <== SelectArrayValue(maxKVPairLen)(field, value_index+value_len); - signal after_is_quote <== IsEqual()([char_after_value, 34]); - signal after_is_whitespace <== isWhitespace()(char_after_value); - // check OR(after_is_quote, after_is_whitespace) === 1. - signal after_is_whitespace_or_quote <== OR()(after_is_quote, after_is_whitespace); - // Check the char after is either quote or whitespace, OR that it is the field delimiter - (1 - after_is_whitespace_or_quote)*(field_len-1-value_index-value_len) === 0; - - // Check that field value doesn't have mismatched quotes - signal and_1 <== AND()(before_is_quote,after_is_whitespace); - signal and_2 <== AND()(before_is_whitespace,after_is_quote); - and_1 + and_2 === 0; - - - signal is_whitespace[maxKVPairLen]; - for (var i = 0; i < maxKVPairLen; i++) { - is_whitespace[i] <== isWhitespace()(field[i]); - } - - signal whitespace_selector_one[maxKVPairLen] <== ArraySelectorComplex(maxKVPairLen)(name_len+2, colon_index); // Skip 2 quotes around name, stop 1 index before the colon - signal whitespace_selector_two[maxKVPairLen] <== ArraySelectorComplex(maxKVPairLen)(colon_index+1, value_index-1); // There could potentially be quotes around the value, so we don't contstrain the character before value_index to be whitespace - signal whitespace_selector_three[maxKVPairLen] <== ArraySelectorComplex(maxKVPairLen)(value_index+value_len+1, field_len-1); // similarly to before, don't constrain character just after value end - - - signal name_selector[maxKVPairLen] <== ArraySelector(maxKVPairLen)(1, name_len+1); - signal value_selector[maxKVPairLen] <== ArraySelector(maxKVPairLen)(value_index, value_index+value_len); - - - for (var i = 0; i < maxKVPairLen; i++) { - (whitespace_selector_one[i] + whitespace_selector_two[i] + whitespace_selector_three[i]) * (1 - is_whitespace[i]) === 0; - } -} - - - - diff --git a/keyless/circuit/templates/helpers/misc.circom b/keyless/circuit/templates/helpers/misc.circom deleted file mode 100644 index 3385644889bbf..0000000000000 --- a/keyless/circuit/templates/helpers/misc.circom +++ /dev/null @@ -1,179 +0,0 @@ -pragma circom 2.1.3; - -include "./arrays.circom"; -include "./hashtofield.circom"; -include "./packing.circom"; -include "circomlib/circuits/gates.circom"; -include "circomlib/circuits/bitify.circom"; - -// Checks if character 'char' is a whitespace character. Returns 1 if so, 0 otherwise -// Assumes char is a valid ascii character. Does not check for non-ascii unicode whitespace chars. -template isWhitespace() { - signal input char; - - signal is_tab <== IsEqual()([char, 9]); // character is a tab space - - signal is_line_break_part_1 <== GreaterEqThan(8)([char, 10]); // ASCII bytes values between 10 ... - signal is_line_break_part_2 <== LessEqThan(8)([char, 13]); // ... and 13 inclusive are line break characters - signal is_line_break <== is_line_break_part_1 * is_line_break_part_2; - - signal is_space <== IsEqual()([char, 32]); // ' ' - - signal output is_whitespace <== is_tab + is_line_break + is_space; -} - -// https://github.com/TheFrozenFire/snark-jwt-verify/blob/master/circuits/calculate_total.circom -// This circuit returns the sum of the inputs. -// n must be greater than 0. -template CalculateTotal(n) { - signal input nums[n]; - signal output sum; - - signal sums[n]; - sums[0] <== nums[0]; - - for (var i=1; i < n; i++) { - sums[i] <== sums[i - 1] + nums[i]; - } - - sum <== sums[n - 1]; -} - -// Given input `in`, enforces that `in[0] === in[1]` if `bool` is 1 -template AssertEqualIfTrue() { - signal input in[2]; - signal input bool; - - (in[0]-in[1]) * bool === 0; -} - -// Enforce that if uid name is "email", the email verified field is either true or "true" -template EmailVerifiedCheck(maxEVNameLen, maxEVValueLen, maxUIDNameLen) { - signal input ev_name[maxEVNameLen]; - signal input ev_value[maxEVValueLen]; - signal input ev_value_len; - signal input uid_name[maxUIDNameLen]; - signal input uid_name_len; - signal output uid_is_email; - - var email[5] = [101, 109, 97, 105, 108]; // email - - var uid_starts_with_email_0 = IsEqual()([email[0], uid_name[0]]); - var uid_starts_with_email_1 = IsEqual()([email[1], uid_name[1]]); - var uid_starts_with_email_2 = IsEqual()([email[2], uid_name[2]]); - var uid_starts_with_email_3 = IsEqual()([email[3], uid_name[3]]); - var uid_starts_with_email_4 = IsEqual()([email[4], uid_name[4]]); - - var uid_starts_with_email = MultiAND(5)([uid_starts_with_email_0, uid_starts_with_email_1, uid_starts_with_email_2, uid_starts_with_email_3, uid_starts_with_email_4]); - - - signal uid_name_len_is_5 <== IsEqual()([uid_name_len, 5]); - uid_is_email <== AND()(uid_starts_with_email, uid_name_len_is_5); // '1' if uid_name is "email" with length 5. This guarantees uid_name is in fact "email" (with quotes) combined with the logic in `JWTFieldCheck` - - var required_ev_name[14] = [101, 109, 97, 105, 108, 95, 118, 101, 114, 105, 102, 105, 101, 100]; // email_verified - - // If uid name is "email", enforce ev_name is "email_verified" - for (var i = 0; i < 14; i++) { - AssertEqualIfTrue()([ev_name[i], required_ev_name[i]], uid_is_email); - } - - signal ev_val_len_is_4 <== IsEqual()([ev_value_len, 4]); - signal ev_val_len_is_6 <== IsEqual()([ev_value_len, 6]); - var ev_val_len_is_correct = OR()(ev_val_len_is_4, ev_val_len_is_6); - - signal not_uid_is_email <== NOT()(uid_is_email); - signal is_ok <== OR()(not_uid_is_email, ev_val_len_is_correct); - is_ok === 1; - - var required_ev_val_len_4[4] = [116, 114, 117, 101]; // true - signal check_ev_val_bool <== AND()(ev_val_len_is_4, uid_is_email); - for (var i = 0; i < 4; i ++) { - AssertEqualIfTrue()([required_ev_val_len_4[i], ev_value[i]], check_ev_val_bool); - } - - var required_ev_val_len_6[6] = [34, 116, 114, 117, 101, 34]; // "true" - signal check_ev_val_str <== AND()(ev_val_len_is_6, uid_is_email); - for (var i = 0; i < 6; i++) { - AssertEqualIfTrue()([required_ev_val_len_6[i], ev_value[i]], check_ev_val_str); - } -} - -// Given an array of ascii characters representing a JSON object, output a binary array demarquing -// input = { asdfsdf "asdf" } -// output = 000000000001111000 -template StringBodies(len) { - signal input in[len]; - signal output out[len]; - - - signal quotes[len]; - signal quote_parity[len]; - signal quote_parity_1[len]; - signal quote_parity_2[len]; - - signal backslashes[len]; - signal adjacent_backslash_parity[len]; - - quotes[0] <== IsEqual()([in[0], 34]); - quote_parity[0] <== IsEqual()([in[0], 34]); - - backslashes[0] <== IsEqual()([in[0], 92]); - adjacent_backslash_parity[0] <== IsEqual()([in[0], 92]); - - for (var i = 1; i < len; i++) { - backslashes[i] <== IsEqual()([in[i], 92]); - adjacent_backslash_parity[i] <== backslashes[i] * (1 - adjacent_backslash_parity[i-1]); - } - - for (var i = 1; i < len; i++) { - var is_quote = IsEqual()([in[i], 34]); - var prev_is_odd_backslash = adjacent_backslash_parity[i-1]; - quotes[i] <== is_quote * (1 - prev_is_odd_backslash); // 1 iff there is a non-escaped quote at this position - quote_parity_1[i] <== quotes[i] * (1 - quote_parity[i-1]); // 1 iff quotes[i] == 1 and quote_parity[i-1] == 0, else 0 - quote_parity_2[i] <== (1 - quotes[i]) * quote_parity[i-1]; // 1 iff quotes[i] == 0 and quote_party[i-1] == 1, else 0 - quote_parity[i] <== quote_parity_1[i] + quote_parity_2[i]; // Or of previous two, i.e., XOR(quotes[i], quote_parity[i-1]) - } - // input = { asdfsdf "asdf" } - // output = 000000000011111000 - // i.e., still has offset-by-one error - - out[0] <== 0; - - for (var i = 1; i < len; i++) { - out[i] <== AND()(quote_parity[i-1], quote_parity[i]); // remove offset error - } -} - - - -// Given a base64-encoded array `in`, max length `maxN`, and actual unpadded length `n`, returns -// the actual length of the decoded string -template Base64DecodedLength(maxN) { - var max_q = (3 * maxN) \ 4; - //signal input in[maxN]; - signal input n; // actual lenght - signal output decoded_len; - signal q <-- 3*n \ 4; - signal r <-- 3*n % 4; - - 3*n - 4*q - r === 0; - signal r_correct_reminder <== LessThan(2)([r, 4]); - r_correct_reminder === 1; - - // use log function to compute log(max_q) - signal q_correct_quotient <== LessThan(252)([q, max_q]); - q_correct_quotient === 1; - - // var eq = 61; - // assumes valid encoding (if last != "=" then second to last is also - // != "=") - // TODO: We don't seem to need this, as the jwt spec removes b64 padding - // see https://datatracker.ietf.org/doc/html/rfc7515#page-54 - //signal l <== SelectArrayValue(maxN)(in, n - 1); - //signal s2l <== SelectArrayValue(maxN)(in, n - 2); - //signal s_l <== IsEqual()([l, eq]); - //signal s_s2l <== IsEqual()([s2l, eq]); - //signal reducer <== -1*s_l -1*s_s2l; - //decoded_len <== q + reducer; - //log("decoded_len", decoded_len); -} diff --git a/keyless/circuit/templates/helpers/packing.circom b/keyless/circuit/templates/helpers/packing.circom deleted file mode 100644 index a34b856edd9e7..0000000000000 --- a/keyless/circuit/templates/helpers/packing.circom +++ /dev/null @@ -1,93 +0,0 @@ -pragma circom 2.1.3; - -include "./arrays.circom"; - -// Based on `Num2Bits` in circomlib -template Num2BitsBE(n) { - signal input in; - signal output out[n]; - var lc1 = 0; - - var e2 = 1; - for (var i = 0; i < n; i++) { - var idx = (n - 1) - i; - out[idx] <-- (in >> i) & 1; - out[idx] * (out[idx] - 1 ) === 0; - lc1 += out[idx] * e2; - e2 = e2 + e2; - } - lc1 === in; -} - -// Converts a bit array into a big endian integer -// Inspired by Bits2Num in https://github.com/iden3/circomlib/blob/master/circuits/bitify.circom -template Bits2NumBigEndian(n) { - signal input in[n]; - signal output out; - var lc1=0; - - var e2 = 1; - for (var i = 0; i < n; i++) { - var index = n-1-i; - lc1 += in[index] * e2; - e2 = e2 + e2; - } - lc1 ==> out; -} - - -// Converts byte array `in` into a bit array -template BytesToBits(inputLen) { - signal input in[inputLen]; - var byte_len = 8; - signal output bits[byte_len*inputLen]; - component num2bits[inputLen]; - for (var i = 0; i < inputLen; i++) { - num2bits[i] = Num2BitsBE(byte_len); - num2bits[i].in <== in[i]; - for (var j = 0; j < byte_len; j++) { - var index = (i*byte_len)+j; - num2bits[i].out[j] ==> bits[index]; - } - } -} - - -// Converts bit array 'in' into an array of field elements of size `bitsPerFieldElem` each -// Example: with inputLen=11, bitsPerFieldElem=4, [0,0,0,0, 0,0,0,1, 0,1,1,] ==> [0, 1, 6] -template BitsToFieldElems(inputLen, bitsPerFieldElem) { - signal input in[inputLen]; - var num_elems = inputLen%bitsPerFieldElem == 0 ? inputLen \ bitsPerFieldElem : (inputLen\bitsPerFieldElem) + 1; // '\' is the quotient operation - we add 1 if there are extra bits past the full bytes - signal output elems[num_elems]; - component bits_2_num_be[num_elems]; - for (var i = 0; i < num_elems-1; i++) { - bits_2_num_be[i] = Bits2NumBigEndian(bitsPerFieldElem); // assign circuit component - } - - // If we have an extra byte that isn't full of bits, we truncate the Bits2NumBigEndian component size for that byte. This is equivalent to 0 padding the end of the array - var num_extra_bits = inputLen % bitsPerFieldElem; - if (num_extra_bits == 0) { - num_extra_bits = bitsPerFieldElem; // The last field element is full - bits_2_num_be[num_elems-1] = Bits2NumBigEndian(bitsPerFieldElem); - } else { - bits_2_num_be[num_elems-1] = Bits2NumBigEndian(num_extra_bits); - } - - // Assign all but the last field element - for (var i = 0; i < num_elems-1; i++) { - for (var j = 0; j < bitsPerFieldElem; j++) { - var index = (i * bitsPerFieldElem) + j; - bits_2_num_be[i].in[j] <== in[index]; - } - bits_2_num_be[i].out ==> elems[i]; - } - - // Assign the last field element - for (var j = 0; j < num_extra_bits; j++) { - var i = num_elems-1; - var index = (i*bitsPerFieldElem) + j; - bits_2_num_be[num_elems-1].in[j] <== in[index]; - } - bits_2_num_be[num_elems-1].out ==> elems[num_elems-1]; -} - diff --git a/keyless/circuit/templates/helpers/rsa/bigint.circom b/keyless/circuit/templates/helpers/rsa/bigint.circom deleted file mode 100644 index 55fa7a453c860..0000000000000 --- a/keyless/circuit/templates/helpers/rsa/bigint.circom +++ /dev/null @@ -1,563 +0,0 @@ -pragma circom 2.0.2; - -// File copied from https://github.com/doubleblind-xyz/circom-rsa/blob/master/circuits/bigint.circom - -include "circomlib/circuits/comparators.circom"; -include "circomlib/circuits/bitify.circom"; -include "circomlib/circuits/gates.circom"; - -include "./bigint_func.circom"; - -// addition mod 2**n with carry bit -template ModSum(n) { - assert(n <= 252); - signal input a; - signal input b; - signal output sum; - signal output carry; - - component n2b = Num2Bits(n + 1); - n2b.in <== a + b; - carry <== n2b.out[n]; - sum <== a + b - carry * (1 << n); -} - -// a - b -template ModSub(n) { - assert(n <= 252); - signal input a; - signal input b; - signal output out; - signal output borrow; - component lt = LessThan(n); - lt.in[0] <== a; - lt.in[1] <== b; - borrow <== lt.out; - out <== borrow * (1 << n) + a - b; -} - -// a - b - c -// assume a - b - c + 2**n >= 0 -template ModSubThree(n) { - assert(n + 2 <= 253); - signal input a; - signal input b; - signal input c; - assert(a - b - c + (1 << n) >= 0); - signal output out; - signal output borrow; - signal b_plus_c; - b_plus_c <== b + c; - component lt = LessThan(n + 1); - lt.in[0] <== a; - lt.in[1] <== b_plus_c; - borrow <== lt.out; - out <== borrow * (1 << n) + a - b_plus_c; -} - -template ModSumThree(n) { - assert(n + 2 <= 253); - signal input a; - signal input b; - signal input c; - signal output sum; - signal output carry; - - component n2b = Num2Bits(n + 2); - n2b.in <== a + b + c; - carry <== n2b.out[n] + 2 * n2b.out[n + 1]; - sum <== a + b + c - carry * (1 << n); -} - -template ModSumFour(n) { - assert(n + 2 <= 253); - signal input a; - signal input b; - signal input c; - signal input d; - signal output sum; - signal output carry; - - component n2b = Num2Bits(n + 2); - n2b.in <== a + b + c + d; - carry <== n2b.out[n] + 2 * n2b.out[n + 1]; - sum <== a + b + c + d - carry * (1 << n); -} - -// product mod 2**n with carry -template ModProd(n) { - assert(n <= 126); - signal input a; - signal input b; - signal output prod; - signal output carry; - - component n2b = Num2Bits(2 * n); - n2b.in <== a * b; - - component b2n1 = Bits2Num(n); - component b2n2 = Bits2Num(n); - var i; - for (i = 0; i < n; i++) { - b2n1.in[i] <== n2b.out[i]; - b2n2.in[i] <== n2b.out[i + n]; - } - prod <== b2n1.out; - carry <== b2n2.out; -} - -// split a n + m bit input into two outputs -template Split(n, m) { - assert(n <= 126); - signal input in; - signal output small; - signal output big; - - small <-- in % (1 << n); - big <-- in \ (1 << n); - - component n2b_small = Num2Bits(n); - n2b_small.in <== small; - component n2b_big = Num2Bits(m); - n2b_big.in <== big; - - in === small + big * (1 << n); -} - -// split a n + m + k bit input into three outputs -template SplitThree(n, m, k) { - assert(n <= 126); - signal input in; - signal output small; - signal output medium; - signal output big; - - small <-- in % (1 << n); - medium <-- (in \ (1 << n)) % (1 << m); - big <-- in \ (1 << n + m); - - component n2b_small = Num2Bits(n); - n2b_small.in <== small; - component n2b_medium = Num2Bits(m); - n2b_medium.in <== medium; - component n2b_big = Num2Bits(k); - n2b_big.in <== big; - - in === small + medium * (1 << n) + big * (1 << n + m); -} - -// a[i], b[i] in 0... 2**n-1 -// represent a = a[0] + a[1] * 2**n + .. + a[k - 1] * 2**(n * k) -template BigAdd(n, k) { - assert(n <= 252); - signal input a[k]; - signal input b[k]; - signal output out[k + 1]; - - component unit0 = ModSum(n); - unit0.a <== a[0]; - unit0.b <== b[0]; - out[0] <== unit0.sum; - - component unit[k - 1]; - for (var i = 1; i < k; i++) { - unit[i - 1] = ModSumThree(n); - unit[i - 1].a <== a[i]; - unit[i - 1].b <== b[i]; - if (i == 1) { - unit[i - 1].c <== unit0.carry; - } else { - unit[i - 1].c <== unit[i - 2].carry; - } - out[i] <== unit[i - 1].sum; - } - out[k] <== unit[k - 2].carry; -} - -// a and b have n-bit registers -// a has ka registers, each with NONNEGATIVE ma-bit values (ma can be > n) -// b has kb registers, each with NONNEGATIVE mb-bit values (mb can be > n) -// out has ka + kb - 1 registers, each with (ma + mb + ceil(log(max(ka, kb))))-bit values -template BigMultNoCarry(n, ma, mb, ka, kb) { - assert(ma + mb <= 253); - signal input a[ka]; - signal input b[kb]; - signal output out[ka + kb - 1]; - - var prod_val[ka + kb - 1]; - for (var i = 0; i < ka + kb - 1; i++) { - prod_val[i] = 0; - } - for (var i = 0; i < ka; i++) { - for (var j = 0; j < kb; j++) { - prod_val[i + j] += a[i] * b[j]; - } - } - for (var i = 0; i < ka + kb - 1; i++) { - out[i] <-- prod_val[i]; - } - - var a_poly[ka + kb - 1]; - var b_poly[ka + kb - 1]; - var out_poly[ka + kb - 1]; - for (var i = 0; i < ka + kb - 1; i++) { - out_poly[i] = 0; - a_poly[i] = 0; - b_poly[i] = 0; - for (var j = 0; j < ka + kb - 1; j++) { - out_poly[i] = out_poly[i] + out[j] * (i ** j); - } - for (var j = 0; j < ka; j++) { - a_poly[i] = a_poly[i] + a[j] * (i ** j); - } - for (var j = 0; j < kb; j++) { - b_poly[i] = b_poly[i] + b[j] * (i ** j); - } - } - for (var i = 0; i < ka + kb - 1; i++) { - out_poly[i] === a_poly[i] * b_poly[i]; - } -} - - -// in[i] contains longs -// out[i] contains shorts -template LongToShortNoEndCarry(n, k) { - assert(n <= 126); - signal input in[k]; - signal output out[k+1]; - - var split[k][3]; - for (var i = 0; i < k; i++) { - split[i] = SplitThreeFn(in[i], n, n, n); - } - - var carry[k]; - carry[0] = 0; - out[0] <-- split[0][0]; - if (k == 1) { - out[1] <-- split[0][1]; - } - if (k > 1) { - var sumAndCarry[2] = SplitFn(split[0][1] + split[1][0], n, n); - out[1] <-- sumAndCarry[0]; - carry[1] = sumAndCarry[1]; - } - if (k == 2) { - out[2] <-- split[1][1] + split[0][2] + carry[1]; - } - if (k > 2) { - for (var i = 2; i < k; i++) { - var sumAndCarry[2] = SplitFn(split[i][0] + split[i-1][1] + split[i-2][2] + carry[i-1], n, n); - out[i] <-- sumAndCarry[0]; - carry[i] = sumAndCarry[1]; - } - out[k] <-- split[k-1][1] + split[k-2][2] + carry[k-1]; - } - - component outRangeChecks[k+1]; - for (var i = 0; i < k+1; i++) { - outRangeChecks[i] = Num2Bits(n); - outRangeChecks[i].in <== out[i]; - } - - signal runningCarry[k]; - component runningCarryRangeChecks[k]; - runningCarry[0] <-- (in[0] - out[0]) / (1 << n); - runningCarryRangeChecks[0] = Num2Bits(n + log_ceil(k)); - runningCarryRangeChecks[0].in <== runningCarry[0]; - runningCarry[0] * (1 << n) === in[0] - out[0]; - for (var i = 1; i < k; i++) { - runningCarry[i] <-- (in[i] - out[i] + runningCarry[i-1]) / (1 << n); - runningCarryRangeChecks[i] = Num2Bits(n + log_ceil(k)); - runningCarryRangeChecks[i].in <== runningCarry[i]; - runningCarry[i] * (1 << n) === in[i] - out[i] + runningCarry[i-1]; - } - runningCarry[k-1] === out[k]; -} - -template BigMult(n, k) { - signal input a[k]; - signal input b[k]; - signal output out[2 * k]; - - component mult = BigMultNoCarry(n, n, n, k, k); - for (var i = 0; i < k; i++) { - mult.a[i] <== a[i]; - mult.b[i] <== b[i]; - } - - // no carry is possible in the highest order register - component longshort = LongToShortNoEndCarry(n, 2 * k - 1); - for (var i = 0; i < 2 * k - 1; i++) { - longshort.in[i] <== mult.out[i]; - } - for (var i = 0; i < 2 * k; i++) { - out[i] <== longshort.out[i]; - } -} - -template BigLessThan(n, k){ - signal input a[k]; - signal input b[k]; - signal output out; - - component lt[k]; - component eq[k]; - for (var i = 0; i < k; i++) { - lt[i] = LessThan(n); - lt[i].in[0] <== a[i]; - lt[i].in[1] <== b[i]; - eq[i] = IsEqual(); - eq[i].in[0] <== a[i]; - eq[i].in[1] <== b[i]; - } - - // ors[i] holds (lt[k - 1] || (eq[k - 1] && lt[k - 2]) .. || (eq[k - 1] && .. && lt[i])) - // ands[i] holds (eq[k - 1] && .. && lt[i]) - // eq_ands[i] holds (eq[k - 1] && .. && eq[i]) - component ors[k - 1]; - component ands[k - 1]; - component eq_ands[k - 1]; - for (var i = k - 2; i >= 0; i--) { - ands[i] = AND(); - eq_ands[i] = AND(); - ors[i] = OR(); - - if (i == k - 2) { - ands[i].a <== eq[k - 1].out; - ands[i].b <== lt[k - 2].out; - eq_ands[i].a <== eq[k - 1].out; - eq_ands[i].b <== eq[k - 2].out; - ors[i].a <== lt[k - 1].out; - ors[i].b <== ands[i].out; - } else { - ands[i].a <== eq_ands[i + 1].out; - ands[i].b <== lt[i].out; - eq_ands[i].a <== eq_ands[i + 1].out; - eq_ands[i].b <== eq[i].out; - ors[i].a <== ors[i + 1].out; - ors[i].b <== ands[i].out; - } - } - out <== ors[0].out; -} - -template BigIsEqual(k){ - signal input in[2][k]; - signal output out; - component isEqual[k+1]; - var sum = 0; - for(var i = 0; i < k; i++){ - isEqual[i] = IsEqual(); - isEqual[i].in[0] <== in[0][i]; - isEqual[i].in[1] <== in[1][i]; - sum = sum + isEqual[i].out; - } - - isEqual[k] = IsEqual(); - isEqual[k].in[0] <== sum; - isEqual[k].in[1] <== k; - out <== isEqual[k].out; -} - -// leading register of b should be non-zero -template BigMod(n, k) { - assert(n <= 126); - signal input a[2 * k]; - signal input b[k]; - - signal output div[k + 1]; - signal output mod[k]; - - var longdiv[2][100] = long_div(n, k, k, a, b); - for (var i = 0; i < k; i++) { - div[i] <-- longdiv[0][i]; - mod[i] <-- longdiv[1][i]; - } - div[k] <-- longdiv[0][k]; - component range_checks[k + 1]; - for (var i = 0; i <= k; i++) { - range_checks[i] = Num2Bits(n); - range_checks[i].in <== div[i]; - } - - component mul = BigMult(n, k + 1); - for (var i = 0; i < k; i++) { - mul.a[i] <== div[i]; - mul.b[i] <== b[i]; - } - mul.a[k] <== div[k]; - mul.b[k] <== 0; - - component add = BigAdd(n, 2 * k + 2); - for (var i = 0; i < 2 * k; i++) { - add.a[i] <== mul.out[i]; - if (i < k) { - add.b[i] <== mod[i]; - } else { - add.b[i] <== 0; - } - } - add.a[2 * k] <== mul.out[2 * k]; - add.a[2 * k + 1] <== mul.out[2 * k + 1]; - add.b[2 * k] <== 0; - add.b[2 * k + 1] <== 0; - - for (var i = 0; i < 2 * k; i++) { - add.out[i] === a[i]; - } - add.out[2 * k] === 0; - add.out[2 * k + 1] === 0; - - component lt = BigLessThan(n, k); - for (var i = 0; i < k; i++) { - lt.a[i] <== mod[i]; - lt.b[i] <== b[i]; - } - lt.out === 1; -} - -// a[i], b[i] in 0... 2**n-1 -// represent a = a[0] + a[1] * 2**n + .. + a[k - 1] * 2**(n * k) -// assume a >= b -template BigSub(n, k) { - assert(n <= 252); - signal input a[k]; - signal input b[k]; - signal output out[k]; - signal output underflow; - - component unit0 = ModSub(n); - unit0.a <== a[0]; - unit0.b <== b[0]; - out[0] <== unit0.out; - - component unit[k - 1]; - for (var i = 1; i < k; i++) { - unit[i - 1] = ModSubThree(n); - unit[i - 1].a <== a[i]; - unit[i - 1].b <== b[i]; - if (i == 1) { - unit[i - 1].c <== unit0.borrow; - } else { - unit[i - 1].c <== unit[i - 2].borrow; - } - out[i] <== unit[i - 1].out; - } - underflow <== unit[k - 2].borrow; -} - -// calculates (a - b) % p, where a, b < p -// note: does not assume a >= b -template BigSubModP(n, k){ - assert(n <= 252); - signal input a[k]; - signal input b[k]; - signal input p[k]; - signal output out[k]; - component sub = BigSub(n, k); - for (var i = 0; i < k; i++){ - sub.a[i] <== a[i]; - sub.b[i] <== b[i]; - } - signal flag; - flag <== sub.underflow; - component add = BigAdd(n, k); - for (var i = 0; i < k; i++){ - add.a[i] <== sub.out[i]; - add.b[i] <== flag * p[i]; - } - for (var i = 0; i < k; i++){ - out[i] <== add.out[i]; - } -} - -template BigMultModP(n, k) { - assert(n <= 252); - signal input a[k]; - signal input b[k]; - signal input p[k]; - signal output out[k]; - - component big_mult = BigMult(n, k); - for (var i = 0; i < k; i++) { - big_mult.a[i] <== a[i]; - big_mult.b[i] <== b[i]; - } - component big_mod = BigMod(n, k); - for (var i = 0; i < 2 * k; i++) { - big_mod.a[i] <== big_mult.out[i]; - } - for (var i = 0; i < k; i++) { - big_mod.b[i] <== p[i]; - } - for (var i = 0; i < k; i++) { - out[i] <== big_mod.mod[i]; - } -} - -template BigModInv(n, k) { - assert(n <= 252); - signal input in[k]; - signal input p[k]; - signal output out[k]; - - // length k - var inv[100] = mod_inv(n, k, in, p); - for (var i = 0; i < k; i++) { - out[i] <-- inv[i]; - } - component range_checks[k]; - for (var i = 0; i < k; i++) { - range_checks[i] = Num2Bits(n); - range_checks[i].in <== out[i]; - } - - component mult = BigMult(n, k); - for (var i = 0; i < k; i++) { - mult.a[i] <== in[i]; - mult.b[i] <== out[i]; - } - component mod = BigMod(n, k); - for (var i = 0; i < 2 * k; i++) { - mod.a[i] <== mult.out[i]; - } - for (var i = 0; i < k; i++) { - mod.b[i] <== p[i]; - } - mod.mod[0] === 1; - for (var i = 1; i < k; i++) { - mod.mod[i] === 0; - } -} - -// in[i] contains values in the range -2^(m-1) to 2^(m-1) -// constrain that in[] as a big integer is zero -// each limbs is n bits -template CheckCarryToZero(n, m, k) { - assert(k >= 2); - - var EPSILON = 3; - - assert(m + EPSILON <= 253); - - signal input in[k]; - - signal carry[k]; - component carryRangeChecks[k]; - for (var i = 0; i < k-1; i++){ - carryRangeChecks[i] = Num2Bits(m + EPSILON - n); - if( i == 0 ){ - carry[i] <-- in[i] / (1< 10944121435919637611123202872628637544274182200208017171849102093287904247808 ? 1 : 0; -} - -function div_ceil(m, n) { - var ret = 0; - if (m % n == 0) { - ret = m \ n; - } else { - ret = m \ n + 1; - } - return ret; -} - -function log_ceil(n) { - var n_temp = n; - for (var i = 0; i < 254; i++) { - if (n_temp == 0) { - return i; - } - n_temp = n_temp \ 2; - } - return 254; -} - -function SplitFn(in, n, m) { - return [in % (1 << n), (in \ (1 << n)) % (1 << m)]; -} - -function SplitThreeFn(in, n, m, k) { - return [in % (1 << n), (in \ (1 << n)) % (1 << m), (in \ (1 << n + m)) % (1 << k)]; -} - -// m bits per overflowed register (values are potentially negative) -// n bits per properly-sized register -// in has k registers -// out has k + ceil(m/n) - 1 + 1 registers. highest-order potentially negative, -// all others are positive -// - 1 since the last register is included in the last ceil(m/n) array -// + 1 since the carries from previous registers could push you over -function getProperRepresentation(m, n, k, in) { - var ceilMN = div_ceil(m, n); - - var out[100]; // should be out[k + ceilMN] - assert(k + ceilMN < 100); - for (var i = 0; i < k; i++) { - out[i] = in[i]; - } - for (var i = k; i < 100; i++) { - out[i] = 0; - } - assert(n <= m); - for (var i = 0; i+1 < k + ceilMN; i++) { - assert((1 << m) >= out[i] && out[i] >= -(1 << m)); - var shifted_val = out[i] + (1 << m); - assert(0 <= shifted_val && shifted_val <= (1 << (m+1))); - out[i] = shifted_val & ((1 << n) - 1); - out[i+1] += (shifted_val >> n) - (1 << (m - n)); - } - - return out; -} - -// Evaluate polynomial a at point x -function poly_eval(len, a, x) { - var v = 0; - for (var i = 0; i < len; i++) { - v += a[i] * (x ** i); - } - return v; -} - -// Interpolate a degree len-1 polynomial given its evaluations at 0..len-1 -function poly_interp(len, v) { - assert(len <= 200); - var out[200]; - for (var i = 0; i < len; i++) { - out[i] = 0; - } - - // Product_{i=0..len-1} (x-i) - var full_poly[201]; - full_poly[0] = 1; - for (var i = 0; i < len; i++) { - full_poly[i+1] = 0; - for (var j = i; j >= 0; j--) { - full_poly[j+1] += full_poly[j]; - full_poly[j] *= -i; - } - } - - for (var i = 0; i < len; i++) { - var cur_v = 1; - for (var j = 0; j < len; j++) { - if (i == j) { - // do nothing - } else { - cur_v *= i-j; - } - } - cur_v = v[i] / cur_v; - - var cur_rem = full_poly[len]; - for (var j = len-1; j >= 0; j--) { - out[j] += cur_v * cur_rem; - cur_rem = full_poly[j] + i * cur_rem; - } - assert(cur_rem == 0); - } - - return out; -} - -// 1 if true, 0 if false -function long_gt(n, k, a, b) { - for (var i = k - 1; i >= 0; i--) { - if (a[i] > b[i]) { - return 1; - } - if (a[i] < b[i]) { - return 0; - } - } - return 0; -} - -// n bits per register -// a has k registers -// b has k registers -// a >= b -function long_sub(n, k, a, b) { - var diff[100]; - var borrow[100]; - for (var i = 0; i < k; i++) { - if (i == 0) { - if (a[i] >= b[i]) { - diff[i] = a[i] - b[i]; - borrow[i] = 0; - } else { - diff[i] = a[i] - b[i] + (1 << n); - borrow[i] = 1; - } - } else { - if (a[i] >= b[i] + borrow[i - 1]) { - diff[i] = a[i] - b[i] - borrow[i - 1]; - borrow[i] = 0; - } else { - diff[i] = (1 << n) + a[i] - b[i] - borrow[i - 1]; - borrow[i] = 1; - } - } - } - return diff; -} - -// a is a n-bit scalar -// b has k registers -function long_scalar_mult(n, k, a, b) { - var out[100]; - for (var i = 0; i < 100; i++) { - out[i] = 0; - } - for (var i = 0; i < k; i++) { - var temp = out[i] + (a * b[i]); - out[i] = temp % (1 << n); - out[i + 1] = out[i + 1] + temp \ (1 << n); - } - return out; -} - - -// n bits per register -// a has k + m registers -// b has k registers -// out[0] has length m + 1 -- quotient -// out[1] has length k -- remainder -// implements algorithm of https://people.eecs.berkeley.edu/~fateman/282/F%20Wright%20notes/week4.pdf -function long_div(n, k, m, a, b){ - var out[2][100]; - m += k; - while (b[k-1] == 0) { - out[1][k] = 0; - k--; - assert(k > 0); - } - m -= k; - - var remainder[200]; - for (var i = 0; i < m + k; i++) { - remainder[i] = a[i]; - } - - var mult[200]; - var dividend[200]; - for (var i = m; i >= 0; i--) { - if (i == m) { - dividend[k] = 0; - for (var j = k - 1; j >= 0; j--) { - dividend[j] = remainder[j + m]; - } - } else { - for (var j = k; j >= 0; j--) { - dividend[j] = remainder[j + i]; - } - } - - out[0][i] = short_div(n, k, dividend, b); - - var mult_shift[100] = long_scalar_mult(n, k, out[0][i], b); - var subtrahend[200]; - for (var j = 0; j < m + k; j++) { - subtrahend[j] = 0; - } - for (var j = 0; j <= k; j++) { - if (i + j < m + k) { - subtrahend[i + j] = mult_shift[j]; - } - } - remainder = long_sub(n, m + k, remainder, subtrahend); - } - for (var i = 0; i < k; i++) { - out[1][i] = remainder[i]; - } - out[1][k] = 0; - - return out; -} - -// n bits per register -// a has k + 1 registers -// b has k registers -// assumes leading digit of b is at least 2 ** (n - 1) -// 0 <= a < (2**n) * b -function short_div_norm(n, k, a, b) { - var qhat = (a[k] * (1 << n) + a[k - 1]) \ b[k - 1]; - if (qhat > (1 << n) - 1) { - qhat = (1 << n) - 1; - } - - var mult[100] = long_scalar_mult(n, k, qhat, b); - if (long_gt(n, k + 1, mult, a) == 1) { - mult = long_sub(n, k + 1, mult, b); - if (long_gt(n, k + 1, mult, a) == 1) { - return qhat - 2; - } else { - return qhat - 1; - } - } else { - return qhat; - } -} - -// n bits per register -// a has k + 1 registers -// b has k registers -// assumes leading digit of b is non-zero -// 0 <= a < (2**n) * b -function short_div(n, k, a, b) { - var scale = (1 << n) \ (1 + b[k - 1]); - - // k + 2 registers now - var norm_a[200] = long_scalar_mult(n, k + 1, scale, a); - // k + 1 registers now - var norm_b[200] = long_scalar_mult(n, k, scale, b); - - var ret; - if (norm_b[k] != 0) { - ret = short_div_norm(n, k + 1, norm_a, norm_b); - } else { - ret = short_div_norm(n, k, norm_a, norm_b); - } - return ret; -} - -// n bits per register -// a and b both have k registers -// out[0] has length 2 * k -// adapted from BigMulShortLong and LongToShortNoEndCarry2 witness computation -function prod(n, k, a, b) { - // first compute the intermediate values. taken from BigMulShortLong - var prod_val[100]; // length is 2 * k - 1 - for (var i = 0; i < 2 * k - 1; i++) { - prod_val[i] = 0; - if (i < k) { - for (var a_idx = 0; a_idx <= i; a_idx++) { - prod_val[i] = prod_val[i] + a[a_idx] * b[i - a_idx]; - } - } else { - for (var a_idx = i - k + 1; a_idx < k; a_idx++) { - prod_val[i] = prod_val[i] + a[a_idx] * b[i - a_idx]; - } - } - } - - // now do a bunch of carrying to make sure registers not overflowed. taken from LongToShortNoEndCarry2 - var out[100]; // length is 2 * k - - var split[100][3]; // first dimension has length 2 * k - 1 - for (var i = 0; i < 2 * k - 1; i++) { - split[i] = SplitThreeFn(prod_val[i], n, n, n); - } - - var carry[100]; // length is 2 * k - 1 - carry[0] = 0; - out[0] = split[0][0]; - if (2 * k - 1 > 1) { - var sumAndCarry[2] = SplitFn(split[0][1] + split[1][0], n, n); - out[1] = sumAndCarry[0]; - carry[1] = sumAndCarry[1]; - } - if (2 * k - 1 > 2) { - for (var i = 2; i < 2 * k - 1; i++) { - var sumAndCarry[2] = SplitFn(split[i][0] + split[i-1][1] + split[i-2][2] + carry[i-1], n, n); - out[i] = sumAndCarry[0]; - carry[i] = sumAndCarry[1]; - } - out[2 * k - 1] = split[2*k-2][1] + split[2*k-3][2] + carry[2*k-2]; - } - return out; -} - -// n bits per register -// a has k registers -// p has k registers -// e has k registers -// k * n <= 500 -// p is a prime -// computes a^e mod p -function mod_exp(n, k, a, p, e) { - var eBits[500]; // length is k * n - for (var i = 0; i < k; i++) { - for (var j = 0; j < n; j++) { - eBits[j + n * i] = (e[i] >> j) & 1; - } - } - - var out[100]; // length is k - for (var i = 0; i < 100; i++) { - out[i] = 0; - } - out[0] = 1; - - // repeated squaring - for (var i = k * n - 1; i >= 0; i--) { - // multiply by a if bit is 0 - if (eBits[i] == 1) { - var temp[200]; // length 2 * k - temp = prod(n, k, out, a); - var temp2[2][100]; - temp2 = long_div(n, k, k, temp, p); - out = temp2[1]; - } - - // square, unless we're at the end - if (i > 0) { - var temp[200]; // length 2 * k - temp = prod(n, k, out, out); - var temp2[2][100]; - temp2 = long_div(n, k, k, temp, p); - out = temp2[1]; - } - - } - return out; -} - -// n bits per register -// a has k registers -// p has k registers -// k * n <= 500 -// p is a prime -// if a == 0 mod p, returns 0 -// else computes inv = a^(p-2) mod p -function mod_inv(n, k, a, p) { - var isZero = 1; - for (var i = 0; i < k; i++) { - if (a[i] != 0) { - isZero = 0; - } - } - if (isZero == 1) { - var ret[100]; - for (var i = 0; i < k; i++) { - ret[i] = 0; - } - return ret; - } - - var pCopy[100]; - for (var i = 0; i < 100; i++) { - if (i < k) { - pCopy[i] = p[i]; - } else { - pCopy[i] = 0; - } - } - - var two[100]; - for (var i = 0; i < 100; i++) { - two[i] = 0; - } - two[0] = 2; - - var pMinusTwo[100]; - pMinusTwo = long_sub(n, k, pCopy, two); // length k - var out[100]; - out = mod_exp(n, k, a, pCopy, pMinusTwo); - return out; -} - -// a, b and out are all n bits k registers -function long_sub_mod_p(n, k, a, b, p){ - var gt = long_gt(n, k, a, b); - var tmp[100]; - if(gt){ - tmp = long_sub(n, k, a, b); - } - else{ - tmp = long_sub(n, k, b, a); - } - var out[2][100]; - for(var i = k;i < 2 * k; i++){ - tmp[i] = 0; - } - out = long_div(n, k, k, tmp, p); - if(gt==0){ - tmp = long_sub(n, k, p, out[1]); - } - return tmp; -} - -// a, b, p and out are all n bits k registers -function prod_mod_p(n, k, a, b, p){ - var tmp[100]; - var result[2][100]; - tmp = prod(n, k, a, b); - result = long_div(n, k, k, tmp, p); - return result[1]; -} diff --git a/keyless/circuit/templates/helpers/rsa/fp.circom b/keyless/circuit/templates/helpers/rsa/fp.circom deleted file mode 100644 index 9f0d4508960ed..0000000000000 --- a/keyless/circuit/templates/helpers/rsa/fp.circom +++ /dev/null @@ -1,86 +0,0 @@ -pragma circom 2.0.3; - -// File copied from https://github.com/doubleblind-xyz/circom-rsa/blob/master/circuits/fp.circom - -include "circomlib/circuits/bitify.circom"; - -include "./bigint.circom"; -include "./bigint_func.circom"; - -// These functions operate over values in Z/Zp for some integer p (typically, -// but not necessarily prime). Values are stored as standard bignums with k -// chunks of n bits, but intermediate values often have "overflow" bits inside -// various chunks. -// -// These Fp functions will always correctly generate witnesses mod p, but they -// do not *check* that values are normalized to < p; they only check that -// values are correct mod p. This is to save the comparison circuit. -// They *will* always check for intended results mod p (soundness), but it may -// not have a unique intermediate signal. -// -// Conversely, some templates may not be satisfiable if the input witnesses are -// not < p. This does not break completeness, as honest provers will always -// generate witnesses which are canonical (between 0 and p). - -// a * b = r mod p -// a * b - p * q - r for some q -template FpMul(n, k) { - assert(n + n + log_ceil(k) + 2 <= 252); - signal input a[k]; - signal input b[k]; - signal input p[k]; - - signal output out[k]; - - signal v_ab[2*k-1]; - for (var x = 0; x < 2*k-1; x++) { - var v_a = poly_eval(k, a, x); - var v_b = poly_eval(k, b, x); - v_ab[x] <== v_a * v_b; - } - - var ab[200] = poly_interp(2*k-1, v_ab); - // ab_proper has length 2*k - var ab_proper[200] = getProperRepresentation(n + n + log_ceil(k), n, 2*k-1, ab); - - var long_div_out[2][100] = long_div(n, k, k, ab_proper, p); - - // Since we're only computing a*b, we know that q < p will suffice, so we - // know it fits into k chunks and can do size n range checks. - signal q[k]; - component q_range_check[k]; - signal r[k]; - component r_range_check[k]; - for (var i = 0; i < k; i++) { - q[i] <-- long_div_out[0][i]; - q_range_check[i] = Num2Bits(n); - q_range_check[i].in <== q[i]; - - r[i] <-- long_div_out[1][i]; - r_range_check[i] = Num2Bits(n); - r_range_check[i].in <== r[i]; - } - - signal v_pq_r[2*k-1]; - for (var x = 0; x < 2*k-1; x++) { - var v_p = poly_eval(k, p, x); - var v_q = poly_eval(k, q, x); - var v_r = poly_eval(k, r, x); - v_pq_r[x] <== v_p * v_q + v_r; - } - - signal v_t[2*k-1]; - for (var x = 0; x < 2*k-1; x++) { - v_t[x] <== v_ab[x] - v_pq_r[x]; - } - - var t[200] = poly_interp(2*k-1, v_t); - component tCheck = CheckCarryToZero(n, n + n + log_ceil(k) + 2, 2*k-1); - for (var i = 0; i < 2*k-1; i++) { - tCheck.in[i] <== t[i]; - } - - for (var i = 0; i < k; i++) { - out[i] <== r[i]; - } -} diff --git a/keyless/circuit/templates/helpers/rsa/rsa_verify.circom b/keyless/circuit/templates/helpers/rsa/rsa_verify.circom deleted file mode 100644 index 57702d5d899bd..0000000000000 --- a/keyless/circuit/templates/helpers/rsa/rsa_verify.circom +++ /dev/null @@ -1,111 +0,0 @@ -pragma circom 2.0.0; - -// File copied and modified from https://github.com/zkp-application/circom-rsa-verify/blob/main/circuits/rsa_verify.circom, except for the `FpPow65537Mod` template. The only difference is using `FpPow65537Mod` for exponentiation instead of the tempalte provided in the original repo, as it is more efficient - -include "./fp.circom"; - -template NumToBits(n) { - signal input in; - signal output out[n]; - var lc1=0; - - var e2=1; - for (var i = 0; i> i) & 1; - out[i] * (out[i] -1 ) === 0; - lc1 += out[i] * e2; - e2 = e2+e2; - } - - lc1 === in; -} - -// Template copied from https://github.com/doubleblind-xyz/circom-rsa/blob/master/circuits/rsa.circom -template FpPow65537Mod(n, k) { - signal input base[k]; - // Exponent is hardcoded at 65537 - signal input modulus[k]; - signal output out[k]; - - component doublers[16]; - component adder = FpMul(n, k); - for (var i = 0; i < 16; i++) { - doublers[i] = FpMul(n, k); - } - - for (var j = 0; j < k; j++) { - adder.p[j] <== modulus[j]; - for (var i = 0; i < 16; i++) { - doublers[i].p[j] <== modulus[j]; - } - } - for (var j = 0; j < k; j++) { - doublers[0].a[j] <== base[j]; - doublers[0].b[j] <== base[j]; - } - for (var i = 0; i + 1 < 16; i++) { - for (var j = 0; j < k; j++) { - doublers[i + 1].a[j] <== doublers[i].out[j]; - doublers[i + 1].b[j] <== doublers[i].out[j]; - } - } - for (var j = 0; j < k; j++) { - adder.a[j] <== base[j]; - adder.b[j] <== doublers[15].out[j]; - } - for (var j = 0; j < k; j++) { - out[j] <== adder.out[j]; - } -} - - - -// Pkcs1v15 + Sha256 -// exp 65537 -template RsaVerifyPkcs1v15(w, nb) { - //signal input exp[nb]; - signal input sign[nb]; // least-significant-limb first - signal input modulus[nb]; // least-significant-limb first - - signal input hashed[4]; // least-significant-limb first - - // sign ** exp mod modulus - component pm = FpPow65537Mod(w, nb); - for (var i = 0; i < nb; i++) { - pm.base[i] <== sign[i]; - //pm.exp[i] <== exp[i]; - pm.modulus[i] <== modulus[i]; - } - - // 1. Check hashed data - // 64 * 4 = 256 bit. the first 4 numbers - for (var i = 0; i < 4; i++) { - hashed[i] === pm.out[i]; - } - - // 2. Check hash prefix and 1 byte 0x00 - // sha256/152 bit - // 0b00110000001100010011000000001101000001100000100101100000100001100100100000000001011001010000001100000100000000100000000100000101000000000000010000100000 - pm.out[4] === 217300885422736416; - pm.out[5] === 938447882527703397; - // // remain 24 bit - component num2bits_6 = NumToBits(w); - num2bits_6.in <== pm.out[6]; - var remainsBits[32] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0]; - for (var i = 0; i < 32; i++) { - num2bits_6.out[i] === remainsBits[31 - i]; - } - - // 3. Check PS and em[1] = 1. the same code like golang std lib rsa.VerifyPKCS1v15 - for (var i = 32; i < w; i++) { - num2bits_6.out[i] === 1; - } - - for (var i = 7; i < 31; i++) { - // 0b1111111111111111111111111111111111111111111111111111111111111111 - pm.out[i] === 18446744073709551615; - } - // 0b1111111111111111111111111111111111111111111111111 - pm.out[31] === 562949953421311; -} - diff --git a/keyless/circuit/templates/helpers/sha.circom b/keyless/circuit/templates/helpers/sha.circom deleted file mode 100644 index 75627e7450a21..0000000000000 --- a/keyless/circuit/templates/helpers/sha.circom +++ /dev/null @@ -1,112 +0,0 @@ -pragma circom 2.1.3; - -include "circomlib/circuits/sha256/constants.circom"; -include "circomlib/circuits/sha256/sha256compression.circom"; -include "circomlib/circuits/comparators.circom"; -include "./misc.circom"; - -// Similar to `sha256_unsafe` in https://github.com/TheFrozenFire/snark-jwt-verify/blob/master/circuits/sha256.circom -// Hashes a bit array message using SHA2_256, hashing every block up to and including `tBlock`. All blocks after `tBlock` are ignored in the output -// Expects the bit array input to be padded according to https://www.rfc-editor.org/rfc/rfc4634.html#section-4.1 up to tBlock. -template Sha2_256_prepadded_varlen(maxNumBlocks) { - signal input in[maxNumBlocks * 512]; - signal input tBlock; - - signal output out[256]; - - component ha0 = H(0); - component hb0 = H(1); - component hc0 = H(2); - component hd0 = H(3); - component he0 = H(4); - component hf0 = H(5); - component hg0 = H(6); - component hh0 = H(7); - - component sha256compression[maxNumBlocks]; - - for(var i=0; i < maxNumBlocks; i++) { - - sha256compression[i] = Sha256compression(); - - if (i==0) { - for(var k = 0; k < 32; k++) { - sha256compression[i].hin[0*32+k] <== ha0.out[k]; - sha256compression[i].hin[1*32+k] <== hb0.out[k]; - sha256compression[i].hin[2*32+k] <== hc0.out[k]; - sha256compression[i].hin[3*32+k] <== hd0.out[k]; - sha256compression[i].hin[4*32+k] <== he0.out[k]; - sha256compression[i].hin[5*32+k] <== hf0.out[k]; - sha256compression[i].hin[6*32+k] <== hg0.out[k]; - sha256compression[i].hin[7*32+k] <== hh0.out[k]; - } - } else { - for(var k = 0; k < 32; k++) { - sha256compression[i].hin[32*0+k] <== sha256compression[i-1].out[32*0+31-k]; - sha256compression[i].hin[32*1+k] <== sha256compression[i-1].out[32*1+31-k]; - sha256compression[i].hin[32*2+k] <== sha256compression[i-1].out[32*2+31-k]; - sha256compression[i].hin[32*3+k] <== sha256compression[i-1].out[32*3+31-k]; - sha256compression[i].hin[32*4+k] <== sha256compression[i-1].out[32*4+31-k]; - sha256compression[i].hin[32*5+k] <== sha256compression[i-1].out[32*5+31-k]; - sha256compression[i].hin[32*6+k] <== sha256compression[i-1].out[32*6+31-k]; - sha256compression[i].hin[32*7+k] <== sha256compression[i-1].out[32*7+31-k]; - } - } - - for (var k = 0; k < 512; k++) { - sha256compression[i].inp[k] <== in[i*512 + k]; - } - } - - // Collapse the hashing result at the terminating data block - component calcTotal[256]; - signal eqs[maxNumBlocks] <== SingleOneArray(maxNumBlocks)(tBlock); - - // For each bit of the output - for(var k = 0; k < 256; k++) { - calcTotal[k] = CalculateTotal(maxNumBlocks); - - // For each possible block - for (var i = 0; i < maxNumBlocks; i++) { - - // eqs[i] is 1 if the index matches. As such, at most one input to calcTotal is not 0. - // The bit corresponding to the terminating data block will be raised - calcTotal[k].nums[i] <== eqs[i] * sha256compression[i].out[k]; - } - - out[k] <== calcTotal[k].sum; - } -} - -// Verifies SHA2_256 input padding according to https://www.rfc-editor.org/rfc/rfc4634.html#section-4.1 -template Sha2PaddingVerify(maxInputLen) { - signal input in[maxInputLen]; // byte array - signal input num_blocks; // Number of 512-bit blocks in `in` including sha padding - signal input padding_start; // equivalent to L/8, where L is the length of the unpadded message in bits as specified in RFC4634 - signal input L_byte_encoded[8]; // 64-bit encoding of L - signal input padding_without_len[64]; // padding_without_len[0] = 1, followed by K 0s. Length K+1, max length 512 bits. Does not include the 64-bit encoding of L - - var len_bits = num_blocks * 512; - var padding_start_bits = padding_start * 8; - var K = len_bits - padding_start_bits - 1 - 64; - - // Ensure K is smallest value below 512 that satisfies above equation - signal K_is_correct <== LessThan(10)([K,512]); - K_is_correct === 1; - - signal in_hash <== HashBytesToFieldWithLen(maxInputLen)(in, num_blocks*64); - // 4.1.a - CheckSubstrInclusionPoly(maxInputLen, 64)(in, in_hash, padding_without_len, (1+K)/8, padding_start); - padding_without_len[0] === 128; // 10000000 - - // 4.1.b - for (var i = 1; i < 64; i++) { - padding_without_len[i] === 0; - } - - // 4.1.c - CheckSubstrInclusionPoly(maxInputLen, 8)(in, in_hash, L_byte_encoded, 8, padding_start+(K+1)/8); - signal L_bits[64] <== BytesToBits(8)(L_byte_encoded); - signal L_decoded <== Bits2NumBigEndian(64)(L_bits); - L_decoded === 8*padding_start; -} diff --git a/keyless/circuit/templates/main.circom b/keyless/circuit/templates/main.circom deleted file mode 100644 index 862166be2de2b..0000000000000 --- a/keyless/circuit/templates/main.circom +++ /dev/null @@ -1,28 +0,0 @@ -pragma circom 2.1.3; - -include "mainTemplate.circom"; - -component main { public [public_inputs_hash] } = identity( - 192*8, // maxJWTLen - 300, // maxJWTHeaderLen - 192*8-64, // maxJWTPayloadLen - 140, // maxAudKVPairLen - 40, // maxAudNameLen - 120, // maxAudValueLen - 140, // maxIssKVPairLen - 40, // maxIssNameLen - 120, // maxIssValueLen - 50, // maxIatKVPairLen - 10, // maxIatNameLen - 45, // maxIatValueLen - 105, // maxNonceKVPairLen - 10, // maxNonceNameLen - 100, // maxNonceValueLen - 30, // maxEVKVPairLen (email_verified field) - 20, // maxEVNameLen - 10, // maxEVValueLen - 350, // maxUIDKVPairLen - 30, // maxUIDNameLen - 330, // maxUIDValueLen - 350 // maxEFKVPairLen -); diff --git a/keyless/circuit/templates/mainTemplate.circom b/keyless/circuit/templates/mainTemplate.circom deleted file mode 100644 index 8810ec6e0f023..0000000000000 --- a/keyless/circuit/templates/mainTemplate.circom +++ /dev/null @@ -1,334 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/base64.circom"; -include "helpers/arrays.circom"; -include "helpers/misc.circom"; -include "helpers/packing.circom"; -include "helpers/hashtofield.circom"; -include "helpers/sha.circom"; -include "helpers/rsa/rsa_verify.circom"; -include "helpers/jwt_field_parsing.circom"; -include "helpers/rsa/bigint.circom"; -include "../node_modules/circomlib/circuits/poseidon.circom"; -include "../node_modules/circomlib/circuits/bitify.circom"; - -// The main Aptos Keyless circuit -template identity( - maxJWTLen, // Max byte length of the full base64 JWT with SHA2 padding - maxJWTHeaderLen, // Max byte length of the full base64 JWT header with separator - maxJWTPayloadLen, // Max byte length of the full base64 JWT payload with SHA2 padding - maxAudKVPairLen, // Max byte length of the ASCII aud field - maxAudNameLen, // Max byte length of the ASCII aud name - maxAudValueLen, // Max byte length of the ASCII aud value - maxIssKVPairLen, // Max byte length of the ASCII iss field - maxIssNameLen, // Max byte length of the ASCII iss name - maxIssValueLen, // Max byte length of the ASCII iss value - maxIatKVPairLen, // Max byte length of the ASCII iat field - maxIatNameLen, // Max byte length of the ASCII iat name - maxIatValueLen, // Max byte length of the ASCII iat value - maxNonceKVPairLen, // Max byte length of the ASCII nonce field - maxNonceNameLen, // Max byte length of the ASCII nonce name - maxNonceValueLen, // Max byte length of the ASCII nonce value - maxEVKVPairLen, // Max byte length of the ASCII email verified field - maxEVNameLen, // Max byte length of the ASCII email verified name - maxEVValueLen, // Max byte length of the ASCII email verified value - maxUIDKVPairLen, // Max byte length of the ASCII uid field - maxUIDNameLen, // Max byte length of the ASCII uid name - maxUIDValueLen, // Max byte length of the ASCII uid value - maxEFKVPairLen // Max byte length of the ASCII extra field -) { - - signal input jwt[maxJWTLen]; // maxJWTLen is in bytes. Base64 format - - signal input jwt_header_with_separator[maxJWTHeaderLen]; // jwt header + '.' - signal input jwt_payload[maxJWTPayloadLen]; - - - signal input header_len_with_separator; - signal input b64_payload_len; - - ConcatenationCheck(maxJWTLen, maxJWTHeaderLen, maxJWTPayloadLen)(jwt, jwt_header_with_separator, jwt_payload, header_len_with_separator, b64_payload_len); - - var byte_len = 8; - - // Convert jwt bytes into bits for SHA256 hashing - signal jwt_bits[byte_len*maxJWTLen] <== BytesToBits(maxJWTLen)(jwt); - - - signal input jwt_num_sha2_blocks; - signal input jwt_len_bit_encoded[8]; // 64 bit encoding of the jwt len, in bits - signal input padding_without_len[64]; // 1 followed by K 0s, where K is the smallest positive integer solution to L + 1 + K = 448, and L is the jwt length in bits. Max length is 512 bits - - Sha2PaddingVerify(maxJWTLen)(jwt, jwt_num_sha2_blocks, header_len_with_separator+b64_payload_len, jwt_len_bit_encoded, padding_without_len); - - var max_num_jwt_blocks = (maxJWTLen*8)\512; // A SHA2 block is 512 bits. '\' performs division rounding up to a whole integer - - // Compute hash of JWT - signal jwt_sha_hash[256] <== Sha2_256_prepadded_varlen(max_num_jwt_blocks)(jwt_bits, jwt_num_sha2_blocks-1); - - var dot = SelectArrayValue(maxJWTLen)(jwt, header_len_with_separator-1); - - dot === 46; // '.' - - var signature_len = 32; - var size_limbs = 64; // The size of limbs used in the big integer implementation leveraged by RSAVerify65537 - // Pack hash bits into 4 64-bit values - signal packed_jwt_hash[4] <== BitsToFieldElems(256, size_limbs)(jwt_sha_hash); // (input length, byte size of outputs) - - // Verify signature over hash of JWT using modulus input - signal input signature[signature_len]; - CheckAre64BitLimbs(signature_len)(signature); - signal input pubkey_modulus[signature_len]; - // RSA verification assumes the signature is less than the pubkey modulus - signal sig_ok <== BigLessThan(252, signature_len)(signature, pubkey_modulus); - sig_ok === 1; - - var hash_le[4]; - for (var i = 0; i < 4; i++) { - hash_le[i] = packed_jwt_hash[3-i]; - } - - RsaVerifyPkcs1v15(size_limbs, signature_len)(signature, pubkey_modulus, hash_le); - - var max_ascii_jwt_payload_len = (3*maxJWTPayloadLen)\4; //TODO: Describe constraints this puts on max payload size. This equation comes from the implementation of Base64Decode - base64 encoding is about 33% larger than the originally encoded data - signal input jwt_payload_without_sha_padding[maxJWTPayloadLen]; - signal jwt_payload_hash <== HashBytesToFieldWithLen(maxJWTPayloadLen)(jwt_payload, b64_payload_len); - - CheckSubstrInclusionPoly(maxJWTPayloadLen, maxJWTPayloadLen)(jwt_payload, jwt_payload_hash, jwt_payload_without_sha_padding, b64_payload_len, 0); // index is 0 - - log("jwt_payload_without_sha_padding: "); - signal ascii_jwt_payload[max_ascii_jwt_payload_len] <== Base64Decode(max_ascii_jwt_payload_len)(jwt_payload_without_sha_padding); - - signal ascii_payload_len <== Base64DecodedLength(maxJWTPayloadLen)(b64_payload_len); - - signal ascii_jwt_payload_hash <== HashBytesToFieldWithLen(max_ascii_jwt_payload_len)(ascii_jwt_payload, ascii_payload_len); - - - signal string_bodies[max_ascii_jwt_payload_len] <== StringBodies(max_ascii_jwt_payload_len)(ascii_jwt_payload); - - // Check aud field is in the JWT - signal input aud_field[maxAudKVPairLen]; // ASCII - signal input aud_field_string_bodies[maxAudKVPairLen]; // ASCII - signal input aud_field_len; // ASCII - signal input aud_index; // index of aud field in ASCII jwt - CheckSubstrInclusionPoly(max_ascii_jwt_payload_len, maxAudKVPairLen)(ascii_jwt_payload, ascii_jwt_payload_hash, aud_field, aud_field_len, aud_index); - CheckSubstrInclusionPoly(max_ascii_jwt_payload_len, maxAudKVPairLen)(string_bodies, ascii_jwt_payload_hash, aud_field_string_bodies, aud_field_len, aud_index); - - // Perform necessary checks on aud field - var aud_name_len = 3; - signal input aud_value_index; - signal input aud_colon_index; - signal input aud_name[maxAudNameLen]; - signal input use_aud_override; - use_aud_override * (1-use_aud_override) === 0; - - signal aud_value[maxAudValueLen]; - signal input private_aud_value[maxAudValueLen]; - signal input override_aud_value[maxAudValueLen]; - signal input private_aud_value_len; - signal input override_aud_value_len; - - var s = use_aud_override; - s * (s-1) === 0; // Ensure s = 0 or s = 1 - for (var i = 0; i < maxAudValueLen; i++) { - aud_value[i] <== (override_aud_value[i]-private_aud_value[i]) * s + private_aud_value[i]; - } - signal aud_value_len; - aud_value_len <== (override_aud_value_len-private_aud_value_len) * s + private_aud_value_len; - - ParseJWTFieldWithQuotedValue(maxAudKVPairLen, maxAudNameLen, maxAudValueLen)(aud_field, aud_name, aud_value, aud_field_string_bodies, aud_field_len, aud_name_len, aud_value_index, aud_value_len, aud_colon_index); - - // Check aud name is correct - var required_aud_name[aud_name_len] = [97, 117, 100]; // aud - for (var i = 0; i < aud_name_len; i++) { - aud_name[i] === required_aud_name[i]; - } - - // Check user id field is in the JWT - signal input uid_field[maxUIDKVPairLen]; - signal input uid_field_string_bodies[maxUIDKVPairLen]; - signal input uid_field_len; - signal input uid_index; - CheckSubstrInclusionPoly(max_ascii_jwt_payload_len, maxUIDKVPairLen)(ascii_jwt_payload, ascii_jwt_payload_hash, uid_field, uid_field_len, uid_index); - CheckSubstrInclusionPoly(max_ascii_jwt_payload_len, maxUIDKVPairLen)(string_bodies, ascii_jwt_payload_hash, uid_field_string_bodies, uid_field_len, uid_index); - - // Perform necessary checks on user id field. Some fields this might be in practice are "sub" or "email" - signal input uid_name_len; - signal input uid_value_index; - signal input uid_value_len; - signal input uid_colon_index; - signal input uid_name[maxUIDNameLen]; - signal input uid_value[maxUIDValueLen]; - - ParseJWTFieldWithQuotedValue(maxUIDKVPairLen, maxUIDNameLen, maxUIDValueLen)(uid_field, uid_name, uid_value, uid_field_string_bodies, uid_field_len, uid_name_len, uid_value_index, uid_value_len, uid_colon_index); - - // Check extra field is in the JWT - signal input extra_field[maxEFKVPairLen]; - signal input extra_field_len; - signal input extra_index; - signal input use_extra_field; - use_extra_field * (use_extra_field-1) === 0; // Ensure 0 or 1 - - signal ef_passes <== CheckSubstrInclusionPolyBoolean(max_ascii_jwt_payload_len, maxEFKVPairLen)(ascii_jwt_payload, ascii_jwt_payload_hash, extra_field, extra_field_len, extra_index); - - // Fail if use_extra_field = 1 and ef_passes = 0 - signal not_ef_passes <== NOT()(ef_passes); - signal ef_fail <== AND()(use_extra_field, not_ef_passes); - ef_fail === 0; - - // Check that ef is not inside a string body - signal ef_start_char <== SelectArrayValue(max_ascii_jwt_payload_len)(string_bodies, extra_index); - ef_start_char === 0; - - // Check email verified field - signal input ev_field[maxEVKVPairLen]; - signal input ev_field_len; - signal input ev_index; - - var ev_name_len = 14; - signal input ev_value_index; - signal input ev_value_len; - signal input ev_colon_index; - signal input ev_name[maxEVNameLen]; - signal input ev_value[maxEVValueLen]; - - // Boolean truth table for checking whether we should fail on the results of 'EmailVerifiedCheck' - // and `CheckSubstrInclusionPolyBoolean`. We must fail if the uid name is 'email', and the provided - // `ev_field` is not in the full JWT according to the substring check - // uid_is_email | ev_in_jwt | ev_fail - // 1 | 1 | 1 - // 1 | 0 | 0 - // 0 | 1 | 1 - // 0 | 0 | 1 - signal uid_is_email <== EmailVerifiedCheck(maxEVNameLen, maxEVValueLen, maxUIDNameLen)(ev_name, ev_value, ev_value_len, uid_name, uid_name_len); - signal ev_in_jwt <== CheckSubstrInclusionPolyBoolean(max_ascii_jwt_payload_len, maxEVKVPairLen)(ascii_jwt_payload, ascii_jwt_payload_hash, ev_field, ev_field_len, ev_index); - signal not_ev_in_jwt <== NOT()(ev_in_jwt); - signal ev_fail <== AND()(uid_is_email, not_ev_in_jwt); - ev_fail === 0; - - // Need custom logic here because some providers apparently do not follow the OIDC spec and put the email_verified value in quotes - ParseEmailVerifiedField(maxEVKVPairLen, maxEVNameLen, maxEVValueLen)(ev_field, ev_name, ev_value, ev_field_len, ev_name_len, ev_value_index, ev_value_len, ev_colon_index); - - // Check iss field is in the JWT - // Note that because `iss_field` is a public input, we assume the verifier will perform correctness checks on it outside of the circuit. - signal input iss_field[maxIssKVPairLen]; - signal input iss_field_string_bodies[maxIssKVPairLen]; - signal input iss_field_len; - signal input iss_index; - CheckSubstrInclusionPoly(max_ascii_jwt_payload_len, maxIssKVPairLen)(ascii_jwt_payload, ascii_jwt_payload_hash, iss_field, iss_field_len, iss_index); - CheckSubstrInclusionPoly(max_ascii_jwt_payload_len, maxIssKVPairLen)(string_bodies, ascii_jwt_payload_hash, iss_field_string_bodies, iss_field_len, iss_index); - - // Perform necessary checks on iss field - var iss_name_len = 3; // iss - signal input iss_value_index; - signal input iss_value_len; - signal input iss_colon_index; - signal input iss_name[maxIssNameLen]; - signal input iss_value[maxIssValueLen]; - - ParseJWTFieldWithQuotedValue(maxIssKVPairLen, maxIssNameLen, maxIssValueLen)(iss_field, iss_name, iss_value, iss_field_string_bodies, iss_field_len, iss_name_len, iss_value_index, iss_value_len, iss_colon_index); - - // Check name of the iss field is correct - var required_iss_name[iss_name_len] = [105, 115, 115]; // iss - for (var i = 0; i < iss_name_len; i++) { - iss_name[i] === required_iss_name[i]; - } - - // Check iat field is in the JWT - signal input iat_field[maxIatKVPairLen]; - signal input iat_field_len; - signal input iat_index; - CheckSubstrInclusionPoly(max_ascii_jwt_payload_len, maxIatKVPairLen)(ascii_jwt_payload, ascii_jwt_payload_hash, iat_field, iat_field_len, iat_index); - - // Perform necessary checks on iat field - var iat_name_len = 3; // iat - signal input iat_value_index; - signal input iat_value_len; - signal input iat_colon_index; - signal input iat_name[maxIatNameLen]; - signal input iat_value[maxIatValueLen]; - - ParseJWTFieldWithUnquotedValue(maxIatKVPairLen, maxIatNameLen, maxIatValueLen)(iat_field, iat_name, iat_value, iat_field_len, iat_name_len, iat_value_index, iat_value_len, iat_colon_index); - - // Check that iat is not inside a string body - signal iat_start_char <== SelectArrayValue(max_ascii_jwt_payload_len)(string_bodies, iat_index); - iat_start_char === 0; - - // Check name of the iat field is correct - var required_iat_name[iat_name_len] = [105, 97, 116]; // iat - for (var i = 0; i < iat_name_len; i++) { - iat_name[i] === required_iat_name[i]; - } - - signal iat_field_elem <== ASCIIDigitsToField(maxIatValueLen)(iat_value, iat_value_len); - - signal input exp_date; - signal input exp_delta; - signal jwt_not_expired <== LessThan(252)([exp_date, iat_field_elem + exp_delta]); - jwt_not_expired === 1; - - // Check nonce field is in the JWT - signal input nonce_field[maxNonceKVPairLen]; - signal input nonce_field_string_bodies[maxNonceKVPairLen]; - signal input nonce_field_len; - signal input nonce_index; - CheckSubstrInclusionPoly(max_ascii_jwt_payload_len, maxNonceKVPairLen)(ascii_jwt_payload, ascii_jwt_payload_hash, nonce_field, nonce_field_len, nonce_index); - CheckSubstrInclusionPoly(max_ascii_jwt_payload_len, maxNonceKVPairLen)(string_bodies, ascii_jwt_payload_hash, nonce_field_string_bodies, nonce_field_len, nonce_index); - - // Perform necessary checks on nonce field - var nonce_name_len = 5; // nonce - signal input nonce_value_index; - signal input nonce_value_len; - signal input nonce_colon_index; - signal input nonce_name[maxNonceNameLen]; - signal input nonce_value[maxNonceValueLen]; - - ParseJWTFieldWithQuotedValue(maxNonceKVPairLen, maxNonceNameLen, maxNonceValueLen)(nonce_field, nonce_name, nonce_value, nonce_field_string_bodies, nonce_field_len, nonce_name_len, nonce_value_index, nonce_value_len, nonce_colon_index); - - // Check name of the nonce field is correct - var required_nonce_name[nonce_name_len] = [110, 111, 110, 99, 101]; // nonce - for (var i = 0; i < nonce_name_len; i++) { - nonce_name[i] === required_nonce_name[i]; - } - - // Calculate nonce - signal input temp_pubkey[3]; // Represented as 3 elements of up to 31 bytes each to allow for pubkeys of up to 64 bytes each - signal input temp_pubkey_len; // This is public and checked by the verifier. Included in nonce hash to prevent collisions - signal input jwt_randomness; - signal computed_nonce <== Poseidon(6)([temp_pubkey[0], temp_pubkey[1], temp_pubkey[2], temp_pubkey_len, exp_date, jwt_randomness]); - log("computed nonce is: ", computed_nonce); - - // Check nonce is correct - signal nonce_field_elem <== ASCIIDigitsToField(maxNonceValueLen)(nonce_value, nonce_value_len); - - nonce_field_elem === computed_nonce; - - // Compute the address seed - signal input pepper; - signal private_aud_val_hashed <== HashBytesToFieldWithLen(maxAudValueLen)(private_aud_value, private_aud_value_len); - log("private aud val hash is: ", private_aud_val_hashed); - signal uid_value_hashed <== HashBytesToFieldWithLen(maxUIDValueLen)(uid_value, uid_value_len); - log("uid val hash is: ", uid_value_hashed); - signal uid_name_hashed <== HashBytesToFieldWithLen(maxUIDNameLen)(uid_name, uid_name_len); - log("uid name hash is: ", uid_name_hashed); - signal addr_seed <== Poseidon(4)([pepper, private_aud_val_hashed, uid_value_hashed, uid_name_hashed]); - log("addr seed is: ", addr_seed); - - // Check public inputs are correct - - signal override_aud_val_hashed <== HashBytesToFieldWithLen(maxAudValueLen)(override_aud_value, override_aud_value_len); - log("override aud val hash is: ", override_aud_val_hashed); - signal hashed_jwt_header <== HashBytesToFieldWithLen(maxJWTHeaderLen)(jwt_header_with_separator, header_len_with_separator); - log("jwt header hash is: ", hashed_jwt_header); - signal hashed_pubkey_modulus <== Hash64BitLimbsToFieldWithLen(signature_len)(pubkey_modulus, 256); // 256 bytes per signature - log("pubkey hash is: ", hashed_pubkey_modulus); - signal hashed_iss_value <== HashBytesToFieldWithLen(maxIssValueLen)(iss_value, iss_value_len); - log("iss field hash is: ", hashed_iss_value); - signal hashed_extra_field <== HashBytesToFieldWithLen(maxEFKVPairLen)(extra_field, extra_field_len); - log("extra field hash is: ", hashed_extra_field); - signal computed_public_inputs_hash <== Poseidon(14)([temp_pubkey[0], temp_pubkey[1], temp_pubkey[2], temp_pubkey_len, addr_seed, exp_date, exp_delta, hashed_iss_value, use_extra_field, hashed_extra_field, hashed_jwt_header, hashed_pubkey_modulus, override_aud_val_hashed, use_aud_override]); - log("public inputs hash is: ", computed_public_inputs_hash); - - signal input public_inputs_hash; - public_inputs_hash === computed_public_inputs_hash; -} diff --git a/keyless/circuit/templates/tests/array_selector_test.circom b/keyless/circuit/templates/tests/array_selector_test.circom deleted file mode 100644 index 0c5f9464eec53..0000000000000 --- a/keyless/circuit/templates/tests/array_selector_test.circom +++ /dev/null @@ -1,21 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template array_selector_test() { - var len = 8; - - signal input start_index; - signal input end_index; - signal input expected_out[len]; - - component array_selector = ArraySelector(len); - - array_selector.start_index <== start_index; - array_selector.end_index <== end_index; - - array_selector.out === expected_out; - -} - -component main = array_selector_test(); diff --git a/keyless/circuit/templates/tests/arrays/array_selector_complex_large_test.circom b/keyless/circuit/templates/tests/arrays/array_selector_complex_large_test.circom deleted file mode 100644 index 1a60a335eea10..0000000000000 --- a/keyless/circuit/templates/tests/arrays/array_selector_complex_large_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template array_selector_complex_test(len) { - signal input start_index; - signal input end_index; - signal input expected_output[len]; - - signal out[len] <== ArraySelectorComplex(len)(start_index, end_index); - out === expected_output; -} - -component main = array_selector_complex_test( - 2000 -); diff --git a/keyless/circuit/templates/tests/arrays/array_selector_complex_small_test.circom b/keyless/circuit/templates/tests/arrays/array_selector_complex_small_test.circom deleted file mode 100644 index 00461642a37d7..0000000000000 --- a/keyless/circuit/templates/tests/arrays/array_selector_complex_small_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template array_selector_complex_test(len) { - signal input start_index; - signal input end_index; - signal input expected_output[len]; - - signal out[len] <== ArraySelectorComplex(len)(start_index, end_index); - out === expected_output; -} - -component main = array_selector_complex_test( - 3 -); diff --git a/keyless/circuit/templates/tests/arrays/array_selector_complex_test.circom b/keyless/circuit/templates/tests/arrays/array_selector_complex_test.circom deleted file mode 100644 index 4f1deca591b40..0000000000000 --- a/keyless/circuit/templates/tests/arrays/array_selector_complex_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template array_selector_complex_test(len) { - signal input start_index; - signal input end_index; - signal input expected_output[len]; - - signal out[len] <== ArraySelectorComplex(len)(start_index, end_index); - out === expected_output; -} - -component main = array_selector_complex_test( - 8 -); diff --git a/keyless/circuit/templates/tests/arrays/array_selector_test.circom b/keyless/circuit/templates/tests/arrays/array_selector_test.circom deleted file mode 100644 index be200df729ef5..0000000000000 --- a/keyless/circuit/templates/tests/arrays/array_selector_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template array_selector_test(len) { - signal input start_index; - signal input end_index; - signal input expected_output[len]; - - signal out[len] <== ArraySelector(len)(start_index, end_index); - out === expected_output; -} - -component main = array_selector_test( - 8 -); diff --git a/keyless/circuit/templates/tests/arrays/array_selector_test_large.circom b/keyless/circuit/templates/tests/arrays/array_selector_test_large.circom deleted file mode 100644 index 85c5d771411b0..0000000000000 --- a/keyless/circuit/templates/tests/arrays/array_selector_test_large.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template array_selector_test(len) { - signal input start_index; - signal input end_index; - signal input expected_output[len]; - - signal out[len] <== ArraySelector(len)(start_index, end_index); - out === expected_output; -} - -component main = array_selector_test( - 2000 -); diff --git a/keyless/circuit/templates/tests/arrays/array_selector_test_small.circom b/keyless/circuit/templates/tests/arrays/array_selector_test_small.circom deleted file mode 100644 index 228f63bef714c..0000000000000 --- a/keyless/circuit/templates/tests/arrays/array_selector_test_small.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template array_selector_test(len) { - signal input start_index; - signal input end_index; - signal input expected_output[len]; - - signal out[len] <== ArraySelector(len)(start_index, end_index); - out === expected_output; -} - -component main = array_selector_test( - 2 -); diff --git a/keyless/circuit/templates/tests/arrays/ascii_digits_to_field_large_test.circom b/keyless/circuit/templates/tests/arrays/ascii_digits_to_field_large_test.circom deleted file mode 100644 index a9f169479de3b..0000000000000 --- a/keyless/circuit/templates/tests/arrays/ascii_digits_to_field_large_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_are_ascii_digits_test(maxLen) { - signal input digits[maxLen]; - signal input len; - signal input expected_output; - - signal out <== ASCIIDigitsToField(maxLen)(digits, len); - expected_output === out; -} - -component main = check_are_ascii_digits_test( - 2000 -); diff --git a/keyless/circuit/templates/tests/arrays/ascii_digits_to_field_small_test.circom b/keyless/circuit/templates/tests/arrays/ascii_digits_to_field_small_test.circom deleted file mode 100644 index c1ee83e5f7737..0000000000000 --- a/keyless/circuit/templates/tests/arrays/ascii_digits_to_field_small_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_are_ascii_digits_test(maxLen) { - signal input digits[maxLen]; - signal input len; - signal input expected_output; - - signal out <== ASCIIDigitsToField(maxLen)(digits, len); - expected_output === out; -} - -component main = check_are_ascii_digits_test( - 2 -); diff --git a/keyless/circuit/templates/tests/arrays/ascii_digits_to_field_test.circom b/keyless/circuit/templates/tests/arrays/ascii_digits_to_field_test.circom deleted file mode 100644 index ea53bcb013a91..0000000000000 --- a/keyless/circuit/templates/tests/arrays/ascii_digits_to_field_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_are_ascii_digits_test(maxLen) { - signal input digits[maxLen]; - signal input len; - signal input expected_output; - - signal out <== ASCIIDigitsToField(maxLen)(digits, len); - expected_output === out; -} - -component main = check_are_ascii_digits_test( - 20 -); diff --git a/keyless/circuit/templates/tests/arrays/check_are_ascii_digits_large_test.circom b/keyless/circuit/templates/tests/arrays/check_are_ascii_digits_large_test.circom deleted file mode 100644 index 35ce35a8a5351..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_are_ascii_digits_large_test.circom +++ /dev/null @@ -1,14 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_are_ascii_digits_test(maxNumDigits) { - signal input in[maxNumDigits]; - signal input len; - - CheckAreASCIIDigits(maxNumDigits)(in, len); -} - -component main = check_are_ascii_digits_test( - 2000 -); diff --git a/keyless/circuit/templates/tests/arrays/check_are_ascii_digits_max_len_test.circom b/keyless/circuit/templates/tests/arrays/check_are_ascii_digits_max_len_test.circom deleted file mode 100644 index 3454934fb9512..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_are_ascii_digits_max_len_test.circom +++ /dev/null @@ -1,14 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_are_ascii_digits_test(maxNumDigits) { - signal input in[maxNumDigits]; - signal input len; - - CheckAreASCIIDigits(maxNumDigits)(in, len); -} - -component main = check_are_ascii_digits_test( - 8 -); diff --git a/keyless/circuit/templates/tests/arrays/check_are_ascii_digits_test.circom b/keyless/circuit/templates/tests/arrays/check_are_ascii_digits_test.circom deleted file mode 100644 index 336a6a64bfa14..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_are_ascii_digits_test.circom +++ /dev/null @@ -1,14 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_are_ascii_digits_test(maxNumDigits) { - signal input in[maxNumDigits]; - signal input len; - - CheckAreASCIIDigits(maxNumDigits)(in, len); -} - -component main = check_are_ascii_digits_test( - 20 -); diff --git a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_large_test.circom b/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_large_test.circom deleted file mode 100644 index da54e2ed2d687..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_large_test.circom +++ /dev/null @@ -1,19 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_substr_inclusion_poly_boolean_test(maxStrLen, maxSubstrLen) { - signal input str[maxStrLen]; - signal input str_hash; - signal input substr[maxSubstrLen]; - signal input substr_len; - signal input start_index; - signal input expected_output; - - signal out <== CheckSubstrInclusionPolyBoolean(maxStrLen, maxSubstrLen)(str, str_hash, substr, substr_len, start_index); - expected_output === out; -} - -component main = check_substr_inclusion_poly_boolean_test( - 2000, 1000 -); diff --git a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_no_padding_test.circom b/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_no_padding_test.circom deleted file mode 100644 index 8a5cfe6f19547..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_no_padding_test.circom +++ /dev/null @@ -1,19 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_substr_inclusion_poly_boolean_test(maxStrLen, maxSubstrLen) { - signal input str[maxStrLen]; - signal input str_hash; - signal input substr[maxSubstrLen]; - signal input substr_len; - signal input start_index; - signal input expected_output; - - signal out <== CheckSubstrInclusionPolyBoolean(maxStrLen, maxSubstrLen)(str, str_hash, substr, substr_len, start_index); - expected_output === out; -} - -component main = check_substr_inclusion_poly_boolean_test( - 12, 11 -); diff --git a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_small_test.circom b/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_small_test.circom deleted file mode 100644 index 2bbb16eadbbee..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_small_test.circom +++ /dev/null @@ -1,19 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_substr_inclusion_poly_boolean_test(maxStrLen, maxSubstrLen) { - signal input str[maxStrLen]; - signal input str_hash; - signal input substr[maxSubstrLen]; - signal input substr_len; - signal input start_index; - signal input expected_output; - - signal out <== CheckSubstrInclusionPolyBoolean(maxStrLen, maxSubstrLen)(str, str_hash, substr, substr_len, start_index); - expected_output === out; -} - -component main = check_substr_inclusion_poly_boolean_test( - 100, 20 -); diff --git a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_test.circom b/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_test.circom deleted file mode 100644 index 2bbb16eadbbee..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_boolean_test.circom +++ /dev/null @@ -1,19 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_substr_inclusion_poly_boolean_test(maxStrLen, maxSubstrLen) { - signal input str[maxStrLen]; - signal input str_hash; - signal input substr[maxSubstrLen]; - signal input substr_len; - signal input start_index; - signal input expected_output; - - signal out <== CheckSubstrInclusionPolyBoolean(maxStrLen, maxSubstrLen)(str, str_hash, substr, substr_len, start_index); - expected_output === out; -} - -component main = check_substr_inclusion_poly_boolean_test( - 100, 20 -); diff --git a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_large_test.circom b/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_large_test.circom deleted file mode 100644 index d5a25bef97415..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_large_test.circom +++ /dev/null @@ -1,17 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_substr_inclusion_poly_test(maxStrLen, maxSubstrLen) { - signal input str[maxStrLen]; - signal input str_hash; - signal input substr[maxSubstrLen]; - signal input substr_len; - signal input start_index; - - CheckSubstrInclusionPoly(maxStrLen, maxSubstrLen)(str, str_hash, substr, substr_len, start_index); -} - -component main = check_substr_inclusion_poly_test( - 2000, 1000 -); diff --git a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_no_padding_test.circom b/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_no_padding_test.circom deleted file mode 100644 index 2b93f3ef863ac..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_no_padding_test.circom +++ /dev/null @@ -1,17 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_substr_inclusion_poly_test(maxStrLen, maxSubstrLen) { - signal input str[maxStrLen]; - signal input str_hash; - signal input substr[maxSubstrLen]; - signal input substr_len; - signal input start_index; - - CheckSubstrInclusionPoly(maxStrLen, maxSubstrLen)(str, str_hash, substr, substr_len, start_index); -} - -component main = check_substr_inclusion_poly_test( - 12, 11 -); diff --git a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_test.circom b/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_test.circom deleted file mode 100644 index daa35523f6cae..0000000000000 --- a/keyless/circuit/templates/tests/arrays/check_substr_inclusion_poly_test.circom +++ /dev/null @@ -1,17 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_substr_inclusion_poly_test(maxStrLen, maxSubstrLen) { - signal input str[maxStrLen]; - signal input str_hash; - signal input substr[maxSubstrLen]; - signal input substr_len; - signal input start_index; - - CheckSubstrInclusionPoly(maxStrLen, maxSubstrLen)(str, str_hash, substr, substr_len, start_index); -} - -component main = check_substr_inclusion_poly_test( - 100, 20 -); diff --git a/keyless/circuit/templates/tests/arrays/concatenation_check_large_test.circom b/keyless/circuit/templates/tests/arrays/concatenation_check_large_test.circom deleted file mode 100644 index 0a7c75a37607c..0000000000000 --- a/keyless/circuit/templates/tests/arrays/concatenation_check_large_test.circom +++ /dev/null @@ -1,18 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template concatenation_check_test(maxFullStringLen, maxLeftStringLen, maxRightStringLen) { - signal input full_string[maxFullStringLen]; - signal input left[maxLeftStringLen]; - signal input right[maxRightStringLen]; - signal input left_len; - signal input right_len; - - log("silly test string"); - ConcatenationCheck(maxFullStringLen, maxLeftStringLen, maxRightStringLen)(full_string, left, right, left_len, right_len); -} - -component main = concatenation_check_test( - 1600, 1000, 1000 -); diff --git a/keyless/circuit/templates/tests/arrays/concatenation_check_small_test.circom b/keyless/circuit/templates/tests/arrays/concatenation_check_small_test.circom deleted file mode 100644 index 70c2a6fb510e8..0000000000000 --- a/keyless/circuit/templates/tests/arrays/concatenation_check_small_test.circom +++ /dev/null @@ -1,17 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template concatenation_check_test(maxFullStringLen, maxLeftStringLen, maxRightStringLen) { - signal input full_string[maxFullStringLen]; - signal input left[maxLeftStringLen]; - signal input right[maxRightStringLen]; - signal input left_len; - signal input right_len; - - ConcatenationCheck(maxFullStringLen, maxLeftStringLen, maxRightStringLen)(full_string, left, right, left_len, right_len); -} - -component main = concatenation_check_test( - 2, 1, 1 -); diff --git a/keyless/circuit/templates/tests/arrays/concatenation_check_test.circom b/keyless/circuit/templates/tests/arrays/concatenation_check_test.circom deleted file mode 100644 index dfc25eaa84a3e..0000000000000 --- a/keyless/circuit/templates/tests/arrays/concatenation_check_test.circom +++ /dev/null @@ -1,17 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template concatenation_check_test(maxFullStringLen, maxLeftStringLen, maxRightStringLen) { - signal input full_string[maxFullStringLen]; - signal input left[maxLeftStringLen]; - signal input right[maxRightStringLen]; - signal input left_len; - signal input right_len; - - ConcatenationCheck(maxFullStringLen, maxLeftStringLen, maxRightStringLen)(full_string, left, right, left_len, right_len); -} - -component main = concatenation_check_test( - 100, 70, 70 -); diff --git a/keyless/circuit/templates/tests/arrays/left_array_selector_large_test.circom b/keyless/circuit/templates/tests/arrays/left_array_selector_large_test.circom deleted file mode 100644 index ea703bba130ce..0000000000000 --- a/keyless/circuit/templates/tests/arrays/left_array_selector_large_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template left_array_selector_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== LeftArraySelector(len)(index); - out === expected_output; -} - -component main = left_array_selector_test( - 2000 -); diff --git a/keyless/circuit/templates/tests/arrays/left_array_selector_small_test.circom b/keyless/circuit/templates/tests/arrays/left_array_selector_small_test.circom deleted file mode 100644 index 015a0db265810..0000000000000 --- a/keyless/circuit/templates/tests/arrays/left_array_selector_small_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template left_array_selector_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== LeftArraySelector(len)(index); - out === expected_output; -} - -component main = left_array_selector_test( - 1 -); diff --git a/keyless/circuit/templates/tests/arrays/left_array_selector_test.circom b/keyless/circuit/templates/tests/arrays/left_array_selector_test.circom deleted file mode 100644 index e8e9af0ab722c..0000000000000 --- a/keyless/circuit/templates/tests/arrays/left_array_selector_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template left_array_selector_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== LeftArraySelector(len)(index); - out === expected_output; -} - -component main = left_array_selector_test( - 8 -); diff --git a/keyless/circuit/templates/tests/arrays/right_array_selector_large_test.circom b/keyless/circuit/templates/tests/arrays/right_array_selector_large_test.circom deleted file mode 100644 index 057dffd47e3cc..0000000000000 --- a/keyless/circuit/templates/tests/arrays/right_array_selector_large_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template right_array_selector_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== RightArraySelector(len)(index); - out === expected_output; -} - -component main = right_array_selector_test( - 2000 -); diff --git a/keyless/circuit/templates/tests/arrays/right_array_selector_small_test.circom b/keyless/circuit/templates/tests/arrays/right_array_selector_small_test.circom deleted file mode 100644 index c893813e77370..0000000000000 --- a/keyless/circuit/templates/tests/arrays/right_array_selector_small_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template right_array_selector_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== RightArraySelector(len)(index); - out === expected_output; -} - -component main = right_array_selector_test( - 1 -); diff --git a/keyless/circuit/templates/tests/arrays/right_array_selector_test.circom b/keyless/circuit/templates/tests/arrays/right_array_selector_test.circom deleted file mode 100644 index a19534a9f7958..0000000000000 --- a/keyless/circuit/templates/tests/arrays/right_array_selector_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template right_array_selector_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== RightArraySelector(len)(index); - out === expected_output; -} - -component main = right_array_selector_test( - 8 -); diff --git a/keyless/circuit/templates/tests/arrays/select_array_value_large_test.circom b/keyless/circuit/templates/tests/arrays/select_array_value_large_test.circom deleted file mode 100644 index ff2a1b3982aaf..0000000000000 --- a/keyless/circuit/templates/tests/arrays/select_array_value_large_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template select_array_value_test(len) { - signal input array[len]; - signal input index; - signal input expected_output; - - signal out <== SelectArrayValue(len)(array, index); - out === expected_output; -} - -component main = select_array_value_test( - 2000 -); diff --git a/keyless/circuit/templates/tests/arrays/select_array_value_small_test.circom b/keyless/circuit/templates/tests/arrays/select_array_value_small_test.circom deleted file mode 100644 index 32f330e064ae7..0000000000000 --- a/keyless/circuit/templates/tests/arrays/select_array_value_small_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template select_array_value_test(len) { - signal input array[len]; - signal input index; - signal input expected_output; - - signal out <== SelectArrayValue(len)(array, index); - out === expected_output; -} - -component main = select_array_value_test( - 1 -); diff --git a/keyless/circuit/templates/tests/arrays/select_array_value_test.circom b/keyless/circuit/templates/tests/arrays/select_array_value_test.circom deleted file mode 100644 index 693380c569c9c..0000000000000 --- a/keyless/circuit/templates/tests/arrays/select_array_value_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template select_array_value_test(len) { - signal input array[len]; - signal input index; - signal input expected_output; - - signal out <== SelectArrayValue(len)(array, index); - out === expected_output; -} - -component main = select_array_value_test( - 8 -); diff --git a/keyless/circuit/templates/tests/arrays/single_neg_one_array_large_test.circom b/keyless/circuit/templates/tests/arrays/single_neg_one_array_large_test.circom deleted file mode 100644 index d535b327c0a8d..0000000000000 --- a/keyless/circuit/templates/tests/arrays/single_neg_one_array_large_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template single_neg_one_array_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== SingleNegOneArray(len)(index); - out === expected_output; -} - -component main = single_neg_one_array_test( - 2000 -); diff --git a/keyless/circuit/templates/tests/arrays/single_neg_one_array_small_test.circom b/keyless/circuit/templates/tests/arrays/single_neg_one_array_small_test.circom deleted file mode 100644 index 2fb74b2343bd7..0000000000000 --- a/keyless/circuit/templates/tests/arrays/single_neg_one_array_small_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template single_neg_one_array_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== SingleNegOneArray(len)(index); - out === expected_output; -} - -component main = single_neg_one_array_test( - 1 -); diff --git a/keyless/circuit/templates/tests/arrays/single_neg_one_array_test.circom b/keyless/circuit/templates/tests/arrays/single_neg_one_array_test.circom deleted file mode 100644 index cbd9669a48dbf..0000000000000 --- a/keyless/circuit/templates/tests/arrays/single_neg_one_array_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template single_neg_one_array_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== SingleNegOneArray(len)(index); - out === expected_output; -} - -component main = single_neg_one_array_test( - 8 -); diff --git a/keyless/circuit/templates/tests/arrays/single_one_array_large_test.circom b/keyless/circuit/templates/tests/arrays/single_one_array_large_test.circom deleted file mode 100644 index 330495f6bf873..0000000000000 --- a/keyless/circuit/templates/tests/arrays/single_one_array_large_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template single_one_array_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== SingleOneArray(len)(index); - out === expected_output; -} - -component main = single_one_array_test( - 2000 -); diff --git a/keyless/circuit/templates/tests/arrays/single_one_array_small_test.circom b/keyless/circuit/templates/tests/arrays/single_one_array_small_test.circom deleted file mode 100644 index 39a2d154c3ff5..0000000000000 --- a/keyless/circuit/templates/tests/arrays/single_one_array_small_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template single_one_array_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== SingleOneArray(len)(index); - out === expected_output; -} - -component main = single_one_array_test( - 1 -); diff --git a/keyless/circuit/templates/tests/arrays/single_one_array_test.circom b/keyless/circuit/templates/tests/arrays/single_one_array_test.circom deleted file mode 100644 index ac083c7a387b6..0000000000000 --- a/keyless/circuit/templates/tests/arrays/single_one_array_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template single_one_array_test(len) { - signal input index; - signal input expected_output[len]; - - signal out[len] <== SingleOneArray(len)(index); - out === expected_output; -} - -component main = single_one_array_test( - 8 -); diff --git a/keyless/circuit/templates/tests/base64_decode_test.circom b/keyless/circuit/templates/tests/base64_decode_test.circom deleted file mode 100644 index a40d11626c709..0000000000000 --- a/keyless/circuit/templates/tests/base64_decode_test.circom +++ /dev/null @@ -1,17 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/base64.circom"; - -template base64_decode_test(maxJWTPayloadLen) { - var max_ascii_jwt_payload_len = (3*maxJWTPayloadLen)\4; - signal input jwt_payload[maxJWTPayloadLen]; - signal input ascii_jwt_payload[max_ascii_jwt_payload_len]; - component base64decode = Base64Decode(max_ascii_jwt_payload_len); - base64decode.in <== jwt_payload; - ascii_jwt_payload === base64decode.out; - -} - -component main = base64_decode_test( - 192*8-64 // maxJWTPayloadLen -); diff --git a/keyless/circuit/templates/tests/base64_decode_test_short.circom b/keyless/circuit/templates/tests/base64_decode_test_short.circom deleted file mode 100644 index a23e0c53ec020..0000000000000 --- a/keyless/circuit/templates/tests/base64_decode_test_short.circom +++ /dev/null @@ -1,17 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/base64.circom"; - -template base64_decode_test(maxJWTPayloadLen) { - var max_ascii_jwt_payload_len = (3*maxJWTPayloadLen)\4; - signal input jwt_payload[maxJWTPayloadLen]; - signal input ascii_jwt_payload[max_ascii_jwt_payload_len]; - component base64decode = Base64Decode(max_ascii_jwt_payload_len); - base64decode.in <== jwt_payload; - ascii_jwt_payload === base64decode.out; - -} - -component main = base64_decode_test( - 4 -); diff --git a/keyless/circuit/templates/tests/base64_lookup_test.circom b/keyless/circuit/templates/tests/base64_lookup_test.circom deleted file mode 100644 index 89ab269af72b5..0000000000000 --- a/keyless/circuit/templates/tests/base64_lookup_test.circom +++ /dev/null @@ -1,15 +0,0 @@ - -pragma circom 2.1.3; - -include "helpers/base64.circom"; - -template base64_lookup_test() { - signal input in_b64_char; - signal input out_num; - component base64_url_lookup = Base64URLLookup(); - base64_url_lookup.in <== in_b64_char; - out_num === base64_url_lookup.out; - -} - -component main = base64_lookup_test(); diff --git a/keyless/circuit/templates/tests/bigint/big_less_than_test.circom b/keyless/circuit/templates/tests/bigint/big_less_than_test.circom deleted file mode 100644 index 736e813c7599c..0000000000000 --- a/keyless/circuit/templates/tests/bigint/big_less_than_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/rsa/bigint.circom"; - -template big_less_than_test() { - signal input a[32]; - signal input b[32]; - signal input expected_output; - component c1 = BigLessThan(252, 32); // mainTemplate usage - c1.a <== a; - c1.b <== b; - expected_output === c1.out; - log("hi", c1.out); -} - -component main = big_less_than_test(); diff --git a/keyless/circuit/templates/tests/check_substr_inclusion_poly_boolean_test.circom b/keyless/circuit/templates/tests/check_substr_inclusion_poly_boolean_test.circom deleted file mode 100644 index 02be2768724ae..0000000000000 --- a/keyless/circuit/templates/tests/check_substr_inclusion_poly_boolean_test.circom +++ /dev/null @@ -1,28 +0,0 @@ - - -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_substr_inclusion_poly_boolean_test() { - var max_str_len = 256; - var max_substr_len = 8; - - signal input str[max_str_len]; - signal input str_hash; - signal input substr[max_substr_len]; - signal input substr_len; - signal input start_index; - signal input check_passes; - - component check_substr_inclusion_poly_boolean = CheckSubstrInclusionPolyBoolean(max_str_len, max_substr_len); - - check_substr_inclusion_poly_boolean.str <== str; - check_substr_inclusion_poly_boolean.str_hash <== str_hash; - check_substr_inclusion_poly_boolean.substr <== substr; - check_substr_inclusion_poly_boolean.substr_len <== substr_len; - check_substr_inclusion_poly_boolean.start_index <== start_index; - check_substr_inclusion_poly_boolean.check_passes === check_passes; -} - -component main = check_substr_inclusion_poly_boolean_test(); diff --git a/keyless/circuit/templates/tests/check_substr_inclusion_poly_test.circom b/keyless/circuit/templates/tests/check_substr_inclusion_poly_test.circom deleted file mode 100644 index 6b8ef13521476..0000000000000 --- a/keyless/circuit/templates/tests/check_substr_inclusion_poly_test.circom +++ /dev/null @@ -1,25 +0,0 @@ - -pragma circom 2.1.3; - -include "helpers/arrays.circom"; - -template check_substr_inclusion_poly_test() { - var max_str_len = 256; - var max_substr_len = 8; - - signal input str[max_str_len]; - signal input str_hash; - signal input substr[max_substr_len]; - signal input substr_len; - signal input start_index; - - component check_substr_inclusion_poly = CheckSubstrInclusionPoly(max_str_len, max_substr_len); - - check_substr_inclusion_poly.str <== str; - check_substr_inclusion_poly.str_hash <== str_hash; - check_substr_inclusion_poly.substr <== substr; - check_substr_inclusion_poly.substr_len <== substr_len; - check_substr_inclusion_poly.start_index <== start_index; -} - -component main = check_substr_inclusion_poly_test(); diff --git a/keyless/circuit/templates/tests/jwt_field_parsing/parse_email_verified_field_test.circom b/keyless/circuit/templates/tests/jwt_field_parsing/parse_email_verified_field_test.circom deleted file mode 100644 index 6467f1b1d1292..0000000000000 --- a/keyless/circuit/templates/tests/jwt_field_parsing/parse_email_verified_field_test.circom +++ /dev/null @@ -1,7 +0,0 @@ - -pragma circom 2.1.3; - -include "helpers/jwt_field_parsing.circom"; - - -component main = ParseEmailVerifiedField(30, 20, 10); diff --git a/keyless/circuit/templates/tests/jwt_field_parsing/parse_quoted_test.circom b/keyless/circuit/templates/tests/jwt_field_parsing/parse_quoted_test.circom deleted file mode 100644 index da3f9b619c057..0000000000000 --- a/keyless/circuit/templates/tests/jwt_field_parsing/parse_quoted_test.circom +++ /dev/null @@ -1,6 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/jwt_field_parsing.circom"; - - -component main = ParseJWTFieldWithQuotedValue(60, 30, 30); diff --git a/keyless/circuit/templates/tests/jwt_field_parsing/parse_unquoted_test.circom b/keyless/circuit/templates/tests/jwt_field_parsing/parse_unquoted_test.circom deleted file mode 100644 index 51b5b08b1b466..0000000000000 --- a/keyless/circuit/templates/tests/jwt_field_parsing/parse_unquoted_test.circom +++ /dev/null @@ -1,6 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/jwt_field_parsing.circom"; - - -component main = ParseJWTFieldWithUnquotedValue(60, 30, 30); diff --git a/keyless/circuit/templates/tests/misc/assert_equal_if_true_test.circom b/keyless/circuit/templates/tests/misc/assert_equal_if_true_test.circom deleted file mode 100644 index ea6a917289e97..0000000000000 --- a/keyless/circuit/templates/tests/misc/assert_equal_if_true_test.circom +++ /dev/null @@ -1,7 +0,0 @@ - -pragma circom 2.1.3; - -include "helpers/misc.circom"; - - -component main = AssertEqualIfTrue(); diff --git a/keyless/circuit/templates/tests/misc/calculate_total_test.circom b/keyless/circuit/templates/tests/misc/calculate_total_test.circom deleted file mode 100644 index 4094ba2f6e771..0000000000000 --- a/keyless/circuit/templates/tests/misc/calculate_total_test.circom +++ /dev/null @@ -1,17 +0,0 @@ - -pragma circom 2.1.3; - -include "helpers/misc.circom"; - -template calculate_total_test() { - var len = 10; - signal input nums[len]; - signal input sum; - component calculate_total = CalculateTotal(len); - calculate_total.nums <== nums; - calculate_total.sum === sum; - -} - -component main = calculate_total_test( -); diff --git a/keyless/circuit/templates/tests/misc/email_verified_check_test.circom b/keyless/circuit/templates/tests/misc/email_verified_check_test.circom deleted file mode 100644 index b2e6e76242448..0000000000000 --- a/keyless/circuit/templates/tests/misc/email_verified_check_test.circom +++ /dev/null @@ -1,29 +0,0 @@ - -pragma circom 2.1.3; - -include "helpers/misc.circom"; - -template email_verified_check_test() { - var maxEVNameLen = 20; - var maxEVValueLen = 10; - var maxUIDNameLen = 30; - signal input ev_name[maxEVNameLen]; - signal input ev_value[maxEVValueLen]; - signal input ev_value_len; - signal input uid_name[maxUIDNameLen]; - signal input uid_name_len; - signal input uid_is_email; - component email_verified_check = EmailVerifiedCheck(maxEVNameLen, maxEVValueLen, maxUIDNameLen); - email_verified_check.ev_name <== ev_name; - email_verified_check.ev_value <== ev_value; - email_verified_check.ev_value_len <== ev_value_len; - email_verified_check.uid_name <== uid_name; - email_verified_check.uid_name_len <== uid_name_len; - email_verified_check.uid_is_email === uid_is_email; - -} - -component main = email_verified_check_test( -); - - diff --git a/keyless/circuit/templates/tests/misc/is_whitespace_test.circom b/keyless/circuit/templates/tests/misc/is_whitespace_test.circom deleted file mode 100644 index 1f74c192623fc..0000000000000 --- a/keyless/circuit/templates/tests/misc/is_whitespace_test.circom +++ /dev/null @@ -1,16 +0,0 @@ - -pragma circom 2.1.3; - -include "helpers/misc.circom"; - -template is_whitespace_test() { - signal input char; - signal input result; - component is_whitespace = isWhitespace(); - is_whitespace.char <== char; - is_whitespace.is_whitespace === result; - -} - -component main = is_whitespace_test( -); diff --git a/keyless/circuit/templates/tests/misc/string_bodies_test.circom b/keyless/circuit/templates/tests/misc/string_bodies_test.circom deleted file mode 100644 index 32f36df73a64d..0000000000000 --- a/keyless/circuit/templates/tests/misc/string_bodies_test.circom +++ /dev/null @@ -1,18 +0,0 @@ - - -pragma circom 2.1.3; - -include "helpers/misc.circom"; - -template string_bodies_test() { - var len = 13; - signal input in[len]; - signal input out[len]; - component string_bodies = StringBodies(len); - string_bodies.in <== in; - string_bodies.out === out; - -} - -component main = string_bodies_test( -); diff --git a/keyless/circuit/templates/tests/packing/bits2num_big_endian_test.circom b/keyless/circuit/templates/tests/packing/bits2num_big_endian_test.circom deleted file mode 100644 index 83295344f4a66..0000000000000 --- a/keyless/circuit/templates/tests/packing/bits2num_big_endian_test.circom +++ /dev/null @@ -1,21 +0,0 @@ - - -pragma circom 2.1.3; - -include "helpers/packing.circom"; - -template bits2num_big_endian_test() { - var max_bits_len = 64; - signal input bits_in[max_bits_len]; - signal input num_out; - component num2bits_be = Bits2NumBigEndian(max_bits_len); - num2bits_be.in <== bits_in; - for (var i = 0; i < max_bits_len; i++ ) { - log(num2bits_be.in[i]); - } - log("output:", num2bits_be.out); - num2bits_be.out === num_out; - -} - -component main = bits2num_big_endian_test(); diff --git a/keyless/circuit/templates/tests/packing/bits_to_field_elems_test.circom b/keyless/circuit/templates/tests/packing/bits_to_field_elems_test.circom deleted file mode 100644 index 29121a5bf36b2..0000000000000 --- a/keyless/circuit/templates/tests/packing/bits_to_field_elems_test.circom +++ /dev/null @@ -1,18 +0,0 @@ - -pragma circom 2.1.3; - -include "helpers/packing.circom"; - -template bits_to_field_elems_test() { - var max_bits_len = 256; - var bits_per_field_elem = 64; - var num_field_elems = max_bits_len%bits_per_field_elem == 0 ? max_bits_len \ bits_per_field_elem : (max_bits_len\bits_per_field_elem) + 1; // '\' is the quotient operation - we add 1 if there are extra bits past the full bytes - signal input bits_in[max_bits_len]; - signal input field_elems_out[num_field_elems]; - component bits_to_field_elems = BitsToFieldElems(max_bits_len, bits_per_field_elem); - bits_to_field_elems.in <== bits_in; - bits_to_field_elems.elems === field_elems_out; - -} - -component main = bits_to_field_elems_test(); diff --git a/keyless/circuit/templates/tests/packing/bytes_to_bits_test.circom b/keyless/circuit/templates/tests/packing/bytes_to_bits_test.circom deleted file mode 100644 index c5fc8fe6ffb6a..0000000000000 --- a/keyless/circuit/templates/tests/packing/bytes_to_bits_test.circom +++ /dev/null @@ -1,16 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/packing.circom"; - -template bytes_to_bits_test() { - var max_bytes_len = 10; - var max_bits_len = max_bytes_len * 8; - signal input bytes_in[max_bytes_len]; - signal input bits_out[max_bits_len]; - component bytes_to_bits = BytesToBits(max_bytes_len); - bytes_to_bits.in <== bytes_in; - bytes_to_bits.bits === bits_out; - -} - -component main = bytes_to_bits_test(); diff --git a/keyless/circuit/templates/tests/packing/num2bits_be_test.circom b/keyless/circuit/templates/tests/packing/num2bits_be_test.circom deleted file mode 100644 index 0f0697db94d09..0000000000000 --- a/keyless/circuit/templates/tests/packing/num2bits_be_test.circom +++ /dev/null @@ -1,16 +0,0 @@ - -pragma circom 2.1.3; - -include "helpers/packing.circom"; - -template num2bits_be_test() { - var max_bits_len = 8; - signal input num_in; - signal input bits_out[max_bits_len]; - component num2bits_be = Num2BitsBE(max_bits_len); - num2bits_be.in <== num_in; - num2bits_be.out === bits_out; - -} - -component main = num2bits_be_test(); diff --git a/keyless/circuit/templates/tests/rsa_verify_test.circom b/keyless/circuit/templates/tests/rsa_verify_test.circom deleted file mode 100644 index d862e04de832f..0000000000000 --- a/keyless/circuit/templates/tests/rsa_verify_test.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/rsa/rsa_verify.circom"; - -component main = RsaVerifyPkcs1v15(64, 32); diff --git a/keyless/circuit/templates/tests/sha2_padding_verify_test.circom b/keyless/circuit/templates/tests/sha2_padding_verify_test.circom deleted file mode 100644 index c14580f11945f..0000000000000 --- a/keyless/circuit/templates/tests/sha2_padding_verify_test.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/sha.circom"; - -component main = Sha2PaddingVerify(256); // 4 blocks diff --git a/keyless/circuit/templates/tests/sha_test.circom b/keyless/circuit/templates/tests/sha_test.circom deleted file mode 100644 index 6dae907e73cb0..0000000000000 --- a/keyless/circuit/templates/tests/sha_test.circom +++ /dev/null @@ -1,15 +0,0 @@ -pragma circom 2.1.3; - -include "helpers/sha.circom"; - -template sha_test(max_num_blocks) { - signal input padded_input_bits[max_num_blocks * 512]; - signal input input_bit_len; - signal input expected_digest_bits[256]; - component c1 = Sha2_256_prepadded_varlen(max_num_blocks); - c1.in <== padded_input_bits; - c1.tBlock <== (input_bit_len / 512) - 1; - expected_digest_bits === c1.out; -} - -component main = sha_test(4); diff --git a/keyless/circuit/templates/update_ctags.sh b/keyless/circuit/templates/update_ctags.sh deleted file mode 100755 index 1aaaa73a2a752..0000000000000 --- a/keyless/circuit/templates/update_ctags.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -find . -name "*.circom" | ctags --language-force=C -L- diff --git a/keyless/circuit/tools/create-proofs-for-testing.sh b/keyless/circuit/tools/create-proofs-for-testing.sh deleted file mode 100755 index fda40dec8a689..0000000000000 --- a/keyless/circuit/tools/create-proofs-for-testing.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/bash - -# -# TODO: update `create-proofs-for-testing.sh` to match the latest circuit, then provide instructions. -# - -set -e - -scriptdir="$(cd "$(dirname "$0")" >/dev/null 2>&1 && pwd)" -repodir=$scriptdir - -echo "Executing from directory: $scriptdir" - -print_usage() { -cat < [] - -Creates proofs for the inputs generated by the keyless-circuit's input_gen.py -script. We use these proofs to test our Rust verifier. - -Uses as the path to the prover key. - -If is --local then uses the current repo rather than -cloning a remote branch inside $scriptdir/tmp/keyless-circuit-. - -Proofs are stored in which defaults to the root of the repository (i.e., $repodir) -DONE -} - -pushd() { - command pushd "$@" > /dev/null -} - -popd() { - command popd "$@" > /dev/null -} - -proofgen() { - branch=$1 - prover_key=$2 - outdir=$3 - - if [ ! -f $prover_key ]; then - echo "$prover_key is not a file (may be a directory?)" - exit 1 - fi - - prover_key=`realpath $prover_key` - - echo - echo "Using proving key from $prover_key" - - tmpdir=tmp - mkdir -p $tmpdir - pushd $tmpdir/ - { - if [ $branch == "--local" ]; then - echo - echo "Using current repo in $repodir" - keylessrepo=$repodir - else - keylessrepo=aptos-keyless-circuit-$(echo $branch | tr / -) - echo - echo "Cloning or updating aptos-keyless-circuit:$branch in $keylessrepo..." - if [ -d $keylessrepo ]; then - echo "Looks like repo is cloned. Updating..." - pushd $keylessrepo; git checkout $branch; popd - else - echo "Cloning..." - git clone git@github.com:aptos-labs/aptos-keyless-circuit $keylessrepo - pushd $keylessrepo; git checkout $branch; popd - fi - fi - pushd $keylessrepo - { - echo - echo "Creating python3 virtual env w/ deps..." - virtualenv ig - source ./ig/bin/activate - - pip3 install pyjwt pycryptodome cryptography - - pushd templates/ - { - echo - echo "(Re)compiling circuit. This will take several seconds..." - circom -l . main.circom --r1cs --wasm --sym - } - popd - - echo - echo "Running input_gen.py..." - touch input.json - python3 input_gen.py - pushd templates/main_js - { - echo - echo "Generating witness..." - node generate_witness.js main.wasm ../../input.json witness.wtns - } - popd - - echo - echo "Generating proof. Should take around 30 seconds..." - rm -f $outdir/proof.json - rm -f $outdir/public.json - snarkjs groth16 prove $prover_key templates/main_js/witness.wtns $outdir/proof.json $outdir/public.json - - echo - echo "Done. Find the {input,proof,public}.json output files in `pwd`" - } - popd - } - popd -} - -if [ "$#" -lt 2 ]; then - print_usage - exit 1 -fi - -outdir=${3:-$repodir} -mkdir -p $outdir -pushd $repodir/ - proofgen "$1" "$2" "$outdir" -popd diff --git a/keyless/circuit/tools/input_gen.py b/keyless/circuit/tools/input_gen.py deleted file mode 100755 index df5cbc471b922..0000000000000 --- a/keyless/circuit/tools/input_gen.py +++ /dev/null @@ -1,618 +0,0 @@ -#!/usr/bin/env python3 - -# WARNING: This code is guaranteed to work only for the hardcoded JWT present, and is meant only to be used to provide a quick and easy way to run the full Keyless circuit. Detailed unit tests can be found in `circuit/src`. - -import json -import os -from typing import Any - -import jwt -from Crypto.Util.number import bytes_to_long -from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.hazmat.backends import default_backend as crypto_default_backend -import base64 -from Crypto.PublicKey import RSA -from Crypto.Signature.pkcs1_15 import PKCS115_SigScheme -from Crypto.Hash import SHA256 -import Crypto -import pprint - -def calc_string_bodies(string): - string_bodies = [0] * len(string) - string_bodies[1] = int(string[0] == '"') - - for i in range(2,len(string)): - if not string_bodies[i-2] and string[i-1] == '"' and string[i-2] != '\\': - string_bodies[i] = 1 - elif string_bodies[i-1] and string[i] == '"' and string[i-1] != '\\': - string_bodies[i] = 0 - else: - string_bodies[i] = string_bodies[i-1] - return string_bodies - -# Returns JSON array of bytes representing the input `string`, 0 padded to `maxLen` -def pad_string_new(string, maxLen, n="", use_ord=False): - if use_ord: - result = [ord(c) for c in string] - else: - result = [b for b in bytes(string, 'utf-8')] - - # pad to maxLen - string_to_pad = maxLen - len(result) - for i in range(string_to_pad): - result.append(0) - - if "family_name" in string: - print("family_name") - - result = json.dumps([str(x) for x in result], separators=(",", ":")) - print(">>>N>", f"{n} '{string}'", f"'{result}'") - if n: - print("") # f"len({n}): {len(result)}") - return result - - -# Returns JSON array of bytes representing the input `string`, 0 padded to `maxLen` -def pad_string(string, maxLen, n="", use_ord=True): - string_len = len(string) - string_to_pad = maxLen - string_len - - result = "[" - for c in string: - if use_ord: - result = result + '"' + str(ord(c)) + '",' - else: - result = result + '"' + str(c) + '",' - - for i in range(string_to_pad): - result = result + '"' + '0' + '",' - - result = result[:-1] # remove last unnecessary ',' - result += "]" - print(">>>O>", f"{n} '{string}'", f"'{result}'") - return result - -def format_output(dictionary): - res = "{" - for key in dictionary: - res = res + key + " : " + str(dictionary[key]) + "," - res = res[:-1] + "}" - return res - - -MAX = 2048 -BASE = 64 - - -def long_to_limbs(n): - '''Limbs are in l-endian.''' - limbs = [] - for i in range(int(MAX / BASE)): # split into 32 64-bit limbs - idx = i * BASE - - limbs.append((n >> idx) & ((1 << BASE) - 1)) - - return limbs - - -def limbs_to_long(limbs): - val = 0 - base = 2 ** BASE - for (i, l) in enumerate(limbs): - val += l * (base ** i) - - return val - - -# iat_value = "1700255944" # Friday, November 17, 2023 -iat_value = "1719866138" - -exp_date_num = 111_111_111_111 -exp_date = str(exp_date_num) # 12-21-5490 -exp_horizon_num = 999_999_999_999 # ~31,710 years -exp_horizon = str(exp_horizon_num) -# nonce_value = "2284473333442251804379681643965308154311773667525398119496797545594705356495" -nonce_value = "2284473333442251804379681643965308154311773667525398119496797545594705356495" -public_inputs_hash_value = '"' + str( - 990250399590304032496786539443088814495837679250179990478424822100531016130) + '"' - -nonce = int(nonce_value) - -jwt_max_len = 192 * 8 - -# jwt_dict = { -# "iss": "test.oidc.provider", -# "azp": "511276456880-i7i4787c1863damto6899ts989j2e35r.apps.googleusercontent.com", -# "aud": "511276456880-i7i4787c1863damto6899ts989j2e35r.apps.googleusercontent.com", -# "sub": "102904630171592520592", -# "email": "hero1200091@gmail.com", -# "email_verified": True, -# "nonce": "12772123150809496860193457976937182964297283633705872391534946866719681904311", -# "nbf": 1711552330, -# "name": "コンドウハルキ", -# "picture": "https://lh3.googleusercontent.com/a/ACg8ocIMZfIkNWGRBTD924xl_iefpMccLguwdMIinMPzaj5L4Q=s96-c", -# "given_name": "ルキ", -# "family_name": "コンドウ", -# "iat": 1711552630, -# "exp": 1911556230 -# } - -#jwt_dict = { -# "iss":"https://accounts.google.com", -# "azp":"407408718192.apps.googleusercontent.com", -# "aud":"407408718192.apps.googleusercontent.com", -# "sub":"113990307082899718775", -# "at_hash":"lVeD4xP6Q1ZGrL3gFcCQLQ", -# "name":"Michael Straka", -# "picture":"https://lh3.googleusercontent.com/a/ACg8ocLVn8F8VnXKNNJhROhTpQuLLjFEdv_uhoe-DUaRTlxKEy9e4w=s96-c", -# "given_name":"Michael", -# "family_name":"Straka", -# "iat":1719866138, -# "exp":1719869738, -# "nonce":"2284473333442251804379681643965308154311773667525398119496797545594705356495" -# } - - -#original_b64 = "eyJpc3MiOiJ0ZXN0Lm9pZGMucHJvdmlkZXIiLCJhenAiOiI1MTEyNzY0NTY4ODAtaTdpNDc4N2MxODYzZGFtdG82ODk5dHM5ODlqMmUzNXIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI1MTEyNzY0NTY4ODAtaTdpNDc4N2MxODYzZGFtdG82ODk5dHM5ODlqMmUzNXIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDI5MDQ2MzAxNzE1OTI1MjA1OTIiLCJlbWFpbCI6Imhlcm8xMjAwMDkxQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJub25jZSI6IjEyNzcyMTIzMTUwODA5NDk2ODYwMTkzNDU3OTc2OTM3MTgyOTY0Mjk3MjgzNjMzNzA1ODcyMzkxNTM0OTQ2ODY2NzE5NjgxOTA0MzExIiwibmJmIjoxNzExNTUyMzMwLCJuYW1lIjoi44Kz44Oz44OJ44Km44OP44Or44KtIiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hL0FDZzhvY0lNWmZJa05XR1JCVEQ5MjR4bF9pZWZwTWNjTGd1d2RNSWluTVB6YWo1TDRRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IuODq-OCrSIsImZhbWlseV9uYW1lIjoi44Kz44Oz44OJ44KmIiwiaWF0IjoxNzExNTUyNjMwLCJleHAiOjE5MTE1NTYyMzB9" -original_b64 = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMTM5OTAzMDcwODI4OTk3MTg3NzUiLCJhdF9oYXNoIjoibFZlRDR4UDZRMVpHckwzZ0ZjQ1FMUSIsIm5hbWUiOiJNaWNoYWVsIFN0cmFrYSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NMVm44RjhWblhLTk5KaFJPaFRwUXVMTGpGRWR2X3Vob2UtRFVhUlRseEtFeTllNHc9czk2LWMiLCJnaXZlbl9uYW1lIjoiTWljaGFlbCIsImZhbWlseV9uYW1lIjoiU3RyYWthIiwiaWF0IjoxNzE5ODY2MTM4LCJleHAiOjE3MTk4Njk3MzgsIm5vbmNlIjoiMjI4NDQ3MzMzMzQ0MjI1MTgwNDM3OTY4MTY0Mzk2NTMwODE1NDMxMTc3MzY2NzUyNTM5ODExOTQ5Njc5NzU0NTU5NDcwNTM1NjQ5NSJ9" -original_str = base64.urlsafe_b64decode(original_b64) -print("original_str bytes", original_str) -jwt_dict = json.loads(original_str) - -#jwt_dict['iat'] = int(iat_value) # WARNING: the code assumes this is NOT the last field -#jwt_dict['nonce'] = nonce_value # WARNING: the code assumes this is the last field - -secret = rsa.generate_private_key( - backend=crypto_default_backend(), - public_exponent=65537, - key_size=2048 -) - - -class MyPyJWT(jwt.PyJWT): - def _encode_payload( - self, - payload: dict[str, Any], - headers: dict[str, Any] | None = None, - json_encoder: type[json.JSONEncoder] | None = None, - ) -> bytes: - return original_str # json.dumps(payload, separators=(",", ":"), ).encode("utf-8") - - -signed_b64_jwt_string = MyPyJWT().encode(jwt_dict, secret, algorithm="RS256", headers={"kid": "test_jwk"}) -unsigned_b64_jwt_string = signed_b64_jwt_string[:signed_b64_jwt_string.rfind(".")] - -# public_key = secret.public_key().public_bytes( -# crypto_serialization.Encoding.OpenSSH, -# crypto_serialization.PublicFormat.OpenSSH -# ) -jwt_payload_b64 = unsigned_b64_jwt_string[unsigned_b64_jwt_string.rfind(".") + 1:] -print(jwt_payload_b64) -jwt_payload = base64.urlsafe_b64decode(jwt_payload_b64) -jwt_payload = jwt_payload.decode('utf-8') -print("\njwt_payload bytes ", jwt_payload, "\n") -jwt_max_header_len = 300 -jwt_header_string = unsigned_b64_jwt_string[:unsigned_b64_jwt_string.find(".") + 1] - -header_value = pad_string(jwt_header_string, jwt_max_header_len) - -header_len_with_separator_value = '"' + str(len(jwt_header_string)) + '"' - -maxAudKVPairLen = 140 -maxAudNameLen = 40 -maxAudValueLen = 120 -aud_field_string = "\"aud\":\"407408718192.apps.googleusercontent.com\"," -#aud_field_string = "\"aud\":\"511276456880-i7i4787c1863damto6899ts989j2e35r.apps.googleusercontent.com\"," -aud_string_bodies = calc_string_bodies(aud_field_string) -aud_string_bodies_value = pad_string(aud_string_bodies, maxAudKVPairLen, use_ord=False) -aud_field_value = pad_string(aud_field_string, maxAudKVPairLen) -aud_field_len_value = '"' + str(len(aud_field_string)) + '"' -aud_index_value = '"' + str(jwt_payload.index("aud") - 1) + '"' # First '"' character in aud field index in payload -aud_colon_index = aud_field_string.index(":") -aud_colon_index_value = '"' + str(aud_colon_index) + '"' -aud_value_index_value = '"' + str(aud_colon_index + 2) + '"' # TODO: This doesn't work if there's whitespace -aud_name = "aud" -aud_value = "407408718192.apps.googleusercontent.com" -#aud_value = "511276456880-i7i4787c1863damto6899ts989j2e35r.apps.googleusercontent.com" -aud_name_value = pad_string(aud_name, maxAudNameLen) -aud_value_value = pad_string(aud_value, maxAudValueLen) -aud_value_len_value = '"' + str(len(aud_value)) + '"' - -private_aud_value_value = aud_value_value -override_aud_value_value = pad_string("", maxAudValueLen) -private_aud_value_len_value = aud_value_len_value -override_aud_value_len_value = '"' + "0" + '"' -use_aud_override_value = '"' + "0" + '"' - -maxIatKVPairLen = 50 -maxIatNameLen = 10 -maxIatValueLen = 45 -iat_field_string = "\"iat\":" + iat_value + "," -print("iat_field_string") -print(iat_field_string) -iat_field_value = pad_string(iat_field_string, maxIatKVPairLen) -iat_field_len_value = '"' + str(len(iat_field_string)) + '"' -iat_index_value = '"' + str(jwt_payload.index("iat") - 1) + '"' # First '"' character in aud field index in payload -iat_colon_index = iat_field_string.index(":") -iat_colon_index_value = '"' + str(iat_colon_index) + '"' -iat_value_index_value = '"' + str(iat_colon_index + 1) + '"' # TODO: This doesn't work if there's whitespace -iat_name = "iat" -iat_name_value = pad_string(iat_name, maxIatNameLen) -iat_value_value = pad_string(iat_value, maxIatValueLen) -iat_value_len_value = '"' + str(len(iat_value)) + '"' -exp_date_value = '"' + exp_date + '"' -exp_horizon_value = '"' + exp_horizon + '"' - -maxUidKVPairLen = 350 -maxUidNameLen = 30 -maxUidValueLen = 330 -uid_field_string = "\"sub\":\"113990307082899718775\"," -#uid_field_string = "\"sub\":\"102904630171592520592\"," -uid_string_bodies = calc_string_bodies(uid_field_string) -uid_string_bodies_value = pad_string(uid_string_bodies, maxUidKVPairLen, use_ord=False) -uid_field_value = pad_string(uid_field_string, maxUidKVPairLen) -uid_field_len_value = '"' + str(len(uid_field_string)) + '"' -uid_index_value = '"' + str(jwt_payload.index("sub") - 1) + '"' # This doesn't work for non-sub user id fields - -uid_name_len_value = '"' + str(3) + '"' # sub -uid_colon_index = uid_field_string.index(":") -uid_colon_index_value = '"' + str(uid_colon_index) + '"' -uid_value_index_value = '"' + str(uid_colon_index + 2) + '"' -uid_name = "sub" -uid_value = "113990307082899718775" -#uid_value = "102904630171592520592" -uid_name_value = pad_string(uid_name, maxUidNameLen) -uid_value_value = pad_string(uid_value, maxUidValueLen) -uid_value_len_value = '"' + str(len(uid_value)) + '"' - -# Extra revealed public JWT field -maxEFKVPairLen = 350 -maxEFNameLen = 30 -maxEFValueLen = 330 -extra_field_string = f"\"family_name\":\"{jwt_dict['family_name']}\"," -extra_field_value = pad_string_new(extra_field_string, maxEFKVPairLen) -extra_field_len_value = '"' + str(len(extra_field_string)) + '"' -extra_index_value = '"' + str(jwt_payload.index("family_name") - 1) + '"' - -extra_name_len_value = '"' + str(11) + '"' # family_name -extra_colon_index = extra_field_string.index(":") -extra_colon_index_value = '"' + str(extra_colon_index) + '"' -extra_value_index_value = '"' + str(extra_colon_index + 2) + '"' -extra_name = "family_name" -extra_value = "Straka"; -#extra_value = "コンドウ" -extra_name_value = pad_string_new(extra_name, maxEFNameLen) -extra_value_value = pad_string_new(extra_value, maxEFValueLen) -extra_value_len_value = '"' + str(len(extra_value)) + '"' -use_extra_field_value = '"' + str(0) + '"' - -maxEVKVPairLen = 30 -maxEVNameLen = 20 -maxEVValueLen = 10 -ev_field_string = "\"email_verified\":true," -ev_field_value = pad_string(ev_field_string, maxEVKVPairLen) -ev_field_len_value = '"' + str(len(ev_field_string)) + '"' -ev_index_value = '"' + str(0) + '"' - -ev_colon_index = 16 -ev_colon_index_value = '"' + str(ev_colon_index) + '"' -ev_value_index_value = '"' + str(ev_colon_index + 1) + '"' # TODO: Doesn't work with whitespace -ev_name = "email_verified" -ev_value = "true" -ev_name_value = pad_string(ev_name, maxEVNameLen) -ev_value_value = pad_string(ev_value, maxEVValueLen) -ev_value_len_value = '"' + str(len(ev_value)) + '"' - -maxIssKVPairLen = 140 -maxIssNameLen = 40 -maxIssValueLen = 120 -iss_field_string = "\"iss\":\"https://accounts.google.com\"," -#iss_field_string = "\"iss\":\"test.oidc.provider\"," -iss_string_bodies = calc_string_bodies(iss_field_string) -iss_string_bodies_value = pad_string(iss_string_bodies, maxIssKVPairLen, use_ord=False) -iss_field_value = pad_string(iss_field_string, maxIssKVPairLen) -iss_field_len_value = '"' + str(len(iss_field_string)) + '"' -iss_index_value = '"' + str(jwt_payload.index("iss") - 1) + '"' - -iss_colon_index = iss_field_string.index(":") -iss_colon_index_value = '"' + str(iss_colon_index) + '"' -iss_value_index_value = '"' + str(iss_colon_index + 2) + '"' # TODO: Doesn't work with whitespace -iss_name = "iss" -iss_value = "https://accounts.google.com" -#iss_value = "test.oidc.provider" -iss_name_value = pad_string(iss_name, maxIssNameLen) -iss_value_value = pad_string(iss_value, maxIssValueLen) -iss_value_len_value = '"' + str(len(iss_value)) + '"' - -# Values used in nonce -temp_pubkey_0 = 242984842061174104272170180221318235913385474778206477109637294427650138112 -temp_pubkey_1 = 4497911 -temp_pubkey_2 = 0 -temp_pubkey_len = 34 -jwt_randomness = 42 -nonce_bitstring = format(nonce, 'b') -temp_pubkey_value = "[ \"" + str(temp_pubkey_0) + '"' + ',\"' + str(temp_pubkey_1) + '"' + ',\"' + str( - temp_pubkey_2) + '"]' -temp_pubkey_len_value = '"' + str(temp_pubkey_len) + '"' -jwt_randomness_value = '"' + str(jwt_randomness) + '"' - -maxNonceKVPairLen = 105 -maxNonceNameLen = 10 -maxNonceValueLen = 100 -nonce_field_string = "\"nonce\":\"" + nonce_value + "\"}" -nonce_string_bodies = calc_string_bodies(nonce_field_string) -nonce_string_bodies_value = pad_string(nonce_string_bodies, maxNonceKVPairLen, use_ord=False) -nonce_field_value = pad_string(nonce_field_string, maxNonceKVPairLen) -nonce_field_len_value = '"' + str(len(nonce_field_string)) + '"' -nonce_index_value = '"' + str(jwt_payload.index("nonce") - 1) + '"' - -nonce_colon_index = nonce_field_string.index(":") -nonce_colon_index_value = '"' + str(nonce_colon_index) + '"' -nonce_value_index_value = '"' + str(nonce_colon_index + 2) + '"' # TODO: Doesn't work with whitespace -nonce_name = "nonce" -nonce_value_reversed = nonce_value[::-1] -nonce_name_value = pad_string(nonce_name, maxNonceNameLen) -nonce_value_value = pad_string(nonce_value, maxNonceValueLen) -nonce_value_len_value = '"' + str(len(nonce_value)) + '"' - -pepper = 76 -pepper_value = '"' + str(pepper) + '"' - -jwt_payload_string_no_padding = unsigned_b64_jwt_string[unsigned_b64_jwt_string.find(".") + 1:] -print("\n\n") -print("original_b64 payload ", original_b64) -print("jwt_payload_string_no_padding", jwt_payload_string_no_padding) - -print("original_b64 bytes ", base64.urlsafe_b64decode(original_b64)) -print("jwt_payload_string_no_padding bytes", base64.urlsafe_b64decode(jwt_payload_string_no_padding)) -print("\n\n") - -jwt_max_payload_len = 192 * 8 - 64 - -jwt_payload_string_no_padding_value = pad_string(jwt_payload_string_no_padding, jwt_max_payload_len, - n="jwt_payload_string_no_padding_value") - -payload_len = len(jwt_payload_string_no_padding) -payload_len_value = '"' + str(payload_len) + '"' - -# Add SHA2 padding to the end of the b64 jwt string -unsigned_b64_jwt_bits = "" -for c in unsigned_b64_jwt_string: - bits = bin(ord(c)) - bits = bits[2:].zfill(8) - unsigned_b64_jwt_bits += bits - -L = len(unsigned_b64_jwt_bits) - -# Used as circuit input -L_bit_encoded = format(L, 'b').zfill(64) -print("L_bit_encoded: ", L_bit_encoded) - -L_byte_encoded = "" -for i in range(8): - idx = i * 8 - bits = L_bit_encoded[idx:idx + 8] - ascii_char = chr(int(bits, 2)) - L_byte_encoded += ascii_char - -print("L_byte_encoded: ", L_byte_encoded.encode('utf-8')) -L_byte_encoded_value = pad_string(L_byte_encoded, 8, n="L_byte_encoded_value", use_ord=True) - -L_mod = L % 512 -# https://www.rfc-editor.org/rfc/rfc4634.html#section-4.1 -# 4.1.a append '1' -unsigned_b64_jwt_bits += '1' - -# 4.1.b Append 'K' 0s where K is the smallest non-negative integer solution to L+1+K = 448 mod 512, and L is the length of the message in bits -K = 448 - L_mod - 1 - -# Used as a circuit input -padding_without_len = '1' + '0' * K -padding_without_len = padding_without_len.ljust(512, '0') - -padding_without_len_bytes = "" -for i in range(64): - idx = i * 8 - bits = padding_without_len[idx:idx + 8] - ascii_char = chr(int(bits, 2)) - padding_without_len_bytes += ascii_char - -padding_without_len_bytes_value = pad_string(padding_without_len_bytes, 64, n="padding_without_len_bytes", use_ord=True) - -unsigned_b64_jwt_bits_sha_padded = unsigned_b64_jwt_bits + '0' * K - -# 4.1.c Append L in binary form as 64 bits -L_bits = format(L, 'b').zfill(64) - -unsigned_b64_jwt_bits_sha_padded += L_bits - -unsigned_b64_jwt_string_sha_padded = "" -for i in range(int(len(unsigned_b64_jwt_bits_sha_padded) / 8)): - idx = i * 8 - bits = unsigned_b64_jwt_bits_sha_padded[idx:idx + 8] - ascii_char = chr(int(bits, 2)) - unsigned_b64_jwt_string_sha_padded += ascii_char - -print("unsigned_b64_jwt_bits_sha_padded", unsigned_b64_jwt_bits_sha_padded) - -jwt_value = pad_string(unsigned_b64_jwt_string_sha_padded, jwt_max_len, n="jwt_value") - -jwt_num_sha2_blocks = int((len(unsigned_b64_jwt_string_sha_padded) * 8) / 512) # SHA2 uses 512-bit blocks -jwt_num_sha2_blocks_value = '"' + str(jwt_num_sha2_blocks) + '"' - -jwt_payload_string = unsigned_b64_jwt_string_sha_padded[unsigned_b64_jwt_string_sha_padded.find(".") + 1:] - -payload_value = pad_string(jwt_payload_string, jwt_max_payload_len) - -# Compute RSA signature over the full unsigned JWT -with open(f"tools/test_rsa_privkey.pem", 'rb') as f: - privkey_str = f.read() - f.close() -keyPair = Crypto.PublicKey.RSA.import_key(privkey_str) -# keyPair = RSA.generate(bits=2048) - - -jwt_byte_encoding = str.encode(unsigned_b64_jwt_string) -hash = SHA256.new(jwt_byte_encoding) -signer = PKCS115_SigScheme(keyPair) -signature = signer.sign(hash) - -sig_long = bytes_to_long(signature) -sig_limbs = long_to_limbs(sig_long) -##print(limbs_to_long(sig_limbs) == sig_long) -sig_value = "[" -for l in sig_limbs: - sig_value += '"' + str(l) + '"' + "," -sig_value = sig_value[:-1] + "]" - -mod_limbs = long_to_limbs(keyPair.n) -##print(limbs_to_long(mod_limbs) == keyPair.n) - -mod_value = "[" -for l in mod_limbs: - mod_value += '"' + str(l) + '"' + "," -mod_value = mod_value[:-1] + "]" - -hash_limbs = long_to_limbs(bytes_to_long(hash.digest()))[:4] -##print(hash_limbs) - -json_dict = { - "\"jwt\"": jwt_value, - "\"jwt_header_with_separator\"": header_value, - "\"jwt_payload\"": payload_value, - "\"public_inputs_hash\"": public_inputs_hash_value, - "\"header_len_with_separator\"": header_len_with_separator_value, - "\"signature\"": sig_value, - "\"pubkey_modulus\"": mod_value, - "\"aud_field\"": aud_field_value, - "\"aud_field_string_bodies\"": aud_string_bodies_value, - "\"aud_field_len\"": aud_field_len_value, - "\"aud_index\"": aud_index_value, - "\"aud_value_index\"": aud_value_index_value, - "\"aud_colon_index\"": aud_colon_index_value, - "\"aud_name\"": aud_name_value, - "\"uid_field\"": uid_field_value, - "\"uid_field_string_bodies\"": uid_string_bodies_value, - "\"uid_field_len\"": uid_field_len_value, - "\"uid_index\"": uid_index_value, - "\"uid_name_len\"": uid_name_len_value, - "\"uid_value_index\"": uid_value_index_value, - "\"uid_value_len\"": uid_value_len_value, - "\"uid_colon_index\"": uid_colon_index_value, - "\"uid_name\"": uid_name_value, - "\"uid_value\"": uid_value_value, - "\"ev_field\"": ev_field_value, - "\"ev_field_len\"": ev_field_len_value, - "\"ev_index\"": ev_index_value, - "\"ev_value_index\"": ev_value_index_value, - "\"ev_value_len\"": ev_value_len_value, - "\"ev_colon_index\"": ev_colon_index_value, - "\"ev_name\"": ev_name_value, - "\"ev_value\"": ev_value_value, - "\"iss_field\"": iss_field_value, - "\"iss_field_string_bodies\"": iss_string_bodies_value, - "\"iss_field_len\"": iss_field_len_value, - "\"iss_index\"": iss_index_value, - "\"iss_value_index\"": iss_value_index_value, - "\"iss_value_len\"": iss_value_len_value, - "\"iss_colon_index\"": iss_colon_index_value, - "\"iss_name\"": iss_name_value, - "\"iss_value\"": iss_value_value, - "\"nonce_field\"": nonce_field_value, - "\"nonce_field_string_bodies\"": nonce_string_bodies_value, - "\"nonce_field_len\"": nonce_field_len_value, - "\"nonce_index\"": nonce_index_value, - "\"nonce_value_index\"": nonce_value_index_value, - "\"nonce_value_len\"": nonce_value_len_value, - "\"nonce_colon_index\"": nonce_colon_index_value, - "\"nonce_name\"": nonce_name_value, - "\"nonce_value\"": nonce_value_value, - "\"temp_pubkey\"": temp_pubkey_value, - "\"jwt_randomness\"": jwt_randomness_value, - "\"pepper\"": pepper_value, - "\"jwt_num_sha2_blocks\"": jwt_num_sha2_blocks_value, - "\"iat_field\"": iat_field_value, - "\"iat_field_len\"": iat_field_len_value, - "\"iat_index\"": iat_index_value, - "\"iat_value_index\"": iat_value_index_value, - "\"iat_value_len\"": iat_value_len_value, - "\"iat_colon_index\"": iat_colon_index_value, - "\"iat_name\"": iat_name_value, - "\"iat_value\"": iat_value_value, - "\"exp_date\"": exp_date_value, - "\"exp_delta\"": exp_horizon_value, - "\"b64_payload_len\"": payload_len_value, - "\"jwt_len_bit_encoded\"": L_byte_encoded_value, - "\"padding_without_len\"": padding_without_len_bytes_value, - "\"temp_pubkey_len\"": temp_pubkey_len_value, - "\"private_aud_value\"": private_aud_value_value, - "\"override_aud_value\"": override_aud_value_value, - "\"private_aud_value_len\"": private_aud_value_len_value, - "\"override_aud_value_len\"": override_aud_value_len_value, - "\"use_aud_override\"": use_aud_override_value, - "\"extra_field\"": extra_field_value, - "\"extra_field_len\"": extra_field_len_value, - "\"extra_index\"": extra_index_value, - "\"jwt_payload_without_sha_padding\"": jwt_payload_string_no_padding_value, - "\"use_extra_field\"": use_extra_field_value -} -inputs_dot_json = format_output(json_dict) - -# print(inputs_dot_json) -print("Writing circuit inputs to input.json...") -if os.path.exists("input.json"): - os.remove("input.json") -f = open("input.json", "a") -f.write(inputs_dot_json) -f.close() -# print(format(int(binascii.hexlify(hash.digest()),16), 'b')) -##print(K) -# os.remove("privkey.pem") -# privkeyfile = open("privkey.pem", "wb") -# privkeyfile.write(keyPair.exportKey("PEM")) -# privkeyfile.close() - -##print("signed jwt: " + signed_b64_jwt_string) -##print("unsigned signed jwt: " + unsigned_b64_jwt_string) -##print(ev_colon_index) -##print(ev_value_index_value) - -print("Results") -print("-------") - -print("\nIssued at:") -print(iat_value) - -print("\nExpiration date:") -print(exp_date) - -print("\nExpiration horizon:") -print(exp_horizon) - -print("\nPepper") -print(pepper) - -print("\nExtra field") -print(extra_field_string) - -print("\nEPK blinder (JWT randomness)") -print(jwt_randomness_value) - -print("\nbase64url-encoded RSA modulus") -modulus_bytes = keyPair.n.to_bytes((keyPair.n.bit_length() + 7) // 8, byteorder='big') -print(base64.urlsafe_b64encode(modulus_bytes)) - -print("\nPublic inputs hash") -print(public_inputs_hash_value) - -print("\nbase64url-encoded JWT header:") -print(jwt_header_string[:-1]) - -print("\nDecoded JWT header:") -print(base64.urlsafe_b64decode(jwt_header_string[:-1] + "==")) - -print("\nDecoded JWT payload:") -print(jwt_payload) - -print("\nPretty-printed JWT payload:") -jwt_parsed = json.loads(jwt_payload) diff --git a/keyless/circuit/tools/install-deps.sh b/keyless/circuit/tools/install-deps.sh deleted file mode 100755 index a0487d6958bc8..0000000000000 --- a/keyless/circuit/tools/install-deps.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh - -set -e -install_node() { - echo "nodejs installation started." - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm - [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion - nvm install --lts - node -v - npm -v - echo "nodejs installation finished." -} - -install_git_lfs() { - echo "git lfs installation started." - if which brew > /dev/null; then - brew install git-lfs - elif which apt-get > /dev/null; then - sudo apt-get install git-lfs - else - echo "Can't figure out what platform you are on. Currently this script only supports MacOS and Debian." - fi - git lfs install - echo "git lfs installation finished." -} - -install_circom() { - echo "circom installation started." - original_dir=$(pwd) - cd `mktemp -d` - git clone https://github.com/iden3/circom - cd circom - git switch -d v2.1.7 - cargo build --release - cargo install --path circom - cd "$original_dir" - echo "circom installation finished." -} - -install_pip3_deps() { - echo "pip3 deps installation started." - sudo apt install python3-venv -y - echo "pip3 deps installation finished." -} - -install_npm_deps() { - echo "snarkjs installation started." - npm install -g snarkjs - echo "snarkjs installation finished." -} - -install_circomlib() { - echo "circomlib@2.0.5 installation started." - npm install -g circomlib@2.0.5 - echo "circomlib@2.0.5 installation finished." -} - -install_node -install_pip3_deps -install_npm_deps -install_circomlib -install_circom -install_git_lfs diff --git a/keyless/circuit/tools/test_rsa_privkey.pem b/keyless/circuit/tools/test_rsa_privkey.pem deleted file mode 100644 index 3af92c2eb7b71..0000000000000 --- a/keyless/circuit/tools/test_rsa_privkey.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDpLtqxS7OrlD/d -T2tuz4+QNUh2OCa2Bat4bmpY+wL3FdkqIxXUCJX0tfKpCwBikKoQMzddt+ZmoZvj -zIuFv9eploqBJhoL+HYOMzuWCshACn33TZGvx9SYs3aK+vm2cvFRQ6cw5zZJC2v1 -2DNM41hblm7c/DK8BaTkPq54hSEu1jOlwH562g10vcivbvjoojL9VSwPAAzt2Gup -IrxTbEUIaVq7iKQ5O2/MOjCcAwcyt8TurUHpZlAMBCUGbFFCzIqWfkMiwq/rFq42 -wdGAEApy1TFkbwzhAkjHdLoC6CF3dFkLgJrkB7193wvyaU1gEKtCE5nt1LR/hq3h -quUtxqO3AgMBAAECggEBANX6C+7EA/TADrbcCT7fMuNnMb5iGovPuiDCWc6bUIZC -Q0yac45l7o1nZWzfzpOkIprJFNZoSgIF7NJmQeYTPCjAHwsSVraDYnn3Y4d1D3tM -5XjJcpX2bs1NactxMTLOWUl0JnkGwtbWp1Qq+DBnMw6ghc09lKTbHQvhxSKNL/0U -C+YmCYT5ODmxzLBwkzN5RhxQZNqol/4LYVdji9bS7N/UITw5E6LGDOo/hZHWqJsE -fgrJTPsuCyrYlwrNkgmV2KpRrGz5MpcRM7XHgnqVym+HyD/r9E7MEFdTLEaiiHcm -Ish1usJDEJMFIWkF+rnEoJkQHbqiKlQBcoqSbCmoMWECgYEA/4379mMPF0JJ/EER -4VH7/ZYxjdyphenx2VYCWY/uzT0KbCWQF8KXckuoFrHAIP3EuFn6JNoIbja0NbhI -HGrU29BZkATG8h/xjFy/zPBauxTQmM+yS2T37XtMoXNZNS/ubz2lJXMOapQQiXVR -l/tzzpyWaCe9j0NT7DAU0ZFmDbECgYEA6ZbjkcOs2jwHsOwwfamFm4VpUFxYtED7 -9vKzq5d7+Ii1kPKHj5fDnYkZd+mNwNZ02O6OGxh40EDML+i6nOABPg/FmXeVCya9 -Vump2Yqr2fAK3xm6QY5KxAjWWq2kVqmdRmICSL2Z9rBzpXmD5o06y9viOwd2bhBo -0wB02416GecCgYEA+S/ZoEa3UFazDeXlKXBn5r2tVEb2hj24NdRINkzC7h23K/z0 -pDZ6tlhPbtGkJodMavZRk92GmvF8h2VJ62vAYxamPmhqFW5Qei12WL+FuSZywI7F -q/6oQkkYT9XKBrLWLGJPxlSKmiIGfgKHrUrjgXPutWEK1ccw7f10T2UXvgECgYEA -nXqLa58G7o4gBUgGnQFnwOSdjn7jkoppFCClvp4/BtxrxA+uEsGXMKLYV75OQd6T -IhkaFuxVrtiwj/APt2lRjRym9ALpqX3xkiGvz6ismR46xhQbPM0IXMc0dCeyrnZl -QKkcrxucK/Lj1IBqy0kVhZB1IaSzVBqeAPrCza3AzqsCgYEAvSiEjDvGLIlqoSvK -MHEVe8PBGOZYLcAdq4YiOIBgddoYyRsq5bzHtTQFgYQVK99Cnxo+PQAvzGb+dpjN -/LIEAS2LuuWHGtOrZlwef8ZpCQgrtmp/phXfVi6llcZx4mMm7zYmGhh2AsA9yEQc -acgc4kgDThAjD7VlXad9UHpNMO8= ------END PRIVATE KEY----- diff --git a/keyless/circuit/tools/trusted-setup.sh b/keyless/circuit/tools/trusted-setup.sh deleted file mode 100755 index 8a0d419a2a3f5..0000000000000 --- a/keyless/circuit/tools/trusted-setup.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/bash - -set -e - -if [ ! -e ".circuit-root" ]; then - echo "Error: the current working directory is not circuit package root (the directory that contains `.circuit-root`)" - exit 1 -fi - -print_usage() { -cat < -DONE -} - -pushd() { - command pushd "$@" > /dev/null -} - -popd() { - command popd "$@" > /dev/null -} - -trusted_setup() { - outdir=$1 - - mkdir -p $outdir - outdir=`realpath $outdir` - - echo - echo "Generating proving key and verification key in $outdir" - - ptau_repo=aptos-keyless-trusted-setup-contributions-may-2024 - ptau_file=powersOfTau28_hez_final_21.ptau - if [ ! -d "$ptau_repo" ]; then - echo - echo "You haven't downloaded the .ptau file yet. Downloading now..." - GIT_LFS_SKIP_SMUDGE=1 git clone git@github.com:aptos-labs/$ptau_repo.git - pushd $ptau_repo/ - { - echo - echo "Downloading ~2.4 GiB file. This will take a while..." - git lfs pull --include $ptau_file - echo "Done downloading .ptau file." - } - popd - fi - ptaudir=`realpath $ptau_repo` - - pushd templates/ - { - echo - echo "Re-compiling circuit. This will take several seconds..." - circom -l . -l $(npm root -g) main.circom --r1cs --wasm --sym - - rm -f $outdir/prover_key.zkey - rm -f $outdir/verification_key.json - - echo - echo "Running dummy phase-2 setup..." - echo "This will take several minutes..." - time snarkjs groth16 setup main.r1cs $ptaudir/$ptau_file $outdir/prover_key.zkey - - echo - echo "Exporting verification key..." - snarkjs zkey export verificationkey $outdir/prover_key.zkey $outdir/verification_key.json - } - popd - - echo - echo "Done. Find the prover_key.zkey and verification_key.json files in $outdir" -} - -if [ "$#" -ne 1 ]; then - print_usage - exit 2 -fi - -if [ -e "$1" ]; then - echo "Error: output path already exists." - exit 3 -fi - -trusted_setup "$1" diff --git a/keyless/common/Cargo.toml b/keyless/common/Cargo.toml deleted file mode 100644 index 7c594c68dc56b..0000000000000 --- a/keyless/common/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "aptos-keyless-common" -description = "Aptos Keyless circuit tests" -version = "0.1.0" - -# Workspace inherited keys -authors = { workspace = true } -edition = { workspace = true } -homepage = { workspace = true } -license = { workspace = true } -publish = { workspace = true } -repository = { workspace = true } -rust-version = { workspace = true } - -[dependencies] -anyhow = { workspace = true } -aptos-types = { workspace = true } -ark-bn254 = { workspace = true } -ark-ff = { workspace = true } -base64 = { workspace = true } -hex = { workspace = true } -num-bigint = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -tempfile = { workspace = true } -tracing = { workspace = true } diff --git a/keyless/common/src/api.rs b/keyless/common/src/api.rs deleted file mode 100644 index 5f812bb629c63..0000000000000 --- a/keyless/common/src/api.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use aptos_types::{ - keyless::{Groth16Proof, Pepper}, - transaction::authenticator::EphemeralPublicKey, -}; -use serde::{Deserialize, Serialize}; - -//#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] -//pub struct EphemeralPublicKeyBlinder(pub(crate) Vec); - -pub type EphemeralPublicKeyBlinder = Vec; - -// TODO can I wrap this in a struct while preserving serialization format? -pub type PoseidonHash = [u8; 32]; - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestInput { - pub jwt_b64: String, - pub epk: EphemeralPublicKey, - #[serde(with = "hex")] - pub epk_blinder: EphemeralPublicKeyBlinder, - pub exp_date_secs: u64, - pub exp_horizon_secs: u64, - pub pepper: Pepper, - pub uid_key: String, - pub extra_field: Option, - pub idc_aud: Option, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(untagged)] -#[allow(clippy::large_enum_variant)] // EphemeralSignature has the WebAuthn (Passkey) variant which is large. -pub enum ProverServiceResponse { - Success { - proof: Groth16Proof, - #[serde(with = "hex")] - public_inputs_hash: PoseidonHash, - #[serde(with = "hex")] - training_wheels_signature: Vec, - }, - Error { - message: String, - }, -} diff --git a/keyless/common/src/input_processing/bits.rs b/keyless/common/src/input_processing/bits.rs deleted file mode 100644 index f683037ade289..0000000000000 --- a/keyless/common/src/input_processing/bits.rs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use anyhow::{bail, Result}; -use std::ops::{self, Add, AddAssign}; - -/// Type for bit representation during conversion. Represents bits using strings, for easy -/// manipulation: -/// ```ignore -/// use prover_service::input_processing::bits::Bits; -/// let b = Bits::raw("00001111"); -/// assert_eq!(b.as_bytes().unwrap()[0], 15u8); -/// ``` -/// -/// This struct is mainly used for the sha padding computation. -#[derive(Debug, Eq, PartialEq)] -pub struct Bits { - pub(crate) b: String, -} - -impl Default for Bits { - fn default() -> Self { - Self::new() - } -} - -impl Bits { - pub fn new() -> Self { - Bits { b: String::new() } - } - - /// Input: Bits in BIG-ENDIAN order - /// Output: bytes in BIG_ENDIAN order - pub fn as_bytes(self) -> Result> { - if self.b.len() % 8 != 0 { - bail!("Tried to convert bits to bytes, where bit length is not divisible by 8") - } else { - let mut bytes = Vec::new(); - - for i in 0..(self.b.len() / 8) { - let idx = i * 8; - let bits_for_chunk: &str = &self[idx..idx + 8]; - let chunk_byte = - u8::from_str_radix(bits_for_chunk, 2).expect("Binary string should parse"); - - bytes.push(chunk_byte); - } - - Ok(bytes) - } - } - - pub fn bit_representation_of_str(s: &str) -> Self { - let mut bits = Bits::new(); - for byte in s.as_bytes() { - bits.b += &format!("{byte:08b}"); - } - bits - } - - pub fn bit_representation_of_bytes(s: &[u8]) -> Self { - let mut bits = Bits::new(); - for byte in s { - bits.b += &format!("{byte:08b}"); - } - bits - } - - pub fn raw(b: &str) -> Self { - Bits { b: String::from(b) } - } -} - -impl ops::Index> for Bits { - type Output = str; - - fn index(&self, index: ops::Range) -> &str { - self.b.index(index) - } -} - -impl AddAssign for Bits { - fn add_assign(&mut self, rhs: Bits) { - self.b += &rhs.b; - } -} - -impl Add for Bits { - type Output = Bits; - - fn add(self, rhs: Bits) -> Self::Output { - Bits { b: self.b + &rhs.b } - } -} - -impl From for String { - fn from(value: Bits) -> Self { - value.b - } -} diff --git a/keyless/common/src/input_processing/circuit_input_signals.rs b/keyless/common/src/input_processing/circuit_input_signals.rs deleted file mode 100644 index c30146fd2da26..0000000000000 --- a/keyless/common/src/input_processing/circuit_input_signals.rs +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use super::config::CircuitPaddingConfig; -use anyhow::{anyhow, bail, Result}; -use ark_bn254::Fr; -use serde_json::Value; -use std::{collections::BTreeMap, marker::PhantomData}; - -#[derive(Debug)] -pub enum CircuitInputSignal { - U64(u64), - Fr(Fr), - Frs(Vec), - Limbs(Vec), - Bytes(Vec), -} - -pub struct Unpadded; - -#[derive(Debug)] -pub struct Padded; - -#[derive(Debug)] -pub struct CircuitInputSignals { - signals: BTreeMap, - t: PhantomData, -} - -impl Default for CircuitInputSignals { - fn default() -> Self { - Self::new() - } -} - -impl CircuitInputSignals { - pub fn new() -> Self { - Self { - signals: BTreeMap::new(), - t: PhantomData, - } - } - - pub fn bytes_input(mut self, signal_name: &str, signal_value: &[u8]) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::Bytes(Vec::from(signal_value)), - ); - self - } - - pub fn byte_input(mut self, signal_name: &str, signal_value: u8) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::U64(signal_value as u64), - ); - self - } - - pub fn bits_input(self, signal_name: &str, signal_value: &[bool]) -> Self { - let bytes: Vec = signal_value.iter().map(|&val| val as u8).collect(); - self.bytes_input(signal_name, bytes.as_slice()) - } - - pub fn str_input(mut self, signal_name: &str, signal_value: &str) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::Bytes(Vec::from(signal_value.as_bytes())), - ); - self - } - - pub fn usize_input(mut self, signal_name: &str, signal_value: usize) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::U64(signal_value as u64), - ); - self - } - - pub fn limbs_input(mut self, signal_name: &str, signal_value: &[u64]) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::Limbs(Vec::from(signal_value)), - ); - self - } - - pub fn u64_input(mut self, signal_name: &str, signal_value: u64) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::U64(signal_value), - ); - self - } - - pub fn frs_input(mut self, signal_name: &str, signal_value: &[Fr]) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::Frs(Vec::from(signal_value)), - ); - self - } - - pub fn fr_input(mut self, signal_name: &str, signal_value: Fr) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::Fr(signal_value), - ); - self - } - - pub fn bools_input(mut self, signal_name: &str, signal_value: &[bool]) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::Bytes(signal_value.iter().map(|b| *b as u8).collect::>()), - ); - self - } - - pub fn bool_input(mut self, signal_name: &str, signal_value: bool) -> Self { - self.signals.insert( - String::from(signal_name), - CircuitInputSignal::U64(signal_value as u64), - ); - self - } - - pub fn merge(mut self, to_merge: CircuitInputSignals) -> Result { - for (key, _) in self.signals.iter() { - if to_merge.signals.contains_key(key) { - bail!("Cannot redefine a signal input that is already defined.") - } - } - - self.signals.extend(to_merge.signals); - - Ok(Self { - signals: self.signals, - t: PhantomData, - }) - } - - pub fn pad(self, config: &CircuitPaddingConfig) -> Result> { - let padded_signals_vec: Result> = self - .signals - .into_iter() - .map(|(k, v)| { - anyhow::Ok((String::from(&k), pad_if_needed(&k, v, &config.max_lengths)?)) - }) - .collect(); - - let padded_signals: BTreeMap = - BTreeMap::from_iter(padded_signals_vec?); - - Ok(CircuitInputSignals { - signals: padded_signals, - t: PhantomData, - }) - } -} - -// padding helper functions - -fn pad_if_needed( - k: &str, - v: CircuitInputSignal, - global_input_max_lengths: &BTreeMap, -) -> Result { - Ok(match v { - CircuitInputSignal::U64(x) => CircuitInputSignal::U64(x), - CircuitInputSignal::Fr(x) => CircuitInputSignal::Fr(x), - CircuitInputSignal::Frs(x) => CircuitInputSignal::Frs(x), - CircuitInputSignal::Limbs(mut x) => { - let zeros_needed = - global_input_max_lengths.get(k).copied().unwrap_or(x.len()) - x.len(); - x.extend(vec![0; zeros_needed]); - CircuitInputSignal::Limbs(x) - }, - - CircuitInputSignal::Bytes(b) => { - CircuitInputSignal::Bytes(pad_bytes(&b, global_input_max_lengths[k])?) - }, - }) -} - -fn pad_bytes(unpadded_bytes: &[u8], max_size: usize) -> Result, anyhow::Error> { - let mut bytes = Vec::from(unpadded_bytes); - - println!("size: {}", bytes.len()); - println!("max size: {}", max_size); - println!("{:?}", String::from_utf8_lossy(&bytes)); - - if max_size < bytes.len() { - Err(anyhow!("max_size exceeded")) - } else { - bytes.extend([0].repeat(max_size - bytes.len())); - Ok(bytes) - } -} - -/// Can only serialize a CircuitInputSignals struct if padding has been added -impl CircuitInputSignals { - pub fn to_json_value(self) -> serde_json::Value { - Value::from(serde_json::Map::from_iter( - self.signals.into_iter().map(|(k, v)| (k, stringify(v))), - )) - } -} - -fn stringify_vec(v: &[T]) -> Vec { - v.iter().map(|num| num.to_string()).collect() -} - -fn stringify_vec_fr(v: &[Fr]) -> Vec { - v.iter().map(fr_to_string).collect() -} - -fn stringify(input: CircuitInputSignal) -> Value { - match input { - CircuitInputSignal::U64(x) => Value::from(x.to_string()), - CircuitInputSignal::Fr(x) => Value::from(fr_to_string(&x)), - CircuitInputSignal::Frs(x) => Value::from(stringify_vec_fr(&x)), - CircuitInputSignal::Limbs(x) => Value::from(stringify_vec(&x)), - CircuitInputSignal::Bytes(x) => Value::from(stringify_vec(&x)), - } -} - -/// Annoyingly, Fr serializes 0 to the empty string. Mitigate this here -fn fr_to_string(fr: &Fr) -> String { - let s = fr.to_string(); - if s.is_empty() { - String::from("0") - } else { - s - } -} diff --git a/keyless/common/src/input_processing/config.rs b/keyless/common/src/input_processing/config.rs deleted file mode 100644 index f881e0abc4da1..0000000000000 --- a/keyless/common/src/input_processing/config.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; - -#[derive(Serialize, Deserialize, Clone)] -pub struct CircuitPaddingConfig { - pub max_lengths: BTreeMap, -} - -impl CircuitPaddingConfig { - #[allow(clippy::new_without_default)] - pub fn new() -> Self { - Self { - max_lengths: BTreeMap::new(), - } - } - - pub fn max_length(mut self, signal: &str, l: usize) -> Self { - self.max_lengths.insert(String::from(signal), l); - self - } -} diff --git a/keyless/common/src/input_processing/encoding.rs b/keyless/common/src/input_processing/encoding.rs deleted file mode 100644 index d74dea6a71e05..0000000000000 --- a/keyless/common/src/input_processing/encoding.rs +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::api::{EphemeralPublicKeyBlinder, PoseidonHash}; -use anyhow::{anyhow, Result}; -use aptos_types::{ - jwks::rsa::RSA_JWK, keyless::Pepper, transaction::authenticator::EphemeralPublicKey, -}; -use ark_bn254::Fr; -use ark_ff::{BigInteger, PrimeField}; -use num_bigint::BigUint; -use serde::{Deserialize, Serialize}; - -pub type RsaSignature = BigUint; - -pub trait AsFr { - fn as_fr(&self) -> Fr; -} - -pub trait FromFr { - fn from_fr(fr: &Fr) -> Self; -} - -pub trait TryFromFr: Sized { - fn try_from_fr(fr: &Fr) -> Result; -} - -impl AsFr for PoseidonHash { - fn as_fr(&self) -> Fr { - Fr::from_le_bytes_mod_order(self.as_slice()) - } -} - -impl TryFromFr for PoseidonHash { - fn try_from_fr(fr: &Fr) -> Result { - let v = fr.into_bigint().to_bytes_le(); - let arr: PoseidonHash = v - .try_into() - .map_err(|_| anyhow!("Conversion from Fr to bytes failed"))?; - Ok(arr) - } -} - -impl AsFr for EphemeralPublicKeyBlinder { - fn as_fr(&self) -> Fr { - Fr::from_le_bytes_mod_order(self) - } -} - -impl FromFr for EphemeralPublicKeyBlinder { - fn from_fr(fr: &Fr) -> Self { - fr.into_bigint().to_bytes_le() - } -} - -impl AsFr for Pepper { - fn as_fr(&self) -> Fr { - Fr::from_le_bytes_mod_order(self.to_bytes()) - } -} - -pub trait FromB64 { - fn from_b64(s: &str) -> Result - where - Self: Sized; -} - -impl FromB64 for RsaSignature { - /// JWT signature is encoded in big-endian. - fn from_b64(s: &str) -> Result { - Ok(BigUint::from_bytes_be(&base64::decode_config( - s, - base64::URL_SAFE_NO_PAD, - )?)) - } -} - -pub trait FromHex { - fn from_hex(s: &str) -> Result - where - Self: Sized; -} - -impl FromHex for EphemeralPublicKey { - fn from_hex(s: &str) -> Result - where - Self: Sized, - { - Ok(EphemeralPublicKey::try_from(hex::decode(s)?.as_slice())?) - } -} - -#[derive(Debug)] -pub struct JwtParts { - header: String, - payload: String, - signature: String, -} - -#[derive(Serialize, Deserialize)] -pub struct JwtHeader { - pub kid: String, -} - -#[derive(Serialize, Deserialize)] -pub struct JwtPayload { - pub iss: String, - pub iat: u64, - pub nonce: String, - pub sub: Option, - pub email: Option, - pub aud: Option, -} - -impl FromB64 for JwtParts { - fn from_b64(s: &str) -> Result - where - Self: Sized, - { - let jwt_parts: Vec<&str> = s.split('.').collect(); - Ok(Self { - header: String::from( - *jwt_parts - .first() - .ok_or_else(|| anyhow!("JWT did not parse correctly"))?, - ), - payload: String::from( - *jwt_parts - .get(1) - .ok_or_else(|| anyhow!("JWT did not parse correctly"))?, - ), - signature: String::from( - *jwt_parts - .get(2) - .ok_or_else(|| anyhow!("JWT did not parse correctly"))?, - ), - }) - } -} - -impl JwtParts { - pub fn unsigned_undecoded(&self) -> String { - String::from(&self.header) + "." + &self.payload - } - - pub fn payload_undecoded(&self) -> String { - String::from(&self.payload) - } - - pub fn header_undecoded_with_dot(&self) -> String { - String::from(&self.header) + "." - } - - pub fn header_decoded(&self) -> Result { - Ok(String::from_utf8(base64::decode_config( - &self.header, - base64::URL_SAFE_NO_PAD, - )?)?) - } - - pub fn payload_decoded(&self) -> Result { - Ok(String::from_utf8(base64::decode_config( - &self.payload, - base64::URL_SAFE_NO_PAD, - )?)?) - } - - pub fn signature(&self) -> Result { - RsaSignature::from_b64(&self.signature) - } -} - -pub struct UnsignedJwtPartsWithPadding { - b: Vec, -} - -impl UnsignedJwtPartsWithPadding { - pub fn from_b64_bytes_with_padding(b: &[u8]) -> Self { - Self { b: Vec::from(b) } - } - - pub fn payload_with_padding(&self) -> Result> { - let first_dot = self - .b - .iter() - .position(|c| c == &b'.') - .ok_or_else(|| anyhow!("Not a valid jwt; has no \".\""))?; - - Ok(Vec::from(&self.b[first_dot + 1..])) - } -} - -/// Trait which signals that this type allows conversion into 64-bit limbs. Used for JWT signature -/// and JWK modulus. -pub trait As64BitLimbs { - fn as_64bit_limbs(&self) -> Vec; -} - -impl As64BitLimbs for RSA_JWK { - fn as_64bit_limbs(&self) -> Vec { - let modulus_bytes = base64::decode_config(&self.n, base64::URL_SAFE_NO_PAD) - .expect("JWK should always have a properly-encoded modulus"); - // JWKs encode modulus in big-endian order - let modulus_biguint: BigUint = BigUint::from_bytes_be(&modulus_bytes); - modulus_biguint.to_u64_digits() - } -} - -impl As64BitLimbs for RsaSignature { - fn as_64bit_limbs(&self) -> Vec { - self.to_u64_digits() - } -} diff --git a/keyless/common/src/input_processing/mod.rs b/keyless/common/src/input_processing/mod.rs deleted file mode 100644 index 461913f077516..0000000000000 --- a/keyless/common/src/input_processing/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -pub mod bits; -pub mod circuit_input_signals; -pub mod config; -pub mod encoding; -pub mod sha; -pub mod witness_gen; diff --git a/keyless/common/src/input_processing/sha.rs b/keyless/common/src/input_processing/sha.rs deleted file mode 100644 index 3127d664a95bf..0000000000000 --- a/keyless/common/src/input_processing/sha.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] - -use super::bits::Bits; -use tracing::debug; - -pub fn jwt_bit_len(jwt: &[u8]) -> usize { - jwt.len() * 8 -} - -/// input: jwt as base64 without padding. -/// output: length of bit representation of jwt, encoded in big-endian as 8 bits. -pub fn jwt_bit_len_binary(jwt_unsigned: &[u8]) -> Bits { - let L = jwt_bit_len(jwt_unsigned); - - Bits::raw(&format!("{L:064b}")) -} - -/// input: jwt as base64 without padding. -/// output: bit representation of sha padding -pub fn compute_sha_padding(jwt_unsigned: &[u8]) -> Bits { - let mut padding_bits = Bits::new(); - let L = jwt_bit_len(jwt_unsigned); - // Following the spec linked here: - //https://www.rfc-editor.org/rfc/rfc4634.html#section-4.1 - // Step 4.1.a: add bit '1' - padding_bits += Bits::raw("1"); - // Step 4.1.b Append K '0' bits where K is the smallest non-negative integer solution to L+1+K = 448 mod 512, and L is the length of the message in bits - // i.e., K is smallest non-neg integer such that L + K + 1 + 64 == 0 mod 512 - // we never expect this to cause an error, so unwrapping here is ok - // There was a bug here, which is why we are logging so much - let K_before_mod = 448 - (L as i64) - 1; - debug!("Computing sha padding: K_before_mod={}", K_before_mod); - let K_i64 = K_before_mod.rem_euclid(512); - debug!("Computing sha padding: K_i64={}", K_i64); - let K_usize = usize::try_from(K_i64).unwrap(); - debug!("Computing sha padding: K_usize={}", K_usize); - padding_bits += Bits::raw(&("0".repeat(K_usize))); - // 4.1.c Append L in binary form (big-endian) as 64 bits - padding_bits += jwt_bit_len_binary(jwt_unsigned); - - padding_bits -} - -pub fn compute_sha_padding_without_len(jwt_unsigned: &[u8]) -> Bits { - let mut padding_bits = Bits::new(); - let L = jwt_bit_len(jwt_unsigned); - // Following the spec linked here: - //https://www.rfc-editor.org/rfc/rfc4634.html#section-4.1 - // Step 4.1.a: add bit '1' - padding_bits += Bits::raw("1"); - // Step 4.1.b Append K '0' bits where K is the smallest non-negative integer solution to L+1+K = 448 mod 512, and L is the length of the message in bits - // i.e., K is smallest non-neg integer such that L + K + 1 + 64 == 0 mod 512 - // we never expect this to cause an error, so unwrapping here is ok - // There was a bug here, which is why we are logging so much - let K_before_mod = 448 - (L as i64) - 1; - debug!("Computing sha padding: K_before_mod={}", K_before_mod); - let K_i64 = K_before_mod.rem_euclid(512); - debug!("Computing sha padding: K_i64={}", K_i64); - let K_usize = usize::try_from(K_i64).unwrap(); - debug!("Computing sha padding: K_usize={}", K_usize); - padding_bits += Bits::raw(&("0".repeat(K_usize))); - // Skip 4.1.c - padding_bits -} - -pub fn with_sha_padding_bytes(jwt_unsigned: &[u8]) -> Vec { - (Bits::bit_representation_of_bytes(jwt_unsigned) + compute_sha_padding(jwt_unsigned)) - .as_bytes() - .expect("Should have length a multiple of 8") -} diff --git a/keyless/common/src/input_processing/witness_gen.rs b/keyless/common/src/input_processing/witness_gen.rs deleted file mode 100644 index 6df60c3822113..0000000000000 --- a/keyless/common/src/input_processing/witness_gen.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use anyhow::{anyhow, bail, Result}; -use std::{fs, process::Command}; -use tempfile::NamedTempFile; -use tracing::info_span; - -pub trait PathStr { - fn path_str(&self) -> Result<&str>; -} - -impl PathStr for NamedTempFile { - fn path_str(&self) -> Result<&str> { - self.path() - .to_str() - .ok_or_else(|| anyhow!("tempfile path error")) - } -} - -pub fn witness_gen( - witness_gen_js_path: &str, - witness_gen_wasm_path: &str, - body: &str, -) -> Result { - let span = info_span!("Generating witness"); - let _enter = span.enter(); - let input_file = NamedTempFile::new()?; - let witness_file = NamedTempFile::new()?; - fs::write(input_file.path(), body.as_bytes())?; - let mut cmd = get_witness_command( - witness_gen_js_path, - witness_gen_wasm_path, - input_file.path_str()?, - witness_file.path_str()?, - ); - let output = cmd.output()?; - // Check if the command executed successfully - if output.status.success() { - // if config.enable_dangerous_logging { - // // Convert the output bytes to a string - // let stdout = String::from_utf8_lossy(&output.stdout); - // // Print the output - // println!("Command output:\n{}", stdout); - // } - Ok(witness_file) - } else { - // Print the error message if the command failed - let stderr = String::from_utf8_lossy(&output.stderr); - let stdout = String::from_utf8_lossy(&output.stdout); - bail!("Command failed:\n{}\n{}", stdout, stderr) - } -} - -fn get_witness_command( - witness_gen_js_path: &str, - witness_gen_wasm_path: &str, - input_file_path: &str, - witness_file_path: &str, -) -> Command { - let mut c = Command::new("node"); - c.args(&[ - witness_gen_js_path.to_string(), - witness_gen_wasm_path.to_string(), - String::from(input_file_path), - String::from(witness_file_path), - ]); - c -} diff --git a/keyless/common/src/lib.rs b/keyless/common/src/lib.rs deleted file mode 100644 index 2e9931583c27e..0000000000000 --- a/keyless/common/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -pub mod api; -pub mod input_processing;