├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── amcl ├── Cargo.toml └── src │ ├── aes.rs │ ├── arch.rs │ ├── bls381 │ ├── big.rs │ ├── dbig.rs │ ├── ecdh.rs │ ├── ecp.rs │ ├── ecp2.rs │ ├── fp.rs │ ├── fp12.rs │ ├── fp2.rs │ ├── fp4.rs │ ├── mod.rs │ ├── mpin.rs │ ├── pair.rs │ └── rom.rs │ ├── gcm.rs │ ├── hash256.rs │ ├── hash384.rs │ ├── hash512.rs │ ├── lib.rs │ ├── main.rs │ ├── nhs.rs │ ├── rand.rs │ └── sha3.rs ├── docs ├── VerifiableCredentials.md ├── flow-diagram.png ├── flow.puml └── zklang_proof_spec.json ├── src ├── commitments │ ├── mod.rs │ └── pedersen_BLS12_381.rs ├── ffi │ └── mod.rs ├── hash_functions │ ├── bls12_381_hash.rs │ └── mod.rs ├── lib.rs ├── prf │ └── mod.rs ├── signatures │ └── mod.rs ├── utils │ ├── mod.rs │ └── random.rs └── zkl │ ├── mod.rs │ └── spec.rs └── wrappers ├── dotnet └── PLACEHOLDER.md ├── golang └── PLACEHOLDER.md ├── ios └── PLACEHOLDER.md ├── java ├── android │ └── PLACEHOLDER.md └── jna │ └── PLACEHOLDER.md ├── nodejs └── PLACEHOLDER.md └── python3 └── PLACEHOLDER.md /.gitignore: -------------------------------------------------------------------------------- 1 | cargo-registry 2 | target 3 | build 4 | .idea 5 | *.iml 6 | .venv 7 | .cache 8 | .DS_Store 9 | **/*.rs.bk 10 | Cargo.lock 11 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "z-mix" 3 | version = "0.1.0" 4 | authors = ["Michael Lodder "] 5 | license = "Apache-2.0" 6 | 7 | [lib] 8 | name = "zmix" 9 | crate-type = ["rlib", "staticlib", "cdylib"] 10 | 11 | [dependencies] 12 | amcl = { path = "./amcl" } 13 | serde_json = "1.0.26" 14 | rand = "0.5.3" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lab Name 2 | z-mix 3 | 4 | # Short Description 5 | z-mix will offer a generic way to create Zero-Knowledge proofs, proving statements about multiple cryptographic building blocks, containing signatures, commitments, and verifiable encryption. 6 | z-mix facilitates 7 | 8 | # Scope of Lab 9 | The goal of z-mix is to become a part of Hyperledger crypto-lib, and eventually be adopted by Hyperledger projects. Multiple existing Hyperledger projects require Zero-Knowledge proofs, e.g., Fabric and Indy. The goal of this library is to provide a single flexible and secure implementation to construct such proofs. 10 | z-mix is a C callable library but there are also convenience wrappers for various programming languages. 11 | 12 | # Initial Committers 13 | * Manu Drijvers (manudrijvers) 14 | * Jan Camenisch (jancamenisch) 15 | * Nathan George (nage) 16 | * Daniel Hardman (dhh1128) 17 | * Angelo De Caro (adecaro) 18 | * Maria Dubovitskaya (dubovitskaya) 19 | * Jason Law (jasonalaw) 20 | * Michael Lodder (mikelodder7) 21 | * Lovesh Harchandani (lovesh) 22 | 23 | # Sponsors 24 | * Nathan George 25 | * Hart Montgomery 26 | 27 | # Spec 28 | z-mix uses JSON objects to provide a *zero knowledge language (ZKL)* to express 29 | 30 | * Requests of attested attribute values 31 | * Resolutions for requests that can be validated 32 | * Proofs that satisfy requests 33 | 34 | ### Process 35 | z-mix translates a ZKL-ProofSpec and a corresponding ZKL-Witness, both represented as JSON objects, into a ZKL-Proof JSON object. 36 | 37 | The **ZKL-ProofSpec** defines the statement to be proven and contains all public information needed by a verifier \[e.g., Credential Definitions, Revocation Authority, Pseudonyms]. 38 | 39 | The **ZKL-Witness** contains the secrets required to compute a proof \[e.g. secret keys, all attribute values, the credentials involved, the randomness used to compute a pseudonym]. 40 | 41 | The **ZKL Proof** is the data that satisfies the statement to be proven. 42 | 43 | ### Examples 44 | 45 | z-mix is written in Rust. z-mix can be included into other Rust projects by adding the following to the Cargo.toml: 46 | 47 | ```toml 48 | z_mix = { version = "0.1", git = "https://github.com/hyperledger-labs/z-mix.git" } 49 | ``` 50 | 51 | An example how to use in your rust project 52 | 53 | ```rust 54 | extern crate z_mix; 55 | 56 | use z_mix::zkl::{Parser, ProofSpecBuilder, WitnessBuilder}; 57 | 58 | fn main() { 59 | let mut proof_spec_builder = ProofSpecBuilder::new(); 60 | 61 | // Add proof spec data 62 | 63 | let mut witness_builder = WitnessBuilder::new(); 64 | 65 | // Add witness data 66 | 67 | let proof_spec = proof_spec_builder.finish(); 68 | let witness = witness_builder.finish(); 69 | 70 | match Parser::parse(&proof_spec, &witness) { 71 | Ok(proof) => { 72 | match proof.verify(&proof_spec) { 73 | Ok(v) => println!("Proof result - {}", v), 74 | Err(pe) => panic!("Proof::verify encountered an error - {:?}", pe) 75 | } 76 | }, 77 | Err(e) => panic!("Parser::parse encountered an error - {:?}", e) 78 | }; 79 | } 80 | ``` 81 | -------------------------------------------------------------------------------- /amcl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "amcl" 3 | version = "0.1.0" 4 | authors = ["lovesh harchandani "] 5 | workspace = ".." 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /amcl/src/arch.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | pub type Chunk=i64; 21 | pub type DChunk=i128; 22 | pub const CHUNK:usize=64; 23 | -------------------------------------------------------------------------------- /amcl/src/bls381/dbig.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | use arch; 21 | use bls381::big; 22 | use bls381::big::BIG; 23 | use arch::Chunk; 24 | 25 | //#[derive(Copy, Clone)] 26 | pub struct DBIG { 27 | pub w: [Chunk; big::DNLEN] 28 | } 29 | 30 | impl DBIG { 31 | pub fn new() -> DBIG { 32 | DBIG { 33 | w: [0; big::DNLEN as usize] 34 | } 35 | } 36 | 37 | pub fn new_copy(y:&DBIG) -> DBIG { 38 | let mut s= DBIG::new(); 39 | for i in 0..big::DNLEN {s.w[i]=y.w[i]} 40 | return s; 41 | } 42 | 43 | pub fn new_scopy(x:&BIG) -> DBIG { 44 | let mut b= DBIG::new(); 45 | for i in 0 ..big::NLEN { 46 | b.w[i]=x.w[i]; 47 | } 48 | b.w[big::NLEN-1]=x.get(big::NLEN-1)&big::BMASK; /* top word normalized */ 49 | b.w[big::NLEN]=x.get(big::NLEN-1)>>big::BASEBITS; 50 | 51 | for i in big::NLEN+1 ..big::DNLEN {b.w[i]=0} 52 | return b; 53 | } 54 | 55 | /* split DBIG at position n, return higher half, keep lower half */ 56 | pub fn split(&mut self,n: usize) -> BIG 57 | { 58 | let mut t=BIG::new(); 59 | let m=n%big::BASEBITS; 60 | let mut carry=self.w[big::DNLEN-1]<<(big::BASEBITS-m); 61 | 62 | for i in (big::NLEN-1..big::DNLEN-1).rev() { 63 | let nw=(self.w[i]>>m)|carry; 64 | carry= (self.w[i]<<(big::BASEBITS-m))&big::BMASK; 65 | t.set(i+1-big::NLEN,nw); 66 | } 67 | self.w[big::NLEN-1]&=((1 as Chunk)<>(big::BASEBITS-n)); 77 | for i in (m+1..big::DNLEN-1).rev() { 78 | self.w[i]=((self.w[i-m]<>(big::BASEBITS-n)); 79 | } 80 | 81 | self.w[m]=(self.w[0]<>n)|((self.w[m+i+1]<<(big::BASEBITS-n))&big::BMASK); 91 | } 92 | self.w[big::DNLEN-m-1]=self.w[big::DNLEN-1]>>n; 93 | for i in big::DNLEN - m ..big::DNLEN {self.w[i]=0} 94 | } 95 | 96 | /* Copy from another DBIG */ 97 | pub fn copy(&mut self,x: &DBIG) { 98 | for i in 0 ..big::DNLEN { 99 | self.w[i]=x.w[i]; 100 | } 101 | } 102 | 103 | pub fn ucopy(&mut self,x: &BIG) { 104 | for i in 0 ..big::NLEN { 105 | self.w[i]=0; 106 | } 107 | for i in big::NLEN ..big::DNLEN { 108 | self.w[i]=x.w[i-big::NLEN]; 109 | } 110 | } 111 | 112 | pub fn cmove(&mut self,g:&DBIG,d: isize) { 113 | let b=-d as Chunk; 114 | for i in 0 ..big::DNLEN { 115 | self.w[i]^=(self.w[i]^g.w[i])&b; 116 | } 117 | } 118 | 119 | /* self+=x */ 120 | pub fn add(&mut self,x:&DBIG) { 121 | for i in 0 ..big::DNLEN { 122 | self.w[i]+=x.w[i]; 123 | } 124 | } 125 | 126 | /* self-=x */ 127 | pub fn sub(&mut self,x:&DBIG) { 128 | for i in 0 ..big::DNLEN { 129 | self.w[i]-=x.w[i]; 130 | } 131 | } 132 | 133 | /* self=x-self */ 134 | pub fn rsub(&mut self,x:&DBIG) { 135 | for i in 0 ..big::DNLEN { 136 | self.w[i]=x.w[i]-self.w[i]; 137 | } 138 | } 139 | 140 | 141 | /* Compare a and b, return 0 if a==b, -1 if ab. Inputs must be normalised */ 142 | pub fn comp(a: &DBIG,b: &DBIG) -> isize { 143 | for i in (0 ..big::DNLEN).rev() { 144 | if a.w[i]==b.w[i] {continue} 145 | if a.w[i]>b.w[i] {return 1} 146 | else {return -1} 147 | } 148 | return 0; 149 | } 150 | 151 | /* normalise BIG - force all digits < 2^big::BASEBITS */ 152 | pub fn norm(&mut self) { 153 | let mut carry=0 as Chunk; 154 | for i in 0 ..big::DNLEN-1 { 155 | let d=self.w[i]+carry; 156 | self.w[i]=d&big::BMASK; 157 | carry=d>>big::BASEBITS; 158 | } 159 | self.w[big::DNLEN-1]+=carry 160 | } 161 | 162 | /* reduces self DBIG mod a BIG, and returns the BIG */ 163 | pub fn dmod(&mut self,c: &BIG) -> BIG { 164 | let mut k=0; 165 | self.norm(); 166 | let mut m=DBIG::new_scopy(c); 167 | let mut dr=DBIG::new(); 168 | 169 | if DBIG::comp(self,&m)<0 { 170 | let r=BIG::new_dcopy(self); 171 | return r; 172 | } 173 | 174 | loop { 175 | m.shl(1); 176 | k += 1; 177 | if DBIG::comp(self,&m)<0 {break;} 178 | } 179 | 180 | while k>0 { 181 | m.shr(1); 182 | 183 | dr.copy(self); 184 | dr.sub(&m); 185 | dr.norm(); 186 | self.cmove(&dr,(1-((dr.w[big::DNLEN-1]>>(arch::CHUNK-1))&1)) as isize); 187 | /* 188 | if DBIG::comp(self,&m)>=0 { 189 | self.sub(&m); 190 | self.norm(); 191 | } */ 192 | k -= 1; 193 | } 194 | let r=BIG::new_dcopy(self); 195 | return r; 196 | } 197 | 198 | /* return this/c */ 199 | pub fn div(&mut self,c: &BIG) -> BIG { 200 | let mut k=0; 201 | let mut m=DBIG::new_scopy(c); 202 | let mut a=BIG::new(); 203 | let mut e=BIG::new_int(1); 204 | let mut dr=DBIG::new(); 205 | let mut r=BIG::new(); 206 | self.norm(); 207 | 208 | while DBIG::comp(self,&m)>=0 { 209 | e.fshl(1); 210 | m.shl(1); 211 | k+=1; 212 | } 213 | 214 | while k>0 { 215 | m.shr(1); 216 | e.shr(1); 217 | 218 | dr.copy(self); 219 | dr.sub(&m); 220 | dr.norm(); 221 | let d=(1-((dr.w[big::DNLEN-1]>>(arch::CHUNK-1))&1)) as isize; 222 | self.cmove(&dr,d); 223 | r.copy(&a); 224 | r.add(&e); 225 | r.norm(); 226 | a.cmove(&r,d); 227 | /* 228 | if DBIG::comp(self,&m)>0 { 229 | a.add(&e); 230 | a.norm(); 231 | self.sub(&m); 232 | self.norm(); 233 | } */ 234 | k-=1; 235 | } 236 | return a; 237 | } 238 | 239 | /* return number of bits */ 240 | pub fn nbits(&mut self) -> usize { 241 | let mut k=big::DNLEN-1; 242 | self.norm(); 243 | while (k as isize)>=0 && self.w[k]==0 {k=k.wrapping_sub(1)} 244 | if (k as isize) <0 {return 0} 245 | let mut bts=(big::BASEBITS as usize)*k; 246 | let mut c=self.w[k]; 247 | while c!=0 {c/=2; bts+=1;} 248 | return bts; 249 | } 250 | 251 | /* Convert to Hex String */ 252 | pub fn to_string(&mut self) -> String { 253 | let mut s = String::new(); 254 | let mut len=self.nbits(); 255 | 256 | if len%4==0 { 257 | len/=4; 258 | } else { 259 | len/=4; 260 | len+=1; 261 | } 262 | 263 | for i in (0 ..len).rev() { 264 | let mut b=DBIG::new_copy(&self); 265 | b.shr(i*4); 266 | s=s + &format!("{:X}", b.w[0]&15); 267 | } 268 | return s; 269 | } 270 | 271 | } 272 | -------------------------------------------------------------------------------- /amcl/src/bls381/ecdh.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | use bls381::ecp; 21 | use bls381::ecp::ECP; 22 | use bls381::big::BIG; 23 | use bls381::rom; 24 | use bls381::big; 25 | 26 | use rand::RAND; 27 | use hash256::HASH256; 28 | use hash384::HASH384; 29 | use hash512::HASH512; 30 | use aes; 31 | use aes::AES; 32 | 33 | 34 | pub const INVALID_PUBLIC_KEY:isize=-2; 35 | pub const ERROR: isize=-3; 36 | pub const INVALID: isize=-4; 37 | pub const EFS: usize=big::MODBYTES as usize; 38 | pub const EGS: usize=big::MODBYTES as usize; 39 | //pub const EAS: usize=16; 40 | //pub const EBS: usize=16; 41 | pub const SHA256: usize=32; 42 | pub const SHA384: usize=48; 43 | pub const SHA512: usize=64; 44 | 45 | //pub const HASH_TYPE: usize=SHA512; 46 | 47 | #[allow(non_snake_case)] 48 | 49 | fn inttobytes(n: usize,b:&mut [u8]) { 50 | let mut i=b.len(); 51 | let mut m=n; 52 | while m>0 && i>0 { 53 | i-=1; 54 | b[i]=(m&0xff) as u8; 55 | m/=256; 56 | } 57 | } 58 | 59 | fn hashit(sha: usize, a: &[u8],n: usize,b: Option<&[u8]>,pad: usize,w: &mut [u8]) { 60 | let mut r:[u8;64]=[0;64]; 61 | if sha==SHA256 { 62 | let mut h=HASH256::new(); 63 | h.process_array(a); 64 | if n>0 {h.process_num(n as i32)} 65 | if let Some(x) = b { 66 | h.process_array(x); 67 | } 68 | let hs=h.hash(); 69 | for i in 0..sha {r[i]=hs[i];} 70 | } 71 | if sha==SHA384 { 72 | let mut h=HASH384::new(); 73 | h.process_array(a); 74 | if n>0 {h.process_num(n as i32)} 75 | if let Some(x) = b { 76 | h.process_array(x); 77 | } 78 | let hs=h.hash(); 79 | for i in 0..sha {r[i]=hs[i];} 80 | } 81 | if sha==SHA512 { 82 | let mut h=HASH512::new(); 83 | h.process_array(a); 84 | if n>0 {h.process_num(n as i32)} 85 | if let Some(x) = b { 86 | h.process_array(x); 87 | } 88 | let hs=h.hash(); 89 | for i in 0..sha {r[i]=hs[i];} 90 | } 91 | 92 | if pad==0 { 93 | for i in 0..sha {w[i]=r[i]} 94 | } else { 95 | 96 | if pad<=sha { 97 | for i in 0..pad {w[i]=r[i]} 98 | } else { 99 | for i in 0..sha {w[i+pad-sha]=r[i]} 100 | for i in 0..(pad-sha) {w[i]=0} 101 | 102 | 103 | //for i in 0..sha {w[i]=r[i]} 104 | //for i in sha..pad {w[i]=0} 105 | } 106 | } 107 | } 108 | 109 | /* Key Derivation Functions */ 110 | /* Input octet Z */ 111 | /* Output key of length olen */ 112 | pub fn kdf1(sha: usize,z: &[u8],olen: usize,k: &mut [u8]) { 113 | /* NOTE: the parameter olen is the length of the output K in bytes */ 114 | let hlen=sha; 115 | let mut lk=0; 116 | 117 | let mut cthreshold=olen/hlen; if olen%hlen!=0 {cthreshold+=1} 118 | 119 | for counter in 0..cthreshold { 120 | let mut b:[u8;64]=[0;64]; 121 | hashit(sha,z,counter,None,0,&mut b); 122 | if lk+hlen>olen { 123 | for i in 0..(olen%hlen) {k[lk]=b[i]; lk+=1} 124 | } else { 125 | for i in 0..hlen {k[lk]=b[i]; lk+=1} 126 | } 127 | } 128 | } 129 | 130 | pub fn kdf2(sha: usize,z: &[u8],p: Option<&[u8]>,olen: usize,k: &mut [u8]) { 131 | /* NOTE: the parameter olen is the length of the output K in bytes */ 132 | let hlen=sha; 133 | let mut lk=0; 134 | 135 | let mut cthreshold=olen/hlen; if olen%hlen!=0 {cthreshold+=1} 136 | 137 | for counter in 1..cthreshold+1 { 138 | let mut b:[u8;64]=[0;64]; 139 | hashit(sha,z,counter,p,0,&mut b); 140 | if lk+hlen>olen { 141 | for i in 0..(olen%hlen) {k[lk]=b[i]; lk+=1} 142 | } else { 143 | for i in 0..hlen {k[lk]=b[i]; lk+=1} 144 | } 145 | } 146 | } 147 | 148 | /* Password based Key Derivation Function */ 149 | /* Input password p, salt s, and repeat count */ 150 | /* Output key of length olen */ 151 | pub fn pbkdf2(sha: usize,pass: &[u8],salt: &[u8],rep: usize,olen: usize,k: &mut [u8]) { 152 | let mut d=olen/sha; if olen%sha!=0 {d+=1} 153 | let mut f:[u8;64]=[0;64]; 154 | let mut u:[u8;64]=[0;64]; 155 | let mut ku:[u8;64]=[0;64]; 156 | let mut s:[u8;36]=[0;36]; // Maximum salt of 32 bytes + 4 157 | let mut n:[u8;4]=[0;4]; 158 | 159 | let sl=salt.len(); 160 | let mut kp=0; 161 | for i in 0..d { 162 | for j in 0..sl {s[j]=salt[j]} 163 | inttobytes(i+1,&mut n); 164 | for j in 0..4 {s[sl+j]=n[j]} 165 | 166 | hmac(sha,&s[0..sl+4],pass,sha,&mut f); 167 | 168 | for j in 0..sha {u[j]=f[j]} 169 | for _ in 1..rep { 170 | hmac(sha,&mut u,pass,sha,&mut ku); 171 | for k in 0..sha {u[k]=ku[k]; f[k]^=u[k]} 172 | } 173 | for j in 0..EFS {if kp bool { 179 | /* Input is from an octet m * 180 | * olen is requested output length in bytes. k is the key * 181 | * The output is the calculated tag */ 182 | let mut b:[u8;64]=[0;64]; /* Not good */ 183 | let mut k0:[u8;128]=[0;128]; 184 | // let olen=tag.len(); /* length of HMAC */ 185 | 186 | if olen<4 /*|| olen>sha */ {return false} 187 | 188 | let mut lb=64; 189 | if sha>32 {lb=128} 190 | 191 | for i in 0..lb {k0[i]=0} 192 | 193 | if k.len() > lb { 194 | hashit(sha,k,0,None,0,&mut b); 195 | for i in 0..sha {k0[i]=b[i]} 196 | } else { 197 | for i in 0..k.len() {k0[i]=k[i]} 198 | } 199 | 200 | for i in 0..lb {k0[i]^=0x36} 201 | hashit(sha,&mut k0[0..lb],0,Some(m),0,&mut b); 202 | 203 | for i in 0..lb {k0[i]^=0x6a} 204 | hashit(sha,&mut k0[0..lb],0,Some(&b[0..sha]),olen,tag); 205 | 206 | return true; 207 | } 208 | 209 | /* AES encryption/decryption. Encrypt byte array m using key k and returns ciphertext c */ 210 | pub fn cbc_iv0_encrypt(k: &[u8],m: &[u8]) -> Vec { /* AES CBC encryption, with Null IV and key K */ 211 | /* Input is from an octet string m, output is to an octet string c */ 212 | /* Input is padded as necessary to make up a full final block */ 213 | let mut a=AES::new(); 214 | let mut fin=false; 215 | let mut c:Vec=Vec::new(); 216 | 217 | let mut buff:[u8;16]=[0;16]; 218 | 219 | a.init(aes::CBC,k.len(),k,None); 220 | 221 | let mut ipt=0; 222 | // let mut opt=0; 223 | let mut i; 224 | loop { 225 | i=0; 226 | while i<16 { 227 | if ipt Option> { /* padding is removed */ 256 | let mut a=AES::new(); 257 | let mut fin=false; 258 | let mut m:Vec=Vec::new(); 259 | 260 | let mut buff:[u8;16]=[0;16]; 261 | 262 | a.init(aes::CBC,k.len(),k,None); 263 | 264 | let mut ipt=0; 265 | //let mut opt=0; 266 | let mut i; 267 | 268 | if c.len()==0 {return None} 269 | let mut ch=c[ipt]; ipt+=1; 270 | 271 | loop { 272 | i=0; 273 | while i<16 { 274 | buff[i]=ch; 275 | if ipt>=c.len() { 276 | fin=true; break; 277 | } else {ch=c[ipt]; ipt+=1 } 278 | i+=1; 279 | } 280 | a.decrypt(&mut buff); 281 | if fin {break} 282 | for j in 0..16 { 283 | m.push(buff[j]); 284 | //m[opt]=buff[j]; opt+=1; 285 | } 286 | } 287 | 288 | a.end(); 289 | let mut bad=false; 290 | let padlen=buff[15] as usize; 291 | if i!=15 || padlen<1 || padlen>16 {bad=true} 292 | if padlen>=2 && padlen<=16 { 293 | for j in 16-padlen..16 { 294 | if buff[j]!=padlen as u8 {bad=true} 295 | } 296 | } 297 | 298 | if !bad { 299 | for _ in 0..16-padlen { 300 | m.push(buff[i]); 301 | //m[opt]=buff[j]; opt+=1; 302 | } 303 | } 304 | 305 | if bad {return None} 306 | return Some(m); 307 | } 308 | 309 | /* Calculate a public/private EC GF(p) key pair w,s where W=s.G mod EC(p), 310 | * where s is the secret key and W is the public key 311 | * and G is fixed generator. 312 | * If RNG is NULL then the private key is provided externally in s 313 | * otherwise it is generated randomly internally */ 314 | #[allow(non_snake_case)] 315 | pub fn key_pair_generate(rng: Option<&mut RAND>,s: &mut [u8],w: &mut [u8]) -> isize { 316 | let res=0; 317 | let mut sc:BIG; 318 | let G=ECP::generator(); 319 | 320 | let r=BIG::new_ints(&rom::CURVE_ORDER); 321 | 322 | if let Some(mut x)=rng { 323 | sc=BIG::randomnum(&r,&mut x); 324 | } else { 325 | sc=BIG::frombytes(&s); 326 | sc.rmod(&r); 327 | } 328 | 329 | //if rom::AES_S>0 { 330 | // sc.mod2m(2*rom::AES_S) 331 | //} 332 | sc.tobytes(s); 333 | 334 | let mut WP=G.mul(&mut sc); 335 | 336 | WP.tobytes(w,false); // To use point compression on public keys, change to true 337 | 338 | return res; 339 | } 340 | 341 | /* validate public key */ 342 | #[allow(non_snake_case)] 343 | pub fn public_key_validate(w: &[u8]) -> isize { 344 | let mut WP=ECP::frombytes(w); 345 | let mut res=0; 346 | 347 | let r=BIG::new_ints(&rom::CURVE_ORDER); 348 | 349 | if WP.is_infinity() {res=INVALID_PUBLIC_KEY} 350 | if res==0 { 351 | 352 | let q=BIG::new_ints(&rom::MODULUS); 353 | let nb=q.nbits(); 354 | let mut k=BIG::new(); k.one(); k.shl((nb+4)/2); 355 | k.add(&q); 356 | k.div(&r); 357 | 358 | while k.parity()==0 { 359 | k.shr(1); 360 | WP.dbl(); 361 | } 362 | 363 | if !k.isunity() {WP=WP.mul(&mut k)} 364 | if WP.is_infinity() {res=INVALID_PUBLIC_KEY} 365 | 366 | } 367 | return res; 368 | } 369 | 370 | /* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */ 371 | #[allow(non_snake_case)] 372 | pub fn ecpsvdp_dh(s: &[u8],wd: &[u8],z: &mut [u8]) -> isize { 373 | let mut res=0; 374 | let mut t:[u8;EFS]=[0;EFS]; 375 | 376 | let mut sc=BIG::frombytes(&s); 377 | 378 | let mut W=ECP::frombytes(&wd); 379 | if W.is_infinity() {res=ERROR} 380 | 381 | if res==0 { 382 | let r=BIG::new_ints(&rom::CURVE_ORDER); 383 | sc.rmod(&r); 384 | W=W.mul(&mut sc); 385 | if W.is_infinity() { 386 | res=ERROR; 387 | } else { 388 | W.getx().tobytes(&mut t); 389 | for i in 0..EFS {z[i]=t[i]} 390 | } 391 | } 392 | return res; 393 | } 394 | 395 | /* IEEE ECDSA Signature, C and D are signature on F using private key S */ 396 | #[allow(non_snake_case)] 397 | pub fn ecpsp_dsa(sha: usize,rng: &mut RAND,s: &[u8],f: &[u8],c: &mut [u8],d: &mut [u8]) -> isize { 398 | let mut t:[u8;EFS]=[0;EFS]; 399 | let mut b:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize]; 400 | 401 | hashit(sha,f,0,None,big::MODBYTES as usize,&mut b); 402 | 403 | let G=ECP::generator(); 404 | 405 | 406 | let r=BIG::new_ints(&rom::CURVE_ORDER); 407 | 408 | let mut sc=BIG::frombytes(s); /* s or &s? */ 409 | let fb=BIG::frombytes(&b); 410 | 411 | let mut cb=BIG::new(); 412 | let mut db=BIG::new(); 413 | let mut tb=BIG::new(); 414 | let mut V=ECP::new(); 415 | 416 | while db.iszilch() { 417 | let mut u=BIG::randomnum(&r,rng); 418 | let mut w=BIG::randomnum(&r,rng); /* side channel masking */ 419 | //if rom::AES_S>0 { 420 | // u.mod2m(2*rom::AES_S); 421 | //} 422 | V.copy(&G); 423 | V=V.mul(&mut u); 424 | let vx=V.getx(); 425 | cb.copy(&vx); 426 | cb.rmod(&r); 427 | if cb.iszilch() {continue} 428 | 429 | tb.copy(&BIG::modmul(&mut u,&mut w,&r)); 430 | u.copy(&tb); 431 | 432 | u.invmodp(&r); 433 | db.copy(&BIG::modmul(&mut sc,&mut cb,&r)); 434 | db.add(&fb); 435 | 436 | tb.copy(&BIG::modmul(&mut db,&mut w,&r)); 437 | db.copy(&tb); 438 | 439 | tb.copy(&BIG::modmul(&mut u,&mut db,&r)); 440 | db.copy(&tb); 441 | } 442 | 443 | cb.tobytes(&mut t); 444 | for i in 0..EFS {c[i]=t[i]} 445 | db.tobytes(&mut t); 446 | for i in 0..EFS {d[i]=t[i]} 447 | return 0; 448 | } 449 | 450 | /* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */ 451 | #[allow(non_snake_case)] 452 | pub fn ecpvp_dsa(sha: usize,w: &[u8],f: &[u8],c: &[u8],d: &[u8]) -> isize { 453 | let mut res=0; 454 | 455 | let mut b:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize]; 456 | 457 | hashit(sha,f,0,None,big::MODBYTES as usize,&mut b); 458 | 459 | let mut G=ECP::generator(); 460 | 461 | let r=BIG::new_ints(&rom::CURVE_ORDER); 462 | 463 | let mut cb=BIG::frombytes(c); /* c or &c ? */ 464 | let mut db=BIG::frombytes(d); /* d or &d ? */ 465 | let mut fb=BIG::frombytes(&b); 466 | let mut tb=BIG::new(); 467 | 468 | if cb.iszilch() || BIG::comp(&cb,&r)>=0 || db.iszilch() || BIG::comp(&db,&r)>=0 { 469 | res=INVALID; 470 | } 471 | 472 | if res==0 { 473 | db.invmodp(&r); 474 | tb.copy(&BIG::modmul(&mut fb,&mut db,&r)); 475 | fb.copy(&tb); 476 | let h2=BIG::modmul(&mut cb,&mut db,&r); 477 | 478 | let WP=ECP::frombytes(&w); 479 | if WP.is_infinity() { 480 | res=ERROR; 481 | } else { 482 | let mut P=ECP::new(); 483 | P.copy(&WP); 484 | 485 | P=P.mul2(&h2,&mut G,&fb); 486 | 487 | if P.is_infinity() { 488 | res=INVALID; 489 | } else { 490 | db=P.getx(); 491 | db.rmod(&r); 492 | 493 | if BIG::comp(&db,&cb)!=0 {res=INVALID} 494 | } 495 | } 496 | } 497 | 498 | return res; 499 | } 500 | 501 | /* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */ 502 | #[allow(non_snake_case)] 503 | pub fn ecies_encrypt(sha: usize,p1: &[u8],p2: &[u8],rng: &mut RAND,w: &[u8],m: &[u8],v: &mut [u8],t: &mut [u8]) -> Option> { 504 | let mut z:[u8;EFS]=[0;EFS]; 505 | let mut k1:[u8;ecp::AESKEY]=[0;ecp::AESKEY]; 506 | let mut k2:[u8;ecp::AESKEY]=[0;ecp::AESKEY]; 507 | let mut u:[u8;EGS]=[0;EGS]; 508 | let mut vz:[u8;3*EFS+1]=[0;3*EFS+1]; 509 | let mut k:[u8;2*ecp::AESKEY]=[0;2*ecp::AESKEY]; 510 | 511 | if key_pair_generate(Some(rng),&mut u,v)!=0 {return None} 512 | if ecpsvdp_dh(&u,&w,&mut z)!=0 {return None} 513 | 514 | for i in 0..2*EFS+1 {vz[i]=v[i]} 515 | for i in 0..EFS {vz[2*EFS+1+i]=z[i]} 516 | 517 | kdf2(sha,&vz,Some(p1),2*ecp::AESKEY,&mut k); 518 | 519 | for i in 0..ecp::AESKEY {k1[i]=k[i]; k2[i]=k[ecp::AESKEY+i]} 520 | 521 | let mut c=cbc_iv0_encrypt(&k1,m); 522 | 523 | let mut l2:[u8;8]=[0;8]; 524 | let p2l=p2.len(); 525 | 526 | inttobytes(p2l,&mut l2); 527 | 528 | for i in 0..p2l { 529 | c.push(p2[i]); 530 | } 531 | for i in 0..8 { 532 | c.push(l2[i]); 533 | } 534 | 535 | hmac(sha,&c,&k2,t.len(),t); 536 | 537 | for _ in 0..p2l+8 {c.pop();} 538 | 539 | return Some(c); 540 | } 541 | 542 | /* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */ 543 | #[allow(non_snake_case)] 544 | pub fn ecies_decrypt(sha: usize,p1: &[u8],p2: &[u8],v: &[u8],c: &mut Vec,t: &[u8],u: &[u8]) -> Option> { 545 | let mut z:[u8;EFS]=[0;EFS]; 546 | let mut k1:[u8;ecp::AESKEY]=[0;ecp::AESKEY]; 547 | let mut k2:[u8;ecp::AESKEY]=[0;ecp::AESKEY]; 548 | let mut vz:[u8;3*EFS+1]=[0;3*EFS+1]; 549 | let mut k:[u8;2*ecp::AESKEY]=[0;2*ecp::AESKEY]; 550 | 551 | let mut tag:[u8;32]=[0;32]; /* 32 is max length of tag */ 552 | 553 | for i in 0..t.len() {tag[i]=t[i]} 554 | 555 | if ecpsvdp_dh(&u,&v,&mut z)!=0 {return None} 556 | 557 | for i in 0..2*EFS+1 {vz[i]=v[i]} 558 | for i in 0..EFS {vz[2*EFS+1+i]=z[i]} 559 | 560 | kdf2(sha,&vz,Some(p1),2*ecp::AESKEY,&mut k); 561 | 562 | for i in 0..ecp::AESKEY {k1[i]=k[i]; k2[i]=k[ecp::AESKEY+i]} 563 | 564 | let m=cbc_iv0_decrypt(&k1,&c); 565 | 566 | if m==None {return None} 567 | 568 | let mut l2:[u8;8]=[0;8]; 569 | let p2l=p2.len(); 570 | 571 | inttobytes(p2l,&mut l2); 572 | 573 | for i in 0..p2l { 574 | c.push(p2[i]); 575 | } 576 | for i in 0..8 { 577 | c.push(l2[i]); 578 | } 579 | 580 | hmac(sha,&c,&k2,t.len(),&mut tag); 581 | 582 | for _ in 0..p2l+8 {c.pop();} 583 | 584 | let mut same=true; 585 | for i in 0..t.len() { 586 | if t[i]!=tag[i] {same=false} 587 | } 588 | if !same {return None} 589 | 590 | return m; 591 | } 592 | 593 | -------------------------------------------------------------------------------- /amcl/src/bls381/ecp2.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | use bls381::rom; 21 | use bls381::big; 22 | use bls381::ecp; 23 | use bls381::fp2::FP2; 24 | use bls381::big::BIG; 25 | 26 | pub struct ECP2 { 27 | x:FP2, 28 | y:FP2, 29 | z:FP2, 30 | // inf: bool 31 | } 32 | 33 | #[allow(non_snake_case)] 34 | impl ECP2 { 35 | 36 | pub fn new() -> ECP2 { 37 | ECP2 { 38 | x: FP2::new(), 39 | y: FP2::new_int(1), 40 | z: FP2::new(), 41 | // inf: true 42 | } 43 | } 44 | #[allow(non_snake_case)] 45 | /* construct this from (x,y) - but set to O if not on curve */ 46 | pub fn new_fp2s(ix:&FP2,iy:&FP2) -> ECP2 { 47 | let mut E=ECP2::new(); 48 | E.x.copy(&ix); 49 | E.y.copy(&iy); 50 | E.z.one(); 51 | 52 | let mut rhs=ECP2::rhs(&mut E.x); 53 | let mut y2=FP2::new_copy(&E.y); 54 | y2.sqr(); 55 | if !y2.equals(&mut rhs) { 56 | E.inf(); 57 | } 58 | return E; 59 | } 60 | 61 | /* construct this from x - but set to O if not on curve */ 62 | pub fn new_fp2(ix:&FP2) -> ECP2 { 63 | let mut E=ECP2::new(); 64 | E.x.copy(&ix); 65 | E.y.one(); 66 | E.z.one(); 67 | 68 | let mut rhs=ECP2::rhs(&mut E.x); 69 | if rhs.sqrt() { 70 | E.y.copy(&rhs); 71 | // E.inf=false; 72 | } else {E.inf();} 73 | return E; 74 | } 75 | 76 | /* Test this=O? */ 77 | pub fn is_infinity(&self) -> bool { 78 | // if self.inf {return true} 79 | let mut xx=FP2::new_copy(&self.x); 80 | let mut zz=FP2::new_copy(&self.z); 81 | return xx.iszilch() && zz.iszilch(); 82 | } 83 | 84 | /* copy self=P */ 85 | pub fn copy(&mut self,P: &ECP2) { 86 | self.x.copy(&P.x); 87 | self.y.copy(&P.y); 88 | self.z.copy(&P.z); 89 | // self.inf=P.inf; 90 | } 91 | 92 | /* set self=O */ 93 | pub fn inf(&mut self) { 94 | // self.inf=true; 95 | self.x.zero(); 96 | self.y.one(); 97 | self.z.zero(); 98 | } 99 | 100 | /* set self=-self */ 101 | pub fn neg(&mut self) { 102 | // if self.is_infinity() {return} 103 | self.y.norm(); self.y.neg(); self.y.norm(); 104 | } 105 | 106 | /* Conditional move of Q to self dependant on d */ 107 | pub fn cmove(&mut self,Q: &ECP2,d: isize) { 108 | self.x.cmove(&Q.x,d); 109 | self.y.cmove(&Q.y,d); 110 | self.z.cmove(&Q.z,d); 111 | /* 112 | let bd:bool; 113 | if d==0 {bd=false} 114 | else {bd=true} 115 | 116 | self.inf=(self.inf!=(self.inf!=Q.inf)&&bd); */ 117 | } 118 | 119 | /* return 1 if b==c, no branching */ 120 | fn teq(b: i32,c: i32) -> isize { 121 | let mut x=b^c; 122 | x-=1; // if x=0, x now -1 123 | return ((x>>31)&1) as isize; 124 | } 125 | 126 | /* Constant time select from pre-computed table */ 127 | pub fn selector(&mut self,W: &[ECP2],b: i32) { 128 | let mut MP=ECP2::new(); 129 | let m=b>>31; 130 | let mut babs=(b^m)-m; 131 | 132 | babs=(babs-1)/2; 133 | 134 | self.cmove(&W[0],ECP2::teq(babs,0)); // conditional move 135 | self.cmove(&W[1],ECP2::teq(babs,1)); 136 | self.cmove(&W[2],ECP2::teq(babs,2)); 137 | self.cmove(&W[3],ECP2::teq(babs,3)); 138 | self.cmove(&W[4],ECP2::teq(babs,4)); 139 | self.cmove(&W[5],ECP2::teq(babs,5)); 140 | self.cmove(&W[6],ECP2::teq(babs,6)); 141 | self.cmove(&W[7],ECP2::teq(babs,7)); 142 | 143 | MP.copy(self); 144 | MP.neg(); 145 | self.cmove(&MP,(m&1) as isize); 146 | } 147 | 148 | /* Test if P == Q */ 149 | pub fn equals(&mut self,Q :&mut ECP2) -> bool { 150 | // if self.is_infinity() && Q.is_infinity() {return true} 151 | // if self.is_infinity() || Q.is_infinity() {return false} 152 | 153 | let mut a=FP2::new_copy(&self.x); 154 | let mut b=FP2::new_copy(&Q.x); 155 | 156 | a.mul(&Q.z); 157 | b.mul(&self.z); 158 | if !a.equals(&mut b) {return false} 159 | a.copy(&self.y); a.mul(&Q.z); 160 | b.copy(&Q.y); b.mul(&self.z); 161 | if !a.equals(&mut b) {return false} 162 | 163 | return true; 164 | } 165 | 166 | /* set to Affine - (x,y,z) to (x,y) */ 167 | pub fn affine(&mut self) { 168 | if self.is_infinity() {return} 169 | let mut one=FP2::new_int(1); 170 | if self.z.equals(&mut one) {return} 171 | self.z.inverse(); 172 | 173 | self.x.mul(&self.z); self.x.reduce(); 174 | self.y.mul(&self.z); self.y.reduce(); 175 | self.z.copy(&one); 176 | } 177 | 178 | /* extract affine x as FP2 */ 179 | pub fn getx(&mut self) -> FP2 { 180 | self.affine(); 181 | return FP2::new_copy(&self.x); 182 | } 183 | 184 | /* extract affine y as FP2 */ 185 | pub fn gety(&mut self) -> FP2 { 186 | self.affine(); 187 | return FP2::new_copy(&self.y); 188 | } 189 | 190 | /* extract projective x */ 191 | pub fn getpx(&self) -> FP2 { 192 | return FP2::new_copy(&self.x); 193 | } 194 | /* extract projective y */ 195 | pub fn getpy(&self) -> FP2 { 196 | return FP2::new_copy(&self.y); 197 | } 198 | /* extract projective z */ 199 | pub fn getpz(&self) -> FP2 { 200 | return FP2::new_copy(&self.z); 201 | } 202 | 203 | /* convert to byte array */ 204 | pub fn tobytes(&mut self,b: &mut [u8]) { 205 | let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize]; 206 | let mb=big::MODBYTES as usize; 207 | 208 | self.affine(); 209 | self.x.geta().tobytes(&mut t); 210 | for i in 0..mb { b[i]=t[i]} 211 | self.x.getb().tobytes(&mut t); 212 | for i in 0..mb { b[i+mb]=t[i]} 213 | 214 | self.y.geta().tobytes(&mut t); 215 | for i in 0..mb {b[i+2*mb]=t[i]} 216 | self.y.getb().tobytes(&mut t); 217 | for i in 0..mb {b[i+3*mb]=t[i]} 218 | } 219 | 220 | /* convert from byte array to point */ 221 | pub fn frombytes(b: &[u8]) -> ECP2 { 222 | let mut t:[u8;big::MODBYTES as usize]=[0;big::MODBYTES as usize]; 223 | let mb=big::MODBYTES as usize; 224 | 225 | for i in 0..mb {t[i]=b[i]} 226 | let mut ra=BIG::frombytes(&t); 227 | for i in 0..mb {t[i]=b[i+mb]} 228 | let mut rb=BIG::frombytes(&t); 229 | let rx=FP2::new_bigs(&ra,&rb); 230 | 231 | for i in 0..mb {t[i]=b[i+2*mb]} 232 | ra.copy(&BIG::frombytes(&t)); 233 | for i in 0..mb {t[i]=b[i+3*mb]} 234 | rb.copy(&BIG::frombytes(&t)); 235 | let ry=FP2::new_bigs(&ra,&rb); 236 | 237 | return ECP2::new_fp2s(&rx,&ry); 238 | } 239 | 240 | /* convert this to hex string */ 241 | pub fn tostring(&mut self) -> String { 242 | if self.is_infinity() {return String::from("infinity")} 243 | self.affine(); 244 | return format!("({},{})",self.x.tostring(),self.y.tostring()); 245 | } 246 | 247 | /* Calculate RHS of twisted curve equation x^3+B/i */ 248 | pub fn rhs(x:&mut FP2) -> FP2 { 249 | x.norm(); 250 | let mut r=FP2::new_copy(x); 251 | r.sqr(); 252 | let mut b=FP2::new_big(&BIG::new_ints(&rom::CURVE_B)); 253 | if ecp::SEXTIC_TWIST==ecp::D_TYPE { 254 | b.div_ip(); 255 | } 256 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 257 | b.norm(); 258 | b.mul_ip(); 259 | b.norm(); 260 | } 261 | 262 | r.mul(x); 263 | r.add(&b); 264 | 265 | r.reduce(); 266 | return r; 267 | } 268 | 269 | /* self+=self */ 270 | pub fn dbl(&mut self) -> isize { 271 | // if self.inf {return -1} 272 | 273 | let mut iy=FP2::new_copy(&self.y); 274 | if ecp::SEXTIC_TWIST==ecp::D_TYPE { 275 | iy.mul_ip(); iy.norm(); 276 | } 277 | 278 | let mut t0=FP2::new_copy(&self.y); //***** Change 279 | t0.sqr(); 280 | if ecp::SEXTIC_TWIST==ecp::D_TYPE { 281 | t0.mul_ip(); 282 | } 283 | let mut t1=FP2::new_copy(&iy); 284 | t1.mul(&self.z); 285 | let mut t2=FP2::new_copy(&self.z); 286 | t2.sqr(); 287 | 288 | self.z.copy(&t0); 289 | self.z.add(&t0); self.z.norm(); 290 | self.z.dbl(); 291 | self.z.dbl(); 292 | self.z.norm(); 293 | 294 | t2.imul(3*rom::CURVE_B_I); 295 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 296 | t2.mul_ip(); 297 | t2.norm(); 298 | } 299 | let mut x3=FP2::new_copy(&t2); 300 | x3.mul(&self.z); 301 | 302 | let mut y3=FP2::new_copy(&t0); 303 | 304 | y3.add(&t2); y3.norm(); 305 | self.z.mul(&t1); 306 | t1.copy(&t2); t1.add(&t2); t2.add(&t1); t2.norm(); 307 | t0.sub(&t2); t0.norm(); //y^2-9bz^2 308 | y3.mul(&t0); y3.add(&x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2 309 | t1.copy(&self.x); t1.mul(&iy); // 310 | self.x.copy(&t0); self.x.norm(); self.x.mul(&t1); self.x.dbl(); //(y^2-9bz^2)xy2 311 | 312 | self.x.norm(); 313 | self.y.copy(&y3); self.y.norm(); 314 | 315 | return 1; 316 | 317 | } 318 | 319 | /* self+=Q - return 0 for add, 1 for double, -1 for O */ 320 | pub fn add(&mut self,Q:&ECP2) -> isize { 321 | /*if self.inf { 322 | self.copy(Q); 323 | return -1; 324 | } 325 | if Q.inf {return -1}*/ 326 | 327 | 328 | let b=3*rom::CURVE_B_I; 329 | let mut t0=FP2::new_copy(&self.x); 330 | t0.mul(&Q.x); // x.Q.x 331 | let mut t1=FP2::new_copy(&self.y); 332 | t1.mul(&Q.y); // y.Q.y 333 | 334 | let mut t2=FP2::new_copy(&self.z); 335 | t2.mul(&Q.z); 336 | let mut t3=FP2::new_copy(&self.x); 337 | t3.add(&self.y); t3.norm(); //t3=X1+Y1 338 | let mut t4=FP2::new_copy(&Q.x); 339 | t4.add(&Q.y); t4.norm(); //t4=X2+Y2 340 | t3.mul(&t4); //t3=(X1+Y1)(X2+Y2) 341 | t4.copy(&t0); t4.add(&t1); //t4=X1.X2+Y1.Y2 342 | 343 | t3.sub(&t4); t3.norm(); 344 | if ecp::SEXTIC_TWIST==ecp::D_TYPE { 345 | t3.mul_ip(); t3.norm(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 346 | } 347 | t4.copy(&self.y); 348 | t4.add(&self.z); t4.norm(); //t4=Y1+Z1 349 | let mut x3=FP2::new_copy(&Q.y); 350 | x3.add(&Q.z); x3.norm(); //x3=Y2+Z2 351 | 352 | t4.mul(&x3); //t4=(Y1+Z1)(Y2+Z2) 353 | x3.copy(&t1); // 354 | x3.add(&t2); //X3=Y1.Y2+Z1.Z2 355 | 356 | t4.sub(&x3); t4.norm(); 357 | if ecp::SEXTIC_TWIST==ecp::D_TYPE { 358 | t4.mul_ip(); t4.norm(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 359 | } 360 | x3.copy(&self.x); x3.add(&self.z); x3.norm(); // x3=X1+Z1 361 | let mut y3=FP2::new_copy(&Q.x); 362 | y3.add(&Q.z); y3.norm(); // y3=X2+Z2 363 | x3.mul(&y3); // x3=(X1+Z1)(X2+Z2) 364 | y3.copy(&t0); 365 | y3.add(&t2); // y3=X1.X2+Z1+Z2 366 | y3.rsub(&x3); y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1 367 | 368 | if ecp::SEXTIC_TWIST==ecp::D_TYPE { 369 | t0.mul_ip(); t0.norm(); // x.Q.x 370 | t1.mul_ip(); t1.norm(); // y.Q.y 371 | } 372 | x3.copy(&t0); x3.add(&t0); 373 | t0.add(&x3); t0.norm(); 374 | t2.imul(b); 375 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 376 | t2.mul_ip(); 377 | } 378 | let mut z3=FP2::new_copy(&t1); z3.add(&t2); z3.norm(); 379 | t1.sub(&t2); t1.norm(); 380 | y3.imul(b); 381 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 382 | y3.mul_ip(); 383 | y3.norm(); 384 | } 385 | x3.copy(&y3); x3.mul(&t4); t2.copy(&t3); t2.mul(&t1); x3.rsub(&t2); 386 | y3.mul(&t0); t1.mul(&z3); y3.add(&t1); 387 | t0.mul(&t3); z3.mul(&t4); z3.add(&t0); 388 | 389 | self.x.copy(&x3); self.x.norm(); 390 | self.y.copy(&y3); self.y.norm(); 391 | self.z.copy(&z3); self.z.norm(); 392 | 393 | return 0; 394 | } 395 | 396 | /* set this-=Q */ 397 | pub fn sub(&mut self,Q :&ECP2) -> isize { 398 | let mut NQ=ECP2::new(); NQ.copy(Q); 399 | NQ.neg(); 400 | let d=self.add(&NQ); 401 | return d; 402 | } 403 | 404 | /* set this*=q, where q is Modulus, using Frobenius */ 405 | pub fn frob(&mut self,x:&FP2) { 406 | // if self.inf {return} 407 | let mut x2=FP2::new_copy(x); 408 | x2.sqr(); 409 | self.x.conj(); 410 | self.y.conj(); 411 | self.z.conj(); 412 | self.z.reduce(); 413 | self.x.mul(&x2); 414 | self.y.mul(&x2); 415 | self.y.mul(x); 416 | } 417 | 418 | /* self*=e */ 419 | pub fn mul(&self,e: &BIG) -> ECP2 { 420 | /* fixed size windows */ 421 | let mut mt=BIG::new(); 422 | let mut t=BIG::new(); 423 | let mut P=ECP2::new(); 424 | let mut Q=ECP2::new(); 425 | let mut C=ECP2::new(); 426 | 427 | if self.is_infinity() {return P} 428 | 429 | let mut W:[ECP2;8]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()]; 430 | 431 | const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4; 432 | let mut w:[i8;CT]=[0;CT]; 433 | 434 | // self.affine(); 435 | 436 | /* precompute table */ 437 | Q.copy(&self); 438 | Q.dbl(); 439 | 440 | W[0].copy(&self); 441 | 442 | for i in 1..8 { 443 | C.copy(&W[i-1]); 444 | W[i].copy(&C); 445 | W[i].add(&mut Q); 446 | } 447 | 448 | /* make exponent odd - add 2P if even, P if odd */ 449 | t.copy(&e); 450 | let s=t.parity(); 451 | t.inc(1); t.norm(); let ns=t.parity(); mt.copy(&t); mt.inc(1); mt.norm(); 452 | t.cmove(&mt,s); 453 | Q.cmove(&self,ns); 454 | C.copy(&Q); 455 | 456 | let nb=1+(t.nbits()+3)/4; 457 | 458 | /* convert exponent to signed 4-bit window */ 459 | for i in 0..nb { 460 | w[i]=(t.lastbits(5)-16) as i8; 461 | t.dec(w[i] as isize); t.norm(); 462 | t.fshr(4); 463 | } 464 | w[nb]=(t.lastbits(5)) as i8; 465 | 466 | P.copy(&W[((w[nb] as usize) -1)/2]); 467 | for i in (0..nb).rev() { 468 | Q.selector(&W,w[i] as i32); 469 | P.dbl(); 470 | P.dbl(); 471 | P.dbl(); 472 | P.dbl(); 473 | P.add(&mut Q); 474 | } 475 | P.sub(&mut C); 476 | P.affine(); 477 | return P; 478 | } 479 | 480 | 481 | /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ 482 | // Bos & Costello https://eprint.iacr.org/2013/458.pdf 483 | // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf 484 | // Side channel attack secure 485 | 486 | pub fn mul4(Q: &mut [ECP2],u: &[BIG]) -> ECP2 { 487 | let mut W=ECP2::new(); 488 | let mut P=ECP2::new(); 489 | 490 | let mut T:[ECP2;8]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()]; 491 | 492 | let mut mt=BIG::new(); 493 | 494 | let mut t:[BIG;4]=[BIG::new_copy(&u[0]),BIG::new_copy(&u[1]),BIG::new_copy(&u[2]),BIG::new_copy(&u[3])]; 495 | 496 | const CT:usize=1+big::NLEN*(big::BASEBITS as usize); 497 | let mut w:[i8;CT]=[0;CT]; 498 | let mut s:[i8;CT]=[0;CT]; 499 | 500 | for i in 0..4 { 501 | Q[i].affine(); 502 | t[i].norm(); 503 | } 504 | 505 | T[0].copy(&Q[0]); W.copy(&T[0]); 506 | T[1].copy(&W); T[1].add(&mut Q[1]); // Q[0]+Q[1] 507 | T[2].copy(&W); T[2].add(&mut Q[2]); W.copy(&T[1]); // Q[0]+Q[2] 508 | T[3].copy(&W); T[3].add(&mut Q[2]); W.copy(&T[0]); // Q[0]+Q[1]+Q[2] 509 | T[4].copy(&W); T[4].add(&mut Q[3]); W.copy(&T[1]); // Q[0]+Q[3] 510 | T[5].copy(&W); T[5].add(&mut Q[3]); W.copy(&T[2]); // Q[0]+Q[1]+Q[3] 511 | T[6].copy(&W); T[6].add(&mut Q[3]); W.copy(&T[3]); // Q[0]+Q[2]+Q[3] 512 | T[7].copy(&W); T[7].add(&mut Q[3]); // Q[0]+Q[1]+Q[2]+Q[3] 513 | 514 | // Make it odd 515 | let pb=1-t[0].parity(); 516 | t[0].inc(pb); 517 | t[0].norm(); 518 | 519 | // Number of bits 520 | mt.zero(); 521 | for i in 0..4 { 522 | mt.or(&t[i]); 523 | } 524 | 525 | let nb=1+mt.nbits(); 526 | 527 | // Sign pivot 528 | 529 | s[nb-1]=1; 530 | for i in 0..nb-1 { 531 | t[0].fshr(1); 532 | s[i]=(2*t[0].parity()-1) as i8; 533 | //println!("s={}",s[i]); 534 | } 535 | 536 | // Recoded exponent 537 | for i in 0..nb { 538 | w[i]=0; 539 | let mut k=1; 540 | for j in 1..4 { 541 | let bt=s[i]*(t[j].parity() as i8); 542 | t[j].fshr(1); 543 | t[j].dec((bt>>1) as isize); 544 | t[j].norm(); 545 | w[i]+=bt*(k as i8); 546 | k=2*k; 547 | } 548 | } 549 | 550 | // Main loop 551 | P.selector(&T,(2*w[nb-1]+1) as i32); 552 | for i in (0..nb-1).rev() { 553 | 554 | P.dbl(); 555 | W.selector(&T,(2*w[i]+s[i]) as i32); 556 | P.add(&mut W); 557 | } 558 | 559 | // apply correction 560 | W.copy(&P); 561 | W.sub(&mut Q[0]); 562 | P.cmove(&W,pb); 563 | P.affine(); 564 | 565 | return P; 566 | } 567 | 568 | 569 | #[allow(non_snake_case)] 570 | pub fn mapit(h: &[u8]) -> ECP2 { 571 | let mut q=BIG::new_ints(&rom::MODULUS); 572 | let mut x=BIG::frombytes(h); 573 | x.rmod(&mut q); 574 | let mut Q:ECP2; 575 | let one=BIG::new_int(1); 576 | 577 | loop { 578 | let X=FP2::new_bigs(&one,&x); 579 | Q=ECP2::new_fp2(&X); 580 | if !Q.is_infinity() {break} 581 | x.inc(1); x.norm(); 582 | } 583 | let mut X = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB)); 584 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 585 | X.inverse(); 586 | X.norm(); 587 | } 588 | x = BIG::new_ints(&rom::CURVE_BNX); 589 | 590 | if ecp::CURVE_PAIRING_TYPE==ecp::BN { 591 | 592 | let mut T=Q.mul(&mut x); 593 | if ecp::SIGN_OF_X==ecp::NEGATIVEX { 594 | T.neg(); 595 | } 596 | let mut K=ECP2::new(); K.copy(&T); 597 | K.dbl(); K.add(&T); 598 | 599 | K.frob(&X); 600 | Q.frob(&X); Q.frob(&X); Q.frob(&X); 601 | Q.add(&T); Q.add(&K); 602 | T.frob(&X); T.frob(&X); 603 | Q.add(&T); 604 | } 605 | if ecp::CURVE_PAIRING_TYPE==ecp::BLS { 606 | 607 | let mut xQ=Q.mul(&mut x); 608 | let mut x2Q=xQ.mul(&mut x); 609 | 610 | if ecp::SIGN_OF_X==ecp::NEGATIVEX { 611 | xQ.neg(); 612 | } 613 | x2Q.sub(&xQ); 614 | x2Q.sub(&Q); 615 | 616 | xQ.sub(&Q); 617 | xQ.frob(&X); 618 | 619 | Q.dbl(); 620 | Q.frob(&X); 621 | Q.frob(&X); 622 | 623 | Q.add(&x2Q); 624 | Q.add(&xQ); 625 | } 626 | 627 | Q.affine(); 628 | return Q; 629 | } 630 | 631 | pub fn generator() -> ECP2 { 632 | return ECP2::new_fp2s(&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PXA),&BIG::new_ints(&rom::CURVE_PXB)),&FP2::new_bigs(&BIG::new_ints(&rom::CURVE_PYA),&BIG::new_ints(&rom::CURVE_PYB))); 633 | } 634 | 635 | } 636 | /* 637 | fn main() 638 | { 639 | let mut r=BIG::new_ints(&rom::MODULUS); 640 | 641 | let pxa=BIG::new_ints(&rom::CURVE_PXA); 642 | let pxb=BIG::new_ints(&rom::CURVE_PXB); 643 | let pya=BIG::new_ints(&rom::CURVE_PYA); 644 | let pyb=BIG::new_ints(&rom::CURVE_PYB); 645 | 646 | let fra=BIG::new_ints(&rom::CURVE_FRA); 647 | let frb=BIG::new_ints(&rom::CURVE_FRB); 648 | 649 | let mut f=FP2::new_bigs(&fra,&frb); 650 | 651 | let px=FP2::new_bigs(&pxa,&pxb); 652 | let py=FP2::new_bigs(&pya,&pyb); 653 | 654 | let mut P=ECP2::new_fp2s(&px,&py); 655 | 656 | println!("P= {}",P.tostring()); 657 | 658 | P=P.mul(&mut r); 659 | println!("P= {}",P.tostring()); 660 | 661 | let mut Q=ECP2::new_fp2s(&px,&py); 662 | Q.frob(&mut f); 663 | println!("Q= {}",Q.tostring()); 664 | } 665 | */ 666 | -------------------------------------------------------------------------------- /amcl/src/bls381/fp.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | use bls381::big; 21 | use bls381::big::BIG; 22 | use bls381::dbig::DBIG; 23 | use bls381::rom; 24 | use arch::Chunk; 25 | 26 | //#[cfg(D32)] 27 | //use arch::DChunk; 28 | 29 | #[derive(Copy, Clone)] 30 | pub struct FP { 31 | pub x:BIG, 32 | pub xes:i32 33 | } 34 | 35 | pub const NOT_SPECIAL:usize =0; 36 | pub const PSEUDO_MERSENNE:usize=1; 37 | pub const MONTGOMERY_FRIENDLY:usize=2; 38 | pub const GENERALISED_MERSENNE:usize=3; 39 | 40 | pub const MODBITS:usize = 381; /* Number of bits in Modulus */ 41 | pub const MOD8: usize = 3; /* Modulus mod 8 */ 42 | pub const MODTYPE:usize=NOT_SPECIAL; 43 | 44 | pub const FEXCESS:i32 = ((1 as i32)<<25); 45 | pub const OMASK:Chunk = (-1)<<(MODBITS%big::BASEBITS); 46 | pub const TBITS:usize=MODBITS%big::BASEBITS; // Number of active bits in top word 47 | pub const TMASK:Chunk=(1< FP { 54 | FP { 55 | x: BIG::new(), 56 | xes:1 57 | } 58 | } 59 | 60 | pub fn new_int(a:isize) -> FP { 61 | let mut f=FP::new(); 62 | f.x.inc(a); 63 | f.nres(); 64 | return f; 65 | } 66 | 67 | pub fn new_copy(y:&FP) -> FP { 68 | let mut f=FP::new(); 69 | f.x.copy(&(y.x)); 70 | f.xes=y.xes; 71 | return f; 72 | } 73 | 74 | pub fn new_big(y:&BIG) -> FP { 75 | let mut f=FP::new(); 76 | f.x.copy(y); 77 | f.nres(); 78 | return f; 79 | } 80 | 81 | pub fn nres(&mut self) { 82 | if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE { 83 | let r=BIG::new_ints(&rom::R2MODP); 84 | let mut d=BIG::mul(&(self.x),&r); 85 | self.x.copy(&FP::modulo(&mut d)); 86 | self.xes=2; 87 | } else { 88 | self.xes=1; 89 | } 90 | 91 | } 92 | 93 | /* convert back to regular form */ 94 | pub fn redc(&mut self) -> BIG { 95 | if MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE { 96 | let mut d=DBIG::new_scopy(&(self.x)); 97 | return FP::modulo(&mut d); 98 | } else { 99 | let r=BIG::new_copy(&(self.x)); 100 | return r; 101 | } 102 | } 103 | 104 | 105 | /* reduce a DBIG to a BIG using the appropriate form of the modulus */ 106 | /* dd */ 107 | pub fn modulo(d: &mut DBIG) -> BIG { 108 | 109 | if MODTYPE==PSEUDO_MERSENNE { 110 | let mut b=BIG::new(); 111 | let mut t=d.split(MODBITS); 112 | b.dcopy(&d); 113 | let v=t.pmul(rom::MCONST as isize); 114 | 115 | t.add(&b); 116 | t.norm(); 117 | 118 | 119 | let tw=t.w[big::NLEN-1]; 120 | t.w[big::NLEN-1] &= TMASK; 121 | t.w[0]+=rom::MCONST*((tw>>TBITS)+(v<<(big::BASEBITS-TBITS))); 122 | t.norm(); 123 | return t; 124 | } 125 | 126 | if MODTYPE==MONTGOMERY_FRIENDLY 127 | { 128 | let mut b=BIG::new(); 129 | for i in 0 ..big::NLEN { 130 | let x=d.w[i]; 131 | 132 | let tuple=BIG::muladd(x,rom::MCONST-1,x,d.w[big::NLEN+i-1]); 133 | d.w[big::NLEN+i]+=tuple.0; d.w[big::NLEN+i-1]=tuple.1; 134 | } 135 | 136 | b.zero(); 137 | 138 | for i in 0 ..big::NLEN { 139 | b.w[i]=d.w[big::NLEN+i]; 140 | } 141 | b.norm(); 142 | return b; 143 | } 144 | 145 | if MODTYPE==GENERALISED_MERSENNE 146 | { // GoldiLocks Only 147 | let mut b=BIG::new(); 148 | let t=d.split(MODBITS); 149 | let rm2=(MODBITS/2) as usize; 150 | b.dcopy(&d); 151 | b.add(&t); 152 | let mut dd=DBIG::new_scopy(&t); 153 | dd.shl(rm2); 154 | 155 | let mut tt=dd.split(MODBITS); 156 | let lo=BIG::new_dcopy(&dd); 157 | b.add(&tt); 158 | b.add(&lo); 159 | b.norm(); 160 | tt.shl(rm2); 161 | b.add(&tt); 162 | 163 | let carry=b.w[big::NLEN-1]>>TBITS; 164 | b.w[big::NLEN-1]&=TMASK; 165 | b.w[0]+=carry; 166 | 167 | b.w[(224/big::BASEBITS) as usize]+=carry<<(224%big::BASEBITS); 168 | b.norm(); 169 | return b; 170 | } 171 | 172 | if MODTYPE==NOT_SPECIAL { 173 | let m = BIG::new_ints(&rom::MODULUS); 174 | return BIG::monty(&m,rom::MCONST,d); 175 | } 176 | return BIG::new(); 177 | } 178 | 179 | /* convert to string */ 180 | pub fn tostring(&mut self) -> String { 181 | let s=self.redc().tostring(); 182 | return s; 183 | } 184 | 185 | /* reduce this mod Modulus */ 186 | pub fn reduce(&mut self) { 187 | let p = BIG::new_ints(&rom::MODULUS); 188 | self.x.rmod(&p); 189 | self.xes=1; 190 | } 191 | 192 | /* test this=0? */ 193 | pub fn iszilch(&mut self) -> bool { 194 | self.reduce(); 195 | return self.x.iszilch(); 196 | } 197 | 198 | /* copy from FP b */ 199 | pub fn copy(&mut self,b: &FP) { 200 | self.x.copy(&(b.x)); 201 | self.xes=b.xes; 202 | } 203 | 204 | /* copy from BIG b */ 205 | pub fn bcopy(&mut self,b: &BIG) { 206 | self.x.copy(&b); 207 | self.nres(); 208 | } 209 | 210 | /* set this=0 */ 211 | pub fn zero(&mut self) { 212 | self.x.zero(); 213 | self.xes=1; 214 | } 215 | 216 | /* set this=1 */ 217 | pub fn one(&mut self) { 218 | self.x.one(); self.nres() 219 | } 220 | 221 | /* normalise this */ 222 | pub fn norm(&mut self) { 223 | self.x.norm(); 224 | } 225 | /* swap FPs depending on d */ 226 | pub fn cswap(&mut self,b: &mut FP,d: isize) { 227 | self.x.cswap(&mut (b.x),d); 228 | let mut c=d as i32; 229 | c=!(c-1); 230 | let t=c&(self.xes^b.xes); 231 | self.xes^=t; 232 | b.xes^=t; 233 | } 234 | 235 | /* copy FPs depending on d */ 236 | pub fn cmove(&mut self,b: &FP,d: isize) { 237 | self.x.cmove(&(b.x),d); 238 | let c=d as i32; 239 | self.xes^=(self.xes^b.xes)&(-c); 240 | } 241 | 242 | /* this*=b mod Modulus */ 243 | pub fn mul(&mut self,b: &FP) 244 | { 245 | if (self.xes as i64)*(b.xes as i64) > FEXCESS as i64 {self.reduce()} 246 | 247 | let mut d=BIG::mul(&(self.x),&(b.x)); 248 | self.x.copy(&FP::modulo(&mut d)); 249 | self.xes=2; 250 | } 251 | 252 | fn logb2(w: u32) -> usize { 253 | let mut v=w; 254 | v |= v >> 1; 255 | v |= v >> 2; 256 | v |= v >> 4; 257 | v |= v >> 8; 258 | v |= v >> 16; 259 | 260 | v = v - ((v >> 1) & 0x55555555); 261 | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 262 | let r= (( ((v + (v >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24) as usize; 263 | return r; 264 | } 265 | 266 | /* this = -this mod Modulus */ 267 | pub fn neg(&mut self) { 268 | let mut p = BIG::new_ints(&rom::MODULUS); 269 | let sb=FP::logb2((self.xes-1) as u32); 270 | 271 | p.fshl(sb); 272 | self.x.rsub(&p); 273 | self.xes=1<<(sb as i32); 274 | if self.xes>FEXCESS {self.reduce()} 275 | 276 | } 277 | 278 | /* this*=c mod Modulus, where c is a small int */ 279 | pub fn imul(&mut self,c: isize) { 280 | let mut cc=c; 281 | // self.norm(); 282 | let mut s=false; 283 | if cc<0 { 284 | cc = -cc; 285 | s=true; 286 | } 287 | 288 | if MODTYPE==PSEUDO_MERSENNE || MODTYPE==GENERALISED_MERSENNE { 289 | let mut d=self.x.pxmul(cc); 290 | self.x.copy(&FP::modulo(&mut d)); 291 | self.xes=2 292 | } else { 293 | if self.xes*(cc as i32) <= FEXCESS { 294 | self.x.pmul(cc); 295 | self.xes*=cc as i32; 296 | } else { 297 | let n=FP::new_int(cc); 298 | self.mul(&n); 299 | } 300 | 301 | } 302 | 303 | if s {self.neg(); self.norm();} 304 | } 305 | 306 | /* self*=self mod Modulus */ 307 | pub fn sqr(&mut self) { 308 | // self.norm(); 309 | if (self.xes as i64)*(self.xes as i64) > FEXCESS as i64 {self.reduce()} 310 | 311 | 312 | let mut d=BIG::sqr(&(self.x)); 313 | self.x.copy(&FP::modulo(&mut d)); 314 | self.xes=2 315 | } 316 | 317 | /* self+=b */ 318 | pub fn add(&mut self,b: &FP) { 319 | self.x.add(&(b.x)); 320 | self.xes+=b.xes; 321 | if self.xes>FEXCESS {self.reduce()} 322 | } 323 | 324 | /* self+=self */ 325 | pub fn dbl(&mut self) { 326 | self.x.dbl(); 327 | self.xes+=self.xes; 328 | if self.xes>FEXCESS {self.reduce()} 329 | } 330 | 331 | /* self-=b */ 332 | pub fn sub(&mut self,b: &FP) 333 | { 334 | let mut n=FP::new_copy(b); 335 | n.neg(); 336 | self.add(&n); 337 | } 338 | 339 | /* self=b-self */ 340 | pub fn rsub(&mut self,b: &FP) 341 | { 342 | self.neg(); 343 | self.add(&b); 344 | } 345 | 346 | /* self/=2 mod Modulus */ 347 | pub fn div2(&mut self) { 348 | // self.x.norm(); 349 | if self.x.parity()==0 { 350 | self.x.fshr(1); 351 | } else { 352 | let p = BIG::new_ints(&rom::MODULUS); 353 | self.x.add(&p); 354 | self.x.norm(); 355 | self.x.fshr(1); 356 | } 357 | } 358 | /* self=1/self mod Modulus */ 359 | pub fn inverse(&mut self) { 360 | /* 361 | let mut p = BIG::new_ints(&rom::MODULUS); 362 | let mut r=self.redc(); 363 | r.invmodp(&mut p); 364 | self.x.copy(&r); 365 | self.nres(); 366 | */ 367 | let mut m2 = BIG::new_ints(&rom::MODULUS); 368 | m2.dec(2); m2.norm(); 369 | let inv=self.pow(&mut m2); 370 | self.copy(&inv); 371 | } 372 | 373 | /* return TRUE if self==a */ 374 | pub fn equals(&mut self,a: &mut FP) -> bool { 375 | a.reduce(); 376 | self.reduce(); 377 | if BIG::comp(&(a.x),&self.x)==0 {return true} 378 | return false; 379 | } 380 | 381 | 382 | /* return self^e mod Modulus */ 383 | pub fn pow(&mut self,e: &mut BIG) -> FP { 384 | let mut tb:[FP;16]=[FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new(),FP::new()]; 385 | const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4; 386 | let mut w:[i8;CT]=[0;CT]; 387 | 388 | self.norm(); 389 | let mut t=BIG::new_copy(e); 390 | t.norm(); 391 | let nb=1+(t.nbits()+3)/4; 392 | 393 | for i in 0..nb { 394 | let lsbs=t.lastbits(4); 395 | t.dec(lsbs); 396 | t.norm(); 397 | w[i]=lsbs as i8; 398 | t.fshr(4); 399 | } 400 | tb[0].one(); 401 | tb[1].copy(&self); 402 | 403 | let mut c=FP::new(); 404 | for i in 2..16 { 405 | c.copy(&tb[i-1]); 406 | tb[i].copy(&c); 407 | tb[i].mul(&self); 408 | } 409 | let mut r=FP::new_copy(&tb[w[nb-1] as usize]); 410 | for i in (0..nb-1).rev() { 411 | r.sqr(); 412 | r.sqr(); 413 | r.sqr(); 414 | r.sqr(); 415 | r.mul(&tb[w[i] as usize]) 416 | } 417 | r.reduce(); 418 | return r; 419 | } 420 | 421 | /* return self^e mod Modulus 422 | pub fn pow(&mut self,e: &mut BIG) -> FP { 423 | let p = BIG::new_ints(&rom::MODULUS); 424 | let mut r=FP::new_int(1); 425 | e.norm(); 426 | self.x.norm(); 427 | let mut m=FP::new_copy(self); 428 | loop { 429 | let bt=e.parity(); 430 | e.fshr(1); 431 | if bt==1 {r.mul(&m)} 432 | if e.iszilch() {break} 433 | m.sqr(); 434 | } 435 | r.x.rmod(&p); 436 | return r; 437 | } */ 438 | 439 | /* return sqrt(this) mod Modulus */ 440 | pub fn sqrt(&mut self) -> FP { 441 | self.reduce(); 442 | let mut p = BIG::new_ints(&rom::MODULUS); 443 | if MOD8==5 { 444 | p.dec(5); p.norm(); p.shr(3); 445 | let mut i=FP::new_copy(self); i.x.shl(1); 446 | let v=i.pow(&mut p); 447 | i.mul(&v); i.mul(&v); 448 | i.x.dec(1); 449 | let mut r=FP::new_copy(self); 450 | r.mul(&v); r.mul(&i); 451 | r.reduce(); 452 | return r; 453 | } 454 | else 455 | { 456 | p.inc(1); p.norm(); p.shr(2); 457 | return self.pow(&mut p); 458 | } 459 | } 460 | /* return jacobi symbol (this/Modulus) */ 461 | pub fn jacobi(&mut self) -> isize 462 | { 463 | let mut p = BIG::new_ints(&rom::MODULUS); 464 | let mut w=self.redc(); 465 | return w.jacobi(&mut p); 466 | } 467 | 468 | } 469 | /* 470 | fn main() { 471 | let p = BIG::new_ints(&rom::MODULUS); 472 | let mut e = BIG::new_copy(&p); 473 | e.dec(1); 474 | 475 | let mut x = FP::new_int(3); 476 | let mut s=x.pow(&mut e); 477 | 478 | println!("s= {}",s.tostring()); 479 | } 480 | */ 481 | -------------------------------------------------------------------------------- /amcl/src/bls381/fp2.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | use bls381::fp; 21 | use bls381::fp::FP; 22 | use bls381::big::BIG; 23 | use bls381::dbig::DBIG; 24 | use bls381::rom; 25 | 26 | #[derive(Copy, Clone)] 27 | pub struct FP2 { 28 | a:FP, 29 | b:FP, 30 | } 31 | 32 | impl FP2 { 33 | 34 | pub fn new() -> FP2 { 35 | FP2 { 36 | a: FP::new(), 37 | b: FP::new(), 38 | } 39 | } 40 | 41 | pub fn new_int(a: isize) -> FP2 { 42 | let mut f=FP2::new(); 43 | f.a.copy(&FP::new_int(a)); 44 | f.b.zero(); 45 | return f; 46 | } 47 | 48 | pub fn new_copy(x: &FP2) -> FP2 { 49 | let mut f=FP2::new(); 50 | f.a.copy(&x.a); 51 | f.b.copy(&x.b); 52 | return f 53 | } 54 | 55 | pub fn new_fps(c: &FP,d: &FP) -> FP2 { 56 | let mut f=FP2::new(); 57 | f.a.copy(c); 58 | f.b.copy(d); 59 | return f; 60 | } 61 | 62 | pub fn new_bigs(c: &BIG,d: &BIG) -> FP2 { 63 | let mut f=FP2::new(); 64 | f.a.copy(&FP::new_big(c)); 65 | f.b.copy(&FP::new_big(d)); 66 | return f; 67 | } 68 | 69 | pub fn new_fp(c: &FP) -> FP2 { 70 | let mut f=FP2::new(); 71 | f.a.copy(c); 72 | f.b.zero(); 73 | return f; 74 | } 75 | 76 | pub fn new_big(c: &BIG) -> FP2 { 77 | let mut f=FP2::new(); 78 | f.a.copy(&FP::new_big(c)); 79 | f.b.zero(); 80 | return f; 81 | } 82 | 83 | /* reduce components mod Modulus */ 84 | pub fn reduce(&mut self) { 85 | self.a.reduce(); 86 | self.b.reduce(); 87 | } 88 | 89 | /* normalise components of w */ 90 | pub fn norm(&mut self) { 91 | self.a.norm(); 92 | self.b.norm(); 93 | } 94 | 95 | /* test self=0 ? */ 96 | pub fn iszilch(&mut self) -> bool { 97 | self.reduce(); 98 | return self.a.iszilch() && self.b.iszilch(); 99 | } 100 | 101 | pub fn cmove(&mut self,g:&FP2,d: isize) { 102 | self.a.cmove(&g.a,d); 103 | self.b.cmove(&g.b,d); 104 | } 105 | 106 | /* test self=1 ? */ 107 | pub fn isunity(&mut self) -> bool { 108 | let mut one=FP::new_int(1); 109 | return self.a.equals(&mut one) && self.b.iszilch(); 110 | } 111 | 112 | /* test self=x */ 113 | pub fn equals(&mut self,x:&mut FP2) -> bool { 114 | return self.a.equals(&mut x.a) && self.b.equals(&mut x.b); 115 | } 116 | 117 | /* extract a */ 118 | pub fn geta(&mut self) -> BIG { 119 | return self.a.redc(); 120 | } 121 | 122 | /* extract b */ 123 | pub fn getb(&mut self) -> BIG { 124 | return self.b.redc(); 125 | } 126 | 127 | /* copy self=x */ 128 | pub fn copy(&mut self,x :&FP2) { 129 | self.a.copy(&x.a); 130 | self.b.copy(&x.b); 131 | } 132 | 133 | /* set self=0 */ 134 | pub fn zero(&mut self) { 135 | self.a.zero(); 136 | self.b.zero(); 137 | } 138 | 139 | /* set self=1 */ 140 | pub fn one(&mut self) { 141 | self.a.one(); 142 | self.b.zero(); 143 | } 144 | 145 | /* negate self mod Modulus */ 146 | pub fn neg(&mut self) { 147 | // self.norm(); 148 | let mut m=FP::new_copy(&self.a); 149 | let mut t=FP::new(); 150 | 151 | m.add(&self.b); 152 | m.neg(); 153 | // m.norm(); 154 | t.copy(&m); t.add(&self.b); 155 | self.b.copy(&m); 156 | self.b.add(&self.a); 157 | self.a.copy(&t); 158 | } 159 | 160 | /* set to a-ib */ 161 | pub fn conj(&mut self) { 162 | self.b.neg(); 163 | self.b.norm(); 164 | } 165 | 166 | /* self+=a */ 167 | pub fn add(&mut self,x:&FP2) { 168 | self.a.add(&x.a); 169 | self.b.add(&x.b); 170 | } 171 | 172 | pub fn dbl(&mut self) { 173 | self.a.dbl(); 174 | self.b.dbl(); 175 | } 176 | 177 | /* self-=a */ 178 | pub fn sub(&mut self,x:&FP2) { 179 | let mut m=FP2::new_copy(x); 180 | m.neg(); 181 | self.add(&m); 182 | } 183 | 184 | /* self=a-self */ 185 | pub fn rsub(&mut self,x:&FP2) { 186 | self.neg(); 187 | self.add(x); 188 | } 189 | 190 | /* self*=s, where s is an FP */ 191 | pub fn pmul(&mut self,s:&FP) { 192 | self.a.mul(s); 193 | self.b.mul(s); 194 | } 195 | 196 | /* self*=i, where i is an int */ 197 | pub fn imul(&mut self,c: isize) { 198 | self.a.imul(c); 199 | self.b.imul(c); 200 | } 201 | 202 | /* self*=self */ 203 | pub fn sqr(&mut self) { 204 | let mut w1=FP::new_copy(&self.a); 205 | let mut w3=FP::new_copy(&self.a); 206 | let mut mb=FP::new_copy(&self.b); 207 | 208 | // w3.mul(&self.b); 209 | w1.add(&self.b); 210 | 211 | w3.add(&self.a); 212 | w3.norm(); 213 | self.b.mul(&w3); 214 | 215 | mb.neg(); 216 | self.a.add(&mb); 217 | 218 | w1.norm(); 219 | self.a.norm(); 220 | 221 | self.a.mul(&w1); 222 | } 223 | 224 | /* this*=y */ 225 | pub fn mul(&mut self,y :&FP2) { 226 | 227 | 228 | if ((self.a.xes+self.b.xes) as i64)*((y.a.xes+y.b.xes) as i64) > fp::FEXCESS as i64 { 229 | if self.a.xes>1 {self.a.reduce()} 230 | if self.b.xes>1 {self.b.reduce()} 231 | } 232 | 233 | 234 | let p = BIG::new_ints(&rom::MODULUS); 235 | let mut pr=DBIG::new(); 236 | 237 | pr.ucopy(&p); 238 | 239 | let mut c=BIG::new_copy(&(self.a.x)); 240 | let mut d=BIG::new_copy(&(y.a.x)); 241 | 242 | let mut a=BIG::mul(&self.a.x,&y.a.x); 243 | let mut b=BIG::mul(&self.b.x,&y.b.x); 244 | 245 | c.add(&self.b.x); c.norm(); 246 | d.add(&y.b.x); d.norm(); 247 | 248 | let mut e=BIG::mul(&c,&d); 249 | let mut f=DBIG::new_copy(&a); f.add(&b); 250 | b.rsub(&pr); 251 | 252 | a.add(&b); a.norm(); 253 | e.sub(&f); e.norm(); 254 | 255 | self.a.x.copy(&FP::modulo(&mut a)); self.a.xes=3; 256 | self.b.x.copy(&FP::modulo(&mut e)); self.b.xes=2; 257 | 258 | } 259 | 260 | /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */ 261 | /* returns true if this is QR */ 262 | pub fn sqrt(&mut self) -> bool { 263 | if self.iszilch() {return true} 264 | let mut w1=FP::new_copy(&self.b); 265 | let mut w2=FP::new_copy(&self.a); 266 | w1.sqr(); w2.sqr(); w1.add(&w2); 267 | if w1.jacobi()!=1 { self.zero(); return false } 268 | w2.copy(&w1.sqrt()); w1.copy(&w2); 269 | w2.copy(&self.a); w2.add(&w1); w2.norm(); w2.div2(); 270 | if w2.jacobi()!=1 { 271 | w2.copy(&self.a); w2.sub(&w1); w2.norm(); w2.div2(); 272 | if w2.jacobi()!=1 { self.zero(); return false } 273 | } 274 | w1.copy(&w2.sqrt()); 275 | self.a.copy(&w1); 276 | w1.dbl(); 277 | w1.inverse(); 278 | self.b.mul(&w1); 279 | return true; 280 | } 281 | 282 | /* output to hex string */ 283 | pub fn tostring(&mut self) -> String { 284 | return format!("[{},{}]",self.a.tostring(),self.b.tostring()); 285 | } 286 | 287 | /* self=1/self */ 288 | pub fn inverse(&mut self) { 289 | self.norm(); 290 | let mut w1=FP::new_copy(&self.a); 291 | let mut w2=FP::new_copy(&self.b); 292 | 293 | w1.sqr(); 294 | w2.sqr(); 295 | w1.add(&w2); 296 | w1.inverse(); 297 | self.a.mul(&w1); 298 | w1.neg(); w1.norm(); 299 | self.b.mul(&w1); 300 | } 301 | 302 | /* self/=2 */ 303 | pub fn div2(&mut self) { 304 | self.a.div2(); 305 | self.b.div2(); 306 | } 307 | 308 | /* self*=sqrt(-1) */ 309 | pub fn times_i(&mut self) { 310 | // a.norm(); 311 | let z=FP::new_copy(&self.a); 312 | self.a.copy(&self.b); self.a.neg(); 313 | self.b.copy(&z); 314 | } 315 | 316 | /* w*=(1+sqrt(-1)) */ 317 | /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */ 318 | pub fn mul_ip(&mut self) { 319 | // self.norm(); 320 | let t=FP2::new_copy(self); 321 | let z=FP::new_copy(&self.a); 322 | self.a.copy(&self.b); 323 | self.a.neg(); 324 | self.b.copy(&z); 325 | self.add(&t); 326 | // self.norm(); 327 | } 328 | 329 | pub fn div_ip2(&mut self) { 330 | let mut t=FP2::new(); 331 | self.norm(); 332 | t.a.copy(&self.a); t.a.add(&self.b); 333 | t.b.copy(&self.b); t.b.sub(&self.a); 334 | t.norm(); self.copy(&t); 335 | } 336 | 337 | /* w/=(1+sqrt(-1)) */ 338 | pub fn div_ip(&mut self) { 339 | let mut t=FP2::new(); 340 | self.norm(); 341 | t.a.copy(&self.a); t.a.add(&self.b); 342 | t.b.copy(&self.b); t.b.sub(&self.a); 343 | t.norm(); self.copy(&t); 344 | self.div2(); 345 | } 346 | 347 | } 348 | /* 349 | fn main() 350 | { 351 | let mut x=FP2::new(); 352 | } 353 | */ 354 | -------------------------------------------------------------------------------- /amcl/src/bls381/fp4.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | use bls381::fp::FP; 21 | use bls381::fp2::FP2; 22 | use bls381::big::BIG; 23 | 24 | #[derive(Copy, Clone)] 25 | pub struct FP4 { 26 | a:FP2, 27 | b:FP2, 28 | } 29 | 30 | impl FP4 { 31 | 32 | pub fn new() -> FP4 { 33 | FP4 { 34 | a: FP2::new(), 35 | b: FP2::new(), 36 | } 37 | } 38 | 39 | pub fn new_int(a: isize) -> FP4 { 40 | let mut f=FP4::new(); 41 | f.a.copy(&FP2::new_int(a)); 42 | f.b.zero(); 43 | return f; 44 | } 45 | 46 | pub fn new_copy(x: &FP4) -> FP4 { 47 | let mut f=FP4::new(); 48 | f.a.copy(&x.a); 49 | f.b.copy(&x.b); 50 | return f; 51 | } 52 | 53 | pub fn new_fp2s(c: &FP2,d: &FP2) -> FP4 { 54 | let mut f=FP4::new(); 55 | f.a.copy(c); 56 | f.b.copy(d); 57 | return f; 58 | } 59 | 60 | pub fn new_fp2(c: &FP2) -> FP4 { 61 | let mut f=FP4::new(); 62 | f.a.copy(c); 63 | f.b.zero(); 64 | return f; 65 | } 66 | 67 | /* reduce components mod Modulus */ 68 | pub fn reduce(&mut self) { 69 | self.a.reduce(); 70 | self.b.reduce(); 71 | } 72 | 73 | /* normalise components of w */ 74 | pub fn norm(&mut self) { 75 | self.a.norm(); 76 | self.b.norm(); 77 | } 78 | 79 | pub fn cmove(&mut self,g:&FP4,d: isize) { 80 | self.a.cmove(&g.a,d); 81 | self.b.cmove(&g.b,d); 82 | } 83 | 84 | /* test self=0 ? */ 85 | pub fn iszilch(&mut self) -> bool { 86 | self.reduce(); 87 | return self.a.iszilch() && self.b.iszilch(); 88 | } 89 | 90 | /* test self=1 ? */ 91 | pub fn isunity(&mut self) -> bool { 92 | let mut one=FP2::new_int(1); 93 | return self.a.equals(&mut one) && self.b.iszilch(); 94 | } 95 | 96 | /* test is w real? That is in a+ib test b is zero */ 97 | pub fn isreal(&mut self) -> bool { 98 | return self.b.iszilch(); 99 | } 100 | /* extract real part a */ 101 | pub fn real(&self) -> FP2 { 102 | let f=FP2::new_copy(&self.a); 103 | return f; 104 | } 105 | 106 | pub fn geta(&self) -> FP2 { 107 | let f=FP2::new_copy(&self.a); 108 | return f; 109 | } 110 | /* extract imaginary part b */ 111 | pub fn getb(&self) -> FP2 { 112 | let f=FP2::new_copy(&self.b); 113 | return f; 114 | } 115 | 116 | /* test self=x */ 117 | pub fn equals(&mut self,x:&mut FP4) -> bool { 118 | return self.a.equals(&mut x.a) && self.b.equals(&mut x.b); 119 | } 120 | /* copy self=x */ 121 | pub fn copy(&mut self,x :&FP4) { 122 | self.a.copy(&x.a); 123 | self.b.copy(&x.b); 124 | } 125 | 126 | /* set self=0 */ 127 | pub fn zero(&mut self) { 128 | self.a.zero(); 129 | self.b.zero(); 130 | } 131 | 132 | /* set self=1 */ 133 | pub fn one(&mut self) { 134 | self.a.one(); 135 | self.b.zero(); 136 | } 137 | 138 | /* negate self mod Modulus */ 139 | pub fn neg(&mut self) { 140 | self.norm(); 141 | let mut m=FP2::new_copy(&self.a); 142 | let mut t=FP2::new(); 143 | 144 | m.add(&self.b); 145 | m.neg(); 146 | // m.norm(); 147 | t.copy(&m); t.add(&self.b); 148 | self.b.copy(&m); 149 | self.b.add(&self.a); 150 | self.a.copy(&t); 151 | self.norm(); 152 | } 153 | 154 | /* set to a-ib */ 155 | pub fn conj(&mut self) { 156 | self.b.neg(); 157 | self.norm(); 158 | } 159 | 160 | /* self=-conjugate(self) */ 161 | pub fn nconj(&mut self) { 162 | self.a.neg(); self.norm(); 163 | } 164 | 165 | /* self+=a */ 166 | pub fn add(&mut self,x:&FP4) { 167 | self.a.add(&x.a); 168 | self.b.add(&x.b); 169 | } 170 | 171 | pub fn padd(&mut self,x:&FP2) { 172 | self.a.add(x); 173 | } 174 | 175 | pub fn dbl(&mut self) { 176 | self.a.dbl(); 177 | self.b.dbl(); 178 | } 179 | 180 | /* self-=a */ 181 | pub fn sub(&mut self,x:&FP4) { 182 | let mut m=FP4::new_copy(x); 183 | m.neg(); 184 | self.add(&m); 185 | } 186 | 187 | /* self-=a */ 188 | pub fn rsub(&mut self,x:&FP4) { 189 | self.neg(); 190 | self.add(x); 191 | } 192 | 193 | /* self*=s, where s is an FP2 */ 194 | pub fn pmul(&mut self,s:&FP2) { 195 | self.a.mul(s); 196 | self.b.mul(s); 197 | } 198 | 199 | /* self*=s, where s is an FP */ 200 | pub fn qmul(&mut self,s:&FP) { 201 | self.a.pmul(s); 202 | self.b.pmul(s); 203 | } 204 | 205 | /* self*=i, where i is an int */ 206 | pub fn imul(&mut self,c: isize) { 207 | self.a.imul(c); 208 | self.b.imul(c); 209 | } 210 | 211 | /* self*=self */ 212 | pub fn sqr(&mut self) { 213 | // self.norm(); 214 | 215 | let mut t1=FP2::new_copy(&self.a); 216 | let mut t2=FP2::new_copy(&self.b); 217 | let mut t3=FP2::new_copy(&self.a); 218 | 219 | 220 | t3.mul(&self.b); 221 | t1.add(&self.b); 222 | t2.mul_ip(); 223 | 224 | t2.add(&self.a); 225 | 226 | t1.norm(); 227 | t2.norm(); 228 | 229 | self.a.copy(&t1); 230 | 231 | self.a.mul(&t2); 232 | 233 | t2.copy(&t3); 234 | t2.mul_ip(); 235 | t2.add(&t3); t2.norm(); 236 | t2.neg(); 237 | self.a.add(&t2); 238 | 239 | t3.dbl(); 240 | self.b.copy(&t3); 241 | 242 | self.norm(); 243 | } 244 | 245 | /* self*=y */ 246 | pub fn mul(&mut self,y :&FP4) { 247 | self.norm(); 248 | 249 | let mut t1=FP2::new_copy(&self.a); 250 | let mut t2=FP2::new_copy(&self.b); 251 | let mut t3=FP2::new(); 252 | let mut t4=FP2::new_copy(&self.b); 253 | 254 | t1.mul(&y.a); 255 | t2.mul(&y.b); 256 | t3.copy(&y.b); 257 | t3.add(&y.a); 258 | t4.add(&self.a); 259 | 260 | t3.norm(); t4.norm(); 261 | 262 | t4.mul(&t3); 263 | 264 | t3.copy(&t1); 265 | t3.neg(); 266 | t4.add(&t3); 267 | t4.norm(); 268 | 269 | t3.copy(&t2); 270 | t3.neg(); 271 | self.b.copy(&t4); 272 | self.b.add(&t3); 273 | 274 | t2.mul_ip(); 275 | self.a.copy(&t2); 276 | self.a.add(&t1); 277 | 278 | self.norm(); 279 | } 280 | 281 | /* output to hex string */ 282 | pub fn tostring(&mut self) -> String { 283 | return format!("[{},{}]",self.a.tostring(),self.b.tostring()); 284 | } 285 | 286 | /* self=1/self */ 287 | pub fn inverse(&mut self) { 288 | self.norm(); 289 | 290 | let mut t1=FP2::new_copy(&self.a); 291 | let mut t2=FP2::new_copy(&self.b); 292 | 293 | t1.sqr(); 294 | t2.sqr(); 295 | t2.mul_ip(); t2.norm(); 296 | t1.sub(&t2); 297 | t1.inverse(); 298 | self.a.mul(&t1); 299 | t1.neg(); t1.norm(); 300 | self.b.mul(&t1); 301 | } 302 | 303 | /* self*=i where i = sqrt(-1+sqrt(-1)) */ 304 | pub fn times_i(&mut self) { 305 | // self.norm(); 306 | let mut s=FP2::new_copy(&self.b); 307 | let mut t=FP2::new_copy(&self.b); 308 | s.times_i(); 309 | t.add(&s); 310 | // t.norm(); 311 | self.b.copy(&self.a); 312 | self.a.copy(&t); 313 | self.norm(); 314 | } 315 | 316 | /* self=self^p using Frobenius */ 317 | pub fn frob(&mut self,f: &FP2) { 318 | self.a.conj(); 319 | self.b.conj(); 320 | self.b.mul(f); 321 | } 322 | 323 | /* self=self^e */ 324 | pub fn pow(&mut self,e: &mut BIG) -> FP4 { 325 | self.norm(); 326 | e.norm(); 327 | let mut w=FP4::new_copy(self); 328 | let mut z=BIG::new_copy(&e); 329 | let mut r=FP4::new_int(1); 330 | loop { 331 | let bt=z.parity(); 332 | z.fshr(1); 333 | if bt==1 {r.mul(&mut w)}; 334 | if z.iszilch() {break} 335 | w.sqr(); 336 | } 337 | r.reduce(); 338 | return r; 339 | } 340 | 341 | /* XTR xtr_a function */ 342 | pub fn xtr_a(&mut self,w:&FP4,y:&FP4,z:&FP4) { 343 | let mut r=FP4::new_copy(w); 344 | let mut t=FP4::new_copy(w); 345 | // y.norm(); 346 | r.sub(y); r.norm(); 347 | r.pmul(&self.a); 348 | t.add(y); t.norm(); 349 | t.pmul(&self.b); 350 | t.times_i(); 351 | 352 | self.copy(&r); 353 | self.add(&t); 354 | self.add(z); 355 | 356 | self.norm(); 357 | } 358 | 359 | /* XTR xtr_d function */ 360 | pub fn xtr_d(&mut self) { 361 | let mut w=FP4::new_copy(self); 362 | self.sqr(); w.conj(); 363 | w.dbl(); w.norm(); 364 | self.sub(&w); 365 | self.reduce(); 366 | } 367 | 368 | /* r=x^n using XTR method on traces of FP12s */ 369 | pub fn xtr_pow(&mut self,n: &mut BIG) -> FP4 { 370 | let mut a=FP4::new_int(3); 371 | let mut b=FP4::new_copy(self); 372 | let mut c=FP4::new_copy(&b); 373 | c.xtr_d(); 374 | let mut t=FP4::new(); 375 | let mut r=FP4::new(); 376 | 377 | n.norm(); 378 | let par=n.parity(); 379 | let mut v=BIG::new_copy(n); v.fshr(1); 380 | if par==0 {v.dec(1); v.norm(); } 381 | 382 | let nb=v.nbits(); 383 | for i in (0..nb).rev() { 384 | if v.bit(i)!=1 { 385 | t.copy(&b); 386 | self.conj(); 387 | c.conj(); 388 | b.xtr_a(&a,self,&c); 389 | self.conj(); 390 | c.copy(&t); 391 | c.xtr_d(); 392 | a.xtr_d(); 393 | } else { 394 | t.copy(&a); t.conj(); 395 | a.copy(&b); 396 | a.xtr_d(); 397 | b.xtr_a(&c,self,&t); 398 | c.xtr_d(); 399 | } 400 | } 401 | if par==0 { 402 | r.copy(&c) 403 | } else {r.copy(&b)} 404 | r.reduce(); 405 | return r; 406 | } 407 | 408 | /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ 409 | pub fn xtr_pow2(&mut self,ck: &FP4,ckml: &FP4,ckm2l: &FP4,a: &mut BIG,b: &mut BIG) -> FP4 { 410 | a.norm(); b.norm(); 411 | let mut e=BIG::new_copy(a); 412 | let mut d=BIG::new_copy(b); 413 | let mut w=BIG::new(); 414 | 415 | let mut cu=FP4::new_copy(ck); // can probably be passed in w/o copying 416 | let mut cv=FP4::new_copy(self); 417 | let mut cumv=FP4::new_copy(ckml); 418 | let mut cum2v=FP4::new_copy(ckm2l); 419 | let mut r=FP4::new(); 420 | let mut t=FP4::new(); 421 | 422 | let mut f2:usize=0; 423 | while d.parity()==0 && e.parity()==0 { 424 | d.fshr(1); 425 | e.fshr(1); 426 | f2+=1; 427 | } 428 | 429 | while BIG::comp(&d,&e)!=0 { 430 | if BIG::comp(&d,&e)>0 { 431 | w.copy(&e); w.imul(4); w.norm(); 432 | if BIG::comp(&d,&w)<=0 { 433 | w.copy(&d); d.copy(&e); 434 | e.rsub(&w); e.norm(); 435 | 436 | t.copy(&cv); 437 | t.xtr_a(&cu,&cumv,&cum2v); 438 | cum2v.copy(&cumv); 439 | cum2v.conj(); 440 | cumv.copy(&cv); 441 | cv.copy(&cu); 442 | cu.copy(&t); 443 | } else { 444 | if d.parity()==0 { 445 | d.fshr(1); 446 | r.copy(&cum2v); r.conj(); 447 | t.copy(&cumv); 448 | t.xtr_a(&cu,&cv,&r); 449 | cum2v.copy(&cumv); 450 | cum2v.xtr_d(); 451 | cumv.copy(&t); 452 | cu.xtr_d(); 453 | } else { 454 | if e.parity()==1 { 455 | d.sub(&e); d.norm(); 456 | d.fshr(1); 457 | t.copy(&cv); 458 | t.xtr_a(&cu,&cumv,&cum2v); 459 | cu.xtr_d(); 460 | cum2v.copy(&cv); 461 | cum2v.xtr_d(); 462 | cum2v.conj(); 463 | cv.copy(&t); 464 | } else { 465 | w.copy(&d); 466 | d.copy(&e); d.fshr(1); 467 | e.copy(&w); 468 | t.copy(&cumv); 469 | t.xtr_d(); 470 | cumv.copy(&cum2v); cumv.conj(); 471 | cum2v.copy(&t); cum2v.conj(); 472 | t.copy(&cv); 473 | t.xtr_d(); 474 | cv.copy(&cu); 475 | cu.copy(&t); 476 | } 477 | } 478 | } 479 | } 480 | if BIG::comp(&d,&e)<0 { 481 | w.copy(&d); w.imul(4); w.norm(); 482 | if BIG::comp(&e,&w)<=0 { 483 | e.sub(&d); e.norm(); 484 | t.copy(&cv); 485 | t.xtr_a(&cu,&cumv,&cum2v); 486 | cum2v.copy(&cumv); 487 | cumv.copy(&cu); 488 | cu.copy(&t); 489 | } else { 490 | if e.parity()==0 { 491 | w.copy(&d); 492 | d.copy(&e); d.fshr(1); 493 | e.copy(&w); 494 | t.copy(&cumv); 495 | t.xtr_d(); 496 | cumv.copy(&cum2v); cumv.conj(); 497 | cum2v.copy(&t); cum2v.conj(); 498 | t.copy(&cv); 499 | t.xtr_d(); 500 | cv.copy(&cu); 501 | cu.copy(&t); 502 | } else { 503 | if d.parity()==1 { 504 | w.copy(&e); 505 | e.copy(&d); 506 | w.sub(&d); w.norm(); 507 | d.copy(&w); d.fshr(1); 508 | t.copy(&cv); 509 | t.xtr_a(&cu,&cumv,&cum2v); 510 | cumv.conj(); 511 | cum2v.copy(&cu); 512 | cum2v.xtr_d(); 513 | cum2v.conj(); 514 | cu.copy(&cv); 515 | cu.xtr_d(); 516 | cv.copy(&t); 517 | } else { 518 | d.fshr(1); 519 | r.copy(&cum2v); r.conj(); 520 | t.copy(&cumv); 521 | t.xtr_a(&cu,&cv,&r); 522 | cum2v.copy(&cumv); 523 | cum2v.xtr_d(); 524 | cumv.copy(&t); 525 | cu.xtr_d(); 526 | } 527 | } 528 | } 529 | } 530 | } 531 | r.copy(&cv); 532 | r.xtr_a(&cu,&cumv,&cum2v); 533 | for _ in 0..f2 {r.xtr_d()} 534 | r=r.xtr_pow(&mut d); 535 | return r; 536 | } 537 | 538 | 539 | /* this/=2 */ 540 | pub fn div2(&mut self) { 541 | self.a.div2(); 542 | self.b.div2(); 543 | } 544 | 545 | pub fn div_i(&mut self) { 546 | let mut u=FP2::new_copy(&self.a); 547 | let v=FP2::new_copy(&self.b); 548 | u.div_ip(); 549 | self.a.copy(&v); 550 | self.b.copy(&u); 551 | } 552 | 553 | pub fn div_2i(&mut self) { 554 | let mut u=FP2::new_copy(&self.a); 555 | let mut v=FP2::new_copy(&self.b); 556 | u.div_ip2(); 557 | v.dbl(); v.norm(); 558 | self.a.copy(&v); 559 | self.b.copy(&u); 560 | } 561 | 562 | /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */ 563 | /* returns true if this is QR */ 564 | pub fn sqrt(&mut self) -> bool { 565 | if self.iszilch() {return true;} 566 | 567 | let mut a=FP2::new_copy(&self.a); 568 | let mut s=FP2::new_copy(&self.b); 569 | let mut t=FP2::new_copy(&self.a); 570 | 571 | if s.iszilch() { 572 | if t.sqrt() { 573 | self.a.copy(&t); 574 | self.b.zero(); 575 | } else { 576 | t.div_ip(); 577 | t.sqrt(); 578 | self.b.copy(&t); 579 | self.a.zero(); 580 | } 581 | return true; 582 | } 583 | s.sqr(); 584 | a.sqr(); 585 | s.mul_ip(); 586 | s.norm(); 587 | a.sub(&s); 588 | 589 | s.copy(&a); 590 | if !s.sqrt() { 591 | return false; 592 | } 593 | 594 | a.copy(&t); a.add(&s); a.norm(); a.div2(); 595 | 596 | if !a.sqrt() { 597 | a.copy(&t); a.sub(&s); a.norm(); a.div2(); 598 | if !a.sqrt() { 599 | return false 600 | } 601 | } 602 | t.copy(&self.b); 603 | s.copy(&a); s.add(&a); 604 | s.inverse(); 605 | 606 | t.mul(&s); 607 | self.a.copy(&a); 608 | self.b.copy(&t); 609 | 610 | return true; 611 | } 612 | 613 | 614 | } 615 | /* 616 | fn main() 617 | { 618 | let mut w=FP4::new(); 619 | } 620 | */ 621 | -------------------------------------------------------------------------------- /amcl/src/bls381/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod big; 2 | pub mod dbig; 3 | pub mod fp; 4 | pub mod ecp; 5 | pub mod ecp2; 6 | pub mod fp2; 7 | pub mod fp4; 8 | pub mod fp12; 9 | pub mod pair; 10 | pub mod mpin; 11 | pub mod rom; 12 | -------------------------------------------------------------------------------- /amcl/src/bls381/pair.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | 21 | use bls381::fp::FP; 22 | use bls381::ecp::ECP; 23 | use bls381::fp2::FP2; 24 | use bls381::ecp2::ECP2; 25 | use bls381::fp4::FP4; 26 | use bls381::fp12::FP12; 27 | use bls381::big::BIG; 28 | use bls381::dbig::DBIG; 29 | use bls381::ecp; 30 | use bls381::rom; 31 | 32 | #[allow(non_snake_case)] 33 | fn linedbl(A: &mut ECP2,qx: &FP,qy: &FP) -> FP12 { 34 | let mut a=FP4::new(); 35 | let mut b=FP4::new(); 36 | let mut c=FP4::new(); 37 | 38 | let mut xx=FP2::new_copy(&A.getpx()); //X 39 | let mut yy=FP2::new_copy(&A.getpy()); //Y 40 | let mut zz=FP2::new_copy(&A.getpz()); //Z 41 | let mut yz=FP2::new_copy(&yy); //Y 42 | yz.mul(&zz); //YZ 43 | xx.sqr(); //X^2 44 | yy.sqr(); //Y^2 45 | zz.sqr(); //Z^2 46 | 47 | yz.imul(4); 48 | yz.neg(); yz.norm(); //-2YZ 49 | yz.pmul(qy); //-2YZ.Ys 50 | 51 | xx.imul(6); //3X^2 52 | xx.pmul(qx); //3X^2.Xs 53 | 54 | let sb=3*rom::CURVE_B_I; 55 | zz.imul(sb); 56 | if ecp::SEXTIC_TWIST==ecp::D_TYPE { 57 | zz.div_ip2(); 58 | } 59 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 60 | zz.mul_ip(); 61 | zz.dbl(); 62 | yz.mul_ip(); 63 | yz.norm(); 64 | } 65 | 66 | zz.norm(); // 3b.Z^2 67 | 68 | yy.dbl(); 69 | zz.sub(&yy); zz.norm(); // 3b.Z^2-Y^2 70 | 71 | a.copy(&FP4::new_fp2s(&yz,&zz)); // -2YZ.Ys | 3b.Z^2-Y^2 | 3X^2.Xs 72 | if ecp::SEXTIC_TWIST==ecp::D_TYPE { 73 | b.copy(&FP4::new_fp2(&xx)); // L(0,1) | L(0,0) | L(1,0) 74 | } 75 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 76 | c.copy(&FP4::new_fp2(&xx)); 77 | c.times_i(); 78 | } 79 | A.dbl(); 80 | return FP12::new_fp4s(&a,&b,&c); 81 | } 82 | 83 | #[allow(non_snake_case)] 84 | fn lineadd(A: &mut ECP2,B: &ECP2,qx: &FP,qy: &FP) -> FP12 { 85 | 86 | let mut a=FP4::new(); 87 | let mut b=FP4::new(); 88 | let mut c=FP4::new(); 89 | 90 | let mut x1=FP2::new_copy(&A.getpx()); // X1 91 | let mut y1=FP2::new_copy(&A.getpy()); // Y1 92 | let mut t1=FP2::new_copy(&A.getpz()); // Z1 93 | let mut t2=FP2::new_copy(&A.getpz()); // Z1 94 | 95 | t1.mul(&B.getpy()); // T1=Z1.Y2 96 | t2.mul(&B.getpx()); // T2=Z1.X2 97 | 98 | x1.sub(&t2); x1.norm(); // X1=X1-Z1.X2 99 | y1.sub(&t1); y1.norm(); // Y1=Y1-Z1.Y2 100 | 101 | t1.copy(&x1); // T1=X1-Z1.X2 102 | x1.pmul(qy); // X1=(X1-Z1.X2).Ys 103 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 104 | x1.mul_ip(); 105 | x1.norm(); 106 | } 107 | 108 | t1.mul(&B.getpy()); // T1=(X1-Z1.X2).Y2 109 | 110 | t2.copy(&y1); // T2=Y1-Z1.Y2 111 | t2.mul(&B.getpx()); // T2=(Y1-Z1.Y2).X2 112 | t2.sub(&t1); t2.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 113 | y1.pmul(qx); y1.neg(); y1.norm(); // Y1=-(Y1-Z1.Y2).Xs 114 | 115 | a.copy(&FP4::new_fp2s(&x1,&t2)); // (X1-Z1.X2).Ys | (Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 | - (Y1-Z1.Y2).Xs 116 | if ecp::SEXTIC_TWIST==ecp::D_TYPE { 117 | b.copy(&FP4::new_fp2(&y1)); 118 | } 119 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 120 | c.copy(&FP4::new_fp2(&y1)); 121 | c.times_i(); 122 | } 123 | 124 | A.add(B); 125 | return FP12::new_fp4s(&a,&b,&c); 126 | } 127 | 128 | #[allow(non_snake_case)] 129 | /* Optimal R-ate pairing */ 130 | pub fn ate(P: &ECP2,Q: &ECP) -> FP12 { 131 | let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB)); 132 | let x = BIG::new_ints(&rom::CURVE_BNX); 133 | let mut n = BIG::new_copy(&x); 134 | let mut K = ECP2::new(); 135 | 136 | if ecp::CURVE_PAIRING_TYPE == ecp::BN { 137 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 138 | f.inverse(); 139 | f.norm(); 140 | } 141 | n.pmul(6); 142 | if ecp::SIGN_OF_X == ecp::POSITIVEX { 143 | n.inc(2); 144 | } else { 145 | n.dec(2); 146 | } 147 | 148 | } else {n.copy(&x)} 149 | 150 | n.norm(); 151 | let mut n3 = BIG::new_copy(&n); 152 | n3.pmul(3); 153 | n3.norm(); 154 | 155 | let qx=FP::new_copy(&Q.getpx()); 156 | let qy=FP::new_copy(&Q.getpy()); 157 | 158 | let mut A=ECP2::new(); 159 | let mut r=FP12::new_int(1); 160 | 161 | A.copy(&P); 162 | let mut NP=ECP2::new(); 163 | NP.copy(&P); 164 | NP.neg(); 165 | 166 | let nb=n3.nbits(); 167 | 168 | for i in (1..nb-1).rev() { 169 | r.sqr(); 170 | let mut lv=linedbl(&mut A,&qx,&qy); 171 | r.smul(&lv,ecp::SEXTIC_TWIST); 172 | let bt=n3.bit(i)-n.bit(i); 173 | if bt==1 { 174 | lv=lineadd(&mut A,P,&qx,&qy); 175 | r.smul(&lv,ecp::SEXTIC_TWIST); 176 | } 177 | if bt == -1 { 178 | 179 | lv=lineadd(&mut A,&NP,&qx,&qy); 180 | r.smul(&lv,ecp::SEXTIC_TWIST); 181 | 182 | } 183 | } 184 | 185 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 186 | r.conj(); 187 | } 188 | 189 | 190 | /* R-ate fixup required for BN curves */ 191 | 192 | if ecp::CURVE_PAIRING_TYPE == ecp::BN { 193 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 194 | //r.conj(); 195 | A.neg(); 196 | } 197 | 198 | K.copy(&P); 199 | K.frob(&f); 200 | 201 | let mut lv=lineadd(&mut A,&K,&qx,&qy); 202 | r.smul(&lv,ecp::SEXTIC_TWIST); 203 | K.frob(&f); 204 | K.neg(); 205 | lv=lineadd(&mut A,&K,&qx,&qy); 206 | r.smul(&lv,ecp::SEXTIC_TWIST); 207 | } 208 | 209 | return r; 210 | } 211 | 212 | #[allow(non_snake_case)] 213 | /* Optimal R-ate double pairing e(P,Q).e(R,S) */ 214 | pub fn ate2(P: &ECP2,Q: &ECP,R: &ECP2,S: &ECP) -> FP12 { 215 | let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB)); 216 | let x = BIG::new_ints(&rom::CURVE_BNX); 217 | let mut n = BIG::new_copy(&x); 218 | let mut K = ECP2::new(); 219 | 220 | if ecp::CURVE_PAIRING_TYPE == ecp::BN { 221 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 222 | f.inverse(); 223 | f.norm(); 224 | } 225 | n.pmul(6); 226 | if ecp::SIGN_OF_X == ecp::POSITIVEX { 227 | n.inc(2); 228 | } else { 229 | n.dec(2); 230 | } 231 | } else {n.copy(&x)} 232 | 233 | n.norm(); 234 | let mut n3 = BIG::new_copy(&n); 235 | n3.pmul(3); 236 | n3.norm(); 237 | 238 | 239 | let qx=FP::new_copy(&Q.getpx()); 240 | let qy=FP::new_copy(&Q.getpy()); 241 | 242 | let sx=FP::new_copy(&S.getpx()); 243 | let sy=FP::new_copy(&S.getpy()); 244 | 245 | let mut A=ECP2::new(); 246 | let mut B=ECP2::new(); 247 | let mut r=FP12::new_int(1); 248 | 249 | A.copy(&P); 250 | B.copy(&R); 251 | 252 | let mut NP=ECP2::new(); 253 | NP.copy(&P); 254 | NP.neg(); 255 | let mut NR=ECP2::new(); 256 | NR.copy(&R); 257 | NR.neg(); 258 | 259 | let nb=n3.nbits(); 260 | 261 | for i in (1..nb-1).rev() { 262 | r.sqr(); 263 | let mut lv=linedbl(&mut A,&qx,&qy); 264 | r.smul(&lv,ecp::SEXTIC_TWIST); 265 | lv=linedbl(&mut B,&sx,&sy); 266 | r.smul(&lv,ecp::SEXTIC_TWIST); 267 | let bt=n3.bit(i)-n.bit(i); 268 | if bt == 1 { 269 | lv=lineadd(&mut A,P,&qx,&qy); 270 | r.smul(&lv,ecp::SEXTIC_TWIST); 271 | lv=lineadd(&mut B,R,&sx,&sy); 272 | r.smul(&lv,ecp::SEXTIC_TWIST); 273 | } 274 | if bt == -1 { 275 | 276 | lv=lineadd(&mut A,&NP,&qx,&qy); 277 | r.smul(&lv,ecp::SEXTIC_TWIST); 278 | lv=lineadd(&mut B,&NR,&sx,&sy); 279 | r.smul(&lv,ecp::SEXTIC_TWIST); 280 | 281 | } 282 | } 283 | 284 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 285 | r.conj(); 286 | } 287 | 288 | /* R-ate fixup */ 289 | if ecp::CURVE_PAIRING_TYPE == ecp::BN { 290 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 291 | //r.conj(); 292 | A.neg(); 293 | B.neg(); 294 | } 295 | K.copy(&P); 296 | K.frob(&f); 297 | 298 | let mut lv=lineadd(&mut A,&K,&qx,&qy); 299 | r.smul(&lv,ecp::SEXTIC_TWIST); 300 | K.frob(&f); 301 | K.neg(); 302 | lv=lineadd(&mut A,&K,&qx,&qy); 303 | r.smul(&lv,ecp::SEXTIC_TWIST); 304 | 305 | K.copy(&R); 306 | K.frob(&f); 307 | 308 | lv=lineadd(&mut B,&K,&sx,&sy); 309 | r.smul(&lv,ecp::SEXTIC_TWIST); 310 | K.frob(&f); 311 | K.neg(); 312 | lv=lineadd(&mut B,&K,&sx,&sy); 313 | r.smul(&lv,ecp::SEXTIC_TWIST); 314 | } 315 | 316 | return r; 317 | } 318 | 319 | /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ 320 | pub fn fexp(m: &FP12) -> FP12 { 321 | let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB)); 322 | let mut x = BIG::new_ints(&rom::CURVE_BNX); 323 | let mut r=FP12::new_copy(m); 324 | 325 | /* Easy part of final exp */ 326 | let mut lv=FP12::new_copy(&r); 327 | lv.inverse(); 328 | r.conj(); 329 | 330 | r.mul(&lv); 331 | lv.copy(&r); 332 | r.frob(&f); 333 | r.frob(&f); 334 | r.mul(&lv); 335 | /* Hard part of final exp */ 336 | if ecp::CURVE_PAIRING_TYPE == ecp::BN { 337 | lv.copy(&r); 338 | lv.frob(&f); 339 | let mut x0=FP12::new_copy(&lv); 340 | x0.frob(&f); 341 | lv.mul(&r); 342 | x0.mul(&lv); 343 | x0.frob(&f); 344 | let mut x1=FP12::new_copy(&r); 345 | x1.conj(); 346 | let mut x4=r.pow(&mut x); 347 | if ecp::SIGN_OF_X == ecp::POSITIVEX { 348 | x4.conj(); 349 | } 350 | 351 | let mut x3=FP12::new_copy(&x4); 352 | x3.frob(&f); 353 | 354 | let mut x2=x4.pow(&mut x); 355 | if ecp::SIGN_OF_X == ecp::POSITIVEX { 356 | x2.conj(); 357 | } 358 | let mut x5=FP12::new_copy(&x2); x5.conj(); 359 | lv=x2.pow(&mut x); 360 | if ecp::SIGN_OF_X == ecp::POSITIVEX { 361 | lv.conj(); 362 | } 363 | x2.frob(&f); 364 | r.copy(&x2); r.conj(); 365 | 366 | x4.mul(&r); 367 | x2.frob(&f); 368 | 369 | r.copy(&lv); 370 | r.frob(&f); 371 | lv.mul(&r); 372 | 373 | lv.usqr(); 374 | lv.mul(&x4); 375 | lv.mul(&x5); 376 | r.copy(&x3); 377 | r.mul(&x5); 378 | r.mul(&lv); 379 | lv.mul(&x2); 380 | r.usqr(); 381 | r.mul(&lv); 382 | r.usqr(); 383 | lv.copy(&r); 384 | lv.mul(&x1); 385 | r.mul(&x0); 386 | lv.usqr(); 387 | r.mul(&lv); 388 | r.reduce(); 389 | } else { 390 | 391 | // Ghamman & Fouotsa Method 392 | 393 | let mut y0=FP12::new_copy(&r); y0.usqr(); 394 | let mut y1=y0.pow(&mut x); 395 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 396 | y1.conj(); 397 | } 398 | x.fshr(1); let mut y2=y1.pow(&mut x); 399 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 400 | y2.conj(); 401 | } 402 | x.fshl(1); 403 | let mut y3=FP12::new_copy(&r); y3.conj(); 404 | y1.mul(&y3); 405 | 406 | y1.conj(); 407 | y1.mul(&y2); 408 | 409 | y2=y1.pow(&mut x); 410 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 411 | y2.conj(); 412 | } 413 | y3=y2.pow(&mut x); 414 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 415 | y3.conj(); 416 | } 417 | y1.conj(); 418 | y3.mul(&y1); 419 | 420 | y1.conj(); 421 | y1.frob(&f); y1.frob(&f); y1.frob(&f); 422 | y2.frob(&f); y2.frob(&f); 423 | y1.mul(&y2); 424 | 425 | y2=y3.pow(&mut x); 426 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 427 | y2.conj(); 428 | } 429 | y2.mul(&y0); 430 | y2.mul(&r); 431 | 432 | y1.mul(&y2); 433 | y2.copy(&y3); y2.frob(&f); 434 | y1.mul(&y2); 435 | r.copy(&y1); 436 | r.reduce(); 437 | 438 | 439 | /* 440 | let mut x0=FP12::new_copy(&r); 441 | let mut x1=FP12::new_copy(&r); 442 | lv.copy(&r); lv.frob(&mut f); 443 | let mut x3=FP12::new_copy(&lv); x3.conj(); x1.mul(&mut x3); 444 | lv.frob(&mut f); lv.frob(&mut f); 445 | x1.mul(&mut lv); 446 | 447 | r=r.pow(&mut x); //r=r.pow(x); 448 | x3.copy(&r); x3.conj(); x1.mul(&mut x3); 449 | lv.copy(&r); lv.frob(&mut f); 450 | x0.mul(&mut lv); 451 | lv.frob(&mut f); 452 | x1.mul(&mut lv); 453 | lv.frob(&mut f); 454 | x3.copy(&lv); x3.conj(); x0.mul(&mut x3); 455 | 456 | r=r.pow(&mut x); 457 | x0.mul(&mut r); 458 | lv.copy(&r); lv.frob(&mut f); lv.frob(&mut f); 459 | x3.copy(&lv); x3.conj(); x0.mul(&mut x3); 460 | lv.frob(&mut f); 461 | x1.mul(&mut lv); 462 | 463 | r=r.pow(&mut x); 464 | lv.copy(&r); lv.frob(&mut f); 465 | x3.copy(&lv); x3.conj(); x0.mul(&mut x3); 466 | lv.frob(&mut f); 467 | x1.mul(&mut lv); 468 | 469 | r=r.pow(&mut x); 470 | x3.copy(&r); x3.conj(); x0.mul(&mut x3); 471 | lv.copy(&r); lv.frob(&mut f); 472 | x1.mul(&mut lv); 473 | 474 | r=r.pow(&mut x); 475 | x1.mul(&mut r); 476 | 477 | x0.usqr(); 478 | x0.mul(&mut x1); 479 | r.copy(&x0); 480 | r.reduce(); */ 481 | } 482 | return r; 483 | } 484 | 485 | #[allow(non_snake_case)] 486 | /* GLV method */ 487 | fn glv(e: &BIG) -> [BIG;2] { 488 | let mut u:[BIG;2]=[BIG::new(),BIG::new()]; 489 | if ecp::CURVE_PAIRING_TYPE == ecp::BN { 490 | let mut t=BIG::new(); 491 | let q=BIG::new_ints(&rom::CURVE_ORDER); 492 | let mut v:[BIG;2]=[BIG::new(),BIG::new()]; 493 | 494 | for i in 0..2 { 495 | t.copy(&BIG::new_ints(&rom::CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]); 496 | let mut d:DBIG = BIG::mul(&t,e); 497 | v[i].copy(&d.div(&q)); 498 | } 499 | u[0].copy(&e); 500 | for i in 0..2 { 501 | for j in 0..2 { 502 | t=BIG::new_ints(&rom::CURVE_SB[j][i]); 503 | t=BIG::modmul(&mut v[j],&mut t,&q); 504 | u[i].add(&q); 505 | u[i].sub(&t); 506 | u[i].rmod(&q); 507 | } 508 | } 509 | } else { 510 | let q=BIG::new_ints(&rom::CURVE_ORDER); 511 | let x=BIG::new_ints(&rom::CURVE_BNX); 512 | let x2=BIG::smul(&x,&x); 513 | u[0].copy(&e); 514 | u[0].rmod(&x2); 515 | u[1].copy(&e); 516 | u[1].div(&x2); 517 | u[1].rsub(&q); 518 | } 519 | return u; 520 | } 521 | 522 | #[allow(non_snake_case)] 523 | /* Galbraith & Scott Method */ 524 | pub fn gs(e: &BIG) -> [BIG;4] { 525 | let mut u:[BIG;4]=[BIG::new(),BIG::new(),BIG::new(),BIG::new()]; 526 | if ecp::CURVE_PAIRING_TYPE == ecp::BN { 527 | let mut t=BIG::new(); 528 | let q=BIG::new_ints(&rom::CURVE_ORDER); 529 | 530 | let mut v:[BIG;4]=[BIG::new(),BIG::new(),BIG::new(),BIG::new()]; 531 | for i in 0..4 { 532 | t.copy(&BIG::new_ints(&rom::CURVE_WB[i])); 533 | let mut d:DBIG=BIG::mul(&t,e); 534 | v[i].copy(&d.div(&q)); 535 | } 536 | u[0].copy(&e); 537 | for i in 0..4 { 538 | for j in 0..4 { 539 | t=BIG::new_ints(&rom::CURVE_BB[j][i]); 540 | t=BIG::modmul(&mut v[j],&mut t,&q); 541 | u[i].add(&q); 542 | u[i].sub(&t); 543 | u[i].rmod(&q); 544 | } 545 | } 546 | } else { 547 | let q=BIG::new_ints(&rom::CURVE_ORDER); 548 | let x=BIG::new_ints(&rom::CURVE_BNX); 549 | let mut w=BIG::new_copy(&e); 550 | for i in 0..3 { 551 | u[i].copy(&w); 552 | u[i].rmod(&x); 553 | w.div(&x); 554 | } 555 | u[3].copy(&w); 556 | if ecp::SIGN_OF_X == ecp::NEGATIVEX { 557 | let mut t=BIG::new(); 558 | t.copy(&BIG::modneg(&mut u[1],&q)); 559 | u[1].copy(&t); 560 | t.copy(&BIG::modneg(&mut u[3],&q)); 561 | u[3].copy(&t); 562 | } 563 | } 564 | return u; 565 | } 566 | 567 | #[allow(non_snake_case)] 568 | /* Multiply P by e in group G1 */ 569 | pub fn g1mul(P: &ECP,e: &mut BIG) -> ECP { 570 | let mut R=ECP::new(); 571 | if rom::USE_GLV { 572 | // P.affine(); 573 | R.copy(P); 574 | let mut Q=ECP::new(); 575 | Q.copy(P); 576 | let q=BIG::new_ints(&rom::CURVE_ORDER); 577 | let mut cru=FP::new_big(&BIG::new_ints(&rom::CURVE_CRU)); 578 | let mut u=glv(e); 579 | Q.mulx(&mut cru); 580 | 581 | let mut np=u[0].nbits(); 582 | let mut t:BIG=BIG::modneg(&mut u[0],&q); 583 | let mut nn=t.nbits(); 584 | if nn ECP2 { 609 | let mut R=ECP2::new(); 610 | if rom::USE_GS_G2 { 611 | let mut Q:[ECP2;4]=[ECP2::new(),ECP2::new(),ECP2::new(),ECP2::new()]; 612 | let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB)); 613 | let q=BIG::new_ints(&rom::CURVE_ORDER); 614 | let mut u=gs(e); 615 | let mut T=ECP2::new(); 616 | 617 | if ecp::SEXTIC_TWIST==ecp::M_TYPE { 618 | f.inverse(); 619 | f.norm(); 620 | } 621 | 622 | let mut t=BIG::new(); 623 | // P.affine(); 624 | Q[0].copy(&P); 625 | for i in 1..4 { 626 | T.copy(&Q[i-1]); 627 | Q[i].copy(&T); 628 | Q[i].frob(&f); 629 | } 630 | for i in 0..4 { 631 | let np=u[i].nbits(); 632 | t.copy(&BIG::modneg(&mut u[i],&q)); 633 | let nn=t.nbits(); 634 | if nn FP12 { 652 | let mut r=FP12::new(); 653 | if rom::USE_GS_GT { 654 | let mut g:[FP12;4]=[FP12::new(),FP12::new(),FP12::new(),FP12::new()]; 655 | let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA),&BIG::new_ints(&rom::FRB)); 656 | let q=BIG::new_ints(&rom::CURVE_ORDER); 657 | let mut t=BIG::new(); 658 | let mut u=gs(e); 659 | let mut w=FP12::new(); 660 | 661 | g[0].copy(&d); 662 | for i in 1..4 { 663 | w.copy(&g[i-1]); 664 | g[i].copy(&w); 665 | g[i].frob(&f); 666 | } 667 | for i in 0..4 { 668 | let np=u[i].nbits(); 669 | t.copy(&BIG::modneg(&mut u[i],&q)); 670 | let nn=t.nbits(); 671 | if nn u32 { /* pack bytes into a 32-bit Word */ 45 | return ((((b[0])&0xff) as u32)<<24)|((((b[1])&0xff) as u32)<<16)|((((b[2])&0xff) as u32)<<8)|(((b[3])&0xff) as u32); 46 | } 47 | 48 | fn unpack(a: u32) -> [u8;4] { /* unpack bytes from a word */ 49 | let b:[u8;4]=[((a>>24)&0xff) as u8,((a>>16)&0xff) as u8,((a>>8)&0xff) as u8,(a&0xff) as u8]; 50 | return b; 51 | } 52 | 53 | fn precompute(&mut self,h: &[u8]) { 54 | let mut b:[u8;4]=[0;4]; 55 | let mut j=0; 56 | for i in 0..GCM_NB { 57 | b[0]=h[j]; b[1]=h[j+1]; b[2]=h[j+2]; b[3]=h[j+3]; 58 | self.table[0][i]=GCM::pack(b); 59 | j+=4; 60 | } 61 | for i in 1..128 { 62 | let mut c:u32=0; 63 | for j in 0..GCM_NB {self.table[i][j]=c|(self.table[i-1][j])>>1; c=self.table[i-1][j]<<31;} 64 | if c != 0 {self.table[i][0]^=0xE1000000} /* irreducible polynomial */ 65 | } 66 | } 67 | 68 | fn gf2mul(&mut self) { /* gf2m mul - Z=H*X mod 2^128 */ 69 | let mut p:[u32;4]=[0;4]; 70 | 71 | for i in 0..4 {p[i]=0} 72 | let mut j:usize=8; 73 | let mut m=0; 74 | for i in 0..128 { 75 | j-=1; 76 | let mut c=((self.statex[m]>>j)&1) as u32; c= (!c) +1; 77 | for k in 0..GCM_NB {p[k]^=self.table[i][k]&c} 78 | if j==0 { 79 | j=8; m+=1; 80 | if m==16 {break} 81 | } 82 | } 83 | j=0; 84 | for i in 0..GCM_NB { 85 | let b=GCM::unpack(p[i]); 86 | self.statex[j]=b[0]; self.statex[j+1]=b[1]; self.statex[j+2]=b[2]; self.statex[j+3]=b[3]; 87 | j+=4; 88 | } 89 | } 90 | 91 | fn wrap(&mut self) { /* Finish off GHASH */ 92 | let mut f:[u32;4]=[0;4]; 93 | let mut el:[u8;16]=[0;16]; 94 | 95 | /* convert lengths from bytes to bits */ 96 | f[0]=(self.lena[0]<<3)|(self.lena[1]&0xE0000000)>>29; 97 | f[1]=self.lena[1]<<3; 98 | f[2]=(self.lenc[0]<<3)|(self.lenc[1]&0xE0000000)>>29; 99 | f[3]=self.lenc[1]<<3; 100 | let mut j=0; 101 | for i in 0..GCM_NB { 102 | let b=GCM::unpack(f[i]); 103 | el[j]=b[0]; el[j+1]=b[1]; el[j+2]=b[2]; el[j+3]=b[3]; 104 | j+=4; 105 | } 106 | for i in 0..16 {self.statex[i]^=el[i]} 107 | self.gf2mul(); 108 | } 109 | 110 | fn ghash(&mut self,plain: &[u8],len: usize) -> bool { 111 | if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER} 112 | if self.status != GCM_ACCEPTING_CIPHER {return false} 113 | 114 | let mut j=0; 115 | while j=len {break} 118 | self.statex[i]^=plain[j]; j+=1; 119 | self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1} 120 | } 121 | self.gf2mul(); 122 | } 123 | if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE} 124 | return true; 125 | } 126 | 127 | /* Initialize GCM mode */ 128 | pub fn init(&mut self,nk: usize,key: &[u8],niv: usize,iv: &[u8]) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */ 129 | let mut h:[u8;16]=[0;16]; 130 | 131 | for i in 0..16 {h[i]=0; self.statex[i]=0} 132 | 133 | self.a=AES::new(); 134 | 135 | self.a.init(aes::ECB,nk,key,None); 136 | self.a.ecb_encrypt(&mut h); /* E(K,0) */ 137 | self.precompute(&h); 138 | 139 | self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0; 140 | if niv==12 { 141 | for i in 0..12 {self.a.f[i]=iv[i]} 142 | let b=GCM::unpack(1); 143 | self.a.f[12]=b[0]; self.a.f[13]=b[1]; self.a.f[14]=b[2]; self.a.f[15]=b[3]; /* initialise IV */ 144 | for i in 0..16 {self.y_0[i]=self.a.f[i]} 145 | } else { 146 | self.status=GCM_ACCEPTING_CIPHER; 147 | self.ghash(iv,niv); /* GHASH(H,0,IV) */ 148 | self.wrap(); 149 | for i in 0..16 {self.a.f[i]=self.statex[i];self.y_0[i]=self.a.f[i];self.statex[i]=0} 150 | self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0; 151 | } 152 | self.status=GCM_ACCEPTING_HEADER; 153 | } 154 | 155 | pub fn new() -> GCM { 156 | GCM { 157 | table:[[0;4];128], 158 | statex:[0;16], 159 | y_0:[0;16], 160 | //counter:0, 161 | lena:[0;2], 162 | lenc:[0;2], 163 | status:0, 164 | a:AES::new() 165 | } 166 | } 167 | 168 | /* Add Header data - included but not encrypted */ 169 | pub fn add_header(&mut self,header: &[u8],len: usize) -> bool { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */ 170 | if self.status != GCM_ACCEPTING_HEADER {return false} 171 | let mut j=0; 172 | while j=len {break} 175 | self.statex[i]^=header[j]; j+=1; 176 | self.lena[1]+=1; if self.lena[1]==0 {self.lena[0]+=1} 177 | } 178 | self.gf2mul(); 179 | } 180 | if len%16 != 0 {self.status=GCM_ACCEPTING_CIPHER} 181 | return true; 182 | } 183 | 184 | /* Add Plaintext - included and encrypted */ 185 | pub fn add_plain(&mut self,cipher: &mut [u8],plain: &[u8],len: usize) -> bool { 186 | let mut cb:[u8;16]=[0;16]; 187 | let mut b:[u8;4]=[0;4]; 188 | 189 | let mut counter: u32; 190 | if self.status == GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER} 191 | if self.status != GCM_ACCEPTING_CIPHER {return false} 192 | 193 | let mut j=0; 194 | while j=len {break} 205 | cipher[j]=plain[j]^cb[i]; 206 | self.statex[i]^=cipher[j]; j+=1; 207 | self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1} 208 | } 209 | self.gf2mul() 210 | } 211 | if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE} 212 | return true; 213 | } 214 | 215 | /* Add Ciphertext - decrypts to plaintext */ 216 | pub fn add_cipher(&mut self,plain: &mut [u8],cipher: &[u8],len: usize) -> bool { 217 | let mut cb:[u8;16]=[0;16]; 218 | let mut b:[u8;4]=[0;4]; 219 | 220 | let mut counter: u32; 221 | 222 | if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER} 223 | if self.status != GCM_ACCEPTING_CIPHER {return false} 224 | 225 | let mut j=0; 226 | while j=len {break} 236 | let oc=cipher[j]; 237 | plain[j]=cipher[j]^cb[i]; 238 | self.statex[i]^=oc; j+=1; 239 | self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1} 240 | } 241 | self.gf2mul() 242 | } 243 | if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE} 244 | return true; 245 | } 246 | 247 | /* Finish and extract Tag */ 248 | pub fn finish(&mut self,extract: bool) -> [u8;16] { /* Finish off GHASH and extract tag (MAC) */ 249 | let mut tag:[u8;16]=[0;16]; 250 | 251 | self.wrap(); 252 | /* extract tag */ 253 | if extract { 254 | self.a.ecb_encrypt(&mut (self.y_0)); /* E(K,Y0) */ 255 | for i in 0..16 {self.y_0[i]^=self.statex[i]} 256 | for i in 0..16 {tag[i]=self.y_0[i];self.y_0[i]=0;self.statex[i]=0} 257 | } 258 | self.status=GCM_FINISHED; 259 | self.a.end(); 260 | return tag; 261 | } 262 | 263 | pub fn hex2bytes(hex: &[u8],bin: &mut [u8]) { 264 | let len=hex.len(); 265 | 266 | for i in 0..len/2 { 267 | let mut v:u8; 268 | let mut c = hex[2*i]; 269 | if c >= b'0' && c <= b'9' { 270 | v = c - b'0'; 271 | } else if c >= b'A' && c <= b'F' { 272 | v = c - b'A' + 10; 273 | } else if c >= b'a' && c <= b'f' { 274 | v = c - b'a' + 10; 275 | } else { 276 | v = 0; 277 | } 278 | v <<= 4; 279 | c = hex[2*i + 1]; 280 | if c >= b'0' && c <= b'9' { 281 | v += c - b'0'; 282 | } else if c >= b'A' && c <= b'F' { 283 | v += c - b'A' + 10; 284 | } else if c >= b'a' && c <= b'f' { 285 | v += c - b'a' + 10; 286 | } else { 287 | v = 0; 288 | } 289 | bin[i] = v; 290 | } 291 | } 292 | 293 | } 294 | /* 295 | fn main() 296 | { 297 | let kt=b"feffe9928665731c6d6a8f9467308308"; 298 | let mt=b"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"; 299 | let ht=b"feedfacedeadbeeffeedfacedeadbeefabaddad2"; 300 | let nt=b"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b"; 301 | // Tag should be 619cc5aefffe0bfa462af43c1699d050 302 | 303 | let mut gcm=GCM::new(); 304 | 305 | let len=mt.len()/2; 306 | let lenh=ht.len()/2; 307 | let lenk=kt.len()/2; 308 | let leniv=nt.len()/2; 309 | 310 | //let mut t:[u8;16]=[0;16]; // Tag 311 | let mut k:[u8;16]=[0;16]; // AES Key 312 | let mut h:[u8;64]=[0;64]; // Header - to be included in Authentication, but not encrypted 313 | let mut n:[u8;100]=[0;100]; // IV - Initialisation vector 314 | let mut m:[u8;100]=[0;100]; // Plaintext to be encrypted/authenticated 315 | let mut c:[u8;100]=[0;100]; // Ciphertext 316 | let mut p:[u8;100]=[0;100]; // Recovered Plaintext 317 | 318 | GCM::hex2bytes(mt,&mut m); 319 | GCM::hex2bytes(ht,&mut h); 320 | GCM::hex2bytes(kt,&mut k); 321 | GCM::hex2bytes(nt,&mut n); 322 | 323 | println!("Plaintext="); 324 | for i in 0..len {print!("{:02x}",m[i])} 325 | println!(""); 326 | 327 | gcm.init(lenk,&k,leniv,&n); 328 | 329 | gcm.add_header(&h,lenh); 330 | gcm.add_plain(&mut c,&m,len); 331 | let mut t=gcm.finish(true); 332 | 333 | println!("Ciphertext="); 334 | for i in 0..len {print!("{:02x}",c[i])} 335 | println!(""); 336 | 337 | println!("Tag="); 338 | for i in 0..16 {print!("{:02x}",t[i])} 339 | println!(""); 340 | 341 | gcm.init(lenk,&k,leniv,&n); 342 | 343 | gcm.add_header(&h,lenh); 344 | gcm.add_cipher(&mut p,&c,len); 345 | t=gcm.finish(true); 346 | 347 | println!("Plaintext="); 348 | for i in 0..len {print!("{:02x}",p[i])} 349 | println!(""); 350 | 351 | println!("Tag="); 352 | for i in 0..16 {print!("{:02x}",t[i])} 353 | println!(""); 354 | 355 | } 356 | */ 357 | -------------------------------------------------------------------------------- /amcl/src/hash256.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | const HASH256_H0: u32=0x6A09E667; 21 | const HASH256_H1: u32=0xBB67AE85; 22 | const HASH256_H2: u32=0x3C6EF372; 23 | const HASH256_H3: u32=0xA54FF53A; 24 | const HASH256_H4: u32=0x510E527F; 25 | const HASH256_H5: u32=0x9B05688C; 26 | const HASH256_H6: u32=0x1F83D9AB; 27 | const HASH256_H7: u32=0x5BE0CD19; 28 | 29 | const HASH256_K : [u32;64]=[ 30 | 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 31 | 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 32 | 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 33 | 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 34 | 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 35 | 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 36 | 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 37 | 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2]; 38 | 39 | 40 | pub struct HASH256 { 41 | length: [u32;2], 42 | h: [u32;8], 43 | w: [u32;64] 44 | } 45 | 46 | impl HASH256 { 47 | fn s(n: u32,x: u32) -> u32 { 48 | return ((x)>>n) | ((x)<<(32-n)); 49 | } 50 | fn r(n: u32,x: u32) -> u32 { 51 | return (x)>>n; 52 | } 53 | 54 | fn ch(x: u32,y: u32,z: u32) -> u32 { 55 | return (x&y)^(!(x)&z); 56 | } 57 | 58 | fn maj(x: u32,y: u32,z: u32) -> u32 { 59 | return (x&y)^(x&z)^(y&z); 60 | } 61 | fn sig0(x: u32) -> u32 { 62 | return HASH256::s(2,x)^HASH256::s(13,x)^HASH256::s(22,x); 63 | } 64 | 65 | fn sig1(x: u32) -> u32 { 66 | return HASH256::s(6,x)^HASH256::s(11,x)^HASH256::s(25,x); 67 | } 68 | 69 | fn theta0(x: u32) -> u32 { 70 | return HASH256::s(7,x)^HASH256::s(18,x)^HASH256::r(3,x); 71 | } 72 | 73 | fn theta1(x: u32) -> u32 { 74 | return HASH256::s(17,x)^HASH256::s(19,x)^HASH256::r(10,x); 75 | } 76 | 77 | fn transform(&mut self) { /* basic transformation step */ 78 | for j in 16..64 { 79 | self.w[j]=HASH256::theta1(self.w[j-2]).wrapping_add(self.w[j-7]).wrapping_add(HASH256::theta0(self.w[j-15])).wrapping_add(self.w[j-16]); 80 | } 81 | let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; 82 | let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7]; 83 | for j in 0..64 { /* 64 times - mush it up */ 84 | let t1=hh.wrapping_add(HASH256::sig1(e)).wrapping_add(HASH256::ch(e,f,g)).wrapping_add(HASH256_K[j]).wrapping_add(self.w[j]); 85 | let t2=HASH256::sig0(a).wrapping_add(HASH256::maj(a,b,c)); 86 | hh=g; g=f; f=e; 87 | e=d.wrapping_add(t1); 88 | d=c; 89 | c=b; 90 | b=a; 91 | a=t1.wrapping_add(t2) ; 92 | } 93 | self.h[0]=self.h[0].wrapping_add(a); self.h[1]=self.h[1].wrapping_add(b); self.h[2]=self.h[2].wrapping_add(c); self.h[3]=self.h[3].wrapping_add(d); 94 | self.h[4]=self.h[4].wrapping_add(e); self.h[5]=self.h[5].wrapping_add(f); self.h[6]=self.h[6].wrapping_add(g); self.h[7]=self.h[7].wrapping_add(hh); 95 | 96 | } 97 | 98 | /* Initialise Hash function */ 99 | pub fn init(&mut self) { /* initialise */ 100 | for i in 0..64 {self.w[i]=0} 101 | self.length[0]=0; self.length[1]=0; 102 | self.h[0]=HASH256_H0; 103 | self.h[1]=HASH256_H1; 104 | self.h[2]=HASH256_H2; 105 | self.h[3]=HASH256_H3; 106 | self.h[4]=HASH256_H4; 107 | self.h[5]=HASH256_H5; 108 | self.h[6]=HASH256_H6; 109 | self.h[7]=HASH256_H7; 110 | } 111 | 112 | pub fn new() -> HASH256 { 113 | let mut nh=HASH256 { 114 | length: [0;2], 115 | h: [0;8], 116 | w: [0;64] 117 | }; 118 | nh.init(); 119 | return nh; 120 | } 121 | 122 | /* process a single byte */ 123 | pub fn process(&mut self,byt: u8) { /* process the next message byte */ 124 | let cnt=((self.length[0]/32)%16) as usize; 125 | self.w[cnt]<<=8; 126 | self.w[cnt]|=(byt&0xFF) as u32; 127 | self.length[0]+=8; 128 | if self.length[0]==0 {self.length[1]+=1; self.length[0]=0} 129 | if (self.length[0]%512)==0 {self.transform()} 130 | } 131 | 132 | /* process an array of bytes */ 133 | pub fn process_array(&mut self,b: &[u8]) { 134 | for i in 0..b.len() {self.process(b[i])} 135 | } 136 | 137 | /* process a 32-bit integer */ 138 | pub fn process_num(&mut self,n: i32) { 139 | self.process(((n>>24)&0xff) as u8); 140 | self.process(((n>>16)&0xff) as u8); 141 | self.process(((n>>8)&0xff) as u8); 142 | self.process((n&0xff) as u8); 143 | } 144 | 145 | /* Generate 32-byte Hash */ 146 | pub fn hash(&mut self) -> [u8;32] { /* pad message and finish - supply digest */ 147 | let mut digest:[u8;32]=[0;32]; 148 | let len0=self.length[0]; 149 | let len1=self.length[1]; 150 | self.process(0x80); 151 | while (self.length[0]%512)!=448 {self.process(0)} 152 | self.w[14]=len1; 153 | self.w[15]=len0; 154 | self.transform(); 155 | for i in 0..32 { /* convert to bytes */ 156 | digest[i]=((self.h[i/4]>>(8*(3-i%4))) & 0xff) as u8; 157 | } 158 | self.init(); 159 | return digest; 160 | } 161 | } 162 | 163 | //248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 164 | /* 165 | fn main() { 166 | let s = String::from("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); 167 | let test = s.into_bytes(); 168 | let mut sh=HASH256::new(); 169 | 170 | for i in 0..test.len(){ 171 | sh.process(test[i]); 172 | } 173 | 174 | let digest=sh.hash(); 175 | for i in 0..32 {print!("{:02x}",digest[i])} 176 | } 177 | */ 178 | -------------------------------------------------------------------------------- /amcl/src/hash384.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | const HASH384_H0: u64=0xcbbb9d5dc1059ed8; 21 | const HASH384_H1: u64=0x629a292a367cd507; 22 | const HASH384_H2: u64=0x9159015a3070dd17; 23 | const HASH384_H3: u64=0x152fecd8f70e5939; 24 | const HASH384_H4: u64=0x67332667ffc00b31; 25 | const HASH384_H5: u64=0x8eb44a8768581511; 26 | const HASH384_H6: u64=0xdb0c2e0d64f98fa7; 27 | const HASH384_H7: u64=0x47b5481dbefa4fa4; 28 | 29 | const HASH384_K : [u64;80]=[ 30 | 0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc, 31 | 0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118, 32 | 0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2, 33 | 0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694, 34 | 0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65, 35 | 0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5, 36 | 0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4, 37 | 0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70, 38 | 0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df, 39 | 0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b, 40 | 0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30, 41 | 0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8, 42 | 0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8, 43 | 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3, 44 | 0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec, 45 | 0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b, 46 | 0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178, 47 | 0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b, 48 | 0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c, 49 | 0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]; 50 | 51 | 52 | pub struct HASH384 { 53 | length: [u64;2], 54 | h: [u64;8], 55 | w: [u64;80] 56 | } 57 | 58 | impl HASH384 { 59 | fn s(n: u64,x: u64) -> u64 { 60 | return ((x)>>n) | ((x)<<(64-n)); 61 | } 62 | fn r(n: u64,x: u64) -> u64 { 63 | return (x)>>n; 64 | } 65 | 66 | fn ch(x: u64,y: u64,z: u64) -> u64 { 67 | return (x&y)^(!(x)&z); 68 | } 69 | 70 | fn maj(x: u64,y: u64,z: u64) -> u64 { 71 | return (x&y)^(x&z)^(y&z); 72 | } 73 | 74 | fn sig0(x: u64) -> u64 { 75 | return HASH384::s(28,x)^HASH384::s(34,x)^HASH384::s(39,x); 76 | } 77 | 78 | fn sig1(x: u64) -> u64 { 79 | return HASH384::s(14,x)^HASH384::s(18,x)^HASH384::s(41,x); 80 | } 81 | 82 | fn theta0(x: u64) -> u64 { 83 | return HASH384::s(1,x)^HASH384::s(8,x)^HASH384::r(7,x); 84 | } 85 | 86 | fn theta1(x: u64) -> u64 { 87 | return HASH384::s(19,x)^HASH384::s(61,x)^HASH384::r(6,x); 88 | } 89 | 90 | fn transform(&mut self) { /* basic transformation step */ 91 | for j in 16..80 { 92 | self.w[j]=HASH384::theta1(self.w[j-2])+self.w[j-7]+HASH384::theta0(self.w[j-15])+self.w[j-16]; 93 | } 94 | let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; 95 | let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7]; 96 | for j in 0..80 { /* 64 times - mush it up */ 97 | let t1=hh.wrapping_add(HASH384::sig1(e)).wrapping_add(HASH384::ch(e,f,g)).wrapping_add(HASH384_K[j]).wrapping_add(self.w[j]); 98 | let t2=HASH384::sig0(a).wrapping_add(HASH384::maj(a,b,c)); 99 | hh=g; g=f; f=e; 100 | e=d.wrapping_add(t1); 101 | d=c; 102 | c=b; 103 | b=a; 104 | a=t1.wrapping_add(t2) ; 105 | } 106 | self.h[0]=self.h[0].wrapping_add(a); self.h[1]=self.h[1].wrapping_add(b); self.h[2]=self.h[2].wrapping_add(c); self.h[3]=self.h[3].wrapping_add(d); 107 | self.h[4]=self.h[4].wrapping_add(e); self.h[5]=self.h[5].wrapping_add(f); self.h[6]=self.h[6].wrapping_add(g); self.h[7]=self.h[7].wrapping_add(hh); 108 | 109 | } 110 | 111 | /* Initialise Hash function */ 112 | pub fn init(&mut self) { /* initialise */ 113 | for i in 0..64 {self.w[i]=0} 114 | self.length[0]=0; self.length[1]=0; 115 | self.h[0]=HASH384_H0; 116 | self.h[1]=HASH384_H1; 117 | self.h[2]=HASH384_H2; 118 | self.h[3]=HASH384_H3; 119 | self.h[4]=HASH384_H4; 120 | self.h[5]=HASH384_H5; 121 | self.h[6]=HASH384_H6; 122 | self.h[7]=HASH384_H7; 123 | } 124 | 125 | pub fn new() -> HASH384 { 126 | let mut nh=HASH384 { 127 | length: [0;2], 128 | h: [0;8], 129 | w: [0;80] 130 | }; 131 | nh.init(); 132 | return nh; 133 | } 134 | 135 | /* process a single byte */ 136 | pub fn process(&mut self,byt: u8) { /* process the next message byte */ 137 | let cnt=((self.length[0]/64)%16) as usize; 138 | self.w[cnt]<<=8; 139 | self.w[cnt]|=(byt&0xFF) as u64; 140 | self.length[0]+=8; 141 | if self.length[0]==0 {self.length[1]+=1; self.length[0]=0} 142 | if (self.length[0]%1024)==0 {self.transform()} 143 | } 144 | 145 | /* process an array of bytes */ 146 | pub fn process_array(&mut self,b: &[u8]) { 147 | for i in 0..b.len() {self.process(b[i])} 148 | } 149 | 150 | /* process a 32-bit integer */ 151 | pub fn process_num(&mut self,n: i32) { 152 | self.process(((n>>24)&0xff) as u8); 153 | self.process(((n>>16)&0xff) as u8); 154 | self.process(((n>>8)&0xff) as u8); 155 | self.process((n&0xff) as u8); 156 | } 157 | 158 | /* Generate 32-byte Hash */ 159 | pub fn hash(&mut self) -> [u8;48] { /* pad message and finish - supply digest */ 160 | let mut digest:[u8;48]=[0;48]; 161 | let len0=self.length[0]; 162 | let len1=self.length[1]; 163 | self.process(0x80); 164 | while (self.length[0]%1024)!=896 {self.process(0)} 165 | self.w[14]=len1; 166 | self.w[15]=len0; 167 | self.transform(); 168 | for i in 0..48 { /* convert to bytes */ 169 | digest[i]=((self.h[i/8]>>(8*(7-i%8))) & 0xff) as u8; 170 | } 171 | self.init(); 172 | return digest; 173 | } 174 | } 175 | 176 | //09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039 177 | /* 178 | fn main() { 179 | let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); 180 | let test = s.into_bytes(); 181 | let mut sh=HASH384::new(); 182 | 183 | for i in 0..test.len(){ 184 | sh.process(test[i]); 185 | } 186 | 187 | let digest=sh.hash(); 188 | for i in 0..48 {print!("{:02x}",digest[i])} 189 | } */ 190 | -------------------------------------------------------------------------------- /amcl/src/hash512.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | 21 | const HASH512_H0: u64=0x6a09e667f3bcc908; 22 | const HASH512_H1: u64=0xbb67ae8584caa73b; 23 | const HASH512_H2: u64=0x3c6ef372fe94f82b; 24 | const HASH512_H3: u64=0xa54ff53a5f1d36f1; 25 | const HASH512_H4: u64=0x510e527fade682d1; 26 | const HASH512_H5: u64=0x9b05688c2b3e6c1f; 27 | const HASH512_H6: u64=0x1f83d9abfb41bd6b; 28 | const HASH512_H7: u64=0x5be0cd19137e2179; 29 | 30 | const HASH512_K : [u64;80]=[ 31 | 0x428a2f98d728ae22,0x7137449123ef65cd,0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc, 32 | 0x3956c25bf348b538,0x59f111f1b605d019,0x923f82a4af194f9b,0xab1c5ed5da6d8118, 33 | 0xd807aa98a3030242,0x12835b0145706fbe,0x243185be4ee4b28c,0x550c7dc3d5ffb4e2, 34 | 0x72be5d74f27b896f,0x80deb1fe3b1696b1,0x9bdc06a725c71235,0xc19bf174cf692694, 35 | 0xe49b69c19ef14ad2,0xefbe4786384f25e3,0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65, 36 | 0x2de92c6f592b0275,0x4a7484aa6ea6e483,0x5cb0a9dcbd41fbd4,0x76f988da831153b5, 37 | 0x983e5152ee66dfab,0xa831c66d2db43210,0xb00327c898fb213f,0xbf597fc7beef0ee4, 38 | 0xc6e00bf33da88fc2,0xd5a79147930aa725,0x06ca6351e003826f,0x142929670a0e6e70, 39 | 0x27b70a8546d22ffc,0x2e1b21385c26c926,0x4d2c6dfc5ac42aed,0x53380d139d95b3df, 40 | 0x650a73548baf63de,0x766a0abb3c77b2a8,0x81c2c92e47edaee6,0x92722c851482353b, 41 | 0xa2bfe8a14cf10364,0xa81a664bbc423001,0xc24b8b70d0f89791,0xc76c51a30654be30, 42 | 0xd192e819d6ef5218,0xd69906245565a910,0xf40e35855771202a,0x106aa07032bbd1b8, 43 | 0x19a4c116b8d2d0c8,0x1e376c085141ab53,0x2748774cdf8eeb99,0x34b0bcb5e19b48a8, 44 | 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb,0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3, 45 | 0x748f82ee5defb2fc,0x78a5636f43172f60,0x84c87814a1f0ab72,0x8cc702081a6439ec, 46 | 0x90befffa23631e28,0xa4506cebde82bde9,0xbef9a3f7b2c67915,0xc67178f2e372532b, 47 | 0xca273eceea26619c,0xd186b8c721c0c207,0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178, 48 | 0x06f067aa72176fba,0x0a637dc5a2c898a6,0x113f9804bef90dae,0x1b710b35131c471b, 49 | 0x28db77f523047d84,0x32caab7b40c72493,0x3c9ebe0a15c9bebc,0x431d67c49c100d4c, 50 | 0x4cc5d4becb3e42b6,0x597f299cfc657e2a,0x5fcb6fab3ad6faec,0x6c44198c4a475817]; 51 | 52 | 53 | pub struct HASH512 { 54 | length: [u64;2], 55 | h: [u64;8], 56 | w: [u64;80] 57 | } 58 | 59 | impl HASH512 { 60 | fn s(n: u64,x: u64) -> u64 { 61 | return ((x)>>n) | ((x)<<(64-n)); 62 | } 63 | fn r(n: u64,x: u64) -> u64 { 64 | return (x)>>n; 65 | } 66 | 67 | fn ch(x: u64,y: u64,z: u64) -> u64 { 68 | return (x&y)^(!(x)&z); 69 | } 70 | 71 | fn maj(x: u64,y: u64,z: u64) -> u64 { 72 | return (x&y)^(x&z)^(y&z); 73 | } 74 | 75 | fn sig0(x: u64) -> u64 { 76 | return HASH512::s(28,x)^HASH512::s(34,x)^HASH512::s(39,x); 77 | } 78 | 79 | fn sig1(x: u64) -> u64 { 80 | return HASH512::s(14,x)^HASH512::s(18,x)^HASH512::s(41,x); 81 | } 82 | 83 | fn theta0(x: u64) -> u64 { 84 | return HASH512::s(1,x)^HASH512::s(8,x)^HASH512::r(7,x); 85 | } 86 | 87 | fn theta1(x: u64) -> u64 { 88 | return HASH512::s(19,x)^HASH512::s(61,x)^HASH512::r(6,x); 89 | } 90 | 91 | fn transform(&mut self) { /* basic transformation step */ 92 | for j in 16..80 { 93 | self.w[j]=HASH512::theta1(self.w[j-2]).wrapping_add(self.w[j-7]).wrapping_add(HASH512::theta0(self.w[j-15])).wrapping_add(self.w[j-16]); 94 | } 95 | let mut a=self.h[0]; let mut b=self.h[1]; let mut c=self.h[2]; let mut d=self.h[3]; 96 | let mut e=self.h[4]; let mut f=self.h[5]; let mut g=self.h[6]; let mut hh=self.h[7]; 97 | for j in 0..80 { /* 64 times - mush it up */ 98 | let t1=hh.wrapping_add(HASH512::sig1(e)).wrapping_add(HASH512::ch(e,f,g)).wrapping_add(HASH512_K[j]).wrapping_add(self.w[j]); 99 | let t2=HASH512::sig0(a).wrapping_add(HASH512::maj(a,b,c)); 100 | hh=g; g=f; f=e; 101 | e=d.wrapping_add(t1); 102 | d=c; 103 | c=b; 104 | b=a; 105 | a=t1.wrapping_add(t2) ; 106 | } 107 | self.h[0]=self.h[0].wrapping_add(a); self.h[1]=self.h[1].wrapping_add(b); self.h[2]=self.h[2].wrapping_add(c); self.h[3]=self.h[3].wrapping_add(d); 108 | self.h[4]=self.h[4].wrapping_add(e); self.h[5]=self.h[5].wrapping_add(f); self.h[6]=self.h[6].wrapping_add(g); self.h[7]=self.h[7].wrapping_add(hh); 109 | 110 | } 111 | 112 | /* Initialise Hash function */ 113 | pub fn init(&mut self) { /* initialise */ 114 | for i in 0..64 {self.w[i]=0} 115 | self.length[0]=0; self.length[1]=0; 116 | self.h[0]=HASH512_H0; 117 | self.h[1]=HASH512_H1; 118 | self.h[2]=HASH512_H2; 119 | self.h[3]=HASH512_H3; 120 | self.h[4]=HASH512_H4; 121 | self.h[5]=HASH512_H5; 122 | self.h[6]=HASH512_H6; 123 | self.h[7]=HASH512_H7; 124 | } 125 | 126 | pub fn new() -> HASH512 { 127 | let mut nh=HASH512 { 128 | length: [0;2], 129 | h: [0;8], 130 | w: [0;80] 131 | }; 132 | nh.init(); 133 | return nh; 134 | } 135 | 136 | /* process a single byte */ 137 | pub fn process(&mut self,byt: u8) { /* process the next message byte */ 138 | let cnt=((self.length[0]/64)%16) as usize; 139 | self.w[cnt]<<=8; 140 | self.w[cnt]|=(byt&0xFF) as u64; 141 | self.length[0]+=8; 142 | if self.length[0]==0 {self.length[1]+=1; self.length[0]=0} 143 | if (self.length[0]%1024)==0 {self.transform()} 144 | } 145 | 146 | /* process an array of bytes */ 147 | pub fn process_array(&mut self,b: &[u8]) { 148 | for i in 0..b.len() {self.process(b[i])} 149 | } 150 | 151 | /* process a 32-bit integer */ 152 | pub fn process_num(&mut self,n: i32) { 153 | self.process(((n>>24)&0xff) as u8); 154 | self.process(((n>>16)&0xff) as u8); 155 | self.process(((n>>8)&0xff) as u8); 156 | self.process((n&0xff) as u8); 157 | } 158 | 159 | /* Generate 32-byte Hash */ 160 | pub fn hash(&mut self) -> [u8;64] { /* pad message and finish - supply digest */ 161 | let mut digest:[u8;64]=[0;64]; 162 | let len0=self.length[0]; 163 | let len1=self.length[1]; 164 | self.process(0x80); 165 | while (self.length[0]%1024)!=896 {self.process(0)} 166 | self.w[14]=len1; 167 | self.w[15]=len0; 168 | self.transform(); 169 | for i in 0..64 { /* convert to bytes */ 170 | digest[i]=((self.h[i/8]>>(8*(7-i%8))) & 0xff) as u8; 171 | } 172 | self.init(); 173 | return digest; 174 | } 175 | } 176 | 177 | //8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909 178 | /* 179 | fn main() { 180 | let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); 181 | let test = s.into_bytes(); 182 | let mut sh=HASH512::new(); 183 | 184 | for i in 0..test.len(){ 185 | sh.process(test[i]); 186 | } 187 | 188 | let digest=sh.hash(); 189 | for i in 0..64 {print!("{:02x}",digest[i])} 190 | } */ 191 | -------------------------------------------------------------------------------- /amcl/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod arch; 2 | pub mod aes; 3 | pub mod gcm; 4 | pub mod hash256; 5 | pub mod hash384; 6 | pub mod hash512; 7 | pub mod rand; 8 | pub mod sha3; 9 | pub mod nhs; 10 | 11 | pub mod bls381; 12 | -------------------------------------------------------------------------------- /amcl/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, world!"); 3 | } 4 | -------------------------------------------------------------------------------- /amcl/src/rand.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | //mod hash256; 21 | 22 | use hash256::HASH256; 23 | 24 | const RAND_NK: usize=21; 25 | const RAND_NJ: usize=6; 26 | const RAND_NV: usize=8; 27 | 28 | pub struct RAND { 29 | ira: [u32;RAND_NK], /* random number... */ 30 | rndptr: usize, 31 | borrow: u32, 32 | pool_ptr: usize, 33 | pool: [u8;32] 34 | } 35 | 36 | impl RAND { 37 | 38 | pub fn new() -> RAND { 39 | RAND { 40 | ira: [0;RAND_NK], 41 | rndptr:0, 42 | borrow: 0, 43 | pool_ptr:0, 44 | pool:[0;32] 45 | } 46 | } 47 | 48 | pub fn clean(&mut self) { 49 | self.pool_ptr=0; self.rndptr=0; 50 | for i in 0..32 {self.pool[i]=0} 51 | for i in 0..RAND_NK {self.ira[i]=0} 52 | self.borrow=0; 53 | } 54 | 55 | fn sbrand(&mut self) -> u32 { /* Marsaglia & Zaman random number generator */ 56 | self.rndptr+=1; 57 | if self.rndptrt {self.borrow=1} 66 | self.ira[i]=pdiff; 67 | k+=1; 68 | } 69 | return self.ira[0]; 70 | } 71 | 72 | fn sirand(&mut self,seed: u32) { 73 | let mut m: u32=1; 74 | let mut sd=seed; 75 | self.borrow=0; 76 | self.rndptr=0; 77 | self.ira[0]^=sd; 78 | for i in 1..RAND_NK { /* fill initialisation vector */ 79 | let inn=(RAND_NV*i)%RAND_NK; 80 | self.ira[inn]^=m; /* note XOR */ 81 | let t=m; 82 | m=sd.wrapping_sub(m); 83 | sd=t; 84 | } 85 | for _ in 0..10000 {self.sbrand();} /* "warm-up" & stir the generator */ 86 | } 87 | 88 | fn fill_pool(&mut self) { 89 | let mut sh=HASH256::new(); 90 | for _ in 0..128 {sh.process((self.sbrand()&0xff) as u8)} 91 | let w=sh.hash(); 92 | for i in 0..32 {self.pool[i]=w[i]} 93 | self.pool_ptr=0; 94 | } 95 | 96 | fn pack(b: [u8;4]) -> u32 { /* pack 4 bytes into a 32-bit Word */ 97 | return ((((b[3] as u32))&0xff)<<24)|(((b[2] as u32)&0xff)<<16)|(((b[1] as u32)&0xff)<<8)|((b[0] as u32)&0xff); 98 | } 99 | 100 | /* Initialize RNG with some real entropy from some external source */ 101 | pub fn seed(&mut self,rawlen: usize,raw: &[u8]) { /* initialise from at least 128 byte string of raw random entropy */ 102 | let mut b: [u8;4]=[0;4]; 103 | let mut sh=HASH256::new(); 104 | self.pool_ptr=0; 105 | 106 | for i in 0..RAND_NK {self.ira[i]=0} 107 | if rawlen>0 { 108 | for i in 0..rawlen { 109 | sh.process(raw[i]); 110 | } 111 | let digest=sh.hash(); 112 | 113 | /* initialise PRNG from distilled randomness */ 114 | 115 | for i in 0..8 { 116 | b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]; 117 | self.sirand(RAND::pack(b)); 118 | } 119 | } 120 | self.fill_pool(); 121 | } 122 | 123 | /* get random byte */ 124 | pub fn getbyte(&mut self) -> u8 { 125 | let r=self.pool[self.pool_ptr]; 126 | self.pool_ptr+=1; 127 | if self.pool_ptr>=32 {self.fill_pool()} 128 | return (r&0xff) as u8; 129 | } 130 | } 131 | 132 | /* test main program */ 133 | /* 134 | fn main() { 135 | let mut raw : [u8;100]=[0;100]; 136 | let mut rng=RAND::new(); 137 | 138 | rng.clean(); 139 | for i in 0..100 {raw[i]=i as u8} 140 | 141 | rng.seed(100,&raw); 142 | 143 | for _ in 0..1000 { 144 | print!("{:03} ",rng.getbyte()); 145 | } 146 | } 147 | */ 148 | -------------------------------------------------------------------------------- /amcl/src/sha3.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | 21 | pub const HASH224: usize=28; 22 | pub const HASH256: usize=32; 23 | pub const HASH384: usize=48; 24 | pub const HASH512: usize=64; 25 | pub const SHAKE128: usize=16; 26 | pub const SHAKE256: usize=32; 27 | 28 | const ROUNDS: usize=24; 29 | 30 | const RC : [u64;24] = [ 31 | 0x0000000000000001,0x0000000000008082,0x800000000000808A,0x8000000080008000, 32 | 0x000000000000808B,0x0000000080000001,0x8000000080008081,0x8000000000008009, 33 | 0x000000000000008A,0x0000000000000088,0x0000000080008009,0x000000008000000A, 34 | 0x000000008000808B,0x800000000000008B,0x8000000000008089,0x8000000000008003, 35 | 0x8000000000008002,0x8000000000000080,0x000000000000800A,0x800000008000000A, 36 | 0x8000000080008081,0x8000000000008080,0x0000000080000001,0x8000000080008008]; 37 | 38 | 39 | 40 | pub struct SHA3 { 41 | length: u64, 42 | rate: usize, 43 | len: usize, 44 | s: [[u64;5];5] 45 | } 46 | 47 | impl SHA3 { 48 | fn rotl(x: u64,n: u64) -> u64 { 49 | return ((x)<>(64-n)); 50 | } 51 | 52 | fn transform(&mut self) { /* basic transformation step */ 53 | let mut c: [u64; 5] = [0; 5]; 54 | let mut d: [u64; 5] = [0; 5]; 55 | let mut b: [[u64;5];5]=[[0;5];5]; 56 | 57 | for k in 0..ROUNDS { 58 | c[0]=self.s[0][0]^self.s[0][1]^self.s[0][2]^self.s[0][3]^self.s[0][4]; 59 | c[1]=self.s[1][0]^self.s[1][1]^self.s[1][2]^self.s[1][3]^self.s[1][4]; 60 | c[2]=self.s[2][0]^self.s[2][1]^self.s[2][2]^self.s[2][3]^self.s[2][4]; 61 | c[3]=self.s[3][0]^self.s[3][1]^self.s[3][2]^self.s[3][3]^self.s[3][4]; 62 | c[4]=self.s[4][0]^self.s[4][1]^self.s[4][2]^self.s[4][3]^self.s[4][4]; 63 | 64 | d[0]=c[4]^SHA3::rotl(c[1],1); 65 | d[1]=c[0]^SHA3::rotl(c[2],1); 66 | d[2]=c[1]^SHA3::rotl(c[3],1); 67 | d[3]=c[2]^SHA3::rotl(c[4],1); 68 | d[4]=c[3]^SHA3::rotl(c[0],1); 69 | 70 | for i in 0..5 { 71 | for j in 0..5 { 72 | self.s[i][j]^=d[i]; 73 | } 74 | } 75 | 76 | b[0][0]=self.s[0][0]; 77 | b[1][3]=SHA3::rotl(self.s[0][1],36); 78 | b[2][1]=SHA3::rotl(self.s[0][2],3); 79 | b[3][4]=SHA3::rotl(self.s[0][3],41); 80 | b[4][2]=SHA3::rotl(self.s[0][4],18); 81 | 82 | b[0][2]=SHA3::rotl(self.s[1][0],1); 83 | b[1][0]=SHA3::rotl(self.s[1][1],44); 84 | b[2][3]=SHA3::rotl(self.s[1][2],10); 85 | b[3][1]=SHA3::rotl(self.s[1][3],45); 86 | b[4][4]=SHA3::rotl(self.s[1][4],2); 87 | 88 | b[0][4]=SHA3::rotl(self.s[2][0],62); 89 | b[1][2]=SHA3::rotl(self.s[2][1],6); 90 | b[2][0]=SHA3::rotl(self.s[2][2],43); 91 | b[3][3]=SHA3::rotl(self.s[2][3],15); 92 | b[4][1]=SHA3::rotl(self.s[2][4],61); 93 | 94 | b[0][1]=SHA3::rotl(self.s[3][0],28); 95 | b[1][4]=SHA3::rotl(self.s[3][1],55); 96 | b[2][2]=SHA3::rotl(self.s[3][2],25); 97 | b[3][0]=SHA3::rotl(self.s[3][3],21); 98 | b[4][3]=SHA3::rotl(self.s[3][4],56); 99 | 100 | b[0][3]=SHA3::rotl(self.s[4][0],27); 101 | b[1][1]=SHA3::rotl(self.s[4][1],20); 102 | b[2][4]=SHA3::rotl(self.s[4][2],39); 103 | b[3][2]=SHA3::rotl(self.s[4][3],8); 104 | b[4][0]=SHA3::rotl(self.s[4][4],14); 105 | 106 | for i in 0..5 { 107 | for j in 0..5 { 108 | self.s[i][j]=b[i][j]^(!b[(i+1)%5][j]&b[(i+2)%5][j]); 109 | } 110 | } 111 | 112 | self.s[0][0]^=RC[k]; 113 | } 114 | } 115 | 116 | /* Initialise Hash function */ 117 | pub fn init(&mut self,olen: usize) { /* initialise */ 118 | for i in 0..5 { 119 | for j in 0..5 { 120 | self.s[i][j]=0; 121 | } 122 | } 123 | self.length=0; 124 | self.len=olen; 125 | self.rate=200-2*olen; 126 | } 127 | 128 | pub fn new(olen: usize) -> SHA3 { 129 | let mut nh=SHA3 { 130 | length: 0, 131 | rate: 0, 132 | len: 0, 133 | s: [[0;5];5] 134 | }; 135 | nh.init(olen); 136 | return nh; 137 | } 138 | 139 | /* process a single byte */ 140 | pub fn process(&mut self,byt: u8) { /* process the next message byte */ 141 | let cnt=(self.length%(self.rate as u64)) as usize; 142 | let b=cnt%8; 143 | let ind=cnt/8; 144 | let i=ind%5; 145 | let j=ind/5; 146 | self.s[i][j]^=((byt&0xff) as u64) << (8*b); 147 | self.length+=1; 148 | if cnt+1 == self.rate { 149 | self.transform(); 150 | } 151 | } 152 | 153 | pub fn squeeze(&mut self,buff: &mut [u8],olen: usize) { 154 | //let olen=buff.len(); 155 | let mut done=false; 156 | let mut m=0; 157 | loop { 158 | for j in 0..5 { 159 | for i in 0..5 { 160 | let mut el=self.s[i][j]; 161 | for _ in 0..8 { 162 | buff[m]=(el&0xff) as u8; 163 | m+=1; 164 | if m>=olen || (m%self.rate)==0 { 165 | done=true; 166 | break; 167 | } 168 | el>>=8; 169 | } 170 | if done {break} 171 | } 172 | if done {break} 173 | } 174 | if m>=olen {break} 175 | done=false; 176 | self.transform(); 177 | } 178 | 179 | } 180 | 181 | /* Generate 32-byte Hash */ 182 | pub fn hash(&mut self,digest: &mut [u8]) { /* pad message and finish - supply digest */ 183 | let q=self.rate-(self.length%(self.rate as u64)) as usize; 184 | if q==1 { 185 | self.process(0x86); 186 | } else { 187 | self.process(0x06); 188 | while (self.length%(self.rate as u64)) as usize != self.rate-1 {self.process(0x00)} 189 | self.process(0x80); 190 | } 191 | let hlen=self.len as usize; 192 | self.squeeze(digest,hlen); 193 | } 194 | 195 | pub fn shake(&mut self,digest: &mut[u8],olen: usize) { 196 | let q=self.rate-(self.length%(self.rate as u64)) as usize; 197 | if q==1 { 198 | self.process(0x9f); 199 | } else { 200 | self.process(0x1f); 201 | while (self.length%(self.rate as u64)) as usize != self.rate-1 {self.process(0x00)} 202 | self.process(0x80); 203 | } 204 | self.squeeze(digest,olen); 205 | } 206 | 207 | } 208 | 209 | //916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18 210 | //afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185 211 | //98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2 212 | /* 213 | fn main() { 214 | let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); 215 | let mut digest: [u8;100]=[0;100]; 216 | let test = s.into_bytes(); 217 | 218 | let mut sh=SHA3::new(HASH256); 219 | for i in 0..test.len(){ 220 | sh.process(test[i]); 221 | } 222 | sh.hash(&mut digest); 223 | for i in 0..32 {print!("{:02x}",digest[i])} 224 | println!(""); 225 | 226 | sh=SHA3::new(HASH512); 227 | for i in 0..test.len(){ 228 | sh.process(test[i]); 229 | } 230 | sh.hash(&mut digest); 231 | for i in 0..64 {print!("{:02x}",digest[i])} 232 | println!(""); 233 | 234 | sh=SHA3::new(SHAKE256); 235 | for i in 0..test.len(){ 236 | sh.process(test[i]); 237 | } 238 | sh.shake(&mut digest,72); 239 | for i in 0..72 {print!("{:02x}",digest[i])} 240 | println!(""); 241 | 242 | } */ 243 | -------------------------------------------------------------------------------- /docs/VerifiableCredentials.md: -------------------------------------------------------------------------------- 1 | ### Components 2 | 3 | 1. **Verifiable Credential Proof Request** - Verifier generates a *proof request* to send to the prover. 4 | Prover determines if the Request is appropriate, i.e., should it be fulfilled. 5 | If so, then Prover determines if the Request can be resolved against credentials she has. 6 | If not, then Prover may acquire credentials from issuers. 7 | If it can be resolved, then Prover resolves it by selecting the credentials and attributes that satisfy the Request. 8 | 1. **Verifiable Credential Proof Resolution** - Prover generates a *proof resolution*, which is a simplified version of a Proof Request that helps the Verifier know how to confirm the Proof is valid. 9 | Specifically, the Resolution includes a reference to a sepcific credential definition for every "credential" entry in the proof request. 10 | Data that satisfies the non-cryptographic part of the Request. 11 | 1. **ZKL Proof Spec** - Generated deterministically from a Resolution and the top-level Schema which provides ordered attributes. 12 | (The inputs are Verifiable Credential Proof Resolution, and all public information \[e.g., Credential Definitions, Revocation Authority, Pseudonyms].) 13 | 1. **ZKL Witness** - Prover provides private inputs containing the secrets required to compute a proof. 14 | \[e.g. secret keys, all attribute values, the credentials involved, the randomness used to compute a pseudonym]. 15 | 1. **ZKL Proof** - Data that satisfies the cryptographic part of the Request. 16 | 17 | ### ZKL Flow 18 | 19 | Holders don't handle cryptographic material or messaging with Verifiers directly, but instead use software and hardware components to do this called agents. 20 | Cryptographic secrets are stored in wallets. Crypto engine is the software/hardware library that performs the ZK computations. Public registry 21 | is any highly available and tamper-evident storage source that contains public material that both Holder and Verifier trust. Sovrin is a public permissioned ledger designed for this purpose. 22 | 23 | ![flow](flow-diagram.png) 24 | -------------------------------------------------------------------------------- /docs/flow-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger-labs/z-mix/652e0066da8640fa54dcc6cce50c81dd28e93cd9/docs/flow-diagram.png -------------------------------------------------------------------------------- /docs/flow.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | actor Verifier as v 4 | box "Holder" 5 | participant agent as a 6 | participant wallet as w 7 | participant "crypto engine" as ce 8 | end box 9 | 10 | participant "public registry\n(Sovrin)" as reg 11 | 12 | v -\ a: Proof Request 13 | activate a 14 | 15 | a -\ w: credential match request 16 | a \- w: matches 17 | a -> a: generate Proof Resolution \n(from matches & Proof Request) 18 | 19 | a --\ reg: GET_CRED_DEF, GET_REVOC_REG request 20 | a \-- reg: CRED_DEF, REVOC_REG (issuer pubkey and revocation registry for cred) 21 | a -> a: generate ZKL-ProofSpec \n(from Proof Resolution & Public Keys) 22 | 23 | a -\ w: secrets request 24 | a \- w: secrets 25 | a <- a: generate ZKL-Witness \n(from secrets & ZKL-ProofSpec) 26 | ||| 27 | a -\ ce: ZKL-ProofSpec & ZKL-Witness 28 | a \- ce: ZKL-Proof 29 | 30 | a -> a: generate Proof\n(from ZKL-Proof & \nProof Resolution & \nRevealed Attributes) 31 | 32 | a -\ v: Proof 33 | deactivate a 34 | 35 | 36 | @enduml 37 | -------------------------------------------------------------------------------- /docs/zklang_proof_spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "https://github.com/hyperledger-labs/zmix/docs/zklang_spec.json", 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "title": "ZKLang Proof Specification", 5 | "type": "object", 6 | "required": ["attributeCount", "clauses"], 7 | "properties": { 8 | "attributeCount": { 9 | "type": "integer", 10 | "min": 1, 11 | "description": "The number of attributes to be involved in the proof" 12 | }, 13 | "disclosed": { 14 | "type": "array", 15 | "items": { 16 | "type": "object", 17 | "required": ["index", "value"], 18 | "properties": { 19 | "index": { 20 | "type": "integer", 21 | "description": "The attribute index that has this value" 22 | }, 23 | "value": { 24 | "type": "string", 25 | "description": "The actual value of the attribute" 26 | } 27 | } 28 | } 29 | }, 30 | "clauses": { 31 | "type": "array", 32 | "minItems": 1, 33 | "items": { 34 | "anyOf": [ 35 | { "$ref": "#/definitions/commitmentClause" }, 36 | { "$ref": "#/definitions/credentialClause" }, 37 | { "$ref": "#/definitions/intervalClause" }, 38 | { "$ref": "#/definitions/setClause" }, 39 | { "$ref": "#/definitions/verifiable_encClause" }, 40 | { "$ref": "#/definitions/nymClause" }, 41 | { "$ref": "#/definitions/scope_nymClause" } 42 | ] 43 | } 44 | } 45 | }, 46 | "definitions": { 47 | "attrs": { 48 | "type": "array", 49 | "minItems": 1, 50 | "uniqueItems": true, 51 | "items": { "type": "integer" } 52 | }, 53 | "pk": { 54 | "type": "string" 55 | }, 56 | "commitmentClause": { 57 | "type": "object", 58 | "required": ["type", "clauseData"], 59 | "properties": { 60 | "type": { 61 | "type": "string", 62 | "enum": ["commitment"] 63 | }, 64 | "clauseData": { 65 | "$ref": "#/definitions/commitment" 66 | } 67 | } 68 | }, 69 | "credentialClause": { 70 | "type": "object", 71 | "required": ["type", "clauseData"], 72 | "properties": { 73 | "type": { 74 | "type": "string", 75 | "enum": ["credential"] 76 | }, 77 | "clauseData": { 78 | "$ref": "#/definitions/credential" 79 | } 80 | } 81 | }, 82 | "intervalClause": { 83 | "type": "object", 84 | "required": ["type", "clauseData"], 85 | "properties": { 86 | "type": { 87 | "type": "string", 88 | "enum": ["interval"] 89 | }, 90 | "clauseData": { 91 | "$ref": "#/definitions/interval" 92 | } 93 | } 94 | }, 95 | "setClause": { 96 | "type": "object", 97 | "required": ["type", "clauseData"], 98 | "properties": { 99 | "type": { 100 | "type": "string", 101 | "enum": ["set"] 102 | }, 103 | "clauseData": { 104 | "$ref": "#/definitions/set" 105 | } 106 | } 107 | }, 108 | "verifiable_encClause": { 109 | "type": "object", 110 | "required": ["type", "clauseData"], 111 | "properties": { 112 | "type": { 113 | "type": "string", 114 | "enum": ["verifiable_enc"] 115 | }, 116 | "clauseData": { 117 | "$ref": "#/definitions/verifiable_enc" 118 | } 119 | } 120 | }, 121 | "nymClause": { 122 | "type": "object", 123 | "required": ["type", "clauseData"], 124 | "properties": { 125 | "type": { 126 | "type": "string", 127 | "enum": ["nym"] 128 | }, 129 | "clauseData": { 130 | "$ref": "#/definitions/nym" 131 | } 132 | } 133 | }, 134 | "scope_nymClause": { 135 | "type": "object", 136 | "required": ["type", "clauseData"], 137 | "properties": { 138 | "type": { 139 | "type": "string", 140 | "enum": ["scope_nym"] 141 | }, 142 | "clauseData": { 143 | "$ref": "#/definitions/scope_nym" 144 | } 145 | } 146 | }, 147 | "commitment": { 148 | "type": "object", 149 | "allOf": [ 150 | { 151 | "required": ["attrs"] 152 | }, 153 | { 154 | "oneOf": [ 155 | { 156 | "required": ["generators", "modulus"], 157 | "not": { "required": ["curve"] } 158 | }, 159 | { 160 | "required": ["curve"], 161 | "not": { "required": ["generators", "modulus"]} 162 | } 163 | ] 164 | } 165 | ], 166 | "properties": { 167 | "attrs": { 168 | "$ref": "#/definitions/attrs" 169 | }, 170 | "generators": { 171 | "type": "array", 172 | "minItems": 1, 173 | "items": { 174 | "type": "string" 175 | } 176 | }, 177 | "modulus": { 178 | "type": "string" 179 | }, 180 | "curve": { 181 | "type": "string", 182 | "enum": ["x25519", "p256r1", "p384", "p512", "p256k1", "bls381", "bn254"] 183 | } 184 | } 185 | }, 186 | "credential": { 187 | "type": "object", 188 | "required": ["attrs", "pk"], 189 | "properties": { 190 | "attrs": { 191 | "$ref": "#/definitions/attrs" 192 | }, 193 | "pk": { 194 | "$ref": "#/definitions/pk" 195 | } 196 | } 197 | }, 198 | "interval": { 199 | "type": "object", 200 | "allOf": [ 201 | { 202 | "required": ["attrs"] 203 | }, 204 | { 205 | "oneOf": [ 206 | { 207 | "required": ["pk", "min", "max"], 208 | "not": { "required": ["sigs"] } 209 | }, 210 | { 211 | "required": ["sigs"], 212 | "not": { "required": ["pk", "min", "max"] } 213 | } 214 | ] 215 | } 216 | ], 217 | "properties": { 218 | "attrs": { 219 | "$ref": "#/definitions/attrs" 220 | }, 221 | "pk": { 222 | "$ref": "#/definitions/pk" 223 | }, 224 | "min": { 225 | "type": "number" 226 | }, 227 | "max": { 228 | "type": "number" 229 | }, 230 | "sigs": { 231 | "type": "array", 232 | "minItems": 1, 233 | "items": { 234 | "type": "string" 235 | } 236 | } 237 | } 238 | }, 239 | "set": { 240 | "type": "object", 241 | "allOf": [ 242 | { 243 | "required": ["attrs", "pk", "type"] 244 | }, 245 | { 246 | "oneOf": [ 247 | { 248 | "required": ["value"], 249 | "not": { "required": ["circuit"] } 250 | }, 251 | { 252 | "required": ["circuit"], 253 | "not": { "required": ["value"] } 254 | } 255 | ] 256 | } 257 | ], 258 | "properties": { 259 | "attrs": { 260 | "$ref": "#/definitions/attrs" 261 | }, 262 | "pk": { 263 | "$ref": "#/definitions/pk" 264 | }, 265 | "value": { 266 | "type": "integer" 267 | }, 268 | "circuit": { 269 | "type": "string" 270 | } 271 | } 272 | }, 273 | "verifiable_enc": { 274 | "type": "object", 275 | "required": ["attrs", "pk", "crypto_val", "label"], 276 | "properties": { 277 | "attrs": { 278 | "$ref": "#/definitions/attrs" 279 | }, 280 | "pk": { 281 | "$ref": "#/definitions/pk" 282 | }, 283 | "crypto_val": { 284 | "type": "string" 285 | }, 286 | "label": { 287 | "type": "string", 288 | "description": "Decryption Policy" 289 | } 290 | } 291 | }, 292 | "nym": { 293 | "type": "object", 294 | "required": ["attrs", "crypto_val"], 295 | "properties": { 296 | "attrs": { 297 | "$ref": "#/definitions/attrs" 298 | }, 299 | "crypto_val": { 300 | "type": "string" 301 | } 302 | } 303 | }, 304 | "scope_nym": { 305 | "type": "object", 306 | "required": ["attrs", "crypto_cal", "scope"], 307 | "properties": { 308 | "attrs": { 309 | "$ref": "#/definitions/attrs" 310 | }, 311 | "crypto_val": { 312 | "type": "string" 313 | }, 314 | "scope": { 315 | "type": "string" 316 | } 317 | } 318 | } 319 | } 320 | } 321 | -------------------------------------------------------------------------------- /src/commitments/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate amcl; 2 | extern crate rand; 3 | 4 | use hash_functions::HashError; 5 | 6 | #[derive(Debug)] 7 | pub enum CommitmentError { 8 | ZeroCountInPedersenSetup(String), 9 | InvalidPointSize(usize, usize), 10 | InvalidBigNumSize(usize, usize), 11 | ZeroMessageCount(String), 12 | InvalidGeneratorCount(usize, usize), 13 | HashError(HashError) 14 | } 15 | 16 | impl From for CommitmentError { 17 | fn from(err: HashError) -> CommitmentError { 18 | CommitmentError::HashError(err) 19 | } 20 | } 21 | 22 | // QUESTION: It would be better if we use generic group element for this trait so it can be used 23 | // with Elliptic curves or IntegerMod groups like 24 | // trait CommitmentScheme { 25 | // fn setup(num_elements: u32) -> Vec; 26 | trait CommitmentScheme { 27 | // Returns setup parameters. 28 | // The return type can be changed to Vec when we define a `GroupElement` struct 29 | fn setup(num_elements: usize) -> Result>, CommitmentError>; 30 | 31 | // Commits to `messages`. Returns a commitment 32 | fn commit(generators: &[&[u8]], messages: &[&[u8]]) -> Result<(Vec, Vec), CommitmentError>; 33 | 34 | // Takes the `opening` and check that the `commitment` was indeed done for the `messages` 35 | fn verify(commitment: &[u8], opening: &[u8], generators: &[&[u8]], messages: &[&[u8]]) -> Result; 36 | } 37 | 38 | pub mod pedersen_BLS12_381; 39 | -------------------------------------------------------------------------------- /src/commitments/pedersen_BLS12_381.rs: -------------------------------------------------------------------------------- 1 | extern crate amcl; 2 | extern crate rand; 3 | 4 | use self::rand::rngs::EntropyRng; 5 | 6 | use self::amcl::bls381::ecp::ECP; 7 | use self::amcl::bls381::big::{BIG, MODBYTES}; 8 | 9 | use hash_functions::HashFunction; 10 | use hash_functions::bls12_381_hash::BLS12_381_SHA256_G1; 11 | 12 | use commitments::CommitmentScheme; 13 | use commitments::CommitmentError; 14 | use utils::random::random_big_number; 15 | use amcl::bls381::rom::CURVE_ORDER; 16 | 17 | const SETUP_SEED_G1: &'static str = "Hyperledger-Cryptolib-Pedersen-Commitment-BLS-12-381-G1"; 18 | const GROUP_G1_SIZE: usize = 2 * MODBYTES + 1; 19 | 20 | struct PedersenCommitmentBLS12_381_SHA256_G1 {} 21 | 22 | impl CommitmentScheme for PedersenCommitmentBLS12_381_SHA256_G1 { 23 | // Returns `num_elements` + 1 generators. This is useful when committing to several messages say 24 | // m_1, m_2, m_3, and so on. `setup` will this output g_1, g_2, g_3, g_4 and so on which can then be 25 | // used for commitment f(g_1, g_2, g_3, g_4, ..., m_1, m_2, m_3...) 26 | fn setup(num_elements: usize) -> Result>, CommitmentError> { 27 | if num_elements == 0 { 28 | return Err(CommitmentError::ZeroCountInPedersenSetup(String::from("num_elements cannot be 0"))) 29 | } 30 | let mut generators: Vec = vec![]; 31 | let mut hf = BLS12_381_SHA256_G1::new(None)?; 32 | hf.update(SETUP_SEED_G1.as_bytes()); 33 | for _ in 0..num_elements+1 { 34 | generators.push(hf.hash_on_group()); 35 | let m = hf.digest(None)?; 36 | hf.update(&m); 37 | } 38 | Ok(generators.iter_mut().map(|g| { 39 | let mut temp: [u8; GROUP_G1_SIZE] = [0; GROUP_G1_SIZE]; 40 | g.tobytes(&mut temp, false); 41 | temp.to_vec() 42 | }).collect() 43 | ) 44 | } 45 | 46 | fn commit(generators: &[&[u8]], messages: &[&[u8]]) -> Result<(Vec, Vec), CommitmentError> { 47 | match Self::verify_generator_message_count(generators, messages) { 48 | Ok(_) => (), 49 | Err(err) => return Err(err) 50 | } 51 | 52 | let mut commitment = Self::commit_to_messages(generators, messages)?; 53 | let idx = messages.len(); 54 | let gen = Self::get_point_from_bytes(generators[idx])?; 55 | let mut blinding_factor_bytes: [u8; MODBYTES] = [0; MODBYTES]; 56 | 57 | let mut blinding_factor = random_big_number(&CURVE_ORDER, None); 58 | commitment.add(&gen.mul(&blinding_factor)); 59 | 60 | blinding_factor.tobytes(&mut blinding_factor_bytes); 61 | 62 | // Zero the bytes of blinding factor. 63 | // TODO: A better mechanism is needed. Use either libsodium or some other library that makes sure that `blinding_factor` 64 | // was never swapped to disk or was core dumped. 65 | blinding_factor.zero(); 66 | 67 | let mut comm_bytes: [u8; GROUP_G1_SIZE] = [0; GROUP_G1_SIZE]; 68 | commitment.tobytes(&mut comm_bytes, false); 69 | 70 | Ok((comm_bytes.to_vec(), blinding_factor_bytes.to_vec())) 71 | } 72 | 73 | fn verify(commitment: &[u8], opening: &[u8], generators: &[&[u8]], messages: &[&[u8]]) -> Result { 74 | let mut commitment = Self::get_point_from_bytes(commitment)?; 75 | let opening = Self::get_bignum_from_bytes(opening)?; 76 | 77 | match Self::verify_generator_message_count(generators, messages) { 78 | Ok(_) => (), 79 | Err(err) => return Err(err) 80 | } 81 | 82 | let mut to_check = Self::commit_to_messages(generators, messages)?; 83 | let idx = messages.len(); 84 | let gen = Self::get_point_from_bytes(generators[idx])?; 85 | to_check.add(&gen.mul(&opening)); 86 | Ok(to_check.equals(&mut commitment)) 87 | } 88 | } 89 | 90 | impl PedersenCommitmentBLS12_381_SHA256_G1 { 91 | // Check that there are enough generators for messages 92 | fn verify_generator_message_count(generators: &[&[u8]], messages: &[&[u8]]) -> Result<(), CommitmentError> { 93 | if messages.len() < 1 { 94 | return Err(CommitmentError::ZeroMessageCount(String::from("messages cannot be empty"))) 95 | } 96 | // Extra generators will not be used. 97 | if generators.len() < (messages.len() + 1) { 98 | return Err(CommitmentError::InvalidGeneratorCount(generators.len(), messages.len())) 99 | } 100 | Ok(()) 101 | } 102 | 103 | fn get_point_from_bytes(point_bytes: &[u8]) -> Result { 104 | if point_bytes.len() != GROUP_G1_SIZE { 105 | return Err(CommitmentError::InvalidPointSize(point_bytes.len(), GROUP_G1_SIZE)) 106 | } 107 | Ok(ECP::frombytes(point_bytes)) 108 | } 109 | 110 | fn get_bignum_from_bytes(bignum_bytes: &[u8]) -> Result { 111 | if bignum_bytes.len() != MODBYTES { 112 | return Err(CommitmentError::InvalidBigNumSize(bignum_bytes.len(), MODBYTES)) 113 | } 114 | Ok(BIG::frombytes(bignum_bytes)) 115 | } 116 | 117 | // Used during both commitment and verification 118 | fn commit_to_messages(generators: &[&[u8]], messages: &[&[u8]]) -> Result { 119 | let mut commitment = ECP::new(); 120 | for i in 0..messages.len() { 121 | let gen = Self::get_point_from_bytes(generators[i])?; 122 | let mut hf = BLS12_381_SHA256_G1::new(None)?; 123 | hf.update(messages[i]); 124 | let msg = hf.digest(None)?; 125 | let c = gen.mul(&BIG::frombytes(&msg)); 126 | commitment.add(&c); 127 | } 128 | Ok(commitment) 129 | } 130 | } 131 | 132 | // Alternate implementation 133 | 134 | /* 135 | impl CommitmentScheme for PedersenCommitment { 136 | fn setup(num_elements: u32) -> Vec { 137 | unimplemented!(); 138 | } 139 | } 140 | */ 141 | #[cfg(test)] 142 | mod tests { 143 | use super::*; 144 | use std::collections::HashSet; 145 | 146 | fn check_g1_elem_length(elem: &[u8]) { 147 | assert_eq!(elem.len(), GROUP_G1_SIZE); 148 | } 149 | 150 | fn check_bignum_elem_length(elem: &[u8]) { 151 | assert_eq!(elem.len(), MODBYTES); 152 | } 153 | 154 | #[test] 155 | fn test_setup() { 156 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::setup(0).is_err()); 157 | 158 | for l in vec![1, 2, 3, 10, 100] { 159 | let result = PedersenCommitmentBLS12_381_SHA256_G1::setup(l).unwrap(); 160 | assert_eq!(result.len(), l+1); 161 | 162 | let mut gens: HashSet> = HashSet::new(); 163 | 164 | for r in result { 165 | // All generators have valid size 166 | check_g1_elem_length(&r); 167 | 168 | // All generators can be used to create the group element 169 | ECP::frombytes(&r); 170 | 171 | gens.insert(r); 172 | } 173 | 174 | // All generators are distinct 175 | assert_eq!(gens.len(), l+1); 176 | } 177 | } 178 | 179 | #[test] 180 | fn test_commit() { 181 | let gens_1 = PedersenCommitmentBLS12_381_SHA256_G1::setup(1).unwrap(); 182 | let gens_1: Vec<&[u8]> = gens_1.iter().map(|g|g.as_slice()).collect(); 183 | let msgs_1 = vec!["hello".as_bytes(), "world".as_bytes()]; 184 | 185 | // No messages 186 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::commit(&gens_1, 187 | &vec![]).is_err()); 188 | // Insufficient number of generators 189 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::commit(&gens_1, 190 | &msgs_1).is_err()); 191 | 192 | // Extra bytes in one of the generator 193 | let mut gens_2 = PedersenCommitmentBLS12_381_SHA256_G1::setup(1).unwrap(); 194 | let mut v = gens_2[1].clone(); 195 | v.push(8); 196 | gens_2[1] = v; 197 | let msgs_2 = vec!["hello world".as_bytes()]; 198 | let gens_2: Vec<&[u8]> = gens_2.iter().map(|g|g.as_slice()).collect(); 199 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::commit(&gens_2, 200 | &msgs_2).is_err()); 201 | 202 | let msgs = vec!["hello world", "going to die now", "i am dead"]; 203 | 204 | for i in 0..msgs.len() { 205 | let gens = PedersenCommitmentBLS12_381_SHA256_G1::setup(i+1).unwrap(); 206 | let gens: Vec<&[u8]> = gens.iter().map(|g|g.as_slice()).collect(); 207 | let m: Vec<&[u8]> = msgs.iter().take(i+1).map(|msg| msg.as_bytes()).collect(); 208 | let (c, b) = PedersenCommitmentBLS12_381_SHA256_G1::commit(&gens, 209 | &m).unwrap(); 210 | check_g1_elem_length(&c); 211 | check_bignum_elem_length(&b); 212 | } 213 | } 214 | 215 | #[test] 216 | fn test_verify() { 217 | let msgs = vec!["hello world", "going to die now", "i am dead"]; 218 | 219 | let msg_list_producing_error = vec!["hello world", "going to die now", "i am dead", "extra message"]; 220 | 221 | assert!(msg_list_producing_error.len() > msgs.len()); 222 | 223 | let m_err: Vec<&[u8]> = msg_list_producing_error.iter().map(|msg| msg.as_bytes()).collect(); 224 | 225 | for i in 0..msgs.len() { 226 | let gens_ = PedersenCommitmentBLS12_381_SHA256_G1::setup(i+1).unwrap(); 227 | let gens: Vec<&[u8]> = gens_.iter().map(|g|g.as_slice()).collect(); 228 | let m: Vec<&[u8]> = msgs.iter().take(i+1).map(|msg| msg.as_bytes()).collect(); 229 | let (mut c, mut b) = PedersenCommitmentBLS12_381_SHA256_G1::commit(&gens, 230 | &m).unwrap(); 231 | check_g1_elem_length(&c); 232 | check_bignum_elem_length(&b); 233 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::verify(&c, &b, &gens, &m).unwrap()); 234 | 235 | // No messages 236 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::verify(&c, &b, &gens, &vec![]).is_err()); 237 | 238 | // Insufficient number of generators 239 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::verify(&c, &b, &gens, &m_err).is_err()); 240 | 241 | // Extra bytes in one of the commitment 242 | let mut c_1 = c.clone(); 243 | c_1.push(10); 244 | 245 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::verify(&c_1, &b, &gens, &m).is_err()); 246 | 247 | // Extra bytes in one of the opening 248 | let mut b_1 = b.clone(); 249 | b_1.push(11); 250 | 251 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::verify(&c, &b_1, &gens, &m).is_err()); 252 | 253 | // Extra bytes in one of the commitment and opening 254 | assert!(PedersenCommitmentBLS12_381_SHA256_G1::verify(&c_1, &b_1, &gens, &m).is_err()); 255 | } 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /src/ffi/mod.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger-labs/z-mix/652e0066da8640fa54dcc6cce50c81dd28e93cd9/src/ffi/mod.rs -------------------------------------------------------------------------------- /src/hash_functions/bls12_381_hash.rs: -------------------------------------------------------------------------------- 1 | extern crate amcl; 2 | 3 | use std::collections::HashMap; 4 | 5 | use self::amcl::bls381::ecp::ECP; 6 | use self::amcl::bls381::ecp2::ECP2; 7 | use self::amcl::bls381::mpin::{SHA256, hash_id}; 8 | use self::amcl::bls381::big::MODBYTES; 9 | 10 | use hash_functions::{HashFunction, HashError}; 11 | 12 | const GROUP1_DOMAIN_SEP: u8 = 1; 13 | const GROUP2_DOMAIN_SEP: u8 = 2; 14 | 15 | 16 | pub struct BLS12_381_SHA256_G1 { 17 | msg: Vec, 18 | digest: [u8; MODBYTES] 19 | } 20 | 21 | impl HashFunction for BLS12_381_SHA256_G1 { 22 | fn new(args: Option>) -> Result { 23 | if args.is_some() { 24 | return Err(HashError::InvalidArgs(String::from("Does not expect any args"))) 25 | } 26 | 27 | Ok(BLS12_381_SHA256_G1 { 28 | msg: vec![], 29 | digest: [0; MODBYTES], 30 | }) 31 | } 32 | 33 | fn update(&mut self, input: &[u8]) { 34 | self.msg.push(GROUP1_DOMAIN_SEP); 35 | self.msg.extend_from_slice(input); 36 | let mut h: [u8; MODBYTES] = [0; MODBYTES]; 37 | hash_id(SHA256, &self.msg, &mut h); 38 | self.digest = h; 39 | } 40 | 41 | fn digest(&self, length: Option) -> Result, HashError> { 42 | let mut hash_point = self.hash_on_group(); 43 | let mut digest_bytes: [u8; 2*MODBYTES+1] = [0; 2*MODBYTES+1]; 44 | hash_point.tobytes(&mut digest_bytes, false); 45 | return_digest(&digest_bytes, length) 46 | } 47 | } 48 | 49 | impl BLS12_381_SHA256_G1 { 50 | // Map the digest to group G1 51 | pub fn hash_on_group(&self) -> ECP { 52 | ECP::mapit(&self.digest) 53 | } 54 | } 55 | 56 | pub struct BLS12_381_SHA256_G2 { 57 | msg: Vec, 58 | digest: [u8; MODBYTES] 59 | } 60 | 61 | impl HashFunction for BLS12_381_SHA256_G2 { 62 | fn new(args: Option>) -> Result { 63 | if args.is_some() { 64 | return Err(HashError::InvalidArgs(String::from("Does not expect any args"))) 65 | } 66 | 67 | Ok(BLS12_381_SHA256_G2 { 68 | msg: vec![], 69 | digest: [0; MODBYTES], 70 | }) 71 | } 72 | 73 | fn update(&mut self, input: &[u8]) { 74 | self.msg.push(GROUP2_DOMAIN_SEP); 75 | self.msg.extend_from_slice(input); 76 | let mut h: [u8; MODBYTES] = [0; MODBYTES]; 77 | hash_id(SHA256, &self.msg, &mut h); 78 | self.digest = h; 79 | } 80 | 81 | fn digest(&self, length: Option) -> Result, HashError> { 82 | let mut hash_point = self.hash_on_group(); 83 | let mut digest_bytes: [u8; 4*MODBYTES] = [0; 4*MODBYTES]; 84 | hash_point.tobytes(&mut digest_bytes); 85 | return_digest(&digest_bytes, length) 86 | } 87 | } 88 | 89 | impl BLS12_381_SHA256_G2 { 90 | // Map the digest to group G2 91 | pub fn hash_on_group(&self) -> ECP2 { 92 | ECP2::mapit(&self.digest) 93 | } 94 | } 95 | 96 | fn return_digest(digest_bytes: &[u8], length: Option) -> Result, HashError> { 97 | match length { 98 | Some(l) => { 99 | if l > digest_bytes.len() { 100 | return Err(HashError::InvalidDigestLength(String::from("Length greater than digest"))) 101 | } else { 102 | Ok(digest_bytes[0..l].to_vec()) 103 | } 104 | } 105 | None => Ok(digest_bytes.to_vec()) 106 | } 107 | } 108 | 109 | #[cfg(test)] 110 | mod test { 111 | use super::*; 112 | 113 | fn gen_test_msgs<'a>() -> Vec<&'a str> { 114 | vec!["hello world", 115 | "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", 116 | "", 117 | "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source." 118 | ] 119 | } 120 | 121 | macro_rules! digest_test { 122 | ( $HashFunc:ident, $output_byte_size:expr ) => { 123 | 124 | for msg in &gen_test_msgs() { 125 | let mut hf = $HashFunc::new(None).unwrap(); 126 | hf.update(msg.as_bytes()); 127 | let d1 = hf.digest(None).unwrap(); 128 | 129 | let mut hf = $HashFunc::new(None).unwrap(); 130 | hf.update(msg.as_bytes()); 131 | let d2 = hf.digest(None).unwrap(); 132 | 133 | assert_eq!(d1, d2); 134 | 135 | let d = hf.digest(Some($output_byte_size+10)); 136 | assert!(d.is_err()); 137 | 138 | for n in vec![1, 2, 10, 20, $output_byte_size] { 139 | let d = hf.digest(Some($output_byte_size-n)).unwrap(); 140 | assert_eq!(d2[0..$output_byte_size-n], d[0..$output_byte_size-n]); 141 | } 142 | } 143 | 144 | let mut hf1 = $HashFunc::new(None).unwrap(); 145 | for msg in &gen_test_msgs() { 146 | hf1.update(msg.as_bytes()); 147 | } 148 | let d1 = hf1.digest(None).unwrap(); 149 | 150 | let mut hf2 = $HashFunc::new(None).unwrap(); 151 | for msg in &gen_test_msgs() { 152 | hf2.update(msg.as_bytes()); 153 | } 154 | let d2 = hf2.digest(None).unwrap(); 155 | 156 | assert_eq!(d1, d2); 157 | }; 158 | } 159 | 160 | macro_rules! hashing_on_groups_test { 161 | ( $HashFunc:ident ) => { 162 | for msg in &gen_test_msgs() { 163 | let mut hf = $HashFunc::new(None).unwrap(); 164 | hf.update(msg.as_bytes()); 165 | let mut g1n1 = hf.hash_on_group(); 166 | 167 | let mut hf = $HashFunc::new(None).unwrap(); 168 | hf.update(msg.as_bytes()); 169 | let mut g1n2 = hf.hash_on_group(); 170 | 171 | assert_eq!(g1n1.tostring(), g1n2.tostring()); 172 | 173 | } 174 | } 175 | } 176 | 177 | #[test] 178 | fn test_msg_digest() { 179 | let hm: HashMap = HashMap::new(); 180 | let hf = BLS12_381_SHA256_G1::new(Some(hm)); 181 | assert!(hf.is_err()); 182 | 183 | digest_test!(BLS12_381_SHA256_G1, 2*MODBYTES+1); 184 | digest_test!(BLS12_381_SHA256_G2, 4*MODBYTES); 185 | } 186 | 187 | #[test] 188 | fn test_hashing_on_groups() { 189 | hashing_on_groups_test!(BLS12_381_SHA256_G1); 190 | hashing_on_groups_test!(BLS12_381_SHA256_G2); 191 | } 192 | } -------------------------------------------------------------------------------- /src/hash_functions/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | /* 4 | Hash function like hashing a message in a Group or a function like SHA-3 or BLAKE*. 5 | 6 | Say you want to hash in group G1 of BLS12-381 curve, there would be an implementation of this 7 | trait, say `BLS12_381_G1_Hash` 8 | ``` 9 | impl HashFunction for BLS12_381_G1_Hash .... { 10 | ...... 11 | } 12 | let mut args = HashMap::new(); 13 | args.insert( 14 | "hash_function".to_string(), &[8, 198, 90, 120, .....], // results in string "SHA256" 15 | ); 16 | let hf = BLS12_381_G1_Hash::new(Some(args)); 17 | let x = [100, 200, 250, 901, .....] 18 | hf.update(&x) 19 | hf.digest() 20 | ``` 21 | 22 | Say you want to hash with SHA-3 (or some new hash algo which does not have a vetted implementation), 23 | there would be an implementation of this trait, say `SHA3_Hash` 24 | `` 25 | impl HashFunction for SHA3_Hash .... { 26 | ...... 27 | } 28 | let hf = BLS12_381_Hash::new(None); 29 | let x = [100, 200, 250, 11, .....] 30 | hf.update(&x) 31 | let y = [234, 57, 99, 76, .....] 32 | hf.update(&y) 33 | hf.digest() 34 | ``` 35 | */ 36 | 37 | #[derive(Debug)] 38 | pub enum HashError { 39 | InvalidArgs(String), 40 | InvalidDigestLength(String) 41 | } 42 | 43 | pub trait HashFunction where Self: Sized { 44 | // Creates a new one hash function. `args` is a map, some example args can be curve type, 45 | // curve order, key (in case of keyed hash function), compression support 46 | fn new(args: Option>) -> Result; 47 | 48 | // Updates the hash object. Can be called any number of times 49 | fn update(&mut self, input: &[u8]); 50 | 51 | // Returns the digest. Length is passed as `Some()` in case of an XOF like SHAKE; 52 | // `None` otherwise 53 | fn digest(&self, length: Option) -> Result, HashError>; 54 | } 55 | 56 | pub mod bls12_381_hash; 57 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate serde_json; 3 | extern crate amcl; 4 | 5 | 6 | pub mod commitments; 7 | pub mod ffi; 8 | pub mod zkl; 9 | pub mod prf; 10 | pub mod hash_functions; 11 | pub mod signatures; 12 | pub mod utils; -------------------------------------------------------------------------------- /src/prf/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | /* 4 | Pseudo Random Function like modular exponentiation. 5 | Say you want to exponentiate in a prime field `p` with generator `g`, there would be an implementation of this 6 | trait, say `ModExpPrimeField` 7 | ``` 8 | impl PRF for ModExpPrimeField .... { 9 | ...... 10 | } 11 | let mut args = HashMap::new(); 12 | args.insert( 13 | "field_size".to_string(), &[8, 198, 90, 120, .....], 14 | "generator".to_string(), &[90, 2, 34, 55, .....], 15 | ); 16 | let owf = ModExpPrimeField::new(args); 17 | let x = [100, 200, 250, 901, .....] 18 | owf.compute(&x) 19 | ``` 20 | */ 21 | trait PRF { 22 | // Creates a new Pseudo Random Function. `args` is a map, some example args can be curve type, 23 | // curve order, compression support. 24 | fn new(args: HashMap) -> Self; 25 | 26 | // Compute the one way function. 27 | fn compute(&self, input: &[u8]) -> Vec; 28 | } -------------------------------------------------------------------------------- /src/signatures/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | /* 4 | Say you want to have an ECDSA signature using curve secp256k1, and the implementation is called 5 | ECDSA_secp256k1 6 | ``` 7 | impl SignatureScheme for ECDSA_secp256k1 .... { 8 | ...... 9 | } 10 | let mut args = HashMap::new(); 11 | args.insert( 12 | "hash_function".to_string(), &[90, 12, 33, 45, .....], // results in string "RIPEMD160" 13 | ); 14 | let sig_scheme = ECDSA_secp256k1::new(Some(&args)); 15 | let (sk, vk) = sig_scheme.gen_keypair(None); 16 | let msg = vec![2, 4, 6, ...]; 17 | let sig = sig_scheme.sign(&msg, &sk, None); 18 | sig_scheme.verify(&sig, &msg, &vk); 19 | ``` 20 | */ 21 | 22 | trait SignatureScheme { 23 | // This outputs a new `SignatureScheme` object initialised with necessary system params. 24 | // Equivalent to "Setup" in literature 25 | fn new(args: Option>) -> Self; 26 | // Generates a Signing key, Verification key pair. The "seed" or other parameters 27 | // can be part of `args` 28 | fn gen_keypair(&self, args: Option>) -> (Vec, Vec); 29 | 30 | // Generate signature on a message `message` using signing key `sig_key`. 31 | fn sign(&self, message: &[u8], sig_key: &[u8], extra: Option<&[u8]>) -> Vec; 32 | 33 | // Verify signature `signature` on a message `message` using verification key `ver_key` 34 | fn verify(&self, signature: &[u8], message: &[u8], ver_key: &[u8]) -> bool; 35 | } -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod random; 2 | -------------------------------------------------------------------------------- /src/utils/random.rs: -------------------------------------------------------------------------------- 1 | extern crate rand; 2 | extern crate amcl; 3 | 4 | use self::rand::RngCore; 5 | use self::rand::rngs::EntropyRng; 6 | 7 | use self::amcl::rand::{RAND}; 8 | use self::amcl::arch::Chunk; 9 | use self::amcl::bls381::big::BIG; 10 | 11 | 12 | pub fn get_seeded_RNG(entropy_size: usize, rng: Option) -> RAND { 13 | // initialise from at least 128 byte string of raw random entropy 14 | let mut entropy = vec![0; entropy_size]; 15 | match rng { 16 | Some(mut rng) => rng.fill_bytes(&mut entropy.as_mut_slice()), 17 | None => { 18 | let mut rng = EntropyRng::new(); 19 | rng.fill_bytes(&mut entropy.as_mut_slice()); 20 | } 21 | } 22 | let mut r = RAND::new(); 23 | r.clean(); 24 | r.seed(entropy_size, &entropy); 25 | r 26 | } 27 | 28 | pub fn random_big_number(order: &[Chunk], rng: Option) -> BIG { 29 | // initialise from at least 128 byte string of raw random entropy 30 | let entropy_size = 256; 31 | let mut r = get_seeded_RNG(entropy_size, rng); 32 | BIG::randomnum(&BIG::new_ints(&order), &mut r) 33 | } -------------------------------------------------------------------------------- /src/zkl/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod spec; 2 | 3 | pub struct Parser {} 4 | 5 | impl Parser { 6 | pub fn parse(proof_spec: &spec::ProofSpec, witness: &Witness) -> Result { 7 | unimplemented!(); 8 | } 9 | } 10 | 11 | pub struct Witness {} 12 | 13 | pub struct WitnessBuilder {} 14 | 15 | impl WitnessBuilder { 16 | pub fn new() -> WitnessBuilder { 17 | WitnessBuilder {} 18 | } 19 | } 20 | 21 | pub struct Proof {} 22 | 23 | impl Proof { 24 | pub fn verify(&self, proof_spec: &spec::ProofSpec) -> Result { 25 | unimplemented!(); 26 | } 27 | } 28 | 29 | #[repr(i32)] 30 | #[derive(Debug, Eq, PartialEq)] 31 | pub enum ZKLError { 32 | InvalidProofSpec = 1, 33 | InvalidWitness = 2 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn parse_empty_clause() { 42 | let proof_spec = ProofSpec{}; 43 | let witness = Witness{}; 44 | let result = Parser::parse(&proof_spec, &witness); 45 | assert!(result.is_err()); 46 | if let Err(e) = result { 47 | assert_eq!(e, ZKLError::InvalidProofSpec); 48 | } 49 | } 50 | 51 | #[test] 52 | fn parse_credential_clause() { 53 | //TODO: Add credential clause to the proof_spec 54 | let proof_spec = ProofSpec{}; 55 | let witness = Witness{}; 56 | assert!(Parser::parse(&proof_spec, &witness).is_ok()); 57 | } 58 | 59 | #[test] 60 | fn parse_interval_clause() { 61 | //TODO: Add interval clause to the proof_spec 62 | let proof_spec = ProofSpec{}; 63 | let witness = Witness{}; 64 | assert!(Parser::parse(&proof_spec, &witness).is_ok()); 65 | } 66 | 67 | #[test] 68 | fn parse_set_membership_clause() { 69 | //TODO: Add set membership clause to the proof_spec 70 | let proof_spec = ProofSpec{}; 71 | let witness = Witness{}; 72 | assert!(Parser::parse(&proof_spec, &witness).is_ok()); 73 | } 74 | 75 | #[test] 76 | fn parse_verifiable_encryption_clause() { 77 | //TODO: Add verifiable encryption clause to the proof_spec 78 | let proof_spec = ProofSpec{}; 79 | let witness = Witness{}; 80 | assert!(Parser::parse(&proof_spec, &witness).is_ok()); 81 | } 82 | 83 | #[test] 84 | fn parse_nym_clause() { 85 | //TODO: Add nym clause to the proof_spec 86 | let proof_spec = ProofSpec{}; 87 | let witness = Witness{}; 88 | assert!(Parser::parse(&proof_spec, &witness).is_ok()); 89 | } 90 | 91 | #[test] 92 | fn proof_verify() { 93 | let proof_spec = ProofSpec{}; 94 | let witness = Witness{}; 95 | let proof = Parser::parse(&proof_spec, &witness).unwrap(); 96 | 97 | assert!(proof.verify(&proof_spec).is_ok()); 98 | } 99 | 100 | #[test] 101 | fn proof_verify_fail_attribute_mismatch() { 102 | let proof_spec = ProofSpec{}; 103 | let witness = Witness{}; 104 | let proof = Parser::parse(&proof_spec, &witness).unwrap(); 105 | 106 | //Different proof spec 107 | let proof_spec = ProofSpec{}; 108 | assert!(proof.verify(&proof_spec).is_err()); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/zkl/spec.rs: -------------------------------------------------------------------------------- 1 | pub struct ProofSpec { 2 | pub attribute_count: u32, 3 | pub disclosed_attributes: Vec, 4 | pub clauses: Vec 5 | } 6 | 7 | /// Used for crossing ffi boundary like 'C' 8 | pub struct ProofSpecBuilder { 9 | attribute_count: u32, 10 | disclosed_attributes: Vec, 11 | clauses: Vec 12 | } 13 | 14 | impl ProofSpecBuilder { 15 | pub fn new() -> ProofSpecBuilder { 16 | ProofSpecBuilder { 17 | attribute_count: 0, 18 | disclosed_attributes: Vec::new(), 19 | clauses: Vec::new() 20 | } 21 | } 22 | 23 | pub fn add_clause(&mut self, clause: ProofSpecClauseType) { 24 | self.clauses.push(clause); 25 | } 26 | 27 | pub fn add_disclosed_attribute(&mut self, index: u32, value: &str) { 28 | self.disclosed_attributes.push(DisclosedAttribute{ index, value: value.to_owned() }); 29 | } 30 | 31 | pub fn set_attribute_count(&mut self, attribute_count: u32) { 32 | self.attribute_count = attribute_count; 33 | } 34 | 35 | pub fn finalize(self) -> ProofSpec { 36 | ProofSpec { 37 | attribute_count: self.attribute_count, 38 | disclosed_attributes: self.disclosed_attributes, 39 | clauses: self.clauses 40 | } 41 | } 42 | } 43 | 44 | pub enum ProofSpecClauseType { 45 | Credential, 46 | Interval, 47 | SetMembership, 48 | VerifiableEncryption, 49 | Nym 50 | } 51 | 52 | pub struct DisclosedAttribute { 53 | pub index: u32, 54 | pub value: String, 55 | } 56 | -------------------------------------------------------------------------------- /wrappers/dotnet/PLACEHOLDER.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger-labs/z-mix/652e0066da8640fa54dcc6cce50c81dd28e93cd9/wrappers/dotnet/PLACEHOLDER.md -------------------------------------------------------------------------------- /wrappers/golang/PLACEHOLDER.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger-labs/z-mix/652e0066da8640fa54dcc6cce50c81dd28e93cd9/wrappers/golang/PLACEHOLDER.md -------------------------------------------------------------------------------- /wrappers/ios/PLACEHOLDER.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger-labs/z-mix/652e0066da8640fa54dcc6cce50c81dd28e93cd9/wrappers/ios/PLACEHOLDER.md -------------------------------------------------------------------------------- /wrappers/java/android/PLACEHOLDER.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger-labs/z-mix/652e0066da8640fa54dcc6cce50c81dd28e93cd9/wrappers/java/android/PLACEHOLDER.md -------------------------------------------------------------------------------- /wrappers/java/jna/PLACEHOLDER.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger-labs/z-mix/652e0066da8640fa54dcc6cce50c81dd28e93cd9/wrappers/java/jna/PLACEHOLDER.md -------------------------------------------------------------------------------- /wrappers/nodejs/PLACEHOLDER.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger-labs/z-mix/652e0066da8640fa54dcc6cce50c81dd28e93cd9/wrappers/nodejs/PLACEHOLDER.md -------------------------------------------------------------------------------- /wrappers/python3/PLACEHOLDER.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger-labs/z-mix/652e0066da8640fa54dcc6cce50c81dd28e93cd9/wrappers/python3/PLACEHOLDER.md --------------------------------------------------------------------------------