├── 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, ::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 | -------------------------------------------------------------------------------- /experimentations/pairing/mcl/README.md: -------------------------------------------------------------------------------- 1 | # example signature aggregation using BLS pairings with the mcl library 2 | 3 | mcl: https://github.com/herumi/mcl 4 | -------------------------------------------------------------------------------- /experimentations/pairing/mcl/aggregated.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | @brief a sample of BLS signature 4 | see https://github.com/herumi/bls 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | 9 | */ 10 | #include 11 | //#include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | using namespace mcl::bn256; 19 | //using namespace mcl::bls12; 20 | using namespace std::chrono; 21 | 22 | void Hash(G1& P, const std::string& m) 23 | { 24 | Fp t; 25 | t.setHashOf(m); 26 | mapToG1(P, t); 27 | } 28 | 29 | void KeyGen(Fr& s, G2& pub, const G2& Q) 30 | { 31 | s.setRand(); 32 | G2::mul(pub, Q, s); // pub = sQ 33 | } 34 | 35 | void Sign(G1& sign, const Fr& s, const std::string& m) 36 | { 37 | G1 Hm; 38 | Hash(Hm, m); 39 | G1::mul(sign, Hm, s); // sign = s H(m) 40 | } 41 | 42 | bool Verify(const G1& sign, const G2& Q, const G2& pub, const std::string& m) 43 | { 44 | Fp12 e1, e2; 45 | G1 Hm; 46 | Hash(Hm, m); 47 | pairing(e1, sign, Q); // e1 = e(sign, Q) 48 | pairing(e2, Hm, pub); // e2 = e(Hm, sQ) 49 | return e1 == e2; 50 | } 51 | 52 | void Aggregate(G1& agg, const G1& sign1, const G1&sign2) { 53 | G1::add(agg, sign1, sign2); 54 | } 55 | 56 | bool VerifyAggregate(const G1& aggregated_sig, const G2& Q, const G2& pub1, const G2& pub2, const std::string& m1, const std::string& m2) { 57 | Fp12 e0, e1, e2, e3; 58 | G1 h1, h2; 59 | Hash(h1, m1); 60 | Hash(h2, m2); 61 | 62 | pairing(e0, aggregated_sig, Q); 63 | pairing(e1, h1, pub1); 64 | pairing(e2, h2, pub2); 65 | Fp12::mul(e3, e1, e2); 66 | 67 | return e0 == e3; 68 | } 69 | 70 | bool VerifyAggregate3(const G1& aggregated_sig, const G2& Q, 71 | const G2& pub1, const G2& pub2, const G2& pub3, 72 | const std::string& m1, const std::string& m2, const std::string& m3) { 73 | 74 | Fp12 e0, e1, e2, e3, e4, e5; 75 | G1 h1, h2, h3; 76 | Hash(h1, m1); 77 | Hash(h2, m2); 78 | Hash(h3, m3); 79 | 80 | pairing(e0, aggregated_sig, Q); 81 | pairing(e1, h1, pub1); 82 | pairing(e2, h2, pub2); 83 | pairing(e3, h3, pub3); 84 | 85 | Fp12::mul(e4, e1, e2); 86 | Fp12::mul(e5, e4, e3); 87 | 88 | return e0 == e5; 89 | } 90 | 91 | int main(int argc, char *argv[]) 92 | { 93 | //std::string m = argc == 1 ? "hello mcl" : argv[1]; 94 | std::string m1 = "authentication test caveat 1"; 95 | std::string m2 = "authentication test caveat 2"; 96 | 97 | // setup parameter 98 | initPairing(); 99 | G2 Q; 100 | mapToG2(Q, 1); 101 | 102 | // generate secret key and public key 103 | Fr s1, s2; 104 | G2 pub1, pub2; 105 | KeyGen(s1, pub1, Q); 106 | std::cout << "secret key 1: " << s1 << std::endl; 107 | std::cout << "public key 1: " << pub1 << std::endl; 108 | KeyGen(s2, pub2, Q); 109 | std::cout << "secret key 2: " << s2 << std::endl; 110 | std::cout << "public key 2: " << pub2 << std::endl; 111 | 112 | G1 sign_bench; 113 | CYBOZU_BENCH("sign one", Sign, sign_bench, s1, m1); 114 | 115 | // sign 116 | G1 sign1, sign2; 117 | auto before_sign = high_resolution_clock::now(); 118 | Sign(sign1, s1, m1); 119 | auto after_sign = high_resolution_clock::now(); 120 | std::cout << "msg1 " << m1 << std::endl; 121 | std::cout << "sign1 " << sign1 << std::endl; 122 | Sign(sign2, s2, m2); 123 | std::cout << "msg2 " << m2 << std::endl; 124 | std::cout << "sign2 " << sign2 << std::endl; 125 | 126 | CYBOZU_BENCH("verify one", Verify, sign1, Q, pub1, m1); 127 | auto before_verify_one = high_resolution_clock::now(); 128 | bool b = Verify(sign1, Q, pub1, m1); 129 | auto after_verify_one = high_resolution_clock::now(); 130 | 131 | if(b) { 132 | std::cout << "verify one succeeded" << std::endl; 133 | } else { 134 | std::cout << "verify one failed" << std::endl; 135 | } 136 | 137 | G1 agg; 138 | CYBOZU_BENCH("aggregate two", Aggregate, agg, sign1, sign2); 139 | G1 agg_bench; 140 | auto before_aggregate_two = high_resolution_clock::now(); 141 | Aggregate(agg_bench, sign1, sign2); 142 | auto after_aggregate_two = high_resolution_clock::now(); 143 | 144 | auto before_verify_aggregate = high_resolution_clock::now(); 145 | bool b2 = VerifyAggregate(agg, Q, pub1, pub2, m1, m2); 146 | auto after_verify_aggregate = high_resolution_clock::now(); 147 | 148 | if(b2) { 149 | std::cout << "verify aggregate succeeded" << std::endl; 150 | } else { 151 | std::cout << "verify aggregate failed" << std::endl; 152 | } 153 | 154 | CYBOZU_BENCH("verify aggregate", VerifyAggregate, agg, Q, pub1, pub2, m1, m2); 155 | 156 | Fr s3; 157 | G2 pub3; 158 | KeyGen(s3, pub3, Q); 159 | G1 sign3; 160 | std::string m3 = "authentication test caveat 3"; 161 | Sign(sign3, s3, m3); 162 | G1 agg3; 163 | Aggregate(agg3, agg, sign3); 164 | auto before_verify_aggregate_three = high_resolution_clock::now(); 165 | bool b3 = VerifyAggregate3(agg3, Q, pub1, pub2, pub3, m1, m2, m3); 166 | auto after_verify_aggregate_three = high_resolution_clock::now(); 167 | 168 | 169 | std::cout << "serialized pub1: " << pub1.getStr(2048) << std::endl; 170 | std::cout << "serialized sig: " << agg3.getStr(2048) << std::endl; 171 | 172 | if(b3) { 173 | std::cout << "verify aggregate 3 succeeded" << std::endl; 174 | } else { 175 | std::cout << "verify aggregate 3 failed" << std::endl; 176 | } 177 | 178 | duration sign_dur = after_sign - before_sign; 179 | duration verify_one_dur = after_verify_one - before_verify_one; 180 | duration aggregate_two_dur = after_aggregate_two - before_aggregate_two; 181 | duration verify_aggregate_dur = after_verify_aggregate - before_verify_aggregate; 182 | duration verify_aggregate_three_dur = after_verify_aggregate_three - before_verify_aggregate_three; 183 | 184 | std::cout << "time measurements:" << std::endl 185 | << "sign:\t\t" << sign_dur.count() << std::endl 186 | << "verify:\t\t" << verify_one_dur.count() << std::endl 187 | << "aggregate:\t" << aggregate_two_dur.count() << std::endl 188 | << "verify_aggregate 2:\t" << verify_aggregate_dur.count() << std::endl 189 | << "verify_aggregate 3:\t" << verify_aggregate_three_dur.count() << std::endl; 190 | } 191 | -------------------------------------------------------------------------------- /experimentations/vrf/biscuit-vrf/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /experimentations/vrf/biscuit-vrf/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "biscuit-vrf" 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/vrf/biscuit-vrf/benches/first.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | extern crate test; 3 | 4 | extern crate biscuit_vrf; 5 | extern crate rand; 6 | 7 | use rand::rngs::OsRng; 8 | use biscuit_vrf::{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(&keypair1, &message1[..]); 22 | 23 | assert!(token1.verify(), "cannot verify first token"); 24 | 25 | b.iter(||{ 26 | Token::new(&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(&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(&keypair2, &message2[..]); 47 | 48 | assert!(token2.verify(), "cannot verify second token"); 49 | 50 | b.iter(||{ 51 | token1.append(&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(&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(&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(&keypair3, &message3[..]); 81 | 82 | assert!(token3.verify(), "cannot verify third token"); 83 | 84 | b.iter(||{ 85 | token2.append(&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(&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(&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(&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(&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(&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(&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/vrf/biscuit-vrf/benches/second.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | extern crate test; 3 | 4 | extern crate biscuit_vrf; 5 | extern crate rand; 6 | 7 | use rand::rngs::OsRng; 8 | use biscuit_vrf::second::{KeyPair, Token}; 9 | use test::Bencher; 10 | 11 | mod bench { 12 | use super::*; 13 | use test::Bencher; 14 | 15 | #[bench] 16 | fn sign_first_block(b: &mut Bencher) { 17 | let mut rng: OsRng = OsRng::new().unwrap(); 18 | 19 | let message1 = b"hello"; 20 | let keypair1 = KeyPair::new(&mut rng); 21 | 22 | let token1 = Token::new(&keypair1, &message1[..]); 23 | 24 | assert!(token1.verify(), "cannot verify first token"); 25 | 26 | b.iter(||{ 27 | Token::new(&keypair1, &message1[..]) 28 | }); 29 | } 30 | 31 | #[bench] 32 | fn sign_second_block(b: &mut Bencher) { 33 | let mut rng: OsRng = OsRng::new().unwrap(); 34 | 35 | let message1 = b"hello"; 36 | let keypair1 = KeyPair::new(&mut rng); 37 | 38 | let token1 = Token::new(&keypair1, &message1[..]); 39 | 40 | assert!(token1.verify(), "cannot verify first token"); 41 | 42 | println!("will derive a second token"); 43 | 44 | let message2 = b"world"; 45 | let keypair2 = KeyPair::new(&mut rng); 46 | 47 | let token2 = token1.append(&keypair2, &message2[..]); 48 | 49 | assert!(token2.verify(), "cannot verify second token"); 50 | 51 | b.iter(||{ 52 | token1.append(&keypair2, &message2[..]) 53 | }); 54 | } 55 | 56 | #[bench] 57 | fn sign_third_block(b: &mut Bencher) { 58 | let mut rng: OsRng = OsRng::new().unwrap(); 59 | 60 | let message1 = b"hello"; 61 | let keypair1 = KeyPair::new(&mut rng); 62 | 63 | let token1 = Token::new(&keypair1, &message1[..]); 64 | 65 | assert!(token1.verify(), "cannot verify first token"); 66 | 67 | println!("will derive a second token"); 68 | 69 | let message2 = b"world"; 70 | let keypair2 = KeyPair::new(&mut rng); 71 | 72 | let token2 = token1.append(&keypair2, &message2[..]); 73 | 74 | assert!(token2.verify(), "cannot verify second token"); 75 | 76 | println!("will derive a third token"); 77 | 78 | let message3 = b"!!!"; 79 | let keypair3 = KeyPair::new(&mut rng); 80 | 81 | let token3 = token2.append(&keypair3, &message3[..]); 82 | 83 | assert!(token3.verify(), "cannot verify third token"); 84 | 85 | b.iter(||{ 86 | token2.append(&keypair3, &message3[..]) 87 | }); 88 | } 89 | 90 | #[bench] 91 | fn verify_one_block(b: &mut Bencher) { 92 | let mut rng: OsRng = OsRng::new().unwrap(); 93 | 94 | let message1 = b"hello"; 95 | let keypair1 = KeyPair::new(&mut rng); 96 | 97 | let token1 = Token::new(&keypair1, &message1[..]); 98 | 99 | assert!(token1.verify(), "cannot verify first token"); 100 | 101 | b.iter(||{ 102 | token1.verify() 103 | }); 104 | } 105 | 106 | #[bench] 107 | fn verify_two_blocks(b: &mut Bencher) { 108 | let mut rng: OsRng = OsRng::new().unwrap(); 109 | 110 | let message1 = b"hello"; 111 | let keypair1 = KeyPair::new(&mut rng); 112 | 113 | let token1 = Token::new(&keypair1, &message1[..]); 114 | 115 | assert!(token1.verify(), "cannot verify first token"); 116 | 117 | println!("will derive a second token"); 118 | 119 | let message2 = b"world"; 120 | let keypair2 = KeyPair::new(&mut rng); 121 | 122 | let token2 = token1.append(&keypair2, &message2[..]); 123 | 124 | assert!(token2.verify(), "cannot verify second token"); 125 | 126 | b.iter(||{ 127 | token2.verify() 128 | }); 129 | } 130 | 131 | #[bench] 132 | fn verify_three_blocks(b: &mut Bencher) { 133 | let mut rng: OsRng = OsRng::new().unwrap(); 134 | 135 | let message1 = b"hello"; 136 | let keypair1 = KeyPair::new(&mut rng); 137 | 138 | let token1 = Token::new(&keypair1, &message1[..]); 139 | 140 | assert!(token1.verify(), "cannot verify first token"); 141 | 142 | println!("will derive a second token"); 143 | 144 | let message2 = b"world"; 145 | let keypair2 = KeyPair::new(&mut rng); 146 | 147 | let token2 = token1.append(&keypair2, &message2[..]); 148 | 149 | assert!(token2.verify(), "cannot verify second token"); 150 | 151 | println!("will derive a third token"); 152 | 153 | let message3 = b"!!!"; 154 | let keypair3 = KeyPair::new(&mut rng); 155 | 156 | let token3 = token2.append(&keypair3, &message3[..]); 157 | 158 | assert!(token3.verify(), "cannot verify third token"); 159 | 160 | b.iter(||{ 161 | token3.verify() 162 | }); 163 | } 164 | } 165 | 166 | 167 | -------------------------------------------------------------------------------- /experimentations/vrf/biscuit-vrf/results/first1.bench: -------------------------------------------------------------------------------- 1 | 2 | running 4 tests 3 | test second::tests::change_message ... ignored 4 | test second::tests::three_messages ... ignored 5 | test tests::change_message ... ignored 6 | test tests::three_messages ... ignored 7 | 8 | test result: ok. 0 passed; 0 failed; 4 ignored; 0 measured; 0 filtered out 9 | 10 | 11 | running 6 tests 12 | test bench::sign_first_block ... bench: 278,046 ns/iter (+/- 56,572) 13 | test bench::sign_second_block ... bench: 743,837 ns/iter (+/- 194,811) 14 | test bench::sign_third_block ... bench: 1,005,621 ns/iter (+/- 266,561) 15 | test bench::verify_one_block ... bench: 351,952 ns/iter (+/- 118,599) 16 | test bench::verify_three_blocks ... bench: 861,130 ns/iter (+/- 203,346) 17 | test bench::verify_two_blocks ... bench: 572,537 ns/iter (+/- 109,673) 18 | 19 | test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out 20 | 21 | -------------------------------------------------------------------------------- /experimentations/vrf/biscuit-vrf/results/first2.bench: -------------------------------------------------------------------------------- 1 | 2 | running 2 tests 3 | test tests::change_message ... ignored 4 | test tests::three_messages ... ignored 5 | 6 | test result: ok. 0 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out 7 | 8 | 9 | running 6 tests 10 | test bench::sign_first_block ... bench: 261,651 ns/iter (+/- 10,070) 11 | test bench::sign_second_block ... bench: 695,400 ns/iter (+/- 69,103) 12 | test bench::sign_third_block ... bench: 850,362 ns/iter (+/- 47,122) 13 | test bench::verify_one_block ... bench: 338,537 ns/iter (+/- 23,412) 14 | test bench::verify_three_blocks ... bench: 774,898 ns/iter (+/- 66,362) 15 | test bench::verify_two_blocks ... bench: 566,832 ns/iter (+/- 60,672) 16 | 17 | test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out 18 | 19 | -------------------------------------------------------------------------------- /experimentations/vrf/biscuit-vrf/results/second1.bench: -------------------------------------------------------------------------------- 1 | 2 | running 6 tests 3 | test bench::sign_first_block ... bench: 329,320 ns/iter (+/- 12,878) 4 | test bench::sign_second_block ... bench: 698,439 ns/iter (+/- 45,278) 5 | test bench::sign_third_block ... bench: 788,262 ns/iter (+/- 51,514) 6 | test bench::verify_one_block ... bench: 257,138 ns/iter (+/- 28,285) 7 | test bench::verify_three_blocks ... bench: 428,887 ns/iter (+/- 14,203) 8 | test bench::verify_two_blocks ... bench: 341,531 ns/iter (+/- 25,507) 9 | 10 | test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out 11 | 12 | -------------------------------------------------------------------------------- /experimentations/vrf/biscuit-vrf/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 | pub mod second; 10 | 11 | use sha2::{Digest, Sha512}; 12 | use hmac::{Hmac, Mac}; 13 | use rand::prelude::*; 14 | use serde::{Serialize, Deserialize}; 15 | use curve25519_dalek::{ 16 | constants::RISTRETTO_BASEPOINT_POINT, 17 | ristretto::{RistrettoPoint}, 18 | scalar::Scalar, 19 | traits::Identity 20 | }; 21 | use std::ops::{Deref, Neg}; 22 | 23 | type HmacSha512 = Hmac; 24 | 25 | 26 | pub struct KeyPair { 27 | private: Scalar, 28 | pub public: RistrettoPoint, 29 | } 30 | 31 | impl KeyPair { 32 | pub fn new(rng: &mut T) -> Self { 33 | let private = Scalar::random(rng); 34 | let public = private * RISTRETTO_BASEPOINT_POINT; 35 | 36 | KeyPair { private, public } 37 | } 38 | } 39 | 40 | pub struct Token { 41 | pub messages: Vec>, 42 | pub keys: Vec, 43 | pub signature: TokenSignature, 44 | } 45 | 46 | impl Token { 47 | pub fn new(keypair: &KeyPair, message: &[u8]) -> Self { 48 | let signature = TokenSignature::new(keypair, message); 49 | 50 | Token { 51 | messages: vec![message.to_owned()], 52 | keys: vec![keypair.public], 53 | signature 54 | } 55 | } 56 | 57 | pub fn append(&self, keypair: &KeyPair, message: &[u8]) -> Self { 58 | let signature = self.signature.sign(&self.keys, &self.messages, keypair, message); 59 | 60 | let mut t = Token { 61 | messages: self.messages.clone(), 62 | keys: self.keys.clone(), 63 | signature 64 | }; 65 | 66 | t.messages.push(message.to_owned()); 67 | t.keys.push(keypair.public); 68 | 69 | t 70 | } 71 | 72 | pub fn verify(&self) -> bool { 73 | self.signature.verify(&self.keys, &self.messages) 74 | } 75 | } 76 | 77 | #[derive(Clone,Debug,Serialize,Deserialize)] 78 | pub struct TokenSignature { 79 | gamma: Vec, 80 | c: Vec, 81 | w: RistrettoPoint, 82 | s: Scalar 83 | } 84 | 85 | impl TokenSignature { 86 | pub fn new(keypair: &KeyPair, message: &[u8]) -> Self { 87 | let h = ECVRF_hash_to_curve(keypair.public, message); 88 | let gamma = keypair.private * h; 89 | let k = ECVRF_nonce(keypair.private, h); 90 | let c = ECVRF_hash_points(&[h, gamma, k* RISTRETTO_BASEPOINT_POINT, k*h]); 91 | let s = (k + c * keypair.private).reduce(); 92 | 93 | // W = h^(s0 - S) * .. * hn^(sn - S) 94 | let w = RistrettoPoint::identity(); 95 | 96 | TokenSignature { 97 | gamma: vec![gamma], 98 | c: vec![c], 99 | w, 100 | s 101 | } 102 | } 103 | 104 | pub fn sign>(&self, public_keys: &[RistrettoPoint], 105 | messages: &[M], keypair: &KeyPair, message: &[u8]) -> Self { 106 | let h = ECVRF_hash_to_curve(keypair.public, message); 107 | let gamma = keypair.private * h; 108 | let k = ECVRF_nonce(keypair.private, h); 109 | 110 | let pc = public_keys.iter().zip(self.c.iter()).map(|(p, c)| p*(c.neg())).collect::>(); 111 | // u = g^(k0 + k1 + ... + kn) 112 | let u = add_points(&pc) + (self.s * RISTRETTO_BASEPOINT_POINT) + (k * RISTRETTO_BASEPOINT_POINT); 113 | 114 | let hashes = messages.iter().zip(public_keys.iter()).map(|(m, pk)| ECVRF_hash_to_curve(*pk, m)).collect::>(); 115 | let hashes_sum = add_points(&hashes); 116 | 117 | // v = h0^k0 * h1^k1 * .. * hn^k^n 118 | let v = self.gamma.iter().zip(self.c.iter()).fold(self.w, |acc, (gamma, c)| { 119 | (c.neg() * gamma) + acc 120 | }) + (self.s * hashes_sum) + (k * h); 121 | 122 | let gammas = add_points(&self.gamma); 123 | 124 | let c = ECVRF_hash_points(&[h, gammas + gamma, u, v]); 125 | 126 | let s = (k + c * keypair.private).reduce(); 127 | let agg_s = (self.s + s).reduce(); 128 | 129 | let hs = hashes_sum * s.neg(); 130 | let w = self.w + hs + h * self.s.neg(); 131 | 132 | let mut res = TokenSignature { 133 | gamma: self.gamma.clone(), 134 | c: self.c.clone(), 135 | w, 136 | s: agg_s 137 | }; 138 | res.gamma.push(gamma); 139 | res.c.push(c); 140 | 141 | res 142 | } 143 | 144 | pub fn verify>(&self, public_keys: &[RistrettoPoint], messages: &[M]) -> bool { 145 | if !(public_keys.len() == messages.len() 146 | && public_keys.len() == self.gamma.len() 147 | && public_keys.len() == self.c.len()) { 148 | println!("invalid data"); 149 | return false; 150 | } 151 | 152 | let pc = public_keys.iter().zip(self.c.iter()).map(|(p, c)| p*(c.neg())).collect::>(); 153 | // u = g^(k0 + k1 + ... + kn) 154 | let u = add_points(&pc) + (self.s *RISTRETTO_BASEPOINT_POINT); 155 | 156 | let hashes = messages.iter().zip(public_keys.iter()).map(|(m, pk)| ECVRF_hash_to_curve(*pk, m)).collect::>(); 157 | 158 | // v = h0^k0 * h1^k1 * .. * hn^k^n 159 | let v = self.gamma.iter().zip(self.c.iter()).zip(hashes.iter()).fold(self.w, |acc, ((gamma, c), h)| { 160 | (c.neg() * gamma) + (self.s * h) + acc 161 | }); 162 | 163 | let gammas = add_points(&self.gamma); 164 | 165 | let c = ECVRF_hash_points(&[*hashes.last().unwrap(), gammas, u, v]); 166 | 167 | c == *self.c.last().unwrap() 168 | } 169 | 170 | } 171 | 172 | //FIXME: the ECVRF_hash_to_curve1 looks like a hash and pray, but since 173 | // curve25519-dalek already has a hash to curve function, we can reuse it instead? 174 | pub fn ECVRF_hash_to_curve(point: RistrettoPoint, data: &[u8]) -> RistrettoPoint { 175 | let h = Sha512::new() 176 | .chain(point.compress().as_bytes()) 177 | .chain(data); 178 | 179 | RistrettoPoint::from_hash(h) 180 | } 181 | 182 | //FIXME: is the output value in the right set? 183 | pub fn ECVRF_hash_points(points: &[RistrettoPoint]) -> Scalar { 184 | let mut h = Sha512::new(); 185 | for point in points.iter() { 186 | h.input(point.compress().as_bytes()); 187 | } 188 | 189 | Scalar::from_hash(h) 190 | } 191 | 192 | pub fn add_points(points: &[RistrettoPoint]) -> RistrettoPoint { 193 | assert!(points.len() > 0); 194 | 195 | if points.len() == 1 { 196 | points[0] 197 | } else { 198 | let mut it = points.iter(); 199 | let first = it.next().unwrap(); 200 | it.fold(*first, |acc, pk| acc + pk) 201 | } 202 | } 203 | 204 | pub fn ECVRF_nonce(sk: Scalar, point: RistrettoPoint) -> Scalar { 205 | let k = [0u8; 64]; 206 | let v = [1u8; 64]; 207 | 208 | let mut mac = HmacSha512::new_varkey(&k[..]).unwrap(); 209 | mac.input(&v[..]); 210 | mac.input(&[0]); 211 | mac.input(&sk.as_bytes()[..]); 212 | mac.input(point.compress().as_bytes()); 213 | 214 | let k = mac.result().code(); 215 | 216 | let mut mac = HmacSha512::new_varkey(&k[..]).unwrap(); 217 | mac.input(&v[..]); 218 | mac.input(&[1]); 219 | mac.input(&sk.as_bytes()[..]); 220 | mac.input(point.compress().as_bytes()); 221 | 222 | let k = mac.result().code(); 223 | 224 | // the process in RFC 6979 is a bit ore complex than that 225 | let mut h = Sha512::new(); 226 | h.input(k); 227 | 228 | Scalar::from_hash(h) 229 | 230 | 231 | } 232 | 233 | #[cfg(test)] 234 | mod tests { 235 | use super::*; 236 | 237 | #[test] 238 | fn three_messages() { 239 | //let mut rng: OsRng = OsRng::new().unwrap(); 240 | //keep the same values in tests 241 | let mut rng: StdRng = SeedableRng::seed_from_u64(0); 242 | 243 | let message1 = b"hello"; 244 | let keypair1 = KeyPair::new(&mut rng); 245 | 246 | let token1 = Token::new(&keypair1, &message1[..]); 247 | 248 | assert!(token1.verify(), "cannot verify first token"); 249 | 250 | println!("will derive a second token"); 251 | 252 | let message2 = b"world"; 253 | let keypair2 = KeyPair::new(&mut rng); 254 | 255 | let token2 = token1.append(&keypair2, &message2[..]); 256 | 257 | assert!(token2.verify(), "cannot verify second token"); 258 | 259 | println!("will derive a third token"); 260 | 261 | let message3 = b"!!!"; 262 | let keypair3 = KeyPair::new(&mut rng); 263 | 264 | let token3 = token2.append(&keypair3, &message3[..]); 265 | 266 | assert!(token3.verify(), "cannot verify third token"); 267 | } 268 | 269 | #[test] 270 | fn change_message() { 271 | //let mut rng: OsRng = OsRng::new().unwrap(); 272 | //keep the same values in tests 273 | let mut rng: StdRng = SeedableRng::seed_from_u64(0); 274 | 275 | let message1 = b"hello"; 276 | let keypair1 = KeyPair::new(&mut rng); 277 | 278 | let token1 = Token::new(&keypair1, &message1[..]); 279 | 280 | assert!(token1.verify(), "cannot verify first token"); 281 | 282 | println!("will derive a second token"); 283 | 284 | let message2 = b"world"; 285 | let keypair2 = KeyPair::new(&mut rng); 286 | 287 | let mut token2 = token1.append(&keypair2, &message2[..]); 288 | 289 | token2.messages[1] = Vec::from(&b"you"[..]); 290 | 291 | assert!(!token2.verify(), "second token should not be valid"); 292 | 293 | println!("will derive a third token"); 294 | 295 | let message3 = b"!!!"; 296 | let keypair3 = KeyPair::new(&mut rng); 297 | 298 | let token3 = token2.append(&keypair3, &message3[..]); 299 | 300 | assert!(!token3.verify(), "cannot verify third token"); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /experimentations/vrf/biscuit-vrf/src/second.rs: -------------------------------------------------------------------------------- 1 | //! same solution as in src/lib.rs, but preaggregating the 'gamma' points 2 | //! note: now the gamma points are not added into the 'c' hash calculation 3 | #![allow(non_snake_case)] 4 | 5 | use rand::prelude::*; 6 | use curve25519_dalek::{ 7 | constants::RISTRETTO_BASEPOINT_POINT, 8 | ristretto::{RistrettoPoint}, 9 | scalar::Scalar, 10 | traits::Identity 11 | }; 12 | use std::ops::{Deref, Neg}; 13 | use super::{ECVRF_hash_to_curve, ECVRF_hash_points, ECVRF_nonce, add_points}; 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 | pub struct Token { 30 | pub messages: Vec>, 31 | pub keys: Vec, 32 | pub signature: TokenSignature, 33 | } 34 | 35 | impl Token { 36 | pub fn new(keypair: &KeyPair, message: &[u8]) -> Self { 37 | let signature = TokenSignature::new(keypair, message); 38 | 39 | Token { 40 | messages: vec![message.to_owned()], 41 | keys: vec![keypair.public], 42 | signature 43 | } 44 | } 45 | 46 | pub fn append(&self, keypair: &KeyPair, message: &[u8]) -> Self { 47 | let signature = self.signature.sign(&self.keys, &self.messages, keypair, message); 48 | 49 | let mut t = Token { 50 | messages: self.messages.clone(), 51 | keys: self.keys.clone(), 52 | signature 53 | }; 54 | 55 | t.messages.push(message.to_owned()); 56 | t.keys.push(keypair.public); 57 | 58 | t 59 | } 60 | 61 | pub fn verify(&self) -> bool { 62 | self.signature.verify(&self.keys, &self.messages) 63 | } 64 | } 65 | 66 | pub struct TokenSignature { 67 | gamma_agg: RistrettoPoint, 68 | c: Vec, 69 | w: RistrettoPoint, 70 | s: Scalar 71 | } 72 | 73 | impl TokenSignature { 74 | pub fn new(keypair: &KeyPair, message: &[u8]) -> Self { 75 | let h = ECVRF_hash_to_curve(keypair.public, message); 76 | let gamma = keypair.private * h; 77 | let k = ECVRF_nonce(keypair.private, h); 78 | let c = ECVRF_hash_points(&[h, keypair.public, k* RISTRETTO_BASEPOINT_POINT, k*h]); 79 | let s = (k + c * keypair.private).reduce(); 80 | 81 | // W = h^(s0 - S) * .. * hn^(sn - S) 82 | let w = RistrettoPoint::identity(); 83 | 84 | TokenSignature { 85 | gamma_agg: c.neg() * gamma, 86 | c: vec![c], 87 | w, 88 | s 89 | } 90 | } 91 | 92 | pub fn sign>(&self, public_keys: &[RistrettoPoint], 93 | messages: &[M], keypair: &KeyPair, message: &[u8]) -> Self { 94 | let h = ECVRF_hash_to_curve(keypair.public, message); 95 | let gamma = keypair.private * h; 96 | let k = ECVRF_nonce(keypair.private, h); 97 | 98 | let pc = public_keys.iter().zip(self.c.iter()).map(|(p, c)| p*(c.neg())).collect::>(); 99 | // u = g^(k0 + k1 + ... + kn) 100 | let u = add_points(&pc) + (self.s * RISTRETTO_BASEPOINT_POINT) + (k * RISTRETTO_BASEPOINT_POINT); 101 | 102 | let hashes = messages.iter().zip(public_keys.iter()).map(|(m, pk)| ECVRF_hash_to_curve(*pk, m)).collect::>(); 103 | let hashes_sum = add_points(&hashes); 104 | 105 | // v = h0^k0 * h1^k1 * .. * hn^k^n 106 | let v = self.w + self.gamma_agg + (self.s * hashes_sum) + (k * h); 107 | 108 | let p = add_points(public_keys); 109 | 110 | let c = ECVRF_hash_points(&[h, p + keypair.public, u, v]); 111 | 112 | let s = (k + c * keypair.private).reduce(); 113 | let agg_s = (self.s + s).reduce(); 114 | 115 | let hs = hashes_sum * s.neg(); 116 | let w = self.w + hs + h * self.s.neg(); 117 | 118 | let mut res = TokenSignature { 119 | gamma_agg: self.gamma_agg + c.neg() * gamma, 120 | c: self.c.clone(), 121 | w, 122 | s: agg_s 123 | }; 124 | res.c.push(c); 125 | 126 | res 127 | } 128 | 129 | pub fn verify>(&self, public_keys: &[RistrettoPoint], messages: &[M]) -> bool { 130 | if !(public_keys.len() == messages.len() 131 | && public_keys.len() == self.c.len()) { 132 | println!("invalid data"); 133 | return false; 134 | } 135 | 136 | let pc = public_keys.iter().zip(self.c.iter()).map(|(p, c)| p*c.neg()).collect::>(); 137 | // u = g^(k0 + k1 + ... + kn) 138 | let u = add_points(&pc) + (self.s *RISTRETTO_BASEPOINT_POINT); 139 | 140 | let hashes = messages.iter().zip(public_keys.iter()).map(|(m, pk)| ECVRF_hash_to_curve(*pk, m)).collect::>(); 141 | let hashes_sum = add_points(&hashes); 142 | 143 | let v = self.w + self.gamma_agg + (self.s * hashes_sum); 144 | 145 | let p = add_points(public_keys); 146 | 147 | let c = ECVRF_hash_points(&[*hashes.last().unwrap(), p, u, v]); 148 | 149 | c == *self.c.last().unwrap() 150 | } 151 | 152 | } 153 | 154 | #[cfg(test)] 155 | mod tests { 156 | use super::*; 157 | 158 | #[test] 159 | fn three_messages() { 160 | //let mut rng: OsRng = OsRng::new().unwrap(); 161 | //keep the same values in tests 162 | let mut rng: StdRng = SeedableRng::seed_from_u64(0); 163 | 164 | let message1 = b"hello"; 165 | let keypair1 = KeyPair::new(&mut rng); 166 | 167 | let token1 = Token::new(&keypair1, &message1[..]); 168 | 169 | assert!(token1.verify(), "cannot verify first token"); 170 | 171 | println!("will derive a second token"); 172 | 173 | let message2 = b"world"; 174 | let keypair2 = KeyPair::new(&mut rng); 175 | 176 | let token2 = token1.append(&keypair2, &message2[..]); 177 | 178 | assert!(token2.verify(), "cannot verify second token"); 179 | 180 | println!("will derive a third token"); 181 | 182 | let message3 = b"!!!"; 183 | let keypair3 = KeyPair::new(&mut rng); 184 | 185 | let token3 = token2.append(&keypair3, &message3[..]); 186 | 187 | assert!(token3.verify(), "cannot verify third token"); 188 | } 189 | 190 | #[test] 191 | fn change_message() { 192 | //let mut rng: OsRng = OsRng::new().unwrap(); 193 | //keep the same values in tests 194 | let mut rng: StdRng = SeedableRng::seed_from_u64(0); 195 | 196 | let message1 = b"hello"; 197 | let keypair1 = KeyPair::new(&mut rng); 198 | 199 | let token1 = Token::new(&keypair1, &message1[..]); 200 | 201 | assert!(token1.verify(), "cannot verify first token"); 202 | 203 | println!("will derive a second token"); 204 | 205 | let message2 = b"world"; 206 | let keypair2 = KeyPair::new(&mut rng); 207 | 208 | let mut token2 = token1.append(&keypair2, &message2[..]); 209 | 210 | token2.messages[1] = Vec::from(&b"you"[..]); 211 | 212 | assert!(!token2.verify(), "second token should not be valid"); 213 | 214 | println!("will derive a third token"); 215 | 216 | let message3 = b"!!!"; 217 | let keypair3 = KeyPair::new(&mut rng); 218 | 219 | let token3 = token2.append(&keypair3, &message3[..]); 220 | 221 | assert!(!token3.verify(), "cannot verify third token"); 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /samples/README.md: -------------------------------------------------------------------------------- 1 | # Biscuit samples and expected results 2 | 3 | the `current` folder contains sample tokens and the expected result 4 | of their authorization for the current Biscuit version. 5 | 6 | the `deprecated` folder contains samples for the version 0, 1 and 2 of the formats. Those versions are deprecated and should not be used in new implementations. 7 | -------------------------------------------------------------------------------- /samples/current/test001_basic.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test001_basic.bc -------------------------------------------------------------------------------- /samples/current/test002_different_root_key.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test002_different_root_key.bc -------------------------------------------------------------------------------- /samples/current/test003_invalid_signature_format.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test003_invalid_signature_format.bc -------------------------------------------------------------------------------- /samples/current/test004_random_block.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test004_random_block.bc -------------------------------------------------------------------------------- /samples/current/test005_invalid_signature.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test005_invalid_signature.bc -------------------------------------------------------------------------------- /samples/current/test006_reordered_blocks.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test006_reordered_blocks.bc -------------------------------------------------------------------------------- /samples/current/test007_scoped_rules.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test007_scoped_rules.bc -------------------------------------------------------------------------------- /samples/current/test008_scoped_checks.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test008_scoped_checks.bc -------------------------------------------------------------------------------- /samples/current/test009_expired_token.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test009_expired_token.bc -------------------------------------------------------------------------------- /samples/current/test010_authorizer_scope.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test010_authorizer_scope.bc -------------------------------------------------------------------------------- /samples/current/test011_authorizer_authority_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test011_authorizer_authority_caveats.bc -------------------------------------------------------------------------------- /samples/current/test012_authority_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test012_authority_caveats.bc -------------------------------------------------------------------------------- /samples/current/test013_block_rules.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test013_block_rules.bc -------------------------------------------------------------------------------- /samples/current/test014_regex_constraint.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test014_regex_constraint.bc -------------------------------------------------------------------------------- /samples/current/test015_multi_queries_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test015_multi_queries_caveats.bc -------------------------------------------------------------------------------- /samples/current/test016_caveat_head_name.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test016_caveat_head_name.bc -------------------------------------------------------------------------------- /samples/current/test017_expressions.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test017_expressions.bc -------------------------------------------------------------------------------- /samples/current/test018_unbound_variables_in_rule.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test018_unbound_variables_in_rule.bc -------------------------------------------------------------------------------- /samples/current/test019_generating_ambient_from_variables.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test019_generating_ambient_from_variables.bc -------------------------------------------------------------------------------- /samples/current/test020_sealed.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test020_sealed.bc -------------------------------------------------------------------------------- /samples/current/test021_parsing.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test021_parsing.bc -------------------------------------------------------------------------------- /samples/current/test022_default_symbols.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test022_default_symbols.bc -------------------------------------------------------------------------------- /samples/current/test023_execution_scope.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test023_execution_scope.bc -------------------------------------------------------------------------------- /samples/current/test024_third_party.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test024_third_party.bc -------------------------------------------------------------------------------- /samples/current/test025_check_all.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test025_check_all.bc -------------------------------------------------------------------------------- /samples/current/test026_public_keys_interning.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test026_public_keys_interning.bc -------------------------------------------------------------------------------- /samples/current/test027_integer_wraparound.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test027_integer_wraparound.bc -------------------------------------------------------------------------------- /samples/current/test028_expressions_v4.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test028_expressions_v4.bc -------------------------------------------------------------------------------- /samples/current/test029_reject_if.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test029_reject_if.bc -------------------------------------------------------------------------------- /samples/current/test030_null.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test030_null.bc -------------------------------------------------------------------------------- /samples/current/test031_heterogeneous_equal.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test031_heterogeneous_equal.bc -------------------------------------------------------------------------------- /samples/current/test032_laziness_closures.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test032_laziness_closures.bc -------------------------------------------------------------------------------- /samples/current/test033_typeof.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test033_typeof.bc -------------------------------------------------------------------------------- /samples/current/test034_array_map.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test034_array_map.bc -------------------------------------------------------------------------------- /samples/current/test035_ffi.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test035_ffi.bc -------------------------------------------------------------------------------- /samples/current/test036_secp256r1.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test036_secp256r1.bc -------------------------------------------------------------------------------- /samples/current/test037_secp256r1_third_party.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test037_secp256r1_third_party.bc -------------------------------------------------------------------------------- /samples/current/test038_try_op.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/current/test038_try_op.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test10_authority_rules.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test10_authority_rules.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test11_verifier_authority_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test11_verifier_authority_caveats.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test12_authority_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test12_authority_caveats.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test13_block_rules.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test13_block_rules.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test14_regex_constraint.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test14_regex_constraint.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test15_multi_queries_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test15_multi_queries_caveats.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test16_caveat_head_name.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test16_caveat_head_name.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test1_basic.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test1_basic.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test2_different_root_key.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test2_different_root_key.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test3_invalid_signature_format.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test3_invalid_signature_format.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test4_random_block.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test4_random_block.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test5_invalid_signature.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test5_invalid_signature.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test6_reordered_blocks.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test6_reordered_blocks.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test7_invalid_block_fact_authority.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test7_invalid_block_fact_authority.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test8_invalid_block_fact_ambient.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test8_invalid_block_fact_ambient.bc -------------------------------------------------------------------------------- /samples/deprecated/v0/test9_expired_token.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v0/test9_expired_token.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test10_authority_rules.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test10_authority_rules.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test11_verifier_authority_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test11_verifier_authority_caveats.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test12_authority_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test12_authority_caveats.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test13_block_rules.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test13_block_rules.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test14_regex_constraint.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test14_regex_constraint.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test15_multi_queries_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test15_multi_queries_caveats.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test16_caveat_head_name.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test16_caveat_head_name.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test17_expressions.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test17_expressions.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test18_unbound_variables_in_rule.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test18_unbound_variables_in_rule.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test19_generating_ambient_from_variables.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test19_generating_ambient_from_variables.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test1_basic.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test1_basic.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test2_different_root_key.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test2_different_root_key.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test3_invalid_signature_format.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test3_invalid_signature_format.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test4_random_block.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test4_random_block.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test5_invalid_signature.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test5_invalid_signature.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test6_reordered_blocks.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test6_reordered_blocks.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test7_invalid_block_fact_authority.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test7_invalid_block_fact_authority.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test8_invalid_block_fact_ambient.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test8_invalid_block_fact_ambient.bc -------------------------------------------------------------------------------- /samples/deprecated/v1/test9_expired_token.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v1/test9_expired_token.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test10_authorizer_scope.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test10_authorizer_scope.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test11_authorizer_authority_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test11_authorizer_authority_caveats.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test12_authority_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test12_authority_caveats.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test13_block_rules.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test13_block_rules.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test14_regex_constraint.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test14_regex_constraint.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test15_multi_queries_caveats.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test15_multi_queries_caveats.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test16_caveat_head_name.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test16_caveat_head_name.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test17_expressions.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test17_expressions.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test18_unbound_variables_in_rule.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test18_unbound_variables_in_rule.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test19_generating_ambient_from_variables.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test19_generating_ambient_from_variables.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test1_basic.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test1_basic.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test20_sealed.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test20_sealed.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test21_parsing.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test21_parsing.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test2_different_root_key.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test2_different_root_key.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test3_invalid_signature_format.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test3_invalid_signature_format.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test4_random_block.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test4_random_block.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test5_invalid_signature.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test5_invalid_signature.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test6_reordered_blocks.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test6_reordered_blocks.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test7_scoped_rules.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test7_scoped_rules.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test8_scoped_checks.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test8_scoped_checks.bc -------------------------------------------------------------------------------- /samples/deprecated/v2/test9_expired_token.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-biscuit/biscuit/10be6b3e6e2a1f33864606127ee7db5d1e6d901b/samples/deprecated/v2/test9_expired_token.bc -------------------------------------------------------------------------------- /schema.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package biscuit.format.schema; 4 | 5 | message Biscuit { 6 | optional uint32 rootKeyId = 1; 7 | required SignedBlock authority = 2; 8 | repeated SignedBlock blocks = 3; 9 | required Proof proof = 4; 10 | } 11 | 12 | message SignedBlock { 13 | required bytes block = 1; 14 | required PublicKey nextKey = 2; 15 | required bytes signature = 3; 16 | optional ExternalSignature externalSignature = 4; 17 | optional uint32 version = 5; 18 | } 19 | 20 | message ExternalSignature { 21 | required bytes signature = 1; 22 | required PublicKey publicKey = 2; 23 | } 24 | 25 | message PublicKey { 26 | required Algorithm algorithm = 1; 27 | 28 | enum Algorithm { 29 | Ed25519 = 0; 30 | SECP256R1 = 1; 31 | } 32 | 33 | required bytes key = 2; 34 | } 35 | 36 | message Proof { 37 | oneof Content { 38 | bytes nextSecret = 1; 39 | bytes finalSignature = 2; 40 | } 41 | } 42 | 43 | message Block { 44 | repeated string symbols = 1; 45 | optional string context = 2; 46 | optional uint32 version = 3; 47 | repeated Fact facts = 4; 48 | repeated Rule rules = 5; 49 | repeated Check checks = 6; 50 | repeated Scope scope = 7; 51 | repeated PublicKey publicKeys = 8; 52 | } 53 | 54 | message Scope { 55 | enum ScopeType { 56 | Authority = 0; 57 | Previous = 1; 58 | } 59 | 60 | oneof Content { 61 | ScopeType scopeType = 1; 62 | int64 publicKey = 2; 63 | } 64 | } 65 | 66 | message Fact { 67 | required Predicate predicate = 1; 68 | } 69 | 70 | message Rule { 71 | required Predicate head = 1; 72 | repeated Predicate body = 2; 73 | repeated Expression expressions = 3; 74 | repeated Scope scope = 4; 75 | } 76 | 77 | message Check { 78 | repeated Rule queries = 1; 79 | optional Kind kind = 2; 80 | 81 | enum Kind { 82 | One = 0; 83 | All = 1; 84 | Reject = 2; 85 | } 86 | } 87 | 88 | message Predicate { 89 | required uint64 name = 1; 90 | repeated Term terms = 2; 91 | } 92 | 93 | message Term { 94 | oneof Content { 95 | uint32 variable = 1; 96 | int64 integer = 2; 97 | uint64 string = 3; 98 | uint64 date = 4; 99 | bytes bytes = 5; 100 | bool bool = 6; 101 | TermSet set = 7; 102 | Empty null = 8; 103 | Array array = 9; 104 | Map map = 10; 105 | } 106 | } 107 | 108 | message TermSet { 109 | repeated Term set = 1; 110 | } 111 | 112 | message Array { 113 | repeated Term array = 1; 114 | } 115 | 116 | message Map { 117 | repeated MapEntry entries = 1; 118 | } 119 | 120 | message MapEntry { 121 | required MapKey key = 1; 122 | required Term value = 2; 123 | } 124 | 125 | message MapKey { 126 | oneof Content { 127 | int64 integer = 1; 128 | uint64 string = 2; 129 | } 130 | } 131 | 132 | message Expression { 133 | repeated Op ops = 1; 134 | } 135 | 136 | message Op { 137 | oneof Content { 138 | Term value = 1; 139 | OpUnary unary = 2; 140 | OpBinary Binary = 3; 141 | OpClosure closure = 4; 142 | } 143 | } 144 | 145 | message OpUnary { 146 | enum Kind { 147 | Negate = 0; 148 | Parens = 1; 149 | Length = 2; 150 | TypeOf = 3; 151 | Ffi = 4; 152 | } 153 | 154 | required Kind kind = 1; 155 | optional uint64 ffiName = 2; 156 | } 157 | 158 | message OpBinary { 159 | enum Kind { 160 | LessThan = 0; 161 | GreaterThan = 1; 162 | LessOrEqual = 2; 163 | GreaterOrEqual = 3; 164 | Equal = 4; 165 | Contains = 5; 166 | Prefix = 6; 167 | Suffix = 7; 168 | Regex = 8; 169 | Add = 9; 170 | Sub = 10; 171 | Mul = 11; 172 | Div = 12; 173 | And = 13; 174 | Or = 14; 175 | Intersection = 15; 176 | Union = 16; 177 | BitwiseAnd = 17; 178 | BitwiseOr = 18; 179 | BitwiseXor = 19; 180 | NotEqual = 20; 181 | HeterogeneousEqual = 21; 182 | HeterogeneousNotEqual = 22; 183 | LazyAnd = 23; 184 | LazyOr = 24; 185 | All = 25; 186 | Any = 26; 187 | Get = 27; 188 | Ffi = 28; 189 | TryOr = 29; 190 | } 191 | 192 | required Kind kind = 1; 193 | optional uint64 ffiName = 2; 194 | } 195 | 196 | message OpClosure { 197 | repeated uint32 params = 1; 198 | repeated Op ops = 2; 199 | } 200 | 201 | message Policy { 202 | enum Kind { 203 | Allow = 0; 204 | Deny = 1; 205 | } 206 | 207 | repeated Rule queries = 1; 208 | required Kind kind = 2; 209 | } 210 | 211 | message AuthorizerPolicies { 212 | repeated string symbols = 1; 213 | optional uint32 version = 2; 214 | repeated Fact facts = 3; 215 | repeated Rule rules = 4; 216 | repeated Check checks = 5; 217 | repeated Policy policies = 6; 218 | } 219 | 220 | message ThirdPartyBlockRequest { 221 | optional PublicKey legacyPreviousKey = 1; 222 | repeated PublicKey legacyPublicKeys = 2; 223 | required bytes previousSignature = 3; 224 | 225 | } 226 | 227 | message ThirdPartyBlockContents { 228 | required bytes payload = 1; 229 | required ExternalSignature externalSignature = 2; 230 | } 231 | 232 | message AuthorizerSnapshot { 233 | required RunLimits limits = 1; 234 | required uint64 executionTime = 2; 235 | required AuthorizerWorld world = 3; 236 | } 237 | 238 | message RunLimits { 239 | required uint64 maxFacts = 1; 240 | required uint64 maxIterations = 2; 241 | required uint64 maxTime = 3; 242 | } 243 | 244 | message AuthorizerWorld { 245 | optional uint32 version = 1; 246 | repeated string symbols = 2; 247 | repeated PublicKey publicKeys = 3; 248 | repeated SnapshotBlock blocks = 4; 249 | required SnapshotBlock authorizerBlock = 5; 250 | repeated Policy authorizerPolicies = 6; 251 | repeated GeneratedFacts generatedFacts = 7; 252 | required uint64 iterations = 8; 253 | } 254 | 255 | message Origin { 256 | oneof Content { 257 | Empty authorizer = 1; 258 | uint32 origin = 2; 259 | } 260 | } 261 | 262 | message Empty {} 263 | 264 | message GeneratedFacts { 265 | repeated Origin origins = 1; 266 | repeated Fact facts = 2; 267 | } 268 | 269 | message SnapshotBlock { 270 | optional string context = 1; 271 | optional uint32 version = 2; 272 | repeated Fact facts = 3; 273 | repeated Rule rules = 4; 274 | repeated Check checks = 5; 275 | repeated Scope scope = 6; 276 | optional PublicKey externalKey = 7; 277 | } 278 | --------------------------------------------------------------------------------