├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENCE ├── 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 │ ├── bls383 │ ├── 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 │ ├── secp256k1 │ ├── big.rs │ ├── dbig.rs │ ├── ecdh.rs │ ├── ecp.rs │ ├── fp.rs │ ├── mod.rs │ └── rom.rs │ └── sha3.rs ├── benches └── bls381_benches.rs └── src ├── aggregates.rs ├── amcl_utils.rs ├── errors.rs ├── g1.rs ├── g2.rs ├── keys.rs ├── lib.rs ├── rng.rs ├── signature.rs └── test_vectors └── test_bls.yml /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | .idea/ 5 | amcl/target -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | script: 3 | - cargo build --verbose --all 4 | - cargo test --verbose --all 5 | - cargo fmt --all -- --check 6 | - | 7 | if [[ "$TRAVIS_RUST_VERSION" == nightly* ]]; then 8 | cargo build --no-default-features 9 | fi 10 | rust: 11 | - stable 12 | - beta 13 | - nightly 14 | matrix: 15 | allow_failures: 16 | - rust: nightly 17 | fast_finish: true 18 | install: 19 | - rustup component add rustfmt 20 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bls-aggregates" 3 | version = "0.7.0" 4 | authors = ["Lovesh Harchandani "] 5 | description = "Various signature schemes. BLS, MuSig" 6 | license = "MIT/Apache-2.0" 7 | 8 | [[bench]] 9 | name = "bls381_benches" 10 | harness = false 11 | 12 | [dependencies] 13 | amcl = { path = "./amcl", default-features = false } 14 | hex = { version = "0.3", optional = true } 15 | lazy_static = { version = "1.0", optional = true } 16 | rand = { version = "0.5", default-features = false } 17 | tiny-keccak = "1.4" 18 | yaml-rust = { version = "0.4", optional = true } 19 | 20 | # This cannot be specified as dev-dependencies. Otherwise a cargo bug will always resolve `rand` with `std` feature, which breaks `no_std` builds. 21 | criterion = { version = "0.2", optional = true } 22 | 23 | [features] 24 | default = ["std"] 25 | bench = ["criterion"] 26 | std = [ 27 | "amcl/std", 28 | "rand/std", 29 | "lazy_static", 30 | "hex", 31 | "yaml-rust", 32 | ] 33 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 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 2016 Sovrin Foundation 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ARCHIVED: PROJECT HAS MOVED 2 | 3 | **This repository has moved** to https://github.com/sigp/milagro_bls 4 | 5 | This repository will not be maintained, but active development (as of June 2019) continues at the new repository. 6 | 7 | ----- 8 | 9 | # BLS12-381 Aggregate Signatures in Rust using Apache Milagro 10 | 11 | [![Build Status](https://travis-ci.org/sigp/signature-schemes.svg?branch=master)](https://travis-ci.org/sigp/signature-schemes) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sigp/lighthouse?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 12 | 13 | **WARNING: This is an experiemental library and the cryptography is NOT SAFE!** 14 | 15 | Uses the [The Apache Milagro Cryptographic Library](https://github.com/milagro-crypto/amcl). 16 | 17 | This crate is heavily based upon work by 18 | [@lovesh](https://github.com/lovesh). 19 | 20 | Presently this library only supports features required for Ethereum 2.0 21 | signature validation. The aggregation methods here are vulnerable to the 22 | rouge-key attack. 23 | 24 | There has been no public audit or scrutiny placed upon this crate. If you're a 25 | cryptographer I would love to have your input. 26 | 27 | ## Usage 28 | 29 | ### Single Signatures 30 | 31 | Perform signing and verification of non-aggregate BLS signatures. Supports 32 | serializing and de-serializing both public and secret keys. 33 | 34 | ```rust 35 | let sk_bytes = vec![ 36 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37 | 78, 252, 122, 126, 32, 0, 75, 89, 252, 31, 42, 38 | 130, 254, 88, 6, 90, 138, 202, 135, 194, 233, 39 | 117, 181, 75, 96, 238, 79, 100, 237, 59, 140, 111 40 | ]; 41 | 42 | // Load some keys from a serialized secret key. 43 | let sk = SecretKey::from_bytes(&sk_bytes).unwrap(); 44 | let pk = PublicKey::from_secret_key(&sk); 45 | 46 | // Sign a message 47 | let message = "cats".as_bytes(); 48 | let signature = Signature::new(&message, &sk); 49 | assert!(signature.verify(&message, &pk)); 50 | 51 | // Serialize then de-serialize, just 'cause we can. 52 | let pk_bytes = pk.as_bytes(); 53 | let pk = PublicKey::from_bytes(&pk_bytes).unwrap(); 54 | 55 | // Verify the message 56 | assert!(signature.verify(&message, &pk)); 57 | ``` 58 | 59 | Generate new "random" secret keys (see SecretKey docs for information on 60 | entropy sources). 61 | 62 | ```rust 63 | // Generate a random key pair. 64 | let sk = SecretKey::random(); 65 | let pk = PublicKey::from_secret_key(&sk); 66 | 67 | // Sign and verify a message. 68 | let message = "cats".as_bytes(); 69 | let signature = Signature::new(&message, &sk); 70 | assert!(signature.verify(&message, &pk)); 71 | ``` 72 | 73 | ### Aggregate Signatures 74 | 75 | Aggregate signatures and public keys. Supports serializing and de-serializing 76 | both `AggregateSignatures` and `AggregatePublicKeys`. 77 | 78 | ```rust 79 | let signing_secret_key_bytes = vec![ 80 | vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 81 | 161, 50, 32, 254, 87, 16, 25, 167, 79, 192, 116, 176, 74, 82 | 164, 217, 40, 57, 179, 15, 19, 21, 240, 100, 70, 127, 111, 83 | 170, 129, 137, 42, 53], 84 | vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 85 | 72, 211, 104, 184, 68, 142, 208, 115, 22, 156, 97, 28, 86 | 216, 228, 102, 4, 218, 116, 226, 166, 131, 67, 7, 40, 55, 87 | 157, 167, 157, 127, 143, 13], 88 | ]; 89 | 90 | // Load the key pairs from our serialized secret keys, 91 | let signing_keypairs: Vec = signing_secret_key_bytes 92 | .iter() 93 | .map(|bytes| { 94 | let sk = SecretKey::from_bytes(&bytes).unwrap(); 95 | let pk = PublicKey::from_secret_key(&sk); 96 | Keypair{ sk, pk } 97 | }).collect(); 98 | 99 | let message = "cats".as_bytes(); 100 | 101 | // Create an aggregate signature over some message, also generating an 102 | // aggregate public key at the same time. 103 | let mut agg_sig = AggregateSignature::new(); 104 | let mut agg_pub_key = AggregatePublicKey::new(); 105 | for keypair in &signing_keypairs { 106 | let sig = Signature::new(&message, &keypair.sk); 107 | agg_sig.add(&sig); 108 | agg_pub_key.add(&keypair.pk); 109 | } 110 | 111 | // Serialize and de-serialize the aggregates, just 'cause we can. 112 | let agg_sig_bytes = agg_sig.as_bytes(); 113 | let agg_pub_bytes = agg_pub_key.as_bytes(); 114 | let agg_sig = AggregateSignature:: 115 | from_bytes(&agg_sig_bytes).unwrap(); 116 | let agg_pub_key = AggregatePublicKey:: 117 | from_bytes(&agg_pub_bytes).unwrap(); 118 | 119 | /// Verify the AggregateSignature against the AggregatePublicKey 120 | assert!(agg_sig.verify(&message, &agg_pub_key)); 121 | ``` 122 | -------------------------------------------------------------------------------- /amcl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "amcl" 3 | version = "0.1.0" 4 | authors = ["lovesh harchandani "] 5 | 6 | [dependencies] 7 | 8 | [features] 9 | default = ["std"] 10 | std = [] -------------------------------------------------------------------------------- /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 | #[cfg(feature = "std")] 252 | /* Convert to Hex String */ 253 | pub fn to_string(&mut self) -> String { 254 | let mut s = String::new(); 255 | let mut len=self.nbits(); 256 | 257 | if len%4==0 { 258 | len/=4; 259 | } else { 260 | len/=4; 261 | len+=1; 262 | } 263 | 264 | for i in (0 ..len).rev() { 265 | let mut b=DBIG::new_copy(&self); 266 | b.shr(i*4); 267 | s=s + &format!("{:X}", b.w[0]&15); 268 | } 269 | return s; 270 | } 271 | 272 | } 273 | -------------------------------------------------------------------------------- /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 | #[cfg(feature = "std")] 180 | /* convert to string */ 181 | pub fn tostring(&mut self) -> String { 182 | let s=self.redc().tostring(); 183 | return s; 184 | } 185 | 186 | /* reduce this mod Modulus */ 187 | pub fn reduce(&mut self) { 188 | let p = BIG::new_ints(&rom::MODULUS); 189 | self.x.rmod(&p); 190 | self.xes=1; 191 | } 192 | 193 | /* test this=0? */ 194 | pub fn iszilch(&mut self) -> bool { 195 | self.reduce(); 196 | return self.x.iszilch(); 197 | } 198 | 199 | /* copy from FP b */ 200 | pub fn copy(&mut self,b: &FP) { 201 | self.x.copy(&(b.x)); 202 | self.xes=b.xes; 203 | } 204 | 205 | /* copy from BIG b */ 206 | pub fn bcopy(&mut self,b: &BIG) { 207 | self.x.copy(&b); 208 | self.nres(); 209 | } 210 | 211 | /* set this=0 */ 212 | pub fn zero(&mut self) { 213 | self.x.zero(); 214 | self.xes=1; 215 | } 216 | 217 | /* set this=1 */ 218 | pub fn one(&mut self) { 219 | self.x.one(); self.nres() 220 | } 221 | 222 | /* normalise this */ 223 | pub fn norm(&mut self) { 224 | self.x.norm(); 225 | } 226 | /* swap FPs depending on d */ 227 | pub fn cswap(&mut self,b: &mut FP,d: isize) { 228 | self.x.cswap(&mut (b.x),d); 229 | let mut c=d as i32; 230 | c=!(c-1); 231 | let t=c&(self.xes^b.xes); 232 | self.xes^=t; 233 | b.xes^=t; 234 | } 235 | 236 | /* copy FPs depending on d */ 237 | pub fn cmove(&mut self,b: &FP,d: isize) { 238 | self.x.cmove(&(b.x),d); 239 | let c=d as i32; 240 | self.xes^=(self.xes^b.xes)&(-c); 241 | } 242 | 243 | /* this*=b mod Modulus */ 244 | pub fn mul(&mut self,b: &FP) 245 | { 246 | if (self.xes as i64)*(b.xes as i64) > FEXCESS as i64 {self.reduce()} 247 | 248 | let mut d=BIG::mul(&(self.x),&(b.x)); 249 | self.x.copy(&FP::modulo(&mut d)); 250 | self.xes=2; 251 | } 252 | 253 | fn logb2(w: u32) -> usize { 254 | let mut v=w; 255 | v |= v >> 1; 256 | v |= v >> 2; 257 | v |= v >> 4; 258 | v |= v >> 8; 259 | v |= v >> 16; 260 | 261 | v = v - ((v >> 1) & 0x55555555); 262 | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 263 | let r= (( ((v + (v >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24) as usize; 264 | return r; 265 | } 266 | 267 | /* this = -this mod Modulus */ 268 | pub fn neg(&mut self) { 269 | let mut p = BIG::new_ints(&rom::MODULUS); 270 | let sb=FP::logb2((self.xes-1) as u32); 271 | 272 | p.fshl(sb); 273 | self.x.rsub(&p); 274 | self.xes=1<<(sb as i32); 275 | if self.xes>FEXCESS {self.reduce()} 276 | 277 | } 278 | 279 | /* this*=c mod Modulus, where c is a small int */ 280 | pub fn imul(&mut self,c: isize) { 281 | let mut cc=c; 282 | // self.norm(); 283 | let mut s=false; 284 | if cc<0 { 285 | cc = -cc; 286 | s=true; 287 | } 288 | 289 | if MODTYPE==PSEUDO_MERSENNE || MODTYPE==GENERALISED_MERSENNE { 290 | let mut d=self.x.pxmul(cc); 291 | self.x.copy(&FP::modulo(&mut d)); 292 | self.xes=2 293 | } else { 294 | if self.xes*(cc as i32) <= FEXCESS { 295 | self.x.pmul(cc); 296 | self.xes*=cc as i32; 297 | } else { 298 | let n=FP::new_int(cc); 299 | self.mul(&n); 300 | } 301 | 302 | } 303 | 304 | if s {self.neg(); self.norm();} 305 | } 306 | 307 | /* self*=self mod Modulus */ 308 | pub fn sqr(&mut self) { 309 | // self.norm(); 310 | if (self.xes as i64)*(self.xes as i64) > FEXCESS as i64 {self.reduce()} 311 | 312 | 313 | let mut d=BIG::sqr(&(self.x)); 314 | self.x.copy(&FP::modulo(&mut d)); 315 | self.xes=2 316 | } 317 | 318 | /* self+=b */ 319 | pub fn add(&mut self,b: &FP) { 320 | self.x.add(&(b.x)); 321 | self.xes+=b.xes; 322 | if self.xes>FEXCESS {self.reduce()} 323 | } 324 | 325 | /* self+=self */ 326 | pub fn dbl(&mut self) { 327 | self.x.dbl(); 328 | self.xes+=self.xes; 329 | if self.xes>FEXCESS {self.reduce()} 330 | } 331 | 332 | /* self-=b */ 333 | pub fn sub(&mut self,b: &FP) 334 | { 335 | let mut n=FP::new_copy(b); 336 | n.neg(); 337 | self.add(&n); 338 | } 339 | 340 | /* self=b-self */ 341 | pub fn rsub(&mut self,b: &FP) 342 | { 343 | self.neg(); 344 | self.add(&b); 345 | } 346 | 347 | /* self/=2 mod Modulus */ 348 | pub fn div2(&mut self) { 349 | // self.x.norm(); 350 | if self.x.parity()==0 { 351 | self.x.fshr(1); 352 | } else { 353 | let p = BIG::new_ints(&rom::MODULUS); 354 | self.x.add(&p); 355 | self.x.norm(); 356 | self.x.fshr(1); 357 | } 358 | } 359 | /* self=1/self mod Modulus */ 360 | pub fn inverse(&mut self) { 361 | /* 362 | let mut p = BIG::new_ints(&rom::MODULUS); 363 | let mut r=self.redc(); 364 | r.invmodp(&mut p); 365 | self.x.copy(&r); 366 | self.nres(); 367 | */ 368 | let mut m2 = BIG::new_ints(&rom::MODULUS); 369 | m2.dec(2); m2.norm(); 370 | let inv=self.pow(&mut m2); 371 | self.copy(&inv); 372 | } 373 | 374 | /* return TRUE if self==a */ 375 | pub fn equals(&mut self,a: &mut FP) -> bool { 376 | a.reduce(); 377 | self.reduce(); 378 | if BIG::comp(&(a.x),&self.x)==0 {return true} 379 | return false; 380 | } 381 | 382 | 383 | /* return self^e mod Modulus */ 384 | pub fn pow(&mut self,e: &mut BIG) -> FP { 385 | 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()]; 386 | const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4; 387 | let mut w:[i8;CT]=[0;CT]; 388 | 389 | self.norm(); 390 | let mut t=BIG::new_copy(e); 391 | t.norm(); 392 | let nb=1+(t.nbits()+3)/4; 393 | 394 | for i in 0..nb { 395 | let lsbs=t.lastbits(4); 396 | t.dec(lsbs); 397 | t.norm(); 398 | w[i]=lsbs as i8; 399 | t.fshr(4); 400 | } 401 | tb[0].one(); 402 | tb[1].copy(&self); 403 | 404 | let mut c=FP::new(); 405 | for i in 2..16 { 406 | c.copy(&tb[i-1]); 407 | tb[i].copy(&c); 408 | tb[i].mul(&self); 409 | } 410 | let mut r=FP::new_copy(&tb[w[nb-1] as usize]); 411 | for i in (0..nb-1).rev() { 412 | r.sqr(); 413 | r.sqr(); 414 | r.sqr(); 415 | r.sqr(); 416 | r.mul(&tb[w[i] as usize]) 417 | } 418 | r.reduce(); 419 | return r; 420 | } 421 | 422 | /* return self^e mod Modulus 423 | pub fn pow(&mut self,e: &mut BIG) -> FP { 424 | let p = BIG::new_ints(&rom::MODULUS); 425 | let mut r=FP::new_int(1); 426 | e.norm(); 427 | self.x.norm(); 428 | let mut m=FP::new_copy(self); 429 | loop { 430 | let bt=e.parity(); 431 | e.fshr(1); 432 | if bt==1 {r.mul(&m)} 433 | if e.iszilch() {break} 434 | m.sqr(); 435 | } 436 | r.x.rmod(&p); 437 | return r; 438 | } */ 439 | 440 | /* return sqrt(this) mod Modulus */ 441 | pub fn sqrt(&mut self) -> FP { 442 | self.reduce(); 443 | let mut p = BIG::new_ints(&rom::MODULUS); 444 | if MOD8==5 { 445 | p.dec(5); p.norm(); p.shr(3); 446 | let mut i=FP::new_copy(self); i.x.shl(1); 447 | let v=i.pow(&mut p); 448 | i.mul(&v); i.mul(&v); 449 | i.x.dec(1); 450 | let mut r=FP::new_copy(self); 451 | r.mul(&v); r.mul(&i); 452 | r.reduce(); 453 | return r; 454 | } 455 | else 456 | { 457 | p.inc(1); p.norm(); p.shr(2); 458 | return self.pow(&mut p); 459 | } 460 | } 461 | /* return jacobi symbol (this/Modulus) */ 462 | pub fn jacobi(&mut self) -> isize 463 | { 464 | let mut p = BIG::new_ints(&rom::MODULUS); 465 | let mut w=self.redc(); 466 | return w.jacobi(&mut p); 467 | } 468 | 469 | } 470 | /* 471 | fn main() { 472 | let p = BIG::new_ints(&rom::MODULUS); 473 | let mut e = BIG::new_copy(&p); 474 | e.dec(1); 475 | 476 | let mut x = FP::new_int(3); 477 | let mut s=x.pow(&mut e); 478 | 479 | println!("s= {}",s.tostring()); 480 | } 481 | */ 482 | -------------------------------------------------------------------------------- /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 | #[cfg(feature = "std")] 283 | /* output to hex string */ 284 | pub fn tostring(&mut self) -> String { 285 | return format!("[{},{}]",self.a.tostring(),self.b.tostring()); 286 | } 287 | 288 | /* self=1/self */ 289 | pub fn inverse(&mut self) { 290 | self.norm(); 291 | let mut w1=FP::new_copy(&self.a); 292 | let mut w2=FP::new_copy(&self.b); 293 | 294 | w1.sqr(); 295 | w2.sqr(); 296 | w1.add(&w2); 297 | w1.inverse(); 298 | self.a.mul(&w1); 299 | w1.neg(); w1.norm(); 300 | self.b.mul(&w1); 301 | } 302 | 303 | /* self/=2 */ 304 | pub fn div2(&mut self) { 305 | self.a.div2(); 306 | self.b.div2(); 307 | } 308 | 309 | /* self*=sqrt(-1) */ 310 | pub fn times_i(&mut self) { 311 | // a.norm(); 312 | let z=FP::new_copy(&self.a); 313 | self.a.copy(&self.b); self.a.neg(); 314 | self.b.copy(&z); 315 | } 316 | 317 | /* w*=(1+sqrt(-1)) */ 318 | /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */ 319 | pub fn mul_ip(&mut self) { 320 | // self.norm(); 321 | let t=FP2::new_copy(self); 322 | let z=FP::new_copy(&self.a); 323 | self.a.copy(&self.b); 324 | self.a.neg(); 325 | self.b.copy(&z); 326 | self.add(&t); 327 | // self.norm(); 328 | } 329 | 330 | pub fn div_ip2(&mut self) { 331 | let mut t=FP2::new(); 332 | self.norm(); 333 | t.a.copy(&self.a); t.a.add(&self.b); 334 | t.b.copy(&self.b); t.b.sub(&self.a); 335 | t.norm(); self.copy(&t); 336 | } 337 | 338 | /* w/=(1+sqrt(-1)) */ 339 | pub fn div_ip(&mut self) { 340 | let mut t=FP2::new(); 341 | self.norm(); 342 | t.a.copy(&self.a); t.a.add(&self.b); 343 | t.b.copy(&self.b); t.b.sub(&self.a); 344 | t.norm(); self.copy(&t); 345 | self.div2(); 346 | } 347 | 348 | } 349 | /* 350 | fn main() 351 | { 352 | let mut x=FP2::new(); 353 | } 354 | */ 355 | -------------------------------------------------------------------------------- /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 | #[cfg(feature = "std")] 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 | 291 | let mut t1=FP2::new_copy(&self.a); 292 | let mut t2=FP2::new_copy(&self.b); 293 | 294 | t1.sqr(); 295 | t2.sqr(); 296 | t2.mul_ip(); t2.norm(); 297 | t1.sub(&t2); 298 | t1.inverse(); 299 | self.a.mul(&t1); 300 | t1.neg(); t1.norm(); 301 | self.b.mul(&t1); 302 | } 303 | 304 | /* self*=i where i = sqrt(-1+sqrt(-1)) */ 305 | pub fn times_i(&mut self) { 306 | // self.norm(); 307 | let mut s=FP2::new_copy(&self.b); 308 | let mut t=FP2::new_copy(&self.b); 309 | s.times_i(); 310 | t.add(&s); 311 | // t.norm(); 312 | self.b.copy(&self.a); 313 | self.a.copy(&t); 314 | self.norm(); 315 | } 316 | 317 | /* self=self^p using Frobenius */ 318 | pub fn frob(&mut self,f: &FP2) { 319 | self.a.conj(); 320 | self.b.conj(); 321 | self.b.mul(f); 322 | } 323 | 324 | /* self=self^e */ 325 | pub fn pow(&mut self,e: &mut BIG) -> FP4 { 326 | self.norm(); 327 | e.norm(); 328 | let mut w=FP4::new_copy(self); 329 | let mut z=BIG::new_copy(&e); 330 | let mut r=FP4::new_int(1); 331 | loop { 332 | let bt=z.parity(); 333 | z.fshr(1); 334 | if bt==1 {r.mul(&mut w)}; 335 | if z.iszilch() {break} 336 | w.sqr(); 337 | } 338 | r.reduce(); 339 | return r; 340 | } 341 | 342 | /* XTR xtr_a function */ 343 | pub fn xtr_a(&mut self,w:&FP4,y:&FP4,z:&FP4) { 344 | let mut r=FP4::new_copy(w); 345 | let mut t=FP4::new_copy(w); 346 | // y.norm(); 347 | r.sub(y); r.norm(); 348 | r.pmul(&self.a); 349 | t.add(y); t.norm(); 350 | t.pmul(&self.b); 351 | t.times_i(); 352 | 353 | self.copy(&r); 354 | self.add(&t); 355 | self.add(z); 356 | 357 | self.norm(); 358 | } 359 | 360 | /* XTR xtr_d function */ 361 | pub fn xtr_d(&mut self) { 362 | let mut w=FP4::new_copy(self); 363 | self.sqr(); w.conj(); 364 | w.dbl(); w.norm(); 365 | self.sub(&w); 366 | self.reduce(); 367 | } 368 | 369 | /* r=x^n using XTR method on traces of FP12s */ 370 | pub fn xtr_pow(&mut self,n: &mut BIG) -> FP4 { 371 | let mut a=FP4::new_int(3); 372 | let mut b=FP4::new_copy(self); 373 | let mut c=FP4::new_copy(&b); 374 | c.xtr_d(); 375 | let mut t=FP4::new(); 376 | let mut r=FP4::new(); 377 | 378 | n.norm(); 379 | let par=n.parity(); 380 | let mut v=BIG::new_copy(n); v.fshr(1); 381 | if par==0 {v.dec(1); v.norm(); } 382 | 383 | let nb=v.nbits(); 384 | for i in (0..nb).rev() { 385 | if v.bit(i)!=1 { 386 | t.copy(&b); 387 | self.conj(); 388 | c.conj(); 389 | b.xtr_a(&a,self,&c); 390 | self.conj(); 391 | c.copy(&t); 392 | c.xtr_d(); 393 | a.xtr_d(); 394 | } else { 395 | t.copy(&a); t.conj(); 396 | a.copy(&b); 397 | a.xtr_d(); 398 | b.xtr_a(&c,self,&t); 399 | c.xtr_d(); 400 | } 401 | } 402 | if par==0 { 403 | r.copy(&c) 404 | } else {r.copy(&b)} 405 | r.reduce(); 406 | return r; 407 | } 408 | 409 | /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ 410 | pub fn xtr_pow2(&mut self,ck: &FP4,ckml: &FP4,ckm2l: &FP4,a: &mut BIG,b: &mut BIG) -> FP4 { 411 | a.norm(); b.norm(); 412 | let mut e=BIG::new_copy(a); 413 | let mut d=BIG::new_copy(b); 414 | let mut w=BIG::new(); 415 | 416 | let mut cu=FP4::new_copy(ck); // can probably be passed in w/o copying 417 | let mut cv=FP4::new_copy(self); 418 | let mut cumv=FP4::new_copy(ckml); 419 | let mut cum2v=FP4::new_copy(ckm2l); 420 | let mut r=FP4::new(); 421 | let mut t=FP4::new(); 422 | 423 | let mut f2:usize=0; 424 | while d.parity()==0 && e.parity()==0 { 425 | d.fshr(1); 426 | e.fshr(1); 427 | f2+=1; 428 | } 429 | 430 | while BIG::comp(&d,&e)!=0 { 431 | if BIG::comp(&d,&e)>0 { 432 | w.copy(&e); w.imul(4); w.norm(); 433 | if BIG::comp(&d,&w)<=0 { 434 | w.copy(&d); d.copy(&e); 435 | e.rsub(&w); e.norm(); 436 | 437 | t.copy(&cv); 438 | t.xtr_a(&cu,&cumv,&cum2v); 439 | cum2v.copy(&cumv); 440 | cum2v.conj(); 441 | cumv.copy(&cv); 442 | cv.copy(&cu); 443 | cu.copy(&t); 444 | } else { 445 | if d.parity()==0 { 446 | d.fshr(1); 447 | r.copy(&cum2v); r.conj(); 448 | t.copy(&cumv); 449 | t.xtr_a(&cu,&cv,&r); 450 | cum2v.copy(&cumv); 451 | cum2v.xtr_d(); 452 | cumv.copy(&t); 453 | cu.xtr_d(); 454 | } else { 455 | if e.parity()==1 { 456 | d.sub(&e); d.norm(); 457 | d.fshr(1); 458 | t.copy(&cv); 459 | t.xtr_a(&cu,&cumv,&cum2v); 460 | cu.xtr_d(); 461 | cum2v.copy(&cv); 462 | cum2v.xtr_d(); 463 | cum2v.conj(); 464 | cv.copy(&t); 465 | } else { 466 | w.copy(&d); 467 | d.copy(&e); d.fshr(1); 468 | e.copy(&w); 469 | t.copy(&cumv); 470 | t.xtr_d(); 471 | cumv.copy(&cum2v); cumv.conj(); 472 | cum2v.copy(&t); cum2v.conj(); 473 | t.copy(&cv); 474 | t.xtr_d(); 475 | cv.copy(&cu); 476 | cu.copy(&t); 477 | } 478 | } 479 | } 480 | } 481 | if BIG::comp(&d,&e)<0 { 482 | w.copy(&d); w.imul(4); w.norm(); 483 | if BIG::comp(&e,&w)<=0 { 484 | e.sub(&d); e.norm(); 485 | t.copy(&cv); 486 | t.xtr_a(&cu,&cumv,&cum2v); 487 | cum2v.copy(&cumv); 488 | cumv.copy(&cu); 489 | cu.copy(&t); 490 | } else { 491 | if e.parity()==0 { 492 | w.copy(&d); 493 | d.copy(&e); d.fshr(1); 494 | e.copy(&w); 495 | t.copy(&cumv); 496 | t.xtr_d(); 497 | cumv.copy(&cum2v); cumv.conj(); 498 | cum2v.copy(&t); cum2v.conj(); 499 | t.copy(&cv); 500 | t.xtr_d(); 501 | cv.copy(&cu); 502 | cu.copy(&t); 503 | } else { 504 | if d.parity()==1 { 505 | w.copy(&e); 506 | e.copy(&d); 507 | w.sub(&d); w.norm(); 508 | d.copy(&w); d.fshr(1); 509 | t.copy(&cv); 510 | t.xtr_a(&cu,&cumv,&cum2v); 511 | cumv.conj(); 512 | cum2v.copy(&cu); 513 | cum2v.xtr_d(); 514 | cum2v.conj(); 515 | cu.copy(&cv); 516 | cu.xtr_d(); 517 | cv.copy(&t); 518 | } else { 519 | d.fshr(1); 520 | r.copy(&cum2v); r.conj(); 521 | t.copy(&cumv); 522 | t.xtr_a(&cu,&cv,&r); 523 | cum2v.copy(&cumv); 524 | cum2v.xtr_d(); 525 | cumv.copy(&t); 526 | cu.xtr_d(); 527 | } 528 | } 529 | } 530 | } 531 | } 532 | r.copy(&cv); 533 | r.xtr_a(&cu,&cumv,&cum2v); 534 | for _ in 0..f2 {r.xtr_d()} 535 | r=r.xtr_pow(&mut d); 536 | return r; 537 | } 538 | 539 | 540 | /* this/=2 */ 541 | pub fn div2(&mut self) { 542 | self.a.div2(); 543 | self.b.div2(); 544 | } 545 | 546 | pub fn div_i(&mut self) { 547 | let mut u=FP2::new_copy(&self.a); 548 | let v=FP2::new_copy(&self.b); 549 | u.div_ip(); 550 | self.a.copy(&v); 551 | self.b.copy(&u); 552 | } 553 | 554 | pub fn div_2i(&mut self) { 555 | let mut u=FP2::new_copy(&self.a); 556 | let mut v=FP2::new_copy(&self.b); 557 | u.div_ip2(); 558 | v.dbl(); v.norm(); 559 | self.a.copy(&v); 560 | self.b.copy(&u); 561 | } 562 | 563 | /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */ 564 | /* returns true if this is QR */ 565 | pub fn sqrt(&mut self) -> bool { 566 | if self.iszilch() {return true;} 567 | 568 | let mut a=FP2::new_copy(&self.a); 569 | let mut s=FP2::new_copy(&self.b); 570 | let mut t=FP2::new_copy(&self.a); 571 | 572 | if s.iszilch() { 573 | if t.sqrt() { 574 | self.a.copy(&t); 575 | self.b.zero(); 576 | } else { 577 | t.div_ip(); 578 | t.sqrt(); 579 | self.b.copy(&t); 580 | self.a.zero(); 581 | } 582 | return true; 583 | } 584 | s.sqr(); 585 | a.sqr(); 586 | s.mul_ip(); 587 | s.norm(); 588 | a.sub(&s); 589 | 590 | s.copy(&a); 591 | if !s.sqrt() { 592 | return false; 593 | } 594 | 595 | a.copy(&t); a.add(&s); a.norm(); a.div2(); 596 | 597 | if !a.sqrt() { 598 | a.copy(&t); a.sub(&s); a.norm(); a.div2(); 599 | if !a.sqrt() { 600 | return false 601 | } 602 | } 603 | t.copy(&self.b); 604 | s.copy(&a); s.add(&a); 605 | s.inverse(); 606 | 607 | t.mul(&s); 608 | self.a.copy(&a); 609 | self.b.copy(&t); 610 | 611 | return true; 612 | } 613 | 614 | 615 | } 616 | /* 617 | fn main() 618 | { 619 | let mut w=FP4::new(); 620 | } 621 | */ 622 | -------------------------------------------------------------------------------- /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/rom.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::NLEN; 21 | use arch::Chunk; 22 | 23 | // Base Bits= 58 24 | // bls381 Modulus 25 | 26 | pub const MODULUS:[Chunk;NLEN]=[0x1FEFFFFFFFFAAAB,0x2FFFFAC54FFFFEE,0x12A0F6B0F6241EA,0x213CE144AFD9CC3,0x2434BACD764774B,0x25FF9A692C6E9ED,0x1A0111EA3]; 27 | pub const R2MODP:[Chunk;NLEN]=[0x20639A1D5BEF7AE,0x1244C6462DD93E8,0x22D09B54E6E2CD2,0x111C4B63170E5DB,0x38A6DE8FB366399,0x4F16CFED1F9CBC,0x19EA66A2B]; 28 | pub const MCONST:Chunk=0x1F3FFFCFFFCFFFD; 29 | pub const FRA:[Chunk;NLEN]=[0x10775ED92235FB8,0x3A94F58F9E04F63,0x3D784BAB9C4F67,0x3F4F2F57D3DEC91,0x202C0D1F0FD603,0xAEC199F08C6FAD,0x1904D3BF0]; 30 | pub const FRB:[Chunk;NLEN]=[0xF78A126DDC4AF3,0x356B0535B1FB08B,0xEC971F63C5F282,0x21EDB1ECDBFB032,0x2231F9FB854A147,0x1B1380CA23A7A40,0xFC3E2B3]; 31 | 32 | pub const CURVE_COF_I:isize = 0; 33 | pub const CURVE_A:isize = 0; 34 | pub const CURVE_B_I:isize = 4; 35 | pub const CURVE_B:[Chunk;NLEN]=[0x4,0x0,0x0,0x0,0x0,0x0,0x0]; 36 | pub const CURVE_ORDER:[Chunk;NLEN]=[0x3FFFFFF00000001,0x36900BFFF96FFBF,0x180809A1D80553B,0x14CA675F520CCE7,0x73EDA7,0x0,0x0]; 37 | pub const CURVE_GX:[Chunk;NLEN]=[0x33AF00ADB22C6BB,0x17A0FFE5E86BBFE,0x3A3F171BAC586C5,0x13E5DD2E4168538,0x4FA9AC0FC3688C,0x65F5E509A558E3,0x17F1D3A73]; 38 | pub const CURVE_GY:[Chunk;NLEN]=[0xAA232946C5E7E1,0x331D128A222B903,0x18CB2C04B3EDD03,0x25757402BD8036C,0x1741D8AE4FCF5E0,0xEAA83C68278C3B,0x8B3F481E]; 39 | 40 | pub const CURVE_BNX:[Chunk;NLEN]=[0x201000000010000,0x34,0x0,0x0,0x0,0x0,0x0]; 41 | pub const CURVE_COF:[Chunk;NLEN]=[0xAAAB0000AAAB,0x3230015557855A3,0x396,0x0,0x0,0x0,0x0]; 42 | pub const CURVE_CRU:[Chunk;NLEN]=[0x201FFFFFFFEFFFE,0x1F604D88280008B,0x293BE6F89688DE1,0x1DA83DDFAB76CE,0x3DF76CE51BA69C6,0x17C659CB,0x0]; 43 | 44 | pub const CURVE_PXA:[Chunk;NLEN]=[0x8056C8C121BDB8,0x300C9AA016EFBF5,0xB647AE3D1770BA,0x353E900EC0AD144,0x32DC51051C6E47A,0x23C2A449820149,0x24AA2B2F]; 45 | pub const CURVE_PXB:[Chunk;NLEN]=[0x1AC7D055D042B7E,0x33C4484E51755F9,0x21BBDC7F5049334,0x3426482D86AD769,0x88274F65596BD0,0x9C67D81F6B34E8,0x13E02B605]; 46 | pub const CURVE_PYA:[Chunk;NLEN]=[0x193548608B82801,0x2B2730EEB28A278,0x1A695160D12C923,0x2AA32F74E9DB50A,0x2DA2E351AADFD9B,0x9F5B8463327371,0xCE5D5277]; 47 | pub const CURVE_PYB:[Chunk;NLEN]=[0x2A9075FF05F79BE,0x1C349D73B07686A,0x12AB572E99AB3F3,0x1FA169D8EBC99D2,0x2BC28B99CB3E28,0x3A9CD330CAB34AC,0x606C4A02]; 48 | pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]; 49 | pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]; 50 | pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]; 51 | pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]; 52 | 53 | pub const USE_GLV:bool = true; 54 | pub const USE_GS_G2:bool = true; 55 | pub const USE_GS_GT:bool = true; 56 | pub const GT_STRONG:bool = false; 57 | -------------------------------------------------------------------------------- /amcl/src/bls383/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 bls383::big; 22 | use bls383::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 | #[cfg(feature = "std")] 252 | /* Convert to Hex String */ 253 | pub fn to_string(&mut self) -> String { 254 | let mut s = String::new(); 255 | let mut len=self.nbits(); 256 | 257 | if len%4==0 { 258 | len/=4; 259 | } else { 260 | len/=4; 261 | len+=1; 262 | } 263 | 264 | for i in (0 ..len).rev() { 265 | let mut b=DBIG::new_copy(&self); 266 | b.shr(i*4); 267 | s=s + &format!("{:X}", b.w[0]&15); 268 | } 269 | return s; 270 | } 271 | 272 | } 273 | -------------------------------------------------------------------------------- /amcl/src/bls383/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 bls383::big; 21 | use bls383::big::BIG; 22 | use bls383::dbig::DBIG; 23 | use bls383::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 = 383; /* 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)<<23); 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 | #[cfg(feature = "std")] 180 | /* convert to string */ 181 | pub fn tostring(&mut self) -> String { 182 | let s=self.redc().tostring(); 183 | return s; 184 | } 185 | 186 | /* reduce this mod Modulus */ 187 | pub fn reduce(&mut self) { 188 | let p = BIG::new_ints(&rom::MODULUS); 189 | self.x.rmod(&p); 190 | self.xes=1; 191 | } 192 | 193 | /* test this=0? */ 194 | pub fn iszilch(&mut self) -> bool { 195 | self.reduce(); 196 | return self.x.iszilch(); 197 | } 198 | 199 | /* copy from FP b */ 200 | pub fn copy(&mut self,b: &FP) { 201 | self.x.copy(&(b.x)); 202 | self.xes=b.xes; 203 | } 204 | 205 | /* copy from BIG b */ 206 | pub fn bcopy(&mut self,b: &BIG) { 207 | self.x.copy(&b); 208 | self.nres(); 209 | } 210 | 211 | /* set this=0 */ 212 | pub fn zero(&mut self) { 213 | self.x.zero(); 214 | self.xes=1; 215 | } 216 | 217 | /* set this=1 */ 218 | pub fn one(&mut self) { 219 | self.x.one(); self.nres() 220 | } 221 | 222 | /* normalise this */ 223 | pub fn norm(&mut self) { 224 | self.x.norm(); 225 | } 226 | /* swap FPs depending on d */ 227 | pub fn cswap(&mut self,b: &mut FP,d: isize) { 228 | self.x.cswap(&mut (b.x),d); 229 | let mut c=d as i32; 230 | c=!(c-1); 231 | let t=c&(self.xes^b.xes); 232 | self.xes^=t; 233 | b.xes^=t; 234 | } 235 | 236 | /* copy FPs depending on d */ 237 | pub fn cmove(&mut self,b: &FP,d: isize) { 238 | self.x.cmove(&(b.x),d); 239 | let c=d as i32; 240 | self.xes^=(self.xes^b.xes)&(-c); 241 | } 242 | 243 | /* this*=b mod Modulus */ 244 | pub fn mul(&mut self,b: &FP) 245 | { 246 | if (self.xes as i64)*(b.xes as i64) > FEXCESS as i64 {self.reduce()} 247 | 248 | let mut d=BIG::mul(&(self.x),&(b.x)); 249 | self.x.copy(&FP::modulo(&mut d)); 250 | self.xes=2; 251 | } 252 | 253 | fn logb2(w: u32) -> usize { 254 | let mut v=w; 255 | v |= v >> 1; 256 | v |= v >> 2; 257 | v |= v >> 4; 258 | v |= v >> 8; 259 | v |= v >> 16; 260 | 261 | v = v - ((v >> 1) & 0x55555555); 262 | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 263 | let r= (( ((v + (v >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24) as usize; 264 | return r; 265 | } 266 | 267 | /* this = -this mod Modulus */ 268 | pub fn neg(&mut self) { 269 | let mut p = BIG::new_ints(&rom::MODULUS); 270 | let sb=FP::logb2((self.xes-1) as u32); 271 | 272 | p.fshl(sb); 273 | self.x.rsub(&p); 274 | self.xes=1<<(sb as i32); 275 | if self.xes>FEXCESS {self.reduce()} 276 | 277 | } 278 | 279 | /* this*=c mod Modulus, where c is a small int */ 280 | pub fn imul(&mut self,c: isize) { 281 | let mut cc=c; 282 | // self.norm(); 283 | let mut s=false; 284 | if cc<0 { 285 | cc = -cc; 286 | s=true; 287 | } 288 | 289 | if MODTYPE==PSEUDO_MERSENNE || MODTYPE==GENERALISED_MERSENNE { 290 | let mut d=self.x.pxmul(cc); 291 | self.x.copy(&FP::modulo(&mut d)); 292 | self.xes=2 293 | } else { 294 | if self.xes*(cc as i32) <= FEXCESS { 295 | self.x.pmul(cc); 296 | self.xes*=cc as i32; 297 | } else { 298 | let n=FP::new_int(cc); 299 | self.mul(&n); 300 | } 301 | 302 | } 303 | 304 | if s {self.neg(); self.norm();} 305 | } 306 | 307 | /* self*=self mod Modulus */ 308 | pub fn sqr(&mut self) { 309 | // self.norm(); 310 | if (self.xes as i64)*(self.xes as i64) > FEXCESS as i64 {self.reduce()} 311 | 312 | 313 | let mut d=BIG::sqr(&(self.x)); 314 | self.x.copy(&FP::modulo(&mut d)); 315 | self.xes=2 316 | } 317 | 318 | /* self+=b */ 319 | pub fn add(&mut self,b: &FP) { 320 | self.x.add(&(b.x)); 321 | self.xes+=b.xes; 322 | if self.xes>FEXCESS {self.reduce()} 323 | } 324 | 325 | /* self+=self */ 326 | pub fn dbl(&mut self) { 327 | self.x.dbl(); 328 | self.xes+=self.xes; 329 | if self.xes>FEXCESS {self.reduce()} 330 | } 331 | 332 | /* self-=b */ 333 | pub fn sub(&mut self,b: &FP) 334 | { 335 | let mut n=FP::new_copy(b); 336 | n.neg(); 337 | self.add(&n); 338 | } 339 | 340 | /* self=b-self */ 341 | pub fn rsub(&mut self,b: &FP) 342 | { 343 | self.neg(); 344 | self.add(&b); 345 | } 346 | 347 | /* self/=2 mod Modulus */ 348 | pub fn div2(&mut self) { 349 | // self.x.norm(); 350 | if self.x.parity()==0 { 351 | self.x.fshr(1); 352 | } else { 353 | let p = BIG::new_ints(&rom::MODULUS); 354 | self.x.add(&p); 355 | self.x.norm(); 356 | self.x.fshr(1); 357 | } 358 | } 359 | /* self=1/self mod Modulus */ 360 | pub fn inverse(&mut self) { 361 | /* 362 | let mut p = BIG::new_ints(&rom::MODULUS); 363 | let mut r=self.redc(); 364 | r.invmodp(&mut p); 365 | self.x.copy(&r); 366 | self.nres(); 367 | */ 368 | let mut m2 = BIG::new_ints(&rom::MODULUS); 369 | m2.dec(2); m2.norm(); 370 | let inv=self.pow(&mut m2); 371 | self.copy(&inv); 372 | } 373 | 374 | /* return TRUE if self==a */ 375 | pub fn equals(&mut self,a: &mut FP) -> bool { 376 | a.reduce(); 377 | self.reduce(); 378 | if BIG::comp(&(a.x),&self.x)==0 {return true} 379 | return false; 380 | } 381 | 382 | 383 | /* return self^e mod Modulus */ 384 | pub fn pow(&mut self,e: &mut BIG) -> FP { 385 | 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()]; 386 | const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4; 387 | let mut w:[i8;CT]=[0;CT]; 388 | 389 | self.norm(); 390 | let mut t=BIG::new_copy(e); 391 | t.norm(); 392 | let nb=1+(t.nbits()+3)/4; 393 | 394 | for i in 0..nb { 395 | let lsbs=t.lastbits(4); 396 | t.dec(lsbs); 397 | t.norm(); 398 | w[i]=lsbs as i8; 399 | t.fshr(4); 400 | } 401 | tb[0].one(); 402 | tb[1].copy(&self); 403 | 404 | let mut c=FP::new(); 405 | for i in 2..16 { 406 | c.copy(&tb[i-1]); 407 | tb[i].copy(&c); 408 | tb[i].mul(&self); 409 | } 410 | let mut r=FP::new_copy(&tb[w[nb-1] as usize]); 411 | for i in (0..nb-1).rev() { 412 | r.sqr(); 413 | r.sqr(); 414 | r.sqr(); 415 | r.sqr(); 416 | r.mul(&tb[w[i] as usize]) 417 | } 418 | r.reduce(); 419 | return r; 420 | } 421 | 422 | /* return self^e mod Modulus 423 | pub fn pow(&mut self,e: &mut BIG) -> FP { 424 | let p = BIG::new_ints(&rom::MODULUS); 425 | let mut r=FP::new_int(1); 426 | e.norm(); 427 | self.x.norm(); 428 | let mut m=FP::new_copy(self); 429 | loop { 430 | let bt=e.parity(); 431 | e.fshr(1); 432 | if bt==1 {r.mul(&m)} 433 | if e.iszilch() {break} 434 | m.sqr(); 435 | } 436 | r.x.rmod(&p); 437 | return r; 438 | } */ 439 | 440 | /* return sqrt(this) mod Modulus */ 441 | pub fn sqrt(&mut self) -> FP { 442 | self.reduce(); 443 | let mut p = BIG::new_ints(&rom::MODULUS); 444 | if MOD8==5 { 445 | p.dec(5); p.norm(); p.shr(3); 446 | let mut i=FP::new_copy(self); i.x.shl(1); 447 | let v=i.pow(&mut p); 448 | i.mul(&v); i.mul(&v); 449 | i.x.dec(1); 450 | let mut r=FP::new_copy(self); 451 | r.mul(&v); r.mul(&i); 452 | r.reduce(); 453 | return r; 454 | } 455 | else 456 | { 457 | p.inc(1); p.norm(); p.shr(2); 458 | return self.pow(&mut p); 459 | } 460 | } 461 | /* return jacobi symbol (this/Modulus) */ 462 | pub fn jacobi(&mut self) -> isize 463 | { 464 | let mut p = BIG::new_ints(&rom::MODULUS); 465 | let mut w=self.redc(); 466 | return w.jacobi(&mut p); 467 | } 468 | 469 | } 470 | /* 471 | fn main() { 472 | let p = BIG::new_ints(&rom::MODULUS); 473 | let mut e = BIG::new_copy(&p); 474 | e.dec(1); 475 | 476 | let mut x = FP::new_int(3); 477 | let mut s=x.pow(&mut e); 478 | 479 | println!("s= {}",s.tostring()); 480 | } 481 | */ 482 | -------------------------------------------------------------------------------- /amcl/src/bls383/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 bls383::fp; 21 | use bls383::fp::FP; 22 | use bls383::big::BIG; 23 | use bls383::dbig::DBIG; 24 | use bls383::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 | #[cfg(feature = "std")] 283 | /* output to hex string */ 284 | pub fn tostring(&mut self) -> String { 285 | return format!("[{},{}]",self.a.tostring(),self.b.tostring()); 286 | } 287 | 288 | /* self=1/self */ 289 | pub fn inverse(&mut self) { 290 | self.norm(); 291 | let mut w1=FP::new_copy(&self.a); 292 | let mut w2=FP::new_copy(&self.b); 293 | 294 | w1.sqr(); 295 | w2.sqr(); 296 | w1.add(&w2); 297 | w1.inverse(); 298 | self.a.mul(&w1); 299 | w1.neg(); w1.norm(); 300 | self.b.mul(&w1); 301 | } 302 | 303 | /* self/=2 */ 304 | pub fn div2(&mut self) { 305 | self.a.div2(); 306 | self.b.div2(); 307 | } 308 | 309 | /* self*=sqrt(-1) */ 310 | pub fn times_i(&mut self) { 311 | // a.norm(); 312 | let z=FP::new_copy(&self.a); 313 | self.a.copy(&self.b); self.a.neg(); 314 | self.b.copy(&z); 315 | } 316 | 317 | /* w*=(1+sqrt(-1)) */ 318 | /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */ 319 | pub fn mul_ip(&mut self) { 320 | // self.norm(); 321 | let t=FP2::new_copy(self); 322 | let z=FP::new_copy(&self.a); 323 | self.a.copy(&self.b); 324 | self.a.neg(); 325 | self.b.copy(&z); 326 | self.add(&t); 327 | // self.norm(); 328 | } 329 | 330 | pub fn div_ip2(&mut self) { 331 | let mut t=FP2::new(); 332 | self.norm(); 333 | t.a.copy(&self.a); t.a.add(&self.b); 334 | t.b.copy(&self.b); t.b.sub(&self.a); 335 | t.norm(); self.copy(&t); 336 | } 337 | 338 | /* w/=(1+sqrt(-1)) */ 339 | pub fn div_ip(&mut self) { 340 | let mut t=FP2::new(); 341 | self.norm(); 342 | t.a.copy(&self.a); t.a.add(&self.b); 343 | t.b.copy(&self.b); t.b.sub(&self.a); 344 | t.norm(); self.copy(&t); 345 | self.div2(); 346 | } 347 | 348 | } 349 | /* 350 | fn main() 351 | { 352 | let mut x=FP2::new(); 353 | } 354 | */ 355 | -------------------------------------------------------------------------------- /amcl/src/bls383/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 bls383::fp::FP; 21 | use bls383::fp2::FP2; 22 | use bls383::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 | #[cfg(feature = "std")] 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 | 291 | let mut t1=FP2::new_copy(&self.a); 292 | let mut t2=FP2::new_copy(&self.b); 293 | 294 | t1.sqr(); 295 | t2.sqr(); 296 | t2.mul_ip(); t2.norm(); 297 | t1.sub(&t2); 298 | t1.inverse(); 299 | self.a.mul(&t1); 300 | t1.neg(); t1.norm(); 301 | self.b.mul(&t1); 302 | } 303 | 304 | /* self*=i where i = sqrt(-1+sqrt(-1)) */ 305 | pub fn times_i(&mut self) { 306 | // self.norm(); 307 | let mut s=FP2::new_copy(&self.b); 308 | let mut t=FP2::new_copy(&self.b); 309 | s.times_i(); 310 | t.add(&s); 311 | // t.norm(); 312 | self.b.copy(&self.a); 313 | self.a.copy(&t); 314 | self.norm(); 315 | } 316 | 317 | /* self=self^p using Frobenius */ 318 | pub fn frob(&mut self,f: &FP2) { 319 | self.a.conj(); 320 | self.b.conj(); 321 | self.b.mul(f); 322 | } 323 | 324 | /* self=self^e */ 325 | pub fn pow(&mut self,e: &mut BIG) -> FP4 { 326 | self.norm(); 327 | e.norm(); 328 | let mut w=FP4::new_copy(self); 329 | let mut z=BIG::new_copy(&e); 330 | let mut r=FP4::new_int(1); 331 | loop { 332 | let bt=z.parity(); 333 | z.fshr(1); 334 | if bt==1 {r.mul(&mut w)}; 335 | if z.iszilch() {break} 336 | w.sqr(); 337 | } 338 | r.reduce(); 339 | return r; 340 | } 341 | 342 | /* XTR xtr_a function */ 343 | pub fn xtr_a(&mut self,w:&FP4,y:&FP4,z:&FP4) { 344 | let mut r=FP4::new_copy(w); 345 | let mut t=FP4::new_copy(w); 346 | // y.norm(); 347 | r.sub(y); r.norm(); 348 | r.pmul(&self.a); 349 | t.add(y); t.norm(); 350 | t.pmul(&self.b); 351 | t.times_i(); 352 | 353 | self.copy(&r); 354 | self.add(&t); 355 | self.add(z); 356 | 357 | self.norm(); 358 | } 359 | 360 | /* XTR xtr_d function */ 361 | pub fn xtr_d(&mut self) { 362 | let mut w=FP4::new_copy(self); 363 | self.sqr(); w.conj(); 364 | w.dbl(); w.norm(); 365 | self.sub(&w); 366 | self.reduce(); 367 | } 368 | 369 | /* r=x^n using XTR method on traces of FP12s */ 370 | pub fn xtr_pow(&mut self,n: &mut BIG) -> FP4 { 371 | let mut a=FP4::new_int(3); 372 | let mut b=FP4::new_copy(self); 373 | let mut c=FP4::new_copy(&b); 374 | c.xtr_d(); 375 | let mut t=FP4::new(); 376 | let mut r=FP4::new(); 377 | 378 | n.norm(); 379 | let par=n.parity(); 380 | let mut v=BIG::new_copy(n); v.fshr(1); 381 | if par==0 {v.dec(1); v.norm(); } 382 | 383 | let nb=v.nbits(); 384 | for i in (0..nb).rev() { 385 | if v.bit(i)!=1 { 386 | t.copy(&b); 387 | self.conj(); 388 | c.conj(); 389 | b.xtr_a(&a,self,&c); 390 | self.conj(); 391 | c.copy(&t); 392 | c.xtr_d(); 393 | a.xtr_d(); 394 | } else { 395 | t.copy(&a); t.conj(); 396 | a.copy(&b); 397 | a.xtr_d(); 398 | b.xtr_a(&c,self,&t); 399 | c.xtr_d(); 400 | } 401 | } 402 | if par==0 { 403 | r.copy(&c) 404 | } else {r.copy(&b)} 405 | r.reduce(); 406 | return r; 407 | } 408 | 409 | /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ 410 | pub fn xtr_pow2(&mut self,ck: &FP4,ckml: &FP4,ckm2l: &FP4,a: &mut BIG,b: &mut BIG) -> FP4 { 411 | a.norm(); b.norm(); 412 | let mut e=BIG::new_copy(a); 413 | let mut d=BIG::new_copy(b); 414 | let mut w=BIG::new(); 415 | 416 | let mut cu=FP4::new_copy(ck); // can probably be passed in w/o copying 417 | let mut cv=FP4::new_copy(self); 418 | let mut cumv=FP4::new_copy(ckml); 419 | let mut cum2v=FP4::new_copy(ckm2l); 420 | let mut r=FP4::new(); 421 | let mut t=FP4::new(); 422 | 423 | let mut f2:usize=0; 424 | while d.parity()==0 && e.parity()==0 { 425 | d.fshr(1); 426 | e.fshr(1); 427 | f2+=1; 428 | } 429 | 430 | while BIG::comp(&d,&e)!=0 { 431 | if BIG::comp(&d,&e)>0 { 432 | w.copy(&e); w.imul(4); w.norm(); 433 | if BIG::comp(&d,&w)<=0 { 434 | w.copy(&d); d.copy(&e); 435 | e.rsub(&w); e.norm(); 436 | 437 | t.copy(&cv); 438 | t.xtr_a(&cu,&cumv,&cum2v); 439 | cum2v.copy(&cumv); 440 | cum2v.conj(); 441 | cumv.copy(&cv); 442 | cv.copy(&cu); 443 | cu.copy(&t); 444 | } else { 445 | if d.parity()==0 { 446 | d.fshr(1); 447 | r.copy(&cum2v); r.conj(); 448 | t.copy(&cumv); 449 | t.xtr_a(&cu,&cv,&r); 450 | cum2v.copy(&cumv); 451 | cum2v.xtr_d(); 452 | cumv.copy(&t); 453 | cu.xtr_d(); 454 | } else { 455 | if e.parity()==1 { 456 | d.sub(&e); d.norm(); 457 | d.fshr(1); 458 | t.copy(&cv); 459 | t.xtr_a(&cu,&cumv,&cum2v); 460 | cu.xtr_d(); 461 | cum2v.copy(&cv); 462 | cum2v.xtr_d(); 463 | cum2v.conj(); 464 | cv.copy(&t); 465 | } else { 466 | w.copy(&d); 467 | d.copy(&e); d.fshr(1); 468 | e.copy(&w); 469 | t.copy(&cumv); 470 | t.xtr_d(); 471 | cumv.copy(&cum2v); cumv.conj(); 472 | cum2v.copy(&t); cum2v.conj(); 473 | t.copy(&cv); 474 | t.xtr_d(); 475 | cv.copy(&cu); 476 | cu.copy(&t); 477 | } 478 | } 479 | } 480 | } 481 | if BIG::comp(&d,&e)<0 { 482 | w.copy(&d); w.imul(4); w.norm(); 483 | if BIG::comp(&e,&w)<=0 { 484 | e.sub(&d); e.norm(); 485 | t.copy(&cv); 486 | t.xtr_a(&cu,&cumv,&cum2v); 487 | cum2v.copy(&cumv); 488 | cumv.copy(&cu); 489 | cu.copy(&t); 490 | } else { 491 | if e.parity()==0 { 492 | w.copy(&d); 493 | d.copy(&e); d.fshr(1); 494 | e.copy(&w); 495 | t.copy(&cumv); 496 | t.xtr_d(); 497 | cumv.copy(&cum2v); cumv.conj(); 498 | cum2v.copy(&t); cum2v.conj(); 499 | t.copy(&cv); 500 | t.xtr_d(); 501 | cv.copy(&cu); 502 | cu.copy(&t); 503 | } else { 504 | if d.parity()==1 { 505 | w.copy(&e); 506 | e.copy(&d); 507 | w.sub(&d); w.norm(); 508 | d.copy(&w); d.fshr(1); 509 | t.copy(&cv); 510 | t.xtr_a(&cu,&cumv,&cum2v); 511 | cumv.conj(); 512 | cum2v.copy(&cu); 513 | cum2v.xtr_d(); 514 | cum2v.conj(); 515 | cu.copy(&cv); 516 | cu.xtr_d(); 517 | cv.copy(&t); 518 | } else { 519 | d.fshr(1); 520 | r.copy(&cum2v); r.conj(); 521 | t.copy(&cumv); 522 | t.xtr_a(&cu,&cv,&r); 523 | cum2v.copy(&cumv); 524 | cum2v.xtr_d(); 525 | cumv.copy(&t); 526 | cu.xtr_d(); 527 | } 528 | } 529 | } 530 | } 531 | } 532 | r.copy(&cv); 533 | r.xtr_a(&cu,&cumv,&cum2v); 534 | for _ in 0..f2 {r.xtr_d()} 535 | r=r.xtr_pow(&mut d); 536 | return r; 537 | } 538 | 539 | 540 | /* this/=2 */ 541 | pub fn div2(&mut self) { 542 | self.a.div2(); 543 | self.b.div2(); 544 | } 545 | 546 | pub fn div_i(&mut self) { 547 | let mut u=FP2::new_copy(&self.a); 548 | let v=FP2::new_copy(&self.b); 549 | u.div_ip(); 550 | self.a.copy(&v); 551 | self.b.copy(&u); 552 | } 553 | 554 | pub fn div_2i(&mut self) { 555 | let mut u=FP2::new_copy(&self.a); 556 | let mut v=FP2::new_copy(&self.b); 557 | u.div_ip2(); 558 | v.dbl(); v.norm(); 559 | self.a.copy(&v); 560 | self.b.copy(&u); 561 | } 562 | 563 | /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */ 564 | /* returns true if this is QR */ 565 | pub fn sqrt(&mut self) -> bool { 566 | if self.iszilch() {return true;} 567 | 568 | let mut a=FP2::new_copy(&self.a); 569 | let mut s=FP2::new_copy(&self.b); 570 | let mut t=FP2::new_copy(&self.a); 571 | 572 | if s.iszilch() { 573 | if t.sqrt() { 574 | self.a.copy(&t); 575 | self.b.zero(); 576 | } else { 577 | t.div_ip(); 578 | t.sqrt(); 579 | self.b.copy(&t); 580 | self.a.zero(); 581 | } 582 | return true; 583 | } 584 | s.sqr(); 585 | a.sqr(); 586 | s.mul_ip(); 587 | s.norm(); 588 | a.sub(&s); 589 | 590 | s.copy(&a); 591 | if !s.sqrt() { 592 | return false; 593 | } 594 | 595 | a.copy(&t); a.add(&s); a.norm(); a.div2(); 596 | 597 | if !a.sqrt() { 598 | a.copy(&t); a.sub(&s); a.norm(); a.div2(); 599 | if !a.sqrt() { 600 | return false 601 | } 602 | } 603 | t.copy(&self.b); 604 | s.copy(&a); s.add(&a); 605 | s.inverse(); 606 | 607 | t.mul(&s); 608 | self.a.copy(&a); 609 | self.b.copy(&t); 610 | 611 | return true; 612 | } 613 | 614 | 615 | } 616 | /* 617 | fn main() 618 | { 619 | let mut w=FP4::new(); 620 | } 621 | */ 622 | -------------------------------------------------------------------------------- /amcl/src/bls383/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/bls383/rom.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 bls383::big::NLEN; 21 | use arch::Chunk; 22 | 23 | // Base Bits= 58 24 | pub const MODULUS:[Chunk;NLEN]=[0x2371D6485AAB0AB,0x30FCA6299214AF6,0x3801696124F47A8,0xB3CD969446B0C6,0x1FEA9284A0AD46,0x12ADBAD681B6B71,0x556556956]; 25 | pub const R2MODP:[Chunk;NLEN]=[0x80B6E0116907F4,0xCF53CF9752AC11,0x35D47189941C581,0x19D0835CB1E4D22,0x16963E90A0FC49B,0x367FB9DB3852312,0x4DFECE397]; 26 | pub const MCONST:Chunk=0x1BC0571073435FD; 27 | pub const FRA:[Chunk;NLEN]=[0x52D72D3311DAC1,0x24D203F99DCF806,0x344AE550D8C8A36,0x348FEE86A1A0959,0x2C11B52F10E4C6C,0x9FDA2F0CE2E7F0,0x22ACD5BF0]; 28 | pub const FRB:[Chunk;NLEN]=[0x1E446375298D5EA,0xC2AA22FF4452F0,0x3B684104C2BD72,0x16ACEAE2A2CA76D,0x15ECF3F939260D9,0x8B017E5B388380,0x32B880D66]; 29 | 30 | // Base Bits= 58 31 | 32 | pub const CURVE_A:isize = 0; 33 | pub const CURVE_COF_I:isize = 0; 34 | pub const CURVE_COF:[Chunk;NLEN]=[0x150556155169EAB,0x2AAB0002AAEFFED,0x555,0x0,0x0,0x0,0x0]; 35 | pub const CURVE_B_I:isize = 15; 36 | pub const CURVE_B:[Chunk;NLEN]=[0xF,0x0,0x0,0x0,0x0,0x0,0x0]; 37 | pub const CURVE_ORDER:[Chunk;NLEN]=[0x32099EBFEBC0001,0x17C25684834E5CE,0x1C81698B381DE0,0x2003002E0270110,0x1002001,0x0,0x0]; 38 | pub const CURVE_GX:[Chunk;NLEN]=[0xC4773908734573,0x176FC20FD1DC11E,0x3AD84AF1E3445C5,0x1DAC207D0B0BE1E,0x52DDB050F31D9F,0x25E7B3938E0D7D0,0x41FCBA55B]; 39 | pub const CURVE_GY:[Chunk;NLEN]=[0x12D165E8003F224,0x1F527B21FE63F48,0xA94ADEB4D2DDE5,0x319AED912441D4C,0x1C31C46D99D0DAD,0x133ECC00092BA73,0x68F16727]; 40 | 41 | pub const CURVE_BNX:[Chunk;NLEN]=[0x8000001001200,0x40,0x0,0x0,0x0,0x0,0x0]; 42 | pub const CURVE_CRU:[Chunk;NLEN]=[0xC367502EAAC2A9,0x17DA068B7D974B7,0x2F4A34DEA341BC2,0xD36F75C5738948,0x6E94874605445,0x12ADBAD28116AD1,0x556556956]; 43 | pub const CURVE_PXA:[Chunk;NLEN]=[0x3CB3B62D7F2D86,0x3F6AD9E57474F85,0x1C90F562572EE81,0x3214B55C96F51FC,0x27CB1E746432501,0x1FB00FA301E6425,0x634D2240]; 44 | pub const CURVE_PXB:[Chunk;NLEN]=[0x3D9E41EC452DE15,0x12ACA355FF9837B,0xBA88E92D5D75B5,0x3B6741732277F66,0x3288361DD24F498,0x592EBCDE9DC5,0x300D78006]; 45 | pub const CURVE_PYA:[Chunk;NLEN]=[0x68F0BB9408CB41,0x27B793C83586597,0x3ACA913A2E75B4,0x359CF266CF9A25E,0x33FE6347B6E990E,0x34894D1F2527615,0x33792CF93]; 46 | pub const CURVE_PYB:[Chunk;NLEN]=[0x2D846437F479093,0x10F2C379889218E,0x32F449F7BC98B01,0x111ACFBEA3DEBC2,0x3D15A7AE001CE0D,0xB3631AC93B9EE9,0x20E5247DD]; 47 | pub const CURVE_W:[[Chunk;NLEN];2]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]; 48 | pub const CURVE_SB:[[[Chunk;NLEN];2];2]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]; 49 | pub const CURVE_WB:[[Chunk;NLEN];4]=[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]; 50 | pub const CURVE_BB:[[[Chunk;NLEN];4];4]=[[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0]]]; 51 | 52 | pub const USE_GLV:bool = true; 53 | pub const USE_GS_G2:bool = true; 54 | pub const USE_GS_GT:bool = true; 55 | pub const GT_STRONG:bool = true; 56 | -------------------------------------------------------------------------------- /amcl/src/gcm.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 GCM_NB:usize=4; 21 | const GCM_ACCEPTING_HEADER:usize=0; 22 | const GCM_ACCEPTING_CIPHER:usize=1; 23 | const GCM_NOT_ACCEPTING_MORE:usize=2; 24 | const GCM_FINISHED:usize=3; 25 | 26 | use aes; 27 | use aes::AES; 28 | 29 | pub struct GCM { 30 | table: [[u32;4];128], 31 | statex: [u8;16], 32 | y_0: [u8;16], 33 | // counter: usize, 34 | lena:[u32;2], 35 | lenc:[u32;2], 36 | status:usize, 37 | a:AES 38 | } 39 | 40 | impl GCM { 41 | 42 | fn pack(b: [u8;4]) -> u32 { /* pack bytes into a 32-bit Word */ 43 | return ((((b[0])&0xff) as u32)<<24)|((((b[1])&0xff) as u32)<<16)|((((b[2])&0xff) as u32)<<8)|(((b[3])&0xff) as u32); 44 | } 45 | 46 | fn unpack(a: u32) -> [u8;4] { /* unpack bytes from a word */ 47 | let b:[u8;4]=[((a>>24)&0xff) as u8,((a>>16)&0xff) as u8,((a>>8)&0xff) as u8,(a&0xff) as u8]; 48 | return b; 49 | } 50 | 51 | fn precompute(&mut self,h: &[u8]) { 52 | let mut b:[u8;4]=[0;4]; 53 | let mut j=0; 54 | for i in 0..GCM_NB { 55 | b[0]=h[j]; b[1]=h[j+1]; b[2]=h[j+2]; b[3]=h[j+3]; 56 | self.table[0][i]=GCM::pack(b); 57 | j+=4; 58 | } 59 | for i in 1..128 { 60 | let mut c:u32=0; 61 | for j in 0..GCM_NB {self.table[i][j]=c|(self.table[i-1][j])>>1; c=self.table[i-1][j]<<31;} 62 | if c != 0 {self.table[i][0]^=0xE1000000} /* irreducible polynomial */ 63 | } 64 | } 65 | 66 | fn gf2mul(&mut self) { /* gf2m mul - Z=H*X mod 2^128 */ 67 | let mut p:[u32;4]=[0;4]; 68 | 69 | for i in 0..4 {p[i]=0} 70 | let mut j:usize=8; 71 | let mut m=0; 72 | for i in 0..128 { 73 | j-=1; 74 | let mut c=((self.statex[m]>>j)&1) as u32; c= (!c) +1; 75 | for k in 0..GCM_NB {p[k]^=self.table[i][k]&c} 76 | if j==0 { 77 | j=8; m+=1; 78 | if m==16 {break} 79 | } 80 | } 81 | j=0; 82 | for i in 0..GCM_NB { 83 | let b=GCM::unpack(p[i]); 84 | self.statex[j]=b[0]; self.statex[j+1]=b[1]; self.statex[j+2]=b[2]; self.statex[j+3]=b[3]; 85 | j+=4; 86 | } 87 | } 88 | 89 | fn wrap(&mut self) { /* Finish off GHASH */ 90 | let mut f:[u32;4]=[0;4]; 91 | let mut el:[u8;16]=[0;16]; 92 | 93 | /* convert lengths from bytes to bits */ 94 | f[0]=(self.lena[0]<<3)|(self.lena[1]&0xE0000000)>>29; 95 | f[1]=self.lena[1]<<3; 96 | f[2]=(self.lenc[0]<<3)|(self.lenc[1]&0xE0000000)>>29; 97 | f[3]=self.lenc[1]<<3; 98 | let mut j=0; 99 | for i in 0..GCM_NB { 100 | let b=GCM::unpack(f[i]); 101 | el[j]=b[0]; el[j+1]=b[1]; el[j+2]=b[2]; el[j+3]=b[3]; 102 | j+=4; 103 | } 104 | for i in 0..16 {self.statex[i]^=el[i]} 105 | self.gf2mul(); 106 | } 107 | 108 | fn ghash(&mut self,plain: &[u8],len: usize) -> bool { 109 | if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER} 110 | if self.status != GCM_ACCEPTING_CIPHER {return false} 111 | 112 | let mut j=0; 113 | while j=len {break} 116 | self.statex[i]^=plain[j]; j+=1; 117 | self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1} 118 | } 119 | self.gf2mul(); 120 | } 121 | if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE} 122 | return true; 123 | } 124 | 125 | /* Initialize GCM mode */ 126 | 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 */ 127 | let mut h:[u8;16]=[0;16]; 128 | 129 | for i in 0..16 {h[i]=0; self.statex[i]=0} 130 | 131 | self.a=AES::new(); 132 | 133 | self.a.init(aes::ECB,nk,key,None); 134 | self.a.ecb_encrypt(&mut h); /* E(K,0) */ 135 | self.precompute(&h); 136 | 137 | self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0; 138 | if niv==12 { 139 | for i in 0..12 {self.a.f[i]=iv[i]} 140 | let b=GCM::unpack(1); 141 | 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 */ 142 | for i in 0..16 {self.y_0[i]=self.a.f[i]} 143 | } else { 144 | self.status=GCM_ACCEPTING_CIPHER; 145 | self.ghash(iv,niv); /* GHASH(H,0,IV) */ 146 | self.wrap(); 147 | for i in 0..16 {self.a.f[i]=self.statex[i];self.y_0[i]=self.a.f[i];self.statex[i]=0} 148 | self.lena[0]=0;self.lenc[0]=0;self.lena[1]=0;self.lenc[1]=0; 149 | } 150 | self.status=GCM_ACCEPTING_HEADER; 151 | } 152 | 153 | pub fn new() -> GCM { 154 | GCM { 155 | table:[[0;4];128], 156 | statex:[0;16], 157 | y_0:[0;16], 158 | //counter:0, 159 | lena:[0;2], 160 | lenc:[0;2], 161 | status:0, 162 | a:AES::new() 163 | } 164 | } 165 | 166 | /* Add Header data - included but not encrypted */ 167 | 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 */ 168 | if self.status != GCM_ACCEPTING_HEADER {return false} 169 | let mut j=0; 170 | while j=len {break} 173 | self.statex[i]^=header[j]; j+=1; 174 | self.lena[1]+=1; if self.lena[1]==0 {self.lena[0]+=1} 175 | } 176 | self.gf2mul(); 177 | } 178 | if len%16 != 0 {self.status=GCM_ACCEPTING_CIPHER} 179 | return true; 180 | } 181 | 182 | /* Add Plaintext - included and encrypted */ 183 | pub fn add_plain(&mut self,cipher: &mut [u8],plain: &[u8],len: usize) -> bool { 184 | let mut cb:[u8;16]=[0;16]; 185 | let mut b:[u8;4]=[0;4]; 186 | 187 | let mut counter: u32; 188 | if self.status == GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER} 189 | if self.status != GCM_ACCEPTING_CIPHER {return false} 190 | 191 | let mut j=0; 192 | while j=len {break} 203 | cipher[j]=plain[j]^cb[i]; 204 | self.statex[i]^=cipher[j]; j+=1; 205 | self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1} 206 | } 207 | self.gf2mul() 208 | } 209 | if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE} 210 | return true; 211 | } 212 | 213 | /* Add Ciphertext - decrypts to plaintext */ 214 | pub fn add_cipher(&mut self,plain: &mut [u8],cipher: &[u8],len: usize) -> bool { 215 | let mut cb:[u8;16]=[0;16]; 216 | let mut b:[u8;4]=[0;4]; 217 | 218 | let mut counter: u32; 219 | 220 | if self.status==GCM_ACCEPTING_HEADER {self.status=GCM_ACCEPTING_CIPHER} 221 | if self.status != GCM_ACCEPTING_CIPHER {return false} 222 | 223 | let mut j=0; 224 | while j=len {break} 234 | let oc=cipher[j]; 235 | plain[j]=cipher[j]^cb[i]; 236 | self.statex[i]^=oc; j+=1; 237 | self.lenc[1]+=1; if self.lenc[1]==0 {self.lenc[0]+=1} 238 | } 239 | self.gf2mul() 240 | } 241 | if len%16 != 0 {self.status=GCM_NOT_ACCEPTING_MORE} 242 | return true; 243 | } 244 | 245 | /* Finish and extract Tag */ 246 | pub fn finish(&mut self,extract: bool) -> [u8;16] { /* Finish off GHASH and extract tag (MAC) */ 247 | let mut tag:[u8;16]=[0;16]; 248 | 249 | self.wrap(); 250 | /* extract tag */ 251 | if extract { 252 | self.a.ecb_encrypt(&mut (self.y_0)); /* E(K,Y0) */ 253 | for i in 0..16 {self.y_0[i]^=self.statex[i]} 254 | for i in 0..16 {tag[i]=self.y_0[i];self.y_0[i]=0;self.statex[i]=0} 255 | } 256 | self.status=GCM_FINISHED; 257 | self.a.end(); 258 | return tag; 259 | } 260 | 261 | pub fn hex2bytes(hex: &[u8],bin: &mut [u8]) { 262 | let len=hex.len(); 263 | 264 | for i in 0..len/2 { 265 | let mut v:u8; 266 | let mut c = hex[2*i]; 267 | if c >= b'0' && c <= b'9' { 268 | v = c - b'0'; 269 | } else if c >= b'A' && c <= b'F' { 270 | v = c - b'A' + 10; 271 | } else if c >= b'a' && c <= b'f' { 272 | v = c - b'a' + 10; 273 | } else { 274 | v = 0; 275 | } 276 | v <<= 4; 277 | c = hex[2*i + 1]; 278 | if c >= b'0' && c <= b'9' { 279 | v += c - b'0'; 280 | } else if c >= b'A' && c <= b'F' { 281 | v += c - b'A' + 10; 282 | } else if c >= b'a' && c <= b'f' { 283 | v += c - b'a' + 10; 284 | } else { 285 | v = 0; 286 | } 287 | bin[i] = v; 288 | } 289 | } 290 | 291 | } 292 | /* 293 | fn main() 294 | { 295 | let kt=b"feffe9928665731c6d6a8f9467308308"; 296 | let mt=b"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"; 297 | let ht=b"feedfacedeadbeeffeedfacedeadbeefabaddad2"; 298 | let nt=b"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b"; 299 | // Tag should be 619cc5aefffe0bfa462af43c1699d050 300 | 301 | let mut gcm=GCM::new(); 302 | 303 | let len=mt.len()/2; 304 | let lenh=ht.len()/2; 305 | let lenk=kt.len()/2; 306 | let leniv=nt.len()/2; 307 | 308 | //let mut t:[u8;16]=[0;16]; // Tag 309 | let mut k:[u8;16]=[0;16]; // AES Key 310 | let mut h:[u8;64]=[0;64]; // Header - to be included in Authentication, but not encrypted 311 | let mut n:[u8;100]=[0;100]; // IV - Initialisation vector 312 | let mut m:[u8;100]=[0;100]; // Plaintext to be encrypted/authenticated 313 | let mut c:[u8;100]=[0;100]; // Ciphertext 314 | let mut p:[u8;100]=[0;100]; // Recovered Plaintext 315 | 316 | GCM::hex2bytes(mt,&mut m); 317 | GCM::hex2bytes(ht,&mut h); 318 | GCM::hex2bytes(kt,&mut k); 319 | GCM::hex2bytes(nt,&mut n); 320 | 321 | println!("Plaintext="); 322 | for i in 0..len {print!("{:02x}",m[i])} 323 | println!(""); 324 | 325 | gcm.init(lenk,&k,leniv,&n); 326 | 327 | gcm.add_header(&h,lenh); 328 | gcm.add_plain(&mut c,&m,len); 329 | let mut t=gcm.finish(true); 330 | 331 | println!("Ciphertext="); 332 | for i in 0..len {print!("{:02x}",c[i])} 333 | println!(""); 334 | 335 | println!("Tag="); 336 | for i in 0..16 {print!("{:02x}",t[i])} 337 | println!(""); 338 | 339 | gcm.init(lenk,&k,leniv,&n); 340 | 341 | gcm.add_header(&h,lenh); 342 | gcm.add_cipher(&mut p,&c,len); 343 | t=gcm.finish(true); 344 | 345 | println!("Plaintext="); 346 | for i in 0..len {print!("{:02x}",p[i])} 347 | println!(""); 348 | 349 | println!("Tag="); 350 | for i in 0..16 {print!("{:02x}",t[i])} 351 | println!(""); 352 | 353 | } 354 | */ 355 | -------------------------------------------------------------------------------- /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 | #![cfg_attr( 2 | not(feature = "std"), 3 | no_std, 4 | feature(alloc), 5 | feature(alloc_prelude), 6 | feature(prelude_import) 7 | )] 8 | 9 | #[cfg(not(feature = "std"))] 10 | extern crate alloc; 11 | 12 | #[cfg(not(feature = "std"))] 13 | pub(crate) mod prelude { 14 | pub use alloc::prelude::v1::*; 15 | pub use core::prelude::v1::*; 16 | } 17 | 18 | #[cfg(not(feature = "std"))] 19 | #[allow(unused)] 20 | #[prelude_import] 21 | use crate::prelude::*; 22 | 23 | #[rustfmt::skip] 24 | pub mod aes; 25 | #[rustfmt::skip] 26 | pub mod arch; 27 | #[rustfmt::skip] 28 | pub mod gcm; 29 | #[rustfmt::skip] 30 | pub mod hash256; 31 | #[rustfmt::skip] 32 | pub mod hash384; 33 | #[rustfmt::skip] 34 | pub mod hash512; 35 | #[rustfmt::skip] 36 | pub mod nhs; 37 | #[rustfmt::skip] 38 | pub mod rand; 39 | #[rustfmt::skip] 40 | pub mod sha3; 41 | 42 | #[rustfmt::skip] 43 | pub mod bls381; 44 | #[rustfmt::skip] 45 | pub mod bls383; 46 | #[rustfmt::skip] 47 | pub mod secp256k1; 48 | -------------------------------------------------------------------------------- /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/secp256k1/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 secp256k1::big; 22 | use secp256k1::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 | #[cfg(feature = "std")] 252 | /* Convert to Hex String */ 253 | pub fn to_string(&mut self) -> String { 254 | let mut s = String::new(); 255 | let mut len=self.nbits(); 256 | 257 | if len%4==0 { 258 | len/=4; 259 | } else { 260 | len/=4; 261 | len+=1; 262 | } 263 | 264 | for i in (0 ..len).rev() { 265 | let mut b=DBIG::new_copy(&self); 266 | b.shr(i*4); 267 | s=s + &format!("{:X}", b.w[0]&15); 268 | } 269 | return s; 270 | } 271 | 272 | } 273 | -------------------------------------------------------------------------------- /amcl/src/secp256k1/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 secp256k1::big; 21 | use secp256k1::big::BIG; 22 | use secp256k1::dbig::DBIG; 23 | use secp256k1::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 = 256; /* Number of bits in Modulus */ 41 | pub const MOD8: usize = 7; /* Modulus mod 8 */ 42 | pub const MODTYPE:usize=NOT_SPECIAL; 43 | 44 | pub const FEXCESS:i32 = ((1 as i32)<<24); 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 | #[cfg(feature = "std")] 180 | /* convert to string */ 181 | pub fn tostring(&mut self) -> String { 182 | let s=self.redc().tostring(); 183 | return s; 184 | } 185 | 186 | /* reduce this mod Modulus */ 187 | pub fn reduce(&mut self) { 188 | let p = BIG::new_ints(&rom::MODULUS); 189 | self.x.rmod(&p); 190 | self.xes=1; 191 | } 192 | 193 | /* test this=0? */ 194 | pub fn iszilch(&mut self) -> bool { 195 | self.reduce(); 196 | return self.x.iszilch(); 197 | } 198 | 199 | /* copy from FP b */ 200 | pub fn copy(&mut self,b: &FP) { 201 | self.x.copy(&(b.x)); 202 | self.xes=b.xes; 203 | } 204 | 205 | /* copy from BIG b */ 206 | pub fn bcopy(&mut self,b: &BIG) { 207 | self.x.copy(&b); 208 | self.nres(); 209 | } 210 | 211 | /* set this=0 */ 212 | pub fn zero(&mut self) { 213 | self.x.zero(); 214 | self.xes=1; 215 | } 216 | 217 | /* set this=1 */ 218 | pub fn one(&mut self) { 219 | self.x.one(); self.nres() 220 | } 221 | 222 | /* normalise this */ 223 | pub fn norm(&mut self) { 224 | self.x.norm(); 225 | } 226 | /* swap FPs depending on d */ 227 | pub fn cswap(&mut self,b: &mut FP,d: isize) { 228 | self.x.cswap(&mut (b.x),d); 229 | let mut c=d as i32; 230 | c=!(c-1); 231 | let t=c&(self.xes^b.xes); 232 | self.xes^=t; 233 | b.xes^=t; 234 | } 235 | 236 | /* copy FPs depending on d */ 237 | pub fn cmove(&mut self,b: &FP,d: isize) { 238 | self.x.cmove(&(b.x),d); 239 | let c=d as i32; 240 | self.xes^=(self.xes^b.xes)&(-c); 241 | } 242 | 243 | /* this*=b mod Modulus */ 244 | pub fn mul(&mut self,b: &FP) 245 | { 246 | if (self.xes as i64)*(b.xes as i64) > FEXCESS as i64 {self.reduce()} 247 | 248 | let mut d=BIG::mul(&(self.x),&(b.x)); 249 | self.x.copy(&FP::modulo(&mut d)); 250 | self.xes=2; 251 | } 252 | 253 | fn logb2(w: u32) -> usize { 254 | let mut v=w; 255 | v |= v >> 1; 256 | v |= v >> 2; 257 | v |= v >> 4; 258 | v |= v >> 8; 259 | v |= v >> 16; 260 | 261 | v = v - ((v >> 1) & 0x55555555); 262 | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 263 | let r= (( ((v + (v >> 4)) & 0xF0F0F0F).wrapping_mul(0x1010101)) >> 24) as usize; 264 | return r; 265 | } 266 | 267 | /* this = -this mod Modulus */ 268 | pub fn neg(&mut self) { 269 | let mut p = BIG::new_ints(&rom::MODULUS); 270 | let sb=FP::logb2((self.xes-1) as u32); 271 | 272 | p.fshl(sb); 273 | self.x.rsub(&p); 274 | self.xes=1<<(sb as i32); 275 | if self.xes>FEXCESS {self.reduce()} 276 | 277 | } 278 | 279 | /* this*=c mod Modulus, where c is a small int */ 280 | pub fn imul(&mut self,c: isize) { 281 | let mut cc=c; 282 | // self.norm(); 283 | let mut s=false; 284 | if cc<0 { 285 | cc = -cc; 286 | s=true; 287 | } 288 | 289 | if MODTYPE==PSEUDO_MERSENNE || MODTYPE==GENERALISED_MERSENNE { 290 | let mut d=self.x.pxmul(cc); 291 | self.x.copy(&FP::modulo(&mut d)); 292 | self.xes=2 293 | } else { 294 | if self.xes*(cc as i32) <= FEXCESS { 295 | self.x.pmul(cc); 296 | self.xes*=cc as i32; 297 | } else { 298 | let n=FP::new_int(cc); 299 | self.mul(&n); 300 | } 301 | 302 | } 303 | 304 | if s {self.neg(); self.norm();} 305 | } 306 | 307 | /* self*=self mod Modulus */ 308 | pub fn sqr(&mut self) { 309 | // self.norm(); 310 | if (self.xes as i64)*(self.xes as i64) > FEXCESS as i64 {self.reduce()} 311 | 312 | 313 | let mut d=BIG::sqr(&(self.x)); 314 | self.x.copy(&FP::modulo(&mut d)); 315 | self.xes=2 316 | } 317 | 318 | /* self+=b */ 319 | pub fn add(&mut self,b: &FP) { 320 | self.x.add(&(b.x)); 321 | self.xes+=b.xes; 322 | if self.xes>FEXCESS {self.reduce()} 323 | } 324 | 325 | /* self+=self */ 326 | pub fn dbl(&mut self) { 327 | self.x.dbl(); 328 | self.xes+=self.xes; 329 | if self.xes>FEXCESS {self.reduce()} 330 | } 331 | 332 | /* self-=b */ 333 | pub fn sub(&mut self,b: &FP) 334 | { 335 | let mut n=FP::new_copy(b); 336 | n.neg(); 337 | self.add(&n); 338 | } 339 | 340 | /* self=b-self */ 341 | pub fn rsub(&mut self,b: &FP) 342 | { 343 | self.neg(); 344 | self.add(&b); 345 | } 346 | 347 | /* self/=2 mod Modulus */ 348 | pub fn div2(&mut self) { 349 | // self.x.norm(); 350 | if self.x.parity()==0 { 351 | self.x.fshr(1); 352 | } else { 353 | let p = BIG::new_ints(&rom::MODULUS); 354 | self.x.add(&p); 355 | self.x.norm(); 356 | self.x.fshr(1); 357 | } 358 | } 359 | /* self=1/self mod Modulus */ 360 | pub fn inverse(&mut self) { 361 | /* 362 | let mut p = BIG::new_ints(&rom::MODULUS); 363 | let mut r=self.redc(); 364 | r.invmodp(&mut p); 365 | self.x.copy(&r); 366 | self.nres(); 367 | */ 368 | let mut m2 = BIG::new_ints(&rom::MODULUS); 369 | m2.dec(2); m2.norm(); 370 | let inv=self.pow(&mut m2); 371 | self.copy(&inv); 372 | } 373 | 374 | /* return TRUE if self==a */ 375 | pub fn equals(&mut self,a: &mut FP) -> bool { 376 | a.reduce(); 377 | self.reduce(); 378 | if BIG::comp(&(a.x),&self.x)==0 {return true} 379 | return false; 380 | } 381 | 382 | 383 | /* return self^e mod Modulus */ 384 | pub fn pow(&mut self,e: &mut BIG) -> FP { 385 | 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()]; 386 | const CT:usize=1+(big::NLEN*(big::BASEBITS as usize)+3)/4; 387 | let mut w:[i8;CT]=[0;CT]; 388 | 389 | self.norm(); 390 | let mut t=BIG::new_copy(e); 391 | t.norm(); 392 | let nb=1+(t.nbits()+3)/4; 393 | 394 | for i in 0..nb { 395 | let lsbs=t.lastbits(4); 396 | t.dec(lsbs); 397 | t.norm(); 398 | w[i]=lsbs as i8; 399 | t.fshr(4); 400 | } 401 | tb[0].one(); 402 | tb[1].copy(&self); 403 | 404 | let mut c=FP::new(); 405 | for i in 2..16 { 406 | c.copy(&tb[i-1]); 407 | tb[i].copy(&c); 408 | tb[i].mul(&self); 409 | } 410 | let mut r=FP::new_copy(&tb[w[nb-1] as usize]); 411 | for i in (0..nb-1).rev() { 412 | r.sqr(); 413 | r.sqr(); 414 | r.sqr(); 415 | r.sqr(); 416 | r.mul(&tb[w[i] as usize]) 417 | } 418 | r.reduce(); 419 | return r; 420 | } 421 | 422 | /* return self^e mod Modulus 423 | pub fn pow(&mut self,e: &mut BIG) -> FP { 424 | let p = BIG::new_ints(&rom::MODULUS); 425 | let mut r=FP::new_int(1); 426 | e.norm(); 427 | self.x.norm(); 428 | let mut m=FP::new_copy(self); 429 | loop { 430 | let bt=e.parity(); 431 | e.fshr(1); 432 | if bt==1 {r.mul(&m)} 433 | if e.iszilch() {break} 434 | m.sqr(); 435 | } 436 | r.x.rmod(&p); 437 | return r; 438 | } */ 439 | 440 | /* return sqrt(this) mod Modulus */ 441 | pub fn sqrt(&mut self) -> FP { 442 | self.reduce(); 443 | let mut p = BIG::new_ints(&rom::MODULUS); 444 | if MOD8==5 { 445 | p.dec(5); p.norm(); p.shr(3); 446 | let mut i=FP::new_copy(self); i.x.shl(1); 447 | let v=i.pow(&mut p); 448 | i.mul(&v); i.mul(&v); 449 | i.x.dec(1); 450 | let mut r=FP::new_copy(self); 451 | r.mul(&v); r.mul(&i); 452 | r.reduce(); 453 | return r; 454 | } 455 | else 456 | { 457 | p.inc(1); p.norm(); p.shr(2); 458 | return self.pow(&mut p); 459 | } 460 | } 461 | /* return jacobi symbol (this/Modulus) */ 462 | pub fn jacobi(&mut self) -> isize 463 | { 464 | let mut p = BIG::new_ints(&rom::MODULUS); 465 | let mut w=self.redc(); 466 | return w.jacobi(&mut p); 467 | } 468 | 469 | } 470 | /* 471 | fn main() { 472 | let p = BIG::new_ints(&rom::MODULUS); 473 | let mut e = BIG::new_copy(&p); 474 | e.dec(1); 475 | 476 | let mut x = FP::new_int(3); 477 | let mut s=x.pow(&mut e); 478 | 479 | println!("s= {}",s.tostring()); 480 | } 481 | */ 482 | -------------------------------------------------------------------------------- /amcl/src/secp256k1/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod big; 2 | pub mod dbig; 3 | pub mod fp; 4 | pub mod ecp; 5 | pub mod ecdh; 6 | pub mod rom; 7 | 8 | 9 | -------------------------------------------------------------------------------- /amcl/src/secp256k1/rom.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 | /* Fixed Data in ROM - Field and Curve parameters */ 21 | 22 | use secp256k1::big::NLEN; 23 | use arch::Chunk; 24 | 25 | // Base Bits= 56 26 | // secp256k1 modulus 27 | pub const MODULUS:[Chunk;NLEN]=[0xFFFFFEFFFFFC2F,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFFFFFFFF,0xFFFFFFFF]; 28 | pub const R2MODP:[Chunk;NLEN]=[0xA1000000000000,0x7A2000E90,0x1,0x0,0x0]; 29 | pub const MCONST:Chunk=0x38091DD2253531; 30 | 31 | // secp256k1 curve 32 | pub const CURVE_A:isize = 0; 33 | pub const CURVE_COF_I:isize = 1; 34 | pub const CURVE_COF:[Chunk;NLEN]=[0x1,0x0,0x0,0x0,0x0]; 35 | pub const CURVE_B_I:isize = 7; 36 | pub const CURVE_B:[Chunk;NLEN]=[0x7,0x0,0x0,0x0,0x0]; 37 | pub const CURVE_ORDER:[Chunk;NLEN]=[0xD25E8CD0364141,0xDCE6AF48A03BBF,0xFFFFFFFFFEBAAE,0xFFFFFFFFFFFFFF,0xFFFFFFFF]; 38 | pub const CURVE_GX:[Chunk;NLEN]=[0xF2815B16F81798,0xFCDB2DCE28D959,0x95CE870B07029B,0xF9DCBBAC55A062,0x79BE667E]; 39 | pub const CURVE_GY:[Chunk;NLEN]=[0x47D08FFB10D4B8,0xB448A68554199C,0xFC0E1108A8FD17,0x26A3C4655DA4FB,0x483ADA77]; 40 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /benches/bls381_benches.rs: -------------------------------------------------------------------------------- 1 | extern crate amcl; 2 | extern crate bls_aggregates; 3 | extern crate criterion; 4 | extern crate hex; 5 | extern crate rand; 6 | 7 | use self::amcl::bls381 as BLSCurve; 8 | use bls_aggregates::*; 9 | use criterion::{black_box, criterion_group, criterion_main, Benchmark, Criterion}; 10 | use BLSCurve::big::BIG; 11 | use BLSCurve::ecp::ECP; 12 | 13 | pub type BigNum = BIG; 14 | pub type GroupG1 = ECP; 15 | 16 | fn compression_signature(c: &mut Criterion) { 17 | let compressed_g2 = hex::decode("a666d31d7e6561371644eb9ca7dbcb87257d8fd84a09e38a7a491ce0bbac64a324aa26385aebc99f47432970399a2ecb0def2d4be359640e6dae6438119cbdc4f18e5e4496c68a979473a72b72d3badf98464412e9d8f8d2ea9b31953bb24899").unwrap(); 18 | let mut signature = Signature::from_bytes(&compressed_g2).unwrap(); 19 | 20 | c.bench( 21 | "compression", 22 | Benchmark::new("Decompress a Signature", move |b| { 23 | b.iter(|| { 24 | black_box(Signature::from_bytes(&compressed_g2).unwrap()); 25 | }) 26 | }) 27 | .sample_size(100), 28 | ); 29 | 30 | c.bench( 31 | "compression", 32 | Benchmark::new("Compress a Signature", move |b| { 33 | b.iter(|| { 34 | black_box(Signature::as_bytes(&mut signature)); 35 | }) 36 | }) 37 | .sample_size(10), 38 | ); 39 | } 40 | 41 | fn compression_public_key(c: &mut Criterion) { 42 | let compressed_g1 = hex::decode("a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a").unwrap(); 43 | let mut public_key = PublicKey::from_bytes(&compressed_g1).unwrap(); 44 | 45 | c.bench( 46 | "compression", 47 | Benchmark::new("Decompress a PublicKey", move |b| { 48 | b.iter(|| { 49 | black_box(PublicKey::from_bytes(&compressed_g1).unwrap()); 50 | }) 51 | }) 52 | .sample_size(100), 53 | ); 54 | 55 | c.bench( 56 | "compression", 57 | Benchmark::new("Compress a PublicKey", move |b| { 58 | b.iter(|| { 59 | black_box(PublicKey::as_bytes(&mut public_key)); 60 | }) 61 | }) 62 | .sample_size(10), 63 | ); 64 | } 65 | 66 | fn compression_public_key_bigs(c: &mut Criterion) { 67 | let compressed_g1 = hex::decode("a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a").unwrap(); 68 | let mut public_key = PublicKey::from_bytes(&compressed_g1).unwrap(); 69 | let uncompressed_bytes = public_key.as_uncompressed_bytes(); 70 | 71 | c.bench( 72 | "compression", 73 | Benchmark::new("Decompress a PublicKey from Bigs", move |b| { 74 | b.iter(|| { 75 | black_box(PublicKey::from_uncompressed_bytes(&uncompressed_bytes)).unwrap(); 76 | }) 77 | }) 78 | .sample_size(100), 79 | ); 80 | 81 | c.bench( 82 | "compression", 83 | Benchmark::new("Compress a PublicKey to Bigs", move |b| { 84 | b.iter(|| { 85 | black_box(public_key.as_uncompressed_bytes()); 86 | }) 87 | }) 88 | .sample_size(10), 89 | ); 90 | } 91 | 92 | fn signing(c: &mut Criterion) { 93 | let keypair = Keypair::random(&mut rand::thread_rng()); 94 | let sk = keypair.sk; 95 | let pk = keypair.pk; 96 | 97 | let msg = "Some msg"; 98 | let domain = 42; 99 | let sig = Signature::new(&msg.as_bytes(), domain, &sk); 100 | 101 | c.bench( 102 | "signing", 103 | Benchmark::new("Create a Signature", move |b| { 104 | b.iter(|| { 105 | black_box(Signature::new(&msg.as_bytes(), domain, &sk)); 106 | }) 107 | }) 108 | .sample_size(10), 109 | ); 110 | 111 | c.bench( 112 | "signing", 113 | Benchmark::new("Verify a Signature", move |b| { 114 | b.iter(|| { 115 | black_box(sig.verify(&msg.as_bytes(), domain, &pk)); 116 | }) 117 | }) 118 | .sample_size(10), 119 | ); 120 | } 121 | 122 | fn aggregation(c: &mut Criterion) { 123 | let keypair = Keypair::random(&mut rand::thread_rng()); 124 | let sk = keypair.sk; 125 | let pk = keypair.pk; 126 | 127 | let msg = "Some msg"; 128 | let domain = 42; 129 | let sig = Signature::new(&msg.as_bytes(), domain, &sk); 130 | 131 | let mut aggregate_publickey = AggregatePublicKey::new(); 132 | aggregate_publickey.add(&pk); 133 | 134 | let mut aggregate_signature = AggregateSignature::new(); 135 | aggregate_signature.add(&sig); 136 | 137 | c.bench( 138 | "aggregation", 139 | Benchmark::new("Aggregate a PublicKey", move |b| { 140 | b.iter(|| { 141 | black_box(aggregate_publickey.add(&pk)); 142 | }) 143 | }) 144 | .sample_size(100), 145 | ); 146 | 147 | c.bench( 148 | "aggregation", 149 | Benchmark::new("Aggregate a Signature", move |b| { 150 | b.iter(|| { 151 | black_box(aggregate_signature.add(&sig)); 152 | }) 153 | }) 154 | .sample_size(100), 155 | ); 156 | } 157 | 158 | fn aggregate_verfication(c: &mut Criterion) { 159 | let n = 128; 160 | 161 | let mut pubkeys = vec![]; 162 | let mut agg_sig = AggregateSignature::new(); 163 | let msg = b"signed message"; 164 | let domain = 0; 165 | 166 | for _ in 0..n { 167 | let keypair = Keypair::random(&mut rand::thread_rng()); 168 | let sig = Signature::new(&msg[..], domain, &keypair.sk); 169 | agg_sig.add(&sig); 170 | pubkeys.push(keypair.pk); 171 | } 172 | 173 | assert_eq!(pubkeys.len(), n); 174 | 175 | c.bench( 176 | "aggregation", 177 | Benchmark::new("Verifying aggregate of 128 signatures", move |b| { 178 | b.iter(|| { 179 | let pubkeys_as_ref: Vec<&PublicKey> = pubkeys.iter().collect(); 180 | let agg_pub = AggregatePublicKey::from_public_keys(pubkeys_as_ref.as_slice()); 181 | let verified = agg_sig.verify(&msg[..], domain, &agg_pub); 182 | assert!(verified); 183 | }) 184 | }) 185 | .sample_size(100), 186 | ); 187 | } 188 | 189 | fn aggregate_verfication_multiple_messages(c: &mut Criterion) { 190 | let n = 128; 191 | 192 | let mut pubkeys = vec![]; 193 | let mut agg_sig = AggregateSignature::new(); 194 | 195 | let mut msgs = vec![vec![0; 32], vec![1; 32]]; 196 | 197 | let domain = 0; 198 | 199 | for i in 0..n { 200 | let keypair = Keypair::random(&mut rand::thread_rng()); 201 | 202 | let msg = &msgs[i / (n / msgs.len())]; 203 | 204 | let sig = Signature::new(&msg[..], domain, &keypair.sk); 205 | agg_sig.add(&sig); 206 | 207 | pubkeys.push(keypair.pk); 208 | } 209 | 210 | let mut agg_msg = vec![]; 211 | agg_msg.append(&mut msgs[0].to_vec()); 212 | agg_msg.append(&mut msgs[1].to_vec()); 213 | 214 | assert_eq!(pubkeys.len(), n as usize); 215 | assert_eq!(agg_msg.len(), 2 * 32); 216 | 217 | c.bench( 218 | "aggregation", 219 | Benchmark::new( 220 | "Verifying aggregate of 128 signatures with two distinct messages", 221 | move |b| { 222 | b.iter(|| { 223 | let mut agg_pubs = vec![AggregatePublicKey::new(); 2]; 224 | 225 | for i in 0..n { 226 | agg_pubs[i / (n / msgs.len())].add(&pubkeys[i]); 227 | } 228 | let agg_pubs_refs: Vec<&AggregatePublicKey> = agg_pubs.iter().collect(); 229 | let verified = 230 | agg_sig.verify_multiple(&agg_msg[..], domain, agg_pubs_refs.as_slice()); 231 | 232 | assert!(verified); 233 | }) 234 | }, 235 | ) 236 | .sample_size(100), 237 | ); 238 | } 239 | 240 | fn key_generation(c: &mut Criterion) { 241 | c.bench( 242 | "key generation", 243 | Benchmark::new("Generate random keypair", move |b| { 244 | b.iter(|| { 245 | black_box(Keypair::random(&mut rand::thread_rng())); 246 | }) 247 | }), 248 | ); 249 | 250 | c.bench( 251 | "key generation", 252 | Benchmark::new("Generate keypair from known string", move |b| { 253 | b.iter(|| { 254 | let secret = vec![42; 48]; 255 | let sk = SecretKey::from_bytes(&secret).unwrap(); 256 | let pk = PublicKey::from_secret_key(&sk); 257 | let keypair = Keypair { sk, pk }; 258 | black_box(keypair); 259 | }) 260 | }), 261 | ); 262 | } 263 | 264 | criterion_group!( 265 | benches, 266 | compression_signature, 267 | compression_public_key, 268 | compression_public_key_bigs, 269 | signing, 270 | aggregation, 271 | aggregate_verfication, 272 | aggregate_verfication_multiple_messages, 273 | key_generation 274 | ); 275 | criterion_main!(benches); 276 | -------------------------------------------------------------------------------- /src/errors.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq, Clone)] 2 | pub enum DecodeError { 3 | BadPoint, 4 | IncorrectSize, 5 | Infinity, 6 | InvalidCFlag, 7 | } 8 | -------------------------------------------------------------------------------- /src/g1.rs: -------------------------------------------------------------------------------- 1 | use super::amcl_utils::{compress_g1, decompress_g1, BigNum, GroupG1}; 2 | use super::errors::DecodeError; 3 | #[cfg(feature = "std")] 4 | use std::fmt; 5 | 6 | pub struct G1Point { 7 | point: GroupG1, 8 | } 9 | 10 | impl G1Point { 11 | pub fn new() -> Self { 12 | Self { 13 | point: GroupG1::new(), 14 | } 15 | } 16 | 17 | pub fn from_raw(point: GroupG1) -> Self { 18 | Self { point } 19 | } 20 | 21 | pub fn add(&mut self, point: &G1Point) { 22 | self.point.add(&point.point); 23 | } 24 | 25 | pub fn affine(&mut self) { 26 | self.point.affine(); 27 | } 28 | 29 | pub fn is_infinity(&self) -> bool { 30 | self.point.is_infinity() 31 | } 32 | 33 | pub fn inf(&mut self) { 34 | self.point.inf() 35 | } 36 | 37 | pub fn as_raw(&self) -> &GroupG1 { 38 | &self.point 39 | } 40 | 41 | pub fn getx(&mut self) -> BigNum { 42 | self.point.getx() 43 | } 44 | 45 | pub fn gety(&mut self) -> BigNum { 46 | self.point.gety() 47 | } 48 | 49 | /// Instatiate the G1 point from compressed bytes. 50 | pub fn from_bytes(bytes: &[u8]) -> Result { 51 | let pt = decompress_g1(&bytes)?; 52 | Ok(Self { point: pt }) 53 | } 54 | 55 | /// Export (serialize) the G1 point to compressed bytes. 56 | pub fn as_bytes(&mut self) -> Vec { 57 | compress_g1(&mut self.point) 58 | } 59 | } 60 | 61 | #[cfg(feature = "std")] 62 | impl fmt::Debug for G1Point { 63 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 64 | let mut temp = GroupG1::new(); 65 | temp.copy(&self.point); 66 | write!(f, "{}", temp.tostring()) 67 | } 68 | } 69 | 70 | impl Clone for G1Point { 71 | fn clone(&self) -> Self { 72 | let mut temp_s = GroupG1::new(); 73 | temp_s.copy(self.as_raw()); 74 | Self { point: temp_s } 75 | } 76 | } 77 | 78 | impl PartialEq for G1Point { 79 | fn eq(&self, other: &G1Point) -> bool { 80 | let mut clone_a = self.clone(); 81 | let mut clone_b = other.clone(); 82 | 83 | clone_a.point.equals(&mut clone_b.point) 84 | } 85 | } 86 | 87 | impl Eq for G1Point {} 88 | 89 | impl Default for G1Point { 90 | fn default() -> Self { 91 | Self::new() 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/g2.rs: -------------------------------------------------------------------------------- 1 | use super::amcl_utils::{compress_g2, decompress_g2, GroupG2}; 2 | use super::errors::DecodeError; 3 | #[cfg(feature = "std")] 4 | use std::fmt; 5 | 6 | pub struct G2Point { 7 | point: GroupG2, 8 | } 9 | 10 | impl G2Point { 11 | pub fn new() -> Self { 12 | Self { 13 | point: GroupG2::new(), 14 | } 15 | } 16 | 17 | pub fn from_raw(point: GroupG2) -> Self { 18 | Self { point } 19 | } 20 | 21 | pub fn add(&mut self, point: &G2Point) { 22 | self.point.add(&point.point); 23 | } 24 | 25 | pub fn affine(&mut self) { 26 | self.point.affine(); 27 | } 28 | 29 | pub fn is_infinity(&self) -> bool { 30 | self.point.is_infinity() 31 | } 32 | 33 | pub fn inf(&mut self) { 34 | self.point.inf() 35 | } 36 | 37 | pub fn as_raw(&self) -> &GroupG2 { 38 | &self.point 39 | } 40 | 41 | /// Instatiate the point from compressed bytes. 42 | pub fn from_bytes(bytes: &[u8]) -> Result { 43 | let pt = decompress_g2(&bytes)?; 44 | Ok(Self { point: pt }) 45 | } 46 | 47 | /// Export (serialize) the point to compressed bytes. 48 | pub fn as_bytes(&mut self) -> Vec { 49 | compress_g2(&mut self.point) 50 | } 51 | } 52 | 53 | #[cfg(feature = "std")] 54 | impl fmt::Debug for G2Point { 55 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 56 | let mut temp = GroupG2::new(); 57 | temp.copy(&self.point); 58 | write!(f, "{}", temp.tostring()) 59 | } 60 | } 61 | 62 | impl Clone for G2Point { 63 | fn clone(&self) -> Self { 64 | let mut temp_s = GroupG2::new(); 65 | temp_s.copy(self.as_raw()); 66 | Self { point: temp_s } 67 | } 68 | } 69 | 70 | impl PartialEq for G2Point { 71 | fn eq(&self, other: &G2Point) -> bool { 72 | let mut clone_a = self.clone(); 73 | let mut clone_b = other.clone(); 74 | 75 | clone_a.point.equals(&mut clone_b.point) 76 | } 77 | } 78 | 79 | impl Eq for G2Point {} 80 | 81 | impl Default for G2Point { 82 | fn default() -> Self { 83 | Self::new() 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/keys.rs: -------------------------------------------------------------------------------- 1 | extern crate amcl; 2 | extern crate rand; 3 | 4 | use super::amcl_utils::{self, BigNum, GroupG1, CURVE_ORDER, MOD_BYTE_SIZE}; 5 | use super::errors::DecodeError; 6 | use super::g1::G1Point; 7 | use super::rng::get_seeded_rng; 8 | use rand::Rng; 9 | #[cfg(feature = "std")] 10 | use std::fmt; 11 | 12 | #[derive(Clone)] 13 | /// A BLS secret key. 14 | pub struct SecretKey { 15 | pub x: BigNum, 16 | } 17 | 18 | impl SecretKey { 19 | /// Generate a new SecretKey using an Rng to seed the `amcl::rand::RAND` PRNG. 20 | pub fn random(rng: &mut R) -> Self { 21 | let mut r = get_seeded_rng(rng, 256); 22 | let x = BigNum::randomnum(&BigNum::new_ints(&CURVE_ORDER), &mut r); 23 | SecretKey { x } 24 | } 25 | 26 | /// Instantiate a SecretKey from existing bytes. 27 | pub fn from_bytes(bytes: &[u8]) -> Result { 28 | if bytes.len() != MOD_BYTE_SIZE { 29 | return Err(DecodeError::IncorrectSize); 30 | } 31 | Ok(SecretKey { 32 | x: BigNum::frombytes(bytes), 33 | }) 34 | } 35 | 36 | /// Export the SecretKey to bytes. 37 | pub fn as_bytes(&self) -> Vec { 38 | let mut temp = BigNum::new_copy(&self.x); 39 | let mut bytes: [u8; MOD_BYTE_SIZE] = [0; MOD_BYTE_SIZE]; 40 | temp.tobytes(&mut bytes); 41 | bytes.to_vec() 42 | } 43 | } 44 | 45 | #[cfg(feature = "std")] 46 | impl fmt::Debug for SecretKey { 47 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 48 | let mut temp = BigNum::new(); 49 | temp.copy(&self.x); 50 | write!(f, "{}", temp.tostring()) 51 | } 52 | } 53 | 54 | impl PartialEq for SecretKey { 55 | fn eq(&self, other: &SecretKey) -> bool { 56 | self.as_bytes() == other.as_bytes() 57 | } 58 | } 59 | 60 | impl Eq for SecretKey {} 61 | 62 | /// A BLS public key. 63 | #[derive(Clone, PartialEq, Eq)] 64 | #[cfg_attr(feature = "std", derive(Debug))] 65 | pub struct PublicKey { 66 | pub point: G1Point, 67 | } 68 | 69 | impl PublicKey { 70 | /// Instantiate a PublicKey from some SecretKey. 71 | pub fn from_secret_key(sk: &SecretKey) -> Self { 72 | PublicKey { 73 | point: { 74 | #[cfg(feature = "std")] 75 | { 76 | G1Point::from_raw(amcl_utils::GENERATORG1.mul(&sk.x)) 77 | } 78 | #[cfg(not(feature = "std"))] 79 | { 80 | G1Point::from_raw(amcl_utils::GroupG1::generator().mul(&sk.x)) 81 | } 82 | }, 83 | } 84 | } 85 | 86 | /// Instantiate a PublicKey from some GroupG1 point. 87 | pub fn new_from_raw(pt: &GroupG1) -> Self { 88 | PublicKey { 89 | point: G1Point::from_raw(*pt), 90 | } 91 | } 92 | 93 | /// Instantiate a PublicKey from compressed bytes. 94 | pub fn from_bytes(bytes: &[u8]) -> Result { 95 | let point = G1Point::from_bytes(bytes)?; 96 | Ok(Self { point }) 97 | } 98 | 99 | /// Export the PublicKey to compressed bytes. 100 | pub fn as_bytes(&self) -> Vec { 101 | let mut clone = self.point.clone(); 102 | clone.as_bytes() 103 | } 104 | 105 | /// Export the public key to uncompress (x, y) bytes 106 | pub fn as_uncompressed_bytes(&mut self) -> Vec { 107 | if self.point.is_infinity() { 108 | return vec![0; 96]; 109 | } 110 | 111 | let mut result: Vec = vec![]; 112 | let mut bytes = [0 as u8; 48]; 113 | self.point.getx().tobytes(&mut bytes); 114 | result.extend_from_slice(&bytes); 115 | self.point.gety().tobytes(&mut bytes); 116 | result.extend_from_slice(&bytes); 117 | result 118 | } 119 | 120 | /// InstantiatePublicKey from uncompress (x, y) bytes 121 | pub fn from_uncompressed_bytes(bytes: &[u8]) -> Result { 122 | if bytes.len() != 96 { 123 | return Err(DecodeError::IncorrectSize); 124 | } 125 | 126 | let mut nil = true; 127 | for byte in bytes { 128 | if *byte != 0 { 129 | nil = false; 130 | break; 131 | } 132 | } 133 | if nil { 134 | // Point is infinity 135 | return Ok(PublicKey::new_from_raw(&GroupG1::new())); 136 | } 137 | 138 | let x_big = BigNum::frombytes(&bytes[0..48]); 139 | let y_big = BigNum::frombytes(&bytes[48..]); 140 | let point = GroupG1::new_bigs(&x_big, &y_big); 141 | 142 | if point.is_infinity() { 143 | return Err(DecodeError::BadPoint); 144 | } 145 | 146 | Ok(PublicKey::new_from_raw(&point)) 147 | } 148 | } 149 | 150 | /// A helper which stores a BLS public and private key pair. 151 | #[derive(Clone, PartialEq, Eq)] 152 | #[cfg_attr(feature = "std", derive(Debug))] 153 | pub struct Keypair { 154 | pub sk: SecretKey, 155 | pub pk: PublicKey, 156 | } 157 | 158 | impl Keypair { 159 | /// Instantiate a Keypair using SecretKey::random(). 160 | pub fn random(rng: &mut R) -> Self { 161 | let sk = SecretKey::random(rng); 162 | let pk = PublicKey::from_secret_key(&sk); 163 | Keypair { sk, pk } 164 | } 165 | } 166 | 167 | #[cfg(test)] 168 | mod tests { 169 | extern crate hex; 170 | extern crate rand; 171 | extern crate yaml_rust; 172 | 173 | use self::yaml_rust::yaml; 174 | use super::super::amcl_utils::compress_g1; 175 | use super::super::signature::Signature; 176 | use super::*; 177 | use std::{fs::File, io::prelude::*, path::PathBuf}; 178 | 179 | #[test] 180 | fn test_secret_key_serialization_isomorphism() { 181 | let sk_bytes = vec![ 182 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 252, 122, 126, 32, 0, 75, 89, 252, 183 | 31, 42, 130, 254, 88, 6, 90, 138, 202, 135, 194, 233, 117, 181, 75, 96, 238, 79, 100, 184 | 237, 59, 140, 111, 185 | ]; 186 | let sk = SecretKey::from_bytes(&sk_bytes).unwrap(); 187 | let decoded_sk = sk.as_bytes(); 188 | assert_eq!(decoded_sk, sk_bytes); 189 | } 190 | 191 | #[test] 192 | fn test_public_key_serialization_isomorphism() { 193 | for _ in 0..30 { 194 | let sk = SecretKey::random(&mut rand::thread_rng()); 195 | let pk = PublicKey::from_secret_key(&sk); 196 | let decoded_pk = pk.as_bytes(); 197 | let encoded_pk = PublicKey::from_bytes(&decoded_pk).unwrap(); 198 | let re_recoded_pk = encoded_pk.as_bytes(); 199 | assert_eq!(decoded_pk, re_recoded_pk); 200 | } 201 | } 202 | 203 | #[test] 204 | fn test_public_key_uncompressed_serialization_isomorphism() { 205 | for _ in 0..30 { 206 | let sk = SecretKey::random(&mut rand::thread_rng()); 207 | let mut pk = PublicKey::from_secret_key(&sk); 208 | let decoded_pk = pk.as_uncompressed_bytes(); 209 | let mut encoded_pk = PublicKey::from_uncompressed_bytes(&decoded_pk).unwrap(); 210 | let re_recoded_pk = encoded_pk.as_uncompressed_bytes(); 211 | assert_eq!(decoded_pk, re_recoded_pk); 212 | } 213 | } 214 | 215 | #[test] 216 | fn test_public_key_uncompressed_serialization_infinity() { 217 | let sk_bytes = vec![0; 48]; 218 | let sk = SecretKey::from_bytes(&sk_bytes).unwrap(); 219 | let mut pk = PublicKey::from_secret_key(&sk); 220 | let decoded_pk = pk.as_uncompressed_bytes(); 221 | let recoded_pk = PublicKey::from_uncompressed_bytes(&decoded_pk).unwrap(); 222 | assert_eq!(recoded_pk, pk); 223 | assert!(recoded_pk.point.is_infinity()) 224 | } 225 | 226 | #[test] 227 | fn test_public_key_uncompressed_serialization_incorrect_size() { 228 | let bytes = vec![0; 1]; 229 | assert_eq!( 230 | PublicKey::from_uncompressed_bytes(&bytes), 231 | Err(DecodeError::IncorrectSize) 232 | ); 233 | 234 | let bytes = vec![0; 95]; 235 | assert_eq!( 236 | PublicKey::from_uncompressed_bytes(&bytes), 237 | Err(DecodeError::IncorrectSize) 238 | ); 239 | 240 | let bytes = vec![0; 97]; 241 | assert_eq!( 242 | PublicKey::from_uncompressed_bytes(&bytes), 243 | Err(DecodeError::IncorrectSize) 244 | ); 245 | 246 | let bytes = vec![]; 247 | assert_eq!( 248 | PublicKey::from_uncompressed_bytes(&bytes), 249 | Err(DecodeError::IncorrectSize) 250 | ); 251 | } 252 | 253 | #[test] 254 | fn test_public_key_uncompressed_serialization_bad_point() { 255 | // Point (1, 1) is not valid 256 | let mut bytes = vec![0; 96]; 257 | bytes[47] = 1; 258 | bytes[95] = 1; 259 | assert_eq!( 260 | PublicKey::from_uncompressed_bytes(&bytes), 261 | Err(DecodeError::BadPoint) 262 | ); 263 | } 264 | 265 | #[test] 266 | fn test_signature_verify_with_serialized_public_key() { 267 | let sk_bytes = vec![ 268 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 252, 122, 126, 32, 0, 75, 89, 252, 269 | 31, 42, 130, 254, 88, 6, 90, 138, 202, 135, 194, 233, 117, 181, 75, 96, 238, 79, 100, 270 | 237, 59, 140, 111, 271 | ]; 272 | let sk = SecretKey::from_bytes(&sk_bytes).unwrap(); 273 | let pk = PublicKey::from_secret_key(&sk); 274 | let domain = 42; 275 | 276 | let message = "cats".as_bytes(); 277 | let signature = Signature::new(&message, domain, &sk); 278 | assert!(signature.verify(&message, domain, &pk)); 279 | 280 | let pk_bytes = pk.as_bytes(); 281 | let pk = PublicKey::from_bytes(&pk_bytes).unwrap(); 282 | assert!(signature.verify(&message, domain, &pk)); 283 | } 284 | 285 | #[test] 286 | fn test_random_secret_key_can_sign() { 287 | let sk = SecretKey::random(&mut rand::thread_rng()); 288 | let pk = PublicKey::from_secret_key(&sk); 289 | let domain = 42; 290 | 291 | let message = "cats".as_bytes(); 292 | let signature = Signature::new(&message, domain, &sk); 293 | assert!(signature.verify(&message, domain, &pk)); 294 | } 295 | 296 | // Test vector from https://github.com/ethereum/eth2.0-tests/blob/master/bls/test_bls.yml 297 | // case03_private_to_public_key 298 | #[test] 299 | fn case03_private_to_public_key() { 300 | // Run tests from test_bls.yml 301 | let mut file = { 302 | let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 303 | file_path_buf.push("src/test_vectors/test_bls.yml"); 304 | 305 | File::open(file_path_buf).unwrap() 306 | }; 307 | let mut yaml_str = String::new(); 308 | file.read_to_string(&mut yaml_str).unwrap(); 309 | let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap(); 310 | let doc = &docs[0]; 311 | 312 | // Select test case03 313 | let test_cases = doc["case03_private_to_public_key"].as_vec().unwrap(); 314 | 315 | // Verify input against output for each pair 316 | for test_case in test_cases { 317 | // Convert input to rust formats 318 | let input = test_case["input"].as_str().unwrap(); 319 | // Convert privateKey from yaml to SecretKey 320 | let privkey = input.trim_start_matches("0x"); 321 | let mut privkey = hex::decode(privkey).unwrap(); 322 | while privkey.len() < 48 { 323 | // Prepend until correct length 324 | privkey.insert(0, 0); 325 | } 326 | let sk = SecretKey::from_bytes(&privkey).unwrap(); 327 | 328 | // Create public key from private key and compress 329 | let pk = PublicKey::from_secret_key(&sk); 330 | let pk = compress_g1(&mut pk.point.as_raw().clone()); 331 | 332 | // Convert given output to rust PublicKey 333 | let output = test_case["output"].as_str().unwrap(); 334 | let output = output.trim_start_matches("0x"); 335 | let output = hex::decode(output).unwrap(); 336 | 337 | assert_eq!(output, pk); 338 | } 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr( 2 | not(feature = "std"), 3 | no_std, 4 | feature(alloc), 5 | feature(alloc_prelude), 6 | feature(prelude_import) 7 | )] 8 | 9 | #[cfg(not(feature = "std"))] 10 | #[macro_use] 11 | extern crate alloc; 12 | 13 | #[cfg(not(feature = "std"))] 14 | pub(crate) mod prelude { 15 | pub use alloc::prelude::v1::*; 16 | pub use core::prelude::v1::*; 17 | } 18 | 19 | #[cfg(not(feature = "std"))] 20 | #[allow(unused)] 21 | #[prelude_import] 22 | use crate::prelude::*; 23 | 24 | extern crate amcl; 25 | #[cfg(feature = "std")] 26 | #[macro_use] 27 | extern crate lazy_static; 28 | extern crate rand; 29 | 30 | mod aggregates; 31 | mod amcl_utils; 32 | mod errors; 33 | mod g1; 34 | mod g2; 35 | mod keys; 36 | mod rng; 37 | mod signature; 38 | 39 | use self::amcl::bls381 as BLSCurve; 40 | 41 | pub use aggregates::{AggregatePublicKey, AggregateSignature}; 42 | pub use amcl_utils::{compress_g2, hash_on_g2}; 43 | pub use errors::DecodeError; 44 | pub use keys::{Keypair, PublicKey, SecretKey}; 45 | pub use signature::Signature; 46 | -------------------------------------------------------------------------------- /src/rng.rs: -------------------------------------------------------------------------------- 1 | extern crate amcl; 2 | extern crate rand; 3 | 4 | use rand::Rng; 5 | 6 | use self::amcl::rand::RAND; 7 | 8 | pub fn get_seeded_rng(rng: &mut R, entropy_size: usize) -> RAND { 9 | // Generate entropy to seed the RNG 10 | let mut entropy = vec![0; entropy_size]; 11 | rng.fill_bytes(&mut entropy.as_mut_slice()); 12 | 13 | // Create the amcl RNG 14 | let mut rng = RAND::new(); 15 | rng.clean(); 16 | rng.seed(entropy_size, &entropy); 17 | rng 18 | } 19 | -------------------------------------------------------------------------------- /src/signature.rs: -------------------------------------------------------------------------------- 1 | extern crate amcl; 2 | 3 | use super::amcl_utils::{self, ate_pairing, hash_on_g2, map_to_g2}; 4 | use super::errors::DecodeError; 5 | use super::g2::G2Point; 6 | use super::keys::{PublicKey, SecretKey}; 7 | 8 | #[derive(Clone, PartialEq, Eq)] 9 | #[cfg_attr(feature = "std", derive(Debug))] 10 | pub struct Signature { 11 | pub point: G2Point, 12 | } 13 | 14 | impl Signature { 15 | /// Instantiate a new Signature from a message and a SecretKey. 16 | pub fn new(msg: &[u8], d: u64, sk: &SecretKey) -> Self { 17 | let hash_point = hash_on_g2(msg, d); 18 | let mut sig = hash_point.mul(&sk.x); 19 | sig.affine(); 20 | Self { 21 | point: G2Point::from_raw(sig), 22 | } 23 | } 24 | 25 | /// Instantiate a new Signature from a message and a SecretKey, where the message has already 26 | /// been hashed. 27 | pub fn new_hashed(msg_hash_real: &[u8], msg_hash_imaginary: &[u8], sk: &SecretKey) -> Self { 28 | let hash_point = map_to_g2(msg_hash_real, msg_hash_imaginary); 29 | let mut sig = hash_point.mul(&sk.x); 30 | sig.affine(); 31 | Self { 32 | point: G2Point::from_raw(sig), 33 | } 34 | } 35 | 36 | /// Verify the Signature against a PublicKey. 37 | /// 38 | /// In theory, should only return true if the PublicKey matches the SecretKey used to 39 | /// instantiate the Signature. 40 | pub fn verify(&self, msg: &[u8], d: u64, pk: &PublicKey) -> bool { 41 | let mut msg_hash_point = hash_on_g2(msg, d); 42 | msg_hash_point.affine(); 43 | let mut lhs = { 44 | #[cfg(feature = "std")] 45 | { 46 | ate_pairing(self.point.as_raw(), &amcl_utils::GENERATORG1) 47 | } 48 | #[cfg(not(feature = "std"))] 49 | { 50 | ate_pairing(self.point.as_raw(), &amcl_utils::GroupG1::generator()) 51 | } 52 | }; 53 | let mut rhs = ate_pairing(&msg_hash_point, &pk.point.as_raw()); 54 | lhs.equals(&mut rhs) 55 | } 56 | 57 | /// Verify the Signature against a PublicKey, where the message has already been hashed. 58 | /// 59 | /// The supplied hashes will be mapped to G2. 60 | /// 61 | /// In theory, should only return true if the PublicKey matches the SecretKey used to 62 | /// instantiate the Signature. 63 | pub fn verify_hashed( 64 | &self, 65 | msg_hash_real: &[u8], 66 | msg_hash_imaginary: &[u8], 67 | pk: &PublicKey, 68 | ) -> bool { 69 | let mut msg_hash_point = map_to_g2(msg_hash_real, msg_hash_imaginary); 70 | msg_hash_point.affine(); 71 | let mut lhs = { 72 | #[cfg(feature = "std")] 73 | { 74 | ate_pairing(self.point.as_raw(), &amcl_utils::GENERATORG1) 75 | } 76 | #[cfg(not(feature = "std"))] 77 | { 78 | ate_pairing(self.point.as_raw(), &amcl_utils::GroupG1::generator()) 79 | } 80 | }; 81 | let mut rhs = ate_pairing(&msg_hash_point, &pk.point.as_raw()); 82 | lhs.equals(&mut rhs) 83 | } 84 | 85 | /// Instantiate a Signature from compressed bytes. 86 | pub fn from_bytes(bytes: &[u8]) -> Result { 87 | let point = G2Point::from_bytes(bytes)?; 88 | Ok(Self { point }) 89 | } 90 | 91 | /// Compress the Signature as bytes. 92 | pub fn as_bytes(&self) -> Vec { 93 | let mut clone = self.point.clone(); 94 | clone.as_bytes() 95 | } 96 | } 97 | 98 | #[cfg(test)] 99 | mod tests { 100 | extern crate hex; 101 | extern crate rand; 102 | extern crate yaml_rust; 103 | 104 | use self::yaml_rust::yaml; 105 | use super::super::keys::Keypair; 106 | use super::*; 107 | use std::{fs::File, io::prelude::*, path::PathBuf}; 108 | 109 | #[test] 110 | fn basic_sign_verify() { 111 | let keypair = Keypair::random(&mut rand::thread_rng()); 112 | let sk = keypair.sk; 113 | let vk = keypair.pk; 114 | 115 | let messages = vec!["", "a", "an example"]; 116 | let domain = 42; 117 | 118 | for m in messages { 119 | /* 120 | * Simple sign and verify 121 | */ 122 | let bytes = m.as_bytes(); 123 | let mut sig = Signature::new(&bytes, domain, &sk); 124 | assert!(sig.verify(&bytes, domain, &vk)); 125 | 126 | /* 127 | * Test serializing, then deserializing the signature 128 | */ 129 | let sig_bytes = sig.as_bytes(); 130 | let mut new_sig = Signature::from_bytes(&sig_bytes).unwrap(); 131 | assert_eq!(&sig.as_bytes(), &new_sig.as_bytes()); 132 | assert!(new_sig.verify(&bytes, domain, &vk)); 133 | } 134 | } 135 | 136 | #[test] 137 | fn verification_failure_message() { 138 | let keypair = Keypair::random(&mut rand::thread_rng()); 139 | let sk = keypair.sk; 140 | let vk = keypair.pk; 141 | 142 | let mut msg = "Some msg"; 143 | let domain = 42; 144 | let sig = Signature::new(&msg.as_bytes(), domain, &sk); 145 | msg = "Other msg"; 146 | assert_eq!(sig.verify(&msg.as_bytes(), domain, &vk), false); 147 | msg = ""; 148 | assert_eq!(sig.verify(&msg.as_bytes(), domain, &vk), false); 149 | } 150 | 151 | #[test] 152 | fn verification_failure_domain() { 153 | let keypair = Keypair::random(&mut rand::thread_rng()); 154 | let sk = keypair.sk; 155 | let vk = keypair.pk; 156 | 157 | let msg = "Some msg"; 158 | let mut domain = 42; 159 | let sig = Signature::new(&msg.as_bytes(), domain, &sk); 160 | domain = 11; 161 | assert_eq!(sig.verify(&msg.as_bytes(), domain, &vk), false); 162 | } 163 | 164 | #[test] 165 | fn case04_sign_messages() { 166 | // Run tests from test_bls.yml 167 | let mut file = { 168 | let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 169 | file_path_buf.push("src/test_vectors/test_bls.yml"); 170 | 171 | File::open(file_path_buf).unwrap() 172 | }; 173 | let mut yaml_str = String::new(); 174 | file.read_to_string(&mut yaml_str).unwrap(); 175 | let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap(); 176 | let doc = &docs[0]; 177 | 178 | // Select test case04 179 | let test_cases = doc["case04_sign_messages"].as_vec().unwrap(); 180 | 181 | // Verify input against output for each pair 182 | for test_case in test_cases { 183 | // Convert input to rust formats 184 | let input = test_case["input"].clone(); 185 | // Convert domain from yaml to u64 186 | let domain = input["domain"].as_str().unwrap(); 187 | let domain = domain.trim_start_matches("0x"); 188 | let domain = u64::from_str_radix(domain, 16).unwrap(); 189 | 190 | // Convert msg from yaml to bytes (Vec) 191 | let msg = input["message"].as_str().unwrap(); 192 | let msg = msg.trim_start_matches("0x"); 193 | let msg = hex::decode(msg).unwrap(); 194 | 195 | // Convert privateKey from yaml to SecretKey 196 | let privkey = input["privkey"].as_str().unwrap(); 197 | let privkey = privkey.trim_start_matches("0x"); 198 | let mut privkey = hex::decode(privkey).unwrap(); 199 | while privkey.len() < 48 { 200 | // Prepend until correct length 201 | privkey.insert(0, 0); 202 | } 203 | let sk = SecretKey::from_bytes(&privkey).unwrap(); 204 | 205 | // Create signature 206 | let mut sig = Signature::new(&msg, domain, &sk); 207 | let compressed_sig = sig.as_bytes(); 208 | 209 | // Convert given output to rust compressed signature (Vec) 210 | let output = test_case["output"].as_str().unwrap(); 211 | let output = output.trim_start_matches("0x"); 212 | let output = hex::decode(output).unwrap(); 213 | 214 | assert_eq!(output, compressed_sig); 215 | } 216 | } 217 | } 218 | --------------------------------------------------------------------------------