├── .bazelrc ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── WORKSPACE └── act ├── BUILD ├── act.h ├── act.proto ├── act_v0 ├── BUILD ├── act_v0.cc ├── act_v0.h ├── act_v0.proto ├── act_v0_test.cc ├── parameters.cc ├── parameters.h ├── parameters_test.cc └── testing │ ├── BUILD │ ├── generate_transcript.cc │ ├── golden_transcript_test.cc │ ├── transcript.proto │ └── transcripts │ ├── golden_transcript_1_09122023 │ ├── golden_transcript_2_09122023 │ └── golden_transcript_3_09122023 ├── fake_act.cc ├── fake_act.h └── fake_act_test.cc /.bazelrc: -------------------------------------------------------------------------------- 1 | # Options for compiling ACT code. 2 | # Include these in dependent workspaces by using the --bazelrc flag, or by 3 | # adding import %act_workspace%/bazel.rc to the .bazelrc file in the 4 | # dependent workspace. 5 | 6 | build -c opt 7 | build --cxxopt='-std=c++17' 8 | build --host_cxxopt='-std=c++17' 9 | 10 | test -c opt 11 | test --cxxopt='-std=c++17' 12 | build --host_cxxopt='-std=c++17' -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Bazel generated symlinks 2 | bazel-* 3 | # Mac files 4 | .DS_Store -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows 28 | [Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # An Implementation of Anonymous Counting Tokens. 2 | 3 | An anonymous counting token (ACT) scheme allows Clients to obtain blind 4 | signatures or MACs (aka tokens) on messages of their choice, while at the same 5 | time enabling Issuers to enforce rate limits on the number of tokens that a 6 | client can obtain for each message. Specifically, 7 | 8 | * Blind issuance: The Issuer doesn't see the message for which a token is 9 | being requested 10 | * Unlinkability: When the Client redeems a token, the token cannot be linked 11 | to the issuance phase 12 | * Throttled issuance on identical messages: The Issuer can detect if a 13 | particular Client is requesting a token for a previously used message. 14 | 15 | This repository implements a variant of the scheme described in [1], which is 16 | secure in the random oracle model under the q-DDHI assumption (in a cyclic 17 | group) and the DCR assumption. The variant implemented here relaxes the proven 18 | soundness guarantee to the non-concurrent setting. It also assumes that the 19 | server generates its parameters correctly. Future versions will support server 20 | proofs for correct parameter generation. 21 | 22 | This implementation also supports batched token issuance. Batched token issuance 23 | can have significant performance benefits as compared to individual token 24 | issuance. 25 | 26 | > [[1] "Anonymous Counting Tokens." Fabrice Benhamouda, Mariana Raykova, Karn 27 | > Seth.](https://eprint.iacr.org/2023/320) 28 | 29 | ## Building/Running Tests 30 | 31 | This repository requires Bazel. You can install Bazel by 32 | following the instructions for your platform on the 33 | [Bazel website](https://docs.bazel.build/versions/master/install.html). 34 | 35 | Once you have installed Bazel you can clone this repository and run all tests 36 | that are included by navigating into the root folder and running: 37 | 38 | ```bash 39 | bazel test //... 40 | ``` 41 | 42 | 43 | ## Disclaimer 44 | 45 | This is not an officially supported Google product. The code is provided as-is, 46 | with no guarantees of correctness or security. -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """WORKSPACE file for Anonymous Counting Tokens code.""" 16 | 17 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 18 | load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") 19 | 20 | # Private Join and Compute 21 | http_archive( 22 | name = "private_join_and_compute", 23 | sha256 = "9304a6fe62c7227657e7cecf08c6234c14dfb558bd6a2fa778de845056fb9dd3", 24 | strip_prefix = "private-join-and-compute-f77f26fab7f37e5e1e2d43250662c0281bd7fa4a", 25 | urls = ["https://github.com/google/private-join-and-compute/archive/f77f26fab7f37e5e1e2d43250662c0281bd7fa4a.zip"], 26 | ) 27 | 28 | # loads boringssl, absl, googletest, protobuf. 29 | load("@private_join_and_compute//bazel:pjc_deps.bzl", "pjc_deps") 30 | pjc_deps() 31 | 32 | load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") 33 | protobuf_deps() 34 | 35 | # gRPC 36 | # must be included separately, since we need to load transitive deps of grpc for 37 | # some of the pjc deps. 38 | http_archive( 39 | name = "com_github_grpc_grpc", 40 | sha256 = "feaeeb315133ea5e3b046c2c0231f5b86ef9d297e536a14b73e0393335f8b157", 41 | strip_prefix = "grpc-1.51.3", 42 | urls = [ 43 | "https://github.com/grpc/grpc/archive/v1.51.3.tar.gz", 44 | ], 45 | ) 46 | 47 | load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") 48 | grpc_deps() 49 | 50 | load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") 51 | grpc_extra_deps() -------------------------------------------------------------------------------- /act/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Contains implementations for Anonymous Counting Tokens. 16 | 17 | load("@rules_cc//cc:defs.bzl", "cc_library") 18 | load("@rules_proto//proto:defs.bzl", "proto_library") 19 | 20 | package(default_visibility = ["//visibility:public"]) 21 | 22 | proto_library( 23 | name = "act_proto", 24 | srcs = ["act.proto"], 25 | deps = ["//act/act_v0:act_v0_proto"], 26 | ) 27 | 28 | cc_proto_library( 29 | name = "act_cc_proto", 30 | deps = [":act_proto"], 31 | ) 32 | 33 | cc_library( 34 | name = "act", 35 | hdrs = ["act.h"], 36 | deps = [ 37 | ":act_cc_proto", 38 | "@private_join_and_compute//private_join_and_compute/util:status_includes", 39 | ], 40 | ) 41 | 42 | cc_library( 43 | name = "fake_act", 44 | srcs = ["fake_act.cc"], 45 | hdrs = ["fake_act.h"], 46 | deps = [ 47 | ":act", 48 | ":act_cc_proto", 49 | "@private_join_and_compute//private_join_and_compute/crypto:bn_util", 50 | "@private_join_and_compute//private_join_and_compute/util:status_includes", 51 | ], 52 | ) 53 | 54 | cc_test( 55 | name = "fake_act_test", 56 | srcs = [ 57 | "fake_act_test.cc", 58 | ], 59 | deps = [ 60 | ":fake_act", 61 | "@com_github_google_googletest//:gtest_main", 62 | "@private_join_and_compute//private_join_and_compute/util:status_includes", 63 | "@private_join_and_compute//private_join_and_compute/util:status_testing_includes", 64 | ], 65 | ) 66 | -------------------------------------------------------------------------------- /act/act.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #ifndef PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_ACT_H_ 17 | #define PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_ACT_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "act/act.pb.h" 25 | #include "private_join_and_compute/util/status.inc" 26 | 27 | namespace private_join_and_compute { 28 | namespace anonymous_counting_tokens { 29 | 30 | // Abstract class for methods related to Anonymous Counting Tokens. 31 | class AnonymousCountingTokens { 32 | public: 33 | virtual ~AnonymousCountingTokens() = default; 34 | 35 | // Implementations should return a fresh set of Server parameters 36 | // corresponding to these SchemeParameters. 37 | virtual StatusOr GenerateServerParameters( 38 | const SchemeParameters& scheme_parameters) = 0; 39 | 40 | // Implementations should return a fresh set of Client parameters 41 | // corresponding to these SchemeParameters and ServerPublicParameters. 42 | virtual StatusOr GenerateClientParameters( 43 | const SchemeParameters& scheme_parameters, 44 | const ServerPublicParameters& server_public_parameters) = 0; 45 | 46 | // Implementations should verify the consistency of these 47 | // ClientPublicParameters with the Server and scheme parameters. 48 | virtual Status CheckClientParameters( 49 | const SchemeParameters& scheme_parameters, 50 | const ClientPublicParameters& client_public_parameters, 51 | const ServerPublicParameters& server_public_parameters, 52 | const ServerPrivateParameters& server_private_parameters) = 0; 53 | 54 | // Implementations should generate a tuple of client_fingerprints, 55 | // TokensRequest and TokensRequestPrivateState for the given set of messages. 56 | virtual StatusOr, TokensRequest, 57 | TokensRequestPrivateState>> 58 | GenerateTokensRequest( 59 | absl::Span messages, 60 | const SchemeParameters& scheme_parameters, 61 | const ClientPublicParameters& client_public_parameters, 62 | const ClientPrivateParameters& client_private_parameters, 63 | const ServerPublicParameters& server_public_parameters) = 0; 64 | 65 | // Implementations should return OkStatus on a valid request. 66 | virtual Status CheckTokensRequest( 67 | absl::Span client_fingerprints, 68 | const TokensRequest& tokens_request, 69 | const SchemeParameters& scheme_parameters, 70 | const ClientPublicParameters& client_public_parameters, 71 | const ServerPublicParameters& server_public_parameters, 72 | const ServerPrivateParameters& server_private_parameters) = 0; 73 | 74 | // Implementations should return the TokensResponse. 75 | virtual StatusOr GenerateTokensResponse( 76 | const TokensRequest& tokens_request, 77 | const SchemeParameters& scheme_parameters, 78 | const ClientPublicParameters& client_public_parameters, 79 | const ServerPublicParameters& server_public_parameters, 80 | const ServerPrivateParameters& server_private_parameters) = 0; 81 | 82 | // Implementations should return OkStatus on a valid response. 83 | virtual Status VerifyTokensResponse( 84 | absl::Span messages, 85 | const TokensRequest& tokens_request, 86 | const TokensRequestPrivateState& tokens_request_private_state, 87 | const TokensResponse& tokens_response, 88 | const SchemeParameters& scheme_parameters, 89 | const ClientPublicParameters& client_public_parameters, 90 | const ClientPrivateParameters& client_private_parameters, 91 | const ServerPublicParameters& server_public_parameters) = 0; 92 | 93 | // Implementations should return a vector of tokens corresponding to the 94 | // supplied messages. 95 | virtual StatusOr> RecoverTokens( 96 | absl::Span messages, 97 | const TokensRequest& tokens_request, 98 | const TokensRequestPrivateState& tokens_request_private_state, 99 | const TokensResponse& tokens_response, 100 | const SchemeParameters& scheme_parameters, 101 | const ClientPublicParameters& client_public_parameters, 102 | const ClientPrivateParameters& client_private_parameters, 103 | const ServerPublicParameters& server_public_parameters) = 0; 104 | 105 | // Implementations should return OkStatus on valid tokens. 106 | virtual Status VerifyToken( 107 | std::string m, const Token& token, 108 | const SchemeParameters& scheme_parameters, 109 | const ServerPublicParameters& server_public_parameters, 110 | const ServerPrivateParameters& server_private_parameters) = 0; 111 | 112 | protected: 113 | AnonymousCountingTokens() = default; 114 | }; 115 | 116 | } // namespace anonymous_counting_tokens 117 | } // namespace private_join_and_compute 118 | 119 | #endif // PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_ACT_H_ 120 | -------------------------------------------------------------------------------- /act/act.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | syntax = "proto3"; 17 | 18 | package private_join_and_compute.anonymous_counting_tokens; 19 | 20 | import "act/act_v0/act_v0.proto"; 21 | 22 | option java_multiple_files = true; 23 | 24 | // The parameters defining the ACT scheme. 25 | message SchemeParameters { 26 | oneof scheme_parameters_oneof { 27 | SchemeParametersV0 scheme_parameters_v0 = 1; 28 | } 29 | } 30 | 31 | message ServerParameters { 32 | ServerPublicParameters public_parameters = 1; 33 | ServerPrivateParameters private_parameters = 2; 34 | } 35 | 36 | // The Server's public parameters for the ACT scheme. 37 | message ServerPublicParameters { 38 | oneof server_public_parameters_oneof { 39 | ServerPublicParametersV0 server_public_parameters_v0 = 1; 40 | } 41 | } 42 | 43 | // The Server's private parameters for the ACT scheme. 44 | message ServerPrivateParameters { 45 | oneof server_private_parameters_oneof { 46 | ServerPrivateParametersV0 server_private_parameters_v0 = 1; 47 | } 48 | } 49 | 50 | message ClientParameters { 51 | ClientPublicParameters public_parameters = 1; 52 | ClientPrivateParameters private_parameters = 2; 53 | } 54 | 55 | // The Client's public parameters for the ACT scheme. 56 | message ClientPublicParameters { 57 | oneof client_public_parameters_oneof { 58 | ClientPublicParametersV0 client_public_parameters_v0 = 1; 59 | } 60 | } 61 | 62 | // The Client's private parameters for the ACT scheme. 63 | message ClientPrivateParameters { 64 | oneof client_private_parameters_oneof { 65 | ClientPrivateParametersV0 client_private_parameters_v0 = 1; 66 | } 67 | } 68 | 69 | // The Client's token request. Can correspond to a batch of tokens. 70 | message TokensRequest { 71 | oneof tokens_request_oneof { 72 | TokensRequestV0 tokens_request_v0 = 1; 73 | } 74 | } 75 | 76 | // Private state corresponding to the Client's token request, needed to recover 77 | // the tokens from the server's response. 78 | message TokensRequestPrivateState { 79 | oneof tokens_request_private_state_oneof { 80 | TokensRequestPrivateStateV0 tokens_request_private_state_v0 = 1; 81 | } 82 | } 83 | 84 | // The Server's response to a TokensRequest. Can correspond to a batch of 85 | // tokens. 86 | message TokensResponse { 87 | oneof tokens_response_oneof { 88 | TokensResponseV0 tokens_response_v0 = 1; 89 | } 90 | } 91 | 92 | // An actual token recovered from the TokenResponse. 93 | message Token { 94 | reserved 1; 95 | 96 | oneof token_oneof { 97 | TokenV0 token_v0 = 2; 98 | } 99 | 100 | // Serialized BigNum corresponding to the nonce for this token. 101 | bytes nonce_bytes = 3; 102 | } 103 | -------------------------------------------------------------------------------- /act/act_v0/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | load("@rules_cc//cc:defs.bzl", "cc_library") 16 | load("@rules_proto//proto:defs.bzl", "proto_library") 17 | 18 | package(default_visibility = ["//visibility:public"]) 19 | 20 | proto_library( 21 | name = "act_v0_proto", 22 | srcs = ["act_v0.proto"], 23 | deps = [ 24 | "@private_join_and_compute//private_join_and_compute/crypto/dodis_yampolskiy_prf:bb_oblivious_signature_proto", 25 | "@private_join_and_compute//private_join_and_compute/crypto/dodis_yampolskiy_prf:dy_verifiable_random_function_proto", 26 | "@private_join_and_compute//private_join_and_compute/crypto/proto:big_num_proto", 27 | "@private_join_and_compute//private_join_and_compute/crypto/proto:camenisch_shoup_proto", 28 | "@private_join_and_compute//private_join_and_compute/crypto/proto:pedersen_proto", 29 | ], 30 | ) 31 | 32 | cc_proto_library( 33 | name = "act_v0_cc_proto", 34 | deps = [":act_v0_proto"], 35 | ) 36 | 37 | cc_library( 38 | name = "act_v0", 39 | srcs = ["act_v0.cc"], 40 | hdrs = ["act_v0.h"], 41 | deps = [ 42 | ":act_v0_cc_proto", 43 | "//act", 44 | "//act:act_cc_proto", 45 | "@private_join_and_compute//private_join_and_compute/crypto:bn_util", 46 | "@private_join_and_compute//private_join_and_compute/crypto:camenisch_shoup", 47 | "@private_join_and_compute//private_join_and_compute/crypto:ec_util", 48 | "@private_join_and_compute//private_join_and_compute/crypto:pedersen_over_zn", 49 | "@private_join_and_compute//private_join_and_compute/crypto/dodis_yampolskiy_prf:bb_oblivious_signature", 50 | "@private_join_and_compute//private_join_and_compute/crypto/dodis_yampolskiy_prf:bb_oblivious_signature_cc_proto", 51 | "@private_join_and_compute//private_join_and_compute/crypto/dodis_yampolskiy_prf:dy_verifiable_random_function", 52 | "@private_join_and_compute//private_join_and_compute/crypto/dodis_yampolskiy_prf:dy_verifiable_random_function_cc_proto", 53 | "@private_join_and_compute//private_join_and_compute/crypto/proto:ec_point_cc_proto", 54 | "@private_join_and_compute//private_join_and_compute/crypto/proto:proto_util", 55 | "@private_join_and_compute//private_join_and_compute/util:status_includes", 56 | ], 57 | ) 58 | 59 | cc_test( 60 | name = "act_v0_test", 61 | srcs = ["act_v0_test.cc"], 62 | deps = [ 63 | ":act_v0", 64 | ":act_v0_cc_proto", 65 | ":parameters", 66 | "//act", 67 | "//act:act_cc_proto", 68 | "@com_github_google_googletest//:gtest_main", 69 | "@private_join_and_compute//private_join_and_compute/crypto:bn_util", 70 | "@private_join_and_compute//private_join_and_compute/crypto:camenisch_shoup", 71 | "@private_join_and_compute//private_join_and_compute/crypto:ec_util", 72 | "@private_join_and_compute//private_join_and_compute/crypto:pedersen_over_zn", 73 | "@private_join_and_compute//private_join_and_compute/crypto/dodis_yampolskiy_prf:bb_oblivious_signature_cc_proto", 74 | "@private_join_and_compute//private_join_and_compute/crypto/dodis_yampolskiy_prf:dy_verifiable_random_function_cc_proto", 75 | "@private_join_and_compute//private_join_and_compute/crypto/proto:big_num_cc_proto", 76 | "@private_join_and_compute//private_join_and_compute/crypto/proto:camenisch_shoup_cc_proto", 77 | "@private_join_and_compute//private_join_and_compute/crypto/proto:pedersen_cc_proto", 78 | "@private_join_and_compute//private_join_and_compute/util:status_includes", 79 | "@private_join_and_compute//private_join_and_compute/util:status_testing_includes", 80 | ], 81 | ) 82 | 83 | cc_library( 84 | name = "parameters", 85 | srcs = ["parameters.cc"], 86 | hdrs = ["parameters.h"], 87 | deps = [ 88 | ":act_v0_cc_proto", 89 | "//act:act_cc_proto", 90 | "@com_google_absl//absl/strings", 91 | "@private_join_and_compute//private_join_and_compute/crypto:openssl_includes", 92 | ], 93 | ) 94 | 95 | cc_test( 96 | name = "parameters_test", 97 | size = "enormous", 98 | srcs = ["parameters_test.cc"], 99 | deps = [ 100 | ":act_v0", 101 | ":parameters", 102 | "//act", 103 | "//act:act_cc_proto", 104 | "@com_github_google_googletest//:gtest_main", 105 | "@com_google_absl//absl/strings", 106 | "@private_join_and_compute//private_join_and_compute/util:status_includes", 107 | "@private_join_and_compute//private_join_and_compute/util:status_testing_includes", 108 | ], 109 | ) 110 | -------------------------------------------------------------------------------- /act/act_v0/act_v0.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #include "act/act_v0/act_v0.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "act/act.pb.h" 25 | #include "act/act_v0/act_v0.pb.h" 26 | #include "private_join_and_compute/crypto/big_num.h" 27 | #include "private_join_and_compute/crypto/camenisch_shoup.h" 28 | #include "private_join_and_compute/crypto/context.h" 29 | #include "private_join_and_compute/crypto/dodis_yampolskiy_prf/bb_oblivious_signature.h" 30 | #include "private_join_and_compute/crypto/dodis_yampolskiy_prf/bb_oblivious_signature.pb.h" 31 | #include "private_join_and_compute/crypto/dodis_yampolskiy_prf/dy_verifiable_random_function.h" 32 | #include "private_join_and_compute/crypto/dodis_yampolskiy_prf/dy_verifiable_random_function.pb.h" 33 | #include "private_join_and_compute/crypto/ec_group.h" 34 | #include "private_join_and_compute/crypto/ec_point.h" 35 | #include "private_join_and_compute/crypto/pedersen_over_zn.h" 36 | #include "private_join_and_compute/crypto/proto/ec_point.pb.h" 37 | #include "private_join_and_compute/crypto/proto/proto_util.h" 38 | 39 | namespace private_join_and_compute { 40 | namespace anonymous_counting_tokens { 41 | 42 | namespace { 43 | 44 | StatusOr> CreateBbObliviousSignature( 45 | const SchemeParametersV0& scheme_parameters_v0, 46 | const ServerPublicParametersV0& server_public_parameters_v0, Context* ctx, 47 | ECGroup* ec_group, PedersenOverZn* pedersen, 48 | PublicCamenischShoup* public_camenisch_shoup) { 49 | proto::BbObliviousSignatureParameters bb_oblivious_signature_parameters; 50 | bb_oblivious_signature_parameters.set_challenge_length_bits( 51 | scheme_parameters_v0.challenge_length_bits()); 52 | bb_oblivious_signature_parameters.set_security_parameter( 53 | scheme_parameters_v0.security_parameter()); 54 | bb_oblivious_signature_parameters.set_random_oracle_prefix( 55 | scheme_parameters_v0.random_oracle_prefix()); 56 | bb_oblivious_signature_parameters.set_base_g( 57 | server_public_parameters_v0.prf_base_g()); 58 | *bb_oblivious_signature_parameters.mutable_pedersen_parameters() = 59 | server_public_parameters_v0.pedersen_parameters(); 60 | *bb_oblivious_signature_parameters.mutable_camenisch_shoup_public_key() = 61 | server_public_parameters_v0.camenisch_shoup_public_key(); 62 | 63 | return BbObliviousSignature::Create( 64 | std::move(bb_oblivious_signature_parameters), ctx, ec_group, 65 | public_camenisch_shoup, pedersen); 66 | } 67 | 68 | StatusOr> CreateDyVrf( 69 | const SchemeParametersV0& scheme_parameters_v0, 70 | const ServerPublicParametersV0& server_public_parameters_v0, Context* ctx, 71 | ECGroup* ec_group, PedersenOverZn* pedersen) { 72 | proto::DyVrfParameters dy_vrf_parameters; 73 | dy_vrf_parameters.set_challenge_length_bits( 74 | scheme_parameters_v0.challenge_length_bits()); 75 | dy_vrf_parameters.set_security_parameter( 76 | scheme_parameters_v0.security_parameter()); 77 | dy_vrf_parameters.set_random_oracle_prefix( 78 | scheme_parameters_v0.random_oracle_prefix()); 79 | dy_vrf_parameters.set_dy_prf_base_g(server_public_parameters_v0.prf_base_g()); 80 | *dy_vrf_parameters.mutable_pedersen_parameters() = 81 | server_public_parameters_v0.pedersen_parameters(); 82 | 83 | return DyVerifiableRandomFunction::Create(std::move(dy_vrf_parameters), ctx, 84 | ec_group, pedersen); 85 | } 86 | 87 | // Used to generate the client-independent portion of the nonce. A different 88 | // nonce is chosen for each element in the batched token request. 89 | StatusOr> GetNoncesForTokenRequest( 90 | Context* ctx, const SchemeParameters& scheme_parameters, 91 | const ServerPublicParameters& server_public_parameters, 92 | const ClientPublicParameters& client_public_parameters, 93 | const TokensRequestV0::Part1& tokens_request_part_1, 94 | uint64_t num_messages) { 95 | // Parses bit length of the random challenge from scheme parameters. 96 | uint64_t challenge_length_bits = 97 | scheme_parameters.scheme_parameters_v0().challenge_length_bits(); 98 | // Computes the upper bound of the challenge and input to the random oracle. 99 | BigNum challenge_upper_bound = ctx->One().Lshift(challenge_length_bits); 100 | 101 | // Note that the random oracle prefix is implicitly included as part of the 102 | // parameters being serialized in the statement proto. We skip including it 103 | // again here to avoid unnecessary duplication. 104 | std::string challenge_string = "GetNoncesForTokenRequest:"; 105 | auto challenge_sos = 106 | std::make_unique( 107 | &challenge_string); 108 | auto challenge_cos = 109 | std::make_unique( 110 | challenge_sos.get()); 111 | challenge_cos->SetSerializationDeterministic(true); 112 | challenge_cos->WriteVarint64(scheme_parameters.ByteSizeLong()); 113 | challenge_cos->WriteString(SerializeAsStringInOrder(scheme_parameters)); 114 | challenge_cos->WriteVarint64(server_public_parameters.ByteSizeLong()); 115 | challenge_cos->WriteString( 116 | SerializeAsStringInOrder(server_public_parameters)); 117 | challenge_cos->WriteVarint64(client_public_parameters.ByteSizeLong()); 118 | challenge_cos->WriteString( 119 | SerializeAsStringInOrder(client_public_parameters)); 120 | challenge_cos->WriteVarint64(tokens_request_part_1.ByteSizeLong()); 121 | challenge_cos->WriteString(SerializeAsStringInOrder(tokens_request_part_1)); 122 | challenge_cos->WriteVarint64(num_messages); 123 | 124 | // Delete the serialization objects to make sure they clean up and write. 125 | challenge_cos.reset(); 126 | challenge_sos.reset(); 127 | 128 | std::vector outputs; 129 | outputs.reserve(num_messages); 130 | for (uint64_t i = 0; i < num_messages; ++i) { 131 | std::string random_oracle_input_i = absl::StrCat(challenge_string, ",", i); 132 | outputs.push_back( 133 | ctx->RandomOracleSha512(random_oracle_input_i, challenge_upper_bound)); 134 | } 135 | 136 | return std::move(outputs); 137 | } 138 | 139 | } // namespace 140 | 141 | std::unique_ptr AnonymousCountingTokensV0::Create() { 142 | return absl::WrapUnique( 143 | new AnonymousCountingTokensV0()); 144 | } 145 | 146 | // Returns a fresh set of Server parameters corresponding to these 147 | // SchemeParameters. Fails with InvalidArgument if the parameters don't 148 | // correspond to ACT v0. 149 | StatusOr AnonymousCountingTokensV0::GenerateServerParameters( 150 | const SchemeParameters& scheme_parameters) { 151 | if (!scheme_parameters.has_scheme_parameters_v0()) { 152 | return absl::InvalidArgumentError( 153 | "AnonymousCountingTokensV0::GenerateServerParameters: supplied " 154 | "parameters do not correspond to ACTv0."); 155 | } 156 | 157 | const SchemeParametersV0& scheme_parameters_v0 = 158 | scheme_parameters.scheme_parameters_v0(); 159 | 160 | Context ctx; 161 | ASSIGN_OR_RETURN(ECGroup ec_group, 162 | ECGroup::Create(scheme_parameters_v0.prf_ec_group(), &ctx)); 163 | 164 | // Choose base g. 165 | ASSIGN_OR_RETURN(ECPoint dy_prf_base_g, ec_group.GetRandomGenerator()); 166 | 167 | // Generate RSA-Modulus and Camenisch-Shoup encryption key. 168 | CamenischShoupKey camenisch_shoup_key = GenerateCamenischShoupKey( 169 | &ctx, scheme_parameters_v0.modulus_length_bits(), 170 | scheme_parameters_v0.camenisch_shoup_s(), 171 | scheme_parameters_v0.vector_encryption_length()); 172 | 173 | BigNum n = camenisch_shoup_key.n; 174 | 175 | auto camenisch_shoup_public_key = std::make_unique( 176 | CamenischShoupPublicKey{camenisch_shoup_key.n, camenisch_shoup_key.s, 177 | camenisch_shoup_key.vector_encryption_length, 178 | camenisch_shoup_key.g, camenisch_shoup_key.ys}); 179 | auto camenisch_shoup_private_key = std::make_unique( 180 | CamenischShoupPrivateKey{camenisch_shoup_key.xs}); 181 | 182 | auto public_camenisch_shoup = std::make_unique( 183 | &ctx, camenisch_shoup_public_key->n, camenisch_shoup_public_key->s, 184 | camenisch_shoup_public_key->g, camenisch_shoup_public_key->ys); 185 | 186 | // Generate Pedersen Parameters. 187 | PedersenOverZn::Parameters pedersen_parameters = 188 | PedersenOverZn::GenerateParameters( 189 | &ctx, n, scheme_parameters_v0.pedersen_batch_size()); 190 | 191 | ASSIGN_OR_RETURN( 192 | std::unique_ptr pedersen, 193 | PedersenOverZn::Create(&ctx, pedersen_parameters.gs, 194 | pedersen_parameters.h, pedersen_parameters.n)); 195 | 196 | ServerParameters server_parameters; 197 | 198 | ServerPublicParametersV0* server_public_parameters_v0 = 199 | server_parameters.mutable_public_parameters() 200 | ->mutable_server_public_parameters_v0(); 201 | ASSIGN_OR_RETURN(*server_public_parameters_v0->mutable_prf_base_g(), 202 | dy_prf_base_g.ToBytesCompressed()); 203 | *server_public_parameters_v0->mutable_pedersen_parameters() = 204 | PedersenOverZn::ParametersToProto(pedersen_parameters); 205 | *server_public_parameters_v0->mutable_camenisch_shoup_public_key() = 206 | CamenischShoupPublicKeyToProto(*camenisch_shoup_public_key); 207 | 208 | ServerPrivateParametersV0* server_private_parameters_v0 = 209 | server_parameters.mutable_private_parameters() 210 | ->mutable_server_private_parameters_v0(); 211 | *server_private_parameters_v0->mutable_camenisch_shoup_private_key() = 212 | CamenischShoupPrivateKeyToProto(*camenisch_shoup_private_key); 213 | 214 | // Generate Boneh-Boyen Oblivious Signature object. This call is safe even 215 | // with the partially-ready server_public_parameters. 216 | ASSIGN_OR_RETURN( 217 | std::unique_ptr bb_oblivious_signature, 218 | CreateBbObliviousSignature(scheme_parameters_v0, 219 | *server_public_parameters_v0, &ctx, &ec_group, 220 | pedersen.get(), public_camenisch_shoup.get())); 221 | 222 | // Generate Boneh-Boyen Oblivious Signature key. 223 | ASSIGN_OR_RETURN( 224 | std::tie(*server_public_parameters_v0 225 | ->mutable_bb_oblivious_signature_public_key(), 226 | *server_private_parameters_v0 227 | ->mutable_bb_oblivious_signature_private_key()), 228 | bb_oblivious_signature->GenerateKeys()); 229 | 230 | return std::move(server_parameters); 231 | } 232 | 233 | // Returns a fresh set of Client parameters corresponding to these 234 | // SchemeParameters and ServerPublicParameters. Fails with InvalidArgument if 235 | // the parameters don't correspond to ACT v0. 236 | StatusOr AnonymousCountingTokensV0::GenerateClientParameters( 237 | const SchemeParameters& scheme_parameters, 238 | const ServerPublicParameters& server_public_parameters) { 239 | if (!scheme_parameters.has_scheme_parameters_v0() || 240 | !server_public_parameters.has_server_public_parameters_v0()) { 241 | return absl::InvalidArgumentError( 242 | "AnonymousCountingTokensV0::GenerateClientParameters: supplied " 243 | "parameters do not correspond to ACT v0."); 244 | } 245 | 246 | const SchemeParametersV0& scheme_parameters_v0 = 247 | scheme_parameters.scheme_parameters_v0(); 248 | const ServerPublicParametersV0& server_public_parameters_v0 = 249 | server_public_parameters.server_public_parameters_v0(); 250 | 251 | Context ctx; 252 | ASSIGN_OR_RETURN(ECGroup ec_group, 253 | ECGroup::Create(scheme_parameters_v0.prf_ec_group(), &ctx)); 254 | 255 | // Deserialize Pedersen Params 256 | ASSIGN_OR_RETURN( 257 | std::unique_ptr pedersen, 258 | PedersenOverZn::FromProto( 259 | &ctx, server_public_parameters_v0.pedersen_parameters())); 260 | 261 | // Generate Client VRF object. 262 | ASSIGN_OR_RETURN( 263 | std::unique_ptr dy_vrf, 264 | CreateDyVrf(scheme_parameters_v0, server_public_parameters_v0, &ctx, 265 | &ec_group, pedersen.get())); 266 | 267 | ClientParameters client_parameters; 268 | ClientPublicParametersV0* client_public_parameters_v0 = 269 | client_parameters.mutable_public_parameters() 270 | ->mutable_client_public_parameters_v0(); 271 | ClientPrivateParametersV0* client_private_parameters_v0 = 272 | client_parameters.mutable_private_parameters() 273 | ->mutable_client_private_parameters_v0(); 274 | 275 | ASSIGN_OR_RETURN( 276 | std::tie( 277 | *client_public_parameters_v0->mutable_dy_vrf_public_key(), 278 | *client_private_parameters_v0->mutable_dy_vrf_private_key(), 279 | *client_public_parameters_v0->mutable_dy_vrf_generate_keys_proof()), 280 | dy_vrf->GenerateKeyPair()); 281 | 282 | return std::move(client_parameters); 283 | } 284 | 285 | // Verifies the consistency of the ClientPublicParameters with the Server and 286 | // scheme parameters. Fails with InvalidArgument if the parameters don't 287 | // correspond to ACT v0. 288 | Status AnonymousCountingTokensV0::CheckClientParameters( 289 | const SchemeParameters& scheme_parameters, 290 | const ClientPublicParameters& client_public_parameters, 291 | const ServerPublicParameters& server_public_parameters, 292 | const ServerPrivateParameters& server_private_parameters) { 293 | if (!scheme_parameters.has_scheme_parameters_v0() || 294 | !client_public_parameters.has_client_public_parameters_v0() || 295 | !server_public_parameters.has_server_public_parameters_v0() || 296 | !server_private_parameters.has_server_private_parameters_v0()) { 297 | return absl::InvalidArgumentError( 298 | "AnonymousCountingTokensV0::CheckClientParameters: supplied " 299 | "parameters do not correspond to ACT v0."); 300 | } 301 | 302 | const SchemeParametersV0& scheme_parameters_v0 = 303 | scheme_parameters.scheme_parameters_v0(); 304 | const ServerPublicParametersV0& server_public_parameters_v0 = 305 | server_public_parameters.server_public_parameters_v0(); 306 | const ClientPublicParametersV0& client_public_parameters_v0 = 307 | client_public_parameters.client_public_parameters_v0(); 308 | Context ctx; 309 | ASSIGN_OR_RETURN(ECGroup ec_group, 310 | ECGroup::Create(scheme_parameters_v0.prf_ec_group(), &ctx)); 311 | 312 | // Deserialize Pedersen Params 313 | ASSIGN_OR_RETURN( 314 | std::unique_ptr pedersen, 315 | PedersenOverZn::FromProto( 316 | &ctx, server_public_parameters_v0.pedersen_parameters())); 317 | 318 | // Generate Client VRF object. 319 | ASSIGN_OR_RETURN( 320 | std::unique_ptr dy_vrf, 321 | CreateDyVrf(scheme_parameters_v0, server_public_parameters_v0, &ctx, 322 | &ec_group, pedersen.get())); 323 | 324 | // Verify the proof for the Client's VRF key. 325 | return dy_vrf->VerifyGenerateKeysProof( 326 | client_public_parameters_v0.dy_vrf_public_key(), 327 | client_public_parameters_v0.dy_vrf_generate_keys_proof()); 328 | } 329 | 330 | // Returns a tuple of client_fingerprints, TokensRequest and 331 | // TokensRequestPrivateState for the given set of messages. Fails with 332 | // InvalidArgument if the parameters don't correspond to ACT v0. 333 | StatusOr, TokensRequest, 334 | TokensRequestPrivateState>> 335 | AnonymousCountingTokensV0::GenerateTokensRequest( 336 | absl::Span messages, 337 | const SchemeParameters& scheme_parameters, 338 | const ClientPublicParameters& client_public_parameters, 339 | const ClientPrivateParameters& client_private_parameters, 340 | const ServerPublicParameters& server_public_parameters) { 341 | if (!scheme_parameters.has_scheme_parameters_v0() || 342 | !client_public_parameters.has_client_public_parameters_v0() || 343 | !client_private_parameters.has_client_private_parameters_v0() || 344 | !server_public_parameters.has_server_public_parameters_v0()) { 345 | return absl::InvalidArgumentError( 346 | "AnonymousCountingTokensV0::GenerateTokensRequest: supplied " 347 | "parameters do not correspond to ACT v0."); 348 | } 349 | 350 | const SchemeParametersV0& scheme_parameters_v0 = 351 | scheme_parameters.scheme_parameters_v0(); 352 | const ClientPublicParametersV0& client_public_parameters_v0 = 353 | client_public_parameters.client_public_parameters_v0(); 354 | const ClientPrivateParametersV0& client_private_parameters_v0 = 355 | client_private_parameters.client_private_parameters_v0(); 356 | const ServerPublicParametersV0& server_public_parameters_v0 = 357 | server_public_parameters.server_public_parameters_v0(); 358 | 359 | TokensRequest tokens_request_proto; 360 | TokensRequestV0* tokens_request_v0 = 361 | tokens_request_proto.mutable_tokens_request_v0(); 362 | TokensRequestV0::Part1* tokens_request_v0_part_1 = 363 | tokens_request_v0->mutable_part_1(); 364 | TokensRequestPrivateState tokens_request_private_state; 365 | 366 | Context ctx; 367 | ASSIGN_OR_RETURN(ECGroup ec_group, 368 | ECGroup::Create(scheme_parameters_v0.prf_ec_group(), &ctx)); 369 | 370 | // Deserialize and create cryptographic objects. 371 | ASSIGN_OR_RETURN( 372 | std::unique_ptr pedersen, 373 | PedersenOverZn::FromProto( 374 | &ctx, server_public_parameters_v0.pedersen_parameters())); 375 | ASSIGN_OR_RETURN( 376 | std::unique_ptr public_camenisch_shoup, 377 | PublicCamenischShoup::FromProto( 378 | &ctx, server_public_parameters_v0.camenisch_shoup_public_key())); 379 | ASSIGN_OR_RETURN( 380 | ECPoint dy_prf_base_g, 381 | ec_group.CreateECPoint(server_public_parameters_v0.prf_base_g())); 382 | 383 | ASSIGN_OR_RETURN( 384 | std::unique_ptr dy_vrf, 385 | CreateDyVrf(scheme_parameters_v0, server_public_parameters_v0, &ctx, 386 | &ec_group, pedersen.get())); 387 | 388 | // Deserialize Boneh-Boyen Oblivious Signature parameters and keys 389 | ASSIGN_OR_RETURN( 390 | std::unique_ptr bb_oblivious_signature, 391 | CreateBbObliviousSignature(scheme_parameters_v0, 392 | server_public_parameters_v0, &ctx, &ec_group, 393 | pedersen.get(), public_camenisch_shoup.get())); 394 | 395 | // 1) Hash all messages to the exponent group/ BigNums. 396 | std::vector hashed_messages; 397 | hashed_messages.reserve(messages.size()); 398 | for (size_t i = 0; i < messages.size(); ++i) { 399 | hashed_messages.push_back( 400 | ctx.RandomOracleSha512(messages[i], ec_group.GetOrder())); 401 | } 402 | 403 | // 2) Commit to hashed messages. 404 | ASSIGN_OR_RETURN( 405 | PedersenOverZn::CommitmentAndOpening commit_and_open_messages, 406 | pedersen->Commit(hashed_messages)); 407 | tokens_request_v0_part_1->set_commit_messages( 408 | commit_and_open_messages.commitment.ToBytes()); 409 | 410 | // 3) Generate client nonces and commit to them. 411 | std::vector client_nonces; 412 | client_nonces.reserve(messages.size()); 413 | for (size_t i = 0; i < messages.size(); ++i) { 414 | client_nonces.push_back(ec_group.GeneratePrivateKey()); 415 | } 416 | ASSIGN_OR_RETURN( 417 | PedersenOverZn::CommitmentAndOpening commit_and_open_client_nonces, 418 | pedersen->Commit(client_nonces)); 419 | tokens_request_v0_part_1->set_commit_client_nonces( 420 | commit_and_open_client_nonces.commitment.ToBytes()); 421 | 422 | // 4) Perform a VRF on the committed messages and serialize as fingerprints. 423 | ASSIGN_OR_RETURN( 424 | std::vector prf_evaluations, 425 | dy_vrf->Apply(hashed_messages, 426 | client_private_parameters_v0.dy_vrf_private_key())); 427 | std::vector fingerprints; 428 | fingerprints.reserve(prf_evaluations.size()); 429 | for (size_t i = 0; i < prf_evaluations.size(); ++i) { 430 | ASSIGN_OR_RETURN(std::string fingerprint, 431 | prf_evaluations[i].ToBytesCompressed()); 432 | fingerprints.push_back(std::move(fingerprint)); 433 | } 434 | 435 | // Also create the proof that the fingerprints were correctly generated. 436 | ASSIGN_OR_RETURN(*tokens_request_v0_part_1->mutable_fingerprints_proof(), 437 | dy_vrf->GenerateApplyProof( 438 | hashed_messages, prf_evaluations, 439 | client_public_parameters_v0.dy_vrf_public_key(), 440 | client_private_parameters_v0.dy_vrf_private_key(), 441 | commit_and_open_messages)); 442 | 443 | // 5) Generate server nonces by hashing the preceding portion of the request. 444 | ASSIGN_OR_RETURN(std::vector server_nonces, 445 | GetNoncesForTokenRequest( 446 | &ctx, scheme_parameters, server_public_parameters, 447 | client_public_parameters, *tokens_request_v0_part_1, 448 | messages.size())); 449 | // We commit the "server_nonces" with randomness 0, which is ok since they 450 | // are known to both parties, and furthermore will be homomorphically added to 451 | // the "client_nonces" which have properly generated randomness. 452 | ASSIGN_OR_RETURN(PedersenOverZn::Commitment commit_server_nonces, 453 | pedersen->CommitWithRand(server_nonces, ctx.Zero())); 454 | 455 | // 6) Homomorphically compute commitments to the nonces (rs) 456 | std::vector nonces; 457 | nonces.reserve(messages.size()); 458 | for (size_t i = 0; i < messages.size(); ++i) { 459 | // No mod performed here, since the homomorphic addition of the commitments 460 | // will not be mod-ed, and we want consistency. 461 | nonces.push_back(server_nonces[i] + client_nonces[i]); 462 | } 463 | PedersenOverZn::Commitment commit_nonce = pedersen->Add( 464 | commit_server_nonces, commit_and_open_client_nonces.commitment); 465 | PedersenOverZn::Opening commit_nonce_opening = 466 | commit_and_open_client_nonces.opening; 467 | 468 | *tokens_request_private_state.mutable_tokens_request_private_state_v0() 469 | ->mutable_nonces() = BigNumVectorToProto(nonces); 470 | 471 | // 7) Generate Boneh-Boyen Oblivious Signature Request request. 472 | ASSIGN_OR_RETURN( 473 | std::tie( 474 | *tokens_request_v0->mutable_bb_oblivious_signature_request(), 475 | *tokens_request_v0->mutable_bb_oblivious_signature_request_proof(), 476 | *tokens_request_private_state 477 | .mutable_tokens_request_private_state_v0() 478 | ->mutable_bb_oblivious_signature_request_private_state()), 479 | bb_oblivious_signature->GenerateRequestAndProof( 480 | hashed_messages, nonces, 481 | server_public_parameters_v0.bb_oblivious_signature_public_key(), 482 | commit_and_open_messages, {commit_nonce, commit_nonce_opening})); 483 | 484 | return std::make_tuple(std::move(fingerprints), 485 | std::move(tokens_request_proto), 486 | std::move(tokens_request_private_state)); 487 | } 488 | 489 | // Returns OkStatus on a valid request. Fails with InvalidArgument if the 490 | // parameters don't correspond to ACT v0. 491 | Status AnonymousCountingTokensV0::CheckTokensRequest( 492 | absl::Span client_fingerprints, 493 | const TokensRequest& tokens_request, 494 | const SchemeParameters& scheme_parameters, 495 | const ClientPublicParameters& client_public_parameters, 496 | const ServerPublicParameters& server_public_parameters, 497 | const ServerPrivateParameters& server_private_parameters) { 498 | if (!tokens_request.has_tokens_request_v0() || 499 | !scheme_parameters.has_scheme_parameters_v0() || 500 | !client_public_parameters.has_client_public_parameters_v0() || 501 | !server_public_parameters.has_server_public_parameters_v0()) { 502 | return absl::InvalidArgumentError( 503 | "AnonymousCountingTokensV0::GenerateTokensResponse: supplied " 504 | "parameters do not correspond to ACT v0."); 505 | } 506 | 507 | const TokensRequestV0& tokens_request_v0 = tokens_request.tokens_request_v0(); 508 | const SchemeParametersV0& scheme_parameters_v0 = 509 | scheme_parameters.scheme_parameters_v0(); 510 | const ClientPublicParametersV0& client_public_parameters_v0 = 511 | client_public_parameters.client_public_parameters_v0(); 512 | const ServerPublicParametersV0& server_public_parameters_v0 = 513 | server_public_parameters.server_public_parameters_v0(); 514 | 515 | Context ctx; 516 | ASSIGN_OR_RETURN(ECGroup ec_group, 517 | ECGroup::Create(scheme_parameters_v0.prf_ec_group(), &ctx)); 518 | 519 | // Deserialize and create cryptographic objects. 520 | ASSIGN_OR_RETURN( 521 | std::unique_ptr pedersen, 522 | PedersenOverZn::FromProto( 523 | &ctx, server_public_parameters_v0.pedersen_parameters())); 524 | ASSIGN_OR_RETURN( 525 | std::unique_ptr public_camenisch_shoup, 526 | PublicCamenischShoup::FromProto( 527 | &ctx, server_public_parameters_v0.camenisch_shoup_public_key())); 528 | 529 | // Construct the DY VRF object 530 | ASSIGN_OR_RETURN( 531 | std::unique_ptr dy_vrf, 532 | CreateDyVrf(scheme_parameters_v0, server_public_parameters_v0, &ctx, 533 | &ec_group, pedersen.get())); 534 | 535 | PedersenOverZn::Commitment commit_messages = ctx.CreateBigNum( 536 | tokens_request.tokens_request_v0().part_1().commit_messages()); 537 | 538 | std::vector deserialized_fingerprints; 539 | deserialized_fingerprints.reserve(client_fingerprints.size()); 540 | for (size_t i = 0; i < client_fingerprints.size(); ++i) { 541 | ASSIGN_OR_RETURN(ECPoint deserialized_fingerprint, 542 | ec_group.CreateECPoint(client_fingerprints[i])); 543 | 544 | // Test that the deserialized fingerprint reserializes to the exact same 545 | // value. 546 | ASSIGN_OR_RETURN(std::string reserialized_fingerprint, 547 | deserialized_fingerprint.ToBytesCompressed()); 548 | if (reserialized_fingerprint != client_fingerprints[i]) { 549 | return absl::InvalidArgumentError(absl::StrCat( 550 | "AnonymousCountingTokensV0::CheckTokensRequest: client_fingerprints[", 551 | i, 552 | "] comes out to a different value when serialized and " 553 | "deserialized.")); 554 | } 555 | 556 | deserialized_fingerprints.push_back(std::move(deserialized_fingerprint)); 557 | } 558 | 559 | RETURN_IF_ERROR(dy_vrf->VerifyApplyProof( 560 | deserialized_fingerprints, 561 | client_public_parameters_v0.dy_vrf_public_key(), commit_messages, 562 | tokens_request_v0.part_1().fingerprints_proof())); 563 | 564 | // Deserialize Boneh-Boyen Oblivious Signature parameters and keys 565 | ASSIGN_OR_RETURN( 566 | std::unique_ptr bb_oblivious_signature, 567 | CreateBbObliviousSignature(scheme_parameters_v0, 568 | server_public_parameters_v0, &ctx, &ec_group, 569 | pedersen.get(), public_camenisch_shoup.get())); 570 | 571 | // Regenerate the commitments to messages and nonces (rs) by replaying the 572 | // steps the client took to generate them. 573 | PedersenOverZn::Commitment commit_client_nonces = ctx.CreateBigNum( 574 | tokens_request.tokens_request_v0().part_1().commit_client_nonces()); 575 | 576 | ASSIGN_OR_RETURN( 577 | std::vector server_nonces, 578 | GetNoncesForTokenRequest( 579 | &ctx, scheme_parameters, server_public_parameters, 580 | client_public_parameters, tokens_request.tokens_request_v0().part_1(), 581 | tokens_request.tokens_request_v0() 582 | .bb_oblivious_signature_request() 583 | .num_messages())); 584 | ASSIGN_OR_RETURN(PedersenOverZn::Commitment commit_server_nonces, 585 | pedersen->CommitWithRand(server_nonces, ctx.Zero())); 586 | PedersenOverZn::Commitment commit_nonce = 587 | pedersen->Add(commit_server_nonces, commit_client_nonces); 588 | 589 | return bb_oblivious_signature->VerifyRequest( 590 | server_public_parameters_v0.bb_oblivious_signature_public_key(), 591 | tokens_request_v0.bb_oblivious_signature_request(), 592 | tokens_request_v0.bb_oblivious_signature_request_proof(), commit_messages, 593 | commit_nonce); 594 | } 595 | 596 | // Returns the TokensResponse. Fails with InvalidArgument if the parameters 597 | // don't correspond to ACT v0. 598 | StatusOr AnonymousCountingTokensV0::GenerateTokensResponse( 599 | const TokensRequest& tokens_request, 600 | const SchemeParameters& scheme_parameters, 601 | const ClientPublicParameters& client_public_parameters, 602 | const ServerPublicParameters& server_public_parameters, 603 | const ServerPrivateParameters& server_private_parameters) { 604 | if (!tokens_request.has_tokens_request_v0() || 605 | !scheme_parameters.has_scheme_parameters_v0() || 606 | !client_public_parameters.has_client_public_parameters_v0() || 607 | !server_public_parameters.has_server_public_parameters_v0() || 608 | !server_private_parameters.has_server_private_parameters_v0()) { 609 | return absl::InvalidArgumentError( 610 | "AnonymousCountingTokensV0::GenerateTokensResponse: supplied " 611 | "parameters do not correspond to ACT v0."); 612 | } 613 | 614 | const TokensRequestV0& tokens_request_v0 = tokens_request.tokens_request_v0(); 615 | const SchemeParametersV0& scheme_parameters_v0 = 616 | scheme_parameters.scheme_parameters_v0(); 617 | const ServerPublicParametersV0& server_public_parameters_v0 = 618 | server_public_parameters.server_public_parameters_v0(); 619 | const ServerPrivateParametersV0& server_private_parameters_v0 = 620 | server_private_parameters.server_private_parameters_v0(); 621 | 622 | TokensResponse tokens_response; 623 | TokensResponseV0* tokens_response_v0 = 624 | tokens_response.mutable_tokens_response_v0(); 625 | 626 | Context ctx; 627 | ASSIGN_OR_RETURN(ECGroup ec_group, 628 | ECGroup::Create(scheme_parameters_v0.prf_ec_group(), &ctx)); 629 | 630 | // Deserialize and create cryptographic objects. 631 | ASSIGN_OR_RETURN( 632 | std::unique_ptr pedersen, 633 | PedersenOverZn::FromProto( 634 | &ctx, server_public_parameters_v0.pedersen_parameters())); 635 | ASSIGN_OR_RETURN( 636 | std::unique_ptr public_camenisch_shoup, 637 | PublicCamenischShoup::FromProto( 638 | &ctx, server_public_parameters_v0.camenisch_shoup_public_key())); 639 | ASSIGN_OR_RETURN( 640 | std::unique_ptr private_camenisch_shoup, 641 | PrivateCamenischShoup::FromProto( 642 | &ctx, server_public_parameters_v0.camenisch_shoup_public_key(), 643 | server_private_parameters_v0.camenisch_shoup_private_key())); 644 | 645 | // Deserialize Boneh-Boyen Oblivious Signature parameters and keys 646 | ASSIGN_OR_RETURN( 647 | std::unique_ptr bb_oblivious_signature, 648 | CreateBbObliviousSignature(scheme_parameters_v0, 649 | server_public_parameters_v0, &ctx, &ec_group, 650 | pedersen.get(), public_camenisch_shoup.get())); 651 | 652 | // Regenerate the commitments to messages and nonces (rs) by replaying the 653 | // steps the client took to generate them. 654 | PedersenOverZn::Commitment commit_messages = ctx.CreateBigNum( 655 | tokens_request.tokens_request_v0().part_1().commit_messages()); 656 | PedersenOverZn::Commitment commit_client_nonces = ctx.CreateBigNum( 657 | tokens_request.tokens_request_v0().part_1().commit_client_nonces()); 658 | 659 | ASSIGN_OR_RETURN( 660 | std::vector server_nonces, 661 | GetNoncesForTokenRequest( 662 | &ctx, scheme_parameters, server_public_parameters, 663 | client_public_parameters, tokens_request.tokens_request_v0().part_1(), 664 | tokens_request.tokens_request_v0() 665 | .bb_oblivious_signature_request() 666 | .num_messages())); 667 | ASSIGN_OR_RETURN(PedersenOverZn::Commitment commit_server_nonces, 668 | pedersen->CommitWithRand(server_nonces, ctx.Zero())); 669 | PedersenOverZn::Commitment commit_nonce = 670 | pedersen->Add(commit_server_nonces, commit_client_nonces); 671 | 672 | // Generate response and proof for the Boneh-Boyen Oblivious Signature. 673 | ASSIGN_OR_RETURN( 674 | std::tie( 675 | *tokens_response_v0->mutable_bb_oblivious_signature_response(), 676 | *tokens_response_v0->mutable_bb_oblivious_signature_response_proof()), 677 | bb_oblivious_signature->GenerateResponseAndProof( 678 | tokens_request_v0.bb_oblivious_signature_request(), 679 | server_public_parameters_v0.bb_oblivious_signature_public_key(), 680 | server_private_parameters_v0.bb_oblivious_signature_private_key(), 681 | commit_messages, commit_nonce, private_camenisch_shoup.get())); 682 | 683 | return std::move(tokens_response); 684 | } 685 | 686 | // Returns OkStatus on a valid response. Fails with InvalidArgument if the 687 | // parameters don't correspond to ACT v0. 688 | Status AnonymousCountingTokensV0::VerifyTokensResponse( 689 | absl::Span messages, const TokensRequest& tokens_request, 690 | const TokensRequestPrivateState& tokens_request_private_state, 691 | const TokensResponse& tokens_response, 692 | const SchemeParameters& scheme_parameters, 693 | const ClientPublicParameters& client_public_parameters, 694 | const ClientPrivateParameters& client_private_parameters, 695 | const ServerPublicParameters& server_public_parameters) { 696 | if (!tokens_request.has_tokens_request_v0() || 697 | !tokens_response.has_tokens_response_v0() || 698 | !tokens_request_private_state.has_tokens_request_private_state_v0() || 699 | !scheme_parameters.has_scheme_parameters_v0() || 700 | !client_public_parameters.has_client_public_parameters_v0() || 701 | !client_private_parameters.has_client_private_parameters_v0() || 702 | !server_public_parameters.has_server_public_parameters_v0()) { 703 | return absl::InvalidArgumentError( 704 | "AnonymousCountingTokensV0::VerifyTokensResponse: supplied " 705 | "parameters do not correspond to ACT v0."); 706 | } 707 | 708 | const TokensRequestV0& tokens_request_v0 = tokens_request.tokens_request_v0(); 709 | const SchemeParametersV0& scheme_parameters_v0 = 710 | scheme_parameters.scheme_parameters_v0(); 711 | const ServerPublicParametersV0& server_public_parameters_v0 = 712 | server_public_parameters.server_public_parameters_v0(); 713 | const TokensResponseV0& tokens_response_v0 = 714 | tokens_response.tokens_response_v0(); 715 | 716 | Context ctx; 717 | ASSIGN_OR_RETURN(ECGroup ec_group, 718 | ECGroup::Create(scheme_parameters_v0.prf_ec_group(), &ctx)); 719 | 720 | // Deserialize and create cryptographic objects. 721 | ASSIGN_OR_RETURN( 722 | std::unique_ptr pedersen, 723 | PedersenOverZn::FromProto( 724 | &ctx, server_public_parameters_v0.pedersen_parameters())); 725 | ASSIGN_OR_RETURN( 726 | std::unique_ptr public_camenisch_shoup, 727 | PublicCamenischShoup::FromProto( 728 | &ctx, server_public_parameters_v0.camenisch_shoup_public_key())); 729 | 730 | // Deserialize Boneh-Boyen Oblivious Signature parameters and keys 731 | ASSIGN_OR_RETURN( 732 | std::unique_ptr bb_oblivious_signature, 733 | CreateBbObliviousSignature(scheme_parameters_v0, 734 | server_public_parameters_v0, &ctx, &ec_group, 735 | pedersen.get(), public_camenisch_shoup.get())); 736 | 737 | // Regenerate the commitments to messages and nonces (rs) by replaying the 738 | // steps the client took to generate them. 739 | PedersenOverZn::Commitment commit_messages = ctx.CreateBigNum( 740 | tokens_request.tokens_request_v0().part_1().commit_messages()); 741 | PedersenOverZn::Commitment commit_client_nonces = ctx.CreateBigNum( 742 | tokens_request.tokens_request_v0().part_1().commit_client_nonces()); 743 | 744 | ASSIGN_OR_RETURN( 745 | std::vector server_nonces, 746 | GetNoncesForTokenRequest( 747 | &ctx, scheme_parameters, server_public_parameters, 748 | client_public_parameters, tokens_request.tokens_request_v0().part_1(), 749 | tokens_request.tokens_request_v0() 750 | .bb_oblivious_signature_request() 751 | .num_messages())); 752 | ASSIGN_OR_RETURN(PedersenOverZn::Commitment commit_server_nonces, 753 | pedersen->CommitWithRand(server_nonces, ctx.Zero())); 754 | PedersenOverZn::Commitment commit_nonce = 755 | pedersen->Add(commit_server_nonces, commit_client_nonces); 756 | 757 | return bb_oblivious_signature->VerifyResponse( 758 | server_public_parameters_v0.bb_oblivious_signature_public_key(), 759 | tokens_response_v0.bb_oblivious_signature_response(), 760 | tokens_response_v0.bb_oblivious_signature_response_proof(), 761 | tokens_request_v0.bb_oblivious_signature_request(), commit_messages, 762 | commit_nonce); 763 | } 764 | 765 | // Returns a vector of tokens corresponding to the supplied messages. Fails 766 | // with InvalidArgument if the parameters don't correspond to ACT v0. 767 | StatusOr> AnonymousCountingTokensV0::RecoverTokens( 768 | absl::Span messages, const TokensRequest& tokens_request, 769 | const TokensRequestPrivateState& tokens_request_private_state, 770 | const TokensResponse& tokens_response, 771 | const SchemeParameters& scheme_parameters, 772 | const ClientPublicParameters& client_public_parameters, 773 | const ClientPrivateParameters& client_private_parameters, 774 | const ServerPublicParameters& server_public_parameters) { 775 | if (!tokens_request.has_tokens_request_v0() || 776 | !tokens_request_private_state.has_tokens_request_private_state_v0() || 777 | !tokens_response.has_tokens_response_v0() || 778 | !scheme_parameters.has_scheme_parameters_v0() || 779 | !client_public_parameters.has_client_public_parameters_v0() || 780 | !client_private_parameters.has_client_private_parameters_v0() || 781 | !server_public_parameters.has_server_public_parameters_v0()) { 782 | return absl::InvalidArgumentError( 783 | "AnonymousCountingTokensV0::VerifyTokensResponse: supplied " 784 | "parameters do not correspond to ACT v0."); 785 | } 786 | 787 | const TokensRequestV0& tokens_request_v0 = tokens_request.tokens_request_v0(); 788 | const TokensRequestPrivateStateV0& tokens_request_private_state_v0 = 789 | tokens_request_private_state.tokens_request_private_state_v0(); 790 | const TokensResponseV0& tokens_response_v0 = 791 | tokens_response.tokens_response_v0(); 792 | const SchemeParametersV0& scheme_parameters_v0 = 793 | scheme_parameters.scheme_parameters_v0(); 794 | const ServerPublicParametersV0& server_public_parameters_v0 = 795 | server_public_parameters.server_public_parameters_v0(); 796 | 797 | Context ctx; 798 | ASSIGN_OR_RETURN(ECGroup ec_group, 799 | ECGroup::Create(scheme_parameters_v0.prf_ec_group(), &ctx)); 800 | 801 | // Deserialize and create cryptographic objects. 802 | ASSIGN_OR_RETURN( 803 | std::unique_ptr pedersen, 804 | PedersenOverZn::FromProto( 805 | &ctx, server_public_parameters_v0.pedersen_parameters())); 806 | ASSIGN_OR_RETURN( 807 | std::unique_ptr public_camenisch_shoup, 808 | PublicCamenischShoup::FromProto( 809 | &ctx, server_public_parameters_v0.camenisch_shoup_public_key())); 810 | ASSIGN_OR_RETURN( 811 | ECPoint dy_prf_base_g, 812 | ec_group.CreateECPoint(server_public_parameters_v0.prf_base_g())); 813 | 814 | // Deserialize Boneh-Boyen Oblivious Signature parameters and keys 815 | ASSIGN_OR_RETURN( 816 | std::unique_ptr bb_oblivious_signature, 817 | CreateBbObliviousSignature(scheme_parameters_v0, 818 | server_public_parameters_v0, &ctx, &ec_group, 819 | pedersen.get(), public_camenisch_shoup.get())); 820 | 821 | // Extract message PRF evaluations 822 | ASSIGN_OR_RETURN(std::vector signatures, 823 | bb_oblivious_signature->ExtractResults( 824 | tokens_response_v0.bb_oblivious_signature_response(), 825 | tokens_request_v0.bb_oblivious_signature_request(), 826 | tokens_request_private_state_v0 827 | .bb_oblivious_signature_request_private_state())); 828 | 829 | // Package tokens. 830 | std::vector nonces = 831 | ParseBigNumVectorProto(&ctx, tokens_request_private_state_v0.nonces()); 832 | 833 | std::vector tokens; 834 | tokens.reserve(messages.size()); 835 | for (size_t i = 0; i < messages.size(); ++i) { 836 | Token token; 837 | TokenV0* token_v0 = token.mutable_token_v0(); 838 | token.set_nonce_bytes(nonces[i].ToBytes()); 839 | ASSIGN_OR_RETURN(*token_v0->mutable_bb_signature(), 840 | signatures[i].ToBytesCompressed()); 841 | tokens.push_back(std::move(token)); 842 | } 843 | 844 | return std::move(tokens); 845 | } 846 | 847 | // Returns OkStatus on valid tokens. Fails with InvalidArgument if the 848 | // parameters don't correspond to ACT v0. 849 | Status AnonymousCountingTokensV0::VerifyToken( 850 | std::string m, const Token& token, 851 | const SchemeParameters& scheme_parameters, 852 | const ServerPublicParameters& server_public_parameters, 853 | const ServerPrivateParameters& server_private_parameters) { 854 | if (!token.has_token_v0() || !scheme_parameters.has_scheme_parameters_v0() || 855 | !server_public_parameters.has_server_public_parameters_v0() || 856 | !server_private_parameters.has_server_private_parameters_v0()) { 857 | return absl::InvalidArgumentError( 858 | "AnonymousCountingTokensV0::VerifyToken: supplied " 859 | "parameters do not correspond to ACT v0."); 860 | } 861 | 862 | const TokenV0& token_v0 = token.token_v0(); 863 | const SchemeParametersV0& scheme_parameters_v0 = 864 | scheme_parameters.scheme_parameters_v0(); 865 | const ServerPublicParametersV0& server_public_parameters_v0 = 866 | server_public_parameters.server_public_parameters_v0(); 867 | const ServerPrivateParametersV0& server_private_parameters_v0 = 868 | server_private_parameters.server_private_parameters_v0(); 869 | 870 | Context ctx; 871 | ASSIGN_OR_RETURN(ECGroup ec_group, 872 | ECGroup::Create(scheme_parameters_v0.prf_ec_group(), &ctx)); 873 | ASSIGN_OR_RETURN( 874 | ECPoint dy_prf_base_g, 875 | ec_group.CreateECPoint(server_public_parameters_v0.prf_base_g())); 876 | BigNum k = ctx.CreateBigNum( 877 | server_private_parameters_v0.bb_oblivious_signature_private_key().k()); 878 | BigNum y = ctx.CreateBigNum( 879 | server_private_parameters_v0.bb_oblivious_signature_private_key().y()); 880 | 881 | BigNum hashed_message = ctx.RandomOracleSha512(m, ec_group.GetOrder()); 882 | BigNum nonce = ctx.CreateBigNum(token.nonce_bytes()); 883 | 884 | // Verify that reserializing the nonce comes out to the same value. 885 | if (nonce.ToBytes() != token.nonce_bytes()) { 886 | return absl::InvalidArgumentError( 887 | "AnonymousCountingTokensV0::VerifyToken: nonce comes out to different " 888 | "value when serialized and deserialized."); 889 | } 890 | 891 | ASSIGN_OR_RETURN(ECPoint signature_from_token, 892 | ec_group.CreateECPoint(token_v0.bb_signature())); 893 | 894 | // Verify that reserializing the signature comes out to the same value 895 | ASSIGN_OR_RETURN(std::string reserialized_signature_from_token, 896 | signature_from_token.ToBytesCompressed()); 897 | if (reserialized_signature_from_token != token_v0.bb_signature()) { 898 | return absl::InvalidArgumentError( 899 | "AnonymousCountingTokensV0::VerifyToken: bb_signature comes out to " 900 | "different value when serialized and deserialized."); 901 | } 902 | 903 | ASSIGN_OR_RETURN( 904 | BigNum inverted_exponent, 905 | (hashed_message + k + (nonce * y)).ModInverse(ec_group.GetOrder())); 906 | ASSIGN_OR_RETURN(ECPoint signature_by_evaluation, 907 | dy_prf_base_g.Mul(inverted_exponent)); 908 | if (signature_by_evaluation != signature_from_token) { 909 | return absl::InvalidArgumentError( 910 | "ACTV0::VerifyToken: Boneh-boyen signature on message and nonce fails " 911 | "to match the token."); 912 | } 913 | 914 | return absl::OkStatus(); 915 | } 916 | 917 | } // namespace anonymous_counting_tokens 918 | } // namespace private_join_and_compute 919 | -------------------------------------------------------------------------------- /act/act_v0/act_v0.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #ifndef PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_ACT_V0_ACT_V0_H_ 17 | #define PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_ACT_V0_ACT_V0_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "act/act.h" 25 | #include "act/act.pb.h" 26 | #include "private_join_and_compute/util/status.inc" 27 | 28 | namespace private_join_and_compute { 29 | namespace anonymous_counting_tokens { 30 | 31 | // An implementation of vO Anonymous Counting Tokens. 32 | class AnonymousCountingTokensV0 : public AnonymousCountingTokens { 33 | public: 34 | static std::unique_ptr Create(); 35 | 36 | // Returns a fresh set of Server parameters corresponding to these 37 | // SchemeParameters. Fails with InvalidArgument if the parameters don't 38 | // correspond to ACT v0. 39 | StatusOr GenerateServerParameters( 40 | const SchemeParameters& scheme_parameters) override; 41 | 42 | // Returns a fresh set of Client parameters corresponding to these 43 | // SchemeParameters and ServerPublicParameters. Fails with InvalidArgument if 44 | // the parameters don't correspond to ACT v0. 45 | StatusOr GenerateClientParameters( 46 | const SchemeParameters& scheme_parameters, 47 | const ServerPublicParameters& server_public_parameters) override; 48 | 49 | // Verifies the consistency of the ClientPublicParameters with the Server and 50 | // scheme parameters. Fails with InvalidArgument if the parameters don't 51 | // correspond to ACT v0. 52 | Status CheckClientParameters( 53 | const SchemeParameters& scheme_parameters, 54 | const ClientPublicParameters& client_public_parameters, 55 | const ServerPublicParameters& server_public_parameters, 56 | const ServerPrivateParameters& server_private_parameters) override; 57 | 58 | // Returns a tuple of client_fingerprints, TokensRequest and 59 | // TokensRequestPrivateState for the given set of messages. Fails with 60 | // InvalidArgument if the parameters don't correspond to ACT v0. 61 | StatusOr, TokensRequest, 62 | TokensRequestPrivateState>> 63 | GenerateTokensRequest( 64 | absl::Span messages, 65 | const SchemeParameters& scheme_parameters, 66 | const ClientPublicParameters& client_public_parameters, 67 | const ClientPrivateParameters& client_private_parameters, 68 | const ServerPublicParameters& server_public_parameters) override; 69 | 70 | // Returns OkStatus on a valid request. Fails with InvalidArgument if the 71 | // parameters don't correspond to ACT v0. 72 | Status CheckTokensRequest( 73 | absl::Span client_fingerprints, 74 | const TokensRequest& tokens_request, 75 | const SchemeParameters& scheme_parameters, 76 | const ClientPublicParameters& client_public_parameters, 77 | const ServerPublicParameters& server_public_parameters, 78 | const ServerPrivateParameters& server_private_parameters) override; 79 | 80 | // Returns the TokensResponse. Fails with InvalidArgument if the parameters 81 | // don't correspond to ACT v0. 82 | StatusOr GenerateTokensResponse( 83 | const TokensRequest& tokens_request, 84 | const SchemeParameters& scheme_parameters, 85 | const ClientPublicParameters& client_public_parameters, 86 | const ServerPublicParameters& server_public_parameters, 87 | const ServerPrivateParameters& server_private_parameters) override; 88 | 89 | // Returns OkStatus on a valid response. Fails with InvalidArgument if the 90 | // parameters don't correspond to ACT v0. 91 | Status VerifyTokensResponse( 92 | absl::Span messages, 93 | const TokensRequest& tokens_request, 94 | const TokensRequestPrivateState& tokens_request_private_state, 95 | const TokensResponse& tokens_response, 96 | const SchemeParameters& scheme_parameters, 97 | const ClientPublicParameters& client_public_parameters, 98 | const ClientPrivateParameters& client_private_parameters, 99 | const ServerPublicParameters& server_public_parameters) override; 100 | 101 | // Returns a vector of tokens corresponding to the supplied messages. Fails 102 | // with InvalidArgument if the parameters don't correspond to ACT v0. 103 | StatusOr> RecoverTokens( 104 | absl::Span messages, 105 | const TokensRequest& tokens_request, 106 | const TokensRequestPrivateState& tokens_request_private_state, 107 | const TokensResponse& tokens_response, 108 | const SchemeParameters& scheme_parameters, 109 | const ClientPublicParameters& client_public_parameters, 110 | const ClientPrivateParameters& client_private_parameters, 111 | const ServerPublicParameters& server_public_parameters) override; 112 | 113 | // Returns OkStatus on valid tokens. Fails with InvalidArgument if the 114 | // parameters don't correspond to ACT v0. 115 | Status VerifyToken( 116 | std::string m, const Token& token, 117 | const SchemeParameters& scheme_parameters, 118 | const ServerPublicParameters& server_public_parameters, 119 | const ServerPrivateParameters& server_private_parameters) override; 120 | 121 | protected: 122 | AnonymousCountingTokensV0() = default; 123 | }; 124 | 125 | } // namespace anonymous_counting_tokens 126 | } // namespace private_join_and_compute 127 | 128 | #endif // PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_ACT_V0_ACT_V0_H_ 129 | -------------------------------------------------------------------------------- /act/act_v0/act_v0.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | syntax = "proto3"; 17 | 18 | package private_join_and_compute.anonymous_counting_tokens; 19 | 20 | import "private_join_and_compute/crypto/dodis_yampolskiy_prf/bb_oblivious_signature.proto"; 21 | import "private_join_and_compute/crypto/dodis_yampolskiy_prf/dy_verifiable_random_function.proto"; 22 | import "private_join_and_compute/crypto/proto/big_num.proto"; 23 | import "private_join_and_compute/crypto/proto/camenisch_shoup.proto"; 24 | import "private_join_and_compute/crypto/proto/pedersen.proto"; 25 | 26 | option java_multiple_files = true; 27 | 28 | // The parameters for ACTv0. 29 | message SchemeParametersV0 { 30 | // How many masking bits (more than the challenge bits) to add in the sigma 31 | // protocols. 32 | uint64 security_parameter = 1; 33 | // How many bits the challenge has. 34 | uint64 challenge_length_bits = 2; 35 | // Length for the RSA modulus. 36 | uint64 modulus_length_bits = 3; 37 | // Camenisch Shoup Damgard-Jurik parameter (message space is n^s). 38 | uint64 camenisch_shoup_s = 4; 39 | // Camenisch-Shoup vector-encryption parameter. 40 | uint64 vector_encryption_length = 5; 41 | // Number of messages that can be committed in a single Pedersen commitment. 42 | uint64 pedersen_batch_size = 6; 43 | // Specification of the EC Group in which the DY-PRF and Boneh Boyen Oblivious 44 | // Signature will be computed. 45 | uint64 prf_ec_group = 7; 46 | // Prefix to attach to any random oracle query (optional). 47 | string random_oracle_prefix = 8; 48 | } 49 | 50 | // The Server's public parameters for the ACTv0 scheme. 51 | message ServerPublicParametersV0 { 52 | reserved 1, 4, 5; 53 | 54 | // Parameters to use for commitments. 55 | private_join_and_compute.proto.PedersenParameters pedersen_parameters = 2; 56 | // Camenisch Shoup public key (for the Boneh-Boyen Oblivious Signature). 57 | private_join_and_compute.proto.CamenischShoupPublicKey camenisch_shoup_public_key = 3; 58 | // Public key for the Boneh-Boyen oblivious signature. 59 | private_join_and_compute.proto.BbObliviousSignaturePublicKey 60 | bb_oblivious_signature_public_key = 6; 61 | 62 | // Serialized ECPoint corresponding to the base g to use for the DY PRF and 63 | // Boneh-Boyen oblivious signature. 64 | bytes prf_base_g = 7; 65 | 66 | } 67 | 68 | // The Server's private parameters for the ACTv0 scheme. 69 | message ServerPrivateParametersV0 { 70 | reserved 2, 3; 71 | // Camenisch Shoup private key (for the Boneh-Boyen Oblivious Signature). 72 | private_join_and_compute.proto.CamenischShoupPrivateKey camenisch_shoup_private_key = 1; 73 | // Private key for the Boneh-Boyen Oblivious Signature. 74 | private_join_and_compute.proto.BbObliviousSignaturePrivateKey 75 | bb_oblivious_signature_private_key = 4; 76 | } 77 | 78 | // The Client's public parameters for the ACT scheme. 79 | message ClientPublicParametersV0 { 80 | // Public key for the DY Verifiable Random Function. 81 | private_join_and_compute.proto.DyVrfPublicKey dy_vrf_public_key = 1; 82 | private_join_and_compute.proto.DyVrfGenerateKeysProof dy_vrf_generate_keys_proof = 2; 83 | } 84 | 85 | // The Client's private parameters for the ACT scheme. 86 | message ClientPrivateParametersV0 { 87 | // Private key for the DY Verifiable Random Function. 88 | private_join_and_compute.proto.DyVrfPrivateKey dy_vrf_private_key = 1; 89 | } 90 | 91 | // The Client's token request. Can correspond to a batch of tokens. 92 | message TokensRequestV0 { 93 | message Part1 { 94 | bytes commit_messages = 1; 95 | bytes commit_client_nonces = 2; 96 | 97 | // Proofs that the fingerprints on the messages were generated correctly. 98 | // The fingerprints correspond to PRF evaluations on the messages. 99 | private_join_and_compute.proto.DyVrfApplyProof fingerprints_proof = 3; 100 | } 101 | 102 | // Part1 of the tokens request feeds into the Random Oracle to produce the 103 | // client-independent portion of the nonces. (The nonce per-token consists 104 | // of a client-chosen part, and a client-independent/not-chosen part. The 105 | // latter is generated by a random oracle call.) 106 | Part1 part_1 = 1; 107 | 108 | // Boneh-Boyen Oblivious Signature request and proof for nonces. 109 | private_join_and_compute.proto.BbObliviousSignatureRequest bb_oblivious_signature_request = 2; 110 | private_join_and_compute.proto.BbObliviousSignatureRequestProof 111 | bb_oblivious_signature_request_proof = 3; 112 | } 113 | 114 | // Private state corresponding to the Client's token request, needed to recover 115 | // the tokens from the server's response. 116 | message TokensRequestPrivateStateV0 { 117 | private_join_and_compute.proto.BbObliviousSignatureRequestPrivateState 118 | bb_oblivious_signature_request_private_state = 1; 119 | // Stores the nonces generated as part of the request (includes the 120 | // client-generated and random-oracle-generated portions combined). 121 | private_join_and_compute.proto.BigNumVector nonces = 2; 122 | } 123 | 124 | // The Server's response to a TokensRequest. Can correspond to a batch of 125 | // tokens. 126 | message TokensResponseV0 { 127 | // Boneh-Boyen Oblivious signature response and proof. 128 | private_join_and_compute.proto.BbObliviousSignatureResponse bb_oblivious_signature_response = 129 | 1; 130 | private_join_and_compute.proto.BbObliviousSignatureResponseProof 131 | bb_oblivious_signature_response_proof = 2; 132 | } 133 | 134 | // An actual token recovered from the TokenResponse. 135 | message TokenV0 { 136 | // The nonce is stored in the enclosing Token proto. 137 | 138 | // Serialized Boneh-Boyen signature on the message and nonce. Serialized 139 | // ECPoint. 140 | bytes bb_signature = 1; 141 | } 142 | -------------------------------------------------------------------------------- /act/act_v0/act_v0_test.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #include "act/act_v0/act_v0.h" 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "act/act.h" 27 | #include "act/act.pb.h" 28 | #include "act/act_v0/act_v0.pb.h" 29 | #include "act/act_v0/parameters.h" 30 | #include "private_join_and_compute/crypto/camenisch_shoup.h" 31 | #include "private_join_and_compute/crypto/context.h" 32 | #include "private_join_and_compute/crypto/dodis_yampolskiy_prf/bb_oblivious_signature.pb.h" 33 | #include "private_join_and_compute/crypto/dodis_yampolskiy_prf/dy_verifiable_random_function.pb.h" 34 | #include "private_join_and_compute/crypto/ec_group.h" 35 | #include "private_join_and_compute/crypto/ec_point.h" 36 | #include "private_join_and_compute/crypto/pedersen_over_zn.h" 37 | #include "private_join_and_compute/crypto/proto/big_num.pb.h" 38 | #include "private_join_and_compute/crypto/proto/camenisch_shoup.pb.h" 39 | #include "private_join_and_compute/crypto/proto/pedersen.pb.h" 40 | #include "private_join_and_compute/util/status.inc" 41 | #include "private_join_and_compute/util/status_testing.inc" 42 | 43 | namespace private_join_and_compute { 44 | namespace anonymous_counting_tokens { 45 | namespace { 46 | 47 | using ::testing::HasSubstr; 48 | using testing::StatusIs; 49 | 50 | const int kTestCurveId = NID_X9_62_prime256v1; 51 | 52 | class AnonymousCountingTokensV0Test : public ::testing::Test { 53 | protected: 54 | static std::string GetRandomOraclePrefix() { 55 | return "TestRandomOraclePrefix"; 56 | } 57 | 58 | static SchemeParameters GetSchemeParameters() { 59 | return ActV0TestSchemeParameters(); 60 | } 61 | 62 | static void SetUpTestSuite() { 63 | std::unique_ptr act = 64 | AnonymousCountingTokensV0::Create(); 65 | ServerParameters server_parameters_temp = 66 | act->GenerateServerParameters(GetSchemeParameters()).value(); 67 | server_parameters_ = new ServerParameters(server_parameters_temp); 68 | } 69 | 70 | static void TearDownTestSuite() { delete server_parameters_; } 71 | 72 | void SetUp() override { 73 | anonymous_counting_tokens_ = AnonymousCountingTokensV0::Create(); 74 | 75 | ASSERT_OK_AND_ASSIGN(auto ec_group_do_not_use_later, 76 | ECGroup::Create(kTestCurveId, &ctx_)); 77 | ec_group_ = std::make_unique(std::move(ec_group_do_not_use_later)); 78 | 79 | // Deserialize components of the precomputed server parameters. 80 | ASSERT_OK_AND_ASSIGN(PedersenOverZn::Parameters pedersen_parameters, 81 | PedersenOverZn::ParseParametersProto( 82 | &ctx_, server_parameters_->public_parameters() 83 | .server_public_parameters_v0() 84 | .pedersen_parameters())); 85 | ASSERT_OK_AND_ASSIGN( 86 | pedersen_, 87 | PedersenOverZn::Create(&ctx_, pedersen_parameters.gs, 88 | pedersen_parameters.h, pedersen_parameters.n)); 89 | 90 | dy_prf_base_g_ = std::make_unique( 91 | ec_group_ 92 | ->CreateECPoint(server_parameters_->public_parameters() 93 | .server_public_parameters_v0() 94 | .prf_base_g()) 95 | .value()); 96 | 97 | cs_public_key_ = std::make_unique( 98 | ParseCamenischShoupPublicKeyProto( 99 | &ctx_, server_parameters_->public_parameters() 100 | .server_public_parameters_v0() 101 | .camenisch_shoup_public_key()) 102 | .value()); 103 | cs_private_key_ = std::make_unique( 104 | ParseCamenischShoupPrivateKeyProto( 105 | &ctx_, server_parameters_->private_parameters() 106 | .server_private_parameters_v0() 107 | .camenisch_shoup_private_key()) 108 | .value()); 109 | 110 | public_camenisch_shoup_ = std::make_unique( 111 | &ctx_, cs_public_key_->n, cs_public_key_->s, cs_public_key_->g, 112 | cs_public_key_->ys); 113 | private_camenisch_shoup_ = std::make_unique( 114 | &ctx_, cs_public_key_->n, cs_public_key_->s, cs_public_key_->g, 115 | cs_public_key_->ys, cs_private_key_->xs); 116 | 117 | ASSERT_OK_AND_ASSIGN( 118 | client_parameters_, 119 | anonymous_counting_tokens_->GenerateClientParameters( 120 | GetSchemeParameters(), server_parameters_->public_parameters())); 121 | } 122 | 123 | // Holds a transcript for an EndToEnd request. 124 | struct Transcript { 125 | std::vector fingerprints; 126 | TokensRequest tokens_request; 127 | TokensRequestPrivateState tokens_request_private_state; 128 | TokensResponse tokens_response; 129 | std::vector tokens; 130 | }; 131 | 132 | // Generates an end-to-end request transcript. Does not verify request or 133 | // response proofs. 134 | StatusOr GenerateTranscript( 135 | absl::Span messages) { 136 | Transcript transcript; 137 | ASSIGN_OR_RETURN( 138 | std::tie(transcript.fingerprints, transcript.tokens_request, 139 | transcript.tokens_request_private_state), 140 | anonymous_counting_tokens_->GenerateTokensRequest( 141 | messages, GetSchemeParameters(), 142 | client_parameters_.public_parameters(), 143 | client_parameters_.private_parameters(), 144 | server_parameters_->public_parameters())); 145 | 146 | ASSIGN_OR_RETURN(transcript.tokens_response, 147 | anonymous_counting_tokens_->GenerateTokensResponse( 148 | transcript.tokens_request, GetSchemeParameters(), 149 | client_parameters_.public_parameters(), 150 | server_parameters_->public_parameters(), 151 | server_parameters_->private_parameters())); 152 | 153 | ASSIGN_OR_RETURN( 154 | transcript.tokens, 155 | anonymous_counting_tokens_->RecoverTokens( 156 | messages, transcript.tokens_request, 157 | transcript.tokens_request_private_state, transcript.tokens_response, 158 | GetSchemeParameters(), client_parameters_.public_parameters(), 159 | client_parameters_.private_parameters(), 160 | server_parameters_->public_parameters())); 161 | 162 | return std::move(transcript); 163 | } 164 | 165 | // Server Parameters, generated once and available to be reused across tests 166 | // to save expensive safe modulus computation. 167 | static ServerParameters* server_parameters_; 168 | 169 | // Instance of AnonymousCountingTokensV0. 170 | std::unique_ptr anonymous_counting_tokens_; 171 | 172 | Context ctx_; 173 | std::unique_ptr ec_group_; 174 | 175 | // Deserialized objects from the saved serialized parameters above. 176 | std::unique_ptr pedersen_; 177 | std::unique_ptr dy_prf_base_g_; 178 | std::unique_ptr cs_public_key_; 179 | std::unique_ptr cs_private_key_; 180 | std::unique_ptr public_camenisch_shoup_; 181 | std::unique_ptr private_camenisch_shoup_; 182 | 183 | // Client parameters for AnonymousCountingTokensV0. 184 | ClientParameters client_parameters_; 185 | }; 186 | 187 | ServerParameters* AnonymousCountingTokensV0Test::server_parameters_ = nullptr; 188 | 189 | TEST_F(AnonymousCountingTokensV0Test, ServerParametersHasNonEmptyFields) { 190 | // Expect all fields are nonempty. 191 | EXPECT_TRUE(server_parameters_->has_public_parameters()); 192 | EXPECT_TRUE(server_parameters_->public_parameters() 193 | .has_server_public_parameters_v0()); 194 | EXPECT_FALSE(server_parameters_->public_parameters() 195 | .server_public_parameters_v0() 196 | .prf_base_g() 197 | .empty()); 198 | EXPECT_TRUE(server_parameters_->public_parameters() 199 | .server_public_parameters_v0() 200 | .has_pedersen_parameters()); 201 | EXPECT_TRUE(server_parameters_->public_parameters() 202 | .server_public_parameters_v0() 203 | .has_camenisch_shoup_public_key()); 204 | EXPECT_TRUE(server_parameters_->public_parameters() 205 | .server_public_parameters_v0() 206 | .has_bb_oblivious_signature_public_key()); 207 | 208 | EXPECT_TRUE(server_parameters_->has_private_parameters()); 209 | EXPECT_TRUE(server_parameters_->private_parameters() 210 | .has_server_private_parameters_v0()); 211 | EXPECT_TRUE(server_parameters_->private_parameters() 212 | .server_private_parameters_v0() 213 | .has_camenisch_shoup_private_key()); 214 | EXPECT_TRUE(server_parameters_->private_parameters() 215 | .server_private_parameters_v0() 216 | .has_bb_oblivious_signature_private_key()); 217 | } 218 | 219 | TEST_F(AnonymousCountingTokensV0Test, GeneratesDifferentServerParameters) { 220 | ASSERT_OK_AND_ASSIGN(ServerParameters other_server_parameters, 221 | anonymous_counting_tokens_->GenerateServerParameters( 222 | GetSchemeParameters())); 223 | 224 | // Expect all fields in the public parameters are different across the 2 225 | // keys. 226 | EXPECT_NE(server_parameters_->public_parameters() 227 | .server_public_parameters_v0() 228 | .prf_base_g(), 229 | other_server_parameters.public_parameters() 230 | .server_public_parameters_v0() 231 | .prf_base_g()); 232 | EXPECT_NE(server_parameters_->public_parameters() 233 | .server_public_parameters_v0() 234 | .pedersen_parameters() 235 | .gs() 236 | .serialized_big_nums(0), 237 | other_server_parameters.public_parameters() 238 | .server_public_parameters_v0() 239 | .pedersen_parameters() 240 | .gs() 241 | .serialized_big_nums(0)); 242 | EXPECT_NE(server_parameters_->public_parameters() 243 | .server_public_parameters_v0() 244 | .camenisch_shoup_public_key() 245 | .ys() 246 | .serialized_big_nums(0), 247 | other_server_parameters.public_parameters() 248 | .server_public_parameters_v0() 249 | .camenisch_shoup_public_key() 250 | .ys() 251 | .serialized_big_nums(0)); 252 | EXPECT_NE(server_parameters_->public_parameters() 253 | .server_public_parameters_v0() 254 | .bb_oblivious_signature_public_key() 255 | .encrypted_k(0) 256 | .u(), 257 | other_server_parameters.public_parameters() 258 | .server_public_parameters_v0() 259 | .bb_oblivious_signature_public_key() 260 | .encrypted_k(0) 261 | .u()); 262 | EXPECT_NE(server_parameters_->public_parameters() 263 | .server_public_parameters_v0() 264 | .bb_oblivious_signature_public_key() 265 | .encrypted_y(0) 266 | .u(), 267 | other_server_parameters.public_parameters() 268 | .server_public_parameters_v0() 269 | .bb_oblivious_signature_public_key() 270 | .encrypted_y(0) 271 | .u()); 272 | } 273 | 274 | TEST_F(AnonymousCountingTokensV0Test, ClientParametersHaveValidFields) { 275 | EXPECT_TRUE(client_parameters_.has_public_parameters()); 276 | EXPECT_TRUE( 277 | client_parameters_.public_parameters().has_client_public_parameters_v0()); 278 | EXPECT_TRUE(client_parameters_.public_parameters() 279 | .client_public_parameters_v0() 280 | .has_dy_vrf_public_key()); 281 | 282 | EXPECT_TRUE(client_parameters_.has_private_parameters()); 283 | EXPECT_TRUE(client_parameters_.private_parameters() 284 | .has_client_private_parameters_v0()); 285 | EXPECT_TRUE(client_parameters_.private_parameters() 286 | .client_private_parameters_v0() 287 | .has_dy_vrf_private_key()); 288 | } 289 | 290 | TEST_F(AnonymousCountingTokensV0Test, GeneratesDifferentClientParameters) { 291 | ASSERT_OK_AND_ASSIGN( 292 | ClientParameters other_client_parameters, 293 | anonymous_counting_tokens_->GenerateClientParameters( 294 | GetSchemeParameters(), server_parameters_->public_parameters())); 295 | 296 | EXPECT_NE(client_parameters_.public_parameters() 297 | .client_public_parameters_v0() 298 | .dy_vrf_public_key() 299 | .commit_prf_key(), 300 | other_client_parameters.public_parameters() 301 | .client_public_parameters_v0() 302 | .dy_vrf_public_key() 303 | .commit_prf_key()); 304 | } 305 | 306 | TEST_F(AnonymousCountingTokensV0Test, ProofFromOtherClientParametersFails) { 307 | ASSERT_OK_AND_ASSIGN( 308 | ClientParameters other_client_parameters, 309 | anonymous_counting_tokens_->GenerateClientParameters( 310 | GetSchemeParameters(), server_parameters_->public_parameters())); 311 | 312 | *client_parameters_.mutable_public_parameters() 313 | ->mutable_client_public_parameters_v0() 314 | ->mutable_dy_vrf_generate_keys_proof() = 315 | other_client_parameters.public_parameters() 316 | .client_public_parameters_v0() 317 | .dy_vrf_generate_keys_proof(); 318 | 319 | EXPECT_THAT( 320 | anonymous_counting_tokens_->CheckClientParameters( 321 | GetSchemeParameters(), client_parameters_.public_parameters(), 322 | server_parameters_->public_parameters(), 323 | server_parameters_->private_parameters()), 324 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed"))); 325 | } 326 | 327 | TEST_F(AnonymousCountingTokensV0Test, ClientParametersPassCheck) { 328 | EXPECT_OK(anonymous_counting_tokens_->CheckClientParameters( 329 | GetSchemeParameters(), client_parameters_.public_parameters(), 330 | server_parameters_->public_parameters(), 331 | server_parameters_->private_parameters())); 332 | } 333 | 334 | TEST_F(AnonymousCountingTokensV0Test, ClientParametersWithoutActV0FailCheck) { 335 | client_parameters_.mutable_public_parameters() 336 | ->clear_client_public_parameters_v0(); 337 | 338 | EXPECT_THAT(anonymous_counting_tokens_->CheckClientParameters( 339 | GetSchemeParameters(), client_parameters_.public_parameters(), 340 | server_parameters_->public_parameters(), 341 | server_parameters_->private_parameters()), 342 | StatusIs(absl::StatusCode::kInvalidArgument, 343 | HasSubstr("CheckClientParameters"))); 344 | } 345 | 346 | TEST_F(AnonymousCountingTokensV0Test, EmptyClientParametersProofFailsCheck) { 347 | client_parameters_.mutable_public_parameters() 348 | ->mutable_client_public_parameters_v0() 349 | ->clear_dy_vrf_generate_keys_proof(); 350 | 351 | EXPECT_THAT( 352 | anonymous_counting_tokens_->CheckClientParameters( 353 | GetSchemeParameters(), client_parameters_.public_parameters(), 354 | server_parameters_->public_parameters(), 355 | server_parameters_->private_parameters()), 356 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed"))); 357 | } 358 | 359 | TEST_F(AnonymousCountingTokensV0Test, GeneratesTokenRequest) { 360 | EXPECT_OK(anonymous_counting_tokens_->GenerateTokensRequest( 361 | {"message_0", "message_1", "message_2"}, GetSchemeParameters(), 362 | client_parameters_.public_parameters(), 363 | client_parameters_.private_parameters(), 364 | server_parameters_->public_parameters())); 365 | } 366 | 367 | TEST_F(AnonymousCountingTokensV0Test, FingerprintsMatchOnlyForEqualMessages) { 368 | std::vector fingerprints_1; 369 | ASSERT_OK_AND_ASSIGN( 370 | std::tie(fingerprints_1, std::ignore, std::ignore), 371 | anonymous_counting_tokens_->GenerateTokensRequest( 372 | {"message_0", "message_1", "message_2"}, GetSchemeParameters(), 373 | client_parameters_.public_parameters(), 374 | client_parameters_.private_parameters(), 375 | server_parameters_->public_parameters())); 376 | 377 | std::vector fingerprints_2; 378 | ASSERT_OK_AND_ASSIGN( 379 | std::tie(fingerprints_2, std::ignore, std::ignore), 380 | anonymous_counting_tokens_->GenerateTokensRequest( 381 | {"message_2", "message_3", "message_4"}, GetSchemeParameters(), 382 | client_parameters_.public_parameters(), 383 | client_parameters_.private_parameters(), 384 | server_parameters_->public_parameters())); 385 | 386 | // Fingerprints should be equal only for "message_2". 387 | EXPECT_EQ(fingerprints_1[2], fingerprints_2[0]); 388 | 389 | for (size_t i = 1; i < fingerprints_1.size(); ++i) { 390 | for (size_t j = 0; j < fingerprints_2.size(); ++j) { 391 | if (!(i == 2 && j == 0)) { 392 | EXPECT_NE(fingerprints_1[i], fingerprints_2[j]); 393 | } 394 | } 395 | } 396 | } 397 | 398 | TEST_F(AnonymousCountingTokensV0Test, TokensRequestIsValid) { 399 | std::vector messages = {"message_1", "message_2", "message_3"}; 400 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 401 | EXPECT_OK(anonymous_counting_tokens_->CheckTokensRequest( 402 | transcript.fingerprints, transcript.tokens_request, GetSchemeParameters(), 403 | client_parameters_.public_parameters(), 404 | server_parameters_->public_parameters(), 405 | server_parameters_->private_parameters())); 406 | } 407 | 408 | TEST_F(AnonymousCountingTokensV0Test, 409 | TokensRequestProofFailsWithDifferentFingerprints) { 410 | std::vector messages_1 = {"message_1", "message_2", "message_3"}; 411 | ASSERT_OK_AND_ASSIGN(Transcript transcript_1, GenerateTranscript(messages_1)); 412 | std::vector messages_2 = {"message_4", "message_5", "message_6"}; 413 | ASSERT_OK_AND_ASSIGN(Transcript transcript_2, GenerateTranscript(messages_2)); 414 | // fingerprints from the second transcript should not allow the proof to 415 | // verify. 416 | EXPECT_THAT( 417 | anonymous_counting_tokens_->CheckTokensRequest( 418 | transcript_2.fingerprints, transcript_1.tokens_request, 419 | GetSchemeParameters(), client_parameters_.public_parameters(), 420 | server_parameters_->public_parameters(), 421 | server_parameters_->private_parameters()), 422 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("failed"))); 423 | } 424 | 425 | TEST_F(AnonymousCountingTokensV0Test, 426 | TokensRequestProofFailsWithWrongNumberOfFingerprints) { 427 | std::vector messages = {"message_1", "message_2", "message_3"}; 428 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 429 | // delete one of the fingerprints. 430 | transcript.fingerprints.pop_back(); 431 | EXPECT_THAT( 432 | anonymous_counting_tokens_->CheckTokensRequest( 433 | transcript.fingerprints, transcript.tokens_request, 434 | GetSchemeParameters(), client_parameters_.public_parameters(), 435 | server_parameters_->public_parameters(), 436 | server_parameters_->private_parameters()), 437 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Number"))); 438 | } 439 | 440 | TEST_F(AnonymousCountingTokensV0Test, 441 | BbSignatureRequestFromDifferentTranscriptIsInvalid) { 442 | std::vector messages = {"message_1", "message_2", "message_3"}; 443 | ASSERT_OK_AND_ASSIGN(Transcript transcript_1, GenerateTranscript(messages)); 444 | ASSERT_OK_AND_ASSIGN(Transcript transcript_2, GenerateTranscript(messages)); 445 | // Replace the bb oblivious signature request from the first transcript with 446 | // that from the second. 447 | *transcript_1.tokens_request.mutable_tokens_request_v0() 448 | ->mutable_bb_oblivious_signature_request() = 449 | transcript_2.tokens_request.tokens_request_v0() 450 | .bb_oblivious_signature_request(); 451 | EXPECT_THAT( 452 | anonymous_counting_tokens_->CheckTokensRequest( 453 | transcript_1.fingerprints, transcript_1.tokens_request, 454 | GetSchemeParameters(), client_parameters_.public_parameters(), 455 | server_parameters_->public_parameters(), 456 | server_parameters_->private_parameters()), 457 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed"))); 458 | } 459 | 460 | TEST_F(AnonymousCountingTokensV0Test, 461 | FingerprintsProofFromDifferentTranscriptIsInvalid) { 462 | std::vector messages = {"message_1", "message_2", "message_3"}; 463 | ASSERT_OK_AND_ASSIGN(Transcript transcript_1, GenerateTranscript(messages)); 464 | ASSERT_OK_AND_ASSIGN(Transcript transcript_2, GenerateTranscript(messages)); 465 | // Replace the fingerprints proof from the first transcript with 466 | // that from the second. 467 | *transcript_1.tokens_request.mutable_tokens_request_v0() 468 | ->mutable_part_1() 469 | ->mutable_fingerprints_proof() = 470 | transcript_2.tokens_request.tokens_request_v0() 471 | .part_1() 472 | .fingerprints_proof(); 473 | EXPECT_THAT( 474 | anonymous_counting_tokens_->CheckTokensRequest( 475 | transcript_1.fingerprints, transcript_1.tokens_request, 476 | GetSchemeParameters(), client_parameters_.public_parameters(), 477 | server_parameters_->public_parameters(), 478 | server_parameters_->private_parameters()), 479 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("failed"))); 480 | } 481 | 482 | TEST_F(AnonymousCountingTokensV0Test, 483 | BbSignatureRequestProofFromDifferentTranscriptIsInvalid) { 484 | std::vector messages = {"message_1", "message_2", "message_3"}; 485 | ASSERT_OK_AND_ASSIGN(Transcript transcript_1, GenerateTranscript(messages)); 486 | ASSERT_OK_AND_ASSIGN(Transcript transcript_2, GenerateTranscript(messages)); 487 | // Replace the bb signature request proof from the first transcript with 488 | // that from the second. 489 | *transcript_1.tokens_request.mutable_tokens_request_v0() 490 | ->mutable_bb_oblivious_signature_request_proof() = 491 | transcript_2.tokens_request.tokens_request_v0() 492 | .bb_oblivious_signature_request_proof(); 493 | EXPECT_THAT( 494 | anonymous_counting_tokens_->CheckTokensRequest( 495 | transcript_1.fingerprints, transcript_1.tokens_request, 496 | GetSchemeParameters(), client_parameters_.public_parameters(), 497 | server_parameters_->public_parameters(), 498 | server_parameters_->private_parameters()), 499 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed"))); 500 | } 501 | 502 | TEST_F(AnonymousCountingTokensV0Test, EmptyRequestIsInvalid) { 503 | std::vector messages = {"message_1", "message_2", "message_3"}; 504 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 505 | transcript.tokens_request.clear_tokens_request_v0(); 506 | EXPECT_THAT(anonymous_counting_tokens_->CheckTokensRequest( 507 | transcript.fingerprints, transcript.tokens_request, 508 | GetSchemeParameters(), client_parameters_.public_parameters(), 509 | server_parameters_->public_parameters(), 510 | server_parameters_->private_parameters()), 511 | StatusIs(absl::StatusCode::kInvalidArgument, 512 | HasSubstr("supplied parameters"))); 513 | } 514 | 515 | TEST_F(AnonymousCountingTokensV0Test, 516 | RequestWithoutFingerprintsProofIsInvalid) { 517 | std::vector messages = {"message_1", "message_2", "message_3"}; 518 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 519 | transcript.tokens_request.mutable_tokens_request_v0() 520 | ->mutable_part_1() 521 | ->clear_fingerprints_proof(); 522 | EXPECT_THAT( 523 | anonymous_counting_tokens_->CheckTokensRequest( 524 | transcript.fingerprints, transcript.tokens_request, 525 | GetSchemeParameters(), client_parameters_.public_parameters(), 526 | server_parameters_->public_parameters(), 527 | server_parameters_->private_parameters()), 528 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Number"))); 529 | } 530 | 531 | TEST_F(AnonymousCountingTokensV0Test, 532 | RequestWithoutBbSignatureRequestProofIsInvalid) { 533 | std::vector messages = {"message_1", "message_2", "message_3"}; 534 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 535 | transcript.tokens_request.mutable_tokens_request_v0() 536 | ->clear_bb_oblivious_signature_request_proof(); 537 | EXPECT_THAT( 538 | anonymous_counting_tokens_->CheckTokensRequest( 539 | transcript.fingerprints, transcript.tokens_request, 540 | GetSchemeParameters(), client_parameters_.public_parameters(), 541 | server_parameters_->public_parameters(), 542 | server_parameters_->private_parameters()), 543 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("number"))); 544 | } 545 | 546 | TEST_F(AnonymousCountingTokensV0Test, GeneratesTokenResponse) { 547 | TokensRequest tokens_request; 548 | ASSERT_OK_AND_ASSIGN( 549 | std::tie(std::ignore, tokens_request, std::ignore), 550 | anonymous_counting_tokens_->GenerateTokensRequest( 551 | {"message_0", "message_1", "message_2"}, GetSchemeParameters(), 552 | client_parameters_.public_parameters(), 553 | client_parameters_.private_parameters(), 554 | server_parameters_->public_parameters())); 555 | 556 | EXPECT_OK(anonymous_counting_tokens_->GenerateTokensResponse( 557 | tokens_request, GetSchemeParameters(), 558 | client_parameters_.public_parameters(), 559 | server_parameters_->public_parameters(), 560 | server_parameters_->private_parameters())); 561 | } 562 | 563 | TEST_F(AnonymousCountingTokensV0Test, TokensResponseIsValid) { 564 | std::vector messages = {"message_1", "message_2", "message_3"}; 565 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 566 | EXPECT_OK(anonymous_counting_tokens_->VerifyTokensResponse( 567 | messages, transcript.tokens_request, 568 | transcript.tokens_request_private_state, transcript.tokens_response, 569 | GetSchemeParameters(), client_parameters_.public_parameters(), 570 | client_parameters_.private_parameters(), 571 | server_parameters_->public_parameters())); 572 | } 573 | 574 | TEST_F(AnonymousCountingTokensV0Test, 575 | TokensResponseIsInvalidForProofFromAnotherTranscript) { 576 | std::vector messages = {"message_1", "message_2", "message_3"}; 577 | ASSERT_OK_AND_ASSIGN(Transcript transcript_1, GenerateTranscript(messages)); 578 | ASSERT_OK_AND_ASSIGN(Transcript transcript_2, GenerateTranscript(messages)); 579 | // Put the proof from the second transcript into the first 580 | *transcript_1.tokens_response.mutable_tokens_response_v0() 581 | ->mutable_bb_oblivious_signature_response_proof() = 582 | transcript_2.tokens_response.tokens_response_v0() 583 | .bb_oblivious_signature_response_proof(); 584 | EXPECT_THAT( 585 | anonymous_counting_tokens_->VerifyTokensResponse( 586 | messages, transcript_1.tokens_request, 587 | transcript_1.tokens_request_private_state, 588 | transcript_1.tokens_response, GetSchemeParameters(), 589 | client_parameters_.public_parameters(), 590 | client_parameters_.private_parameters(), 591 | server_parameters_->public_parameters()), 592 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed"))); 593 | } 594 | 595 | TEST_F(AnonymousCountingTokensV0Test, 596 | TokensResponseIsInvalidForRequestFromAnotherTranscript) { 597 | std::vector messages = {"message_1", "message_2", "message_3"}; 598 | ASSERT_OK_AND_ASSIGN(Transcript transcript_1, GenerateTranscript(messages)); 599 | ASSERT_OK_AND_ASSIGN(Transcript transcript_2, GenerateTranscript(messages)); 600 | // The request and state from transcript_1 should be inconsistent with the 601 | // response from transcript_2. 602 | EXPECT_THAT( 603 | anonymous_counting_tokens_->VerifyTokensResponse( 604 | messages, transcript_1.tokens_request, 605 | transcript_1.tokens_request_private_state, 606 | transcript_2.tokens_response, GetSchemeParameters(), 607 | client_parameters_.public_parameters(), 608 | client_parameters_.private_parameters(), 609 | server_parameters_->public_parameters()), 610 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("Failed"))); 611 | } 612 | 613 | TEST_F(AnonymousCountingTokensV0Test, EmptyResponseShouldBeInvalid) { 614 | std::vector messages = {"message_1", "message_2", "message_3"}; 615 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 616 | 617 | transcript.tokens_response.clear_tokens_response_v0(); 618 | 619 | EXPECT_THAT( 620 | anonymous_counting_tokens_->VerifyTokensResponse( 621 | messages, transcript.tokens_request, 622 | transcript.tokens_request_private_state, transcript.tokens_response, 623 | GetSchemeParameters(), client_parameters_.public_parameters(), 624 | client_parameters_.private_parameters(), 625 | server_parameters_->public_parameters()), 626 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("parameters"))); 627 | } 628 | 629 | TEST_F(AnonymousCountingTokensV0Test, EmptyResponseProofShouldBeInvalid) { 630 | std::vector messages = {"message_1", "message_2", "message_3"}; 631 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 632 | 633 | transcript.tokens_response.mutable_tokens_response_v0() 634 | ->clear_bb_oblivious_signature_response_proof(); 635 | 636 | EXPECT_THAT( 637 | anonymous_counting_tokens_->VerifyTokensResponse( 638 | messages, transcript.tokens_request, 639 | transcript.tokens_request_private_state, transcript.tokens_response, 640 | GetSchemeParameters(), client_parameters_.public_parameters(), 641 | client_parameters_.private_parameters(), 642 | server_parameters_->public_parameters()), 643 | StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("number"))); 644 | } 645 | 646 | TEST_F(AnonymousCountingTokensV0Test, ProducesValidTokens) { 647 | std::vector messages = {"message_1", "message_2", "message_3"}; 648 | 649 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 650 | 651 | EXPECT_EQ(messages.size(), transcript.tokens.size()); 652 | 653 | for (size_t i = 0; i < messages.size(); ++i) { 654 | EXPECT_OK(anonymous_counting_tokens_->VerifyToken( 655 | messages[i], transcript.tokens[i], GetSchemeParameters(), 656 | server_parameters_->public_parameters(), 657 | server_parameters_->private_parameters())); 658 | } 659 | } 660 | 661 | TEST_F(AnonymousCountingTokensV0Test, TokensDoNotVerifyWithWrongMessages) { 662 | std::vector messages = {"message_1", "message_2", "message_3"}; 663 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 664 | 665 | for (size_t i = 0; i < messages.size(); ++i) { 666 | EXPECT_THAT( 667 | anonymous_counting_tokens_->VerifyToken( 668 | "wrong_message", transcript.tokens[i], GetSchemeParameters(), 669 | server_parameters_->public_parameters(), 670 | server_parameters_->private_parameters()), 671 | StatusIs(absl::StatusCode::kInvalidArgument, 672 | HasSubstr("fails to match the token"))); 673 | } 674 | } 675 | 676 | TEST_F(AnonymousCountingTokensV0Test, TokensHaveUniqueNonces) { 677 | std::vector messages = {"message_1", "message_2"}; 678 | ASSERT_OK_AND_ASSIGN(Transcript transcript, GenerateTranscript(messages)); 679 | 680 | EXPECT_NE(transcript.tokens[0].nonce_bytes(), 681 | transcript.tokens[1].nonce_bytes()); 682 | } 683 | 684 | } // namespace 685 | } // namespace anonymous_counting_tokens 686 | } // namespace private_join_and_compute 687 | -------------------------------------------------------------------------------- /act/act_v0/parameters.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #include "act/act_v0/parameters.h" 17 | 18 | #include 19 | 20 | #include "absl/strings/str_cat.h" 21 | #include "act/act_v0/act_v0.pb.h" 22 | 23 | namespace private_join_and_compute { 24 | namespace anonymous_counting_tokens { 25 | 26 | SchemeParameters ActV0TestSchemeParameters() { 27 | int test_modulus_length = 1536; 28 | int batch_size = 3; 29 | std::string random_oracle_prefix = "ActV0TestSchemeParameters"; 30 | 31 | SchemeParameters scheme_parameters; 32 | SchemeParametersV0* scheme_parameters_v0 = 33 | scheme_parameters.mutable_scheme_parameters_v0(); 34 | scheme_parameters_v0->set_security_parameter(kDefaultSecurityParameter); 35 | scheme_parameters_v0->set_challenge_length_bits(kDefaultChallengeLength); 36 | scheme_parameters_v0->set_modulus_length_bits(test_modulus_length); 37 | scheme_parameters_v0->set_camenisch_shoup_s(kDefaultCamenischShoupS); 38 | scheme_parameters_v0->set_vector_encryption_length(batch_size); 39 | scheme_parameters_v0->set_pedersen_batch_size(batch_size); 40 | scheme_parameters_v0->set_prf_ec_group(kDefaultCurveId); 41 | scheme_parameters_v0->set_random_oracle_prefix(random_oracle_prefix); 42 | 43 | return scheme_parameters; 44 | } 45 | 46 | SchemeParameters ActV0Batch16SchemeParameters() { 47 | int batch_size = 16; 48 | std::string random_oracle_prefix = "ActV0Batch16SchemeParameters"; 49 | 50 | SchemeParameters scheme_parameters; 51 | SchemeParametersV0* scheme_parameters_v0 = 52 | scheme_parameters.mutable_scheme_parameters_v0(); 53 | scheme_parameters_v0->set_security_parameter(kDefaultSecurityParameter); 54 | scheme_parameters_v0->set_challenge_length_bits(kDefaultChallengeLength); 55 | scheme_parameters_v0->set_modulus_length_bits(kDefaultModulusLengthBits); 56 | scheme_parameters_v0->set_camenisch_shoup_s(kDefaultCamenischShoupS); 57 | scheme_parameters_v0->set_vector_encryption_length(batch_size); 58 | scheme_parameters_v0->set_pedersen_batch_size(batch_size); 59 | scheme_parameters_v0->set_prf_ec_group(kDefaultCurveId); 60 | scheme_parameters_v0->set_random_oracle_prefix(random_oracle_prefix); 61 | 62 | return scheme_parameters; 63 | } 64 | 65 | SchemeParameters ActV0Batch32SchemeParameters() { 66 | int batch_size = 32; 67 | std::string random_oracle_prefix = "ActV0Batch32SchemeParameters"; 68 | 69 | SchemeParameters scheme_parameters; 70 | SchemeParametersV0* scheme_parameters_v0 = 71 | scheme_parameters.mutable_scheme_parameters_v0(); 72 | scheme_parameters_v0->set_security_parameter(kDefaultSecurityParameter); 73 | scheme_parameters_v0->set_challenge_length_bits(kDefaultChallengeLength); 74 | scheme_parameters_v0->set_modulus_length_bits(kDefaultModulusLengthBits); 75 | scheme_parameters_v0->set_camenisch_shoup_s(kDefaultCamenischShoupS); 76 | scheme_parameters_v0->set_vector_encryption_length(batch_size); 77 | scheme_parameters_v0->set_pedersen_batch_size(batch_size); 78 | scheme_parameters_v0->set_prf_ec_group(kDefaultCurveId); 79 | scheme_parameters_v0->set_random_oracle_prefix(random_oracle_prefix); 80 | 81 | return scheme_parameters; 82 | } 83 | 84 | // Returns parameters supporting 32 messages in a batch, with CS vector 85 | // encryption length set to 2, and modulus length 2048. 86 | SchemeParameters 87 | ActV0SchemeParametersPedersen32Modulus2048CamenischShoupVector2() { 88 | int pedersen_batch_size = 32; 89 | int modulus_length = 2048; 90 | int camensich_shoup_vector_encryption_length = 2; 91 | 92 | return ActV0SchemeParameters(pedersen_batch_size, modulus_length, 93 | camensich_shoup_vector_encryption_length); 94 | } 95 | 96 | // Returns custom parameters. 97 | SchemeParameters ActV0SchemeParameters(int pedersen_batch_size, 98 | int modulus_length_bits, 99 | int camenisch_shoup_vector_length) { 100 | std::string random_oracle_prefix = absl::StrCat( 101 | "ActV0SchemeParametersPedersenBatchSize", pedersen_batch_size, 102 | "ModulusLengthBits", modulus_length_bits, "CamenischShoupVectorLength", 103 | camenisch_shoup_vector_length); 104 | 105 | SchemeParameters scheme_parameters; 106 | SchemeParametersV0* scheme_parameters_v0 = 107 | scheme_parameters.mutable_scheme_parameters_v0(); 108 | scheme_parameters_v0->set_security_parameter(kDefaultSecurityParameter); 109 | scheme_parameters_v0->set_challenge_length_bits(kDefaultChallengeLength); 110 | scheme_parameters_v0->set_modulus_length_bits(modulus_length_bits); 111 | scheme_parameters_v0->set_camenisch_shoup_s(kDefaultCamenischShoupS); 112 | scheme_parameters_v0->set_vector_encryption_length( 113 | camenisch_shoup_vector_length); 114 | scheme_parameters_v0->set_pedersen_batch_size(pedersen_batch_size); 115 | scheme_parameters_v0->set_prf_ec_group(kDefaultCurveId); 116 | scheme_parameters_v0->set_random_oracle_prefix(random_oracle_prefix); 117 | 118 | return scheme_parameters; 119 | } 120 | 121 | } // namespace anonymous_counting_tokens 122 | } // namespace private_join_and_compute 123 | -------------------------------------------------------------------------------- /act/act_v0/parameters.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #ifndef PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_ACT_V0_PARAMETERS_H_ 17 | #define PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_ACT_V0_PARAMETERS_H_ 18 | 19 | #include 20 | 21 | #include "act/act.pb.h" 22 | #include "private_join_and_compute/crypto/openssl.inc" 23 | 24 | namespace private_join_and_compute { 25 | namespace anonymous_counting_tokens { 26 | 27 | const int kDefaultSecurityParameter = 128; 28 | const int kDefaultChallengeLength = 128; 29 | const int kDefaultCamenischShoupS = 1; 30 | const int kDefaultCurveId = NID_X9_62_prime256v1; 31 | const int kDefaultModulusLengthBits = 3072; 32 | 33 | // Returns parameters appropriate only for testing (smaller modulus of 1536 34 | // bits, smaller batch size of 3). 35 | SchemeParameters ActV0TestSchemeParameters(); 36 | 37 | // Returns parameters supporting 16 messages in a batch, with both Pedersen and 38 | // CS parameters set to 16, and modulus length 3072. 39 | SchemeParameters ActV0Batch16SchemeParameters(); 40 | 41 | // Returns parameters supporting 32 messages in a batch, with both Pedersen and 42 | // CS parameters set to 32, and modulus length 3072. 43 | SchemeParameters ActV0Batch32SchemeParameters(); 44 | 45 | // Returns parameters supporting 32 messages in a batch, with CS vector 46 | // encryption length set to 2, and modulus length 2048. 47 | // 48 | // These parameters are currently the best-optimized for performance. 49 | SchemeParameters 50 | ActV0SchemeParametersPedersen32Modulus2048CamenischShoupVector2(); 51 | 52 | // Returns custom parameters. 53 | SchemeParameters ActV0SchemeParameters(int pedersen_batch_size, 54 | int modulus_length_bits, 55 | int camenisch_shoup_vector_length); 56 | 57 | } // namespace anonymous_counting_tokens 58 | } // namespace private_join_and_compute 59 | 60 | #endif // PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_ACT_V0_PARAMETERS_H_ 61 | -------------------------------------------------------------------------------- /act/act_v0/parameters_test.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #include "act/act_v0/parameters.h" 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "act/act.h" 27 | #include "act/act.pb.h" 28 | #include "act/act_v0/act_v0.h" 29 | #include "private_join_and_compute/util/status.inc" 30 | #include "private_join_and_compute/util/status_testing.inc" 31 | 32 | namespace private_join_and_compute { 33 | namespace anonymous_counting_tokens { 34 | namespace { 35 | 36 | Status EndToEndTest(SchemeParameters scheme_parameters, int num_messages) { 37 | std::unique_ptr act = 38 | AnonymousCountingTokensV0::Create(); 39 | 40 | // Generate server parameters. 41 | ASSIGN_OR_RETURN(ServerParameters server_parameters, 42 | act->GenerateServerParameters(scheme_parameters)); 43 | 44 | // Generate client parameters and check them. 45 | ASSIGN_OR_RETURN( 46 | ClientParameters client_parameters, 47 | act->GenerateClientParameters(scheme_parameters, 48 | server_parameters.public_parameters())); 49 | 50 | RETURN_IF_ERROR(act->CheckClientParameters( 51 | scheme_parameters, client_parameters.public_parameters(), 52 | server_parameters.public_parameters(), 53 | server_parameters.private_parameters())); 54 | 55 | // Generate messages. 56 | std::vector messages; 57 | messages.reserve(num_messages); 58 | for (int i = 0; i < num_messages; ++i) { 59 | messages.push_back(absl::StrCat("message", i)); 60 | } 61 | 62 | // Generate Tokens Request and check it. 63 | std::vector client_fingerprints; 64 | TokensRequest tokens_request; 65 | TokensRequestPrivateState tokens_request_private_state; 66 | ASSIGN_OR_RETURN( 67 | std::tie(client_fingerprints, tokens_request, 68 | tokens_request_private_state), 69 | act->GenerateTokensRequest(messages, scheme_parameters, 70 | client_parameters.public_parameters(), 71 | client_parameters.private_parameters(), 72 | server_parameters.public_parameters())); 73 | RETURN_IF_ERROR(act->CheckTokensRequest( 74 | client_fingerprints, tokens_request, scheme_parameters, 75 | client_parameters.public_parameters(), 76 | server_parameters.public_parameters(), 77 | server_parameters.private_parameters())); 78 | 79 | // Generate Tokens Response and check it. 80 | ASSIGN_OR_RETURN( 81 | TokensResponse tokens_response, 82 | act->GenerateTokensResponse(tokens_request, scheme_parameters, 83 | client_parameters.public_parameters(), 84 | server_parameters.public_parameters(), 85 | server_parameters.private_parameters())); 86 | RETURN_IF_ERROR(act->VerifyTokensResponse( 87 | messages, tokens_request, tokens_request_private_state, tokens_response, 88 | scheme_parameters, client_parameters.public_parameters(), 89 | client_parameters.private_parameters(), 90 | server_parameters.public_parameters())); 91 | 92 | // Extract Tokens. 93 | ASSIGN_OR_RETURN( 94 | std::vector tokens, 95 | act->RecoverTokens(messages, tokens_request, tokens_request_private_state, 96 | tokens_response, scheme_parameters, 97 | client_parameters.public_parameters(), 98 | client_parameters.private_parameters(), 99 | server_parameters.public_parameters())); 100 | 101 | // Verify Tokens. 102 | if (tokens.size() != num_messages) { 103 | return absl::InvalidArgumentError("Wrong number of tokens produced"); 104 | } 105 | for (int i = 0; i < num_messages; ++i) { 106 | RETURN_IF_ERROR(act->VerifyToken(messages[i], tokens[i], scheme_parameters, 107 | server_parameters.public_parameters(), 108 | server_parameters.private_parameters())); 109 | } 110 | return absl::OkStatus(); 111 | } 112 | 113 | TEST(ActV0ParametersTest, EndToEndWithTestParameters) { 114 | EXPECT_OK(EndToEndTest(ActV0TestSchemeParameters(), 3)); 115 | } 116 | 117 | TEST(ActV0ParametersTest, EndToEndWithBatch16Parameters) { 118 | EXPECT_OK(EndToEndTest(ActV0Batch16SchemeParameters(), 16)); 119 | } 120 | 121 | TEST(ActV0ParametersTest, EndToEndWithBatch32Parameters) { 122 | EXPECT_OK(EndToEndTest(ActV0Batch32SchemeParameters(), 32)); 123 | } 124 | 125 | TEST(ActV0ParametersTest, EndToEndWithBatch32Cs2Modulus2048Parameters) { 126 | EXPECT_OK(EndToEndTest( 127 | ActV0SchemeParametersPedersen32Modulus2048CamenischShoupVector2(), 32)); 128 | } 129 | 130 | TEST(ActV0ParametersTest, EndToEndWithCustomParameters) { 131 | int pedersen_batch_size = 32; 132 | int modulus_length_bits = 1576; 133 | int camenisch_shoup_vector_length = 2; 134 | EXPECT_OK(EndToEndTest( 135 | ActV0SchemeParameters(pedersen_batch_size, modulus_length_bits, 136 | camenisch_shoup_vector_length), 137 | 32)); 138 | } 139 | 140 | // More extensive tests are in act_v0_test.cc. These tests simply ensure that 141 | // the parameters are functional. 142 | 143 | } // namespace 144 | } // namespace anonymous_counting_tokens 145 | } // namespace private_join_and_compute 146 | -------------------------------------------------------------------------------- /act/act_v0/testing/BUILD: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Google LLC. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | load("@rules_cc//cc:defs.bzl", "cc_library") 16 | load("@rules_proto//proto:defs.bzl", "proto_library") 17 | 18 | package(default_visibility = ["//visibility:public"]) 19 | 20 | proto_library( 21 | name = "transcript_proto", 22 | srcs = ["transcript.proto"], 23 | deps = ["//act:act_proto"], 24 | ) 25 | 26 | cc_proto_library( 27 | name = "transcript_cc_proto", 28 | deps = [":transcript_proto"], 29 | ) 30 | 31 | cc_binary( 32 | name = "generate_transcript", 33 | srcs = ["generate_transcript.cc"], 34 | deps = [ 35 | ":transcript_cc_proto", 36 | "//act", 37 | "//act:act_cc_proto", 38 | "//act/act_v0", 39 | "//act/act_v0:act_v0_cc_proto", 40 | "//act/act_v0:parameters", 41 | "@com_google_absl//absl/flags:flag", 42 | "@com_google_absl//absl/flags:parse", 43 | "@com_google_absl//absl/log", 44 | "@com_google_absl//absl/log:check", 45 | "@com_google_absl//absl/strings", 46 | "@private_join_and_compute//private_join_and_compute/util:proto_util", 47 | "@private_join_and_compute//private_join_and_compute/util:status_includes", 48 | ], 49 | ) 50 | 51 | filegroup( 52 | name = "transcripts", 53 | testonly = 1, 54 | srcs = glob(["transcripts/*"]), 55 | ) 56 | 57 | cc_test( 58 | name = "golden_transcript_test", 59 | srcs = ["golden_transcript_test.cc"], 60 | data = [ 61 | ":transcripts", 62 | ], 63 | deps = [ 64 | ":transcript_cc_proto", 65 | "//act", 66 | "//act:act_cc_proto", 67 | "//act/act_v0", 68 | "//act/act_v0:act_v0_cc_proto", 69 | "//act/act_v0:parameters", 70 | "@com_github_google_googletest//:gtest_main", 71 | "@private_join_and_compute//private_join_and_compute/util:proto_util", 72 | "@private_join_and_compute//private_join_and_compute/util:status_includes", 73 | "@private_join_and_compute//private_join_and_compute/util:status_testing_includes", 74 | ], 75 | ) 76 | -------------------------------------------------------------------------------- /act/act_v0/testing/generate_transcript.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "absl/flags/flag.h" 22 | #include "absl/flags/parse.h" 23 | #include "absl/log/check.h" 24 | #include "absl/log/log.h" 25 | #include "absl/strings/str_cat.h" 26 | #include "absl/strings/string_view.h" 27 | #include "act/act.h" 28 | #include "act/act.pb.h" 29 | #include "act/act_v0/act_v0.h" 30 | #include "act/act_v0/act_v0.pb.h" 31 | #include "act/act_v0/parameters.h" 32 | #include "act/act_v0/testing/transcript.pb.h" 33 | #include "private_join_and_compute/util/proto_util.h" 34 | #include "private_join_and_compute/util/status.inc" 35 | 36 | ABSL_FLAG(std::string, transcript_path, "", 37 | "Prefix of file to which the generated transcript will be " 38 | "written/read from."); 39 | 40 | ABSL_FLAG(bool, verify, false, 41 | "If true, will attempt to read the transcript from the specified " 42 | "path to verify it."); 43 | 44 | namespace private_join_and_compute { 45 | namespace anonymous_counting_tokens { 46 | namespace { 47 | 48 | absl::Status GenerateTranscript(absl::string_view transcript_path) { 49 | SchemeParameters scheme_parameters = 50 | private_join_and_compute::anonymous_counting_tokens:: 51 | ActV0SchemeParametersPedersen32Modulus2048CamenischShoupVector2(); 52 | auto act = AnonymousCountingTokensV0::Create(); 53 | 54 | ASSIGN_OR_RETURN(ServerParameters server_parameters, 55 | act->GenerateServerParameters(scheme_parameters)); 56 | ASSIGN_OR_RETURN( 57 | ClientParameters client_parameters, 58 | act->GenerateClientParameters(scheme_parameters, 59 | server_parameters.public_parameters())); 60 | std::vector messages; 61 | size_t num_messages = 62 | scheme_parameters.scheme_parameters_v0().pedersen_batch_size(); 63 | messages.reserve(num_messages); 64 | for (int i = 0; i < num_messages; ++i) { 65 | messages.push_back(absl::StrCat("message", i)); 66 | } 67 | std::vector client_fingerprints; 68 | TokensRequest tokens_request; 69 | TokensRequestPrivateState tokens_request_private_state; 70 | ASSIGN_OR_RETURN( 71 | std::tie(client_fingerprints, tokens_request, 72 | tokens_request_private_state), 73 | act->GenerateTokensRequest(messages, scheme_parameters, 74 | client_parameters.public_parameters(), 75 | client_parameters.private_parameters(), 76 | server_parameters.public_parameters())); 77 | 78 | ASSIGN_OR_RETURN( 79 | TokensResponse tokens_response, 80 | act->GenerateTokensResponse(tokens_request, scheme_parameters, 81 | client_parameters.public_parameters(), 82 | server_parameters.public_parameters(), 83 | server_parameters.private_parameters())); 84 | 85 | ASSIGN_OR_RETURN( 86 | std::vector tokens, 87 | act->RecoverTokens(messages, tokens_request, tokens_request_private_state, 88 | tokens_response, scheme_parameters, 89 | client_parameters.public_parameters(), 90 | client_parameters.private_parameters(), 91 | server_parameters.public_parameters())); 92 | 93 | Transcript transcript; 94 | *transcript.mutable_scheme_parameters() = scheme_parameters; 95 | *transcript.mutable_server_parameters() = server_parameters; 96 | *transcript.mutable_client_parameters() = client_parameters; 97 | *transcript.mutable_messages() = {messages.begin(), messages.end()}; 98 | *transcript.mutable_fingerprints() = {client_fingerprints.begin(), 99 | client_fingerprints.end()}; 100 | *transcript.mutable_tokens_request() = tokens_request; 101 | *transcript.mutable_tokens_request_private_state() = 102 | tokens_request_private_state; 103 | *transcript.mutable_tokens_response() = tokens_response; 104 | *transcript.mutable_tokens() = {tokens.begin(), tokens.end()}; 105 | 106 | return ProtoUtils::WriteProtoToFile(transcript, transcript_path); 107 | } 108 | 109 | absl::Status VerifyTranscript(absl::string_view transcript_path) { 110 | ASSIGN_OR_RETURN(Transcript transcript, 111 | ProtoUtils::ReadProtoFromFile(transcript_path)); 112 | 113 | auto act = AnonymousCountingTokensV0::Create(); 114 | 115 | if (!transcript.has_scheme_parameters() || 116 | !transcript.scheme_parameters().has_scheme_parameters_v0() || 117 | transcript.scheme_parameters() 118 | .scheme_parameters_v0() 119 | .pedersen_batch_size() <= 0) { 120 | return InvalidArgumentError( 121 | "VerifyTranscript: transcript should have a SchemeParametersV0 with a " 122 | "positive pedersen_batch_size."); 123 | } 124 | 125 | RETURN_IF_ERROR(act->CheckClientParameters( 126 | transcript.scheme_parameters(), 127 | transcript.client_parameters().public_parameters(), 128 | transcript.server_parameters().public_parameters(), 129 | transcript.server_parameters().private_parameters())); 130 | 131 | std::vector client_fingerprints( 132 | transcript.fingerprints().begin(), transcript.fingerprints().end()); 133 | RETURN_IF_ERROR(act->CheckTokensRequest( 134 | client_fingerprints, transcript.tokens_request(), 135 | transcript.scheme_parameters(), 136 | transcript.client_parameters().public_parameters(), 137 | transcript.server_parameters().public_parameters(), 138 | transcript.server_parameters().private_parameters())); 139 | 140 | std::vector messages(transcript.messages().begin(), 141 | transcript.messages().end()); 142 | RETURN_IF_ERROR(act->VerifyTokensResponse( 143 | messages, transcript.tokens_request(), 144 | transcript.tokens_request_private_state(), transcript.tokens_response(), 145 | transcript.scheme_parameters(), 146 | transcript.client_parameters().public_parameters(), 147 | transcript.client_parameters().private_parameters(), 148 | transcript.server_parameters().public_parameters())); 149 | 150 | return OkStatus(); 151 | } 152 | 153 | } // namespace 154 | } // namespace anonymous_counting_tokens 155 | } // namespace private_join_and_compute 156 | 157 | int main(int argc, char** argv) { 158 | absl::ParseCommandLine(argc, argv); 159 | std::string transcript_path = absl::GetFlag(FLAGS_transcript_path); 160 | 161 | bool verify = absl::GetFlag(FLAGS_verify); 162 | if (verify) { 163 | CHECK_OK( 164 | private_join_and_compute::anonymous_counting_tokens::VerifyTranscript( 165 | transcript_path)); 166 | LOG(INFO) << "Successfully verified transcript."; 167 | } else { 168 | CHECK_OK( 169 | private_join_and_compute::anonymous_counting_tokens::GenerateTranscript( 170 | transcript_path)); 171 | LOG(INFO) << "Successfully generated transcript."; 172 | } 173 | 174 | return 0; 175 | } 176 | -------------------------------------------------------------------------------- /act/act_v0/testing/golden_transcript_test.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "act/act.h" 25 | #include "act/act.pb.h" 26 | #include "act/act_v0/act_v0.h" 27 | #include "act/act_v0/testing/transcript.pb.h" 28 | #include "private_join_and_compute/util/proto_util.h" 29 | #include "private_join_and_compute/util/status_testing.inc" 30 | 31 | namespace private_join_and_compute { 32 | namespace anonymous_counting_tokens { 33 | namespace { 34 | 35 | const char kTranscriptPathBase[] = "act/act_v0/testing/transcripts/"; 36 | 37 | TEST(GoldenTranscriptTest, TranscriptPassesValidityTests) { 38 | auto act = AnonymousCountingTokensV0::Create(); 39 | 40 | std::vector transcript_paths; 41 | 42 | for (const auto& entry : 43 | std::filesystem::directory_iterator(kTranscriptPathBase)) { 44 | transcript_paths.push_back(std::string(entry.path())); 45 | } 46 | 47 | for (const auto& transcript_path : transcript_paths) { 48 | ASSERT_OK_AND_ASSIGN( 49 | Transcript transcript, 50 | ProtoUtils::ReadProtoFromFile(transcript_path)); 51 | 52 | EXPECT_OK(act->CheckClientParameters( 53 | transcript.scheme_parameters(), 54 | transcript.client_parameters().public_parameters(), 55 | transcript.server_parameters().public_parameters(), 56 | transcript.server_parameters().private_parameters())); 57 | 58 | std::vector client_fingerprints( 59 | transcript.fingerprints().begin(), transcript.fingerprints().end()); 60 | EXPECT_OK(act->CheckTokensRequest( 61 | client_fingerprints, transcript.tokens_request(), 62 | transcript.scheme_parameters(), 63 | transcript.client_parameters().public_parameters(), 64 | transcript.server_parameters().public_parameters(), 65 | transcript.server_parameters().private_parameters())); 66 | 67 | std::vector messages(transcript.messages().begin(), 68 | transcript.messages().end()); 69 | EXPECT_OK(act->VerifyTokensResponse( 70 | messages, transcript.tokens_request(), 71 | transcript.tokens_request_private_state(), transcript.tokens_response(), 72 | transcript.scheme_parameters(), 73 | transcript.client_parameters().public_parameters(), 74 | transcript.client_parameters().private_parameters(), 75 | transcript.server_parameters().public_parameters())); 76 | } 77 | } 78 | 79 | } // namespace 80 | } // namespace anonymous_counting_tokens 81 | } // namespace private_join_and_compute 82 | -------------------------------------------------------------------------------- /act/act_v0/testing/transcript.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | syntax = "proto3"; 17 | 18 | package private_join_and_compute.anonymous_counting_tokens; 19 | 20 | import "act/act.proto"; 21 | 22 | option java_multiple_files = true; 23 | 24 | message Transcript { 25 | SchemeParameters scheme_parameters = 1; 26 | ServerParameters server_parameters = 2; 27 | ClientParameters client_parameters = 3; 28 | repeated string messages = 4; 29 | repeated bytes fingerprints = 5; 30 | TokensRequest tokens_request = 6; 31 | TokensRequestPrivateState tokens_request_private_state = 7; 32 | TokensResponse tokens_response = 8; 33 | repeated Token tokens = 9; 34 | } 35 | -------------------------------------------------------------------------------- /act/act_v0/testing/transcripts/golden_transcript_1_09122023: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/anonymous-counting-tokens/3dea51443eaabde75c00cd325bc31e3b848a767f/act/act_v0/testing/transcripts/golden_transcript_1_09122023 -------------------------------------------------------------------------------- /act/act_v0/testing/transcripts/golden_transcript_2_09122023: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/anonymous-counting-tokens/3dea51443eaabde75c00cd325bc31e3b848a767f/act/act_v0/testing/transcripts/golden_transcript_2_09122023 -------------------------------------------------------------------------------- /act/act_v0/testing/transcripts/golden_transcript_3_09122023: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/anonymous-counting-tokens/3dea51443eaabde75c00cd325bc31e3b848a767f/act/act_v0/testing/transcripts/golden_transcript_3_09122023 -------------------------------------------------------------------------------- /act/fake_act.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #include "act/fake_act.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "act/act.pb.h" 25 | #include "private_join_and_compute/crypto/context.h" 26 | 27 | namespace private_join_and_compute { 28 | namespace anonymous_counting_tokens { 29 | 30 | // Returns an instance of FakeAnonymousCountingTokens. 31 | std::unique_ptr FakeAnonymousCountingTokens::Create() { 32 | return absl::WrapUnique( 33 | new FakeAnonymousCountingTokens()); 34 | } 35 | 36 | // Returns empty Server parameters. 37 | StatusOr 38 | FakeAnonymousCountingTokens::GenerateServerParameters( 39 | const SchemeParameters& scheme_parameters) { 40 | return ServerParameters::default_instance(); 41 | } 42 | 43 | // Returns empty Client parameters. 44 | StatusOr 45 | FakeAnonymousCountingTokens::GenerateClientParameters( 46 | const SchemeParameters& scheme_parameters, 47 | const ServerPublicParameters& server_public_parameters) { 48 | return ClientParameters::default_instance(); 49 | } 50 | 51 | // Always returns "Ok". 52 | Status FakeAnonymousCountingTokens::CheckClientParameters( 53 | const SchemeParameters& scheme_parameters, 54 | const ClientPublicParameters& client_public_parameters, 55 | const ServerPublicParameters& server_public_parameters, 56 | const ServerPrivateParameters& server_private_parameters) { 57 | return absl::OkStatus(); 58 | } 59 | 60 | // For this fake implementation, the client fingerprints are the same as the 61 | // messages (this is insecure). 62 | StatusOr, TokensRequest, 63 | TokensRequestPrivateState>> 64 | FakeAnonymousCountingTokens::GenerateTokensRequest( 65 | absl::Span messages, 66 | const SchemeParameters& scheme_parameters, 67 | const ClientPublicParameters& client_public_parameters, 68 | const ClientPrivateParameters& client_private_parameters, 69 | const ServerPublicParameters& server_public_parameters) { 70 | return std::make_tuple( 71 | std::vector(messages.begin(), messages.end()), 72 | TokensRequest::default_instance(), 73 | TokensRequestPrivateState::default_instance()); 74 | } 75 | 76 | // Always returns "Ok". 77 | Status FakeAnonymousCountingTokens::CheckTokensRequest( 78 | absl::Span client_fingerprints, 79 | const TokensRequest& tokens_request, 80 | const SchemeParameters& scheme_parameters, 81 | const ClientPublicParameters& client_public_parameters, 82 | const ServerPublicParameters& server_public_parameters, 83 | const ServerPrivateParameters& server_private_parameters) { 84 | return absl::OkStatus(); 85 | } 86 | 87 | // Returns an empty TokensResponse. 88 | StatusOr FakeAnonymousCountingTokens::GenerateTokensResponse( 89 | const TokensRequest& tokens_request, 90 | const SchemeParameters& scheme_parameters, 91 | const ClientPublicParameters& client_public_parameters, 92 | const ServerPublicParameters& server_public_parameters, 93 | const ServerPrivateParameters& server_private_parameters) { 94 | return TokensResponse::default_instance(); 95 | } 96 | 97 | // Always returns "Ok". 98 | Status FakeAnonymousCountingTokens::VerifyTokensResponse( 99 | absl::Span messages, const TokensRequest& tokens_request, 100 | const TokensRequestPrivateState& tokens_request_private_state, 101 | const TokensResponse& tokens_response, 102 | const SchemeParameters& scheme_parameters, 103 | const ClientPublicParameters& client_public_parameters, 104 | const ClientPrivateParameters& client_private_parameters, 105 | const ServerPublicParameters& server_public_parameters) { 106 | return absl::OkStatus(); 107 | } 108 | 109 | // Returns a set of tokens containing randomly generated "nonce" values, and 110 | // all other fields empty. 111 | StatusOr> FakeAnonymousCountingTokens::RecoverTokens( 112 | absl::Span messages, const TokensRequest& tokens_request, 113 | const TokensRequestPrivateState& tokens_request_private_state, 114 | const TokensResponse& tokens_response, 115 | const SchemeParameters& scheme_parameters, 116 | const ClientPublicParameters& client_public_parameters, 117 | const ClientPrivateParameters& client_private_parameters, 118 | const ServerPublicParameters& server_public_parameters) { 119 | Context context; 120 | BigNum nonce_bound = context.One().Lshift(kFakeTokenNonceLengthBits); 121 | 122 | std::vector result; 123 | result.reserve(messages.size()); 124 | for (size_t i = 0; i < messages.size(); ++i) { 125 | Token fake_token; 126 | fake_token.set_nonce_bytes( 127 | context.GenerateRandLessThan(nonce_bound).ToBytes()); 128 | result.push_back(fake_token); 129 | } 130 | 131 | return std::move(result); 132 | } 133 | 134 | // Always returns "Ok". 135 | Status FakeAnonymousCountingTokens::VerifyToken( 136 | std::string m, const Token& token, 137 | const SchemeParameters& scheme_parameters, 138 | const ServerPublicParameters& server_public_parameters, 139 | const ServerPrivateParameters& server_private_parameters) { 140 | return absl::OkStatus(); 141 | } 142 | 143 | } // namespace anonymous_counting_tokens 144 | } // namespace private_join_and_compute 145 | -------------------------------------------------------------------------------- /act/fake_act.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #ifndef PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_FAKE_ACT_H_ 17 | #define PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_FAKE_ACT_H_ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "act/act.h" 25 | #include "act/act.pb.h" 26 | #include "private_join_and_compute/util/status.inc" 27 | 28 | namespace private_join_and_compute { 29 | namespace anonymous_counting_tokens { 30 | 31 | // A fake, insecure implementation of Anonymous Counting Tokens for 32 | // testing/stubbing purposes only. This should NOT be used in production: it 33 | // doesn't have any of the desired security properties. 34 | class FakeAnonymousCountingTokens : public AnonymousCountingTokens { 35 | public: 36 | static const size_t kFakeTokenNonceLengthBits = 256; 37 | 38 | // Returns an instance of FakeAnonymousCountingTokens. 39 | static std::unique_ptr Create(); 40 | 41 | ~FakeAnonymousCountingTokens() override = default; 42 | 43 | // Returns empty Server parameters. 44 | StatusOr GenerateServerParameters( 45 | const SchemeParameters& scheme_parameters) override; 46 | 47 | // Returns empty Client parameters. 48 | StatusOr GenerateClientParameters( 49 | const SchemeParameters& scheme_parameters, 50 | const ServerPublicParameters& server_public_parameters) override; 51 | 52 | // Always returns "Ok". 53 | Status CheckClientParameters( 54 | const SchemeParameters& scheme_parameters, 55 | const ClientPublicParameters& client_public_parameters, 56 | const ServerPublicParameters& server_public_parameters, 57 | const ServerPrivateParameters& server_private_parameters) override; 58 | 59 | // For this fake implementation, the client fingerprints are the same as the 60 | // messages (this is insecure). 61 | StatusOr, TokensRequest, 62 | TokensRequestPrivateState>> 63 | GenerateTokensRequest( 64 | absl::Span messages, 65 | const SchemeParameters& scheme_parameters, 66 | const ClientPublicParameters& client_public_parameters, 67 | const ClientPrivateParameters& client_private_parameters, 68 | const ServerPublicParameters& server_public_parameters) override; 69 | 70 | // Always returns "Ok". 71 | Status CheckTokensRequest( 72 | absl::Span client_fingerprints, 73 | const TokensRequest& tokens_request, 74 | const SchemeParameters& scheme_parameters, 75 | const ClientPublicParameters& client_public_parameters, 76 | const ServerPublicParameters& server_public_parameters, 77 | const ServerPrivateParameters& server_private_parameters) override; 78 | 79 | // Returns an empty TokensResponse. 80 | StatusOr GenerateTokensResponse( 81 | const TokensRequest& tokens_request, 82 | const SchemeParameters& scheme_parameters, 83 | const ClientPublicParameters& client_public_parameters, 84 | const ServerPublicParameters& server_public_parameters, 85 | const ServerPrivateParameters& server_private_parameters) override; 86 | 87 | // Always returns "Ok". 88 | Status VerifyTokensResponse( 89 | absl::Span messages, 90 | const TokensRequest& tokens_request, 91 | const TokensRequestPrivateState& tokens_request_private_state, 92 | const TokensResponse& tokens_response, 93 | const SchemeParameters& scheme_parameters, 94 | const ClientPublicParameters& client_public_parameters, 95 | const ClientPrivateParameters& client_private_parameters, 96 | const ServerPublicParameters& server_public_parameters) override; 97 | 98 | // Returns a set of tokens containing randomly generated "nonce" values, and 99 | // all other fields empty. 100 | StatusOr> RecoverTokens( 101 | absl::Span messages, 102 | const TokensRequest& tokens_request, 103 | const TokensRequestPrivateState& tokens_request_private_state, 104 | const TokensResponse& tokens_response, 105 | const SchemeParameters& scheme_parameters, 106 | const ClientPublicParameters& client_public_parameters, 107 | const ClientPrivateParameters& client_private_parameters, 108 | const ServerPublicParameters& server_public_parameters) override; 109 | 110 | // Always returns "Ok". 111 | Status VerifyToken( 112 | std::string m, const Token& token, 113 | const SchemeParameters& scheme_parameters, 114 | const ServerPublicParameters& server_public_parameters, 115 | const ServerPrivateParameters& server_private_parameters) override; 116 | 117 | protected: 118 | FakeAnonymousCountingTokens() = default; 119 | }; 120 | 121 | } // namespace anonymous_counting_tokens 122 | } // namespace private_join_and_compute 123 | 124 | #endif // PRIVATE_JOIN_AND_COMPUTE_ANONYMOUS_COUNTING_TOKENS_FAKE_ACT_H_ 125 | -------------------------------------------------------------------------------- /act/fake_act_test.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * https://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | #include "act/fake_act.h" 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "private_join_and_compute/util/status.inc" 28 | #include "private_join_and_compute/util/status_testing.inc" 29 | 30 | namespace private_join_and_compute { 31 | namespace anonymous_counting_tokens { 32 | namespace { 33 | 34 | TEST(FakeActTest, FingerprintsAreEqualExactlyWhenMessagesAreEqual) { 35 | auto fake_act = FakeAnonymousCountingTokens::Create(); 36 | 37 | std::vector messages_1 = {"m1", "m2"}; 38 | std::vector fingerprints_1; 39 | 40 | std::vector messages_2 = {"m3", "m1"}; 41 | std::vector fingerprints_2; 42 | 43 | // Empty parameters for testing the fake. 44 | SchemeParameters scheme_parameters; 45 | ClientPublicParameters client_public_parameters; 46 | ClientPrivateParameters client_private_parameters; 47 | ServerPublicParameters server_public_parameters; 48 | 49 | ASSERT_OK_AND_ASSIGN( 50 | std::tie(fingerprints_1, std::ignore, std::ignore), 51 | fake_act->GenerateTokensRequest( 52 | messages_1, scheme_parameters, client_public_parameters, 53 | client_private_parameters, server_public_parameters)); 54 | ASSERT_OK_AND_ASSIGN( 55 | std::tie(fingerprints_2, std::ignore, std::ignore), 56 | fake_act->GenerateTokensRequest( 57 | messages_2, scheme_parameters, client_public_parameters, 58 | client_private_parameters, server_public_parameters)); 59 | 60 | // Only the fingerprints for "m1" should be the same. 61 | EXPECT_EQ(fingerprints_1[0], fingerprints_2[1]); 62 | EXPECT_NE(fingerprints_1[0], fingerprints_2[0]); 63 | EXPECT_NE(fingerprints_1[1], fingerprints_2[1]); 64 | EXPECT_NE(fingerprints_1[1], fingerprints_2[0]); 65 | } 66 | 67 | TEST(FakeActTest, DifferentTokensAreNotEqual) { 68 | auto fake_act = FakeAnonymousCountingTokens::Create(); 69 | 70 | std::vector messages = {"m1", "m2"}; 71 | // Empty parameters and messages for testing the fake. 72 | TokensRequest tokens_request; 73 | TokensRequestPrivateState tokens_request_private_state; 74 | TokensResponse tokens_response; 75 | SchemeParameters scheme_parameters; 76 | ClientPublicParameters client_public_parameters; 77 | ClientPrivateParameters client_private_parameters; 78 | ServerPublicParameters server_public_parameters; 79 | 80 | ASSERT_OK_AND_ASSIGN( 81 | std::vector tokens, 82 | fake_act->RecoverTokens( 83 | messages, tokens_request, tokens_request_private_state, 84 | tokens_response, scheme_parameters, client_public_parameters, 85 | client_private_parameters, server_public_parameters)); 86 | 87 | EXPECT_NE(tokens[0].SerializeAsString(), tokens[1].SerializeAsString()); 88 | } 89 | 90 | } // namespace 91 | } // namespace anonymous_counting_tokens 92 | 93 | } // namespace private_join_and_compute 94 | --------------------------------------------------------------------------------