├── .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 |
--------------------------------------------------------------------------------