├── .github └── settings.yml ├── 0000-template.md ├── CODEOWNERS ├── LICENSE ├── README.md └── text ├── 0001-encryption-api ├── README.md ├── flamacro.tex ├── hartm_macro_safe.tex └── main.tex ├── 0002-zmix-api └── README.md ├── 0011-python-wrappers └── README.md ├── cs-verifiable-encryption └── README.md ├── delegatable_cdd └── README.md ├── language-bindings └── README.md ├── pok-vpc └── README.md └── ps-signatures └── README.md /.github/settings.yml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | 5 | repository: 6 | name: ursa-rfcs 7 | description: Hyperledger Ursa has moved to end-of-life status. 8 | homepage: https://wiki.hyperledger.org/display/ursa 9 | default_branch: main 10 | archived: true 11 | -------------------------------------------------------------------------------- /0000-template.md: -------------------------------------------------------------------------------- 1 | [//]: # (SPDX-License-Identifier: CC-BY-4.0) 2 | 3 | - Feature Name: (fill me in with a unique identifier, my_awesome_feature) 4 | - Start Date: (fill me in with today's date, YYYY-MM-DD) 5 | - RFC PR: (leave this empty) 6 | - Ursa Issue: (leave this empty) 7 | - Version: (use whole numbers: 1, 2, 3, etc) 8 | 9 | # Summary 10 | [summary]: #summary 11 | 12 | One paragraph explanation of the feature. 13 | 14 | # Motivation 15 | [motivation]: #motivation 16 | 17 | Why are we doing this? What is the unfulfilled requirement? What use cases does 18 | it support? What is the expected outcome? 19 | 20 | # Guide-level explanation 21 | [guide-level-explanation]: #guide-level-explanation 22 | 23 | Explain the proposal as if it was already included in Ursa and you were 24 | teaching it to another Ursa programmer. That generally means: 25 | 26 | - Introducing new named concepts. 27 | - Explaining the feature largely in terms of examples. 28 | - Explaining how Ursa programmers should *think* about the feature, and how 29 | it should impact the way they use Ursa. It should explain the impact as 30 | concretely as possible. 31 | - If applicable, provide sample error messages, deprecation warnings, or 32 | migration guidance. 33 | - If applicable, describe the differences between teaching this to existing 34 | Ursa programmers and new Ursa programmers. 35 | - If applicable, describe any changes that may affect the security of 36 | communications or administration. 37 | 38 | # Reference-level explanation 39 | [reference-level-explanation]: #reference-level-explanation 40 | 41 | This is the technical portion of the RFC. Explain the design in sufficient 42 | detail that: 43 | 44 | - Its interaction with other features is clear. 45 | - It is reasonably clear how the feature would be implemented. 46 | - Corner cases are dissected by example. 47 | - Any new or altered interfaces should include pseudo-code. 48 | 49 | The section should return to the examples given in the previous section, and 50 | explain more fully how the detailed proposal makes those examples work. 51 | 52 | # Drawbacks 53 | [drawbacks]: #drawbacks 54 | 55 | Why should we *not* do this? 56 | 57 | # Rationale and alternatives 58 | [alternatives]: #alternatives 59 | 60 | - Why is this design the best in the space of possible designs? 61 | - What other designs have been considered and what is the rationale for not 62 | choosing them? 63 | - What is the impact of not doing this? 64 | - For incorporating new protocol implementations what other implementations 65 | exist and why were they not selected? 66 | - For new protocols, what related protocols exist and why do the not satisfy 67 | requirements? 68 | 69 | # Prior art 70 | [prior-art]: #prior-art 71 | 72 | Discuss prior art, both the good and the bad, in relation to this proposal. 73 | A few examples of what this can include are: 74 | 75 | - For other teams: What lessons can we learn from what other communities have 76 | done here? 77 | - Papers: Are there any published papers or great posts that discuss this? If 78 | you have some relevant papers to refer to, this can serve as a more detailed 79 | theoretical background. 80 | 81 | This section is intended to encourage you as an author to think about the 82 | lessons from other distributed ledgers or cryptographic libraries and provide 83 | readers of your RFC with a fuller picture. 84 | 85 | # Unresolved questions 86 | [unresolved]: #unresolved-questions 87 | 88 | - What parts of the design do you expect to resolve through the RFC process 89 | before this gets merged? 90 | - What parts of the design do you expect to resolve through the implementation 91 | of this feature before stabilization? 92 | - What related issues do you consider out of scope for this RFC that could be 93 | addressed in the future independently of the solution that comes out of this 94 | RFC? 95 | 96 | # Changelog 97 | [changelog]: #changelog 98 | 99 | - [10 Jan 2019] - v2 - a one-line summary of the changes in this version. 100 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @hyperledger/ursa-maintainers 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution 4.0 International Public License 58 | 59 | By exercising the Licensed Rights (defined below), You accept and agree 60 | to be bound by the terms and conditions of this Creative Commons 61 | Attribution 4.0 International Public License ("Public License"). To the 62 | extent this Public License may be interpreted as a contract, You are 63 | granted the Licensed Rights in consideration of Your acceptance of 64 | these terms and conditions, and the Licensor grants You such rights in 65 | consideration of benefits the Licensor receives from making the 66 | Licensed Material available under these terms and conditions. 67 | 68 | 69 | Section 1 -- Definitions. 70 | 71 | a. Adapted Material means material subject to Copyright and Similar 72 | Rights that is derived from or based upon the Licensed Material 73 | and in which the Licensed Material is translated, altered, 74 | arranged, transformed, or otherwise modified in a manner requiring 75 | permission under the Copyright and Similar Rights held by the 76 | Licensor. For purposes of this Public License, where the Licensed 77 | Material is a musical work, performance, or sound recording, 78 | Adapted Material is always produced where the Licensed Material is 79 | synched in timed relation with a moving image. 80 | 81 | b. Adapter's License means the license You apply to Your Copyright 82 | and Similar Rights in Your contributions to Adapted Material in 83 | accordance with the terms and conditions of this Public License. 84 | 85 | c. Copyright and Similar Rights means copyright and/or similar rights 86 | closely related to copyright including, without limitation, 87 | performance, broadcast, sound recording, and Sui Generis Database 88 | Rights, without regard to how the rights are labeled or 89 | categorized. For purposes of this Public License, the rights 90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 91 | Rights. 92 | 93 | d. Effective Technological Measures means those measures that, in the 94 | absence of proper authority, may not be circumvented under laws 95 | fulfilling obligations under Article 11 of the WIPO Copyright 96 | Treaty adopted on December 20, 1996, and/or similar international 97 | agreements. 98 | 99 | e. Exceptions and Limitations means fair use, fair dealing, and/or 100 | any other exception or limitation to Copyright and Similar Rights 101 | that applies to Your use of the Licensed Material. 102 | 103 | f. Licensed Material means the artistic or literary work, database, 104 | or other material to which the Licensor applied this Public 105 | License. 106 | 107 | g. Licensed Rights means the rights granted to You subject to the 108 | terms and conditions of this Public License, which are limited to 109 | all Copyright and Similar Rights that apply to Your use of the 110 | Licensed Material and that the Licensor has authority to license. 111 | 112 | h. Licensor means the individual(s) or entity(ies) granting rights 113 | under this Public License. 114 | 115 | i. Share means to provide material to the public by any means or 116 | process that requires permission under the Licensed Rights, such 117 | as reproduction, public display, public performance, distribution, 118 | dissemination, communication, or importation, and to make material 119 | available to the public including in ways that members of the 120 | public may access the material from a place and at a time 121 | individually chosen by them. 122 | 123 | j. Sui Generis Database Rights means rights other than copyright 124 | resulting from Directive 96/9/EC of the European Parliament and of 125 | the Council of 11 March 1996 on the legal protection of databases, 126 | as amended and/or succeeded, as well as other essentially 127 | equivalent rights anywhere in the world. 128 | 129 | k. You means the individual or entity exercising the Licensed Rights 130 | under this Public License. Your has a corresponding meaning. 131 | 132 | 133 | Section 2 -- Scope. 134 | 135 | a. License grant. 136 | 137 | 1. Subject to the terms and conditions of this Public License, 138 | the Licensor hereby grants You a worldwide, royalty-free, 139 | non-sublicensable, non-exclusive, irrevocable license to 140 | exercise the Licensed Rights in the Licensed Material to: 141 | 142 | a. reproduce and Share the Licensed Material, in whole or 143 | in part; and 144 | 145 | b. produce, reproduce, and Share Adapted Material. 146 | 147 | 2. Exceptions and Limitations. For the avoidance of doubt, where 148 | Exceptions and Limitations apply to Your use, this Public 149 | License does not apply, and You do not need to comply with 150 | its terms and conditions. 151 | 152 | 3. Term. The term of this Public License is specified in Section 153 | 6(a). 154 | 155 | 4. Media and formats; technical modifications allowed. The 156 | Licensor authorizes You to exercise the Licensed Rights in 157 | all media and formats whether now known or hereafter created, 158 | and to make technical modifications necessary to do so. The 159 | Licensor waives and/or agrees not to assert any right or 160 | authority to forbid You from making technical modifications 161 | necessary to exercise the Licensed Rights, including 162 | technical modifications necessary to circumvent Effective 163 | Technological Measures. For purposes of this Public License, 164 | simply making modifications authorized by this Section 2(a) 165 | (4) never produces Adapted Material. 166 | 167 | 5. Downstream recipients. 168 | 169 | a. Offer from the Licensor -- Licensed Material. Every 170 | recipient of the Licensed Material automatically 171 | receives an offer from the Licensor to exercise the 172 | Licensed Rights under the terms and conditions of this 173 | Public License. 174 | 175 | b. No downstream restrictions. You may not offer or impose 176 | any additional or different terms or conditions on, or 177 | apply any Effective Technological Measures to, the 178 | Licensed Material if doing so restricts exercise of the 179 | Licensed Rights by any recipient of the Licensed 180 | Material. 181 | 182 | 6. No endorsement. Nothing in this Public License constitutes or 183 | may be construed as permission to assert or imply that You 184 | are, or that Your use of the Licensed Material is, connected 185 | with, or sponsored, endorsed, or granted official status by, 186 | the Licensor or others designated to receive attribution as 187 | provided in Section 3(a)(1)(A)(i). 188 | 189 | b. Other rights. 190 | 191 | 1. Moral rights, such as the right of integrity, are not 192 | licensed under this Public License, nor are publicity, 193 | privacy, and/or other similar personality rights; however, to 194 | the extent possible, the Licensor waives and/or agrees not to 195 | assert any such rights held by the Licensor to the limited 196 | extent necessary to allow You to exercise the Licensed 197 | Rights, but not otherwise. 198 | 199 | 2. Patent and trademark rights are not licensed under this 200 | Public License. 201 | 202 | 3. To the extent possible, the Licensor waives any right to 203 | collect royalties from You for the exercise of the Licensed 204 | Rights, whether directly or through a collecting society 205 | under any voluntary or waivable statutory or compulsory 206 | licensing scheme. In all other cases the Licensor expressly 207 | reserves any right to collect such royalties. 208 | 209 | 210 | Section 3 -- License Conditions. 211 | 212 | Your exercise of the Licensed Rights is expressly made subject to the 213 | following conditions. 214 | 215 | a. Attribution. 216 | 217 | 1. If You Share the Licensed Material (including in modified 218 | form), You must: 219 | 220 | a. retain the following if it is supplied by the Licensor 221 | with the Licensed Material: 222 | 223 | i. identification of the creator(s) of the Licensed 224 | Material and any others designated to receive 225 | attribution, in any reasonable manner requested by 226 | the Licensor (including by pseudonym if 227 | designated); 228 | 229 | ii. a copyright notice; 230 | 231 | iii. a notice that refers to this Public License; 232 | 233 | iv. a notice that refers to the disclaimer of 234 | warranties; 235 | 236 | v. a URI or hyperlink to the Licensed Material to the 237 | extent reasonably practicable; 238 | 239 | b. indicate if You modified the Licensed Material and 240 | retain an indication of any previous modifications; and 241 | 242 | c. indicate the Licensed Material is licensed under this 243 | Public License, and include the text of, or the URI or 244 | hyperlink to, this Public License. 245 | 246 | 2. You may satisfy the conditions in Section 3(a)(1) in any 247 | reasonable manner based on the medium, means, and context in 248 | which You Share the Licensed Material. For example, it may be 249 | reasonable to satisfy the conditions by providing a URI or 250 | hyperlink to a resource that includes the required 251 | information. 252 | 253 | 3. If requested by the Licensor, You must remove any of the 254 | information required by Section 3(a)(1)(A) to the extent 255 | reasonably practicable. 256 | 257 | 4. If You Share Adapted Material You produce, the Adapter's 258 | License You apply must not prevent recipients of the Adapted 259 | Material from complying with this Public License. 260 | 261 | 262 | Section 4 -- Sui Generis Database Rights. 263 | 264 | Where the Licensed Rights include Sui Generis Database Rights that 265 | apply to Your use of the Licensed Material: 266 | 267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 268 | to extract, reuse, reproduce, and Share all or a substantial 269 | portion of the contents of the database; 270 | 271 | b. if You include all or a substantial portion of the database 272 | contents in a database in which You have Sui Generis Database 273 | Rights, then the database in which You have Sui Generis Database 274 | Rights (but not its individual contents) is Adapted Material; and 275 | 276 | c. You must comply with the conditions in Section 3(a) if You Share 277 | all or a substantial portion of the contents of the database. 278 | 279 | For the avoidance of doubt, this Section 4 supplements and does not 280 | replace Your obligations under this Public License where the Licensed 281 | Rights include other Copyright and Similar Rights. 282 | 283 | 284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 285 | 286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 296 | 297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 306 | 307 | c. The disclaimer of warranties and limitation of liability provided 308 | above shall be interpreted in a manner that, to the extent 309 | possible, most closely approximates an absolute disclaimer and 310 | waiver of all liability. 311 | 312 | 313 | Section 6 -- Term and Termination. 314 | 315 | a. This Public License applies for the term of the Copyright and 316 | Similar Rights licensed here. However, if You fail to comply with 317 | this Public License, then Your rights under this Public License 318 | terminate automatically. 319 | 320 | b. Where Your right to use the Licensed Material has terminated under 321 | Section 6(a), it reinstates: 322 | 323 | 1. automatically as of the date the violation is cured, provided 324 | it is cured within 30 days of Your discovery of the 325 | violation; or 326 | 327 | 2. upon express reinstatement by the Licensor. 328 | 329 | For the avoidance of doubt, this Section 6(b) does not affect any 330 | right the Licensor may have to seek remedies for Your violations 331 | of this Public License. 332 | 333 | c. For the avoidance of doubt, the Licensor may also offer the 334 | Licensed Material under separate terms or conditions or stop 335 | distributing the Licensed Material at any time; however, doing so 336 | will not terminate this Public License. 337 | 338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 339 | License. 340 | 341 | 342 | Section 7 -- Other Terms and Conditions. 343 | 344 | a. The Licensor shall not be bound by any additional or different 345 | terms or conditions communicated by You unless expressly agreed. 346 | 347 | b. Any arrangements, understandings, or agreements regarding the 348 | Licensed Material not stated herein are separate from and 349 | independent of the terms and conditions of this Public License. 350 | 351 | 352 | Section 8 -- Interpretation. 353 | 354 | a. For the avoidance of doubt, this Public License does not, and 355 | shall not be interpreted to, reduce, limit, restrict, or impose 356 | conditions on any use of the Licensed Material that could lawfully 357 | be made without permission under this Public License. 358 | 359 | b. To the extent possible, if any provision of this Public License is 360 | deemed unenforceable, it shall be automatically reformed to the 361 | minimum extent necessary to make it enforceable. If the provision 362 | cannot be reformed, it shall be severed from this Public License 363 | without affecting the enforceability of the remaining terms and 364 | conditions. 365 | 366 | c. No term or condition of this Public License will be waived and no 367 | failure to comply consented to unless expressly agreed to by the 368 | Licensor. 369 | 370 | d. Nothing in this Public License constitutes or may be interpreted 371 | as a limitation upon, or waiver of, any privileges and immunities 372 | that apply to the Licensor or You, including from the legal 373 | processes of any jurisdiction or authority. 374 | 375 | 376 | ======================================================================= 377 | 378 | Creative Commons is not a party to its public 379 | licenses. Notwithstanding, Creative Commons may elect to apply one of 380 | its public licenses to material it publishes and in those instances 381 | will be considered the “Licensor.” The text of the Creative Commons 382 | public licenses is dedicated to the public domain under the CC0 Public 383 | Domain Dedication. Except for the limited purpose of indicating that 384 | material is shared under a Creative Commons public license or as 385 | otherwise permitted by the Creative Commons policies published at 386 | creativecommons.org/policies, Creative Commons does not authorize the 387 | use of the trademark "Creative Commons" or any other trademark or logo 388 | of Creative Commons without its prior written consent including, 389 | without limitation, in connection with any unauthorized modifications 390 | to any of its public licenses or any other arrangements, 391 | understandings, or agreements concerning use of licensed material. For 392 | the avoidance of doubt, this paragraph does not form part of the 393 | public licenses. 394 | 395 | Creative Commons may be contacted at creativecommons.org. 396 | 397 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [//]: # (SPDX-License-Identifier: CC-BY-4.0) 2 | 3 | 4 | [Hyperledger Ursa was moved to EOL at the TOC meeting on 27 APR 2023.](https://toc.hyperledger.org/meeting-minutes/2023/2023-04-27-TOC-meeting-record.html) 5 | 6 | # Ursa RFCs 7 | [Ursa RFCs]: #ursa-rfcs 8 | 9 | Many changes, including bug fixes and documentation improvements can be 10 | implemented and reviewed via the normal GitHub pull request workflow. 11 | 12 | Some changes though are "substantial", and we ask that these be put through a 13 | bit of a design process and produce a consensus among the Ursa community. 14 | 15 | The "RFC" (request for comments) process is intended to provide a consistent 16 | and controlled path for major changes to enter Ursa and other official 17 | project components, so that all stakeholders can be confident about the 18 | direction Ursa is evolving in. 19 | 20 | This process is intended to be substantially similar to the Rust RFCs process, 21 | customized as necessary for use with Ursa. The README.md and 22 | 0000-template.md were initially forked from [Rust 23 | RFCs](https://github.com/rust-lang/rfcs). 24 | 25 | 26 | ## Table of Contents 27 | [Table of Contents]: #table-of-contents 28 | 29 | - [Opening](#ursa-rfcs) 30 | - [Table of Contents] 31 | - [When you need to follow this process] 32 | - [Before creating an RFC] 33 | - [What the process is] 34 | - [The RFC life-cycle] 35 | - [Reviewing RFCs] 36 | - [Implementing an RFC] 37 | - [Help this is all too informal!] 38 | - [License] 39 | 40 | 41 | ## When you need to follow this process 42 | [When you need to follow this process]: #when-you-need-to-follow-this-process 43 | 44 | You need to follow this process if you intend to make "substantial" changes to 45 | Ursa or any of its sub-components or the RFC process itself. What constitutes a 46 | "substantial" change is evolving based on community norms and varies depending 47 | on what part of the project you are proposing to change, but may include the 48 | following. 49 | 50 | - Architectural changes 51 | - Substantial changes to component interfaces 52 | - New core features 53 | - Backward incompatible changes 54 | - Changes that affect the security of communications or administration 55 | - New Protocols 56 | - New implementations of existing protocols 57 | (as they may have different security properties) 58 | 59 | Some changes do not require an RFC: 60 | 61 | - Rephrasing, reorganizing, refactoring, or otherwise "changing shape does 62 | not change meaning". 63 | - Additions that strictly improve objective, numerical quality criteria 64 | (warning removal, speedup, better platform coverage, more parallelism, trap 65 | more errors, etc.) 66 | 67 | If you submit a pull request to implement a new feature without going through 68 | the RFC process, it may be closed with a polite request to submit an RFC first. 69 | 70 | ## Before creating an RFC 71 | [Before creating an RFC]: #before-creating-an-rfc 72 | 73 | A hastily-proposed RFC can hurt its chances of acceptance. Low quality 74 | proposals, proposals for previously-rejected changes, or those that don't fit 75 | into the near-term roadmap, may be quickly rejected, which can be demotivating 76 | for the unprepared contributor. Laying some groundwork ahead of the RFC can 77 | make the process smoother. 78 | 79 | Although there is no single way to prepare for submitting an RFC, it is 80 | generally a good idea to pursue feedback from other project developers 81 | beforehand, to ascertain that the RFC may be desirable; having a consistent 82 | impact on the project requires concerted effort toward consensus-building. 83 | 84 | The most common preparations for writing and submitting an RFC include talking 85 | the idea over on [#ursa](https://chat.hyperledger.org/channel/ursa) and 86 | proposing ideas to the Hyperledger Ursa mailing list 87 | (https://lists.hyperledger.org/mailman/listinfo/hyperledger-ursa). 88 | 89 | As a rule of thumb, receiving encouraging feedback from long-standing project 90 | developers, and particularly maintainers is a good 91 | indication that the RFC is worth pursuing. 92 | 93 | 94 | ## What the process is 95 | [What the process is]: #what-the-process-is 96 | 97 | In short, to get a major feature added to Ursa, one must first get the RFC 98 | merged into the RFC repository as a markdown file. At that point the RFC is 99 | "active" and may be implemented with the goal of eventual inclusion into Ursa. 100 | 101 | - Fork the RFC repo [RFC repository] 102 | - Copy `0000-template.md` to `0000-my-feature.md` (where "my-feature" is 103 | descriptive. Don't assign an RFC number yet). 104 | - If the RFC has supporting images or diagram files, also create a folder 105 | called `0000-my-feature` and put them there. 106 | - Fill in the RFC. Put care into the details: RFCs that do not present 107 | convincing motivation, demonstrate understanding of the impact of the 108 | design, or are disingenuous about the drawbacks or alternatives tend to be 109 | poorly-received. 110 | - Submit a pull request. As a pull request the RFC will receive design 111 | feedback from the larger community, and the author should be prepared to 112 | revise it in response. 113 | - Build consensus and integrate feedback. RFCs that have broad support are 114 | much more likely to make progress than those that don't receive any 115 | comments. Feel free to reach out to the RFC assignee in particular to get 116 | help identifying stakeholders and obstacles. 117 | - Maintainers will discuss the RFC pull request, as much as possible in the 118 | comment thread of the pull request itself. Offline discussion will be 119 | summarized on the pull request comment thread. 120 | - RFCs rarely go through this process unchanged, especially as alternatives 121 | and drawbacks are shown. You can make edits, big and small, to the RFC to 122 | clarify or change the design, but make changes as new commits to the pull 123 | request, and leave a comment on the pull request explaining your changes. 124 | Specifically, do not squash or rebase commits after they are visible on the 125 | pull request. 126 | - At some point, a maintainer will propose a "motion for final 127 | comment period" (FCP), along with a *disposition* for the RFC (merge, close, 128 | or postpone). 129 | - This step is taken when enough of the tradeoffs have been discussed that 130 | the maintainers are in a position to make a decision. That does not require 131 | consensus amongst all participants in the RFC thread (which is usually 132 | impossible). However, the argument supporting the disposition on the RFC 133 | needs to have already been clearly articulated, and there should not be a 134 | strong consensus *against* that position outside of the maintainers. 135 | Maintainers use their best judgment in taking this step, and the FCP itself 136 | ensures there is ample time and notification for stakeholders to push back 137 | if it is made prematurely. 138 | - For RFCs with lengthy discussion, the motion to FCP is usually preceded by 139 | a *summary comment* trying to lay out the current state of the discussion 140 | and major trade-offs/points of disagreement. 141 | - Before actually entering FCP, *all* maintainers must sign off; 142 | this is often the point at which many maintainers first review the RFC 143 | in full depth. 144 | - The FCP lasts one week, or seven calendar days. It is also advertised 145 | widely, e.g. in [Ursa Mailing 146 | List](https://lists.hyperledger.org/mailman/listinfo/hyperledger-ursa). This 147 | way all stakeholders have a chance to lodge any final objections before 148 | a decision is reached. 149 | - In most cases, the FCP period is quiet, and the RFC is either merged or 150 | closed. However, sometimes substantial new arguments or ideas are raised, 151 | the FCP is canceled, and the RFC goes back into development mode. 152 | 153 | ## The RFC life-cycle 154 | [The RFC life-cycle]: #the-rfc-life-cycle 155 | 156 | Once an RFC becomes "active" then authors may implement it and submit the 157 | change as a pull request to the corresponding Ursa repo. Being "active" is not 158 | a rubber stamp, and in particular still does not mean the change will 159 | ultimately be merged; it does mean that in principle all the major stakeholders 160 | have agreed to the change and are amenable to merging it. 161 | 162 | Furthermore, the fact that a given RFC has been accepted and is "active" 163 | implies nothing about what priority is assigned to its implementation, nor does 164 | it imply anything about whether a Ursa developer has been assigned the task of 165 | implementing the feature. While it is not *necessary* that the author of the 166 | RFC also write the implementation, it is by far the most effective way to see 167 | an RFC through to completion: authors should not expect that other project 168 | developers will take on responsibility for implementing their accepted feature. 169 | 170 | Modifications to "active" RFCs can be done in follow-up pull requests. We 171 | strive to write each RFC in a manner that it will reflect the final design of 172 | the feature; but the nature of the process means that we cannot expect every 173 | merged RFC to actually reflect what the end result will be at the time of the 174 | next major release. 175 | 176 | In general, once accepted, RFCs should not be substantially changed. Only very 177 | minor changes should be submitted as amendments. More substantial changes 178 | should be new RFCs, with a note added to the original RFC. Exactly what counts 179 | as a "very minor change" is up to the maintainers to decide. 180 | 181 | ## Reviewing RFCs 182 | [Reviewing RFCs]: #reviewing-rfcs 183 | 184 | While the RFC pull request is up, the maintainers may schedule meetings with 185 | the author and/or relevant stakeholders to discuss the issues in greater detail, 186 | and in some cases the topic may be discussed at a meeting. In either 187 | case a summary from the meeting will be posted back to the RFC pull request. 188 | 189 | Maintainers make final decisions about RFCs after the benefits and drawbacks 190 | are well understood. These decisions can be made at any time, but maintainers 191 | will regularly issue decisions. When a decision is made, the RFC pull request 192 | will either be merged or closed. In either case, if the reasoning is not clear 193 | from the discussion in thread, a maintainer will add a comment describing the 194 | rationale for the decision. 195 | 196 | 197 | ## Implementing an RFC 198 | [Implementing an RFC]: #implementing-an-rfc 199 | 200 | Some accepted RFCs represent vital changes that need to be implemented right 201 | away. Other accepted RFCs can represent changes that can wait until some 202 | arbitrary developer feels like doing the work. Every accepted RFC has an 203 | associated issue tracking its implementation in the Ursa JIRA issue tracker; 204 | thus that associated issue can be assigned a priority via the triage process 205 | that the team uses for all issues related to Ursa. 206 | 207 | The author of an RFC is not obligated to implement it. Of course, the RFC 208 | author (like any other developer) is welcome to post an implementation for 209 | review after the RFC has been accepted. 210 | 211 | If you are interested in working on the implementation for an "active" RFC, but 212 | cannot determine if someone else is already working on it, feel free to ask 213 | (e.g. by leaving a comment on the associated issue). 214 | 215 | 216 | ### Help this is all too informal! 217 | [Help this is all too informal!]: #help-this-is-all-too-informal 218 | 219 | The process is intended to be as lightweight as reasonable for the present 220 | circumstances. As usual, we are trying to let the process be driven by 221 | consensus and community norms, not impose more structure than necessary. 222 | 223 | 224 | [developer discussion forum]: https://chat.hyperledger.org/channel/ursa 225 | [RFC repository]: https://github.com/hyperledger/ursa-rfcs 226 | 227 | 228 | ## License 229 | [License]: #license 230 | 231 | This repository is licensed under a Create Commons [Attribution 4.0 International (CC BY 4.0)](LICENSE). 232 | It is protected by a [Developer Certificate of Origin](https://developercertificate.org/) on every commit. 233 | This means that any contributions you make must be licensed in an CC-BY-4.0-compatible 234 | way, and must be free from patent encumbrances or additional terms and conditions. By 235 | raising a PR, you certify that this is the case for your contribution. 236 | 237 | ### Contributions 238 | 239 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion 240 | in the work by you, as defined in the Create Commons [Attribution 4.0 International (CC BY 4.0)](LICENSE), 241 | shall be licensed as above, without any additional terms or conditions. 242 | -------------------------------------------------------------------------------- /text/0001-encryption-api/README.md: -------------------------------------------------------------------------------- 1 | - Feature Name: (mal000001, encryption-api) 2 | - Start Date: 6-Feb-2019 3 | - RFC PR: (leave this empty) 4 | - Ursa Issue: (leave this empty) 5 | - Version: 1 6 | 7 | # Summary 8 | [summary]: #summary 9 | 10 | Encryption is considered a primary use for cryptography which Ursa does not 11 | currently provide. There is demand for providing easy to use encryption/decryption 12 | interfaces in Ursa. Ursa already has similar interfaces for signing/verification. 13 | The implemented algorithms provide programmers choices that aim 14 | to avoid bad parameter interactions. Keys are passed around as data blobs 15 | allowing consumers to protect them as they see fit. 16 | 17 | # Motivation 18 | [motivation]: #motivation 19 | 20 | Hyperledger projects will need to be able to encrypt/decrypt data using 21 | industry standards. To minimize mistakes and allow other projects good 22 | encryption schemes, Ursa will provide known good implementations with 23 | good APIs that are simple enough to avoid confusion. This defines how software encryption 24 | APIs will be used in Ursa. Hardware interfaces may be similar but are discussed in a different RFC. 25 | 26 | # Guide-level explanation 27 | [guide-level-explanation]: #guide-level-explanation 28 | 29 | In this document, we describe a philosophy and approach for interfaces for Ursa. Our 30 | primary goals are twofold: make an interface that is easy for developers skilled in cryptography 31 | to customize, but difficult for others to misuse. To that end, we describe two sets of interfaces: 32 | 33 | **Developer Interface.** The external interface will be what the developers who are primarily 34 | focused on using cryptography (and are not cryptographic experts) see. As many details as 35 | possible will be hidden from these interfaces. 36 | It should be very difficult for people to misuse this layer and create insecure protocols. 37 | 38 | **Cryptographer Interface.** This is the internal interface that will be used by cryptographers 39 | (in all senses, both cryptography researchers and cryptography engineers). Interfaces will be 40 | flexible, but as descriptive as possible. In addition, interfaces (and protocols) will be as 41 | compos- 42 | able 43 | as possible. Our goal is to make it easy for people to choose which underlying cryptosystems 44 | to build their protocols from in this layer. 45 | It will be potentially possible for people to misuse this layer and create insecure protocols, 46 | so we want to advise that only experts tamper with these “hazardous materials. 47 | 48 | Authenticated encryption methods are strongly preferred and any other methods should be considered lower level–only used by those who know what they are doing. 49 | 50 | ## Developer Interface 51 | 52 | Our idea for the naming convention for the external interface is purely functionality-based. We 53 | will start each function with a reminder of the current cryptographic protocol being implemented 54 | in camel case. So this will be something like PublicKeyEncryptor, for a public key encryption 55 | protocol and Encryptor for symmetric key encryption. 56 | Functions belonging to each type of protocol will be listed after the designation of the protocol 57 | as snake case. For PublicKeyEncryptor, this would be things like key 58 | gen, encrypt, and decrypt. 59 | So an example interface would look like the following: 60 | 61 | # Reference-level explanation 62 | [reference-level-explanation]: #reference-level-explanation 63 | 64 | ```rust 65 | mod pk { 66 | pub enum PublicKeyEncryptorType { 67 | RSA, 68 | ElGamal 69 | } 70 | 71 | pub trait NewPublicKeyEncryptor { 72 | type PublicKeySize = ArrayLength; 73 | type PrivateKeySize = ArrayLength; 74 | 75 | fn new(publickey: GenericArray, 76 | privatekey: GenericArray) -> Self; 77 | } 78 | 79 | pub trait PublicKeyEncryptor { 80 | fn encrypt(&self, in: A) -> Result, Error>; 81 | fn encrypt_buffer(&self, in: A, out: O) -> Result<(), Error>; 82 | fn decrypt(&self, in: A) -> Result, Error>; 83 | fn decrypt_buffer(&self, in: I, out: O) -> Result<(), Error>; 84 | } 85 | 86 | pub struct Rsa2048OaepSha256 { 87 | public_key: GenericArray; 88 | private_key: GenericArray; 89 | } 90 | 91 | impl NewPublicKeyEncryptor for Rsa2048OaepSha256 { 92 | type PublicKeySize = U294; 93 | type PrivateKeySize = U2048; 94 | 95 | fn new(publickey: GenericArray, 96 | privatekey: GenericArray) -> Self { 97 | Self { 98 | publickey, 99 | privatekey 100 | } 101 | } 102 | } 103 | 104 | impl PublicKeyEncryptor for Rsa2048OaepSha256 { 105 | ... 106 | } 107 | } 108 | 109 | mod symm { 110 | pub struct Encryptor { 111 | fn new(params: EncryptorParams) -> Self; 112 | fn key_gen(&self) -> Result; 113 | 114 | fn encrypt(&self, headers: A, plaintext: A, key: &Key) -> Result, Error>; 115 | fn encrypt_buffer(&self, headers: A, in: I, out: O, key: &key); 116 | fn decrypt(&self, headers: Option<&[u8]>, in: &[u8], key: &Key) -> Result, Error>; 117 | fn decrypt_buffer(&self, headers: Option<&[u8], in: &BufReader, key: &Key, out: &BufWriter) -> Result; 118 | } 119 | } 120 | ``` 121 | 122 | In this case, PublicKeyEncryptorParams would denote pre-specified configurations of algorithms that a developer could use. For the external user, this would typically be a single, simple 123 | string and not get into the algorithmic details. As an example, there could be PublicKeyEncryptorParams::IndyDefault , which a external user would not need to know anything about. In 124 | addition, this interface would make it very easy for a user to change their implementations–only 125 | the call to the “new” function would need to be modified. 126 | 127 | ## Cryptographer Interface 128 | 129 | Internally, we will have many different algorithms used to implement the same overall cryp- 130 | tosystems. For instance, we may have both an LWE-based key exchange as well as a traditional 131 | elliptic curve-based Diffie-Hellman protocol. To do this, we will need to use slightly different 132 | naming conventions as well as exploit modularity. 133 | We propose the following naming convention: 134 | 135 | `Cryptosystem-algorithm-parameters-function` 136 | 137 | In this naming convention, cryptosystem describes the overall scheme being defined. For 138 | instance, things like “PublicKeyEncryptor,” “MAC,” and “AUTH-ENCRYPT” would all be 139 | acceptable fields here. The field “algorithm” describes the exact algorithm or paper that is being 140 | implemented. For instance, something like “bls-sig” could go here. “PARAMETERS” describes 141 | all of the relevant parameters of the scheme. This includes things like security parameters, 142 | groups, moduli sizes, and *other dependencies* such as hash functions or other primitives that are 143 | used in the construction of the overall cryptosystem. 144 | 145 | The **RustCrypto** team has implemented many traits and structs that are flexible to suite our purposes 146 | for mixing and matching to make different constructions. See [AEAD](https://github.com/RustCrypto/AEADs) 147 | and [miscreant-rs](https://github.com/miscreant/miscreant.rs) as examples of this. 148 | 149 | Note that the interface is almost exactly the same in these examples, but we need fewer parameters for the more 150 | specific function. In particular, we don’t need to provide a reference to a 128-bit blockcipher 151 | since we would be hard-coding AES into our implementation here. 152 | The idea for encryption APIs is to have many traits that can be mixed and matched to 153 | compose fixed implementations. 154 | 155 | ## Between the Two Interfaces 156 | 157 | The beauty of this kind of system is the ability to hide the internal interface behind the external 158 | one. For instance, the following describes key generation in openSSL: https://github.com/openssl/openssl/blob/master/doc/HOWTO/keys.txt. RSA and elliptic curve keys have to 159 | be generated in a completely different way. This is something that we do not want to have 160 | burden our blockchain developers, who may not be comfortable enough with cryptography to 161 | do something like this. 162 | The only difficult thing we are pushing to the general developers is the “params” when calling 163 | a new function. However, these can be explicitly defined in simple ways by cryptographers. For 164 | instance, we used the example “INDY-DEFAULT” earlier. Someone could develop a set of 165 | parameters that are the default for Indy, define them, and allow everyone else to use them in a 166 | simple call. 167 | When the “new” function is called on the external interface, it will use the “params” to pick 168 | out which protocols from the internal interface to use and create an appropriate instance. Since 169 | we can store state in our *self* object, we can keep track of the parameters here. This way, a 170 | developer that wants to change between different algorithms only has to modify the “params” on the cryptosystem description. 171 | 172 | ## Provider Architecture and Implementations 173 | 174 | # Rationale and alternatives 175 | [alternatives]: #alternatives 176 | 177 | Other libraries tie encryption methods to key objects instead of algorithm objects. 178 | The disadvantage of this model becomes apparent when multiple keys must be used for encryption 179 | and when safeguarding them. 180 | 181 | The key object model requires creating a new object then calling the encryption on the object. 182 | Our model considers keys as data blobs and only need one instance of an encryption scheme which allows any 183 | key to be passed without creating a new instance. 184 | 185 | Safeguarding should be easier where the key is a data blob that can be stored in secure locations. 186 | Key objects tend to encode more than just data when serialized. 187 | 188 | Other crypto libraries like libsodium and secp256k1 also follow this model with openssl beginning to adopt it as well. 189 | 190 | # Unresolved questions 191 | [unresolved]: #unresolved-questions 192 | 193 | - Is there a better naming scheme that we can follow for the algorithms? 194 | 195 | # Changelog 196 | [changelog]: #changelog 197 | 198 | - [2 Apr 2019] - v1 – Initial draft 199 | -------------------------------------------------------------------------------- /text/0001-encryption-api/flamacro.tex: -------------------------------------------------------------------------------- 1 | %\documentclass[orivec]{llncs} 2 | 3 | \ifodd\fullversionflag 4 | \usepackage{fullpage} 5 | \usepackage[a4paper,hmargin=2.5cm,vmargin=3cm]{geometry} 6 | %\pagestyle{headings} %comment this out in the final versions 7 | \else 8 | \fi 9 | 10 | \ifodd\fullversionflag 11 | \usepackage{amsmath,amssymb,amsfonts,amsthm} 12 | \else 13 | \usepackage{amsmath,amssymb,amsfonts} %,amsthm} 14 | \fi 15 | 16 | \usepackage{tikz} 17 | \usepackage{hyperref} 18 | \usepackage{algorithm,algorithmic,verbatim} 19 | \usepackage{thmtools, thm-restate} 20 | \usepackage{bm} 21 | \usetikzlibrary{arrows,positioning,calc,shadows,shapes.geometric, patterns, decorations.markings,backgrounds} 22 | \usepackage{comment} 23 | \usepackage{etoolbox} 24 | \usepackage{afterpage} 25 | %\usepackage{microtype} 26 | %\usepackage{subfigure} 27 | \usetikzlibrary{patterns} 28 | 29 | \newcommand{\inputtikz}[1]{\input{#1}} % comment this to remove figures 30 | %\input{tikzmacros.tikz} 31 | \newcommand{\bool}{\{0,1\}} 32 | \let\xor\oplus 33 | \let\eps\varepsilon 34 | \newcommand{\dist}{\mathtt{dist}} 35 | \newcommand{\wt}{\mathtt{weight}} 36 | \newcommand{\negl}{\mathtt{negl}} 37 | \newcommand{\appref}[1]{Appendix \ref{#1}} 38 | %\newenvironment{keywords}{ 39 | %\list{}{\advance\topsep by0.35cm\relax\small 40 | %\leftmargin=1cm 41 | %\labelwidth=0.35cm 42 | %\listparindent=0.35cm 43 | %\itemindent\listparindent 44 | %\rightmargin\leftmargin}\item[\hskip\labelsep 45 | %\bfseries Keywords:]} 46 | %{\endlist} 47 | 48 | \ifodd\fullversionflag 49 | %\newtheorem{theorem}{Theorem}%[section] 50 | %\newtheorem{definition}[theorem]{Definition} 51 | %\newtheorem{claim}[theorem]{Claim} 52 | %\newtheorem{lemma}[theorem]{Lemma} 53 | %\newtheorem{assumption}{Assumption} 54 | \else 55 | \fi 56 | \declaretheorem[name=Assumption]{assumption} 57 | \declaretheorem[name=Conjecture]{conj} 58 | \newtheorem{innercustomthm}{Assumption} 59 | \newenvironment{customassumption}[1] 60 | {\renewcommand\theinnercustomthm{#1}\innercustomthm} 61 | {\endinnercustomthm} 62 | 63 | \newcommand{\bff}[1]{\mbox{\bf #1}} 64 | \newcommand{\iseq}{\ensuremath{\stackrel{?}{=}}} 65 | \newcommand{\prob}{\mbox{\rm Pr}} 66 | \newcommand{\Exp}{\mbox{\rm Exp}} 67 | \newcommand{\Var}{\mbox{\rm Var}} 68 | %\newcommand{\ir}[0]{\xleftarrow{\$}}%{\stackrel{\mbox{\tiny R}}{\leftarrow}} 69 | \newcommand{\ir}{\gets} 70 | \newcommand{\eqdef}{\stackrel{\rm def}{=}} 71 | 72 | \newcommand{\algo}[1]{{\mbox{\sc #1}}} 73 | 74 | \newcommand{\CC}{\mathbb{C}} 75 | \newcommand{\FF}{\mathbb{F}} 76 | \newcommand{\GG}{\mathbb{G}} 77 | \newcommand{\JJ}{\mathbb{J}} 78 | \newcommand{\NN}{\mathbb{N}} 79 | \newcommand{\QQ}{\mathbb{Q}} 80 | \newcommand{\RR}{\mathbb{R}} 81 | \newcommand{\ZZ}{\mathbb{Z}} 82 | 83 | \newcommand{\G}{\mathcal{G}} 84 | \newcommand{\U}{\mathcal{U}} 85 | \newcommand{\D}{\mathcal{D}} 86 | \newcommand{\cP}{\mathcal{P}} 87 | \newcommand{\zqs}{\ZZ_q^*} 88 | 89 | \newcommand{\dlp}{{\sffamily{DLP}}} 90 | \newcommand{\ddh}{{\sffamily{DDH}}} 91 | \newcommand{\sxdh}{{\sffamily{SXDH}}} 92 | 93 | -------------------------------------------------------------------------------- /text/0001-encryption-api/hartm_macro_safe.tex: -------------------------------------------------------------------------------- 1 | %\documentclass[orivec]{llncs} 2 | 3 | \ifodd\fullversionflag 4 | \usepackage{fullpage} 5 | \usepackage[a4paper,hmargin=2.5cm,vmargin=3cm]{geometry} 6 | %\pagestyle{headings} %comment this out in the final versions 7 | \else 8 | \fi 9 | 10 | \ifodd\fullversionflag 11 | \usepackage{amsmath,amssymb,amsfonts,amsthm} 12 | \else 13 | \usepackage{amsmath,amssymb,amsfonts} %,amsthm} 14 | \fi 15 | 16 | \usepackage{tikz} 17 | \usepackage{hyperref} 18 | \usepackage{algorithm,algorithmic,verbatim} 19 | \usepackage{thmtools, thm-restate} 20 | \usepackage{bm} 21 | \usetikzlibrary{arrows,positioning,calc,shadows,shapes.geometric, patterns, decorations.markings,backgrounds} 22 | \usepackage{comment} 23 | \usepackage{etoolbox} 24 | \usepackage{afterpage} 25 | %\usepackage{microtype} 26 | %\usepackage{subfigure} 27 | \usetikzlibrary{patterns} 28 | 29 | \newcommand{\inputtikz}[1]{\input{#1}} % comment this to remove figures 30 | %\input{tikzmacros.tikz} 31 | \newcommand{\bool}{\{0,1\}} 32 | \let\xor\oplus 33 | \let\eps\varepsilon 34 | \newcommand{\dist}{\mathtt{dist}} 35 | \newcommand{\wt}{\mathtt{weight}} 36 | \newcommand{\negl}{\mathtt{negl}} 37 | \newcommand{\appref}[1]{Appendix \ref{#1}} 38 | %\newenvironment{keywords}{ 39 | %\list{}{\advance\topsep by0.35cm\relax\small 40 | %\leftmargin=1cm 41 | %\labelwidth=0.35cm 42 | %\listparindent=0.35cm 43 | %\itemindent\listparindent 44 | %\rightmargin\leftmargin}\item[\hskip\labelsep 45 | %\bfseries Keywords:]} 46 | %{\endlist} 47 | 48 | \ifodd\fullversionflag 49 | %\newtheorem{theorem}{Theorem}%[section] 50 | %\newtheorem{definition}[theorem]{Definition} 51 | %\newtheorem{claim}[theorem]{Claim} 52 | %\newtheorem{lemma}[theorem]{Lemma} 53 | %\newtheorem{assumption}{Assumption} 54 | \else 55 | \fi 56 | \declaretheorem[name=Assumption]{assumption} 57 | \declaretheorem[name=Conjecture]{conj} 58 | \newtheorem{innercustomthm}{Assumption} 59 | \newenvironment{customassumption}[1] 60 | {\renewcommand\theinnercustomthm{#1}\innercustomthm} 61 | {\endinnercustomthm} 62 | 63 | \newcommand{\bff}[1]{\mbox{\bf #1}} 64 | \newcommand{\iseq}{\ensuremath{\stackrel{?}{=}}} 65 | \newcommand{\prob}{\mbox{\rm Pr}} 66 | \newcommand{\Exp}{\mbox{\rm Exp}} 67 | \newcommand{\Var}{\mbox{\rm Var}} 68 | %\newcommand{\ir}[0]{\xleftarrow{\$}}%{\stackrel{\mbox{\tiny R}}{\leftarrow}} 69 | \newcommand{\ir}{\gets} 70 | \newcommand{\eqdef}{\stackrel{\rm def}{=}} 71 | 72 | \newcommand{\algo}[1]{{\mbox{\sc #1}}} 73 | 74 | \newcommand{\CC}{\mathbb{C}} 75 | \newcommand{\FF}{\mathbb{F}} 76 | \newcommand{\GG}{\mathbb{G}} 77 | \newcommand{\JJ}{\mathbb{J}} 78 | \newcommand{\NN}{\mathbb{N}} 79 | \newcommand{\QQ}{\mathbb{Q}} 80 | \newcommand{\RR}{\mathbb{R}} 81 | \newcommand{\ZZ}{\mathbb{Z}} 82 | 83 | \newcommand{\G}{\mathcal{G}} 84 | \newcommand{\U}{\mathcal{U}} 85 | \newcommand{\D}{\mathcal{D}} 86 | \newcommand{\cP}{\mathcal{P}} 87 | \newcommand{\zqs}{\ZZ_q^*} 88 | 89 | \newcommand{\dlp}{{\sffamily{DLP}}} 90 | \newcommand{\ddh}{{\sffamily{DDH}}} 91 | \newcommand{\sxdh}{{\sffamily{SXDH}}} 92 | 93 | -------------------------------------------------------------------------------- /text/0001-encryption-api/main.tex: -------------------------------------------------------------------------------- 1 | 2 | 3 | In this document, we describe a philosophy and approach for interfaces for Ursa. Our primary goals are twofold: make an interface that is easy for developers skilled in cryptography to customize, but difficult for others to misuse. To that end, we describe two sets of interfaces: 4 | 5 | \paragraph{Developer Interface.} The external interface will be what the developers who are primarily focused on using cryptography (and are not cryptographic experts) see. As many details as possible will be hidden from these interfaces. 6 | 7 | It should be very difficult for people to misuse this layer and create insecure protocols. 8 | 9 | \paragraph{Cryptographer Interface.} This is the internal interface that will be used by cryptographers (in all senses, both cryptography researchers and cryptography engineers). Interfaces will be flexible, but as descriptive as possible. In addition, interfaces (and protocols) will be as \emph{composable} as possible. Our goal is to make it easy for people to choose which underlying cryptosystems to build their protocols from in this layer. 10 | 11 | It will be potentially possible for people to misuse this layer and create insecure protocols, so we want to advise that only experts tamper with these ``hazardous materials.'' 12 | 13 | \section{Developer Interface} 14 | Our idea for the naming convention for the external interface is purely functionality-based. We will start each function with a reminder of the current cryptographic protocol being implemented camel case. So this will be something like PublicKeyEncryptor, for a public key encryption protocol and Encryptor for symmetric key encryption. 15 | 16 | Functions belonging to each type of protocol will be listed after the designation of the protocol as snake case. For PublicKeyEncryptor, this would be things like key\_gen, encrypt, and decrypt. So an example interface would look like the following: 17 | 18 | \begin{verbatim} 19 | pub struct PublicKeyEncryptor { 20 | fn new(params: PublicKeyEncryptorParams) -> Self; 21 | fn key_gen(&self) -> Result<(PublicKey, PrivateKey), Error>; 22 | fn encrypt(&self, pk: &PublicKey, in: &[u8]) -> Vec; 23 | fn encrypt_buffer(&self, pk: &PublicKey, in: &BufReader, out: &BufWriter); 24 | fn decrypt(&self, sk: &PrivateKey, in: &[u8]) -> Result, Error>; 25 | fn decrypt_buffer(&self, pk: &PublicKey, in: &BufReader, out: &BufWriter) -> Result; 26 | } 27 | 28 | pub struct Encryptor { 29 | fn new(params: EncryptorParams) -> Self; 30 | fn key_gen(&self) -> Result; 31 | fn encrypt(&self, headers: Option<&[u8]>, plaintext: &[u8], key: &Key) -> Vec; 32 | fn encrypt_buffer(&self, headers: Option<&[u8]>, in: &BufReader, key: &Key, out: &BufWriter); 33 | fn decrypt(&self, headers: Option<&[u8]>, in: &[u8], key: &Key) -> Result, Error>; 34 | fn decrypt_buffer(&self, headers: Option<&[u8], in: &BufReader, key: &Key, out: &BufWriter) -> Result; 35 | } 36 | \end{verbatim} 37 | 38 | In this case, PublicKeyEncryptorParams would denote pre-specified configurations of algorithms that a developer could use. For the external user, this would typically be a single, simple string and not get into the algorithmic details. As an example, there could be PublicKeyEncryptorParams::IndyDefault , which a external user would not need to know anything about. In addition, this interface would make it very easy for a user to change their implementations--only the call to the ``new'' function would need to be modified. 39 | 40 | 41 | \section{Cryptographer Interface} 42 | Internally, we will have many different algorithms used to implement the same overall cryptosystems. For instance, we may have both an LWE-based key exchange as well as a traditional elliptic curve-based Diffie-Hellman protocol. To do this, we will need to use slightly different naming conventions as well as exploit modularity. 43 | 44 | We propose the following naming convention: 45 | \begin{verbatim} 46 | Cryptosystem-algorithm-parameters-function 47 | \end{verbatim} 48 | 49 | In this naming convention, cryptosystem describes the overall scheme being defined. For instance, things like ``PublicKeyEncryptor,'' ``MAC,'' and ``AUTH-ENCRYPT'' would all be acceptable fields here. The field ``algorithm'' describes the exact algorithm or paper that is being implemented. For instance, something like ``bls-sig'' could go here. ``PARAMETERS'' describes \emph{all} of the relevant parameters of the scheme. This includes things like security parameters, groups, moduli sizes, and \emph{other dependencies} such as hash functions or other primitives that are used in the construction of the overall cryptosystem. 50 | 51 | Perhaps the best way to see how this might work is an example: OCB authenticated encryption. 52 | 53 | \begin{verbatim} 54 | 55 | pub trait AEADCipher { 56 | const NoneSize: usize; 57 | const KeySize: usize; 58 | const TagSize: usize; 59 | 60 | fn encrypt(&self, key: &[u8; Self::KeySize], nonce: &[u8; Self::NonceSize], additional_data: &[u8], data: &[u8]) -> Vec; 61 | fn encrypt_buffer(&self, key: &[u8; Self::KeySize], nonce: &[u8; Self::NonceSize], additional_data: &[u8], in: &BufReader, out: &BufReader); 62 | fn decrypt(&self, key: &[u8; Self::KeySize], nonce: &[u8; Self::NonceSize], additional_data: &[u8], data: &[u8]) -> Result, Error>; 63 | fn decrypt_buffer(&self, key: &[u8; Self::KeySize], nonce: &[u8; Self::NonceSize], additional_data: &[u8], in: &BufReader, out: &BufReader) -> Result; 64 | } 65 | 66 | pub trait StreamCipher { 67 | const KeySize: usize; 68 | const NonceSize: usize; 69 | 70 | fn init(key: &[u8; Self::KeySize], nonce: &[u8; Self::NonceSize]) 71 | fn encrypt(data: &mut [u8]) // encrypt in place 72 | fn decrypt(data: &mut [u8]) // for synchronous ciphers this is the same 73 | } 74 | 75 | pub trait BlockCipher { 76 | fn init(key: &[u8; Self::KeySize], nonce: &[u8; Self::NonceSize]) 77 | fn encrypt_block(block: &mut [u8; Self::BlockSize) //encrypt in place 78 | fn encrypt_blocks(blocks: &mut [[u8; Self::BlockSize], Self::ParallelBlocks]) //encrypt blocks in parallel 79 | fn decrypt_block(block: &mut [u8; Self::BlockSize) //decrypt in place 80 | fn decrypt_blocks(blocks: &mut [[u8; Self::BlockSize], Self::ParallelBlocks]) //decrypt blocks in parallel 81 | } 82 | 83 | pub trait OCB: AEADCipher { 84 | type Output; 85 | fn new(cipher: T) -> Self::Output; 86 | } 87 | 88 | pub trait GCM: AEADCipher { 89 | type Output; 90 | fn new(cipher: T) -> Self::Output; 91 | } 92 | 93 | pub trait NonceGenerator { 94 | gn gen_nonce(size: usize) -> Vec; 95 | } 96 | 97 | pub trait AES-128 { 98 | ... 99 | } 100 | 101 | impl NonceGenerator for E { 102 | fn gen_nonce(size: usize) -> Vec { 103 | ... 104 | } 105 | } 106 | 107 | impl NonceGenerator for E { 108 | fn gen_nonce(size: usize) -> Vec 109 | } 110 | 111 | pub trait SM4 { 112 | ... 113 | } 114 | 115 | \end{verbatim} 116 | 117 | Note that here we are building OCB with a modularized blockcipher. While modular code is nice, we might have some optimized code that is defined in the following way: 118 | 119 | \begin{verbatim} 120 | pub struct SymmetricEncryption where A: AEADCipher { 121 | } 122 | 123 | pub type AES128GCM = SymmtricEncryption>; 124 | pub type AES256OCB = SymmetricEncryption>; 125 | \end{verbatim} 126 | 127 | Note that the interface is almost exactly the same, but we need fewer parameters for the more specific function. In particular, we don't need to provide a reference to a 128-bit blockcipher since we would be hard-coding AES into our implementation here. 128 | 129 | The idea for encryption APIs is to have many traits that can be mixed and matched to compose fixed implementations. 130 | 131 | \section{Between the Two Interfaces} 132 | The beauty of this kind of system is the ability to hide the internal interface behind the external one. For instance, the following describes key generation in openSSL: \url{https://github.com/openssl/openssl/blob/master/doc/HOWTO/keys.txt}. RSA and elliptic curve keys have to be generated in a completely different way. This is something that we do not want to have burden our blockchain developers, who may not be comfortable enough with cryptography to do something like this. 133 | 134 | The only difficult thing we are pushing to the general developers is the ``params'' when calling a new function. However, these can be explicitly defined in simple ways by cryptographers. For instance, we used the example ``INDY-DEFAULT'' earlier. Someone could develop a set of parameters that are the default for Indy, define them, and allow everyone else to use them in a simple call. 135 | 136 | When the ``new'' function is called on the external interface, it will use the ``params'' to pick out which protocols from the internal interface to use and create an appropriate instance. Since we can store state in our \emph{self} object, we can keep track of the parameters here. This way, a developer that wants to change between different algorithms only has to modify the ``params'' on the cryptosystem description. 137 | 138 | 139 | \end{document} 140 | -------------------------------------------------------------------------------- /text/0002-zmix-api/README.md: -------------------------------------------------------------------------------- 1 | - Feature Name: Zmix project API and layout 2 | - Start Date: 2020-06-15 3 | - RFC PR: 4 | - Ursa Issue: 5 | - Version: 1 6 | 7 | # Summary 8 | [summary]: #summary 9 | 10 | Zmix aims to provide a common API that provide zero-knowledge proofs based on three distinct but not exclusive roles: 11 | 12 | - Issuer: any entity that issues credentials to holders. Issuers control what types of signatures to use, to whom they issue, 13 | criteria for issuance, credential validity periods, and revocation registries if desired. 14 | - Holder/Prover: any entity that obtains credentials, manages credentials or secrets, and proves to another party in zero-knowledge information about themselves or others. 15 | - Verifier: any entity that checks zero-knowledge proofs and is convinced of their truthfulness or not. 16 | 17 | # Motivation 18 | [motivation]: #motivation 19 | 20 | Ursa is beginning to have many primitives that serve to construct a la carte zero-knowledge methods. 21 | Unfortunately, there hasn't been a project plan until now for organizing and layering these primitives together. 22 | 23 | There are two ways this can be done in Rust: feature flags or subprojects. Feature flags alone become complicated 24 | as projects grow, confusing end consumers. Subprojects are great for organizing common features and code, but 25 | lines become blurred when common features surface. Zmix will use the best of both worlds. Similar to other rust projects, 26 | Zmix will subdivide primitives into subprojects and provide a top level API for easy consumption like Serde, Rand, and Rayon. 27 | 28 | Serde provides a top level API that supports the common features used for serializing and deserializing data in Rust. 29 | The exact encodings are domain specific and left up to the end user, but included in projects by specifying either features 30 | in serde or including subprojects. Zmix will be organized in a similar way. 31 | 32 | # Guide-level explanation 33 | [guide-level-explanation]: #guide-level-explanation 34 | 35 | Zero-knowledge proofs can be divided into the following categories: 36 | 37 | - Predicates: prove knowledge about statements like inequalities, ranges, and set memberships 38 | - Knowledge proofs: prove knowledge about statements like signatures and commitments. 39 | 40 | Knowledge proofs tend to center around using credentials like cryptographic signatures, proving knowledge of the signature 41 | instead of revealing it, or proving knowledge of committed values. Signatures may be generated by third-parties (Issuers) or self-attested 42 | by the Provers themselves. Credentials are signatures over 1 or more attributes or claims. Attributes may or may not be disclosed 43 | in a proof, but that is the extent of knowledge proofs. We divide signature schemes into the following groups: 44 | 45 | 1. Simple signatures where attributes or data are signed by a single signature and proved using traditional cryptographic methods (ECDSA, Ed25519, RSA). 46 | 1. Attribute-based credentials (ABC) where a credential is obtained on a set of attributes and then, according to the properties of the signature, 47 | it is possible either to prove the knowledge of a subset of the attributes ([CL02](https://groups.csail.mit.edu/cis/pubs/lysyanskaya/cl02b.pdfhttps://groups.csail.mit.edu/cis/pubs/lysyanskaya/cl02b.pdf), 48 | [BBS+](https://crypto.stanford.edu/~xb/crypto04a/groupsigs.pdf), 49 | [PS](https://eprint.iacr.org/2015/525.pdf), 50 | [CDLNT](https://eprint.iacr.org/2020/016.pdf), 51 | [FHS](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.400.8540&rep=rep1&type=pdf), blind signatures) 52 | 1. Sanitizable signatures where some attributes are modified to default values prior to presentation ([CL13](https://dl.acm.org/doi/pdf/10.1145/2484313.2484363)) 53 | 1. Unlinkable Redactable signatures where some attributes are removed prior to presentation ([CDHK](https://eprint.iacr.org/2015/580.pdf), 54 | [San20](https://eprint.iacr.org/2019/1201.pdf), 55 | SPS-EQ with set commitments [FHS14](https://eprint.iacr.org/2014/944.pdf) 56 | ) 57 | 1. ABC signatures where the user receives one credential per attribute and then combines them (aggregatable signatures [CL11](https://dl.acm.org/doi/pdf/10.1145/2046642.2046655)) 58 | 59 | Predicate proofs tend to center around proving subsets of details about attributes or data in credentials without revealing the entire 60 | value. For example, revocation can be verified against a specific registry without revealing the credential identification number, or 61 | the credential validity period can be checked by comparing the current date to the expiration date. Predicates are divided into the following groups: 62 | 63 | 1. Range proofs where a number is validated to be between an upper and lower bound. 64 | 1. Membership proofs where a value is proven against a set of elements as inclusive (value is in the set) or exclusive (value is not in the set). 65 | 1. Equality proofs where a value is tested against another value (inequality, equality of two non disclosed values). 66 | 1. Custom Circuit proofs where proofs do not fall in the previous categories, typically custom logic (zk-SNARKs or R1CS circuits). 67 | 68 | This RFC does not cover communication between Issuers, Provers, or Verifiers. 69 | 70 | ## Issuers 71 | [issuers]: #issuers 72 | Issuers publish signature verification keys to trusted oracles, (either under their control or 73 | the control of a trusted party) and manage credentials that have been issued (revoking 74 | them if incorrect data was signed or in the case of credential abuse or fraud). 75 | 76 | This RFC defines the following functions needed by Issuers: 77 | 78 | - GenerateKeys: Create digital signature keys 79 | - GenerateSign: Create a digital signature 80 | - GenerateBlindSign: Create a blind digital signature 81 | - RevokeSignature: Revoke a digital signature 82 | - UpdateKeys: Change digital signature keys to new keys or nullify to revoke 83 | - GenerateRevocationRegistry: Create a registry used for checking if a digital signature is currently valid 84 | - UpdateRevocationRegistry: Add or remove entries in a revocation registry or nullify to invalidate 85 | 86 | ## Holders 87 | [holders]: #holders 88 | 89 | Holders receive ABC credentials from Issuers, hold data, and prove statements about data to Verifiers. 90 | The data included in proofs may be from credentials received from Issuers or self-attest data. 91 | This RFC defines the functions needed by Holders: 92 | 93 | - PrepareBlindSign: Prepare data to be signed blindly by an Issuer 94 | - UnblindSignature: Unblind a blind signature received from an Issuer 95 | - GenerateSPoK: Create a zero-knowledge proof for a signature 96 | - GeneratePoCV: Create a zero-knowledge proof of committed values 97 | - GeneratePredicate: Create a predicate proof 98 | 99 | Predicates do not necessarily need to be tied to credentials to be used. 100 | 101 | ## Verifiers 102 | [verifiers]: #verifiers 103 | 104 | Verifiers validate received proofs and signatures. 105 | This RFC defines the following functions needed by Verifiers: 106 | 107 | - VerifySignature: Check if a signature is valid 108 | - VerifyProof: Verify a zero-knowledge proof: signature, commitment, and/or predicate. 109 | 110 | # Reference-level explanation 111 | [reference-level-explanation]: #reference-level-explanation 112 | 113 | Zmix defines the common top layer for Issuers, Holders, Verifiers and any other common methods used by all roles and 114 | zero-knowledge proof primitives. Each subcrate will hold only one primitive and all functionality associated therein. 115 | 116 | Below is the proposed structure 117 | 118 | ``` 119 | libzmix 120 | | 121 | --- zmix_common 122 | | 123 | --- utils 124 | errors 125 | zmix_signatures 126 | | 127 | --- bbs 128 | ps 129 | cl 130 | cdlnt 131 | zmix_accumulators 132 | | 133 | --- rsa 134 | hyperelliptic 135 | cks 136 | merkle 137 | zmix_predicates 138 | | 139 | --- bulletproofs 140 | snarks 141 | r1cs 142 | zmix_core 143 | | 144 | --- issuer 145 | holder 146 | verifier 147 | Cargo.toml 148 | ``` 149 | 150 | `common` is used for traits and logic shared across 2 or more subcrates. 151 | 152 | `core` is organized according to the three roles of the zero-knowledge protocols. This is the main crate that will be included in other projects. 153 | 154 | `signatures` are signatures that can be used to generate signature proofs of knowledge with selective disclosure proofs. 155 | Current signatures known to support this scheme are [BBS+](https://crypto.stanford.edu/~xb/crypto04a/groupsigs.pdf), [CL](https://groups.csail.mit.edu/cis/pubs/lysyanskaya/cl02b.pdfhttps://groups.csail.mit.edu/cis/pubs/lysyanskaya/cl02b.pdf), 156 | [PS](https://eprint.iacr.org/2015/525.pdf), [CDLNT](https://eprint.iacr.org/2020/016.pdf), and [delegatable credentials](https://acmccs.github.io/papers/p683-camenischA.pdf). There will be common code shared among signatures 157 | like interfaces and errors. 158 | 159 | `accumulators` are used for zero-knowledge set memberships. Current known schemes are accumulators of unknown order like 160 | [RSA](https://eprint.iacr.org/2018/1188.pdf) and [Hyperelliptic Curves](https://eprint.iacr.org/2020/196.pdf), Elliptic Curve based like [CKS](https://link.springer.com/content/pdf/10.1007%2F978-3-642-00468-1_27.pdf), and [Merkle Tree](https://eprint.iacr.org/2019/1255.pdf) based. 161 | 162 | `predicates` are proofs for testing ranges and inequalities of [numeric](https://eprint.iacr.org/2017/1066.pdf) inputs or 163 | other miscellaneous circuit based proofs like [PLONK](https://eprint.iacr.org/2019/953.pdf) or [SPARTAN](https://eprint.iacr.org/2019/550.pdf) and 164 | [Verifiable Encryption](https://www.shoup.net/papers/verenc.pdf) 165 | 166 | # Drawbacks 167 | [drawbacks]: #drawbacks 168 | 169 | Creating the initial interfaces and APIs will be challenging and may slow down progress. 170 | 171 | # Rationale and alternatives 172 | [alternatives]: #alternatives 173 | 174 | The project could be organized by rust features alone. 175 | This would have multiple drawbacks: 176 | - cfg syntax sprinkled throughout the code, 177 | - lots of combinations in Cargo.toml, 178 | - the difficulty of keeping in mind all the various features when adding or modifying code. 179 | 180 | This would make for a monolithic project that is consumable by users but requires documenting all features 181 | and complex combinations and coding for dangerous combinations. 182 | 183 | The project could be organized by just subcrates with no common API and consumers could pick and choose each one to use. 184 | The disadvantage would be code duplication across projects and the lack of a common API. 185 | 186 | # Prior art 187 | [prior-art]: #prior-art 188 | 189 | ## Good examples 190 | 191 | [Rand](https://github.com/rust-random/rand) 192 | 193 | [Crossbeam](https://github.com/crossbeam-rs/crossbeam) 194 | 195 | [RustCrypto Hashes](https://github.com/RustCrypto/hashes) 196 | 197 | [RustCrypto Encryption](https://github.com/RustCrypto/traits) 198 | 199 | [Accumulators](https://github.com/mikelodder7/accumulator-rs) 200 | 201 | ## Bad examples 202 | 203 | [libursa](https://github.com/hyperledger/ursa/blob/master/libursa/Cargo.toml) 204 | 205 | # Unresolved questions 206 | [unresolved]: #unresolved-questions 207 | 208 | # Changelog 209 | [changelog]: #changelog 210 | 211 | - [15 Jun 2020] - v1 - Initial draft 212 | -------------------------------------------------------------------------------- /text/0011-python-wrappers/README.md: -------------------------------------------------------------------------------- 1 | - Feature Name: ursa-python-wrappers 2 | - Start Date: 2018-12-19 3 | - RFC PR: 4 | - URSA Issue: 5 | 6 | # Summary 7 | [summary]: #summary 8 | 9 | A python wrapper for the URSA code base. 10 | 11 | # Motivation 12 | [motivation]: #motivation 13 | 14 | Many projects in hyperledger and others use python and having a simple and easy to use wrapper 15 | will save many developers time and effort as well as making the wrapper uniform. 16 | 17 | # Guide-level explanation 18 | [guide-level-explanation]: #guide-level-explanation 19 | 20 | 21 | The new directory structure 22 | 23 | ``` 24 | wrappers 25 | |--python 26 | |-- python3.5 27 | |-- test 28 | |-- ursa 29 | | -- bls.py 30 | |-- python3.6 31 | |-- test 32 | |-- ursa 33 | | -- bls.py 34 | 35 | 36 | ``` 37 | The python wrapper is pretty basic and simple to use. The directory structure includes python3.5 and python 3.6 since many 38 | community members have asked for 3.6 support. For now it will only include bls key data structures but it is expected that 39 | others contribute more. The test for all functions and data structures and functions will be stored in test. 40 | 41 | 42 | # Reference-level explanation 43 | [reference-level-explanation]: #reference-level-explanation 44 | 45 | This is the technical portion of the RFC. Explain the design in sufficient detail that: 46 | 47 | - Its interaction with other features is clear. 48 | - It is reasonably clear how the feature would be implemented. 49 | - Corner cases are dissected by example. 50 | 51 | The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work. 52 | 53 | # Drawbacks 54 | [drawbacks]: #drawbacks 55 | 56 | 57 | # Rationale and alternatives 58 | [rationale-and-alternatives]: #rationale-and-alternatives 59 | 60 | This will be correcting the mistakes made in indy-crypto and replace them in current indy-crypto dependent changes. 61 | 62 | # Prior art 63 | [prior-art]: #prior-art 64 | 65 | See indy-crypto/wrappers 66 | 67 | # Unresolved questions 68 | [unresolved-questions]: #unresolved-questions 69 | 70 | 71 | # Future possibilities 72 | [future-possibilities]: #future-possibilities 73 | 74 | 75 | -------------------------------------------------------------------------------- /text/cs-verifiable-encryption/README.md: -------------------------------------------------------------------------------- 1 | - Feature Name: cs-verifiable-encryption 2 | - Start Date: 2019-07-24 3 | - RFC PR: 4 | - Ursa Issue: 5 | - Version: 1 6 | 7 | # Summary 8 | [summary]: #summary 9 | 10 | [Camenisch-Shoup verifiable encryption](https://www.shoup.net/papers/verenc.pdf) is a protocol for proving "properties" 11 | about encrypted data. The "properties" are discrete log relations and the encryption is public key encryption. The party 12 | creating the ciphertext proves in zero knowledge that the ciphertext can be decrypted by the designated party. The RFC 13 | talks about 2 things, the encryption scheme itself and a protocol to prove that the encrypted data satisfies specific 14 | discrete log relation(s). The CS Verifiable Encryption is the most efficient scheme for verifiable encryption known to the author. 15 | 16 | # Motivation 17 | [motivation]: #motivation 18 | 19 | Zero Knowledge Proofs (ZKP) provide anonymity but in some cases the verifier of the ZKP agrees on provisional anonymity meaning 20 | that on pre-agreed terms, the anonymity of the prover can be broken. To break this anonymity the verifier takes the proof to a mutually 21 | trusted 3rd party who is capable of deanonymizing the prover. Hyperledger Aries will like to use this capability with their anonymous credentials. Verifiable encryption will be one of the predicates to satisfy while creating proofs from credentials. Like the way we have proof requests that say "reveal attributes `a` and `b`, prove `c` lies in `[m, n]`, prove `d` is one of these ", there will be an additional predicate "..., prove that you have encrypted attribute `e` and `f` for the auditor". The next 2 sections have details on how that will be achieved. 22 | Consider an example of an online forum where posting requires presenting a ZKP 23 | of required age from a credential that the forum (verifier) verifies. Now, the forum might have rules against posting illicit content and wants to identify the poster in such cases. The forum will thus demand that the poster in addition to presenting a ZKP of required age, also encrypts its SSN (or other government or reliable ID) **that is present in the credential** for an external auditor. In case of an illicit post, the forum can identify the poster with the auditor's help. But unless the auditor decrypts the ciphertext, the forum cannot identify the poster. 24 | Another example is of an ecommerce site that demands that the buyer has certain characteristics but does not need to learn the shipping address. The ecommerce site will request a proof from the buyer where he proves using a credential that he has the desired characteristics and correctly encrypts the shipping address **from the credential** for the shipping company. Now the ecommerce site cannot learn the address but only the shipping company can. 25 | 26 | 27 | # Guide-level explanation 28 | [guide-level-explanation]: #guide-level-explanation 29 | 30 | *Some terminology*: The entity which can decrypt the ciphertext is called *auditor*. The entity demanding a proof (ZKP) is 31 | the *verifier* and the entity creating the proof is called the *prover*. 32 | The *prover* holds 1 or more credentials and creates proof using them. The *auditor* has a public key for encryption and both the *prover* and *verifier* have access to it. This is a long term key and the *auditor* can have the same public key for several independent provers and verifiers. It is important that the public key should be unambiguously known to both the *prover* and *verifier*. One way to achieve that would be for the *auditor* to put it on a tamper evident database accessible to both the *prover* and *verifier*. A blockchain is an eligible option. Now when the *verifier* is only allowing for provisional anonymity (like in examples above), the prover while creating the ZKP, encrypts a pre-decided (between *prover* and *verifier*) attribute(s) from the credential(s) using the *auditor*'s public key. The *verifier* will now verify the ZKP and also use *auditor*'s public key to check that the pre-decided attribute(s) from the credential(s) used to create the ZKP have been encrypted and the *auditor* when asked can decrypt them. 33 | **Note**: The *prover* should never encrypt his link secret for the auditor. 34 | The verifiable encryption follows the Sigma protocol approach where the prover first creates the ciphertext of the attributes and ciphertext of blindings for those attributes. These blindings should match the ones used in the overall proof. After generating/receiving the challenge, it computes the response. The verifier will then use challnge and response to reconstruct the ciphertext over blindings and check for equality. The reason to structure it this way is for composability such that the main proving protocol should be able to use it. 35 | This verifiable encryption is meant to be treated as a predicate. 36 | The next section will describe the API of this protocol. 37 | 38 | # Reference-level explanation 39 | [reference-level-explanation]: #reference-level-explanation 40 | 41 | This protocol has been implemented in this [PR](https://github.com/hyperledger/ursa/pull/40). The PR contains tests to demonstrate how the protocol works. 42 | 43 | 1. The auditor can create his encryption keypair using `CSKeypair::new`. This method takes the maximum number of attributes that can be encrypted using the keypair. The following example creates a keypair whose public key can be used to encrypt at max 3 attributes. Trying to encrypt more will result in an error. The `CSKeypair` is an struct of 2 fields, a public key `CSEncPubkey` and a private key `CSEncPrikey`. 44 | 45 | ```rust 46 | let keypair: CSKeypair = CSKeypair::new(3)?; 47 | let pub_key: &CSEncPubkey = &keypair.pub_key; 48 | let pri_key: &CSEncPrikey = &keypair.pri_key; 49 | ``` 50 | 51 | 1. Say the prover now wants to encrypt 3 attributes. He creates a sequence of his 2 attributes uses the above keypair's public key to call `encrypt`. The `encrypt` in addition to the public key takes a `label` which is a public value and indicates the condition underwhich the ciphertext should be decrypted. The same `label` should be used while decrypting this ciphertext. The `encrypt` function returns a `CSCiphertext` if there is no error. 52 | 53 | ```rust 54 | // `serz_pub_key` is the serialized public key 55 | let pub_key: CSEncPubkey = serde_json::from_str(&serz_pub_key.unwrap()).unwrap(); 56 | let attributes = vec!["Attribute1", "Attribute2", "Attribute3"]; 57 | let ciphertext: CSCiphertext = encrypt(&attributes, "only_decrypt_when_*".as_bytes(), &pub_key)?; 58 | ``` 59 | 60 | 1. To decrypt the ciphertext from above, the auditor will use the label, ciphertext and his keys in `decrypt`. If successful, it returns the decrypted attributes 61 | 62 | ```rust 63 | // `serz_pri_key` is the serialized private key 64 | let pri_key: CSEncPrikey = serde_json::from_str(&serz_pri_key.unwrap()).unwrap(); 65 | let decrypted_messages: Vec = decrypt(label, &ciphertext, &keypair.pub_key, &pri_key)?; 66 | ``` 67 | 68 | 1. To execute the verifiable encryption protocol, prover will first either create or retrieve `blindings` for the attributes he wants to encrypt and then create the ciphertext over the attributes, over the `blindings` using `encrypt_and_prove_phase_1`. 69 | 70 | ```rust 71 | // `serz_pub_key` is the serialized public key 72 | let pub_key: CSEncPubkey = serde_json::from_str(&serz_pub_key.unwrap()).unwrap(); 73 | let (ciphertext, blindings_ciphertext, r, r_tilde) = encrypt_and_prove_phase_1( 74 | &attributes, 75 | &blindings, 76 | label, 77 | &pub_key, 78 | )?; 79 | ``` 80 | 81 | The `r` and `r_tilde` are persisted which he will use while creating the response to the challenge. 82 | The prover sends both `ciphertext` and `blindings_ciphertext` to the verifier. Incase of a non-interactive ZKP, both `ciphertext` and `blindings_ciphertext` should be hashed in the challenge. In the interactive case, the challenge will be sent by the verifier anyway. 83 | 84 | 1. When the prover receives/computes the challenge, it creates the response to it using `encrypt_and_prove_phase_2`. The challenge could have come from a verifier in case of an interactive ZKP or it could be the result of hashing all the commitments of the main proving protocol (including this one). 85 | 86 | ```rust 87 | // `serz_pub_key` is the serialized public key 88 | let pub_key: CSEncPubkey = serde_json::from_str(&serz_pub_key.unwrap()).unwrap(); 89 | let r_hat: BigNumber = encrypt_and_prove_phase_2( 90 | &r, 91 | &r_tilde, 92 | &challenge, 93 | &pub_key, 94 | Some(&mut ctx), 95 | )?; 96 | ``` 97 | 98 | 1. The verifier reconstructs the ciphertext over blindings and matches the received ciphertext over blindings using `reconstruct_blindings_ciphertext`. The `attribute_responses` in the example below is sent by the prover as part of the main protocol for all attributes. The verifier picks those that were encrypted. 99 | 100 | ```rust 101 | let pub_key: CSEncPubkey = serde_json::from_str(&serz_pub_key.unwrap()).unwrap(); 102 | let blindings_ciphertext: CSCiphertext = reconstruct_blindings_ciphertext( 103 | &ciphertext, 104 | &attribute_responses, 105 | &r_hat, 106 | &challenge, 107 | label, 108 | &pub_key, 109 | ) 110 | ``` 111 | 112 | 1. The private key `CSEncPrikey`, public key `CSEncPubkey` and ciphertext `CSCiphertext` are serializable using serde-json. 113 | 114 | # Drawbacks 115 | [drawbacks]: #drawbacks 116 | 117 | The prover should ensure that the auditor will not decrypt his attributes unless the pre-agreed terms are satisfied. If the verifier tricks the prover to encrypt his attributes for a colluding auditor then the prover's privacy is broken. Also the prover should be careful about what attributes he is encrypting and not encrypt sensitive attributes like link secret. The sensitivity of same attributes maybe different depending on the auditor. Though Ursa APIs should not (and cannot) dictate which attributes cannot be encrypted, the consumer of Ursa should take measures to prevent accidental encryption of 118 | such attributes. Eg, Hyperledger Aries can expose 2 methods for verifiably encrypting, like `ver_enc` and `ver_enc_unsafe`, `ver_enc` will not allow encrypting link secret. 119 | Another aspect for CS encryption is that it is expensive. The computations are done modulo a 4096 bit number. Also the verification and the signing key each grow by 512 bytes for each attribute that can be encrypted. Having large signing keys is undesirable when signing keys are to be kept in hardware. Having large verification keys is undesirable when they are to be stored on a storage constraint system like Bitcoin blockchain or Ethereum smart contract and force the signer to introduce a level of indirection in storage where hash of the verification key lives on the blockchain but the verification key lives on an external storage. 120 | 121 | # Rationale and alternatives 122 | [alternatives]: #alternatives 123 | 124 | - CS Verifiable Encryption offers chosen ciphertext security. 125 | - Even though the cryptographic scheme dates back to 2003, the RFC author does not know of a more efficient scheme or a 126 | more recent scheme either. 127 | - A possible but inefficient alternative is to use a generic proving system like ZK-SNARKS or Bulletproof and prove 128 | that the ciphertext can be decrypted and has the desired properties in an arithmetic circuit. The encryption scheme can 129 | be ElGamal. But the arithmetic circuit will need to have constraints for decryption which will be expensive. 130 | - No publicly implementation exists of this scheme. The [Idemix site(https://idemix.wordpress.com/) specifies a 131 | [link to the Idemix library](http://prime.inf.tu-dresden.de/idemix/) but it times out. 132 | 133 | # Prior art 134 | [prior-art]: #prior-art 135 | 136 | As the CS Verifiable Encryption paper mentions, the previous schemes do not provide chosen ciphertext 137 | security and are less efficient. Most of the content in the RFC is taken from CS Verifiable Encryption 138 | [paper](https://www.shoup.net/papers/verenc.pdf), a research report on the ["Specification of the Identity 139 | Mixer Cryptographic Library"](https://domino.research.ibm.com/library/cyberdig.nsf/papers/EEB54FF3B91C1D648525759B004FBBB1/$File/rz3730_revised.pdf), and some other [introductory](https://idemix.wordpress.com/2009/08/18/quick-intro-to-credentials/) 140 | and [architecture level](https://www.freehaven.net/anonbib/cache/idemix.pdf) documents. 141 | 142 | 143 | # Unresolved questions 144 | [unresolved]: #unresolved-questions 145 | 146 | - Please refer the [PR](https://github.com/hyperledger/ursa/pull/40) to see the concerns. 147 | -------------------------------------------------------------------------------- /text/delegatable_cdd/README.md: -------------------------------------------------------------------------------- 1 | - Feature Name: Delegatable anonymous credentials, CDD scheme 2 | - Start Date: 2019-09-06 3 | - RFC PR: (leave this empty) 4 | - Ursa PR: https://github.com/hyperledger/ursa/pull/51 5 | - Version: (use whole numbers: 1, 2, 3, etc) 6 | 7 | # Summary 8 | [summary]: #summary 9 | 10 | This is an implementation of delegatable anonymous credentials as described in 11 | the CCS 17 paper [Practical UC-Secure Delegatable Credentials with Attributes 12 | and Their Application to 13 | Blockchain](https://acmccs.github.io/papers/p683-camenischA.pdf) by Camenisch 14 | et.al. This allows issuers to delegate issuance rights to other entities such 15 | that the presentations from their issued credentials do not reveal their 16 | identities but only the identity of the the first issuer in the delegation chain. 17 | This also allows issuers at each level to add attributes in their issued 18 | credentials. However, downstream issuers in the delegation do learn about all 19 | the upstream issuers, i.e. there is no privacy among issuers. This 20 | implementation is not UC-secure but only implements the delegatable credentials 21 | from the paper. 22 | 23 | # Motivation 24 | [motivation]: #motivation 25 | 26 | Delegatable credentials are useful in saving operational costs of issuance and 27 | can also make issuance cheaper. If an organization that wants to issue 28 | credentials has only the head of the organization (or the relevant individual) 29 | issuing the credential, it becomes a bottleneck. But if the head decides to 30 | delegate the issuance rights to its subordinates, then the credential receivers 31 | can check that credential comes from a delegatee of the head. In addition, 32 | delegation provides privacy to issuers who might want to remain anonymous to 33 | verifiers. This [Aries RFC](https://github.com/hyperledger/aries-rfcs/tree/master/concepts/0104-delegatable-credentials) 34 | goes into more details of delegatable credentials. 35 | 36 | # Guide-level explanation 37 | [guide-level-explanation]: #guide-level-explanation 38 | 39 | The entity delegating the credential issuance rights and identified to the 40 | verifier is called the *root issuer* or the *root delegator*. All issuers have a 41 | signing and verification key but only the root issuer's verification key is 42 | known to the verifier. The linear structure starting at the root issuer and 43 | consisting of subsequent issuers involved in delegation is called the *issuer 44 | chain*. For reasons explained later, an issuer is either an odd-level issuer or 45 | an even-level issuer depending on its position in the issuer chain (if you 46 | find this absurd and want to immediately know the reason for this 47 | odd-even distinction, read the sub-section "Odd-Even distinction"). The *root 48 | issuer* is always an even-level issuer, since it occupies index 0 in the chain. 49 | Similarly, the linear structure starting 50 | at the root issuer's credential and consisting of subsequent issuers' 51 | credentials is called the *credential chain*. A credential is either an odd 52 | level credential or even-level credential depending on the issuer; an even-level 53 | issuer always issues an odd-level credential and vice versa. Each credential in 54 | the credential chain is also called a *link* and has a level which is a 55 | monotonically increasing number starting from 1 with no gaps. The credential 56 | (or link) issued by the root issuer has level 1 (its issued to the issuer at level 1), 57 | the subsequent link will have level 2 (its issued to the issuer at level 2), and so 58 | on. During delegation (credential issuance), the delegator, in addition 59 | to issuing a credential, sends its credential chain also to the delegatee. A 60 | presentation created from the delegated credential is called *attribute token*, 61 | the term *attribute token* comes from the paper. 62 | 63 | Because the verification keys of even-level issuers are cryptographically different 64 | from the verification keys of odd-level issuers, the verification key of even-level 65 | issuers are called even-level verification keys and of odd-level issuers are called 66 | odd-level verification keys. When an entity wants to be an issuer at both even 67 | and odd-levels, it must own two keypairs, one for odd-level and one for even 68 | level. Throughout this document and the code, the terms sigkey and verkey are 69 | used to refer to signing key and verification key. 70 | Lets look at an example. Consider an issuer chain of Alice -> Bob -> Carol -> 71 | Dave where Alice is the root issuer. Alice will issue a delegatable credential 72 | to Bob, Bob will issue a delegatable credential to Carol, Carol will issue a 73 | delegatable credential to Dave and Dave will create a presentation from his 74 | credential that will be verified by Eva. Alice is an even-level issuer who has 75 | an even-level verkey, she will issue an odd-level credential with level 1 to Bob 76 | who has an odd-level verkey and he will issue an even-level credential with 77 | level 2 to Carol who has an even-level verkey and she will issue an odd-level 78 | credential with level 3 to Dave who has an odd-level verkey. If Dave also 79 | requests credential from an odd-level issuer, he will need to have an even-level verkey 80 | (with a different secret key). 81 | During delegation, the delegator also signs the delegatee's verkey as one of the 82 | attributes of the credential. Thus the level 1 credential above (issued to Bob) 83 | will have Bob's odd-level verkey as one of the attributes, while the level 2 84 | credential issued to Carol will have Carol's even-level verkey as one of the 85 | attributes and so on. When Alice delegates to Bob, she sends one credential to 86 | Bob, say C1, when Bob delegates to Carol, he creates a new credential C2 for 87 | Carol and sends C1 in addition to C2 to Carol. Similarly when Carol will issue a 88 | credential, she will also send C1 and C2 in addition to her issued credential. 89 | 90 | ## Odd-Even distinction 91 | 92 | The reason for the distinction between odd and even-levels is the use of *structure 93 | preserving cryptography*. According to the definition in this paper [Structure-Preserving Cryptography](https://www.iacr.org/archive/asiacrypt2015/94520356/94520356.pdf), "A cryptographic scheme is called structure preserving 94 | if its all public inputs and outputs consist of group elements of bilinear 95 | groups and the functional correctness can be verified only by computing group 96 | operations, testing group membership and evaluating pairing product 97 | equations". As a result, the messages are also group elements (of G1 or G2) 98 | unlike some other schemes where the messages are elements of finite fields. The 99 | verification key will be in a different group than the message, so if the message 100 | is in G1, verification key will be in G2, and vice-versa. We saw above that 101 | the delegatee's verkey is signed as part of the delegated credential. So if the 102 | delegator has verkey in group G2, it will sign messages in group G1 which means 103 | the delegatee needs to have a verkey in group G1. Similarly when this delegatee 104 | issues a credential, it will sign the subsequent delegatee's verkey which needs 105 | to be in G2 and these alternations will continue. Two variations of Groth 106 | signatures (described in the paper) are used, the algorithms are same but one, 107 | called `Groth1`, has messages in G1 and verkey in G2 and the other, called 108 | `Groth2`, has messages in G2 and verkey in G1. Even-level issuers use Groth1 109 | signature and have verkey in group G2 while odd-level issuers use Groth2 110 | signatures and have verkey in G1. Signing key is a single field element whereas 111 | the verification key size depends linearly on the maximum number of supported 112 | attributes. It is worth mentioning that the odd/even level API is exposed as a building 113 | block and the application level code should sufficiently hide those details. eg, In the 114 | credential issuance protocol, when the credential is being requested, the requester 115 | would know at what level the issuer is and the requester's code will thus choose the 116 | keys at the appropriate level. 117 | 118 | ## API 119 | 120 | ### Groth1 and Groth2 signatures 121 | 122 | - First, some public system parameters need to be generated which are used by 123 | all system participants for generating keys, signing, verification, etc. These 124 | parameters can be generated by calling `GrothS1::setup` or `GrothS2::setup`. 125 | `setup` takes the maximum number of attributes that need to be supported. Keep 126 | it one more than the number you want to support to accommodate the public key. 127 | ```rust 128 | let max_attrs = 10; 129 | let label = "some label for generating NUMS".as_bytes(); 130 | let params1: Groth1SetupParams = GrothS1::setup(max_attrs, label); 131 | // OR for Groth2 132 | let params2: Groth2SetupParams = GrothS2::setup(max_attrs, label); 133 | ``` 134 | - Signing keys can be generated by calling `GrothS1::keygen` or `GrothS2::keygen`. Each takes the corresponding setup parameters. 135 | ```rust 136 | let (sk1: GrothSigkey, vk1: Groth1Verkey) = GrothS1::keygen(¶ms1); 137 | // OR for Groth2 138 | let (sk2: GrothSigkey, vk2: Groth2Verkey) = GrothS2::keygen(¶ms2); 139 | ``` 140 | - A new signature can be created by calling `Groth1Sig:new` or `Groth2Sig:new`. 141 | ```rust 142 | // `msgs` is a collection of elements in G1 143 | let sig: Groth1Sig = Groth1Sig::new(msgs.as_slice(), &sk1, ¶ms1)?; 144 | // OR for Groth2 145 | let sig: Groth2Sig = Groth2Sig::new(msgs.as_slice(), &sk2, ¶ms2)?; 146 | ``` 147 | - An existing signature can be randomized by calling `randomize` on the signature with a randomly chosen field element. 148 | ```rust 149 | let r = FieldElement::random(); 150 | let sig_randomized = sig.randomize(&r); 151 | ``` 152 | - 2 methods for signature verification, `verify` and `verify_batch`, both with the same API. `verify` computes several pairings to verify the signature whereas `verify_batch` does only 1 big multi-pairing. `verify_batch` has a negligibly higher probability of failure (less soundness) than `verify`. It's `O(n)/|F|` where `n` is the number of attributes and `|F|` is the order of the subgroup, `|F|` usually is > 2250. 153 | 154 | ```rust 155 | sig.verify(msgs.as_slice(), &vk, ¶ms)? 156 | // Or for fast verification 157 | sig.verify_batch(msgs.as_slice(), &vk, ¶ms)? 158 | ``` 159 | 160 | ### Issuers and delegation 161 | 162 | - Issuers are instantiated by calling `EvenLevelIssuer::new` or 163 | `OddLevelIssuer::new` by passing their level to the `new` function. Root 164 | issuers is at level 0 so can be instantiated by `EvenLevelIssuer::new(0)`. 165 | 166 | ```rust 167 | // A level 0 issuer (root issuer) 168 | let l_0_issuer = EvenLevelIssuer::new(0)?; 169 | // A level 1 issuer 170 | let l_1_issuer = OddLevelIssuer::new(1)?; 171 | // A level 2 issuer 172 | let l_2_issuer = EvenLevelIssuer::new(2)?; 173 | ``` 174 | 175 | - There is a another struct defined called `RootIssuer` which is like a proxy to 176 | `EvenLevelIssuer`. 177 | ```rust 178 | pub struct RootIssuer {} 179 | 180 | pub type RootIssuerVerkey = EvenLevelVerkey; 181 | 182 | impl RootIssuer { 183 | pub fn keygen(setup_params: &Groth1SetupParams) -> (Sigkey, RootIssuerVerkey) 184 | 185 | pub fn delegate( 186 | mut delegatee_attributes: G1Vector, 187 | delegatee_vk: OddLevelVerkey, 188 | sk: &Sigkey, 189 | setup_params: &Groth1SetupParams) -> DelgResult 190 | } 191 | ``` 192 | 193 | - Issuers generate their keys with `EvenLevelIssuer::keygen` or 194 | `OddLevelIssuer::keygen`. `GrothSigkey`, `Groth1Verkey` and `Groth2Verkey` 195 | from above are type aliased to `Sigkey`, `EvenLevelVerkey` and 196 | `OddLevelVerkey` respectively. Also the root issuer's verkey is always an 197 | `EvenLevelVerkey`, `RootIssuerVerkey` is type aliased to `EvenLevelVerkey`. 198 | 199 | ```rust 200 | // Params should be generated only once and then published in public 201 | let params1 = GrothS1::setup(max_attributes, label); 202 | let params2 = GrothS2::setup(max_attributes, label); 203 | 204 | // Even level issuer's keys 205 | let (l_even_issuer_sk: Sigkey, l_even_issuer_vk: EvenLevelVerkey) = EvenLevelIssuer::keygen(¶ms1); 206 | // Odd level issuer's keys 207 | let (l_odd_issuer_sk: Sigkey, l_odd_issuer_vk: OddLevelVerkey) = OddLevelIssuer::keygen(¶ms2); 208 | 209 | // A root issuer could either use EvenLevelIssuer::keygen for generating its keys or use RootIssuer::keygen 210 | let (root_issuer_sk: Sigkey, root_issuer_vk: RootIssuerVerkey) = RootIssuer::keygen(¶ms1); 211 | ``` 212 | 213 | - A credential is a called a link and the credentials issued by 214 | `EvenLevelIssuer`s are called `CredLinkOdd` and credentials issued by 215 | `OddLevelIssuer`s are called `CredLinkEven`. 216 | - Issuers can delegate by calling `delegate` method that takes the attributes to 217 | sign, who to delegate to resulting in a credential. The even-level credential 218 | is called `CredLinkEven` and odd-level credential is called `CredLinkOdd`. 219 | 220 | ```rust 221 | // An even-level issuer delegating to an issuer with odd-level verkey `delegatee_verkey` resulting in an odd-level credential 222 | let attributes_1: G1Vector = ....; 223 | let cred_link_1: CredLinkOdd = even_level_issuer 224 | .delegate( 225 | attributes_1.clone(), 226 | delegatee_verkey.clone(), 227 | &delegator_sigkey, 228 | ¶ms1, 229 | )?; 230 | 231 | // An odd-level issuer delegating to an issuer with even-level verkey `delegatee_verkey` resulting in an even-level credential 232 | let attributes_2: G2Vector = ....; 233 | let cred_link_2: CredLinkEven = odd_level_issuer 234 | .delegate( 235 | attributes_2.clone(), 236 | delegatee_verkey.clone(), 237 | &delegator_sigkey, 238 | ¶ms2, 239 | )?; 240 | 241 | // The root issuer can either use the `EvenLevelIssuer`'s delegate method or use the delegate function on `RootIssuer` 242 | let cred_link: CredLinkOdd = RootIssuer::delegate( 243 | attributes.clone(), 244 | delegatee_verkey.clone(), 245 | &root_issuer_sk, 246 | ¶ms1, 247 | ) 248 | ``` 249 | 250 | - A link stores its associated `level`, `attributes` and `signature`. The last 251 | element of `attributes` is the verification key of the delegatee and the 252 | signature is on `attributes`. 253 | ```rust 254 | pub struct CredLinkOdd { 255 | pub level: usize, 256 | pub attributes: G1Vector, 257 | pub signature: Groth1Sig, 258 | } 259 | ``` 260 | - To verify the correctness of link, call `verify` on it with delegator public 261 | key, delegatee public key and setup params. 262 | ```rust 263 | // For odd-level links 264 | cred_link_1.verify(&delegatee_vk, &delegator_vk, ¶ms1) 265 | // For even-level links 266 | cred_link_2.verify(&delegatee_vk, &delegator_vk, ¶ms2) 267 | ``` 268 | - The chain of credentials is kept in `CredChain` which internally has 2 lists, 269 | 1 for odd-level links and 1 for even. 270 | ```rust 271 | pub struct CredChain { 272 | pub odd_links: Vec, 273 | pub even_links: Vec, 274 | } 275 | ``` 276 | - Even or odd-level links can be added by calling `extend_with_even` or 277 | `extend_with_odd` on the chain. These methods will verify that the link has 278 | appropriate level. 279 | ```rust 280 | let mut chain_1: CredChain = CredChain::new(); 281 | // Add an odd link to chain 282 | chain_1.extend_with_odd(cred_link_1)? 283 | // Add an even link to chain 284 | chain_1.extend_with_even(cred_link_2)? 285 | ``` 286 | - To verify that all delegations are valid in the chain, call 287 | `verify_delegations` on the chain. It takes even-level and odd-level 288 | verkeys involved in the delegation. In addition to verifying each link with a call 289 | to its `verify` method, it will also check that there are no gaps or duplicate levels 290 | in the chain. 291 | ```rust 292 | chain_1 293 | .verify_delegations( 294 | vec![&level_0_issuer_vk, &level_2_issuer_vk], // even-level verkeys 295 | vec![&level_1_issuer_vk], // odd-level verkeys 296 | ¶ms1, 297 | ¶ms2 298 | )? 299 | ``` 300 | - A faster way to verify that all delegations are valid in the chain is to batch the pairing-product checks for all links using the same technique used in `verify_batch`. The method for that is `verify_delegations_batched`. This is functionally equivalent to `verify_delegations` but runs faster by negligibly dropping the soundness. Note that the method signature is same as `verify_delegations`. 301 | ```rust 302 | chain_1 303 | .verify_delegations_batched( 304 | vec![&level_0_issuer_vk, &level_2_issuer_vk], // even-level verkeys 305 | vec![&level_1_issuer_vk], // odd-level verkeys 306 | ¶ms1, 307 | ¶ms2 308 | )? 309 | ``` 310 | 311 | - `CredChain`'s size can be found out by calling `CredChain::size`. The number of 312 | odd or even links can be found by calling `CredChain::odd_size` or 313 | `CredChain::even_size`. 314 | - When only some links of the `CredChain` are needed, 315 | `CredChain::get_truncated_chain` can be called that returns a shorter chain of 316 | desired size. 317 | ```rust 318 | // Returns a shorter version of chain_1 of size 5, i.e. sum of odd and even links is 5. 319 | let chain_1_1: CredChain = chain_1.get_truncated(5)?; 320 | ``` 321 | 322 | ### Attribute tokens 323 | 324 | - Call `AttributeToken::new` with the `CredChain` and setup parameters to initialize attribute token generation. 325 | ```rust 326 | let params1: Groth1SetupParams = ...; 327 | let params2: Groth2SetupParams = ...; 328 | let chain_1: CredChain = ...; 329 | let at: AttributeToken = AttributeToken::new(&chain_1, ¶ms1, ¶ms2); 330 | ``` 331 | - Attribute tokens are generated for all levels of the given chain. To generate 332 | attribute token for a subset of the chain, first get a truncated version of 333 | the chain by calling `CredChain::get_truncated_chain` and then use that to 334 | create the attribute token. eg. if chain length is 10 and attribute token is 335 | needed for the first 5 levels of the chain, get a truncated chain with 336 | `CredChain::get_truncated_chain(5)` and then use the result in 337 | `AttributeToken::new`. 338 | ```rust 339 | let chain_1: CredChain = ...; 340 | let chain_1_1: CredChain = chain_1.get_truncated(5)?; 341 | let at: AttributeToken = AttributeToken::new(&chain_1_1, ¶ms1, ¶ms2); 342 | ``` 343 | - Attribute token generation happens in 2 phases. In the commitment phase all 344 | commitments are generated and the response phase accepts the challenge. These 345 | are intentionally decoupled so that this can be used in a higher level 346 | protocol. 347 | - To generate the commitment, call the `commitment` method with the indices of the 348 | revealed attributes at each level. The indices at each level are a set of 349 | integers. When not revealing any attributes at a level, pass an empty HashSet at 350 | that level. The `commitment` method results in an `AttributeTokenComm` object 351 | which can be converted to bytes by calling `to_bytes` so that those bytes can 352 | be used in challenge computation. Or for testing, 353 | `AttributeToken::gen_challenge` can be used that takes `AttributeTokenComm` 354 | ```rust 355 | let chain_1: CredChain = chain of size 2...; 356 | let mut at: AttributeToken = AttributeToken::new(&chain_1, ¶ms1, ¶ms2); 357 | 358 | // No attributes are revealed at any level 359 | let com_1: AttributeTokenComm = at.commitment(vec![HashSet::::new(); 2])?; 360 | 361 | // Reveal attributes 1 and 3 at 1st level, attributes 2, 3, 4 at level 2 362 | let mut revealed_attr_indices_1 = HashSet::::new(); 363 | revealed_attr_indices_1.insert(1); 364 | revealed_attr_indices_1.insert(3); 365 | 366 | let mut revealed_attr_indices_2 = HashSet::::new(); 367 | revealed_attr_indices_2.insert(2); 368 | revealed_attr_indices_2.insert(3); 369 | revealed_attr_indices_2.insert(4); 370 | let com_2: AttributeTokenComm = at 371 | .commitment(vec![ 372 | revealed_attr_indices_1.clone(), 373 | revealed_attr_indices_2.clone(), 374 | ])? 375 | 376 | // To generate bytes for adding to challenge, call `AttributeTokenComm::to_bytes` 377 | let com_2: AttributeTokenComm = ...; 378 | let bytes = com_2.to_bytes(); 379 | ``` 380 | - To generate response, call `AttributeToken::response`, passing the commitment, signing key of the entity creating the presentation, challenge and the even and odd-level verkeys. 381 | ```rust 382 | let resp_2: AttributeTokenResp = at 383 | .response( 384 | &com_2, 385 | &l_2_issuer_sk.0, 386 | &challenge, 387 | vec![&l_2_issuer_vk], 388 | vec![&l_1_issuer_vk], 389 | )? 390 | ``` 391 | - The verifier with then call `AttributeToken::reconstruct_commitment` to 392 | reconstruct the commitment that the prover would have created. He can now hash 393 | it into the challenge to compare with the prover's challenge. 394 | ```rust 395 | let L = 2; // size of delegation chain 396 | // com_2 and resp_2 are the commitment and response sent by the prover. 397 | // vec![HashSet::::new(); 2] indicates that no attributes were revealed. 398 | let recon_com_2: AttributeTokenComm = AttributeToken::reconstruct_commitment( 399 | L, 400 | &com_2, 401 | &resp_2, 402 | &challenge, 403 | vec![HashSet::::new(); 2], 404 | &root_issuer_vk, 405 | ¶ms1, 406 | ¶ms2, 407 | )?; 408 | 409 | // If attributes were revealed, like in the example above, the call would be 410 | let recon_com_2: AttributeTokenComm = AttributeToken::reconstruct_commitment( 411 | L, 412 | &com_2, 413 | &resp_2, 414 | &challenge, 415 | vec![ 416 | revealed_attr_indices_1, 417 | revealed_attr_indices_2, 418 | ], 419 | &root_issuer_vk, 420 | ¶ms1, 421 | ¶ms2, 422 | )?; 423 | ``` 424 | - Commitment computation can be sped up by using precomputation of some of the 425 | pairings. Precomputation can be done on the setup parameters which can be used 426 | for computing commitments involving any `CredChain` or it can be done on 427 | signatures as well which makes those precomputations relevant to that 428 | `CredChain` only. 429 | Thus the commitment can be created using 3 methods, either 430 | `AttributeToken::commitment` that does not accept any precomputation, 431 | `AttributeToken::commitment_with_precomputation_on_setup_params` that only 432 | accepts precomputation done on setup params (using 433 | `PrecompOnSetupParams::new`) and 434 | `AttributeToken::commitment_with_precomputation` that accepts precomputation 435 | done on setup params (using `PrecompOnSetupParams::new`) and on `CredChain` 436 | using `PrecompOnCredChain::new` 437 | 438 | ```rust 439 | // Precomputation on setup params 440 | let precomputed_setup_params: PrecompOnSetupParams = PrecompOnSetupParams::new(¶ms1, ¶ms2); 441 | 442 | // Precomputation on credential chain 443 | let precomp_sig_vals: PrecompOnCredChain = PrecompOnCredChain::new(&chain, ¶ms1, ¶ms2)?; 444 | 445 | // Computing AttributeTokenComm using PrecompOnSetupParams 446 | let at: AttributeToken = ...; 447 | let com_precomp_setup: AttributeTokenComm = at 448 | .commitment_with_precomputation_on_setup_params( 449 | vec![HashSet::::new(); i], 450 | &precomputed_setup_params, 451 | )? 452 | 453 | // Computing AttributeTokenComm using PrecompOnSetupParams and PrecompOnCredChain 454 | let com_precomp: AttributeTokenComm = at 455 | .commitment_with_precomputation( 456 | vec![HashSet::::new(); i], 457 | &precomputed_setup_params, 458 | &precomp_sig_vals, 459 | )? 460 | ``` 461 | 462 | # Reference-level explanation 463 | [reference-level-explanation]: #reference-level-explanation 464 | 465 | Most of the implemented logic follows the paper with the corrections called out 466 | in the code. 467 | At several places, computations like e(a, b)c have been replaced with 468 | e(ac, b) since they are about 30% faster. Attempts are made to 469 | replace computations in G2 with computations in G1 inside pairings. 470 | Regarding the implementation of `verify_batch` function, it applies this 471 | observation to pairings: if it needs to be checked that a == b and c == d and e 472 | == f, then choose a random number `r` and check whether (a-b) + (c-d)\*r + 473 | (e-f)\*r2 == 0. This is because this degree 2 polynomial can have at 474 | most 2 roots and if r is not a root then all the coefficients must be 0. If r is 475 | a randomly chosen element from a sufficiently large set, then the chances of r 476 | being a root are negligible. This is a slight modification of the small-exponents technique 477 | described in [Practical Short Signature Batch Verification](https://eprint.iacr.org/2008/015) 478 | In a pairing scenario if verifier had to check if e(a,b) = 1, e(c, d) = 1 and e(f, g) = 1, 479 | - pick a random value r in Zp\* and 480 | - check e(a,b) \* e(c,d)r \* e(f,g)r2 equals 1 - e(a,b) \* e(c,d)r \* e(f,g)r2 = e(a,b) \* 481 | e(cr, d) \* e(fr2, g). Exponent moved to 1st element of pairing since computation in group G1 is cheaper. 482 | - Now use a single multi-pairing rather than 3 pairings to compute e(a,b) \* 483 | e(cr, d) \* e(fr2, g) 484 | 485 | The same technique is applied to verifying all delegations in the chain in the method `verify_delegations_batched`. 486 | 487 | 488 | # Drawbacks 489 | [drawbacks]: #drawbacks 490 | 491 | This solution should not be used when privacy among issuers is desired. Secondly, 492 | since each issuer can add any attributes in its issued credential, if policies 493 | for issuance are not properly defined, malicious issuers might be able to issue 494 | credentials with unintended attributes (by the delegator) leading to privilege 495 | escalation. Also the shceme does not support blind signatures. So to add a blinded attribute in the signature, the signature should contain the blinded attribute and the prover should prove the knowledge (or other predicates) of the attribute separately, like it done for proving knowledge of secret key when the public key is embedded in the credential. 496 | 497 | # Rationale and alternatives 498 | [alternatives]: #alternatives 499 | 500 | An expensive alternative to delegatable credentials is the holder to get 501 | credential directly from the root issuer. The expensiveness of this is not just 502 | computational but operational too. 503 | There are some alternatives which offer privacy among issuers as well but have 504 | different tradeoffs. [Delegatable Attribute-based Anonymous Credentials from 505 | Dynamically Malleable Signatures](https://eprint.iacr.org/2018/340) requires 506 | the presence of a trusted third party. [Delegatable Anonymous Credentials from 507 | Mercurial Signatures](https://eprint.iacr.org/2018/923) does not support 508 | credentials with attributes. 509 | 510 | 511 | # Prior art 512 | [prior-art]: #prior-art 513 | 514 | Delegatable anonymous credentials have been explored since the last decade and 515 | the first efficient (somewhat) came in 2009 by Belenkiy et al. in "[Randomizable 516 | proofs and delegatable anonymous credentials](https://eprint.iacr.org/2008/428.pdf)". Although this was a significant 517 | efficiency improvement over previous works, it was still impractical. Chase et 518 | al. gave a conceptually novel construction of delegatable anonymous credentials 519 | in 2013 in ["Complex unary transformations and delegatable anonymous credentials"](https://eprint.iacr.org/2013/179.pdf) 520 | but the resulting construction was essentially as inefficient as that of 521 | Belenkiy et al. 522 | 523 | # Unresolved questions 524 | [unresolved]: #unresolved-questions 525 | 526 | - It is expected that the API can be more refined, e.g., it may make sense to use 527 | Rust enums for wrapping EvenLevel(Issuer/Verkey). 528 | - Should `verify` be removed in favour of `verify_batch`? 529 | - Should the credential chain support more methods? 530 | - Can the protocol be made more efficient by using recent research in structure 531 | preserving cryptography? 532 | 533 | # Changelog 534 | [changelog]: #changelog 535 | 536 | 537 | 538 | [^1]: [Structure-Preserving Cryptography](https://www.iacr.org/archive/asiacrypt2015/94520356/94520356.pdf) -------------------------------------------------------------------------------- /text/language-bindings/README.md: -------------------------------------------------------------------------------- 1 | - Feature Name: language-bindings 2 | - Start Date: 2019-03-14 3 | - RFC PR: (leave this empty) 4 | - Ursa Issue: (leave this empty) 5 | - Version: 1 6 | 7 | # Summary 8 | [summary]: #summary 9 | 10 | The Rust programming language was chosen so Ursa can be portable and 11 | consumed by multiple programming languages. This RFC details how this is 12 | to be done. 13 | 14 | # Motivation 15 | [motivation]: #motivation 16 | 17 | Hyperledger projects will want to start using Ursa. Those that use Rust 18 | will have immediate access to the library's functionality. Those projects 19 | using other programming languages will need other methods. 20 | 21 | # Guide-level explanation 22 | [guide-level-explanation]: #guide-level-explanation 23 | 24 | The Rust programming language allows exporting functions to be called 25 | from in other languages. Most programming languages can consume "C" 26 | callable libraries. This RFC covers how Ursa will enable its code to be 27 | consumable by other languages. 28 | 29 | When exporting to other languages there are two types of wrappers that 30 | can be created: thin and idiomatic. Thin wrappers are just language bindings and shall be called 31 | bindings. Example code written 32 | in Rust below will be used to illustrate the difference. 33 | 34 | ```rust 35 | pub struct Ed25519 {} 36 | 37 | impl Ed25519 { 38 | pub fn sign(message: &[u8], private_key: &[u8]) -> Vec { 39 | ... 40 | } 41 | pub fn verify(message: &[u8], public_key: &[u8], signature: &[u8]) -> bool { 42 | ... 43 | } 44 | } 45 | ``` 46 | 47 | The purpose of the wrapper is to expose `sign` and `verify`. Bindings 48 | will be the simplest method like so: 49 | 50 | ```c 51 | int ursa_bls_sign(unsigned char *signature, const unsigned long long signature_len, 52 | const unsigned char *const message, const unsigned long long message_length, 53 | const unsigned char *const private_key, const unsigned long long private_key_length); 54 | 55 | int ursa_bls_verify(const unsigned char *const message, const unsigned long long message_length, 56 | const unsigned char *const public_key, const unsigned long long public_key_length, 57 | const unsigned char *const signature, const unsigned long long signature_length); 58 | ``` 59 | 60 | The C code now exposes those two functions so C# can use them via the binding 61 | 62 | ```csharp 63 | using System; 64 | using System.Runtime.InteropServices; 65 | 66 | namespace Hyperledger.Ursa.Api 67 | { 68 | internal static class NativeMethods 69 | { 70 | [DllImport("ursa", CharSet = CharSet.Ansi)] 71 | internal static extern int ursa_bls_sign(out byte[] signature, long signature_len, 72 | byte[] message, long message_length, 73 | byte[] private_key, long private_key_length); 74 | 75 | [DllImport("ursa", CharSet = CharSet.Ansi)] 76 | internal static extern int ursa_bls_verify(byte[] message, long message_length, 77 | byte[] public_key, long public_key_length, 78 | byte[] signature, long signature_length); 79 | } 80 | } 81 | ``` 82 | 83 | Using bindings are not desirable by end users because it requires more knowledge 84 | about the native library than they perhaps want to know. It also does not allow 85 | language developers to use what they are most familiar with. However, bindings 86 | are required because they handle marshaling between the two languages. Idiomatic wrappers 87 | are written to hide the nastiness of the bindings and allow language developers to 88 | stick to what they like and are familiar with. Continuing the example above, an idiomatic 89 | wrapper can be written like this 90 | 91 | ```csharp 92 | using System; 93 | using System.Text; 94 | using System.Runtime.InteropServices; 95 | 96 | using Hyperledger.Ursa.Api; 97 | 98 | namespace Bls 99 | { 100 | public static class Bls 101 | { 102 | private const int SIGNATURE_BYTES = 32; 103 | 104 | public function byte[] Sign(string message, byte[] privateKey) 105 | { 106 | return Sign(Encoding.UTF8.GetBytes(message), private_key); 107 | } 108 | 109 | public function byte[] Sign(byte[] message, byte[] privateKey) 110 | { 111 | var signature = new byte[SIGNATURE_BYTES]; 112 | 113 | if (NativeMethods.ursa_bls_sign(out signature, SIGNATURE_BYTES, message, message.Length, privateKey, privateKey.Length) == 0) 114 | { 115 | return signature; 116 | } 117 | throw new Exception("An error occurred while signing message"); 118 | } 119 | 120 | public function bool Verify(string message, byte[] publicKey, byte[] signature) 121 | { 122 | return Verify(Encoding.UTF8.GetBytes(message), publicKey, signature); 123 | } 124 | 125 | public function bool Verify(byte[] message, byte[] publicKey, byte[] signature) 126 | { 127 | switch (NativeMethods.ursa_bls_verify(message, message.Length, 128 | privateKey, privateKey.Length, 129 | signature, signature.Length)) 130 | { 131 | case 0: return true; 132 | default: return false; 133 | } 134 | } 135 | } 136 | } 137 | ``` 138 | 139 | The idiomatic wrapper provides more logic and parameters for convenience than the thin wrapper does. 140 | It can also be expanded to include other types but ultimately maps all inputs to 141 | the expected binding types. 142 | 143 | Bindings are composed of many functions using the [foreign function interface (FFI)](https://doc.rust-lang.org/nomicon/ffi.html). 144 | 145 | # Reference-level explanation 146 | [reference-level-explanation]: #reference-level-explanation 147 | 148 | Bindings can be problematic to write by hand and maintain as APIs change. 149 | It is desirable to have bindings generated programmatically. 150 | Rust supports generating FFI using `bindgen`. `bindgen` can map to other languages like 151 | C and WASM. Thus bindings should be created and maintained as much as possible using features like `bindgen`. 152 | Bindings should be included in the Ursa project itself in a folder called `wrappers`. This will allow them to 153 | stay in-sync with any other changes to the core library. Rust also offers the [ffi-support](https://crates.io/crates/ffi-support) crate. The crate exposes 154 | Rust objects in three ways: 155 | 156 | - Serialization methods like proto or flat buffers or JSON. 157 | - HandleMaps that return handle Id's to callers 158 | - Converts between raw Rust native types to C native types. 159 | 160 | Bindings should use the best appropriate option for the given language. For example, WASM must use serialization but Python could use any of them. 161 | 162 | Idiomatic wrappers usually cannot be generated by hand as they require more in depth language experience 163 | than automatic generators can produce. Therefore, idiomatic wrappers should be written by project contributors 164 | and maintained in separate repositories. These wrappers also SHOULD include tests for interacting with 165 | native Ursa. 166 | 167 | Here are general guidelines for producing wrappers: 168 | 169 | `` should follow the naming convention as described [here](https://support.codebasehq.com/articles/tips-tricks/syntax-highlighting-in-markdown) 170 | 171 | - Bindings 172 | - Produced by code 173 | - Output into the `libursa/bindings//folder` 174 | - Idiomatic wrappers 175 | - Written by developers 176 | - Implemented as best deemed by contributors/community 177 | - Stored in separate repositories using the naming convention `ursa-wrapper-` 178 | - Keep certain things invariant 179 | - The reason is to make wrappers similar to one another, and to avoid unnecessary documentation burden or mental model translation between wrappers (which may have light doc) and ursa (where the investment in doc will be substantial). 180 | - If someone learns how to use a wrapper of the API in language 1, and then go look at the wrapper of the API in language 2, one should see the same basic concepts, and be able to predict the function names one should call and the sequence of calls one should use. 181 | - Each wrapper should preserve all the terminology of the main interface: don't change `encrypt` to `seal` or `decrypt` to `open` 182 | - All preconditions on parameters, all data formats (e.g., json, config files, etc), all constraints on input should be identical in all wrappers and in the base API. 183 | - The "level" of the wrapper API can be generally "higher" than the C-callable functions, but it should expose the same amount of functionality and flexibility as the C-callable functions, so the higher level functions, if they exist, should be an addition to lower-level ones, not substitutes for them. In other words, helpers and convenience methods are great, but don’t allow them to entirely hide the core functions which provide granular control. 184 | - The wrapper should document the earliest and latest version of ursa that it knows to be compatible. 185 | - The wrapper should document what platforms it targets, what use cases it's built for, etc. A wrapper should be able to find ursa using default OS methods (e.g., in the system PATH), but should also provide a way for a specific path to ursa to be specified, such that the wrapper can work either from an OS-wide install of ursa or a version in a particular directory. 186 | 187 | # Drawbacks 188 | [drawbacks]: #drawbacks 189 | 190 | - Some developers may want all ursa code written in the language of their needs to avoid issues presented by FFI. 191 | - Some languages cannot generate bindings yet using `bindgen`. 192 | 193 | # Prior art 194 | [prior-art]: #prior-art 195 | 196 | Languages have consumed C callable libraries for many years. Other languages have also compiled to C callable libraries like other system languages. 197 | 198 | # Unresolved questions 199 | [unresolved]: #unresolved-questions 200 | 201 | # Changelog 202 | [changelog]: #changelog 203 | 204 | - [14 Mar 2019] - v1 - Initial version 205 | -------------------------------------------------------------------------------- /text/pok-vpc/README.md: -------------------------------------------------------------------------------- 1 | - Feature Name: pok-vpc 2 | - Start Date: 2019-08-03 3 | - RFC PR: (leave this empty) 4 | - Ursa Issue: (leave this empty) 5 | - Version: 0.1 6 | 7 | # Summary 8 | [summary]: #summary 9 | 10 | This RFC describes constructing proofs of knowledge of committed values in a vector Pedersen commitment using [Schnorr protocol](https://en.wikipedia.org/wiki/Proof_of_knowledge#Schnorr_protocol). The prover is able to construct both interactive and non-interactive proofs of knowledge. The code is [here](https://github.com/hyperledger/ursa/blob/2067d0543c80eb883721863d7886d4e66f1d655d/libzmix/ps/src/pok_vc.rs). 11 | 12 | # Motivation 13 | [motivation]: #motivation 14 | 15 | Several protocols require proving knowledge of committed values in commitments. One of them is proving knowledge of messages and randomness in a vector Pedersen commitment. Such protocols then become part of larger protocols like proving knowledge of a signature or selectively revealing some of the messages in the commitment. These protocols form the basis for anonymous credentials in Hyperledger Aries. 16 | 17 | # Guide-level explanation 18 | [guide-level-explanation]: #guide-level-explanation 19 | 20 | [Schnorr protocol](https://en.wikipedia.org/wiki/Proof_of_knowledge#Schnorr_protocol) is used to prove knowledge of discrete logarithms and relations among them. So it can be used to prove knowledge of `x` in g`x` without revealing `x`. Or it can be used to prove knowledge of `x`, `y` and `z` in g1`x`g2`y`g3`z` without revealing `x`, `y` or `z`. A slight variation of the statement is to reveal that g2's exponent is `y` in g1`x`g2`y`g3`z`. This is accomplished by proving knowledge of `x` and `z` in g1`x`g3`z` and the verifier can check that product of g2`y` and g1`x`g3`z` is indeed g1`x`g2`y`g3`z`. 21 | Being able to prove such statements is important for anonymous credentials because in those the credential signature is of a form Zg1`m1`g2`m2`g3`m3`...gn`n`h`r` where `Z` is derived from signer's secret key and each of mi is a credential attribute and `r` is the randomness. There might be more elements in the signature but the aforementioned is of interest here. When using such credentials for zero knowledge proofs, the prover proves knowledge of the signature and the attributes in there. Depending on the signature scheme used, the prover randomizes the signature in a particular way before creating a proof of knowledge of the messages and signature. 22 | 23 | Interactive Schnorr protocol is 3-step, 24 | - in the first step, prover commits to some randomness and sends it to the verifier. 25 | - in 2nd step, prover gets a challenge from the verifier. 26 | - in 3rd step, prover creates a response involving the randomness, its secret and the challenge and sends to the verifier. 27 | 28 | The verifier will now check correctness of a relation involving the commitment from 1st step, challenge and response. 29 | Non interactive Schnorr protocol modifies the 2nd step. Rather than getting the challenge from the verifier, they compute the challenge by hashing the commitments from 1st step. 30 | 31 | The protocol used to prove knowledge is a generalization of the one described [here](https://www.cs.jhu.edu/~susan/600.641/scribes/lecture10.pdf), under section 3, page 5. Consider an example of prover proving knowledge of `x`, `y` and `z` in g1`x`g2`y`g3`z`. Lets call g1`x`g2`y`g3`z` as P. Only the prover knows `x`, `y` and `z` but both prover and verifier know P, g1, g2 and g3. 32 | - prover picks 3 random numbers r1, r2 and r3 (corresponding to x, y and z), creates commitment T = g1r1g2r2g3r3 and sends T to the verifier. 33 | - verifier sends challenge c to prover. 34 | - prover computes responses s1 = r1 - c*x, s2 = r2 - c*y, s3 = r3 - c*z and sends s1, s2 and s3 to verifier. 35 | - verifier checks if g1s1g2s2g3s3*Pc equals T. If it does then verifier is convinced of prover's knowledge of `x`, `y` and `z`. 36 | 37 | In the non-interactive version prover will hash g1, g2 and g3, P and T to compute challenge c. 38 | 39 | 40 | # Reference-level explanation 41 | [reference-level-explanation]: #reference-level-explanation 42 | 43 | Since the commitment can be in group G1 or G2, the proof of knowledge protocol is implemented as a macro `impl_PoK_VC`. The macro will generate 3 entities (structs), `ProverCommitting`, `ProverCommitted` and `Proof` for each group that is passed to the macro. The macro takes 5 parameters, the first 3 are identifiers for these entities and the last 2 are the group element and the group element vector respectively. 44 | 45 | ```rust 46 | macro_rules! impl_PoK_VC { 47 | ( $ProverCommitting:ident, $ProverCommitted:ident, $Proof:ident, $group_element:ident, $group_element_vec:ident ) => { 48 | ........ 49 | } 50 | ``` 51 | 52 | The macro is defined here [here](https://github.com/hyperledger/ursa/pull/46/files#diff-168ead191b84bf0856f3d153e9da3ba5R14). 53 | 54 | The following describes how the 3 entities are used. 55 | - For the 1st step (commitment), the prover first creates a `ProverCommitting` object. This object holds the generators and random values used during this step. 56 | - Prover calls `ProverCommitting::commit` for each proof of knowledge that he wishes to do. This function takes a generator (`gen`) and optionally takes a randomness. If not supplied, it creates its own. An alternate API could have exposed 2 methods, one commit method that expects a blinding and one that does not. 57 | ```rust 58 | impl $ProverCommitting { 59 | ..... 60 | pub fn commit( 61 | &mut self, 62 | gen: &$group_element, 63 | blinding: Option<&FieldElement>, 64 | ) -> usize { 65 | ...... 66 | } 67 | } 68 | ``` 69 | - Once the prover has committed for all its secrets, it calls `ProverCommitting::finish` method that results in creation of `ProverCommitted` object after consuming `ProverCommitting`. 70 | ```rust 71 | impl $ProverCommitting { 72 | ..... 73 | pub fn finish(self) -> $ProverCommitted { 74 | ...... 75 | } 76 | } 77 | ``` 78 | - `ProverCommitted` marks the end of commitment phase and has the final commitment. The commitment is created through a multi-exponentiation which is more efficient than doing one exponentiation every time `commit` is called. 79 | - Now if this is a non-interactive protocol and the prover wishes to compute the challenge, `ProverCommitted` has a method `ProverCommitted::gen_challenge` to generate the challenge by hashing all generators and commitment. It is optional to use this method as the challenge may come from a super-protocol or from verifier. It takes a vector of bytes that it includes for hashing for computing the challenge. In an interactive proof, the prover can simply receive the challenge. 80 | ```rust 81 | impl $ProverCommitted { 82 | ..... 83 | pub fn gen_challenge(&self, mut extra: Vec) -> FieldElement { 84 | ...... 85 | } 86 | } 87 | ``` 88 | - For the 3rd step, the prover calls `ProverCommitted::gen_proof` that takes the challenge (which was either computed by hashing or received from verifier) and the secrets to compute a `Proof`. 89 | ```rust 90 | impl $ProverCommitted { 91 | ..... 92 | pub fn gen_proof( 93 | self, 94 | challenge: &FieldElement, 95 | secrets: &[FieldElement], 96 | ) -> Result<$Proof, PSError> { 97 | ........ 98 | } 99 | } 100 | ``` 101 | - Now the verifier can verify the proof by calling `Proof::verify` with the Pedersen commitment 102 | ```rust 103 | impl $Proof { 104 | ..... 105 | pub fn verify( 106 | &self, 107 | bases: &[$group_element], 108 | commitment: &$group_element, 109 | challenge: &FieldElement, 110 | ) -> Result { 111 | ...... 112 | } 113 | } 114 | ``` 115 | 116 | To see an example of the above protocol, have a look at these tests for groups [G1](https://github.com/hyperledger/ursa/pull/46/files#diff-168ead191b84bf0856f3d153e9da3ba5R195) and [G2](https://github.com/hyperledger/ursa/pull/46/files#diff-168ead191b84bf0856f3d153e9da3ba5R211). 117 | The above protocol can be used in a proof of knowledge of signature as can be seen [here](https://github.com/hyperledger/ursa/blob/2067d0543c80eb883721863d7886d4e66f1d655d/libzmix/ps/src/pok_sig.rs). 118 | 119 | 120 | # Drawbacks 121 | [drawbacks]: #drawbacks 122 | 123 | Not aware of any drawback. 124 | 125 | # Rationale and alternatives 126 | [alternatives]: #alternatives 127 | 128 | - An expensive alternative is to use generic proving systems like SNARKs or Bulletproofs which allow proving much more complex relations. 129 | - If we decided not to use Interactive ZKP ever, we can utilize [Merlin](https://github.com/dalek-cryptography/merlin) for managing the transcript. 130 | 131 | 132 | # Prior art 133 | [prior-art]: #prior-art 134 | 135 | - Projects like [libscapi](https://github.com/cryptobiu/libscapi) and [schnorr-nizk](https://github.com/adjoint-io/schnorr-nizk) provide examples of how to do interactive and non-interactive protocols respectively. 136 | 137 | 138 | # Unresolved questions 139 | [unresolved]: #unresolved-questions 140 | 141 | - Should similar macros exists with logic for doing different kinds of Schnorr protocols and their composition. 142 | 143 | -------------------------------------------------------------------------------- /text/ps-signatures/README.md: -------------------------------------------------------------------------------- 1 | - Feature Name: ps-signatures 2 | - Start Date: 2019-08-08 3 | - RFC PR: (leave this empty) 4 | - Ursa Issue: (leave this empty) 5 | - Version: 0.1 6 | 7 | # Summary 8 | [summary]: #summary 9 | 10 | Pointcheval-Sanders signature scheme from the paper [Short Randomizable signatures](https://eprint.iacr.org/2015/525) with protocol for proof of knowledge of signature. A user can get signature on known or committed messages from the signer and then prove knowledge of signature and optionally reveal some messages under the signature. Implementation in this [PR](https://github.com/hyperledger/ursa/pull/46). This feature depends on the [PR](https://github.com/hyperledger/ursa-rfcs/pull/10) for RFC for proof of knowledge of committed messages in a commitment. 11 | 12 | # Motivation 13 | [motivation]: #motivation 14 | 15 | Anonymous credentials consists of issuer's signature over credential attributes with the property that it is efficient to prove knowledge of signature without revealing the signature itself. Additionally, it should be possible to reveal some of the attributes of the credential to the verifier. Anonymous credentials are needed in Hyperledger Aries. 16 | 17 | # Guide-level explanation 18 | [guide-level-explanation]: #guide-level-explanation 19 | 20 | There are 3 mainly entities in anonymous credentials, the *issuer* which signs a credential (a vector of attributes) and gives the signature to the *holder* which then uses the signature to prove its knowledge to a *verifier* without revealing the signature. The issuer might not know all the attributes it is signing and the holder might have only given a commitment to those attributes. In this case, the issuer gives a multi-message blind signature to the holder which the holder can unblind. The issuer owns a signing key and a verification key. The verification key is published so that it is accessible by the holder and verifier. The verification key is meant to support a certain number of messages only meaning that a verification key intended to be used for verifying signature over a vector of 5 messages cannot be used to verify signature over 4 or 6 messages. 21 | - `SignatureGroup` and `OtherGroup` are 2 type aliases that can refer to groups G1 and G2 or groups G2 and G1 depending on whether feature `PS_Signature_G2` or `PS_Signature_G1` is enabled. These features are mutually exclusive. The `SignatureGroup` is the group for the elements of `Signature` or `Sigkey`. `Verkey` contains elements of both groups. 22 | - All participants in the system have access to parameters from random oracle which are present in `Params`. The method accepts a label that is hashed to create parameters. 23 | ```rust 24 | let params: Params = Params::new("some label".as_bytes()); 25 | ``` 26 | - The signer calls the `keygen` method to create a 2-tuple of signing key and verification key (`Verkey`, `Sigkey`). The method takes the number of messages to support and system parameters. The size of `Sigkey` and `Verkey` grows linearly with the number of messages that have to be supported. 27 | ```rust 28 | pub fn keygen(count_messages: usize, params: &Params) -> (Verkey, Sigkey) 29 | ``` 30 | - To create blind signatures, signer and user both need to have access to a blinding key `BlindingKey`. It is created by the signer using the signing key. The signer can omit creation (and publishing) of this key if he never intends to sign blind signatures. 31 | ```rust 32 | let (verkey, sigkey) = keygen(count_msgs, ¶ms); 33 | let blinding_key:BlindingKey = BlindingKey::new(&sigkey, ¶ms); 34 | ``` 35 | - The signer can create a new signature on a collection of known messages using `Signature::new`. The number of messages should be compatible with the provided `Sigkey`. Regardless of the number of messages being signed, the signature always consists of 2 group elements. 36 | ```rust 37 | impl Signature { 38 | pub fn new( 39 | messages: &[FieldElement], 40 | sigkey: &Sigkey, 41 | params: &Params, 42 | ) -> Result 43 | } 44 | ``` 45 | Refer test [test_signature_all_known_messages](https://github.com/hyperledger/ursa/pull/46/files#diff-6cb154fe72e95313cfe9016f86d71e73R122) 46 | - The signer can create a new blind signature on a collection of known and blinded messages using `BlindSignature::new`. This method accepts a Pedersen commitment (`commitment` below) to the committed messages created by the holder and the collection of known messages. Note that the commitment could be for several messages. This method **must** only be used if there is one or more blinded messages. 47 | ```rust 48 | impl BlindSignature { 49 | pub fn new( 50 | commitment: &SignatureGroup, 51 | messages: &[FieldElement], 52 | sigkey: &Sigkey, 53 | blinding_key: &BlindingKey, 54 | params: &Params, 55 | ) -> Result 56 | } 57 | ``` 58 | The signer should verify that the commitment is well formed by executing a proof of knowledge protocol as described in the test [test_signature_blinded_messages](https://github.com/hyperledger/ursa/pull/46/files#diff-d55856d1eb6560e1b74d9b6f2a45acabR200). 59 | - Once a holder has received a blind signature created with the `BlindSignature::new` method, he unblinds the signature with `Signature::unblind`. For this the holder must have the randomness he used in the commitment he sent to the issuer. 60 | ```rust 61 | impl BlindSignature { 62 | pub fn unblind(sig: &Signature, blinding: &FieldElement) -> Signature 63 | } 64 | ``` 65 | - To verify a signature, `Signature::verify` must be used. It takes the messages over which the signature is created. 66 | ```rust 67 | impl Signature { 68 | pub fn verify(&self, messages: &[FieldElement], verkey: &Verkey, params: &Params) -> Result 69 | } 70 | ``` 71 | Refer tests [test_signature_many_blinded_messages](https://github.com/hyperledger/ursa/pull/46/files#diff-6cb154fe72e95313cfe9016f86d71e73R151) and [test_signature_known_and_blinded_messages](https://github.com/hyperledger/ursa/pull/46/files#diff-6cb154fe72e95313cfe9016f86d71e73R171) for the unblinding an verification of signature. 72 | - To prove knowledge of the signature, `PoKOfSignature` is used. The protocol has 2 phases, in the pre-challenge phase, the signature is transformed to an aggregate signature and a PoK of the underlying multi-message is created using `PoKOfSignature::init`. `revealed_msg_indices` specifies the indices of messages that are revealed to the verifier and hence do not need to be included in the proof of knowledge. 73 | `blindings` specifies randomness to be used while proving knowledge of the unrevealed messages in the signature. If `blindings` is `None`, a random field element is generated corresponding to each unrevealed message. If `blindings` is to be provided, it must be provided for all unrevealed messages. This parameter is useful when the knowledge of same message is being proved in another relation as well and it needs to be proved that message is same in both relations, eg. If there are 2 signatures whose knowledge is being proved and it also needs to be proven that a specific message under both signatures is equal, then in both proof of knowledge protocols, the same blinding factor must be used for that message. The test `test_PoK_multiple_sigs_with_same_msg` demonstrates that. Another use case can be of proving that signature contains a message present in another Pedersen commitment. 74 | ```rust 75 | impl PoKOfSignature { 76 | pub fn init( 77 | sig: &Signature, 78 | vk: &Verkey, 79 | params: &Params, 80 | messages: &[FieldElement], 81 | blindings: Option<&[FieldElement]>, 82 | revealed_msg_indices: HashSet, 83 | ) -> Result 84 | } 85 | ``` 86 | - After the challenge is generated (or received in case of an interactive protocol), `PoKOfSignature::gen_proof` is used to create the proof `PoKOfSignatureProof`. 87 | ```rust 88 | impl PoKOfSignature { 89 | pub fn gen_proof(self, challenge: &FieldElement) -> Result 90 | } 91 | ``` 92 | - The verifier can then verify the proof using `PoKOfSignatureProof::verify`. 93 | ```rust 94 | impl PoKOfSignatureProof { 95 | pub fn verify( 96 | &self, 97 | vk: &Verkey, 98 | params: &Params, 99 | revealed_msgs: HashMap, 100 | challenge: &FieldElement, 101 | ) -> Result 102 | } 103 | ``` 104 | Refer the tests [test_PoK_sig](https://github.com/hyperledger/ursa/pull/46/files#diff-d55856d1eb6560e1b74d9b6f2a45acabR252) and [test_PoK_sig_reveal_messages](https://github.com/hyperledger/ursa/pull/46/files#diff-d55856d1eb6560e1b74d9b6f2a45acabR276) for the proof of knowledge of signature and proof of knowledge of signature with revealing some messages respectively. 105 | - Another test that shows a more elaborate scenario where a signature is requested on a mix of known and committed messages and then the knowledge of that signature is proved in addition to revealing some messages is shown in test [test_scenario_1](https://github.com/hyperledger/ursa/pull/46/files#diff-3b79c2d1f6accb7035421822bd62d6c6R10). 106 | 107 | # Reference-level explanation 108 | [reference-level-explanation]: #reference-level-explanation 109 | 110 | The default feature is `PS_Signature_G2` meaning signatures are in group G2. 111 | This makes signing expensive but proof of knowledge efficient since 112 | proof of knowledge of signatures will involve a multi-exponentiation in group G1. With feature `PS_Signature_G1`, signature is in group G1 but proof of knowledge of signatures will involve a multi-exponentiation in group G2 which is more expensive. The reason for making `PS_Signature_G2` default is that it is expected that signing is a less common occurence than proof of knowledge of signature. If signing was a equally common like one time use signature or it was critical to keep signatures short and signing more efficient, then feature `PS_Signature_G1` should be used. 113 | The implementation that the RFC is describing is the implementation of sections 4.2, 6.1 and 6.2 of the [PS signatures paper](https://eprint.iacr.org/2015/525) and an attempt has been made to use the same symbol names in the code as used in the paper. 114 | The signature scheme from section 4.2 does not allow blind signatures straightaway and the paper does not describe any technique to do so. But less efficient techniques from Coconut or others can be used. The scheme is implemented as described in the paper. 115 | The signature scheme from section 6.1 of the paper allows for signing blinded messages as well. 2 variation of scheme in section 6.1 are implemented, one of the variations follows the paper with the enhancement being the support of un-blinded (signer-known) messages and is seen in `BlindSignature::new_from_paper`. It works as: 116 | - Say the verification key supports 5 messages, the relevant generators are Y1, Y2, Y3, Y4, Y5. 117 | - The holder wants to reveal only last 3 message to the issuer but commits to the first 2 messages in a commitment C = gtY1m1Y2m2 (t is the randomness and should be preserved for unblinding the sig) and sends C to the issuer (along with a proof of knowledge). 118 | - The issuer now creates D = C * Y3m3Y4m4Y5m5 where m3, m4 and m5 are known to him. The issuer will now choose a random u and create the signature (gu, (XD)u) as described in the paper. 119 | - The holder will unblind the signature as described in the paper. 120 | 121 | But another variations implemented with some modifications and is seen in ``BlindSignature::new`. The public key is split into 2 parts, the 122 | tilde elements (X_tilde and Y_tilde) and non-tilde elements (X, Y). Now the verifier only needs the former 123 | (tilde elements) and thus verifier's storage requirements go down. Keygen and signing are modified as: 124 | - Keygen: Rather than only keeping X as the secret key, signer keeps x, y_1, y_2, ..y_r as secret key. 125 | The public key is unchanged, i.e. (g, Y_1, Y_2,..., Y_tilde_1, Y_tilde_2, ...) 126 | - Sign: Lets say the signer wants to sign a multi-message of 10 messages where only 1 message is blinded. 127 | If we go by the paper where signer does not have y_1, y_2, .. y_10, signer will pick a random u and compute signature as 128 | (g^u, (XC)^u.Y_2^{m_2*u}.Y_3^{m_3*u}...Y_10^{m_10*u}), Y_1 is omitted as the first message was blinded. Of course the term 129 | (XC)^u.Y_2^{m_2*u}.Y_3^{m_3*u}...Y_10^{m_10*u} can be computed using efficient multi-exponentiation techniques but it would be more efficient 130 | if the signer could instead compute (g^u, C^u.g^{(x+y_2.m_2+y_3.m_3+...y_10.m_10).u}). The resulting signature will have the same form 131 | and can be unblinded in the same way as described in the paper. 132 | This will make signer's secret key storage a bit more but will make the signing becomes more efficient, especially in cases 133 | where the signature has only a few blinded messages but most messages are known to the signer which is usually the case with 134 | anonymous credentials where the user's secret key is blinded (its not known to signer) in the signature. This variation makes 135 | signing considerably faster unless the no of unblinded messages is very small compared to no of blinded messages. 136 | Run test `timing_comparison_for_both_blind_signature_schemes` to see the difference 137 | 138 | Some implementation optimizations have been done as well like the use of multi-pairings or multi-exponentiations (both constant and variable time). The PoK protocol for Pedersen commitments used is described in this [RFC](https://github.com/hyperledger/ursa-rfcs/pull/10). PS signatures require type-3 pairings. 139 | 140 | The `PoKOfSignature` is based on section 6.2 of the paper and the implementation follows the paper almost as-it-is. However, the product of multiple pairings is replaced with a multi-pairing for efficiency. The paper specifies the check as e(sigma1, X_tilde) * e(sigma1, Y_tilde1)m1...e(sigma1, g_tilde)t == e(sigma2, g_tilde). This is transformed into the check e(sigma1, X_tilde * Y_tilde1m1 * ...g_tildet) == e(sigma2, g_tilde). This check is transformed to e(sigma1, X_tilde * Y_tilde1m1 * ...g_tildet) * e(sigma2, g_tilde)-1 == 1. Now this can be combined into one multi-pairing. The proof of knowledge (symbol pie in the paper) is done using [this protocol](https://github.com/hyperledger/ursa/pull/46/files#diff-168ead191b84bf0856f3d153e9da3ba5R14). 141 | 142 | 143 | # Drawbacks 144 | [drawbacks]: #drawbacks 145 | 146 | This scheme is based on the LRSW Assumption which was introduced in [1] and proven secure in the generic group model in [2] but this assumption is not popular. 147 | 148 | # Rationale and alternatives 149 | [alternatives]: #alternatives 150 | 151 | - This is meant to be one of the supported signature schemes for anonymous credentials. 152 | - BBS+ is another signature scheme to be supported but PS signatures can be used to build threshold signatures using Coconut or others. 153 | 154 | 155 | # Prior art 156 | [prior-art]: #prior-art 157 | 158 | The RFC author is not aware of any implementation (open or closed source) of PS signatures. 159 | 160 | # Unresolved questions 161 | [unresolved]: #unresolved-questions 162 | 163 | - It is expected that proof of knowledge of signature API will be refined further through broader discussion. 164 | - Proving properties about signed messages (range proof) or relationships among signed messages (equality, inequality) has been considered out of scope. 165 | - Is the LRSW Assumption acceptable? 166 | 167 | # Changelog 168 | [changelog]: #changelog 169 | 170 | - 171 | 172 | 173 | # References 174 | [1] Anna Lysyanskaya, Ronald L. Rivest, Amit Sahai, and Stefan Wolf. Pseudonym systems. In Howard M. 175 | Heys and Carlisle M. Adams, editors, SAC 1999, volume 1758 of LNCS, pages 184–199. Springer, 176 | August 2000. 177 | [2] Victor Shoup. Lower bounds for discrete logarithms and related problems. In Walter Fumy, editor, 178 | EUROCRYPT’97, volume 1233 of LNCS, pages 256–266. Springer, May 1997. 179 | --------------------------------------------------------------------------------