├── DESIGN.md
├── LICENSE
├── README.md
├── SECURITY.md
├── SPECIFICATIONS.md
├── assets
├── constants.md
├── logo-black-white-bg.png
└── logo-black.png
├── biscuit-web-key
├── README.md
└── SPECIFICATIONS.md
├── experimentations
├── README.md
├── biscuit-poc
│ ├── Cargo.lock
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── builder.rs
│ │ ├── lib.rs
│ │ ├── sealed.rs
│ │ ├── ser.rs
│ │ └── verifier.rs
├── challenge-tokens
│ └── biscuit-challenge-tokens
│ │ ├── .gitignore
│ │ ├── Cargo.lock
│ │ ├── Cargo.toml
│ │ ├── benches
│ │ └── first.rs
│ │ └── src
│ │ └── lib.rs
├── datalog
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── biscuit.rs
│ │ └── lib.rs
├── gamma
│ └── biscuit-gamma
│ │ ├── .gitignore
│ │ ├── Cargo.lock
│ │ ├── Cargo.toml
│ │ ├── benches
│ │ └── gamma.rs
│ │ └── src
│ │ └── lib.rs
├── pairing
│ ├── bls
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── benches
│ │ │ └── lib.rs
│ │ └── src
│ │ │ └── lib.rs
│ └── mcl
│ │ ├── README.md
│ │ └── aggregated.cpp
└── vrf
│ └── biscuit-vrf
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── benches
│ ├── first.rs
│ └── second.rs
│ ├── results
│ ├── first1.bench
│ ├── first2.bench
│ └── second1.bench
│ └── src
│ ├── lib.rs
│ └── second.rs
├── samples
├── README.md
├── current
│ ├── README.md
│ ├── samples.json
│ ├── test001_basic.bc
│ ├── test002_different_root_key.bc
│ ├── test003_invalid_signature_format.bc
│ ├── test004_random_block.bc
│ ├── test005_invalid_signature.bc
│ ├── test006_reordered_blocks.bc
│ ├── test007_scoped_rules.bc
│ ├── test008_scoped_checks.bc
│ ├── test009_expired_token.bc
│ ├── test010_authorizer_scope.bc
│ ├── test011_authorizer_authority_caveats.bc
│ ├── test012_authority_caveats.bc
│ ├── test013_block_rules.bc
│ ├── test014_regex_constraint.bc
│ ├── test015_multi_queries_caveats.bc
│ ├── test016_caveat_head_name.bc
│ ├── test017_expressions.bc
│ ├── test018_unbound_variables_in_rule.bc
│ ├── test019_generating_ambient_from_variables.bc
│ ├── test020_sealed.bc
│ ├── test021_parsing.bc
│ ├── test022_default_symbols.bc
│ ├── test023_execution_scope.bc
│ ├── test024_third_party.bc
│ ├── test025_check_all.bc
│ ├── test026_public_keys_interning.bc
│ ├── test027_integer_wraparound.bc
│ ├── test028_expressions_v4.bc
│ ├── test029_reject_if.bc
│ ├── test030_null.bc
│ ├── test031_heterogeneous_equal.bc
│ ├── test032_laziness_closures.bc
│ ├── test033_typeof.bc
│ ├── test034_array_map.bc
│ ├── test035_ffi.bc
│ ├── test036_secp256r1.bc
│ ├── test037_secp256r1_third_party.bc
│ └── test038_try_op.bc
└── deprecated
│ ├── v0
│ ├── README.md
│ ├── test10_authority_rules.bc
│ ├── test11_verifier_authority_caveats.bc
│ ├── test12_authority_caveats.bc
│ ├── test13_block_rules.bc
│ ├── test14_regex_constraint.bc
│ ├── test15_multi_queries_caveats.bc
│ ├── test16_caveat_head_name.bc
│ ├── test1_basic.bc
│ ├── test2_different_root_key.bc
│ ├── test3_invalid_signature_format.bc
│ ├── test4_random_block.bc
│ ├── test5_invalid_signature.bc
│ ├── test6_reordered_blocks.bc
│ ├── test7_invalid_block_fact_authority.bc
│ ├── test8_invalid_block_fact_ambient.bc
│ └── test9_expired_token.bc
│ ├── v1
│ ├── README.md
│ ├── samples.json
│ ├── test10_authority_rules.bc
│ ├── test11_verifier_authority_caveats.bc
│ ├── test12_authority_caveats.bc
│ ├── test13_block_rules.bc
│ ├── test14_regex_constraint.bc
│ ├── test15_multi_queries_caveats.bc
│ ├── test16_caveat_head_name.bc
│ ├── test17_expressions.bc
│ ├── test18_unbound_variables_in_rule.bc
│ ├── test19_generating_ambient_from_variables.bc
│ ├── test1_basic.bc
│ ├── test2_different_root_key.bc
│ ├── test3_invalid_signature_format.bc
│ ├── test4_random_block.bc
│ ├── test5_invalid_signature.bc
│ ├── test6_reordered_blocks.bc
│ ├── test7_invalid_block_fact_authority.bc
│ ├── test8_invalid_block_fact_ambient.bc
│ └── test9_expired_token.bc
│ └── v2
│ ├── README.md
│ ├── samples.json
│ ├── test10_authorizer_scope.bc
│ ├── test11_authorizer_authority_caveats.bc
│ ├── test12_authority_caveats.bc
│ ├── test13_block_rules.bc
│ ├── test14_regex_constraint.bc
│ ├── test15_multi_queries_caveats.bc
│ ├── test16_caveat_head_name.bc
│ ├── test17_expressions.bc
│ ├── test18_unbound_variables_in_rule.bc
│ ├── test19_generating_ambient_from_variables.bc
│ ├── test1_basic.bc
│ ├── test20_sealed.bc
│ ├── test21_parsing.bc
│ ├── test2_different_root_key.bc
│ ├── test3_invalid_signature_format.bc
│ ├── test4_random_block.bc
│ ├── test5_invalid_signature.bc
│ ├── test6_reordered_blocks.bc
│ ├── test7_scoped_rules.bc
│ ├── test8_scoped_checks.bc
│ └── test9_expired_token.bc
└── schema.proto
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Biscuit authentication/authorization token
2 |
3 | [Join the Matrix chat](https://matrix.to/#/#biscuit-auth:matrix.org)
4 |
5 |
6 |
7 |
8 |
9 | ## Version
10 |
11 | The stable version of the specification is at [SPECIFICATIONS.md](https://github.com/biscuit-auth/biscuit/blob/main/SPECIFICATIONS.md). The currently in development version is on the [dev branch](https://github.com/biscuit-auth/biscuit/blob/dev/SPECIFICATIONS.md).
12 |
13 | ## Motivation, goals, non-goals
14 |
15 | See .
16 |
17 | ## Try it out
18 |
19 | Biscuit tokens can be created, attenuated, inspected and authorized from your browser:
20 |
21 | ## Roadmap
22 |
23 | You can follow the next steps on the [roadmap](https://github.com/biscuit-auth/biscuit/issues/12).
24 |
25 | Current status:
26 |
27 | - the credentials language, cryptographic primitives and serialization format are done
28 | - we have implementations for biscuits v2 in
29 | - [Rust](https://github.com/biscuit-auth/biscuit-rust)
30 | - [Web Assembly](https://github.com/biscuit-auth/biscuit-wasm) (based on the Rust version)
31 | - [Python](https://github.com/biscuit-auth/biscuit-python) (based on the Rust version)
32 | - [Haskell](https://github.com/biscuit-auth/biscuit-haskell)
33 | - we have implementations for biscuits v1 in
34 | - [Java](https://github.com/clevercloud/biscuit-java) (migration to v2 is in progress)
35 | - [Go](https://github.com/biscuit-auth/biscuit-go)
36 | - [.Net](https://github.com/dmunch/biscuit-net)
37 | - a website with documentation and an interactive playground is live at
38 | - Currently deploying to real world use cases such as [Apache Pulsar](https://github.com/clevercloud/biscuit-pulsar) at [Clever Cloud](https://www.clever-cloud.com/)
39 | - looking for an audit of the token's design, cryptographic primitives and implementations
40 |
41 | ## Feature support
42 |
43 | The different implementations are following the specification closely, but parts of it may take some time to be fully implemented, so here is the current list of supported features per version:
44 |
45 | * ✅ full support
46 | * 🚧 partial support
47 | * ❌ not supported yet
48 |
49 | | | Rust | Haskell | Java | Go | Python | C# |
50 | |--------------------|------|---------|------|----|--------|----|
51 | |**v2** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
52 | |**v3** | ✅ | ✅ | 🚧 | ❌ | ✅ | ✅ |
53 | | scopes | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
54 | | check all | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
55 | | bitwise operations | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
56 | | third party blocks | ✅ | ✅ | 🚧 | ❌ | 🚧 | ✅ |
57 | | snapshots | ✅ | ❌ | 🚧 | ❌ | ✅ | ❌ |
58 |
59 |
60 | ## How to help us?
61 |
62 | - provide use cases that we can test the token on (some specific kind of checks, auth delegation, etc)
63 | - cryptographic design audit: we need reviews of algorithms, their usage and implementation in various languages
64 | - add support for biscuit v2 to java and go implementations
65 |
66 | ## Project organisation
67 |
68 | - `SPECIFICATIONS.md` is the description of Biscuit, its format and behaviour
69 | - `biscuit-web-key/` is a specification for publishing biscuit public keys
70 | - `DESIGN.md` holds the initial ideas about what Biscuit should be
71 | - `experimentations/` holds initial code examples for the crypographic schemes and caveat language. `code/biscuit-poc/` contains an experimental version of Biscuit, built to explore API issues
72 |
73 | ## License
74 |
75 | Licensed under Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
76 |
77 | logo by Julien Richard
78 |
79 | originally created at [Clever Cloud](https://www.clever-cloud.com/)
80 |
81 | ### Contribution
82 |
83 | Unless you explicitly state otherwise, any contribution intentionally
84 | submitted for inclusion in the work by you, as defined in the Apache-2.0
85 | license, shall be licensed as above, without any additional terms or
86 | conditions.
87 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security
2 |
3 | ## Vulnerabilities
4 |
5 | ### 1 - 2021/05/06 - rules can generate fact with authority or ambient tags using variables
6 |
7 | Affected versions:
8 | - Rust <1.1.0
9 | - Java: <1.1.0
10 | - Go: <1.0.0
11 |
12 | #### Description
13 |
14 | Rules of the format `operation($ambient, #read) <- operation($ambient, $any)`
15 | provided by blocks other than the authority block could be used to generate
16 | facts with the `#authority` or `#ambient` tags.
17 | This can result in elevation of privilege.
18 |
19 | #### Recommandations
20 |
21 | Upgrade immediately to non affected versions
22 |
23 | #### Credits
24 |
25 | This issue was reported by @svvac. Thanks a lot!
26 |
27 | ### 0 - 2021/05/06 - unbound variables in rule head
28 |
29 | Affected versions:
30 | - Rust <1.0.1
31 | - Java: results in Null Pointer Exception in versions <1.1.0
32 | - Go: not affected
33 |
34 | #### Description
35 |
36 | Rules of the format `operation($unbound, #read) <- operation($any1, $any2)` could generate invalid facts containing variables, that would then confuse matching of other checks and make them succeed.
37 | This can result in elevation of privilege.
38 |
39 | #### Recommandations
40 |
41 | Upgrade immediately to non affected versions
42 |
43 | #### Credits
44 |
45 | This issue was reported by @svvac. Thanks a lot!
46 |
--------------------------------------------------------------------------------
/assets/constants.md:
--------------------------------------------------------------------------------
1 | colors: #EEE3DC, #2D2419
2 | font: https://fonts.google.com/specimen/Erica+One
3 |
4 |
--------------------------------------------------------------------------------
/assets/logo-black-white-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/assets/logo-black-white-bg.png
--------------------------------------------------------------------------------
/assets/logo-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/assets/logo-black.png
--------------------------------------------------------------------------------
/biscuit-web-key/README.md:
--------------------------------------------------------------------------------
1 | # Biscuit web key sets
2 |
3 | This additional specification document describes a way to distribute biscuit web keys over HTTPs.
4 |
--------------------------------------------------------------------------------
/biscuit-web-key/SPECIFICATIONS.md:
--------------------------------------------------------------------------------
1 | # Biscuit web keys
2 |
3 | A token issuer may publish public keys over HTTPS, in order to let verifying parties acquire keys
4 | dynamically. This mechanism relies on the trust placed by the verifying parties on the owner of a
5 | specific domain name, related to the issuer. Deciding which domain name to trust for a given
6 | token is still the responsibility of the relying party and has to happen out-of-band.
7 |
8 | Concretely, a domain can expose a list of public key descriptors as a JSON array on a well-known URI.
9 |
10 | Biscuit web key sets can be referred to "bwks", which is pronounced "bivouacs".
11 |
12 | ### Biscuit web keys endpoint
13 |
14 | The owner of `example.org` may expose a list of public key descriptors
15 |
16 | - served over HTTPS;
17 | - for GET requests;
18 | - at `./well-known/biscuit-web-keys`;
19 | - with a JSON payload (described below) as the response body.
20 |
21 | The response body must conform to the following schema:
22 |
23 | ```json
24 | {
25 | "$schema": "http://json-schema.org/draft-2020-12/schema#",
26 | "type": "array",
27 | "items": {
28 | "type": "object",
29 | "properties": {
30 | "algorithm": {
31 | "type": "string",
32 | "enum": [
33 | "ed25519"
34 | ]
35 | },
36 | "key_bytes": {
37 | "type": "string",
38 | "pattern": "^([0-9a-fA-F]{2})*$"
39 | },
40 | "key_id": {
41 | "type": "integer"
42 | },
43 | "issuer": {
44 | "type": "string"
45 | },
46 | "expires_at": {
47 | "type": "string",
48 | "format": "date-time"
49 | }
50 | },
51 | "required": [
52 | "algorithm",
53 | "key_bytes",
54 | "key_id"
55 | ]
56 | }
57 | }
58 | ```
59 |
60 | Additionally:
61 |
62 | - `key_bytes` must contain an hex-encoded byte array, containing the binary encoding of the corresponding public key;
63 | - `key_id` is mandatory and must correspond to the `rootKeyId` field set on tokens signed by the corresponding key;
64 | - `expires_at` is optional and can provide information about the expected validity period of the
65 | corresponding key. It is not linked to expiration checks carried with tokens and is simply intended to advertise planned key rotations;
66 | - `issuer` is optional and can contain freeform text. It is intended to provide finer grained information about the scope, _within the trust boundary set by the domain name_.
67 |
68 | **`key_id` and `issuer` are meant to let verifying parties choose keys within a set that they already trust. They are in no way enough to make the verifying party trust a key.**
69 |
70 |
--------------------------------------------------------------------------------
/experimentations/README.md:
--------------------------------------------------------------------------------
1 | # Experiments around signature aggregation for the biscuit token
2 |
3 | ## Requirements
4 |
5 | We are looking for a non interactive, incrementally aggregated
6 | signature solution for biscuit, ie a way to:
7 | - from (message_0, privkey_0, pubkey_0), generate ([(message_0, pubkey_0)], signature0)
8 | - from ([(message_0, pubkey_0), (message_1, pubkey_1), .. (message_n, pubkey_n)], signature_n), and (message_n+1, privkey_n+1, pubkey_n+1),
9 | generate ([(message_0, pubkey_0), (message_1, pubkey_1), .. (message_n+1, pubkey_n+1)], signature_n+1)
10 |
11 | It should not be possible to infer `signature_n` if we have the token at level `n+1`
12 |
13 | ## Proposals
14 |
15 | ### Pairings
16 |
17 | The first solution that was proposed uses pairing based crypto. There are two experiments,
18 | one with the Rust pairing crate, one with the mcl C++ library.
19 |
20 | #### Performance
21 |
22 | Performance for the Rust library is not great:
23 |
24 | ```
25 | test bench::sign_one_block ... bench: 2,932,712 ns/iter (+/- 326,987)
26 | test bench::sign_two_blocks ... bench: 3,234,507 ns/iter (+/- 671,200)
27 | test bench::verify_one_block ... bench: 15,170,364 ns/iter (+/- 2,726,052)
28 | test bench::verify_two_blocks ... bench: 22,570,853 ns/iter (+/- 2,683,514)
29 | test bench::verify_three_blocks ... bench: 30,657,499 ns/iter (+/- 5,971,353)
30 | ```
31 |
32 | But the mcl library can get at verification in 1 or 2ms.
33 |
34 | #### Signature overhead
35 |
36 | The first group's points can be stored in 48 bytes, the second group's in 96 bytes.
37 | Assuming we use the first group to get smaller points (probably at the price of a reduced security bound),
38 | We would need to store one G1 point per block, and one G2 point.
39 |
40 | So, for:
41 | - 1 block: 1 * 48 + 96 = 144 bytes
42 | - 2 blocks: 2 * 48 + 96 = 192 bytes
43 | - 5 blocks: 5 * 48 + 96 = 336 bytes
44 | - 10 blocks: 10 * 48 + 96 = 576 bytes
45 | - 20 blocks: 20 * 48 + 96 = 1056 bytes
46 |
47 | Pairing based crypto libraries are not frequent, so it might be hard to implement in various languages
48 |
49 | ### Verifiable random functions
50 |
51 | **This solution is currently rejected, as a serious vulnerability was found**
52 |
53 | By reusing primitives from https://tools.ietf.org/html/draft-irtf-cfrg-vrf-04#section-5 , we can generate
54 | aggregated non interactive proof of discrete logarithms, that match our requirements.
55 |
56 | We have an example that uses the curve25519-dalek Rust crate, with the Ristretto group.
57 |
58 | #### Performance
59 |
60 | Here are some benchmarks for this approach:
61 |
62 | The "first" benchmark uses the scheme described in the `DESIGN.md` document.
63 |
64 | ```
65 | test bench::sign_first_block ... bench: 254,468 ns/iter (+/- 20,833)
66 | test bench::sign_second_block ... bench: 690,781 ns/iter (+/- 140,195)
67 | test bench::sign_third_block ... bench: 844,560 ns/iter (+/- 44,068)
68 | test bench::verify_one_block ... bench: 322,904 ns/iter (+/- 27,904)
69 | test bench::verify_two_blocks ... bench: 548,263 ns/iter (+/- 73,312)
70 | test bench::verify_three_blocks ... bench: 748,755 ns/iter (+/- 95,676)
71 | ```
72 |
73 | The "second" benchmark modifies that scheme to precalculate some point additions.
74 |
75 | ```
76 | test bench::sign_first_block ... bench: 325,743 ns/iter (+/- 34,561)
77 | test bench::sign_second_block ... bench: 678,686 ns/iter (+/- 147,267)
78 | test bench::sign_third_block ... bench: 866,091 ns/iter (+/- 282,052)
79 | test bench::verify_one_block ... bench: 264,231 ns/iter (+/- 54,111)
80 | test bench::verify_two_blocks ... bench: 322,503 ns/iter (+/- 17,924)
81 | test bench::verify_three_blocks ... bench: 418,594 ns/iter (+/- 37,085)
82 | ```
83 |
84 | There's probably a lot of low hanging fruit in optimizing those, but
85 | token attenuation and verification happening in less than 1ms makes it usable.
86 |
87 | #### Signature overhead
88 |
89 | a Ristretto point can be stored in 32 bytes, a Scalar can be stored in 32 bytes
90 |
91 | With the first method, we will store 2 points (pubkey and gamma) and 1 scalar
92 | per block, and 1 point and 1 scalar in the signature.
93 | With the second method, we will store 1 point (pubkey) and 1 scalar per block,
94 | and 2 points and 1 scalar in the signature.
95 |
96 | So, for the first method:
97 | - 1 block: 1 * 96 + 64 = 160 bytes
98 | - 2 blocks: 2 * 96 + 64 = 256 bytes
99 | - 5 blocks: 5 * 96 + 64 = 544 bytes
100 | - 10 blocks: 10 * 96 + 64 = 1024 bytes
101 | - 20 blocks: 20 * 96 + 64 = 1984 bytes
102 |
103 | For the second method:
104 | - 1 block: 1 * 64 + 96 = 160 bytes
105 | - 2 blocks: 2 * 64 + 96 = 224 bytes
106 | - 5 blocks: 5 * 64 + 96 = 416 bytes
107 | - 10 blocks: 10 * 64 + 96 = 736 bytes
108 | - 20 blocks: 10 * 64 + 96 = 1376 bytes
109 |
110 | Since this solution uses a well known curve, there's a higher chance of getting
111 | good quality implementations in other languages.
112 |
113 | ### Challenge tokens
114 |
115 | Another method based on a more classical PKI, with a last challenge to prove
116 | that we own the last key.
117 |
118 | Here's a description of the scheme:
119 |
120 | ```
121 | (pk1, sk1) = keygen()
122 | (pk2, sk2) = keygen()
123 | s1 = sign(sk1, caveat1+pk2)
124 | token1=caveat1+pk2+s1+sk2
125 |
126 | Minting a new token:
127 | (pk3, sk3) = keygen()
128 | s2 = sign(sk2, caveat2+pk3)
129 | token2=caveat1+pk2+s1+caveat2+pk3+s2+sk3
130 |
131 | Sending token2 for verification:
132 | verif_token2=caveat1+pk2+s1+caveat2+pk3+s2
133 | h = sign(sk3, nonce+time+verif_token2)
134 | sending verif_token2+h
135 |
136 | The verifier knows pk1 and can check the chain, and h allows checking that we hold sk3
137 | ```
138 |
139 | #### Performance
140 |
141 | Here are some benchmarks for this approach:
142 |
143 | ```
144 | test bench::sign_first_block ... bench: 325,113 ns/iter (+/- 22,812)
145 | test bench::sign_second_block ... bench: 402,085 ns/iter (+/- 36,133)
146 | test bench::sign_third_block ... bench: 405,621 ns/iter (+/- 28,162)
147 | test bench::verify_one_block ... bench: 308,992 ns/iter (+/- 32,920)
148 | test bench::verify_two_blocks ... bench: 472,676 ns/iter (+/- 97,749)
149 | test bench::verify_three_blocks ... bench: 624,811 ns/iter (+/- 63,081)
150 | ```
151 |
152 | #### Signature overhead
153 |
154 | a Ristretto point can be stored in 32 bytes, a Scalar can be stored in 32 bytes
155 |
156 | For each block, we will store 1 point (public key) and 2 scalars (signature).
157 | There's an additional scalar to store the next private key.
158 | The challenge token has 1 point (public key) and 2 scalars (signature) per block,
159 | and there's 1 more point, and 2 scalars (signature), along with the challenge
160 |
161 | This gives the following:
162 | - 1 block: 1 * 96 + 32 = 128 bytes
163 | - 2 blocks: 2 * 96 + 32 = 224 bytes
164 | - 5 blocks: 5 * 96 + 32 = 512 bytes
165 | - 10 blocks: 10 * 96 + 32 = 992 bytes
166 | - 20 blocks: 20 * 96 + 32 = 1952 bytes
167 |
168 | And for the challenge token:
169 | - 1 block: 1 * 96 + 96 = 192 bytes
170 | - 2 blocks: 2 * 96 + 96 = 288 bytes
171 | - 5 blocks: 5 * 96 + 96 = 576 bytes
172 | - 10 blocks: 10 * 96 + 96 = 1056 bytes
173 | - 20 blocks: 20 * 96 + 96 = 2016 bytes
174 |
175 | About the same size as the first VRF solution, but the challenge token makes it bigger
176 |
177 | It can use well known curves and signature algorithms (the example code uses Schnorr signatures).
178 | It has som slight differences in behaviour with the other methods, though:
179 | - generating a verif token requires access to the token (ie no HttpOnly cookies)
180 | - once a challenge token is generated, it cannot be attenuated again (might be a good thing or bad thing depending on the context)
181 |
182 | ### Aggregated gamma signatures
183 |
184 | implementation of the scheme from https://eprint.iacr.org/2018/414.pdf
185 |
186 |
187 | #### Performance
188 |
189 | Performance is on par with the VRF solution (it can be further optimized):
190 |
191 | ```
192 | test bench::sign_first_block ... bench: 81,759 ns/iter (+/- 13,909)
193 | test bench::sign_second_block ... bench: 82,587 ns/iter (+/- 6,963)
194 | test bench::sign_third_block ... bench: 83,048 ns/iter (+/- 12,164)
195 | test bench::verify_one_block ... bench: 209,257 ns/iter (+/- 30,426)
196 | test bench::verify_two_blocks ... bench: 352,418 ns/iter (+/- 32,345)
197 | test bench::verify_three_blocks ... bench: 511,629 ns/iter (+/- 65,295)
198 | ```
199 |
200 | #### Signature overhead
201 |
202 | a Ristretto point can be stored in 32 bytes, a Scalar can be stored in 32 bytes
203 |
204 | we will store 2 points (public key and "A" parameter) per block,
205 | and one scalar in the signature
206 |
207 |
208 | So, for the first method:
209 | - 1 block: 1 * 64 + 32 = 96 bytes
210 | - 2 blocks: 2 * 64 + 32 = 160 bytes
211 | - 5 blocks: 5 * 64 + 32 = 352 bytes
212 | - 10 blocks: 10 * 64 + 32 = 672 bytes
213 | - 20 blocks: 20 * 64 + 32 = 1312 bytes
214 |
215 |
216 | ## Benchmarks summary
217 |
218 | ### Signing
219 |
220 | | | 1 block | 2 blocks | 3 blocks |
221 | | --------- | ------- | -------- | -------- |
222 | | pairing | 2932 μs | 3234 μs | |
223 | | VRF 1 | 254 μs | 690 μs | 844 μs |
224 | | VRF 2 | 325 μs | 678 μs | 866 μs |
225 | | challenge | 325 μs | 402 μs | 405 μs |
226 | | gamma | 81 μs | 82 μs | 83 μs |
227 |
228 | ### Verifying
229 |
230 | | | 1 block | 2 blocks | 3 blocks |
231 | | --------- | -------- | -------- | -------- |
232 | | pairing | 15170 μs | 22570 μs | 30657 μs |
233 | | VRF 1 | 322 μs | 548 μs | 748 μs |
234 | | VRF 2 | 264 μs | 322 μs | 418 μs |
235 | | challenge | 308 μs | 472 μs | 624 μs |
236 | | gamma | 280 μs | 352 μs | 511 μs |
237 |
238 | ### Size overhead
239 |
240 | (in bytes)
241 |
242 | | | 1 block | 2 blocks | 5 blocks | 10 blocks | 20 blocks |
243 | | --------------------------- | ------- | -------- | -------- | --------- | --------- |
244 | | pairing | 144 | 192 | 336 | 576 | 1056 |
245 | | VRF 1 | 160 | 256 | 544 | 1024 | 1984 |
246 | | VRF 2 | 160 | 224 | 416 | 736 | 1376 |
247 | | challenge (base token) | 128 | 224 | 512 | 992 | 1952 |
248 | | challenge (challenge token) | 192 | 288 | 576 | 1056 | 2016 |
249 | | gamma | 96 | 160 | 352 | 672 | 1312 |
250 |
--------------------------------------------------------------------------------
/experimentations/biscuit-poc/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "biscuit-implementation"
3 | version = "0.1.0"
4 | authors = ["Geoffroy Couprie "]
5 | edition = "2018"
6 |
7 | [dependencies]
8 | datalog_with_constraints = { path = "../datalog/" }
9 | biscuit-vrf = { path = "../vrf/biscuit-vrf" }
10 | curve25519-dalek = "^1.0"
11 | rand = "^0.6"
12 | serde = { version = "1.0", features = ["derive"] }
13 | serde_cbor = "0.9"
14 | nom = "4.2"
15 | sha2 = "^0.8"
16 | hmac = "^0.7"
17 |
--------------------------------------------------------------------------------
/experimentations/biscuit-poc/README.md:
--------------------------------------------------------------------------------
1 | # Biscuit proof of concept
2 |
3 | This project explores the issues encountered when implementing
4 | Biscuit with the current design ideas.
5 |
6 | ## Storage format
7 |
8 | ### Block ordering and signature aggregation
9 |
10 | The crypto designs do not impose any order on the blocks, which
11 | might create issues with how each block is interpreted afterwards,
12 | since they might rely on that order.
13 |
14 | Solution: the blocks could contain an index, that would be checked
15 | when deserializing.
16 |
17 | ### Separating the authority block from the rest
18 |
19 | The authority block is the most critical one, since it defines
20 | the starting rights.
21 |
22 | We could make it a special case in the serialization format.
23 |
24 | Or require that the block 0 be the authority block
25 |
26 | ### Two steps of deserialization
27 |
28 | It might be easier to have a first step that deserializes
29 | the keys and signature but keeps the blocks as byte arrays,
30 | to check the signature, then deserializes the blocks to check
31 | the caveats.
32 |
33 | ## datalog implementation
34 |
35 | ### Checking fact scope
36 |
37 | We have to be very clear on the scope in which facts are created.
38 | Authority facts can only be created by the authority blocks facts
39 | and rules.
40 | Ambient facts can only be created by the verifier.
41 | Block facts cannot be in those scopes.
42 |
43 | ### Symbol table handling
44 |
45 | To make the token smaller, we provide a "symbol" data type, which
46 | is stored as an integer, but has a symbol table to map it to a string.
47 | These symbols only support equality, set inclusion and set exclusion.
48 |
49 | The symbol table is created by sending it a string, and if the string is
50 | already present, we return its index, but if it's not, we append it to the list
51 | and return its index.
52 |
53 | The big issue here is that the symbol table has to be the same for the verifier
54 | and for the block creator. Otherwise, some symbols in the block might map to
55 | different strings than what the verifier thinks.
56 |
57 | Right now, we have a default table containing some common symbols like "authority"
58 | and "ambient". Then we add the new strings for the authority block.
59 |
60 | Solution 1:
61 | for each block, start from the default table with the authority symbols added. Then
62 | add the symbols for the block (from its facts and rules). Then add the verifier's
63 | facts and rules. Then run the caveat.
64 |
65 | Solution 2:
66 | start from the default table.
67 | Add the symbols from the authority block.
68 | Add the symbols from each block _in order_.
69 | Add the symbols from the verifier
70 | then for each block, start from there and add the verifier facts and rules and run the
71 | caveats.
72 | there should be no conflict with this way, but it relies on an order for the blocks.
73 |
74 | ### Adding a block requires knowing the previous ones
75 |
76 | so that the symbol table is correct
77 |
--------------------------------------------------------------------------------
/experimentations/biscuit-poc/src/builder.rs:
--------------------------------------------------------------------------------
1 | use datalog::{SymbolTable, ID, Constraint, ConstraintKind, DateConstraint, StrConstraint};
2 | use super::Block;
3 | use std::time::{SystemTime, UNIX_EPOCH};
4 |
5 | #[derive(Clone,Debug)]
6 | pub struct BlockBuilder {
7 | pub index: u32,
8 | pub symbols_start: usize,
9 | pub symbols: SymbolTable,
10 | pub facts: Vec,
11 | pub caveats: Vec,
12 | }
13 |
14 | impl BlockBuilder {
15 | pub fn new(index: u32, base_symbols: SymbolTable) -> BlockBuilder {
16 | BlockBuilder {
17 | index,
18 | symbols_start: base_symbols.symbols.len(),
19 | symbols: base_symbols,
20 | facts: vec![],
21 | caveats: vec![],
22 | }
23 | }
24 |
25 | pub fn symbol_add(&mut self, s: &str) -> ID {
26 | self.symbols.add(s)
27 | }
28 |
29 | pub fn symbol_insert(&mut self, s: &str) -> u64 {
30 | self.symbols.insert(s)
31 | }
32 |
33 | pub fn add_fact(&mut self, fact: &Fact) {
34 | let f = fact.convert(&mut self.symbols);
35 | self.facts.push(f);
36 | }
37 |
38 | pub fn add_caveat(&mut self, caveat: &Rule) {
39 | let c = caveat.convert(&mut self.symbols);
40 | self.caveats.push(c);
41 | }
42 |
43 | pub fn to_block(mut self) -> Block {
44 | let new_syms = self.symbols.symbols.split_off(self.symbols_start);
45 |
46 | self.symbols.symbols = new_syms;
47 |
48 | Block {
49 | index: self.index,
50 | symbols: self.symbols,
51 | facts: self.facts,
52 | caveats: self.caveats,
53 | }
54 | }
55 |
56 | pub fn add_right(&mut self, resource: &str, right: &str) -> bool {
57 | if self.index != 0 {
58 | false
59 | } else {
60 | self.add_fact(&fact("right", &[s("authority"), string(resource), s(right)]));
61 | true
62 | }
63 | }
64 |
65 | pub fn check_right(&mut self, right: &str) {
66 | let caveat = rule("check_right", &[s(right)], &[
67 | pred("resource", &[s("ambient"), Atom::Variable(0)]),
68 | pred("operation", &[s("ambient"), s(right)]),
69 | pred("right", &[s("authority"), Atom::Variable(0), s(right)])
70 | ]);
71 |
72 | self.add_caveat(&caveat);
73 | }
74 |
75 | pub fn resource_prefix(&mut self, prefix: &str) {
76 | let caveat = constrained_rule("prefix", &[Atom::Variable(0)],
77 | &[pred("resource", &[s("ambient"), Atom::Variable(0)])],
78 | &[Constraint {
79 | id: 0,
80 | kind: ConstraintKind::Str(StrConstraint::Prefix(prefix.to_string()))
81 | }]
82 | );
83 |
84 | self.add_caveat(&caveat);
85 | }
86 |
87 | pub fn resource_suffix(&mut self, suffix: &str) {
88 | let caveat = constrained_rule("suffix", &[Atom::Variable(0)],
89 | &[pred("resource", &[s("ambient"), Atom::Variable(0)])],
90 | &[Constraint {
91 | id: 0,
92 | kind: ConstraintKind::Str(StrConstraint::Suffix(suffix.to_string()))
93 | }]
94 | );
95 |
96 | self.add_caveat(&caveat);
97 | }
98 |
99 | pub fn expiration_date(&mut self, date: SystemTime) {
100 | let dur = date.duration_since(UNIX_EPOCH).unwrap();
101 | let d = dur.as_secs();
102 |
103 | let caveat = constrained_rule("expiration", &[Atom::Variable(0)],
104 | &[pred("time", &[s("ambient"), Atom::Variable(0)])],
105 | &[Constraint {
106 | id: 0,
107 | kind: ConstraintKind::Date(DateConstraint::Before(d))
108 | }]
109 | );
110 |
111 | self.add_caveat(&caveat);
112 | }
113 |
114 | pub fn revocation_id(&mut self, id: i64) {
115 | self.add_fact(&fact("revocation_id", &[int(id)]));
116 | }
117 | }
118 |
119 | #[derive(Debug,Clone,PartialEq,Hash,Eq)]
120 | pub enum Atom {
121 | Symbol(String),
122 | Variable(u32),
123 | Integer(i64),
124 | Str(String),
125 | Date(u64),
126 | }
127 |
128 | impl Atom {
129 | pub fn convert(&self, symbols: &mut SymbolTable) -> ID {
130 | match self {
131 | Atom::Symbol(s) => ID::Symbol(symbols.insert(s)),
132 | Atom::Variable(i) => ID::Variable(*i),
133 | Atom::Integer(i) => ID::Integer(*i),
134 | Atom::Str(s) => ID::Str(s.clone()),
135 | Atom::Date(d) => ID::Date(*d),
136 | }
137 | }
138 | }
139 |
140 | impl From<&Atom> for Atom {
141 | fn from(i: &Atom) -> Self {
142 | match i {
143 | Atom::Symbol(ref s) => Atom::Symbol(s.clone()),
144 | Atom::Variable(ref v) => Atom::Variable(*v),
145 | Atom::Integer(ref i) => Atom::Integer(*i),
146 | Atom::Str(ref s) => Atom::Str(s.clone()),
147 | Atom::Date(ref d) => Atom::Date(*d),
148 | }
149 | }
150 | }
151 |
152 | impl AsRef for Atom {
153 | fn as_ref(&self) -> &Atom {
154 | self
155 | }
156 | }
157 |
158 | #[derive(Debug,Clone,PartialEq,Hash,Eq)]
159 | pub struct Predicate {
160 | pub name: String,
161 | pub ids: Vec,
162 | }
163 |
164 | impl Predicate {
165 | pub fn convert(&self, symbols: &mut SymbolTable) -> datalog::Predicate {
166 | let name = symbols.insert(&self.name);
167 | let mut ids = vec![];
168 |
169 | for id in self.ids.iter() {
170 | ids.push(id.convert(symbols));
171 | }
172 |
173 | datalog::Predicate { name, ids }
174 | }
175 | }
176 |
177 | impl Predicate {
178 | pub fn new(name: String, ids: &[Atom]) -> Predicate {
179 | Predicate { name, ids: ids.to_vec() }
180 | }
181 | }
182 |
183 | impl AsRef for Predicate {
184 | fn as_ref(&self) -> &Predicate {
185 | self
186 | }
187 | }
188 |
189 | #[derive(Debug,Clone,PartialEq,Hash,Eq)]
190 | pub struct Fact(pub Predicate);
191 |
192 | impl Fact {
193 | pub fn new(name: String, ids: &[Atom]) -> Fact {
194 | Fact(Predicate::new(name, ids))
195 | }
196 | }
197 |
198 | impl Fact {
199 | pub fn convert(&self, symbols: &mut SymbolTable) -> datalog::Fact {
200 | datalog::Fact(self.0.convert(symbols))
201 | }
202 | }
203 |
204 |
205 | #[derive(Debug,Clone,PartialEq)]
206 | pub struct Rule(pub Predicate, pub Vec, pub Vec);
207 |
208 | impl Rule {
209 | pub fn convert(&self, symbols: &mut SymbolTable) -> datalog::Rule {
210 | let head = self.0.convert(symbols);
211 | let mut body = vec![];
212 | let mut constraints = vec![];
213 |
214 | for p in self.1.iter() {
215 | body.push(p.convert(symbols));
216 | }
217 |
218 | for c in self.2.iter() {
219 | constraints.push(c.clone());
220 | }
221 |
222 | datalog::Rule(head, body, constraints)
223 | }
224 | }
225 |
226 | pub fn fact>(name: &str, ids: &[I]) -> Fact {
227 | Fact(pred(name, ids))
228 | /*Fact(Predicate {
229 | name.to_string(),
230 | ids: ids.iter().map(|id| id.as_ref().clone()).collect(),
231 | })*/
232 | }
233 |
234 | pub fn pred>(name: &str, ids: &[I]) -> Predicate {
235 | Predicate {
236 | name: name.to_string(),
237 | ids: ids.iter().map(|id| id.as_ref().clone()).collect(),
238 | }
239 | }
240 |
241 | pub fn rule, P: AsRef>(head_name: &str, head_ids: &[I], predicates: &[P]) -> Rule {
242 | Rule(
243 | pred(head_name, head_ids),
244 | predicates.iter().map(|p| p.as_ref().clone()).collect(),
245 | Vec::new()
246 | )
247 | }
248 |
249 | pub fn constrained_rule, P: AsRef, C: AsRef>(
250 | head_name: &str, head_ids: &[I], predicates: &[P], constraints: &[C]) -> Rule {
251 | Rule(
252 | pred(head_name, head_ids),
253 | predicates.iter().map(|p| p.as_ref().clone()).collect(),
254 | constraints.iter().map(|c| c.as_ref().clone()).collect(),
255 | )
256 | }
257 |
258 | pub fn int(i: i64) -> Atom {
259 | Atom::Integer(i)
260 | }
261 |
262 | pub fn string(s: &str) -> Atom {
263 | Atom::Str(s.to_string())
264 | }
265 |
266 | pub fn s(s: &str) -> Atom {
267 | Atom::Symbol(s.to_string())
268 | }
269 |
270 | pub fn date(t: &SystemTime) -> Atom {
271 | let dur = t.duration_since(UNIX_EPOCH).unwrap();
272 | Atom::Date(dur.as_secs())
273 | }
274 |
275 | pub fn var(i: u32) -> Atom {
276 | Atom::Variable(i)
277 | }
278 |
--------------------------------------------------------------------------------
/experimentations/biscuit-poc/src/sealed.rs:
--------------------------------------------------------------------------------
1 | use serde::{Serialize, Deserialize};
2 | use sha2::{Digest, Sha256};
3 | use hmac::{Hmac, Mac};
4 | use super::Biscuit;
5 |
6 | type HmacSha256 = Hmac;
7 |
8 | #[derive(Clone,Debug,Serialize,Deserialize)]
9 | pub struct SealedBiscuit {
10 | pub authority: Vec,
11 | pub blocks: Vec>,
12 | pub signature: Vec,
13 | }
14 |
15 | impl SealedBiscuit {
16 | pub fn from_token(token: &Biscuit, secret: &[u8]) -> Self {
17 | let authority = serde_cbor::ser::to_vec_packed(&token.authority).unwrap();
18 | let blocks = token.blocks.iter().map(|b| serde_cbor::ser::to_vec_packed(b).unwrap()).collect::>();
19 |
20 | let mut mac = HmacSha256::new_varkey(secret).unwrap();
21 | mac.input(&authority);
22 | for block in blocks.iter() {
23 | mac.input(&block);
24 | }
25 |
26 | let signature: Vec = mac.result().code().to_vec();
27 |
28 | SealedBiscuit { authority, blocks, signature }
29 | }
30 |
31 | pub fn from_slice(slice: &[u8], secret: &[u8]) ->Result {
32 | let deser: SealedBiscuit = serde_cbor::from_slice(slice)
33 | .map_err(|e| format!("deserialization error: {:?}", e))?;
34 |
35 | let mut mac = HmacSha256::new_varkey(secret).unwrap();
36 | mac.input(&deser.authority);
37 | for block in deser.blocks.iter() {
38 | mac.input(&block);
39 | }
40 |
41 | mac.verify(&deser.signature).map_err(|e| format!("invalid signature: {:?}", e))?;
42 |
43 | Ok(deser)
44 | }
45 |
46 | pub fn to_vec(&self) -> Vec {
47 | serde_cbor::ser::to_vec_packed(self).unwrap()
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/experimentations/biscuit-poc/src/ser.rs:
--------------------------------------------------------------------------------
1 | use curve25519_dalek::ristretto::RistrettoPoint;
2 | use serde::{Serialize, Deserialize};
3 | use vrf::{KeyPair, TokenSignature};
4 |
5 | use super::Block;
6 |
7 | #[derive(Clone,Debug,Serialize,Deserialize)]
8 | pub struct SerializedBiscuit {
9 | pub authority: Vec,
10 | pub blocks: Vec>,
11 | pub keys: Vec,
12 | pub signature: TokenSignature,
13 | }
14 |
15 | impl SerializedBiscuit {
16 | pub fn from_slice(slice: &[u8], public_key: RistrettoPoint) -> Result {
17 | let deser: SerializedBiscuit = serde_cbor::from_slice(&slice)
18 | .map_err(|e| format!("deserialization error: {:?}", e))?;
19 |
20 | if !deser.verify(public_key) {
21 | return Err(String::from("invalid signature"));
22 | }
23 |
24 | Ok(deser)
25 | }
26 |
27 | pub fn to_vec(&self) -> Vec {
28 | serde_cbor::ser::to_vec_packed(self).unwrap()
29 | }
30 |
31 | pub fn new(keypair: &KeyPair, authority: &Block) -> Self {
32 | let v: Vec = serde_cbor::ser::to_vec_packed(authority).unwrap();
33 | let signature = TokenSignature::new(keypair, &v);
34 |
35 | SerializedBiscuit {
36 | authority: v,
37 | blocks: vec![],
38 | keys: vec![keypair.public],
39 | signature
40 | }
41 | }
42 |
43 | pub fn append(&self, keypair: &KeyPair, block: &Block) -> Self {
44 | let v: Vec = serde_cbor::ser::to_vec_packed(block).unwrap();
45 |
46 | let mut blocks = Vec::new();
47 | blocks.push(self.authority.clone());
48 | blocks.extend(self.blocks.iter().cloned());
49 |
50 | let signature = self.signature.sign(&self.keys, &blocks, keypair, &v);
51 |
52 | let mut t = SerializedBiscuit {
53 | authority: self.authority.clone(),
54 | blocks: self.blocks.clone(),
55 | keys: self.keys.clone(),
56 | signature
57 | };
58 |
59 | t.blocks.push(v);
60 | t.keys.push(keypair.public);
61 |
62 | t
63 | }
64 |
65 | pub fn verify(&self, public: RistrettoPoint) -> bool {
66 | if self.keys.is_empty() {
67 | return false;
68 | }
69 | if self.keys[0] != public {
70 | return false;
71 | }
72 |
73 | let mut blocks = Vec::new();
74 | blocks.push(self.authority.clone());
75 | blocks.extend(self.blocks.iter().cloned());
76 |
77 | self.signature.verify(&self.keys, &blocks)
78 | }
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/experimentations/biscuit-poc/src/verifier.rs:
--------------------------------------------------------------------------------
1 | use super::builder::{Fact,Rule, fact, rule, pred, date, string, s,
2 | constrained_rule, Atom};
3 | use datalog::{Constraint, ConstraintKind, IntConstraint};
4 | use super::Biscuit;
5 | use std::time::{UNIX_EPOCH, SystemTime};
6 |
7 | pub struct Verifier {
8 | facts: Vec,
9 | rules: Vec,
10 | caveats: Vec,
11 | }
12 |
13 | impl Verifier {
14 | pub fn new() -> Self {
15 | Verifier {
16 | facts: vec![],
17 | rules: vec![],
18 | caveats: vec![]
19 | }
20 | }
21 |
22 | pub fn add_fact(&mut self, fact: Fact) {
23 | self.facts.push(fact);
24 | }
25 |
26 | pub fn add_rule(&mut self, rule: Rule) {
27 | self.rules.push(rule);
28 | }
29 |
30 | pub fn add_caveat(&mut self, caveat: Rule) {
31 | self.caveats.push(caveat);
32 | }
33 |
34 | pub fn resource(&mut self, resource: &str) {
35 | self.facts.push(fact("resource", &[s("ambient"), string(resource)]));
36 | }
37 |
38 | pub fn operation(&mut self, operation: &str) {
39 | self.facts.push(fact("operation", &[s("ambient"), s(operation)]));
40 | }
41 |
42 | pub fn time(&mut self) {
43 | self.facts.push(fact("time", &[s("ambient"), date(&SystemTime::now())]));
44 | }
45 |
46 | pub fn revocation_check(&mut self, ids: &[i64]) {
47 | let caveat = constrained_rule("revocation_check", &[Atom::Variable(0)],
48 | &[pred("revocation_id", &[Atom::Variable(0)])],
49 | &[Constraint {
50 | id: 0,
51 | kind: ConstraintKind::Int(IntConstraint::NotIn(ids.iter().cloned().collect()))
52 | }]
53 | );
54 | self.add_caveat(caveat);
55 | }
56 |
57 | pub fn verify(&self, mut token: Biscuit) -> Result<(), Vec> {
58 | let symbols = &mut token.symbols;
59 |
60 | let mut ambient_facts = vec![];
61 | let mut ambient_rules = vec![];
62 | let mut ambient_caveats = vec![];
63 |
64 | for fact in self.facts.iter() {
65 | ambient_facts.push(fact.convert(symbols));
66 | }
67 |
68 | for rule in self.rules.iter() {
69 | ambient_rules.push(rule.convert(symbols));
70 | }
71 |
72 | for caveat in self.caveats.iter() {
73 | ambient_caveats.push(caveat.convert(symbols));
74 | }
75 |
76 | token.check(ambient_facts, ambient_rules, ambient_caveats)
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/experimentations/challenge-tokens/biscuit-challenge-tokens/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 |
--------------------------------------------------------------------------------
/experimentations/challenge-tokens/biscuit-challenge-tokens/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | [[package]]
4 | name = "autocfg"
5 | version = "0.1.2"
6 | source = "registry+https://github.com/rust-lang/crates.io-index"
7 |
8 | [[package]]
9 | name = "biscuit-challenge-tokens"
10 | version = "0.1.0"
11 | dependencies = [
12 | "curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
13 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
14 | "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
15 | ]
16 |
17 | [[package]]
18 | name = "bitflags"
19 | version = "1.0.4"
20 | source = "registry+https://github.com/rust-lang/crates.io-index"
21 |
22 | [[package]]
23 | name = "block-buffer"
24 | version = "0.7.2"
25 | source = "registry+https://github.com/rust-lang/crates.io-index"
26 | dependencies = [
27 | "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
28 | "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
29 | "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
30 | "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
31 | ]
32 |
33 | [[package]]
34 | name = "block-padding"
35 | version = "0.1.3"
36 | source = "registry+https://github.com/rust-lang/crates.io-index"
37 | dependencies = [
38 | "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
39 | ]
40 |
41 | [[package]]
42 | name = "byte-tools"
43 | version = "0.3.1"
44 | source = "registry+https://github.com/rust-lang/crates.io-index"
45 |
46 | [[package]]
47 | name = "byteorder"
48 | version = "1.3.1"
49 | source = "registry+https://github.com/rust-lang/crates.io-index"
50 |
51 | [[package]]
52 | name = "cc"
53 | version = "1.0.28"
54 | source = "registry+https://github.com/rust-lang/crates.io-index"
55 |
56 | [[package]]
57 | name = "clear_on_drop"
58 | version = "0.2.3"
59 | source = "registry+https://github.com/rust-lang/crates.io-index"
60 | dependencies = [
61 | "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
62 | ]
63 |
64 | [[package]]
65 | name = "cloudabi"
66 | version = "0.0.3"
67 | source = "registry+https://github.com/rust-lang/crates.io-index"
68 | dependencies = [
69 | "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
70 | ]
71 |
72 | [[package]]
73 | name = "curve25519-dalek"
74 | version = "1.0.3"
75 | source = "registry+https://github.com/rust-lang/crates.io-index"
76 | dependencies = [
77 | "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
78 | "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
79 | "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
80 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
81 | "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
82 | ]
83 |
84 | [[package]]
85 | name = "digest"
86 | version = "0.8.0"
87 | source = "registry+https://github.com/rust-lang/crates.io-index"
88 | dependencies = [
89 | "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
90 | ]
91 |
92 | [[package]]
93 | name = "fake-simd"
94 | version = "0.1.2"
95 | source = "registry+https://github.com/rust-lang/crates.io-index"
96 |
97 | [[package]]
98 | name = "fuchsia-cprng"
99 | version = "0.1.0"
100 | source = "registry+https://github.com/rust-lang/crates.io-index"
101 |
102 | [[package]]
103 | name = "generic-array"
104 | version = "0.12.0"
105 | source = "registry+https://github.com/rust-lang/crates.io-index"
106 | dependencies = [
107 | "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
108 | ]
109 |
110 | [[package]]
111 | name = "libc"
112 | version = "0.2.48"
113 | source = "registry+https://github.com/rust-lang/crates.io-index"
114 |
115 | [[package]]
116 | name = "opaque-debug"
117 | version = "0.2.2"
118 | source = "registry+https://github.com/rust-lang/crates.io-index"
119 |
120 | [[package]]
121 | name = "rand"
122 | version = "0.6.5"
123 | source = "registry+https://github.com/rust-lang/crates.io-index"
124 | dependencies = [
125 | "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
126 | "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
127 | "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
128 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
129 | "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
130 | "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
131 | "rand_jitter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
132 | "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
133 | "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
134 | "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
135 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
136 | ]
137 |
138 | [[package]]
139 | name = "rand_chacha"
140 | version = "0.1.1"
141 | source = "registry+https://github.com/rust-lang/crates.io-index"
142 | dependencies = [
143 | "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
144 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
145 | ]
146 |
147 | [[package]]
148 | name = "rand_core"
149 | version = "0.3.1"
150 | source = "registry+https://github.com/rust-lang/crates.io-index"
151 | dependencies = [
152 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
153 | ]
154 |
155 | [[package]]
156 | name = "rand_core"
157 | version = "0.4.0"
158 | source = "registry+https://github.com/rust-lang/crates.io-index"
159 |
160 | [[package]]
161 | name = "rand_hc"
162 | version = "0.1.0"
163 | source = "registry+https://github.com/rust-lang/crates.io-index"
164 | dependencies = [
165 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
166 | ]
167 |
168 | [[package]]
169 | name = "rand_isaac"
170 | version = "0.1.1"
171 | source = "registry+https://github.com/rust-lang/crates.io-index"
172 | dependencies = [
173 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
174 | ]
175 |
176 | [[package]]
177 | name = "rand_jitter"
178 | version = "0.1.1"
179 | source = "registry+https://github.com/rust-lang/crates.io-index"
180 | dependencies = [
181 | "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
182 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
183 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
184 | ]
185 |
186 | [[package]]
187 | name = "rand_os"
188 | version = "0.1.2"
189 | source = "registry+https://github.com/rust-lang/crates.io-index"
190 | dependencies = [
191 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
192 | "fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
193 | "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
194 | "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
195 | "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
196 | "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
197 | ]
198 |
199 | [[package]]
200 | name = "rand_pcg"
201 | version = "0.1.1"
202 | source = "registry+https://github.com/rust-lang/crates.io-index"
203 | dependencies = [
204 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
205 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
206 | ]
207 |
208 | [[package]]
209 | name = "rand_xorshift"
210 | version = "0.1.1"
211 | source = "registry+https://github.com/rust-lang/crates.io-index"
212 | dependencies = [
213 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
214 | ]
215 |
216 | [[package]]
217 | name = "rdrand"
218 | version = "0.4.0"
219 | source = "registry+https://github.com/rust-lang/crates.io-index"
220 | dependencies = [
221 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
222 | ]
223 |
224 | [[package]]
225 | name = "rustc_version"
226 | version = "0.2.3"
227 | source = "registry+https://github.com/rust-lang/crates.io-index"
228 | dependencies = [
229 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
230 | ]
231 |
232 | [[package]]
233 | name = "semver"
234 | version = "0.9.0"
235 | source = "registry+https://github.com/rust-lang/crates.io-index"
236 | dependencies = [
237 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
238 | ]
239 |
240 | [[package]]
241 | name = "semver-parser"
242 | version = "0.7.0"
243 | source = "registry+https://github.com/rust-lang/crates.io-index"
244 |
245 | [[package]]
246 | name = "sha2"
247 | version = "0.8.0"
248 | source = "registry+https://github.com/rust-lang/crates.io-index"
249 | dependencies = [
250 | "block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
251 | "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
252 | "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
253 | "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
254 | ]
255 |
256 | [[package]]
257 | name = "subtle"
258 | version = "2.0.0"
259 | source = "registry+https://github.com/rust-lang/crates.io-index"
260 |
261 | [[package]]
262 | name = "typenum"
263 | version = "1.10.0"
264 | source = "registry+https://github.com/rust-lang/crates.io-index"
265 |
266 | [[package]]
267 | name = "winapi"
268 | version = "0.3.6"
269 | source = "registry+https://github.com/rust-lang/crates.io-index"
270 | dependencies = [
271 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
272 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
273 | ]
274 |
275 | [[package]]
276 | name = "winapi-i686-pc-windows-gnu"
277 | version = "0.4.0"
278 | source = "registry+https://github.com/rust-lang/crates.io-index"
279 |
280 | [[package]]
281 | name = "winapi-x86_64-pc-windows-gnu"
282 | version = "0.4.0"
283 | source = "registry+https://github.com/rust-lang/crates.io-index"
284 |
285 | [metadata]
286 | "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
287 | "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
288 | "checksum block-buffer 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "509de513cca6d92b6aacf9c61acfe7eaa160837323a81068d690cc1f8e5740da"
289 | "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591"
290 | "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
291 | "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
292 | "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
293 | "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17"
294 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
295 | "checksum curve25519-dalek 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dae47cc3529cdab597dbc8b606e565707209b506e55848f3c15679214a56c956"
296 | "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
297 | "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
298 | "checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31"
299 | "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
300 | "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
301 | "checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409"
302 | "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
303 | "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
304 | "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
305 | "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
306 | "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
307 | "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
308 | "checksum rand_jitter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29fe7b8bc348249f3b1bbb9ab8baa6fa3419196ecfbf213408bca1b2494710de"
309 | "checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d"
310 | "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
311 | "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
312 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
313 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
314 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
315 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
316 | "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
317 | "checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926"
318 | "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
319 | "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
320 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
321 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
322 |
--------------------------------------------------------------------------------
/experimentations/challenge-tokens/biscuit-challenge-tokens/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "biscuit-challenge-tokens"
3 | version = "0.1.0"
4 | authors = ["Geoffroy Couprie "]
5 | edition = "2018"
6 |
7 | [dependencies]
8 | curve25519-dalek = "^1.0"
9 | rand = "^0.6"
10 | sha2 = "^0.8"
11 |
--------------------------------------------------------------------------------
/experimentations/challenge-tokens/biscuit-challenge-tokens/benches/first.rs:
--------------------------------------------------------------------------------
1 | #![allow(deprecated)]
2 | #![feature(test)]
3 | extern crate test;
4 |
5 | extern crate biscuit_challenge_tokens;
6 | extern crate rand;
7 |
8 | use rand::{Rng, SeedableRng, XorShiftRng, OsRng};
9 | use biscuit_challenge_tokens::{KeyPair, Token, ChallengeToken};
10 | use test::Bencher;
11 |
12 | mod bench {
13 | use super::*;
14 | use test::Bencher;
15 |
16 | #[bench]
17 | fn sign_first_block(b: &mut Bencher) {
18 | let mut rng: OsRng = OsRng::new().unwrap();
19 |
20 | let message1 = b"hello";
21 | let keypair1 = KeyPair::new(&mut rng);
22 |
23 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
24 |
25 | assert!(token1.verify(), "cannot verify first token");
26 |
27 | b.iter(||{
28 | let t = Token::new(&mut rng, &keypair1, &message1[..]);
29 | t.challenge(&mut rng, &b"challenge data"[..])
30 | });
31 | }
32 |
33 | #[bench]
34 | fn sign_second_block(b: &mut Bencher) {
35 | let mut rng: OsRng = OsRng::new().unwrap();
36 |
37 | let message1 = b"hello";
38 | let keypair1 = KeyPair::new(&mut rng);
39 |
40 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
41 |
42 | assert!(token1.verify(), "cannot verify first token");
43 |
44 | println!("will derive a second token");
45 |
46 | let message2 = b"world";
47 |
48 | let token2 = token1.append(&mut rng, &message2[..]);
49 |
50 | assert!(token2.verify(), "cannot verify second token");
51 |
52 | b.iter(||{
53 | let t = token1.append(&mut rng, &message2[..]);
54 | t.challenge(&mut rng, &b"challenge data"[..])
55 | });
56 | }
57 |
58 | #[bench]
59 | fn sign_third_block(b: &mut Bencher) {
60 | let mut rng: OsRng = OsRng::new().unwrap();
61 |
62 | let message1 = b"hello";
63 | let keypair1 = KeyPair::new(&mut rng);
64 |
65 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
66 |
67 | assert!(token1.verify(), "cannot verify first token");
68 |
69 | println!("will derive a second token");
70 |
71 | let message2 = b"world";
72 |
73 | let token2 = token1.append(&mut rng, &message2[..]);
74 |
75 | assert!(token2.verify(), "cannot verify second token");
76 |
77 | println!("will derive a third token");
78 |
79 | let message3 = b"!!!";
80 |
81 | let token3 = token2.append(&mut rng, &message3[..]);
82 |
83 | assert!(token3.verify(), "cannot verify third token");
84 |
85 | b.iter(||{
86 | let t = token2.append(&mut rng, &message3[..]);
87 | t.challenge(&mut rng, &b"challenge data"[..])
88 | });
89 | }
90 |
91 | #[bench]
92 | fn verify_one_block(b: &mut Bencher) {
93 | let mut rng: OsRng = OsRng::new().unwrap();
94 |
95 | let message1 = b"hello";
96 | let keypair1 = KeyPair::new(&mut rng);
97 |
98 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
99 |
100 | assert!(token1.verify(), "cannot verify first token");
101 | let challenge = token1.challenge(&mut rng, &b"pouet"[..]);
102 | assert!(challenge.verify(), "cannot verify first challenge token");
103 |
104 | b.iter(||{
105 | challenge.verify()
106 | });
107 | }
108 |
109 | #[bench]
110 | fn verify_two_blocks(b: &mut Bencher) {
111 | let mut rng: OsRng = OsRng::new().unwrap();
112 |
113 | let message1 = b"hello";
114 | let keypair1 = KeyPair::new(&mut rng);
115 |
116 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
117 |
118 | assert!(token1.verify(), "cannot verify first token");
119 |
120 | println!("will derive a second token");
121 |
122 | let message2 = b"world";
123 |
124 | let token2 = token1.append(&mut rng, &message2[..]);
125 |
126 | assert!(token2.verify(), "cannot verify second token");
127 | let challenge = token2.challenge(&mut rng, &b"test"[..]);
128 | assert!(challenge.verify(), "cannot verify second challenge token");
129 |
130 | b.iter(||{
131 | challenge.verify()
132 | });
133 | }
134 |
135 | #[bench]
136 | fn verify_three_blocks(b: &mut Bencher) {
137 | let mut rng: OsRng = OsRng::new().unwrap();
138 |
139 | let message1 = b"hello";
140 | let keypair1 = KeyPair::new(&mut rng);
141 |
142 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
143 |
144 | assert!(token1.verify(), "cannot verify first token");
145 |
146 | println!("will derive a second token");
147 |
148 | let message2 = b"world";
149 |
150 | let token2 = token1.append(&mut rng, &message2[..]);
151 |
152 | assert!(token2.verify(), "cannot verify second token");
153 |
154 | println!("will derive a third token");
155 |
156 | let message3 = b"!!!";
157 |
158 | let token3 = token2.append(&mut rng, &message3[..]);
159 |
160 | assert!(token3.verify(), "cannot verify third token");
161 | let challenge = token3.challenge(&mut rng, &b"time"[..]);
162 | assert!(challenge.verify(), "cannot verify third challenge token");
163 |
164 | b.iter(||{
165 | challenge.verify()
166 | });
167 | }
168 | }
169 |
170 |
171 |
--------------------------------------------------------------------------------
/experimentations/challenge-tokens/biscuit-challenge-tokens/src/lib.rs:
--------------------------------------------------------------------------------
1 | extern crate curve25519_dalek;
2 | extern crate rand;
3 | extern crate sha2;
4 |
5 | use sha2::{Digest, Sha512};
6 | use rand::{Rng, CryptoRng};
7 | use curve25519_dalek::{
8 | constants::RISTRETTO_BASEPOINT_POINT,
9 | ristretto::{RistrettoPoint},
10 | scalar::Scalar,
11 | traits::Identity
12 | };
13 | use std::ops::{Deref, Neg};
14 |
15 | pub struct KeyPair {
16 | private: Scalar,
17 | public: RistrettoPoint,
18 | }
19 |
20 | impl KeyPair {
21 | pub fn new(rng: &mut T) -> Self {
22 | let private = Scalar::random(rng);
23 | let public = private * RISTRETTO_BASEPOINT_POINT;
24 |
25 | KeyPair { private, public }
26 | }
27 | }
28 |
29 | #[derive(Clone,Debug,PartialEq)]
30 | pub struct Signature {
31 | s: Scalar,
32 | e: Scalar,
33 | }
34 |
35 | // schnorr signature
36 | pub fn sign(rng: &mut T, private_key: &Scalar, message: &[u8], next_data: Option<&[u8]>)
37 | -> Signature {
38 |
39 | let k = Scalar::random(rng);
40 | let r = k * RISTRETTO_BASEPOINT_POINT;
41 |
42 | let mut h = Sha512::new();
43 | h.input(r.compress().as_bytes());
44 | h.input(message);
45 | if let Some(data) = next_data {
46 | h.input(data);
47 | }
48 | let e = Scalar::from_hash(h);
49 |
50 | let s = k - private_key * e;
51 |
52 | Signature { s, e }
53 | }
54 |
55 | pub fn verify(public_key: &RistrettoPoint, message: &[u8], next_data: Option<&[u8]>, signature: &Signature)
56 | -> bool {
57 |
58 | let r = (signature.s * RISTRETTO_BASEPOINT_POINT) + (signature.e * public_key);
59 | let mut h = Sha512::new();
60 | h.input(r.compress().as_bytes());
61 | h.input(message);
62 | if let Some(data) = next_data {
63 | h.input(data);
64 | }
65 | let e = Scalar::from_hash(h);
66 |
67 | e == signature.e
68 | }
69 |
70 | pub struct Token {
71 | pub messages: Vec>,
72 | pub keys: Vec,
73 | pub signatures: Vec,
74 | pub next_key: Scalar,
75 | }
76 |
77 | impl Token {
78 | pub fn new(rng: &mut T, keypair: &KeyPair, message: &[u8]) -> Self {
79 | let next_key = Scalar::random(rng);
80 | let next_public = next_key * RISTRETTO_BASEPOINT_POINT;
81 |
82 | let signature = sign(rng, &keypair.private, message, Some(next_public.compress().as_bytes()));
83 |
84 | Token {
85 | messages: vec![message.to_owned()],
86 | keys: vec![keypair.public],
87 | signatures: vec![signature],
88 | next_key,
89 | }
90 | }
91 |
92 | pub fn append(&self, rng: &mut T, message: &[u8]) -> Self {
93 | let next_key = Scalar::random(rng);
94 | let next_public = next_key * RISTRETTO_BASEPOINT_POINT;
95 |
96 | let signature = sign(rng, &self.next_key, message, Some(next_public.compress().as_bytes()));
97 |
98 | let mut t = Token {
99 | messages: self.messages.clone(),
100 | keys: self.keys.clone(),
101 | signatures: self.signatures.clone(),
102 | next_key,
103 | };
104 |
105 | let current_public = self.next_key * RISTRETTO_BASEPOINT_POINT;
106 |
107 | t.messages.push(message.to_owned());
108 | t.keys.push(current_public);
109 | t.signatures.push(signature);
110 |
111 | t
112 | }
113 |
114 | pub fn verify(&self) -> bool {
115 | assert_eq!(self.messages.len(), self.keys.len());
116 | assert_eq!(self.messages.len(), self.signatures.len());
117 |
118 | let mut keys = self.keys.clone();
119 | keys.push(self.next_key * RISTRETTO_BASEPOINT_POINT);
120 |
121 | for i in 0..self.messages.len() {
122 | if !verify(&keys[i], &self.messages[i], Some(keys[i+1].compress().as_bytes()), &self.signatures[i]) {
123 | println!("error verifying signature {}", i);
124 | return false;
125 | } else {
126 | println!("signature {} verified", i);
127 | }
128 | }
129 |
130 | true
131 | }
132 |
133 | pub fn challenge(&self, rng: &mut T, challenge: &[u8]) -> ChallengeToken {
134 | let next_public = self.next_key * RISTRETTO_BASEPOINT_POINT;
135 | let mut h = Sha512::new();
136 | for i in 0..self.messages.len() {
137 | h.input(&self.messages[i]);
138 | h.input(self.keys[i].compress().as_bytes());
139 | h.input(self.signatures[i].s.as_bytes());
140 | h.input(self.signatures[i].e.as_bytes());
141 | }
142 | h.input(next_public.compress().as_bytes());
143 |
144 | // maybe we should hash the whole message instead of just the last signature
145 | let signature = sign(rng, &self.next_key, challenge, Some(h.result().as_slice()));
146 |
147 | ChallengeToken {
148 | messages: self.messages.clone(),
149 | keys: self.keys.clone(),
150 | signatures: self.signatures.clone(),
151 | challenge: Vec::from(challenge),
152 | response: signature,
153 | next_public,
154 | }
155 | }
156 | }
157 |
158 | pub struct ChallengeToken {
159 | pub messages: Vec>,
160 | pub keys: Vec,
161 | pub signatures: Vec,
162 | pub challenge: Vec,
163 | pub response: Signature,
164 | pub next_public: RistrettoPoint,
165 | }
166 |
167 | impl ChallengeToken {
168 | pub fn verify(&self) -> bool {
169 | let mut h = Sha512::new();
170 | for i in 0..self.messages.len() {
171 | h.input(&self.messages[i]);
172 | h.input(self.keys[i].compress().as_bytes());
173 | h.input(self.signatures[i].s.as_bytes());
174 | h.input(self.signatures[i].e.as_bytes());
175 | }
176 | h.input(self.next_public.compress().as_bytes());
177 |
178 | if !verify(&self.next_public, &self.challenge, Some(h.result().as_slice()), &self.response) {
179 | println!("error verifying challenge response");
180 | return false;
181 | }
182 |
183 | assert_eq!(self.messages.len(), self.keys.len());
184 | assert_eq!(self.messages.len(), self.signatures.len());
185 |
186 | let mut keys = self.keys.clone();
187 | keys.push(self.next_public);
188 |
189 | for i in 0..self.messages.len() {
190 | if !verify(&keys[i], &self.messages[i], Some(keys[i+1].compress().as_bytes()), &self.signatures[i]) {
191 | println!("error verifying signature {}", i);
192 | return false;
193 | }
194 | }
195 |
196 | true
197 | }
198 | }
199 |
200 | #[cfg(test)]
201 | mod tests {
202 | use super::*;
203 | use rand::{OsRng,SeedableRng,StdRng};
204 |
205 | #[test]
206 | fn three_messages() {
207 | //let mut rng: OsRng = OsRng::new().unwrap();
208 | //keep the same values in tests
209 | let mut rng: StdRng = SeedableRng::seed_from_u64(0);
210 |
211 | let message1 = b"hello";
212 | let keypair1 = KeyPair::new(&mut rng);
213 |
214 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
215 |
216 | assert!(token1.verify(), "cannot verify first token");
217 | assert!(token1.challenge(&mut rng, &b"pouet"[..]).verify(), "cannot verify first challenge token");
218 |
219 | println!("will derive a second token");
220 |
221 | let message2 = b"world";
222 |
223 | let token2 = token1.append(&mut rng, &message2[..]);
224 |
225 | assert!(token2.verify(), "cannot verify second token");
226 | assert!(token2.challenge(&mut rng, &b"hi"[..]).verify(), "cannot verify second challenge token");
227 |
228 | println!("will derive a third token");
229 |
230 | let message3 = b"!!!";
231 |
232 | let token3 = token2.append(&mut rng, &message3[..]);
233 |
234 | assert!(token3.verify(), "cannot verify third token");
235 | assert!(token3.challenge(&mut rng, &b"test"[..]).verify(), "cannot verify third challenge token");
236 | }
237 |
238 | #[test]
239 | fn change_message() {
240 | //let mut rng: OsRng = OsRng::new().unwrap();
241 | //keep the same values in tests
242 | let mut rng: StdRng = SeedableRng::seed_from_u64(0);
243 |
244 | let message1 = b"hello";
245 | let keypair1 = KeyPair::new(&mut rng);
246 |
247 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
248 |
249 | assert!(token1.verify(), "cannot verify first token");
250 |
251 | println!("will derive a second token");
252 |
253 | let message2 = b"world";
254 |
255 | let mut token2 = token1.append(&mut rng, &message2[..]);
256 |
257 | token2.messages[1] = Vec::from(&b"you"[..]);
258 |
259 | assert!(!token2.verify(), "second token should not be valid");
260 |
261 | println!("will derive a third token");
262 |
263 | let message3 = b"!!!";
264 |
265 | let token3 = token2.append(&mut rng, &message3[..]);
266 |
267 | assert!(!token3.verify(), "third token should not be valid");
268 | }
269 | }
270 |
--------------------------------------------------------------------------------
/experimentations/datalog/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | **/*.rs.bk
3 | Cargo.lock
4 |
--------------------------------------------------------------------------------
/experimentations/datalog/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "datalog_with_constraints"
3 | version = "0.1.0"
4 | authors = ["Geoffroy Couprie "]
5 | edition = "2018"
6 |
7 | [features]
8 | default = ["unstable"]
9 | unstable = []
10 |
11 | [dependencies]
12 | sha2 = "0.8"
13 | serde = { version = "1.0", features = ["derive"] }
14 |
15 |
--------------------------------------------------------------------------------
/experimentations/datalog/README.md:
--------------------------------------------------------------------------------
1 | # datalog with constraints implementation
2 |
3 | Example implementation of https://www.cs.purdue.edu/homes/ninghui/papers/cdatalog_padl03.pdf
4 |
5 | And tests of its use as caveat language
6 |
--------------------------------------------------------------------------------
/experimentations/gamma/biscuit-gamma/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 |
--------------------------------------------------------------------------------
/experimentations/gamma/biscuit-gamma/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | [[package]]
4 | name = "autocfg"
5 | version = "0.1.6"
6 | source = "registry+https://github.com/rust-lang/crates.io-index"
7 |
8 | [[package]]
9 | name = "biscuit-gamma"
10 | version = "0.1.0"
11 | dependencies = [
12 | "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
13 | "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
14 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
15 | "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
16 | "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
17 | ]
18 |
19 | [[package]]
20 | name = "bitflags"
21 | version = "1.1.0"
22 | source = "registry+https://github.com/rust-lang/crates.io-index"
23 |
24 | [[package]]
25 | name = "block-buffer"
26 | version = "0.7.3"
27 | source = "registry+https://github.com/rust-lang/crates.io-index"
28 | dependencies = [
29 | "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
30 | "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
31 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
32 | "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
33 | ]
34 |
35 | [[package]]
36 | name = "block-padding"
37 | version = "0.1.4"
38 | source = "registry+https://github.com/rust-lang/crates.io-index"
39 | dependencies = [
40 | "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
41 | ]
42 |
43 | [[package]]
44 | name = "byte-tools"
45 | version = "0.3.1"
46 | source = "registry+https://github.com/rust-lang/crates.io-index"
47 |
48 | [[package]]
49 | name = "byteorder"
50 | version = "1.3.2"
51 | source = "registry+https://github.com/rust-lang/crates.io-index"
52 |
53 | [[package]]
54 | name = "cc"
55 | version = "1.0.41"
56 | source = "registry+https://github.com/rust-lang/crates.io-index"
57 |
58 | [[package]]
59 | name = "clear_on_drop"
60 | version = "0.2.3"
61 | source = "registry+https://github.com/rust-lang/crates.io-index"
62 | dependencies = [
63 | "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
64 | ]
65 |
66 | [[package]]
67 | name = "cloudabi"
68 | version = "0.0.3"
69 | source = "registry+https://github.com/rust-lang/crates.io-index"
70 | dependencies = [
71 | "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
72 | ]
73 |
74 | [[package]]
75 | name = "crypto-mac"
76 | version = "0.7.0"
77 | source = "registry+https://github.com/rust-lang/crates.io-index"
78 | dependencies = [
79 | "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
80 | "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
81 | ]
82 |
83 | [[package]]
84 | name = "curve25519-dalek"
85 | version = "1.2.3"
86 | source = "registry+https://github.com/rust-lang/crates.io-index"
87 | dependencies = [
88 | "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
89 | "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
90 | "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
91 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
92 | "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
93 | "subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
94 | ]
95 |
96 | [[package]]
97 | name = "digest"
98 | version = "0.8.1"
99 | source = "registry+https://github.com/rust-lang/crates.io-index"
100 | dependencies = [
101 | "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
102 | ]
103 |
104 | [[package]]
105 | name = "fake-simd"
106 | version = "0.1.2"
107 | source = "registry+https://github.com/rust-lang/crates.io-index"
108 |
109 | [[package]]
110 | name = "fuchsia-cprng"
111 | version = "0.1.1"
112 | source = "registry+https://github.com/rust-lang/crates.io-index"
113 |
114 | [[package]]
115 | name = "generic-array"
116 | version = "0.12.3"
117 | source = "registry+https://github.com/rust-lang/crates.io-index"
118 | dependencies = [
119 | "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
120 | ]
121 |
122 | [[package]]
123 | name = "hmac"
124 | version = "0.7.1"
125 | source = "registry+https://github.com/rust-lang/crates.io-index"
126 | dependencies = [
127 | "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
128 | "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
129 | ]
130 |
131 | [[package]]
132 | name = "libc"
133 | version = "0.2.62"
134 | source = "registry+https://github.com/rust-lang/crates.io-index"
135 |
136 | [[package]]
137 | name = "opaque-debug"
138 | version = "0.2.3"
139 | source = "registry+https://github.com/rust-lang/crates.io-index"
140 |
141 | [[package]]
142 | name = "proc-macro2"
143 | version = "1.0.2"
144 | source = "registry+https://github.com/rust-lang/crates.io-index"
145 | dependencies = [
146 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
147 | ]
148 |
149 | [[package]]
150 | name = "quote"
151 | version = "1.0.2"
152 | source = "registry+https://github.com/rust-lang/crates.io-index"
153 | dependencies = [
154 | "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
155 | ]
156 |
157 | [[package]]
158 | name = "rand"
159 | version = "0.6.5"
160 | source = "registry+https://github.com/rust-lang/crates.io-index"
161 | dependencies = [
162 | "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
163 | "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
164 | "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
165 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
166 | "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
167 | "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
168 | "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
169 | "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
170 | "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
171 | "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
172 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
173 | ]
174 |
175 | [[package]]
176 | name = "rand_chacha"
177 | version = "0.1.1"
178 | source = "registry+https://github.com/rust-lang/crates.io-index"
179 | dependencies = [
180 | "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
181 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
182 | ]
183 |
184 | [[package]]
185 | name = "rand_core"
186 | version = "0.3.1"
187 | source = "registry+https://github.com/rust-lang/crates.io-index"
188 | dependencies = [
189 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
190 | ]
191 |
192 | [[package]]
193 | name = "rand_core"
194 | version = "0.4.2"
195 | source = "registry+https://github.com/rust-lang/crates.io-index"
196 |
197 | [[package]]
198 | name = "rand_hc"
199 | version = "0.1.0"
200 | source = "registry+https://github.com/rust-lang/crates.io-index"
201 | dependencies = [
202 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
203 | ]
204 |
205 | [[package]]
206 | name = "rand_isaac"
207 | version = "0.1.1"
208 | source = "registry+https://github.com/rust-lang/crates.io-index"
209 | dependencies = [
210 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
211 | ]
212 |
213 | [[package]]
214 | name = "rand_jitter"
215 | version = "0.1.4"
216 | source = "registry+https://github.com/rust-lang/crates.io-index"
217 | dependencies = [
218 | "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
219 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
220 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
221 | ]
222 |
223 | [[package]]
224 | name = "rand_os"
225 | version = "0.1.3"
226 | source = "registry+https://github.com/rust-lang/crates.io-index"
227 | dependencies = [
228 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
229 | "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
230 | "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
231 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
232 | "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
233 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
234 | ]
235 |
236 | [[package]]
237 | name = "rand_pcg"
238 | version = "0.1.2"
239 | source = "registry+https://github.com/rust-lang/crates.io-index"
240 | dependencies = [
241 | "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
242 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
243 | ]
244 |
245 | [[package]]
246 | name = "rand_xorshift"
247 | version = "0.1.1"
248 | source = "registry+https://github.com/rust-lang/crates.io-index"
249 | dependencies = [
250 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
251 | ]
252 |
253 | [[package]]
254 | name = "rdrand"
255 | version = "0.4.0"
256 | source = "registry+https://github.com/rust-lang/crates.io-index"
257 | dependencies = [
258 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
259 | ]
260 |
261 | [[package]]
262 | name = "serde"
263 | version = "1.0.99"
264 | source = "registry+https://github.com/rust-lang/crates.io-index"
265 | dependencies = [
266 | "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
267 | ]
268 |
269 | [[package]]
270 | name = "serde_derive"
271 | version = "1.0.99"
272 | source = "registry+https://github.com/rust-lang/crates.io-index"
273 | dependencies = [
274 | "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
275 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
276 | "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
277 | ]
278 |
279 | [[package]]
280 | name = "sha2"
281 | version = "0.8.0"
282 | source = "registry+https://github.com/rust-lang/crates.io-index"
283 | dependencies = [
284 | "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
285 | "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
286 | "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
287 | "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
288 | ]
289 |
290 | [[package]]
291 | name = "subtle"
292 | version = "1.0.0"
293 | source = "registry+https://github.com/rust-lang/crates.io-index"
294 |
295 | [[package]]
296 | name = "subtle"
297 | version = "2.1.1"
298 | source = "registry+https://github.com/rust-lang/crates.io-index"
299 |
300 | [[package]]
301 | name = "syn"
302 | version = "1.0.5"
303 | source = "registry+https://github.com/rust-lang/crates.io-index"
304 | dependencies = [
305 | "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
306 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
307 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
308 | ]
309 |
310 | [[package]]
311 | name = "typenum"
312 | version = "1.11.2"
313 | source = "registry+https://github.com/rust-lang/crates.io-index"
314 |
315 | [[package]]
316 | name = "unicode-xid"
317 | version = "0.2.0"
318 | source = "registry+https://github.com/rust-lang/crates.io-index"
319 |
320 | [[package]]
321 | name = "winapi"
322 | version = "0.3.8"
323 | source = "registry+https://github.com/rust-lang/crates.io-index"
324 | dependencies = [
325 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
326 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
327 | ]
328 |
329 | [[package]]
330 | name = "winapi-i686-pc-windows-gnu"
331 | version = "0.4.0"
332 | source = "registry+https://github.com/rust-lang/crates.io-index"
333 |
334 | [[package]]
335 | name = "winapi-x86_64-pc-windows-gnu"
336 | version = "0.4.0"
337 | source = "registry+https://github.com/rust-lang/crates.io-index"
338 |
339 | [metadata]
340 | "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
341 | "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
342 | "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
343 | "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
344 | "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
345 | "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
346 | "checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff"
347 | "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17"
348 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
349 | "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
350 | "checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d"
351 | "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
352 | "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
353 | "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
354 | "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
355 | "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
356 | "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
357 | "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
358 | "checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95"
359 | "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
360 | "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
361 | "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
362 | "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
363 | "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
364 | "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
365 | "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
366 | "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
367 | "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
368 | "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
369 | "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
370 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
371 | "checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
372 | "checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
373 | "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
374 | "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
375 | "checksum subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01f40907d9ffc762709e4ff3eb4a6f6b41b650375a3f09ac92b641942b7fb082"
376 | "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
377 | "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
378 | "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
379 | "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
380 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
381 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
382 |
--------------------------------------------------------------------------------
/experimentations/gamma/biscuit-gamma/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "biscuit-gamma"
3 | version = "0.1.0"
4 | authors = ["Geoffroy Couprie "]
5 | edition = "2018"
6 |
7 | [dependencies]
8 | curve25519-dalek = { version = "^1.0", features = ["serde"] }
9 | rand = "^0.6"
10 | sha2 = "^0.8"
11 | hmac = "^0.7"
12 | serde = { version = "1.0", features = ["derive"] }
13 |
14 |
--------------------------------------------------------------------------------
/experimentations/gamma/biscuit-gamma/benches/gamma.rs:
--------------------------------------------------------------------------------
1 | #![feature(test)]
2 | extern crate test;
3 |
4 | extern crate biscuit_gamma;
5 | extern crate rand;
6 |
7 | use rand::rngs::OsRng;
8 | use biscuit_gamma::{KeyPair, Token, TokenSignature};
9 |
10 | mod bench {
11 | use super::*;
12 | use test::Bencher;
13 |
14 | #[bench]
15 | fn sign_first_block(b: &mut Bencher) {
16 | let mut rng: OsRng = OsRng::new().unwrap();
17 |
18 | let message1 = b"hello";
19 | let keypair1 = KeyPair::new(&mut rng);
20 |
21 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
22 |
23 | assert!(token1.verify(), "cannot verify first token");
24 |
25 | b.iter(||{
26 | Token::new(&mut rng, &keypair1, &message1[..])
27 | });
28 | }
29 |
30 | #[bench]
31 | fn sign_second_block(b: &mut Bencher) {
32 | let mut rng: OsRng = OsRng::new().unwrap();
33 |
34 | let message1 = b"hello";
35 | let keypair1 = KeyPair::new(&mut rng);
36 |
37 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
38 |
39 | assert!(token1.verify(), "cannot verify first token");
40 |
41 | println!("will derive a second token");
42 |
43 | let message2 = b"world";
44 | let keypair2 = KeyPair::new(&mut rng);
45 |
46 | let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
47 |
48 | assert!(token2.verify(), "cannot verify second token");
49 |
50 | b.iter(||{
51 | token1.append(&mut rng, &keypair2, &message2[..])
52 | });
53 | }
54 |
55 | #[bench]
56 | fn sign_third_block(b: &mut Bencher) {
57 | let mut rng: OsRng = OsRng::new().unwrap();
58 |
59 | let message1 = b"hello";
60 | let keypair1 = KeyPair::new(&mut rng);
61 |
62 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
63 |
64 | assert!(token1.verify(), "cannot verify first token");
65 |
66 | println!("will derive a second token");
67 |
68 | let message2 = b"world";
69 | let keypair2 = KeyPair::new(&mut rng);
70 |
71 | let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
72 |
73 | assert!(token2.verify(), "cannot verify second token");
74 |
75 | println!("will derive a third token");
76 |
77 | let message3 = b"!!!";
78 | let keypair3 = KeyPair::new(&mut rng);
79 |
80 | let token3 = token2.append(&mut rng, &keypair3, &message3[..]);
81 |
82 | assert!(token3.verify(), "cannot verify third token");
83 |
84 | b.iter(||{
85 | token2.append(&mut rng, &keypair3, &message3[..])
86 | });
87 | }
88 |
89 | #[bench]
90 | fn verify_one_block(b: &mut Bencher) {
91 | let mut rng: OsRng = OsRng::new().unwrap();
92 |
93 | let message1 = b"hello";
94 | let keypair1 = KeyPair::new(&mut rng);
95 |
96 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
97 |
98 | assert!(token1.verify(), "cannot verify first token");
99 |
100 | b.iter(||{
101 | token1.verify()
102 | });
103 | }
104 |
105 | #[bench]
106 | fn verify_two_blocks(b: &mut Bencher) {
107 | let mut rng: OsRng = OsRng::new().unwrap();
108 |
109 | let message1 = b"hello";
110 | let keypair1 = KeyPair::new(&mut rng);
111 |
112 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
113 |
114 | assert!(token1.verify(), "cannot verify first token");
115 |
116 | println!("will derive a second token");
117 |
118 | let message2 = b"world";
119 | let keypair2 = KeyPair::new(&mut rng);
120 |
121 | let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
122 |
123 | assert!(token2.verify(), "cannot verify second token");
124 |
125 | b.iter(||{
126 | token2.verify()
127 | });
128 | }
129 |
130 | #[bench]
131 | fn verify_three_blocks(b: &mut Bencher) {
132 | let mut rng: OsRng = OsRng::new().unwrap();
133 |
134 | let message1 = b"hello";
135 | let keypair1 = KeyPair::new(&mut rng);
136 |
137 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
138 |
139 | assert!(token1.verify(), "cannot verify first token");
140 |
141 | println!("will derive a second token");
142 |
143 | let message2 = b"world";
144 | let keypair2 = KeyPair::new(&mut rng);
145 |
146 | let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
147 |
148 | assert!(token2.verify(), "cannot verify second token");
149 |
150 | println!("will derive a third token");
151 |
152 | let message3 = b"!!!";
153 | let keypair3 = KeyPair::new(&mut rng);
154 |
155 | let token3 = token2.append(&mut rng, &keypair3, &message3[..]);
156 |
157 | assert!(token3.verify(), "cannot verify third token");
158 |
159 | b.iter(||{
160 | token3.verify()
161 | });
162 | }
163 | }
164 |
165 |
166 |
--------------------------------------------------------------------------------
/experimentations/gamma/biscuit-gamma/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![allow(non_snake_case)]
2 |
3 | extern crate curve25519_dalek;
4 | extern crate rand;
5 | extern crate sha2;
6 | extern crate hmac;
7 | extern crate serde;
8 |
9 | use sha2::{Digest, Sha512};
10 | use hmac::{Hmac, Mac};
11 | use rand::prelude::*;
12 | use serde::{Serialize, Deserialize};
13 | use curve25519_dalek::{
14 | constants::RISTRETTO_BASEPOINT_POINT,
15 | ristretto::{RistrettoPoint},
16 | scalar::Scalar,
17 | traits::Identity
18 | };
19 | use std::ops::{Deref, Neg};
20 |
21 | type HmacSha512 = Hmac;
22 |
23 |
24 | pub struct KeyPair {
25 | private: Scalar,
26 | pub public: RistrettoPoint,
27 | }
28 |
29 | impl KeyPair {
30 | pub fn new(rng: &mut T) -> Self {
31 | let private = Scalar::random(rng);
32 | let public = private * RISTRETTO_BASEPOINT_POINT;
33 |
34 | KeyPair { private, public }
35 | }
36 |
37 | pub fn sign(&self, rng: &mut T, message: &[u8]) -> (Scalar, Scalar) {
38 | let r = Scalar::random(rng);
39 | let A = r * RISTRETTO_BASEPOINT_POINT;
40 | let d = ECVRF_hash_points(&[A]);
41 | // FIXME: maybe there's a simpler hashing process
42 | let e = ECVRF_hash_points(&[self.public, ECVRF_hash_to_curve(RISTRETTO_BASEPOINT_POINT, message)]);
43 | let z = r*d - e*self.private;
44 | (d, z)
45 | }
46 | }
47 |
48 | pub fn verify(public: &RistrettoPoint, message: &[u8], signature: &(Scalar, Scalar)) -> bool {
49 | let (d, z) = signature;
50 | let e = ECVRF_hash_points(&[*public, ECVRF_hash_to_curve(RISTRETTO_BASEPOINT_POINT, message)]);
51 | let d_inv = d.invert();
52 | let A = z * d_inv * RISTRETTO_BASEPOINT_POINT + e * d_inv * public;
53 |
54 | ECVRF_hash_points(&[A]) == *d
55 | }
56 |
57 | pub struct Token {
58 | pub messages: Vec>,
59 | pub keys: Vec,
60 | pub signature: TokenSignature,
61 | }
62 |
63 | impl Token {
64 | pub fn new(rng: &mut T, keypair: &KeyPair, message: &[u8]) -> Self {
65 | let signature = TokenSignature::new(rng, keypair, message);
66 |
67 | Token {
68 | messages: vec![message.to_owned()],
69 | keys: vec![keypair.public],
70 | signature
71 | }
72 | }
73 |
74 | pub fn append(&self, rng: &mut T, keypair: &KeyPair, message: &[u8]) -> Self {
75 | let signature = self.signature.sign(rng, &self.keys, &self.messages, keypair, message);
76 |
77 | let mut t = Token {
78 | messages: self.messages.clone(),
79 | keys: self.keys.clone(),
80 | signature
81 | };
82 |
83 | t.messages.push(message.to_owned());
84 | t.keys.push(keypair.public);
85 |
86 | t
87 | }
88 |
89 | pub fn verify(&self) -> bool {
90 | self.signature.verify(&self.keys, &self.messages)
91 | }
92 | }
93 |
94 | #[derive(Clone,Debug,Serialize,Deserialize)]
95 | pub struct TokenSignature {
96 | parameters: Vec,
97 | z: Scalar
98 | }
99 |
100 | impl TokenSignature {
101 | pub fn new(rng: &mut T, keypair: &KeyPair, message: &[u8]) -> Self {
102 | let r = Scalar::random(rng);
103 | let A = r * RISTRETTO_BASEPOINT_POINT;
104 | let d = ECVRF_hash_points(&[A]);
105 | let e = hash_message(keypair.public, message);
106 | let z = r*d - e * keypair.private;
107 |
108 | TokenSignature {
109 | parameters: vec![A],
110 | z: z,
111 | }
112 | }
113 |
114 | pub fn sign, T: Rng + CryptoRng>(&self, rng: &mut T, public_keys: &[RistrettoPoint],
115 | messages: &[M], keypair: &KeyPair, message: &[u8]) -> Self {
116 | let r = Scalar::random(rng);
117 | let A = r * RISTRETTO_BASEPOINT_POINT;
118 | let d = ECVRF_hash_points(&[A]);
119 | let e = hash_message(keypair.public, message);
120 | let z = r*d - e * keypair.private;
121 |
122 | let mut t = TokenSignature {
123 | parameters: self.parameters.clone(),
124 | z: self.z + z,
125 | };
126 |
127 | t.parameters.push(A);
128 | t
129 | }
130 |
131 | pub fn verify>(&self, public_keys: &[RistrettoPoint], messages: &[M]) -> bool {
132 | if !(public_keys.len() == messages.len()
133 | && public_keys.len() == self.parameters.len()) {
134 | println!("invalid data");
135 | return false;
136 | }
137 |
138 | let zP = self.z * RISTRETTO_BASEPOINT_POINT;
139 | let eiXi = public_keys.iter().zip(messages).map(|(pubkey, message)| {
140 | let e = hash_message(*pubkey, message);
141 | e * pubkey
142 | }).fold(RistrettoPoint::identity(), |acc, point| acc + point);
143 |
144 | let diAi = self.parameters.iter().map(|A| {
145 | let d = ECVRF_hash_points(&[*A]);
146 | d * A
147 | }).fold(RistrettoPoint::identity(), |acc, point| acc + point);
148 |
149 | let res = zP + eiXi - diAi;
150 |
151 | /*
152 | println!("verify identity={:?}", RistrettoPoint::identity());
153 | println!("verify res={:?}", res);
154 | println!("verify identity={:?}", RistrettoPoint::identity().compress());
155 | println!("verify res={:?}", res.compress());
156 | println!("returning: {:?}", RistrettoPoint::identity() == res);
157 | */
158 |
159 | RistrettoPoint::identity() == res
160 | }
161 |
162 | }
163 |
164 | //FIXME: the ECVRF_hash_to_curve1 looks like a hash and pray, but since
165 | // curve25519-dalek already has a hash to curve function, we can reuse it instead?
166 | pub fn ECVRF_hash_to_curve(point: RistrettoPoint, data: &[u8]) -> RistrettoPoint {
167 | let h = Sha512::new()
168 | .chain(point.compress().as_bytes())
169 | .chain(data);
170 |
171 | RistrettoPoint::from_hash(h)
172 | }
173 |
174 | //FIXME: is the output value in the right set?
175 | pub fn ECVRF_hash_points(points: &[RistrettoPoint]) -> Scalar {
176 | let mut h = Sha512::new();
177 | for point in points.iter() {
178 | h.input(point.compress().as_bytes());
179 | }
180 |
181 | Scalar::from_hash(h)
182 | }
183 |
184 | pub fn hash_message(point: RistrettoPoint, data: &[u8]) -> Scalar {
185 | let h = Sha512::new()
186 | .chain(point.compress().as_bytes())
187 | .chain(data);
188 |
189 | Scalar::from_hash(h)
190 | }
191 |
192 |
193 | pub fn add_points(points: &[RistrettoPoint]) -> RistrettoPoint {
194 | assert!(points.len() > 0);
195 |
196 | if points.len() == 1 {
197 | points[0]
198 | } else {
199 | let mut it = points.iter();
200 | let first = it.next().unwrap();
201 | it.fold(*first, |acc, pk| acc + pk)
202 | }
203 | }
204 |
205 | pub fn ECVRF_nonce(sk: Scalar, point: RistrettoPoint) -> Scalar {
206 | let k = [0u8; 64];
207 | let v = [1u8; 64];
208 |
209 | let mut mac = HmacSha512::new_varkey(&k[..]).unwrap();
210 | mac.input(&v[..]);
211 | mac.input(&[0]);
212 | mac.input(&sk.as_bytes()[..]);
213 | mac.input(point.compress().as_bytes());
214 |
215 | let k = mac.result().code();
216 |
217 | let mut mac = HmacSha512::new_varkey(&k[..]).unwrap();
218 | mac.input(&v[..]);
219 | mac.input(&[1]);
220 | mac.input(&sk.as_bytes()[..]);
221 | mac.input(point.compress().as_bytes());
222 |
223 | let k = mac.result().code();
224 |
225 | // the process in RFC 6979 is a bit ore complex than that
226 | let mut h = Sha512::new();
227 | h.input(k);
228 |
229 | Scalar::from_hash(h)
230 | }
231 |
232 | #[cfg(test)]
233 | mod tests {
234 | use super::*;
235 |
236 | #[test]
237 | fn basic_signature() {
238 | let mut rng: StdRng = SeedableRng::seed_from_u64(0);
239 |
240 | let message = b"hello world";
241 | let keypair = KeyPair::new(&mut rng);
242 |
243 | let signature = keypair.sign(&mut rng, message);
244 |
245 | assert!(verify(&keypair.public, message, &signature));
246 |
247 | assert!(!verify(&keypair.public, b"AAAA", &signature));
248 |
249 | }
250 |
251 | #[test]
252 | fn three_messages() {
253 | //let mut rng: OsRng = OsRng::new().unwrap();
254 | //keep the same values in tests
255 | let mut rng: StdRng = SeedableRng::seed_from_u64(0);
256 |
257 | let message1 = b"hello";
258 | let keypair1 = KeyPair::new(&mut rng);
259 |
260 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
261 |
262 | assert!(token1.verify(), "cannot verify first token");
263 |
264 | println!("will derive a second token");
265 |
266 | let message2 = b"world";
267 | let keypair2 = KeyPair::new(&mut rng);
268 |
269 | let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
270 |
271 | assert!(token2.verify(), "cannot verify second token");
272 |
273 | println!("will derive a third token");
274 |
275 | let message3 = b"!!!";
276 | let keypair3 = KeyPair::new(&mut rng);
277 |
278 | let token3 = token2.append(&mut rng, &keypair3, &message3[..]);
279 |
280 | assert!(token3.verify(), "cannot verify third token");
281 | }
282 |
283 | #[test]
284 | fn change_message() {
285 | //let mut rng: OsRng = OsRng::new().unwrap();
286 | //keep the same values in tests
287 | let mut rng: StdRng = SeedableRng::seed_from_u64(0);
288 |
289 | let message1 = b"hello";
290 | let keypair1 = KeyPair::new(&mut rng);
291 |
292 | let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
293 |
294 | assert!(token1.verify(), "cannot verify first token");
295 |
296 | println!("will derive a second token");
297 |
298 | let message2 = b"world";
299 | let keypair2 = KeyPair::new(&mut rng);
300 |
301 | let mut token2 = token1.append(&mut rng, &keypair2, &message2[..]);
302 |
303 | token2.messages[1] = Vec::from(&b"you"[..]);
304 |
305 | assert!(!token2.verify(), "second token should not be valid");
306 |
307 | println!("will derive a third token");
308 |
309 | let message3 = b"!!!";
310 | let keypair3 = KeyPair::new(&mut rng);
311 |
312 | let token3 = token2.append(&mut rng, &keypair3, &message3[..]);
313 |
314 | assert!(!token3.verify(), "cannot verify third token");
315 | }
316 | }
317 |
--------------------------------------------------------------------------------
/experimentations/pairing/bls/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "bls"
3 | version = "0.1.0"
4 | authors = ["Geoffroy Couprie "]
5 |
6 | [dependencies]
7 | pairing = "^0.14"
8 | rand = "*"
9 |
--------------------------------------------------------------------------------
/experimentations/pairing/bls/README.md:
--------------------------------------------------------------------------------
1 | # example signature aggregation using BLS pairings with the Rust pairing crate
2 |
3 | pairing: https://github.com/zkcrypto/pairing
4 |
--------------------------------------------------------------------------------
/experimentations/pairing/bls/benches/lib.rs:
--------------------------------------------------------------------------------
1 | #![feature(test)]
2 | extern crate test;
3 |
4 | extern crate pairing;
5 | extern crate rand;
6 | extern crate bls;
7 |
8 | use rand::{Rand, SeedableRng, XorShiftRng};
9 | use pairing::{CurveAffine, CurveProjective, Engine, Field, PrimeField};
10 | use pairing::bls12_381::Bls12;
11 | use test::Bencher;
12 |
13 | type E = Bls12;
14 |
15 | #[test]
16 | fn blocksign() {
17 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
18 |
19 | // since G1 and G2 are groups of prime order, any element can be a generator
20 | let g1 = ::G1::rand(&mut rng);
21 | let g2 = ::G2::rand(&mut rng);
22 |
23 | // verify that they are not trivial elements
24 | assert_ne!(g1, ::G1::zero());
25 | assert_ne!(g1, ::G1::one());
26 | assert_ne!(g2, ::G2::zero());
27 | assert_ne!(g2, ::G2::one());
28 |
29 | // let's generate the private keys from the scalar field
30 | let k1 = ::Fr::rand(&mut rng);
31 | let k2 = ::Fr::rand(&mut rng);
32 |
33 | // let's generate the public keys in G1
34 | let mut p1 = g1;
35 | p1.mul_assign(k1);
36 | let mut p2 = g1;
37 | p2.mul_assign(k2);
38 |
39 | // let's assume h1 and h2 are respectively the hashes of block 1 and block 2
40 | let h1 = ::G2::rand(&mut rng);
41 | let h2 = ::G2::rand(&mut rng);
42 |
43 | // calculate the signature for the first block
44 | let mut s1 = h1;
45 | s1.mul_assign(k1);
46 |
47 | // let's verify the first signature
48 | // to verify, we need the following information:
49 | // * h1 (we will be able to recalculate it from the message)
50 | // * the public key p1
51 | // * s1 (of course)
52 | let verif1 = ::pairing(g1, s1);
53 | let verif2 = ::pairing(p1, h1);
54 |
55 | assert_eq!(verif1, verif2);
56 |
57 | // calculate the signature for the second block
58 | let mut s2 = h2;
59 | s2.mul_assign(k2);
60 |
61 | // calculate the aggregated signature
62 | let mut agg_sig = s1;
63 | agg_sig.add_assign(&s2);
64 |
65 | // let's verify the second signature
66 | // to verify, we need the following information:
67 | // * h1 (we will be able to recalculate it from the message)
68 | // * h2 (we will be able to recalculate it from the message)
69 | // * the public key p1
70 | // * the public key p2
71 | // * agg_sig
72 | let verif3 = ::pairing(g1, agg_sig);
73 | let mut verif4 = ::pairing(p1, h1);
74 | verif4.mul_assign(&::pairing(p2, h2));
75 |
76 | assert_eq!(verif3, verif4);
77 | }
78 |
79 | mod bench {
80 | use super::*;
81 | use test::Bencher;
82 |
83 | #[bench]
84 | fn sign_one_block(b: &mut Bencher) {
85 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
86 |
87 | // since G1 and G2 are groups of prime order, any element can be a generator
88 | let g1 = ::G1::rand(&mut rng);
89 | let g2 = ::G2::rand(&mut rng);
90 |
91 | // verify that they are not trivial elements
92 | assert_ne!(g1, ::G1::zero());
93 | assert_ne!(g1, ::G1::one());
94 | assert_ne!(g2, ::G2::zero());
95 | assert_ne!(g2, ::G2::one());
96 |
97 | let k1 = ::Fr::rand(&mut rng);
98 |
99 | let mut p1 = g1;
100 | p1.mul_assign(k1);
101 |
102 | let h1 = ::G2::rand(&mut rng);
103 |
104 | b.iter(||{
105 | let mut s1 = h1;
106 | s1.mul_assign(k1);
107 | });
108 | }
109 |
110 | #[bench]
111 | fn verify_one_block(b: &mut Bencher) {
112 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
113 |
114 | // since G1 and G2 are groups of prime order, any element can be a generator
115 | let g1 = ::G1::rand(&mut rng);
116 | let g2 = ::G2::rand(&mut rng);
117 |
118 | // verify that they are not trivial elements
119 | assert_ne!(g1, ::G1::zero());
120 | assert_ne!(g1, ::G1::one());
121 | assert_ne!(g2, ::G2::zero());
122 | assert_ne!(g2, ::G2::one());
123 |
124 | let k1 = ::Fr::rand(&mut rng);
125 |
126 | let mut p1 = g1;
127 | p1.mul_assign(k1);
128 |
129 | let h1 = ::G2::rand(&mut rng);
130 |
131 | let mut s1 = h1;
132 | s1.mul_assign(k1);
133 |
134 | b.iter(||{
135 | let verif1 = ::pairing(g1, s1);
136 | let verif2 = ::pairing(p1, h1);
137 | assert_eq!(verif1, verif2);
138 | });
139 | }
140 |
141 | #[bench]
142 | fn sign_two_blocks(b: &mut Bencher) {
143 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
144 |
145 | // since G1 and G2 are groups of prime order, any element can be a generator
146 | let g1 = ::G1::rand(&mut rng);
147 | let g2 = ::G2::rand(&mut rng);
148 |
149 | // verify that they are not trivial elements
150 | assert_ne!(g1, ::G1::zero());
151 | assert_ne!(g1, ::G1::one());
152 | assert_ne!(g2, ::G2::zero());
153 | assert_ne!(g2, ::G2::one());
154 |
155 | // let's generate the private keys from the scalar field
156 | let k1 = ::Fr::rand(&mut rng);
157 | let k2 = ::Fr::rand(&mut rng);
158 |
159 | // let's generate the public keys in G1
160 | let mut p1 = g1;
161 | p1.mul_assign(k1);
162 | let mut p2 = g1;
163 | p2.mul_assign(k2);
164 |
165 | // let's assume h1 and h2 are respectively the hashes of block 1 and block 2
166 | let h1 = ::G2::rand(&mut rng);
167 | let h2 = ::G2::rand(&mut rng);
168 |
169 | // calculate the signature for the first block
170 | let mut s1 = h1;
171 | s1.mul_assign(k1);
172 |
173 | b.iter(||{
174 | // calculate the signature for the second block
175 | let mut s2 = h2;
176 | s2.mul_assign(k2);
177 |
178 | // calculate the aggregated signature
179 | let mut agg_sig = s1;
180 | agg_sig.add_assign(&s2);
181 | });
182 | }
183 |
184 | #[bench]
185 | fn verify_two_blocks(b: &mut Bencher) {
186 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
187 |
188 | let g1 = ::G1::rand(&mut rng);
189 | let g2 = ::G2::rand(&mut rng);
190 |
191 | assert_ne!(g1, ::G1::zero());
192 | assert_ne!(g1, ::G1::one());
193 | assert_ne!(g2, ::G2::zero());
194 | assert_ne!(g2, ::G2::one());
195 |
196 | let k1 = ::Fr::rand(&mut rng);
197 | let k2 = ::Fr::rand(&mut rng);
198 |
199 | let mut p1 = g1;
200 | p1.mul_assign(k1);
201 | let mut p2 = g1;
202 | p2.mul_assign(k2);
203 |
204 | let h1 = ::G2::rand(&mut rng);
205 | let h2 = ::G2::rand(&mut rng);
206 |
207 | let mut s1 = h1;
208 | s1.mul_assign(k1);
209 |
210 | let verif1 = ::pairing(g1, s1);
211 | let verif2 = ::pairing(p1, h1);
212 |
213 | assert_eq!(verif1, verif2);
214 |
215 | let mut s2 = h2;
216 | s2.mul_assign(k2);
217 |
218 | let mut agg_sig = s1;
219 | agg_sig.add_assign(&s2);
220 |
221 | b.iter(||{
222 | let verif3 = ::pairing(g1, agg_sig);
223 | let mut verif4 = ::pairing(p1, h1);
224 | verif4.mul_assign(&::pairing(p2, h2));
225 |
226 | assert_eq!(verif3, verif4);
227 | });
228 | }
229 |
230 | #[bench]
231 | fn verify_two_blocks_cache_first_pairing(b: &mut Bencher) {
232 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
233 |
234 | let g1 = ::G1::rand(&mut rng);
235 | let g2 = ::G2::rand(&mut rng);
236 |
237 | assert_ne!(g1, ::G1::zero());
238 | assert_ne!(g1, ::G1::one());
239 | assert_ne!(g2, ::G2::zero());
240 | assert_ne!(g2, ::G2::one());
241 |
242 | let k1 = ::Fr::rand(&mut rng);
243 | let k2 = ::Fr::rand(&mut rng);
244 |
245 | let mut p1 = g1;
246 | p1.mul_assign(k1);
247 | let mut p2 = g1;
248 | p2.mul_assign(k2);
249 |
250 | let h1 = ::G2::rand(&mut rng);
251 | let h2 = ::G2::rand(&mut rng);
252 |
253 | let mut s1 = h1;
254 | s1.mul_assign(k1);
255 |
256 | let verif1 = ::pairing(g1, s1);
257 | let verif2 = ::pairing(p1, h1);
258 |
259 | assert_eq!(verif1, verif2);
260 |
261 | let mut s2 = h2;
262 | s2.mul_assign(k2);
263 |
264 | let mut agg_sig = s1;
265 | agg_sig.add_assign(&s2);
266 |
267 | let cached = ::pairing(p1, h1);
268 | b.iter(||{
269 | let verif3 = ::pairing(g1, agg_sig);
270 | let mut verif4 = cached;
271 | verif4.mul_assign(&::pairing(p2, h2));
272 |
273 | assert_eq!(verif3, verif4);
274 | });
275 | }
276 |
277 | #[bench]
278 | fn verify_three_blocks(b: &mut Bencher) {
279 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
280 |
281 | let g1 = ::G1::rand(&mut rng);
282 | let g2 = ::G2::rand(&mut rng);
283 |
284 | assert_ne!(g1, ::G1::zero());
285 | assert_ne!(g1, ::G1::one());
286 | assert_ne!(g2, ::G2::zero());
287 | assert_ne!(g2, ::G2::one());
288 |
289 | let k1 = ::Fr::rand(&mut rng);
290 | let k2 = ::Fr::rand(&mut rng);
291 | let k3 = ::Fr::rand(&mut rng);
292 |
293 | let mut p1 = g1;
294 | p1.mul_assign(k1);
295 | let mut p2 = g1;
296 | p2.mul_assign(k2);
297 | let mut p3 = g1;
298 | p3.mul_assign(k3);
299 |
300 | let h1 = ::G2::rand(&mut rng);
301 | let h2 = ::G2::rand(&mut rng);
302 | let h3 = ::G2::rand(&mut rng);
303 |
304 | let mut s1 = h1;
305 | s1.mul_assign(k1);
306 |
307 | let verif1 = ::pairing(g1, s1);
308 | let verif2 = ::pairing(p1, h1);
309 |
310 | assert_eq!(verif1, verif2);
311 |
312 | let mut s2 = h2;
313 | s2.mul_assign(k2);
314 |
315 | let mut s3 = h3;
316 | s3.mul_assign(k3);
317 |
318 | let mut agg_sig = s1;
319 | agg_sig.add_assign(&s2);
320 | agg_sig.add_assign(&s3);
321 |
322 | b.iter(||{
323 | let verif3 = ::pairing(g1, agg_sig);
324 | let mut verif4 = ::pairing(p1, h1);
325 | verif4.mul_assign(&::pairing(p2, h2));
326 | verif4.mul_assign(&::pairing(p3, h3));
327 |
328 | assert_eq!(verif3, verif4);
329 | });
330 | }
331 |
332 | #[bench]
333 | fn verify_three_blocks_cache_first_pairing(b: &mut Bencher) {
334 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
335 |
336 | let g1 = ::G1::rand(&mut rng);
337 | let g2 = ::G2::rand(&mut rng);
338 |
339 | assert_ne!(g1, ::G1::zero());
340 | assert_ne!(g1, ::G1::one());
341 | assert_ne!(g2, ::G2::zero());
342 | assert_ne!(g2, ::G2::one());
343 |
344 | let k1 = ::Fr::rand(&mut rng);
345 | let k2 = ::Fr::rand(&mut rng);
346 | let k3 = ::Fr::rand(&mut rng);
347 |
348 | let mut p1 = g1;
349 | p1.mul_assign(k1);
350 | let mut p2 = g1;
351 | p2.mul_assign(k2);
352 | let mut p3 = g1;
353 | p3.mul_assign(k3);
354 |
355 | let h1 = ::G2::rand(&mut rng);
356 | let h2 = ::G2::rand(&mut rng);
357 | let h3 = ::G2::rand(&mut rng);
358 |
359 | let mut s1 = h1;
360 | s1.mul_assign(k1);
361 |
362 | let verif1 = ::pairing(g1, s1);
363 | let verif2 = ::pairing(p1, h1);
364 |
365 | assert_eq!(verif1, verif2);
366 |
367 | let mut s2 = h2;
368 | s2.mul_assign(k2);
369 |
370 | let mut s3 = h3;
371 | s3.mul_assign(k3);
372 |
373 | let mut agg_sig = s1;
374 | agg_sig.add_assign(&s2);
375 | agg_sig.add_assign(&s3);
376 |
377 | let cached = ::pairing(p1, h1);
378 | b.iter(||{
379 | let verif3 = ::pairing(g1, agg_sig);
380 | let mut verif4 = cached;
381 | verif4.mul_assign(&::pairing(p2, h2));
382 | verif4.mul_assign(&::pairing(p3, h3));
383 |
384 | assert_eq!(verif3, verif4);
385 | });
386 | }
387 |
388 | #[bench]
389 | fn verify_three_blocks_aggregate_keys(b: &mut Bencher) {
390 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
391 |
392 | let g1 = ::G1::rand(&mut rng);
393 | let g2 = ::G2::rand(&mut rng);
394 |
395 | assert_ne!(g1, ::G1::zero());
396 | assert_ne!(g1, ::G1::one());
397 | assert_ne!(g2, ::G2::zero());
398 | assert_ne!(g2, ::G2::one());
399 |
400 | let k1 = ::Fr::rand(&mut rng);
401 | let k2 = ::Fr::rand(&mut rng);
402 | let k3 = ::Fr::rand(&mut rng);
403 |
404 | let mut p1 = g1;
405 | p1.mul_assign(k1);
406 | let mut p2 = g1;
407 | p2.mul_assign(k2);
408 | let mut p3 = g1;
409 | p3.mul_assign(k3);
410 |
411 | let h1 = ::G2::rand(&mut rng);
412 | let h2 = ::G2::rand(&mut rng);
413 | let h3 = ::G2::rand(&mut rng);
414 |
415 | let mut s1 = h1;
416 | s1.mul_assign(k1);
417 |
418 | let verif1 = ::pairing(g1, s1);
419 | let verif2 = ::pairing(p1, h1);
420 |
421 | assert_eq!(verif1, verif2);
422 |
423 | let mut s2 = h2;
424 | s2.mul_assign(k2);
425 |
426 | let mut s3 = h3;
427 | s3.mul_assign(k3);
428 |
429 | let mut agg_sig = s1;
430 | agg_sig.add_assign(&s2);
431 | agg_sig.add_assign(&s3);
432 |
433 | let mut sum = p1;
434 | sum.add_assign(&p2);
435 | sum.add_assign(&p3);
436 | b.iter(||{
437 | let verif3 = ::pairing(g1, agg_sig);
438 | let mut verif4 = ::pairing(sum, h1);
439 | verif4.mul_assign(&::pairing(g1, h2));
440 | verif4.mul_assign(&::pairing(g1, h3));
441 |
442 | assert_eq!(verif3, verif4);
443 | });
444 | }
445 |
446 | #[bench]
447 | fn verify_three_blocks_g2(b: &mut Bencher) {
448 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
449 |
450 | let g1 = ::G1::rand(&mut rng);
451 | let g2 = ::G2::rand(&mut rng);
452 |
453 | assert_ne!(g1, ::G1::zero());
454 | assert_ne!(g1, ::G1::one());
455 | assert_ne!(g2, ::G2::zero());
456 | assert_ne!(g2, ::G2::one());
457 |
458 | let k1 = ::Fr::rand(&mut rng);
459 | let k2 = ::Fr::rand(&mut rng);
460 | let k3 = ::Fr::rand(&mut rng);
461 |
462 | let mut p1 = g2;
463 | p1.mul_assign(k1);
464 | let mut p2 = g2;
465 | p2.mul_assign(k2);
466 | let mut p3 = g2;
467 | p3.mul_assign(k3);
468 |
469 | let h1 = ::G1::rand(&mut rng);
470 | let h2 = ::G1::rand(&mut rng);
471 | let h3 = ::G1::rand(&mut rng);
472 |
473 | let mut s1 = h1;
474 | s1.mul_assign(k1);
475 |
476 | let verif1 = ::pairing(s1, g2);
477 | let verif2 = ::pairing(h1, p1);
478 |
479 | assert_eq!(verif1, verif2);
480 |
481 | let mut s2 = h2;
482 | s2.mul_assign(k2);
483 |
484 | let mut s3 = h3;
485 | s3.mul_assign(k3);
486 |
487 | let mut agg_sig = s1;
488 | agg_sig.add_assign(&s2);
489 | agg_sig.add_assign(&s3);
490 |
491 | b.iter(||{
492 | let verif3 = ::pairing(agg_sig, g2);
493 | let mut verif4 = ::pairing(h1, p1);
494 | verif4.mul_assign(&::pairing(h2, p2));
495 | verif4.mul_assign(&::pairing(h3, p3));
496 |
497 | assert_eq!(verif3, verif4);
498 | });
499 | }
500 | }
501 |
502 |
--------------------------------------------------------------------------------
/experimentations/pairing/bls/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![cfg_attr(feature = "unstable", feature(test))]
2 | #[cfg(all(feature = "unstable", test))]
3 | extern crate test;
4 | extern crate pairing;
5 | extern crate rand;
6 |
7 | use rand::{Rand, SeedableRng, XorShiftRng};
8 | use pairing::{CurveAffine, CurveProjective, Engine, Field, PrimeField};
9 | use pairing::bls12_381::Bls12;
10 |
11 | type E = Bls12;
12 |
13 | #[test]
14 | fn blocksign() {
15 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
16 |
17 | // since G1 and G2 are groups of prime order, any element can be a generator
18 | let g1 = ::G1::one();
19 | let g2 = ::G2::one();
20 |
21 | // verify that they are not trivial elements
22 | /*assert_ne!(g1, ::G1::zero());
23 | assert_ne!(g1, ::G1::one());
24 | assert_ne!(g2, ::G2::zero());
25 | assert_ne!(g2, ::G2::one());
26 | */
27 |
28 | // let's generate the private keys from the scalar field
29 | let k1 = ::Fr::rand(&mut rng);
30 | let k2 = ::Fr::rand(&mut rng);
31 |
32 | // let's generate the public keys in G1
33 | let mut p1 = g1;
34 | p1.mul_assign(k1);
35 | let mut p2 = g1;
36 | p2.mul_assign(k2);
37 |
38 | // let's assume h1 and h2 are respectively the hashes of block 1 and block 2
39 | let h1 = ::G2::rand(&mut rng);
40 | let h2 = ::G2::rand(&mut rng);
41 |
42 | // calculate the signature for the first block
43 | let mut s1 = h1;
44 | s1.mul_assign(k1);
45 |
46 | // let's verify the first signature
47 | // to verify, we need the following information:
48 | // * h1 (we will be able to recalculate it from the message)
49 | // * the public key p1
50 | // * s1 (of course)
51 | let verif1 = ::pairing(g1, s1);
52 | let verif2 = ::pairing(p1, h1);
53 |
54 | assert_eq!(verif1, verif2);
55 |
56 | // calculate the signature for the second block
57 | let mut s2 = h2;
58 | s2.mul_assign(k2);
59 |
60 | // calculate the aggregated signature
61 | let mut agg_sig = s1;
62 | agg_sig.add_assign(&s2);
63 |
64 | // let's verify the second signature
65 | // to verify, we need the following information:
66 | // * h1 (we will be able to recalculate it from the message)
67 | // * h2 (we will be able to recalculate it from the message)
68 | // * the public key p1
69 | // * the public key p2
70 | // * agg_sig
71 | let verif3 = ::pairing(g1, agg_sig);
72 | let mut verif4 = ::pairing(p1, h1);
73 | verif4.mul_assign(&::pairing(p2, h2));
74 |
75 | assert_eq!(verif3, verif4);
76 | }
77 |
78 | #[cfg(all(feature = "unstable", test))]
79 | mod bench {
80 | use super::*;
81 | use test::Bencher;
82 |
83 | #[bench]
84 | fn sign_one_block(b: &mut Bencher) {
85 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
86 |
87 | // since G1 and G2 are groups of prime order, any element can be a generator
88 | let g1 = ::G1::rand(&mut rng);
89 | let g2 = ::G2::rand(&mut rng);
90 |
91 | // verify that they are not trivial elements
92 | assert_ne!(g1, ::G1::zero());
93 | assert_ne!(g1, ::G1::one());
94 | assert_ne!(g2, ::G2::zero());
95 | assert_ne!(g2, ::G2::one());
96 |
97 | let k1 = ::Fr::rand(&mut rng);
98 |
99 | let mut p1 = g1;
100 | p1.mul_assign(k1);
101 |
102 | let h1 = ::G2::rand(&mut rng);
103 |
104 | b.iter(||{
105 | let mut s1 = h1;
106 | s1.mul_assign(k1);
107 | });
108 | }
109 |
110 | #[bench]
111 | fn verify_one_block(b: &mut Bencher) {
112 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
113 |
114 | // since G1 and G2 are groups of prime order, any element can be a generator
115 | let g1 = ::G1::rand(&mut rng);
116 | let g2 = ::G2::rand(&mut rng);
117 |
118 | // verify that they are not trivial elements
119 | assert_ne!(g1, ::G1::zero());
120 | assert_ne!(g1, ::G1::one());
121 | assert_ne!(g2, ::G2::zero());
122 | assert_ne!(g2, ::G2::one());
123 |
124 | let k1 = ::Fr::rand(&mut rng);
125 |
126 | let mut p1 = g1;
127 | p1.mul_assign(k1);
128 |
129 | let h1 = ::G2::rand(&mut rng);
130 |
131 | let mut s1 = h1;
132 | s1.mul_assign(k1);
133 |
134 | b.iter(||{
135 | let verif1 = ::pairing(g1, s1);
136 | let verif2 = ::pairing(p1, h1);
137 | assert_eq!(verif1, verif2);
138 | });
139 | }
140 |
141 | #[bench]
142 | fn sign_two_blocks(b: &mut Bencher) {
143 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
144 |
145 | // since G1 and G2 are groups of prime order, any element can be a generator
146 | let g1 = ::G1::rand(&mut rng);
147 | let g2 = ::G2::rand(&mut rng);
148 |
149 | // verify that they are not trivial elements
150 | assert_ne!(g1, ::G1::zero());
151 | assert_ne!(g1, ::G1::one());
152 | assert_ne!(g2, ::G2::zero());
153 | assert_ne!(g2, ::G2::one());
154 |
155 | // let's generate the private keys from the scalar field
156 | let k1 = ::Fr::rand(&mut rng);
157 | let k2 = ::Fr::rand(&mut rng);
158 |
159 | // let's generate the public keys in G1
160 | let mut p1 = g1;
161 | p1.mul_assign(k1);
162 | let mut p2 = g1;
163 | p2.mul_assign(k2);
164 |
165 | // let's assume h1 and h2 are respectively the hashes of block 1 and block 2
166 | let h1 = ::G2::rand(&mut rng);
167 | let h2 = ::G2::rand(&mut rng);
168 |
169 | // calculate the signature for the first block
170 | let mut s1 = h1;
171 | s1.mul_assign(k1);
172 |
173 | b.iter(||{
174 | // calculate the signature for the second block
175 | let mut s2 = h2;
176 | s2.mul_assign(k2);
177 |
178 | // calculate the aggregated signature
179 | let mut agg_sig = s1;
180 | agg_sig.add_assign(&s2);
181 | });
182 | }
183 |
184 | #[bench]
185 | fn verify_two_blocks(b: &mut Bencher) {
186 | let mut rng = XorShiftRng::from_seed([0x12345678, 0x12345678, 0x12345678, 0x12345678]);
187 |
188 | let g1 = ::G1::rand(&mut rng);
189 | let g2 = ::G2::rand(&mut rng);
190 |
191 | assert_ne!(g1, ::G1::zero());
192 | assert_ne!(g1,