├── CODEOWNERS ├── rustfmt.toml ├── CHANGELOG ├── accumulator-ecc ├── pairings │ ├── .gitignore │ ├── src │ │ ├── bls12_381 │ │ │ ├── tests │ │ │ │ ├── g1_uncompressed_invalid_test_vectors.dat │ │ │ │ ├── g1_compressed_valid_test_vectors.dat │ │ │ │ ├── g1_uncompressed_valid_test_vectors.dat │ │ │ │ ├── g2_compressed_valid_test_vectors.dat │ │ │ │ └── g2_uncompressed_valid_test_vectors.dat │ │ │ ├── osswu_map │ │ │ │ ├── mod.rs │ │ │ │ ├── g1.rs │ │ │ │ └── g2.rs │ │ │ ├── isogeny │ │ │ │ ├── mod.rs │ │ │ │ ├── g2.rs │ │ │ │ └── tests.rs │ │ │ ├── fq12.rs │ │ │ └── README.md │ │ ├── tests │ │ │ ├── mod.rs │ │ │ ├── repr.rs │ │ │ ├── engine.rs │ │ │ └── field.rs │ │ ├── bn256 │ │ │ ├── README.md │ │ │ ├── cofactor.rs │ │ │ ├── fr.rs │ │ │ └── fq12.rs │ │ ├── signum.rs │ │ ├── hash_to_curve.rs │ │ ├── hash_to_field.rs │ │ └── wnaf.rs │ ├── benches │ │ ├── pairing_benches.rs │ │ └── bls12_381 │ │ │ ├── fq12.rs │ │ │ ├── mod.rs │ │ │ ├── fq2.rs │ │ │ ├── ec.rs │ │ │ ├── fq.rs │ │ │ └── fr.rs │ ├── .travis.yml │ ├── COPYRIGHT │ ├── LICENSE-MIT │ ├── README.md │ └── Cargo.toml ├── Cargo.toml ├── accumulator │ ├── Cargo.toml │ ├── src │ │ ├── error.rs │ │ ├── key.rs │ │ ├── lib.rs │ │ └── macros.rs │ └── README.md └── README.md ├── Cargo.toml ├── .gitignore ├── accumulator-common ├── src │ ├── bigint │ │ └── mod.rs │ ├── macros.rs │ ├── lib.rs │ └── error.rs └── Cargo.toml ├── accumulator-rsa ├── Cargo.toml ├── README.md └── src │ ├── hash.rs │ ├── proofmem.rs │ ├── key.rs │ ├── proofnon.rs │ ├── lib.rs │ ├── witnessmem.rs │ └── witnessnon.rs ├── README.md └── CONTRIBUTING /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @mikelodder7 2 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | reorder_imports = true -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | # Version 0.1.0 2 | - Initial Version 3 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/tests/g1_uncompressed_invalid_test_vectors.dat: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "accumulator-common", 4 | "accumulator-rsa" 5 | ] 6 | -------------------------------------------------------------------------------- /accumulator-ecc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "pairings", 4 | "accumulator" 5 | ] 6 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod curve; 2 | pub mod engine; 3 | pub mod field; 4 | pub mod hash; 5 | pub mod repr; 6 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/tests/g1_compressed_valid_test_vectors.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelodder7/accumulator-rs/HEAD/accumulator-ecc/pairings/src/bls12_381/tests/g1_compressed_valid_test_vectors.dat -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/tests/g1_uncompressed_valid_test_vectors.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelodder7/accumulator-rs/HEAD/accumulator-ecc/pairings/src/bls12_381/tests/g1_uncompressed_valid_test_vectors.dat -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/tests/g2_compressed_valid_test_vectors.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelodder7/accumulator-rs/HEAD/accumulator-ecc/pairings/src/bls12_381/tests/g2_compressed_valid_test_vectors.dat -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/tests/g2_uncompressed_valid_test_vectors.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelodder7/accumulator-rs/HEAD/accumulator-ecc/pairings/src/bls12_381/tests/g2_uncompressed_valid_test_vectors.dat -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bn256/README.md: -------------------------------------------------------------------------------- 1 | # BN256 2 | 3 | This is an implementation of the BN256 pairing-friendly elliptic curve construction. 4 | 5 | ## BN256 Parameterization 6 | 7 | Follows go-ethereum parametrization. -------------------------------------------------------------------------------- /accumulator-ecc/pairings/benches/pairing_benches.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate ff; 4 | extern crate pairings as pairing; 5 | extern crate rand_core; 6 | extern crate rand_xorshift; 7 | extern crate test; 8 | 9 | mod bls12_381; 10 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | # - beta 5 | # - nightly 6 | 7 | before_script: 8 | - rustup component add clippy 9 | 10 | script: 11 | - cargo clippy -- -D warnings 12 | - travis_wait 360 cargo test 13 | - travis_wait 360 cargo test -- --ignored 14 | - travis_wait 360 cargo test --release 15 | - travis_wait 360 cargo test --release -- --ignored 16 | -------------------------------------------------------------------------------- /accumulator-ecc/accumulator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "accumulator" 3 | version = "0.1.0" 4 | authors = ["Trustframe Developers"] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | blake2 = "0.9" 9 | ff-zeroize = "0.6" 10 | hex = "0.4" 11 | hkdf = "0.9" 12 | rand = "0.7" 13 | rayon = "1.4.0" 14 | pairings = { version = "0.20", path = "../pairings" } 15 | serde = { version = "1.0", features = ["derive"] } 16 | serde-big-array = "0.3" 17 | zeroize = { version = "1.2", features = ["zeroize_derive"] } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | **/target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | 14 | #Added by cargo 15 | # 16 | #already existing elements were commented out 17 | 18 | /target 19 | #Cargo.lock 20 | .idea 21 | -------------------------------------------------------------------------------- /accumulator-ecc/accumulator/src/error.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone, Debug)] 2 | pub struct Error { 3 | pub message: String, 4 | pub code: usize, 5 | } 6 | 7 | impl Error { 8 | pub fn from_msg(code: usize, message: &str) -> Self { 9 | Self { 10 | code, 11 | message: message.to_string(), 12 | } 13 | } 14 | } 15 | 16 | impl From for Error { 17 | fn from(err: std::io::Error) -> Self { 18 | Self { 19 | code: 2, 20 | message: err.to_string(), 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyrights in the "pairing-plus" library are retained by their contributors. No 2 | copyright assignment is required to contribute to the "pairing-plus" library. 3 | 4 | The "pairing-plus" library is licensed under 5 | 6 | * MIT license (see ./LICENSE-MIT or http://opensource.org/licenses/MIT) 7 | 8 | Unless you explicitly state otherwise, any contribution intentionally 9 | submitted for inclusion in the work by you, as defined in the MIT 10 | license, shall be licensed as above, without any additional terms or 11 | conditions. 12 | -------------------------------------------------------------------------------- /accumulator-common/src/bigint/mod.rs: -------------------------------------------------------------------------------- 1 | /// Use Big Integer implementation backed by OpenSSL BigNum 2 | #[cfg(feature = "openssl")] 3 | pub mod ossl; 4 | /// Use Big Integer implementation backed by GMP Mpz 5 | #[cfg(feature = "rust-gmp")] 6 | pub mod mpz; 7 | /// Use Big Integer implementation backed by rust's num-bigint 8 | #[cfg(feature = "bi-rust")] 9 | pub mod rust; 10 | 11 | /// The result from running extended euclid algorithm 12 | #[derive(Debug, Default)] 13 | pub struct GcdResult { 14 | /// The greatest common divisor 15 | pub value: BigInteger, 16 | /// Bézout coefficient `a` 17 | pub a: BigInteger, 18 | /// Bézout coefficient `b` 19 | pub b: BigInteger 20 | } 21 | 22 | #[cfg(feature = "openssl")] 23 | pub use ossl::OsslBigInt as BigInteger; 24 | #[cfg(feature = "rust-gmp")] 25 | pub use mpz::MpzBigInt as BigInteger; 26 | #[cfg(feature = "bi-rust")] 27 | pub use rust::RustBigInt as BigInteger; 28 | 29 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/README.md: -------------------------------------------------------------------------------- 1 | # pairing 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/pairing-plus.svg)](https://crates.io/crates/pairing-plus) 4 | [![Build Status](https://travis-ci.com/algorand/pairing-plus.svg)](https://travis-ci.com/algorand/pairing-plus) 5 | 6 | This is a Rust crate for using pairing-friendly elliptic curves. Currently, only the [BLS12-381](https://z.cash/blog/new-snark-curve.html) construction is implemented. 7 | 8 | ## [Documentation](https://docs.rs/pairing-plus/) 9 | 10 | Bring the `pairing-plus` crate into your project just as you normally would. 11 | 12 | ## Security Warnings 13 | 14 | This library does not make any guarantees about constant-time operations, memory access patterns, or resistance to side-channel attacks. 15 | 16 | ## License 17 | 18 | Licensed under 19 | 20 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 21 | 22 | Unless you explicitly state otherwise, any contribution intentionally 23 | submitted for inclusion in the work by you, as defined in the MIT 24 | license, shall be licensed as above, without any additional terms or 25 | conditions. 26 | -------------------------------------------------------------------------------- /accumulator-rsa/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Michael Lodder "] 3 | categories = ["cryptography", "rsa"] 4 | description = "A Universal Cryptographic RSA Accumulator" 5 | documentation = "https://docs.rs/accumulator-rs" 6 | edition = "2018" 7 | license = "Apache-2.0" 8 | name = "rsa" 9 | readme = "README.md" 10 | repository = "https://github.com/mikelodder7/accumulator-rs" 11 | version = "0.1.0" 12 | 13 | [badges] 14 | maintenance = { status = "experimental" } 15 | 16 | [features] 17 | default = ["bi-ossl"] 18 | bi-rust = ["common/bi-rust"] 19 | bi-ossl = ["common/bi-ossl"] 20 | bi-gmp = ["common/bi-gmp"] 21 | 22 | [dependencies] 23 | common = { version = "0.1", package = "accumulator-common", path = "../accumulator-common", default-features = false } 24 | arrayref = "0.3" 25 | blake2 = "0.8" 26 | failure = "0.1" 27 | hex = "0.4" 28 | hkdf = "0.8" 29 | rand = "0.7" 30 | rayon = "1.3" 31 | serde = { version = "1.0", features = ["serde_derive"] } 32 | zeroize = { version = "1.1", features = ["zeroize_derive"] } 33 | 34 | [dev-dependencies] 35 | rust-gmp = "0.5" 36 | 37 | [package.metadata.docs.rs] 38 | all-features = true 39 | rustdoc-args = ["--cfg", "docsrs"] -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bn256/cofactor.rs: -------------------------------------------------------------------------------- 1 | use crate::{bn256::{G1, G2}, CurveProjective, ClearH}; 2 | 3 | impl ClearH for G1 { 4 | fn clear_h(&mut self) { 5 | // Cofactor for BN256 is 1 do thing 6 | } 7 | } 8 | 9 | /// Implements hashing to G2 cofactor clearing 10 | /// as defined in the paper by Fuentes-Castaneda, Knapp and Rodriguez-Henriquez 11 | /// 12 | /// in Section 6.1 13 | /// which states Q -> xQ + F(3xQ) + F(F(xQ)) + F(F(F(Q))) 14 | /// 15 | /// where F is the Frobenius map 16 | /// 17 | /// However according to section 3.3 in 18 | /// 19 | /// 20 | /// This is actually not necessary. So for now we just multiply by h2 21 | impl ClearH for G2 { 22 | fn clear_h(&mut self) { 23 | // TODO: try to get this to work 24 | *self = self.into_affine().scale_by_cofactor() 25 | } 26 | } 27 | 28 | #[test] 29 | fn clear_cofactor() { 30 | use crate::SubgroupCheck; 31 | let g = G2::one(); 32 | // g.clear_h(); 33 | let ga = g.into_affine(); 34 | assert!(ga.scale_by_cofactor().into_affine().in_subgroup()); 35 | assert_eq!(g, ga.scale_by_cofactor()); 36 | } -------------------------------------------------------------------------------- /accumulator-common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Michael Lodder "] 3 | categories = ["cryptography", "rsa"] 4 | description = "Cryptographic Accumulator common structs and methods" 5 | edition = "2018" 6 | license = "Apache-2.0" 7 | name = "accumulator-common" 8 | repository = "https://github.com/mikelodder7/accumulator-rs" 9 | version = "0.1.0" 10 | 11 | [features] 12 | default = ["bi-rust"] 13 | bi-rust = ["glass_pumpkin", "num-bigint", "num-traits", "num-integer", "rand"] 14 | bi-ossl = ["openssl"] 15 | bi-gmp = ["hex", "rust-gmp"] 16 | 17 | [dependencies] 18 | failure = "0.1" 19 | hex = { version = "0.4", optional = true } 20 | glass_pumpkin = { version = "0.4", optional = true } 21 | num-bigint = { version = "0.3", features = ["rand"], optional = true } 22 | num-traits = { version = "0.2", optional = true } 23 | num-integer = { version = "0.1", optional = true } 24 | openssl = { version = "0.10", optional = true } 25 | rand = { version = "0.7", optional = true } 26 | rust-gmp = { version = "0.5", optional = true, git = "https://github.com/mikelodder7/rust-gmp" } 27 | serde = { version = "1.0", features = ["serde_derive"] } 28 | zeroize = { version = "1.1", features = ["zeroize_derive"] } 29 | 30 | [dev-dependencies] 31 | rust-gmp = { version = "0.5", git = "https://github.com/mikelodder7/rust-gmp" } 32 | 33 | [package.metadata.docs.rs] 34 | all-features = true 35 | rustdoc-args = ["--cfg", "docsrs"] 36 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pairings" 3 | 4 | edition = "2018" 5 | # Remember to change version string in README.md. 6 | 7 | version = "0.20.0" 8 | authors = [ 9 | # authors of the original pairing library 10 | "Sean Bowe ", 11 | "Jack Grigg ", 12 | # maintainers of this pairing-fork library 13 | "Riad S. Wahby ", 14 | "Zhenfei Zhang ", 15 | "Mike Lodder Self { 20 | if self == rhs { 21 | Sgn0Result::NonNegative 22 | } else { 23 | Sgn0Result::Negative 24 | } 25 | } 26 | } 27 | 28 | /// Signum computations and conditional in-place negation 29 | pub trait Signum0: Field { 30 | /// Returns either Negative or NonNegative 31 | fn sgn0(&self) -> Sgn0Result; 32 | 33 | /// Negate if the argument is Negative 34 | fn negate_if(&mut self, sgn: Sgn0Result) { 35 | if sgn == Sgn0Result::Negative { 36 | self.negate(); 37 | } 38 | } 39 | } 40 | 41 | #[test] 42 | #[allow(clippy::eq_op)] 43 | fn test_sgn0result_xor() { 44 | assert_eq!( 45 | Sgn0Result::Negative ^ Sgn0Result::Negative, 46 | Sgn0Result::NonNegative 47 | ); 48 | assert_eq!( 49 | Sgn0Result::Negative ^ Sgn0Result::NonNegative, 50 | Sgn0Result::Negative 51 | ); 52 | assert_eq!( 53 | Sgn0Result::NonNegative ^ Sgn0Result::Negative, 54 | Sgn0Result::Negative 55 | ); 56 | assert_eq!( 57 | Sgn0Result::NonNegative ^ Sgn0Result::NonNegative, 58 | Sgn0Result::NonNegative 59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /accumulator-common/src/macros.rs: -------------------------------------------------------------------------------- 1 | /// Implement Serialization methods based on TryFrom 2 | #[macro_export] 3 | macro_rules! serdes_impl { 4 | ($name:ident) => { 5 | impl serde::Serialize for $name { 6 | fn serialize(&self, serializer: S) -> Result 7 | where 8 | S: serde::Serializer, 9 | { 10 | serializer.serialize_bytes(&self.to_bytes()[..]) 11 | } 12 | } 13 | 14 | impl<'a> serde::Deserialize<'a> for $name { 15 | fn deserialize(deserializer: D) -> Result 16 | where 17 | D: serde::Deserializer<'a>, 18 | { 19 | struct DeserializeVisitor; 20 | 21 | impl<'a> serde::de::Visitor<'a> for DeserializeVisitor { 22 | type Value = $name; 23 | 24 | fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 25 | formatter.write_str("expected byte array") 26 | } 27 | 28 | fn visit_bytes(self, value: &[u8]) -> Result<$name, E> 29 | where 30 | E: serde::de::Error, 31 | { 32 | $name::try_from(value).map_err(|_| { 33 | serde::de::Error::invalid_value(serde::de::Unexpected::Bytes(value), &self) 34 | }) 35 | } 36 | } 37 | 38 | deserializer.deserialize_bytes(DeserializeVisitor) 39 | } 40 | } 41 | }; 42 | } -------------------------------------------------------------------------------- /accumulator-common/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny( 2 | // warnings, 3 | missing_docs, 4 | unsafe_code, 5 | unused_import_braces, 6 | unused_lifetimes, 7 | unused_qualifications, 8 | )] 9 | #![cfg_attr(feature = "nightly", feature(doc_cfg))] 10 | //! This crate is only meant to be used internally across 11 | //! accumulator types. 12 | 13 | /// Common macros 14 | pub mod macros; 15 | /// Multiprecision Big Integer Implementation 16 | pub mod bigint; 17 | /// Accumulator errors that can be thrown 18 | pub mod error; 19 | 20 | #[cfg(not(any(feature = "openssl", feature = "rust-gmp", feature = "num-bigint")))] 21 | compile_error!("A big number library must be chosen: either bigint-rust, openssl, or rust-gmp"); 22 | #[cfg(any(all(feature = "openssl", feature = "rust-gmp", feature = "bigint-rust"), 23 | all(feature = "openssl", feature = "rust-gmp"), 24 | all(feature = "openssl", feature = "bigint-rust"), 25 | all(feature = "bigint-rust", feature = "rust-gmp")))] 26 | compile_error!("Only one big number library must be chosen: either bigint-rust, openssl, or rust-gmp"); 27 | 28 | use bigint::BigInteger; 29 | 30 | /// Helper class that always reduces operations by a modulus 31 | #[derive(Debug)] 32 | pub struct Field { 33 | modulus: BigInteger 34 | } 35 | 36 | impl Field { 37 | /// Construct a new field 38 | pub fn new(modulus: &BigInteger) -> Self { 39 | Self { modulus: modulus.clone() } 40 | } 41 | 42 | /// b^e mod r 43 | pub fn exp(&self, base: &BigInteger, exp: &BigInteger) -> BigInteger { 44 | base.mod_exp(exp, &self.modulus) 45 | } 46 | 47 | /// (a * b) mod r 48 | pub fn mul(&self, a: &BigInteger, b: &BigInteger) -> BigInteger { 49 | a.mod_mul(&b, &self.modulus) 50 | } 51 | 52 | /// a^-1 mod r 53 | pub fn inv(&self, a: &BigInteger) -> BigInteger { a.mod_inverse(&self.modulus) } 54 | } -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/hash_to_curve.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | This module defines a hash_to_curve trait. 3 | */ 4 | 5 | use crate::{ 6 | ClearH, 7 | bls12_381::{IsogenyMap, OSSWUMap}, 8 | hash_to_field::{hash_to_field, ExpandMsg, FromRO}, 9 | CurveProjective, 10 | }; 11 | 12 | type CoordT = ::Base; 13 | 14 | /// Random oracle and injective maps to curve 15 | pub trait HashToCurve 16 | where 17 | X: ExpandMsg, 18 | { 19 | /// Random oracle 20 | fn hash_to_curve, Dt: AsRef<[u8]>>(msg: Mt, dst: Dt) -> Self; 21 | 22 | /// Injective encoding 23 | fn encode_to_curve, Dt: AsRef<[u8]>>(msg: Mt, dst: Dt) -> Self; 24 | } 25 | 26 | impl HashToCurve for PtT 27 | where 28 | PtT: ClearH + IsogenyMap + OSSWUMap + std::fmt::Debug, 29 | CoordT: FromRO, 30 | X: ExpandMsg, 31 | { 32 | fn hash_to_curve, Dt: AsRef<[u8]>>(msg: Mt, dst: Dt) -> PtT { 33 | let mut p = { 34 | let u = hash_to_field::, X>(msg.as_ref(), dst.as_ref(), 2); 35 | let mut q0 = PtT::osswu_map(&u[0]); 36 | println!("g0 before = {:?}", q0); 37 | q0.isogeny_map(); 38 | println!("g0 after = {:?}", q0); 39 | let mut q1 = PtT::osswu_map(&u[1]); 40 | println!("g1 before = {:?}", q1); 41 | q1.isogeny_map(); 42 | println!("g1 after = {:?}", q1); 43 | q0.add_assign(&q1); 44 | q0 45 | }; 46 | p.clear_h(); 47 | p 48 | } 49 | 50 | fn encode_to_curve, Dt: AsRef<[u8]>>(msg: Mt, dst: Dt) -> PtT { 51 | let mut p = { 52 | let u = hash_to_field::, X>(msg.as_ref(), dst.as_ref(), 1); 53 | PtT::osswu_map(&u[0]) 54 | }; 55 | p.isogeny_map(); 56 | p.clear_h(); 57 | p 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # accumulator-rs 2 | Cryptographic Accumulators in Rust 3 | 4 | A cryptographic accumulator allows for testing set membership without revealing which set member was tested. This avoids the need to check every member to see if a value exists and compress into a small value. Provers use a witness that a specific value is or is not in the set and generate a zero-knowledge proof. 5 | 6 | There are three constructions for accumulators as referenced [Zero-Knowledge Proofs for Set Membership](https://eprint.iacr.org/2019/1255.pdf) 7 | 8 | 1. RSA-Based: Requires groups of unknown order and can be slow to create but offers reasonable performance for witness updates and proof generation and verification. Each element must be prime number and the modulus must be large enough to be secure (≥ 2048-bits). Elements do not have to be know in advance and can be added on-the-fly. Setup parameters include generating prime numbers for the modulus. 9 | 1. Elliptic-Curve Pairing-Based: Accumulators proofs are smaller and faster to compute that RSA-Based. Setup parameters are large and sets are number of elements allowed is fixed after creation. 10 | 1. Merkle Tree-Based: Setup parameters tend to be short and the accumulator size depends on the depth of the tree and the representation of the leaves. 11 | 12 | This project aims to implement each one and compare their sizes, performance, and complexity. 13 | 14 | # Author 15 | 16 | Michael Lodder 17 | 18 | # License 19 | 20 | Licensed under either of 21 | * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 22 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 23 | 24 | at your option. 25 | 26 | # Contribution 27 | 28 | Unless you explicitly state otherwise, any contribution intentionally submitted 29 | for inclusion in the work by you shall be dual licensed as above, without any 30 | additional terms or conditions. 31 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | # Contributing to Accumulator Rust 2 | 3 | Accumulator Rust is Apache 2.0 licensed and accepts contributions via 4 | [GitHub](https://github.com/mikelodder7/accumulator-rs) pull requests. 5 | 6 | # Ways to contribute to Accumulator-Rs 7 | 8 | - Bugs or issues: Report problems or defects found to the [Michael Lodder](mailto: redmike7@gmail.com) 9 | - Features and enhancements: Provide expanded capabilities or optimizations 10 | - Documentation: Improve existing documentation or create new information 11 | - Tests for events and results: 12 | - Functional: Does the code work as expected? 13 | - Performance: Are there performance bottlenecks or issues? 14 | - Usability: Can the API be improved? 15 | - Security: Are there security concerns about the implementation in terms of constant time or edge cases? 16 | - Localization: Can the library handle arbitrary inputs besides ASCII characters like all UTF-8? Can the code run properly on various OS configurations with different locales? 17 | - Recovery: Does the code handle invalid inputs or operations and fail gracefully or crash or segfault? 18 | 19 | # The Commit Process 20 | 21 | When contributing code, please follow these guidelines: 22 | 23 | - Fork the repository and make your changes in a feature branch 24 | - Include unit and integration tests for any new features and updates to existing tests 25 | - Ensure that the unit and integration tests run successfully. 26 | - Check that the lint tests pass 27 | 28 | ## Important 29 | Use `git rebase origin/master` to limit creating merge commits. The easiest method for this is 30 | 31 | 1. `git fetch origin/master` 32 | 1. `git rebase origin/master` 33 | 34 | Substitute `origin` with the necessary git remote. 35 | 36 | ## Signed-off-by 37 | Each commit must include a "Signed-off-by" line in the commit message (`git commit -s`). This sign-off indicates that you agree the commit satisfies the [Developer Certificate of Origin](https://developercertificate.org). 38 | 39 | ## Commit Email Address 40 | Your commit email address must match your GitHub or GitLab email address. For more information, see https://help.github.com/articles/setting-your-commit-email-address-in-git/. 41 | 42 | -------------------------------------------------------------------------------- /accumulator-rsa/src/hash.rs: -------------------------------------------------------------------------------- 1 | use blake2::{Blake2b, Digest}; 2 | use common::bigint::BigInteger; 3 | use hkdf::Hkdf; 4 | use std::convert::TryFrom; 5 | 6 | /// Hashes `input` to a prime. 7 | /// See Section 7 in 8 | /// 9 | pub(crate) fn hash_to_prime>(input: B) -> BigInteger { 10 | let mut input = input.as_ref().to_vec(); 11 | let mut i = 1usize; 12 | let offset = input.len(); 13 | input.extend_from_slice(&i.to_be_bytes()[..]); 14 | let end = input.len(); 15 | 16 | let mut num; 17 | 18 | loop { 19 | let mut hash = Blake2b::digest(input.as_slice()); 20 | // Force it to be odd 21 | hash[63] |= 1; 22 | // Only need 256 bits just borrow the bottom 32 bytes 23 | // There should be plenty of primes below 2^256 24 | // and we want this to be reasonably fast 25 | num = BigInteger::try_from(&hash[32..]).unwrap(); 26 | if num.is_prime() { 27 | break; 28 | } 29 | i += 1; 30 | let i_bytes = i.to_be_bytes(); 31 | input[offset..end].clone_from_slice(&i_bytes[..]); 32 | } 33 | num 34 | } 35 | 36 | /// Hashes `input` to a member of group `n` 37 | /// that can be used as a generator `g`. `g` will be QR_N. 38 | pub(crate) fn hash_to_generator>(input: B, n: &BigInteger) -> BigInteger { 39 | let length = n.bits() / 8; 40 | let h = Hkdf::::new(Some(b"RSA_ACCUMULATOR_HASH_TO_GENERATOR_"), input.as_ref()); 41 | let mut okm = vec![0u8; length]; 42 | h.expand(b"", &mut okm).unwrap(); 43 | 44 | BigInteger::from(okm).mod_sqr(n) 45 | } 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | use super::*; 50 | use gmp::mpz::{Mpz, ProbabPrimeResult}; 51 | use rand::prelude::*; 52 | 53 | #[test] 54 | fn test_hash() { 55 | let t = hash_to_prime(b"This is a test to find a prime"); 56 | let n = Mpz::from(t.to_bytes().as_slice()); 57 | assert!(n.probab_prime(15) != ProbabPrimeResult::NotPrime); 58 | let mut bytes = vec![0u8; 32]; 59 | for _ in 0..10 { 60 | thread_rng().fill_bytes(bytes.as_mut_slice()); 61 | let t = hash_to_prime(&bytes); 62 | let n = Mpz::from(t.to_bytes().as_slice()); 63 | assert!(n.probab_prime(15) != ProbabPrimeResult::NotPrime); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/osswu_map/mod.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Optimized Simplified SWU maps for G1 and G2 3 | see: https://eprint.iacr.org/2019/403 4 | */ 5 | 6 | mod chain; 7 | mod g1; 8 | mod g2; 9 | #[cfg(test)] 10 | mod tests; 11 | 12 | use crate::CurveProjective; 13 | use ff::Field; 14 | 15 | /// Trait for mapping from base field element to curve point 16 | pub trait OSSWUMap: CurveProjective { 17 | /// Evaluate optimized simplified SWU map on supplied base field element 18 | fn osswu_map(u: &::Base) -> Self; 19 | } 20 | 21 | #[inline(always)] 22 | fn osswu_help(u: &F, xi: &F, ellp_a: &F, ellp_b: &F) -> [F; 7] { 23 | let usq = { 24 | let mut tmp = *u; 25 | tmp.square(); 26 | tmp 27 | }; 28 | 29 | let (nd_common, xi_usq, xi2_u4) = { 30 | let mut tmp = usq; 31 | tmp.mul_assign(xi); // xi * u^2 32 | let tmp2 = tmp; 33 | tmp.square(); // xi^2 * u^4 34 | let tmp3 = tmp; 35 | tmp.add_assign(&tmp2); // xi^2 * u^4 + xi * u^2 36 | (tmp, tmp2, tmp3) 37 | }; 38 | 39 | let x0_num = { 40 | let mut tmp = nd_common; 41 | tmp.add_assign(&F::one()); // 1 + nd_common 42 | tmp.mul_assign(ellp_b); // B * (1 + nd_common) 43 | tmp 44 | }; 45 | 46 | let x0_den = { 47 | let mut tmp = *ellp_a; 48 | if nd_common.is_zero() { 49 | tmp.mul_assign(xi); 50 | } else { 51 | tmp.mul_assign(&nd_common); 52 | tmp.negate(); 53 | } 54 | tmp 55 | }; 56 | 57 | // compute g(X0(u)) 58 | let gx0_den = { 59 | let mut tmp = x0_den; 60 | tmp.square(); 61 | tmp.mul_assign(&x0_den); 62 | tmp // x0_den ^ 3 63 | }; 64 | 65 | let gx0_num = { 66 | let mut tmp1 = gx0_den; 67 | tmp1.mul_assign(ellp_b); // B * x0_den^3 68 | let mut tmp2 = x0_den; 69 | tmp2.square(); // x0_den^2 70 | tmp2.mul_assign(&x0_num); // x0_num * x0_den^2 71 | tmp2.mul_assign(ellp_a); // A * x0_num * x0_den^2 72 | tmp1.add_assign(&tmp2); // ^^^ + B * x0_den^3 73 | tmp2 = x0_num; 74 | tmp2.square(); // x0_num^2 75 | tmp2.mul_assign(&x0_num); // x0_num^3 76 | tmp1.add_assign(&tmp2); // x0_num^3 + A * x0_num * x0_den^2 + B * x0_den^3 77 | tmp1 78 | }; 79 | 80 | [usq, xi_usq, xi2_u4, x0_num, x0_den, gx0_num, gx0_den] 81 | } 82 | -------------------------------------------------------------------------------- /accumulator-rsa/src/proofmem.rs: -------------------------------------------------------------------------------- 1 | use crate::{accumulator::Accumulator, common::error::*, memwitness::MembershipWitness, Poke2Proof}; 2 | use std::convert::TryFrom; 3 | 4 | /// A proof of knowledge of exponents membership proof 5 | #[derive(Debug, Eq, PartialEq, Clone)] 6 | pub struct MembershipProof(Poke2Proof); 7 | 8 | impl MembershipProof { 9 | /// Create a new PoKE2 proof 10 | pub fn new>( 11 | witness: &MembershipWitness, 12 | accumulator: &Accumulator, 13 | nonce: B, 14 | ) -> Self { 15 | let proof = Poke2Proof::new( 16 | &witness.x, 17 | &witness.u, 18 | &accumulator.value, 19 | &accumulator.modulus, 20 | nonce, 21 | ); 22 | Self(proof) 23 | } 24 | 25 | /// Verify a set membership proof 26 | pub fn verify>(&self, accumulator: &Accumulator, nonce: B) -> bool { 27 | self.0.verify(&accumulator.value, &accumulator.modulus, nonce) 28 | } 29 | 30 | /// Serialize this to bytes 31 | pub fn to_bytes(&self) -> Vec { 32 | self.0.to_bytes() 33 | } 34 | } 35 | 36 | impl TryFrom<&[u8]> for MembershipProof { 37 | type Error = AccumulatorError; 38 | 39 | fn try_from(data: &[u8]) -> Result { 40 | let proof = Poke2Proof::try_from(data)?; 41 | Ok(Self(proof)) 42 | } 43 | } 44 | 45 | serdes_impl!(MembershipProof); 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | use super::*; 50 | use crate::{key::AccumulatorSecretKey, MEMBER_SIZE_BITS}; 51 | use common::bigint::BigInteger; 52 | use rayon::prelude::*; 53 | 54 | #[test] 55 | fn proof_test() { 56 | let key = AccumulatorSecretKey::default(); 57 | let members: Vec<[u8; 8]> = vec![ 58 | 3u64.to_be_bytes(), 59 | 7u64.to_be_bytes(), 60 | 11u64.to_be_bytes(), 61 | 13u64.to_be_bytes(), 62 | ]; 63 | let mut acc = Accumulator::with_members(&key, &members); 64 | let witness = MembershipWitness::new(&acc, &members[0]).unwrap(); 65 | let nonce = b"proof_test"; 66 | 67 | let proof = MembershipProof::new(&witness, &acc, nonce); 68 | assert!(proof.verify(&acc, nonce)); 69 | acc.remove_assign(&key, &members[0]).unwrap(); 70 | 71 | assert!(!proof.verify(&acc, nonce)); 72 | assert_eq!(proof.to_bytes().len(), Poke2Proof::SIZE_BYTES); 73 | } 74 | 75 | #[test] 76 | fn big_proof_test() { 77 | let key = AccumulatorSecretKey::default(); 78 | let members: Vec = (0..1_000) 79 | .collect::>() 80 | .par_iter() 81 | .map(|_| BigInteger::generate_prime(MEMBER_SIZE_BITS)) 82 | .collect(); 83 | let mut acc = Accumulator::with_prime_members(&key, &members).unwrap(); 84 | let witness = MembershipWitness::new_prime(&acc, &members[0]).unwrap(); 85 | let nonce = b"big_proof_test"; 86 | 87 | let proof = MembershipProof::new(&witness, &acc, nonce); 88 | assert!(proof.verify(&acc, nonce)); 89 | acc.remove_prime_assign(&key, &members[0]).unwrap(); 90 | 91 | assert!(!proof.verify(&acc, nonce)); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bn256/fr.rs: -------------------------------------------------------------------------------- 1 | use crate::hash_to_field::BaseFromRO; 2 | use digest::generic_array::{typenum::U48, GenericArray}; 3 | use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; 4 | use std::io::{Cursor, Read}; 5 | 6 | #[derive(PrimeField, Zeroize)] 7 | #[PrimeFieldModulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"] 8 | #[PrimeFieldGenerator = "7"] 9 | pub struct Fr(FrRepr); 10 | 11 | /// set the default value for Fr to 0 12 | impl ::std::default::Default for Fr { 13 | fn default() -> Self { 14 | Fr::zero() 15 | } 16 | } 17 | 18 | /// # Safety 19 | pub const unsafe fn transmute(r: FrRepr) -> Fr { 20 | Fr(r) 21 | } 22 | 23 | impl BaseFromRO for Fr { 24 | type BaseLength = U48; 25 | 26 | fn from_okm(okm: &GenericArray) -> Fr { 27 | const F_2_192: Fr = Fr(FrRepr([ 28 | 0x16A0A73150000000u64, 29 | 0xB8114D6D7DE87ADBu64, 30 | 0xE81AC1E7808072C9u64, 31 | 0x10216F7BA065E00Du64, 32 | ])); 33 | 34 | // unwraps are safe here: we only use 24 bytes at a time, which is strictly less than p 35 | let mut repr = FrRepr::default(); 36 | repr.read_be(Cursor::new([0; 8]).chain(Cursor::new(&okm[..24]))) 37 | .unwrap(); 38 | let mut elm = Fr::from_repr(repr).unwrap(); 39 | elm.mul_assign(&F_2_192); 40 | 41 | repr.read_be(Cursor::new([0; 8]).chain(Cursor::new(&okm[24..]))) 42 | .unwrap(); 43 | elm.add_assign(&Fr::from_repr(repr).unwrap()); 44 | elm 45 | } 46 | } 47 | 48 | #[cfg(test)] 49 | use crate::serdes::SerDes; 50 | 51 | // #[test] 52 | // fn test_to_hex() { 53 | // use ff::to_hex; 54 | // assert_eq!( 55 | // to_hex(&Fr::one()), 56 | // "0000000000000000000000000000000000000000000000000000000000000001" 57 | // ); 58 | // } 59 | // 60 | // #[test] 61 | // fn test_fr_from_hex() { 62 | // use ff::from_hex; 63 | // let fr: Fr = 64 | // from_hex("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); 65 | // assert_eq!(fr, Fr::one()); 66 | // 67 | // let fr: Fr = 68 | // from_hex("0x0000000000000000000000000000000000000000000000000000000000000001").unwrap(); 69 | // assert_eq!(fr, Fr::one()); 70 | // 71 | // let fr: Fr = from_hex("0x01").unwrap(); 72 | // assert_eq!(fr, Fr::one()); 73 | // 74 | // let fr: Fr = from_hex("0x00").unwrap(); 75 | // assert_eq!(fr, Fr::zero()); 76 | // 77 | // let fr: Fr = from_hex("00").unwrap(); 78 | // assert_eq!(fr, Fr::zero()); 79 | // } 80 | // 81 | #[test] 82 | fn test_roots_of_unity() { 83 | assert_eq!(Fr::S, 28); 84 | } 85 | 86 | #[test] 87 | fn test_default() { 88 | assert_eq!(Fr::default(), Fr::zero()); 89 | } 90 | 91 | #[test] 92 | fn print_fr_repr() { 93 | const F_2_192: Fr = Fr(FrRepr([ 94 | 0x59476ebc41b4528fu64, 95 | 0xc5a30cb243fcc152u64, 96 | 0x2b34e63940ccbd72u64, 97 | 0x1e179025ca247088u64, 98 | ])); 99 | let mut out = [0u8; 32]; 100 | F_2_192.serialize(&mut out.as_mut(), true).unwrap(); 101 | println!("{:?}", hex::encode(out)); 102 | } -------------------------------------------------------------------------------- /accumulator-ecc/pairings/benches/bls12_381/fq12.rs: -------------------------------------------------------------------------------- 1 | use ff::Field; 2 | use pairing::bls12_381::*; 3 | use rand_core::SeedableRng; 4 | use rand_xorshift::XorShiftRng; 5 | 6 | #[bench] 7 | fn bench_fq12_add_assign(b: &mut ::test::Bencher) { 8 | const SAMPLES: usize = 1000; 9 | 10 | let mut rng = XorShiftRng::from_seed([ 11 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 12 | 0xe5, 13 | ]); 14 | let v: Vec<(Fq12, Fq12)> = (0..SAMPLES) 15 | .map(|_| (Fq12::random(&mut rng), Fq12::random(&mut rng))) 16 | .collect(); 17 | 18 | let mut count = 0; 19 | b.iter(|| { 20 | let mut tmp = v[count].0; 21 | tmp.add_assign(&v[count].1); 22 | count = (count + 1) % SAMPLES; 23 | tmp 24 | }); 25 | } 26 | 27 | #[bench] 28 | fn bench_fq12_sub_assign(b: &mut ::test::Bencher) { 29 | const SAMPLES: usize = 1000; 30 | 31 | let mut rng = XorShiftRng::from_seed([ 32 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 33 | 0xe5, 34 | ]); 35 | let v: Vec<(Fq12, Fq12)> = (0..SAMPLES) 36 | .map(|_| (Fq12::random(&mut rng), Fq12::random(&mut rng))) 37 | .collect(); 38 | 39 | let mut count = 0; 40 | b.iter(|| { 41 | let mut tmp = v[count].0; 42 | tmp.sub_assign(&v[count].1); 43 | count = (count + 1) % SAMPLES; 44 | tmp 45 | }); 46 | } 47 | 48 | #[bench] 49 | fn bench_fq12_mul_assign(b: &mut ::test::Bencher) { 50 | const SAMPLES: usize = 1000; 51 | 52 | let mut rng = XorShiftRng::from_seed([ 53 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 54 | 0xe5, 55 | ]); 56 | let v: Vec<(Fq12, Fq12)> = (0..SAMPLES) 57 | .map(|_| (Fq12::random(&mut rng), Fq12::random(&mut rng))) 58 | .collect(); 59 | 60 | let mut count = 0; 61 | b.iter(|| { 62 | let mut tmp = v[count].0; 63 | tmp.mul_assign(&v[count].1); 64 | count = (count + 1) % SAMPLES; 65 | tmp 66 | }); 67 | } 68 | 69 | #[bench] 70 | fn bench_fq12_squaring(b: &mut ::test::Bencher) { 71 | const SAMPLES: usize = 1000; 72 | 73 | let mut rng = XorShiftRng::from_seed([ 74 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 75 | 0xe5, 76 | ]); 77 | let v: Vec = (0..SAMPLES).map(|_| Fq12::random(&mut rng)).collect(); 78 | 79 | let mut count = 0; 80 | b.iter(|| { 81 | let mut tmp = v[count]; 82 | tmp.square(); 83 | count = (count + 1) % SAMPLES; 84 | tmp 85 | }); 86 | } 87 | 88 | #[bench] 89 | fn bench_fq12_inverse(b: &mut ::test::Bencher) { 90 | const SAMPLES: usize = 1000; 91 | 92 | let mut rng = XorShiftRng::from_seed([ 93 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 94 | 0xe5, 95 | ]); 96 | let v: Vec = (0..SAMPLES).map(|_| Fq12::random(&mut rng)).collect(); 97 | 98 | let mut count = 0; 99 | b.iter(|| { 100 | let tmp = v[count].inverse(); 101 | count = (count + 1) % SAMPLES; 102 | tmp 103 | }); 104 | } 105 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/tests/repr.rs: -------------------------------------------------------------------------------- 1 | use ff::{PrimeField, PrimeFieldRepr}; 2 | use rand_core::SeedableRng; 3 | 4 | pub fn random_repr_tests() { 5 | random_encoding_tests::(); 6 | random_shl_tests::(); 7 | random_shr_tests::(); 8 | } 9 | 10 | fn random_encoding_tests() { 11 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 12 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 13 | 0xe5, 14 | ]); 15 | for _ in 0..1000 { 16 | let r = F::random(&mut rng).into_repr(); 17 | 18 | // Big endian 19 | { 20 | let mut rdecoded = R::default(); 21 | 22 | let mut v: Vec = vec![]; 23 | r.write_be(&mut v).unwrap(); 24 | rdecoded.read_be(&v[0..]).unwrap(); 25 | 26 | assert_eq!(r.as_ref(), rdecoded.as_ref()); 27 | } 28 | 29 | // Little endian 30 | { 31 | let mut rdecoded = R::default(); 32 | 33 | let mut v: Vec = vec![]; 34 | r.write_le(&mut v).unwrap(); 35 | rdecoded.read_le(&v[0..]).unwrap(); 36 | 37 | assert_eq!(r.as_ref(), rdecoded.as_ref()); 38 | } 39 | 40 | { 41 | let mut rdecoded_le = R::default(); 42 | let mut rdecoded_be_flip = R::default(); 43 | 44 | let mut v: Vec = vec![]; 45 | r.write_le(&mut v).unwrap(); 46 | 47 | // This reads in little-endian, so we are done. 48 | rdecoded_le.read_le(&v[..]).unwrap(); 49 | 50 | // This reads in big-endian, so we perform a swap of the 51 | // bytes beforehand. 52 | let v: Vec = v.into_iter().rev().collect(); 53 | rdecoded_be_flip.read_be(&v[..]).unwrap(); 54 | 55 | assert_eq!(rdecoded_le, rdecoded_be_flip); 56 | } 57 | } 58 | } 59 | 60 | fn random_shl_tests() { 61 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 62 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 63 | 0xe5, 64 | ]); 65 | for _ in 0..100 { 66 | let r = F::random(&mut rng).into_repr(); 67 | 68 | for shift in 0..=r.num_bits() { 69 | let mut r1 = r; 70 | let mut r2 = r; 71 | 72 | for _ in 0..shift { 73 | r1.mul2(); 74 | } 75 | 76 | r2.shl(shift); 77 | 78 | assert_eq!(r1, r2); 79 | } 80 | } 81 | } 82 | 83 | fn random_shr_tests() { 84 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 85 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 86 | 0xe5, 87 | ]); 88 | for _ in 0..100 { 89 | let r = F::random(&mut rng).into_repr(); 90 | 91 | for shift in 0..=r.num_bits() { 92 | let mut r1 = r; 93 | let mut r2 = r; 94 | 95 | for _ in 0..shift { 96 | r1.div2(); 97 | } 98 | 99 | r2.shr(shift); 100 | 101 | assert_eq!(r1, r2); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/osswu_map/g1.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Constants for OSSWU map for G1 3 | */ 4 | 5 | use super::chain::chain_pm3div4; 6 | use super::{osswu_help, OSSWUMap}; 7 | use crate::bls12_381::{Fq, FqRepr, G1}; 8 | use crate::signum::Signum0; 9 | use ff::Field; 10 | 11 | pub(super) const ELLP_A: Fq = Fq(FqRepr([ 12 | 0x2f65aa0e9af5aa51u64, 13 | 0x86464c2d1e8416c3u64, 14 | 0xb85ce591b7bd31e2u64, 15 | 0x27e11c91b5f24e7cu64, 16 | 0x28376eda6bfc1835u64, 17 | 0x155455c3e5071d85u64, 18 | ])); 19 | 20 | pub(super) const ELLP_B: Fq = Fq(FqRepr([ 21 | 0xfb996971fe22a1e0u64, 22 | 0x9aa93eb35b742d6fu64, 23 | 0x8c476013de99c5c4u64, 24 | 0x873e27c3a221e571u64, 25 | 0xca72b5e45a52d888u64, 26 | 0x06824061418a386bu64, 27 | ])); 28 | 29 | const XI: Fq = Fq(FqRepr([ 30 | 0x886c00000023ffdcu64, 31 | 0xf70008d3090001du64, 32 | 0x77672417ed5828c3u64, 33 | 0x9dac23e943dc1740u64, 34 | 0x50553f1b9c131521u64, 35 | 0x78c712fbe0ab6e8u64, 36 | ])); 37 | 38 | const SQRT_M_XI_CUBED: Fq = Fq(FqRepr([ 39 | 0x43b571cad3215f1fu64, 40 | 0xccb460ef1c702dc2u64, 41 | 0x742d884f4f97100bu64, 42 | 0xdb2c3e3238a3382bu64, 43 | 0xe40f3fa13fce8f88u64, 44 | 0x73a2af9892a2ffu64, 45 | ])); 46 | 47 | impl OSSWUMap for G1 { 48 | fn osswu_map(u: &Fq) -> G1 { 49 | // compute x0 and g(x0) 50 | let [usq, xi_usq, _, x0_num, x0_den, gx0_num, gx0_den] = 51 | osswu_help(u, &XI, &ELLP_A, &ELLP_B); 52 | 53 | // compute g(X0(u)) ^ ((p - 3) // 4) 54 | let sqrt_candidate = { 55 | let mut tmp1 = gx0_num; 56 | tmp1.mul_assign(&gx0_den); // u * v 57 | let mut tmp2 = gx0_den; 58 | tmp2.square(); // v^2 59 | tmp2.mul_assign(&tmp1); // u * v^3 60 | let tmp3 = tmp2; 61 | chain_pm3div4(&mut tmp2, &tmp3); // (u v^3) ^ ((p - 3) // 4) 62 | tmp2.mul_assign(&tmp1); // u v (u v^3) ^ ((p - 3) // 4) 63 | tmp2 64 | }; 65 | 66 | // select correct values for y and for x numerator 67 | let (mut x_num, mut y) = { 68 | let mut test_cand = sqrt_candidate; 69 | test_cand.square(); 70 | test_cand.mul_assign(&gx0_den); 71 | if test_cand == gx0_num { 72 | (x0_num, sqrt_candidate) // g(x0) is square 73 | } else { 74 | let mut x1_num = x0_num; // g(x1) is square 75 | x1_num.mul_assign(&xi_usq); // x1 = xi u^2 g(x0) 76 | let mut y1 = usq; // y1 = sqrt(-xi**3) * u^3 g(x0) ^ ((p - 1) // 4) 77 | y1.mul_assign(&u); 78 | y1.mul_assign(&sqrt_candidate); 79 | y1.mul_assign(&SQRT_M_XI_CUBED); 80 | (x1_num, y1) 81 | } 82 | }; 83 | 84 | // make sure sign of y and sign of u agree 85 | let sgn0_y_xor_u = y.sgn0() ^ u.sgn0(); 86 | y.negate_if(sgn0_y_xor_u); 87 | 88 | 89 | // convert to projective 90 | x_num.mul_assign(&x0_den); // x_num * x_den / x_den^2 = x_num / x_den 91 | y.mul_assign(&gx0_den); // y * x_den^3 / x_den^3 = y 92 | 93 | 94 | G1 { 95 | x: x_num, 96 | y, 97 | z: x0_den, 98 | } 99 | } 100 | } 101 | 102 | #[test] 103 | fn print_consts_g1() { 104 | println!("{:?}", ELLP_A); 105 | println!("{:?}", ELLP_B); 106 | println!("{:?}", XI); 107 | println!("{:?}", SQRT_M_XI_CUBED); 108 | } -------------------------------------------------------------------------------- /accumulator-common/src/error.rs: -------------------------------------------------------------------------------- 1 | use failure::{Backtrace, Context, Fail}; 2 | 3 | /// The error types 4 | #[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)] 5 | pub enum AccumulatorErrorKind { 6 | /// Type cannot be converted to an BigInteger 7 | #[fail(display = "Type cannot be converted to BigInteger")] 8 | InvalidType, 9 | /// When trying to add a member that already exists in the accumulator 10 | #[fail(display = "The value supplied already exists in the accumulator")] 11 | DuplicateValueSupplied, 12 | /// When trying to create a witness to a value not in the accumulator 13 | /// or when trying to remove an invalid value from the accumulator 14 | #[fail(display = "Member is not currently in the accumulator")] 15 | InvalidMemberSupplied, 16 | /// An incorrect number of bytes was supplied when trying to deserialize from bytes 17 | #[fail(display = "Invalid bytes supplied when deserializing")] 18 | SerializationError, 19 | } 20 | 21 | /// Error wrapper to add context and backtrace 22 | #[derive(Debug)] 23 | pub struct AccumulatorError { 24 | inner: Context, 25 | } 26 | 27 | impl Fail for AccumulatorError { 28 | fn cause(&self) -> Option<&dyn Fail> { 29 | self.inner.cause() 30 | } 31 | 32 | fn backtrace(&self) -> Option<&Backtrace> { 33 | self.inner.backtrace() 34 | } 35 | } 36 | 37 | impl AccumulatorError { 38 | /// Convert from a kind with msg string 39 | pub fn from_msg(kind: AccumulatorErrorKind, msg: D) -> AccumulatorError 40 | where 41 | D: std::fmt::Display + std::fmt::Debug + Send + Sync + 'static, 42 | { 43 | AccumulatorError { 44 | inner: Context::new(msg).context(kind), 45 | } 46 | } 47 | 48 | /// Get the inner error kind 49 | pub fn kind(&self) -> AccumulatorErrorKind { 50 | *self.inner.get_context() 51 | } 52 | } 53 | 54 | impl std::fmt::Display for AccumulatorError { 55 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 56 | let mut first = true; 57 | 58 | for cause in Fail::iter_chain(&self.inner) { 59 | if first { 60 | first = false; 61 | writeln!(f, "Error: {}", cause)?; 62 | } else { 63 | writeln!(f, "Caused by: {}", cause)?; 64 | } 65 | } 66 | 67 | Ok(()) 68 | } 69 | } 70 | 71 | impl From> for AccumulatorError { 72 | fn from(inner: Context) -> Self { 73 | AccumulatorError { inner } 74 | } 75 | } 76 | 77 | impl From for AccumulatorError { 78 | fn from(err: AccumulatorErrorKind) -> Self { 79 | AccumulatorError::from_msg(err, "") 80 | } 81 | } 82 | 83 | #[cfg(feature = "openssl")] 84 | impl From for AccumulatorError { 85 | fn from(err: openssl::error::ErrorStack) -> Self { 86 | AccumulatorError::from_msg(AccumulatorErrorKind::InvalidType, err.errors().iter().map(|e| e.reason().unwrap_or("")).collect::>().join(",")) 87 | } 88 | } 89 | 90 | #[cfg(feature = "rust-gmp")] 91 | impl From for AccumulatorError { 92 | fn from(err: gmp::mpz::ParseMpzError) -> Self { 93 | AccumulatorError::from_msg(AccumulatorErrorKind::InvalidType, format!("{:?}", err)) 94 | } 95 | } 96 | 97 | #[cfg(feature = "bi-rust")] 98 | impl From for AccumulatorError { 99 | fn from(err: num_bigint::ParseBigIntError) -> Self { 100 | AccumulatorError::from_msg(AccumulatorErrorKind::InvalidType, format!("{:?}", err)) 101 | } 102 | } -------------------------------------------------------------------------------- /accumulator-ecc/pairings/benches/bls12_381/mod.rs: -------------------------------------------------------------------------------- 1 | mod ec; 2 | mod fq; 3 | mod fq12; 4 | mod fq2; 5 | mod fr; 6 | 7 | use pairing::bls12_381::*; 8 | use pairing::{CurveAffine, CurveProjective, Engine}; 9 | use rand_core::SeedableRng; 10 | use rand_xorshift::XorShiftRng; 11 | 12 | #[bench] 13 | fn bench_pairing_g1_preparation(b: &mut ::test::Bencher) { 14 | const SAMPLES: usize = 1000; 15 | 16 | let mut rng = XorShiftRng::from_seed([ 17 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 18 | 0xe5, 19 | ]); 20 | 21 | let v: Vec = (0..SAMPLES).map(|_| G1::random(&mut rng)).collect(); 22 | 23 | let mut count = 0; 24 | b.iter(|| { 25 | let tmp = G1Affine::from(v[count]).prepare(); 26 | count = (count + 1) % SAMPLES; 27 | tmp 28 | }); 29 | } 30 | 31 | #[bench] 32 | fn bench_pairing_g2_preparation(b: &mut ::test::Bencher) { 33 | const SAMPLES: usize = 1000; 34 | 35 | let mut rng = XorShiftRng::from_seed([ 36 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 37 | 0xe5, 38 | ]); 39 | 40 | let v: Vec = (0..SAMPLES).map(|_| G2::random(&mut rng)).collect(); 41 | 42 | let mut count = 0; 43 | b.iter(|| { 44 | let tmp = G2Affine::from(v[count]).prepare(); 45 | count = (count + 1) % SAMPLES; 46 | tmp 47 | }); 48 | } 49 | 50 | #[bench] 51 | fn bench_pairing_miller_loop(b: &mut ::test::Bencher) { 52 | const SAMPLES: usize = 1000; 53 | 54 | let mut rng = XorShiftRng::from_seed([ 55 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 56 | 0xe5, 57 | ]); 58 | let v: Vec<(G1Prepared, G2Prepared)> = (0..SAMPLES) 59 | .map(|_| { 60 | ( 61 | G1Affine::from(G1::random(&mut rng)).prepare(), 62 | G2Affine::from(G2::random(&mut rng)).prepare(), 63 | ) 64 | }) 65 | .collect(); 66 | 67 | let mut count = 0; 68 | b.iter(|| { 69 | let tmp = Bls12::miller_loop(&[(&v[count].0, &v[count].1)]); 70 | count = (count + 1) % SAMPLES; 71 | tmp 72 | }); 73 | } 74 | 75 | #[bench] 76 | fn bench_pairing_final_exponentiation(b: &mut ::test::Bencher) { 77 | const SAMPLES: usize = 1000; 78 | 79 | let mut rng = XorShiftRng::from_seed([ 80 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 81 | 0xe5, 82 | ]); 83 | 84 | let v: Vec = (0..SAMPLES) 85 | .map(|_| { 86 | ( 87 | G1Affine::from(G1::random(&mut rng)).prepare(), 88 | G2Affine::from(G2::random(&mut rng)).prepare(), 89 | ) 90 | }) 91 | .map(|(ref p, ref q)| Bls12::miller_loop(&[(p, q)])) 92 | .collect(); 93 | 94 | let mut count = 0; 95 | b.iter(|| { 96 | let tmp = Bls12::final_exponentiation(&v[count]); 97 | count = (count + 1) % SAMPLES; 98 | tmp 99 | }); 100 | } 101 | 102 | #[bench] 103 | fn bench_pairing_full(b: &mut ::test::Bencher) { 104 | const SAMPLES: usize = 1000; 105 | 106 | let mut rng = XorShiftRng::from_seed([ 107 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 108 | 0xe5, 109 | ]); 110 | let v: Vec<(G1, G2)> = (0..SAMPLES) 111 | .map(|_| (G1::random(&mut rng), G2::random(&mut rng))) 112 | .collect(); 113 | 114 | let mut count = 0; 115 | b.iter(|| { 116 | let tmp = Bls12::pairing(v[count].0, v[count].1); 117 | count = (count + 1) % SAMPLES; 118 | tmp 119 | }); 120 | } 121 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/benches/bls12_381/fq2.rs: -------------------------------------------------------------------------------- 1 | use ff::{Field, SqrtField}; 2 | use pairing::bls12_381::*; 3 | use rand_core::SeedableRng; 4 | use rand_xorshift::XorShiftRng; 5 | 6 | #[bench] 7 | fn bench_fq2_add_assign(b: &mut ::test::Bencher) { 8 | const SAMPLES: usize = 1000; 9 | 10 | let mut rng = XorShiftRng::from_seed([ 11 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 12 | 0xe5, 13 | ]); 14 | let v: Vec<(Fq2, Fq2)> = (0..SAMPLES) 15 | .map(|_| (Fq2::random(&mut rng), Fq2::random(&mut rng))) 16 | .collect(); 17 | 18 | let mut count = 0; 19 | b.iter(|| { 20 | let mut tmp = v[count].0; 21 | tmp.add_assign(&v[count].1); 22 | count = (count + 1) % SAMPLES; 23 | tmp 24 | }); 25 | } 26 | 27 | #[bench] 28 | fn bench_fq2_sub_assign(b: &mut ::test::Bencher) { 29 | const SAMPLES: usize = 1000; 30 | 31 | let mut rng = XorShiftRng::from_seed([ 32 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 33 | 0xe5, 34 | ]); 35 | let v: Vec<(Fq2, Fq2)> = (0..SAMPLES) 36 | .map(|_| (Fq2::random(&mut rng), Fq2::random(&mut rng))) 37 | .collect(); 38 | 39 | let mut count = 0; 40 | b.iter(|| { 41 | let mut tmp = v[count].0; 42 | tmp.sub_assign(&v[count].1); 43 | count = (count + 1) % SAMPLES; 44 | tmp 45 | }); 46 | } 47 | 48 | #[bench] 49 | fn bench_fq2_mul_assign(b: &mut ::test::Bencher) { 50 | const SAMPLES: usize = 1000; 51 | 52 | let mut rng = XorShiftRng::from_seed([ 53 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 54 | 0xe5, 55 | ]); 56 | let v: Vec<(Fq2, Fq2)> = (0..SAMPLES) 57 | .map(|_| (Fq2::random(&mut rng), Fq2::random(&mut rng))) 58 | .collect(); 59 | 60 | let mut count = 0; 61 | b.iter(|| { 62 | let mut tmp = v[count].0; 63 | tmp.mul_assign(&v[count].1); 64 | count = (count + 1) % SAMPLES; 65 | tmp 66 | }); 67 | } 68 | 69 | #[bench] 70 | fn bench_fq2_squaring(b: &mut ::test::Bencher) { 71 | const SAMPLES: usize = 1000; 72 | 73 | let mut rng = XorShiftRng::from_seed([ 74 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 75 | 0xe5, 76 | ]); 77 | let v: Vec = (0..SAMPLES).map(|_| Fq2::random(&mut rng)).collect(); 78 | 79 | let mut count = 0; 80 | b.iter(|| { 81 | let mut tmp = v[count]; 82 | tmp.square(); 83 | count = (count + 1) % SAMPLES; 84 | tmp 85 | }); 86 | } 87 | 88 | #[bench] 89 | fn bench_fq2_inverse(b: &mut ::test::Bencher) { 90 | const SAMPLES: usize = 1000; 91 | 92 | let mut rng = XorShiftRng::from_seed([ 93 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 94 | 0xe5, 95 | ]); 96 | let v: Vec = (0..SAMPLES).map(|_| Fq2::random(&mut rng)).collect(); 97 | 98 | let mut count = 0; 99 | b.iter(|| { 100 | let tmp = v[count].inverse(); 101 | count = (count + 1) % SAMPLES; 102 | tmp 103 | }); 104 | } 105 | 106 | #[bench] 107 | fn bench_fq2_sqrt(b: &mut ::test::Bencher) { 108 | const SAMPLES: usize = 1000; 109 | 110 | let mut rng = XorShiftRng::from_seed([ 111 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 112 | 0xe5, 113 | ]); 114 | let v: Vec = (0..SAMPLES).map(|_| Fq2::random(&mut rng)).collect(); 115 | 116 | let mut count = 0; 117 | b.iter(|| { 118 | let tmp = v[count].sqrt(); 119 | count = (count + 1) % SAMPLES; 120 | tmp 121 | }); 122 | } 123 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/isogeny/mod.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Isogenies E' -> E and E2' -> E2 for OSSWU map. 3 | */ 4 | 5 | mod g1; 6 | mod g2; 7 | #[cfg(test)] 8 | mod tests; 9 | 10 | use crate::CurveProjective; 11 | use ff::Field; 12 | 13 | /// Alias for the coordinate type corresponding to a CurveProjective type 14 | type CoordT = ::Base; 15 | 16 | /// Evaluate isogeny map from curve with non-zero j-invariant. 17 | pub trait IsogenyMap { 18 | /// Eavluate isogeny map 19 | fn isogeny_map(&mut self); 20 | } 21 | 22 | /// Generic isogeny evaluation function 23 | fn eval_iso(pt: &mut PtT, coeffs: [&[CoordT]; 4]) { 24 | // XXX hack: In array below, 16 is long enough for both iso11 and iso3. 25 | // Rust (still) can't handle generic array sizes (issue #43408) 26 | let mut tmp = [CoordT::::zero(); 16]; 27 | let mut mapvals = [CoordT::::zero(); 4]; 28 | // scope for pt borrow 29 | { 30 | // unpack input point 31 | let (x, y, z) = pt.as_tuple(); 32 | 33 | // precompute powers of z 34 | let zpows = { 35 | // XXX hack: In array below, 15 is long enough for both iso11 and iso3. 36 | let mut zpows = [CoordT::::zero(); 15]; 37 | zpows[0] = *z; 38 | zpows[0].square(); // z^2 39 | zpows[1] = zpows[0]; 40 | zpows[1].square(); // z^4 41 | { 42 | let (z_squared, rest) = zpows.split_at_mut(1); 43 | for idx in 1..coeffs[2].len() - 2 { 44 | if idx % 2 == 0 { 45 | rest[idx] = rest[idx / 2 - 1]; 46 | rest[idx].square(); 47 | } else { 48 | rest[idx] = rest[idx - 1]; 49 | rest[idx].mul_assign(&z_squared[0]); 50 | } 51 | } 52 | } 53 | zpows 54 | }; 55 | 56 | for idx in 0..4 { 57 | let clen = coeffs[idx].len() - 1; 58 | // multiply coeffs by powers of Z 59 | for jdx in 0..clen { 60 | tmp[jdx] = coeffs[idx][clen - 1 - jdx]; 61 | tmp[jdx].mul_assign(&zpows[jdx]); 62 | } 63 | // compute map value by Horner's rule 64 | mapvals[idx] = coeffs[idx][clen]; 65 | for tmpval in &tmp[..clen] { 66 | mapvals[idx].mul_assign(x); 67 | mapvals[idx].add_assign(tmpval); 68 | } 69 | } 70 | 71 | // x denominator is order 1 less than x numerator, so we need an extra factor of Z^2 72 | mapvals[1].mul_assign(&zpows[0]); 73 | 74 | // multiply result of Y map by the y-coord, y / z^3 75 | mapvals[2].mul_assign(y); 76 | mapvals[3].mul_assign(z); 77 | mapvals[3].mul_assign(&zpows[0]); 78 | } // pt is no longer borrowed here 79 | 80 | // hack to simultaneously access elements of tmp 81 | let (xx, yy, zz) = { 82 | let (xx, rest) = tmp.split_at_mut(1); 83 | let (yy, rest) = rest.split_at_mut(1); 84 | (&mut xx[0], &mut yy[0], &mut rest[0]) 85 | }; 86 | 87 | // compute Jacobian coordinates of resulting point 88 | *zz = mapvals[1]; 89 | zz.mul_assign(&mapvals[3]); // Zout = xden * yden 90 | 91 | *xx = mapvals[0]; 92 | xx.mul_assign(&mapvals[3]); // xnum * yden 93 | xx.mul_assign(zz); // xnum * xden * yden^2 94 | 95 | *yy = *zz; 96 | yy.square(); // xden^2 * yden^2 97 | yy.mul_assign(&mapvals[2]); // ynum * xden^2 * yden^2 98 | yy.mul_assign(&mapvals[1]); // ynum * xden^3 * yden^2 99 | 100 | let (x, y, z) = unsafe { pt.as_tuple_mut() }; 101 | *x = *xx; 102 | *y = *yy; 103 | *z = *zz; 104 | } 105 | -------------------------------------------------------------------------------- /accumulator-rsa/src/key.rs: -------------------------------------------------------------------------------- 1 | use crate::{b2fa, FACTOR_SIZE}; 2 | use common::{ 3 | bigint::BigInteger, 4 | error::{AccumulatorError, AccumulatorErrorKind}, 5 | }; 6 | #[cfg(not(test))] 7 | use rayon::prelude::*; 8 | use std::convert::TryFrom; 9 | use zeroize::Zeroize; 10 | 11 | /// Represents the safe primes used in the modulus for the accumulator 12 | #[derive(Debug, Eq, PartialEq)] 13 | pub struct AccumulatorSecretKey { 14 | /// Must be a safe prime with MIN_SIZE_PRIME bits 15 | pub p: BigInteger, 16 | /// Must be a safe prime with MIN_SIZE_PRIME bits 17 | pub q: BigInteger, 18 | } 19 | 20 | impl AccumulatorSecretKey { 21 | /// Create a new Accumulator secret key by generating two 22 | /// 1024-bit safe primes 23 | pub fn new() -> Self { 24 | Self::default() 25 | } 26 | 27 | /// Compute p * q 28 | pub fn modulus(&self) -> BigInteger { 29 | &self.p * &self.q 30 | } 31 | 32 | /// Compute (p - 1) * (q - 1) 33 | pub fn totient(&self) -> BigInteger { 34 | (&self.p - &BigInteger::from(1u32)) * (&self.q - &BigInteger::from(1u32)) 35 | } 36 | 37 | /// Serialize to raw bytes 38 | pub fn to_bytes(&self) -> Vec { 39 | let mut t = b2fa(&self.p, FACTOR_SIZE); 40 | t.append(b2fa(&self.q, FACTOR_SIZE).as_mut()); 41 | t 42 | } 43 | } 44 | 45 | impl Default for AccumulatorSecretKey { 46 | fn default() -> Self { 47 | let (p, q) = gen_primes(); 48 | Self { p, q } 49 | } 50 | } 51 | 52 | impl Clone for AccumulatorSecretKey { 53 | fn clone(&self) -> Self { 54 | Self { 55 | p: self.p.clone(), 56 | q: self.q.clone(), 57 | } 58 | } 59 | } 60 | 61 | impl TryFrom<&[u8]> for AccumulatorSecretKey { 62 | type Error = AccumulatorError; 63 | 64 | fn try_from(data: &[u8]) -> Result { 65 | if data.len() != 2 * FACTOR_SIZE { 66 | return Err(AccumulatorError::from_msg( 67 | AccumulatorErrorKind::InvalidType, 68 | format!( 69 | "Invalid bytes, expected {}, got {}", 70 | 2 * FACTOR_SIZE, 71 | data.len() 72 | ), 73 | )); 74 | } 75 | let p = BigInteger::try_from(&data[..FACTOR_SIZE])?; 76 | let q = BigInteger::try_from(&data[FACTOR_SIZE..])?; 77 | Ok(Self { p, q }) 78 | } 79 | } 80 | 81 | impl TryFrom> for AccumulatorSecretKey { 82 | type Error = AccumulatorError; 83 | 84 | fn try_from(data: Vec) -> Result { 85 | Self::try_from(data.as_slice()) 86 | } 87 | } 88 | 89 | impl Zeroize for AccumulatorSecretKey { 90 | fn zeroize(&mut self) { 91 | self.p.zeroize(); 92 | self.q.zeroize(); 93 | } 94 | } 95 | 96 | impl Drop for AccumulatorSecretKey { 97 | fn drop(&mut self) { 98 | self.zeroize(); 99 | } 100 | } 101 | 102 | serdes_impl!(AccumulatorSecretKey); 103 | 104 | #[cfg(not(test))] 105 | fn gen_primes() -> (BigInteger, BigInteger) { 106 | use crate::MIN_SIZE_PRIME; 107 | let mut p: Vec = (0..2) 108 | .collect::>() 109 | .par_iter() 110 | .map(|_| BigInteger::generate_safe_prime(MIN_SIZE_PRIME)) 111 | .collect(); 112 | let p1 = p.remove(0); 113 | let p2 = p.remove(0); 114 | (p1, p2) 115 | } 116 | 117 | #[cfg(test)] 118 | fn gen_primes() -> (BigInteger, BigInteger) { 119 | // Taken from https://github.com/mikelodder7/cunningham_chain/blob/master/findings.md 120 | // because AccumulatorSecretKey::default() takes a long time 121 | let p = BigInteger::from("132590288326793330806752358172617836030510421524323425886695490513600853466362871997907908739315399849138190997738786757721539635477379820932279026029679011350046717599386392663749253953274352000157227488895139775977945940993648470523136879899410690348931562489237825925601577159953591977449106730133820825719"); 122 | let q = BigInteger::from("149253707427499607752440533538420296779167710000842829107795675900185486091323606384260179778233711456748787559527972657213022998726578510459854530854900733457277643303592216900588246498239579922221956281290954735600574251392801029419096160964874150455156365996536205549377586240264971604869515447059744740119"); 123 | (p, q) 124 | } 125 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/tests/engine.rs: -------------------------------------------------------------------------------- 1 | use crate::{CurveAffine, CurveProjective, Engine, Field, PrimeField}; 2 | use rand_core::SeedableRng; 3 | 4 | pub fn engine_tests() { 5 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 6 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 7 | 0xe5, 8 | ]); 9 | for _ in 0..10 { 10 | let a = E::G1::random(&mut rng).into_affine(); 11 | let b = E::G2::random(&mut rng).into_affine(); 12 | 13 | assert!(a.pairing_with(&b) == b.pairing_with(&a)); 14 | assert!(a.pairing_with(&b) == E::pairing(a, b)); 15 | } 16 | 17 | for _ in 0..1000 { 18 | let z1 = E::G1Affine::zero().prepare(); 19 | let z2 = E::G2Affine::zero().prepare(); 20 | 21 | let a = E::G1::random(&mut rng).into_affine().prepare(); 22 | let b = E::G2::random(&mut rng).into_affine().prepare(); 23 | let c = E::G1::random(&mut rng).into_affine().prepare(); 24 | let d = E::G2::random(&mut rng).into_affine().prepare(); 25 | 26 | assert_eq!( 27 | E::Fqk::one(), 28 | E::final_exponentiation(&E::miller_loop(&[(&z1, &b)])).unwrap() 29 | ); 30 | 31 | assert_eq!( 32 | E::Fqk::one(), 33 | E::final_exponentiation(&E::miller_loop(&[(&a, &z2)])).unwrap() 34 | ); 35 | 36 | assert_eq!( 37 | E::final_exponentiation(&E::miller_loop(&[(&z1, &b), (&c, &d)])).unwrap(), 38 | E::final_exponentiation(&E::miller_loop(&[(&a, &z2), (&c, &d)])).unwrap() 39 | ); 40 | 41 | assert_eq!( 42 | E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&z1, &d)])).unwrap(), 43 | E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&c, &z2)])).unwrap() 44 | ); 45 | } 46 | 47 | random_bilinearity_tests::(); 48 | random_miller_loop_tests::(); 49 | } 50 | 51 | fn random_miller_loop_tests() { 52 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 53 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 54 | 0xe5, 55 | ]); 56 | // Exercise the miller loop for a reduced pairing 57 | for _ in 0..1000 { 58 | let a = E::G1::random(&mut rng); 59 | let b = E::G2::random(&mut rng); 60 | 61 | let p2 = E::pairing(a, b); 62 | 63 | let a = a.into_affine().prepare(); 64 | let b = b.into_affine().prepare(); 65 | 66 | let p1 = E::final_exponentiation(&E::miller_loop(&[(&a, &b)])).unwrap(); 67 | 68 | assert_eq!(p1, p2); 69 | } 70 | 71 | // Exercise a double miller loop 72 | for _ in 0..1000 { 73 | let a = E::G1::random(&mut rng); 74 | let b = E::G2::random(&mut rng); 75 | let c = E::G1::random(&mut rng); 76 | let d = E::G2::random(&mut rng); 77 | 78 | let ab = E::pairing(a, b); 79 | let cd = E::pairing(c, d); 80 | 81 | let mut abcd = ab; 82 | abcd.mul_assign(&cd); 83 | 84 | let a = a.into_affine().prepare(); 85 | let b = b.into_affine().prepare(); 86 | let c = c.into_affine().prepare(); 87 | let d = d.into_affine().prepare(); 88 | 89 | let abcd_with_double_loop = 90 | E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&c, &d)])).unwrap(); 91 | 92 | assert_eq!(abcd, abcd_with_double_loop); 93 | } 94 | } 95 | 96 | fn random_bilinearity_tests() { 97 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 98 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 99 | 0xe5, 100 | ]); 101 | for _ in 0..1000 { 102 | let a = E::G1::random(&mut rng); 103 | let b = E::G2::random(&mut rng); 104 | 105 | let c = E::Fr::random(&mut rng); 106 | let d = E::Fr::random(&mut rng); 107 | 108 | let mut ac = a; 109 | ac.mul_assign(c); 110 | 111 | let mut ad = a; 112 | ad.mul_assign(d); 113 | 114 | let mut bc = b; 115 | bc.mul_assign(c); 116 | 117 | let mut bd = b; 118 | bd.mul_assign(d); 119 | 120 | let acbd = E::pairing(ac, bd); 121 | let adbc = E::pairing(ad, bc); 122 | 123 | let mut cd = c; 124 | cd.mul_assign(&d); 125 | 126 | let abcd = E::pairing(a, b).pow(cd.into_repr()); 127 | 128 | assert_eq!(acbd, adbc); 129 | assert_eq!(acbd, abcd); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/benches/bls12_381/ec.rs: -------------------------------------------------------------------------------- 1 | mod g1 { 2 | use ff::Field; 3 | use pairing::bls12_381::*; 4 | use pairing::CurveProjective; 5 | use rand_core::SeedableRng; 6 | use rand_xorshift::XorShiftRng; 7 | #[bench] 8 | fn bench_g1_mul_assign(b: &mut ::test::Bencher) { 9 | const SAMPLES: usize = 1000; 10 | 11 | let mut rng = XorShiftRng::from_seed([ 12 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 13 | 0xbc, 0xe5, 14 | ]); 15 | let v: Vec<(G1, Fr)> = (0..SAMPLES) 16 | .map(|_| (G1::random(&mut rng), Fr::random(&mut rng))) 17 | .collect(); 18 | 19 | let mut count = 0; 20 | b.iter(|| { 21 | let mut tmp = v[count].0; 22 | tmp.mul_assign(v[count].1); 23 | count = (count + 1) % SAMPLES; 24 | tmp 25 | }); 26 | } 27 | 28 | #[bench] 29 | fn bench_g1_add_assign(b: &mut ::test::Bencher) { 30 | const SAMPLES: usize = 1000; 31 | 32 | let mut rng = XorShiftRng::from_seed([ 33 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 34 | 0xbc, 0xe5, 35 | ]); 36 | let v: Vec<(G1, G1)> = (0..SAMPLES) 37 | .map(|_| (G1::random(&mut rng), G1::random(&mut rng))) 38 | .collect(); 39 | 40 | let mut count = 0; 41 | b.iter(|| { 42 | let mut tmp = v[count].0; 43 | tmp.add_assign(&v[count].1); 44 | count = (count + 1) % SAMPLES; 45 | tmp 46 | }); 47 | } 48 | 49 | #[bench] 50 | fn bench_g1_add_assign_mixed(b: &mut ::test::Bencher) { 51 | const SAMPLES: usize = 1000; 52 | 53 | let mut rng = XorShiftRng::from_seed([ 54 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 55 | 0xbc, 0xe5, 56 | ]); 57 | let v: Vec<(G1, G1Affine)> = (0..SAMPLES) 58 | .map(|_| (G1::random(&mut rng), G1::random(&mut rng).into())) 59 | .collect(); 60 | 61 | let mut count = 0; 62 | b.iter(|| { 63 | let mut tmp = v[count].0; 64 | tmp.add_assign_mixed(&v[count].1); 65 | count = (count + 1) % SAMPLES; 66 | tmp 67 | }); 68 | } 69 | } 70 | 71 | mod g2 { 72 | use ff::Field; 73 | use pairing::bls12_381::*; 74 | use pairing::CurveProjective; 75 | use rand_core::SeedableRng; 76 | use rand_xorshift::XorShiftRng; 77 | #[bench] 78 | fn bench_g2_mul_assign(b: &mut ::test::Bencher) { 79 | const SAMPLES: usize = 1000; 80 | 81 | let mut rng = XorShiftRng::from_seed([ 82 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 83 | 0xbc, 0xe5, 84 | ]); 85 | let v: Vec<(G2, Fr)> = (0..SAMPLES) 86 | .map(|_| (G2::random(&mut rng), Fr::random(&mut rng))) 87 | .collect(); 88 | 89 | let mut count = 0; 90 | b.iter(|| { 91 | let mut tmp = v[count].0; 92 | tmp.mul_assign(v[count].1); 93 | count = (count + 1) % SAMPLES; 94 | tmp 95 | }); 96 | } 97 | 98 | #[bench] 99 | fn bench_g2_add_assign(b: &mut ::test::Bencher) { 100 | const SAMPLES: usize = 1000; 101 | 102 | let mut rng = XorShiftRng::from_seed([ 103 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 104 | 0xbc, 0xe5, 105 | ]); 106 | let v: Vec<(G2, G2)> = (0..SAMPLES) 107 | .map(|_| (G2::random(&mut rng), G2::random(&mut rng))) 108 | .collect(); 109 | 110 | let mut count = 0; 111 | b.iter(|| { 112 | let mut tmp = v[count].0; 113 | tmp.add_assign(&v[count].1); 114 | count = (count + 1) % SAMPLES; 115 | tmp 116 | }); 117 | } 118 | 119 | #[bench] 120 | fn bench_g2_add_assign_mixed(b: &mut ::test::Bencher) { 121 | const SAMPLES: usize = 1000; 122 | 123 | let mut rng = XorShiftRng::from_seed([ 124 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 125 | 0xbc, 0xe5, 126 | ]); 127 | let v: Vec<(G2, G2Affine)> = (0..SAMPLES) 128 | .map(|_| (G2::random(&mut rng), G2::random(&mut rng).into())) 129 | .collect(); 130 | 131 | let mut count = 0; 132 | b.iter(|| { 133 | let mut tmp = v[count].0; 134 | tmp.add_assign_mixed(&v[count].1); 135 | count = (count + 1) % SAMPLES; 136 | tmp 137 | }); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/hash_to_field.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | This module implements hash_to_field and related hashing primitives 3 | for use with BLS signatures. 4 | */ 5 | 6 | use digest::generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; 7 | use digest::{BlockInput, Digest, ExtendableOutput, Update}; 8 | use std::marker::PhantomData; 9 | 10 | /// hash_to_field for type T using ExpandMsg variant X 11 | pub fn hash_to_field(msg: &[u8], dst: &[u8], count: usize) -> Vec 12 | where 13 | T: FromRO, 14 | X: ExpandMsg, 15 | { 16 | let len_per_elm = ::Length::to_usize(); 17 | let len_in_bytes = count * len_per_elm; 18 | let pseudo_random_bytes = X::expand_message(msg, dst, len_in_bytes); 19 | 20 | let mut ret = Vec::::with_capacity(count); 21 | for idx in 0..count { 22 | let bytes_to_convert = &pseudo_random_bytes[idx * len_per_elm..(idx + 1) * len_per_elm]; 23 | let bytes_arr = GenericArray::::Length>::from_slice(bytes_to_convert); 24 | ret.push(T::from_ro(bytes_arr)); 25 | } 26 | 27 | ret 28 | } 29 | 30 | /// Generate a field element from a random string of bytes 31 | pub trait FromRO { 32 | type Length: ArrayLength; 33 | 34 | fn from_ro(okm: &GenericArray::Length>) -> Self; 35 | } 36 | 37 | /// BaseFromRO is a FromRO impl for a field with extension degree 1. 38 | impl FromRO for T { 39 | type Length = ::BaseLength; 40 | 41 | fn from_ro(okm: &GenericArray::Length>) -> T { 42 | T::from_okm(okm) 43 | } 44 | } 45 | 46 | /// Generate an element of a base field for a random string of bytes 47 | /// (used by FromRO for extension fields). 48 | pub trait BaseFromRO { 49 | type BaseLength: ArrayLength; 50 | 51 | fn from_okm(okm: &GenericArray::BaseLength>) -> Self; 52 | } 53 | 54 | /// Trait for types implementing expand_message interface for hash_to_field 55 | pub trait ExpandMsg { 56 | fn expand_message(msg: &[u8], dst: &[u8], len_in_bytes: usize) -> Vec; 57 | } 58 | 59 | /// Placeholder type for implementing expand_message_xof based on a hash function 60 | #[derive(Debug)] 61 | pub struct ExpandMsgXof { 62 | phantom: PhantomData, 63 | } 64 | 65 | /// ExpandMsgXof implements expand_message_xof for the ExpandMsg trait 66 | impl ExpandMsg for ExpandMsgXof 67 | where 68 | HashT: Default + ExtendableOutput + Update, 69 | { 70 | fn expand_message(msg: &[u8], dst: &[u8], len_in_bytes: usize) -> Vec { 71 | HashT::default() 72 | .chain(msg) 73 | .chain([(len_in_bytes >> 8) as u8, len_in_bytes as u8]) 74 | .chain(dst) 75 | .chain([dst.len() as u8]) 76 | .finalize_boxed(len_in_bytes) 77 | .to_vec() 78 | } 79 | } 80 | 81 | /// Placeholder type for implementing expand_message_xmd based on a hash function 82 | #[derive(Debug)] 83 | pub struct ExpandMsgXmd { 84 | phantom: PhantomData, 85 | } 86 | 87 | /// ExpandMsgXmd implements expand_message_xmd for the ExpandMsg trait 88 | impl ExpandMsg for ExpandMsgXmd 89 | where 90 | HashT: Digest + BlockInput, 91 | { 92 | fn expand_message(msg: &[u8], dst: &[u8], len_in_bytes: usize) -> Vec { 93 | let b_in_bytes = ::OutputSize::to_usize(); 94 | let ell = (len_in_bytes + b_in_bytes - 1) / b_in_bytes; 95 | if ell > 255 { 96 | panic!("ell was too big in expand_message_xmd"); 97 | } 98 | let b_0 = HashT::new() 99 | .chain(GenericArray::::BlockSize>::default()) 100 | .chain(msg) 101 | .chain([(len_in_bytes >> 8) as u8, len_in_bytes as u8, 0u8]) 102 | .chain(dst) 103 | .chain([dst.len() as u8]) 104 | .finalize(); 105 | 106 | let mut b_vals = Vec::::with_capacity(ell * b_in_bytes); 107 | // b_1 108 | b_vals.extend_from_slice( 109 | HashT::new() 110 | .chain(&b_0[..]) 111 | .chain([1u8]) 112 | .chain(dst) 113 | .chain([dst.len() as u8]) 114 | .finalize() 115 | .as_ref(), 116 | ); 117 | 118 | for idx in 1..ell { 119 | // b_0 XOR b_(idx - 1) 120 | let mut tmp = GenericArray::::OutputSize>::default(); 121 | b_0.iter() 122 | .zip(&b_vals[(idx - 1) * b_in_bytes..idx * b_in_bytes]) 123 | .enumerate() 124 | .for_each(|(jdx, (b0val, bi1val))| tmp[jdx] = b0val ^ bi1val); 125 | b_vals.extend_from_slice( 126 | HashT::new() 127 | .chain(tmp) 128 | .chain([(idx + 1) as u8]) 129 | .chain(dst) 130 | .chain([dst.len() as u8]) 131 | .finalize() 132 | .as_ref(), 133 | ); 134 | } 135 | 136 | b_vals.truncate(len_in_bytes); 137 | b_vals 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /accumulator-rsa/src/proofnon.rs: -------------------------------------------------------------------------------- 1 | use crate::{accumulator::Accumulator, b2fa, nonwitness::NonMembershipWitness, Poke2Proof, FACTOR_SIZE, MEMBER_SIZE}; 2 | use common::{bigint::BigInteger, error::*, Field}; 3 | use std::convert::TryFrom; 4 | 5 | /// A proof of knowledge of exponents non-membership proof 6 | #[derive(Debug, Eq, PartialEq, Clone)] 7 | pub struct NonMembershipProof { 8 | v: BigInteger, 9 | r: BigInteger, 10 | q: BigInteger, 11 | z: BigInteger, 12 | proof_g: Poke2Proof, 13 | } 14 | 15 | impl NonMembershipProof { 16 | /// Create 2 new PoKE2 proofs 17 | pub fn new>( 18 | witness: &NonMembershipWitness, 19 | accumulator: &Accumulator, 20 | nonce: B, 21 | ) -> Self { 22 | let nonce = nonce.as_ref(); 23 | let f = Field::new(&accumulator.modulus); 24 | let v = f.exp(&accumulator.value, &witness.a); 25 | 26 | let gv_inv = f.mul(&f.inv(&accumulator.generator), &v); 27 | #[cfg(debug_assertions)] 28 | Self::check_witness(witness, accumulator); 29 | 30 | debug_assert_eq!(gv_inv, witness.b.mod_exp(&witness.x, &accumulator.modulus)); 31 | 32 | let proof_v = Poke2Proof::new(&witness.a, &accumulator.value, &v, &accumulator.modulus, nonce); 33 | let proof_g = Poke2Proof::new(&witness.x, &witness.b, &gv_inv, &accumulator.modulus, nonce); 34 | Self { 35 | v, 36 | r: proof_v.r.clone(), 37 | q: proof_v.q.clone(), 38 | z: proof_v.z.clone(), 39 | proof_g, 40 | } 41 | } 42 | 43 | #[cfg(debug_assertions)] 44 | fn check_witness(witness: &NonMembershipWitness, accumulator: &Accumulator) { 45 | use rayon::prelude::*; 46 | 47 | let x_hat: BigInteger = accumulator.members.par_iter().product(); 48 | let gcd_res = x_hat.bezouts_coefficients(&witness.x); 49 | let expected_b = accumulator.generator.mod_inverse(&accumulator.modulus).mod_exp(&gcd_res.b, &accumulator.modulus); 50 | assert_eq!(expected_b, witness.b); 51 | } 52 | 53 | /// Verify a set membership proof 54 | pub fn verify>(&self, accumulator: &Accumulator, nonce: B) -> bool { 55 | let nonce = nonce.as_ref(); 56 | let f = Field::new(&accumulator.modulus); 57 | let gv_inv = f.mul(&f.inv(&accumulator.generator), &self.v); 58 | // Copy the latest value of the accumulator so the proof will fail if 59 | // the accumulator value has changed since the proof was created 60 | let proof_v = Poke2Proof { 61 | u: accumulator.value.clone(), 62 | r: self.r.clone(), 63 | q: self.q.clone(), 64 | z: self.z.clone(), 65 | }; 66 | let v_res = proof_v.verify(&self.v, &accumulator.modulus, nonce); 67 | let g_res = self.proof_g.verify( &gv_inv, &accumulator.modulus, nonce); 68 | g_res && v_res 69 | } 70 | 71 | /// Serialize this to bytes 72 | pub fn to_bytes(&self) -> Vec { 73 | let mut output = b2fa(&self.v, 2 * FACTOR_SIZE); 74 | output.append(&mut b2fa(&self.z, 2 * FACTOR_SIZE)); 75 | output.append(&mut b2fa(&self.q, 2 * FACTOR_SIZE)); 76 | output.append(&mut b2fa(&self.r, MEMBER_SIZE)); 77 | output.append(&mut self.proof_g.to_bytes()); 78 | output 79 | } 80 | } 81 | 82 | impl TryFrom<&[u8]> for NonMembershipProof { 83 | type Error = AccumulatorError; 84 | 85 | fn try_from(data: &[u8]) -> Result { 86 | if data.len() != Poke2Proof::SIZE_BYTES * 2 + 2 * FACTOR_SIZE { 87 | return Err(AccumulatorErrorKind::SerializationError.into()); 88 | } 89 | let mut offset = 2*FACTOR_SIZE; 90 | let v = BigInteger::try_from(&data[..offset])?; 91 | let mut end = offset + 2*FACTOR_SIZE; 92 | let z = BigInteger::try_from(&data[offset..end])?; 93 | 94 | offset = end; 95 | end = offset + 2*FACTOR_SIZE; 96 | 97 | let q = BigInteger::try_from(&data[offset..end])?; 98 | 99 | offset = end; 100 | end = offset + MEMBER_SIZE; 101 | 102 | let r = BigInteger::try_from(&data[offset..end])?; 103 | 104 | // let proof_v = Poke2Proof::try_from(&data[offset..end])?; 105 | let proof_g = Poke2Proof::try_from(&data[end..])?; 106 | Ok(Self { 107 | v, 108 | z, 109 | q, 110 | r, 111 | proof_g, 112 | }) 113 | } 114 | } 115 | 116 | serdes_impl!(NonMembershipProof); 117 | 118 | #[cfg(test)] 119 | mod tests { 120 | use super::*; 121 | use crate::key::SecretKey; 122 | 123 | #[test] 124 | fn proof_test() { 125 | let key = SecretKey::default(); 126 | let members: Vec<[u8; 8]> = vec![ 127 | 3u64.to_be_bytes(), 128 | 7u64.to_be_bytes(), 129 | 11u64.to_be_bytes(), 130 | 13u64.to_be_bytes(), 131 | ]; 132 | let member = 17u64.to_be_bytes(); 133 | let mut acc = Accumulator::with_members(&key, &members); 134 | let witness = NonMembershipWitness::new(&acc, &member).unwrap(); 135 | let nonce = b"proof_test"; 136 | 137 | let proof = NonMembershipProof::new(&witness, &acc, nonce); 138 | assert!(proof.verify(&acc, nonce)); 139 | acc += 17u64; 140 | 141 | assert!(!proof.verify(&acc, nonce)); 142 | assert_eq!( 143 | proof.to_bytes().len(), 144 | 2 * Poke2Proof::SIZE_BYTES 145 | ); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/fq12.rs: -------------------------------------------------------------------------------- 1 | use super::fq::FROBENIUS_COEFF_FQ12_C1; 2 | use super::fq2::Fq2; 3 | use super::fq6::Fq6; 4 | use ff::Field; 5 | use rand_core::RngCore; 6 | 7 | /// An element of Fq12, represented by c0 + c1 * w. 8 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 9 | pub struct Fq12 { 10 | pub c0: Fq6, 11 | pub c1: Fq6, 12 | } 13 | 14 | impl ::std::fmt::Display for Fq12 { 15 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 16 | write!(f, "Fq12({} + {} * w)", self.c0, self.c1) 17 | } 18 | } 19 | 20 | impl Fq12 { 21 | pub fn conjugate(&mut self) { 22 | self.c1.negate(); 23 | } 24 | 25 | pub fn mul_by_014(&mut self, c0: &Fq2, c1: &Fq2, c4: &Fq2) { 26 | let mut aa = self.c0; 27 | aa.mul_by_01(c0, c1); 28 | let mut bb = self.c1; 29 | bb.mul_by_1(c4); 30 | let mut o = *c1; 31 | o.add_assign(c4); 32 | self.c1.add_assign(&self.c0); 33 | self.c1.mul_by_01(c0, &o); 34 | self.c1.sub_assign(&aa); 35 | self.c1.sub_assign(&bb); 36 | self.c0 = bb; 37 | self.c0.mul_by_nonresidue(); 38 | self.c0.add_assign(&aa); 39 | } 40 | } 41 | 42 | impl Field for Fq12 { 43 | fn random(rng: &mut R) -> Self { 44 | Fq12 { 45 | c0: Fq6::random(rng), 46 | c1: Fq6::random(rng), 47 | } 48 | } 49 | fn zero() -> Self { 50 | Fq12 { 51 | c0: Fq6::zero(), 52 | c1: Fq6::zero(), 53 | } 54 | } 55 | 56 | fn one() -> Self { 57 | Fq12 { 58 | c0: Fq6::one(), 59 | c1: Fq6::zero(), 60 | } 61 | } 62 | 63 | fn is_zero(&self) -> bool { 64 | self.c0.is_zero() && self.c1.is_zero() 65 | } 66 | 67 | fn double(&mut self) { 68 | self.c0.double(); 69 | self.c1.double(); 70 | } 71 | 72 | fn negate(&mut self) { 73 | self.c0.negate(); 74 | self.c1.negate(); 75 | } 76 | 77 | fn add_assign(&mut self, other: &Self) { 78 | self.c0.add_assign(&other.c0); 79 | self.c1.add_assign(&other.c1); 80 | } 81 | 82 | fn sub_assign(&mut self, other: &Self) { 83 | self.c0.sub_assign(&other.c0); 84 | self.c1.sub_assign(&other.c1); 85 | } 86 | 87 | fn frobenius_map(&mut self, power: usize) { 88 | self.c0.frobenius_map(power); 89 | self.c1.frobenius_map(power); 90 | 91 | self.c1.c0.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]); 92 | self.c1.c1.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]); 93 | self.c1.c2.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]); 94 | } 95 | 96 | fn square(&mut self) { 97 | let mut ab = self.c0; 98 | ab.mul_assign(&self.c1); 99 | let mut c0c1 = self.c0; 100 | c0c1.add_assign(&self.c1); 101 | let mut c0 = self.c1; 102 | c0.mul_by_nonresidue(); 103 | c0.add_assign(&self.c0); 104 | c0.mul_assign(&c0c1); 105 | c0.sub_assign(&ab); 106 | self.c1 = ab; 107 | self.c1.add_assign(&ab); 108 | ab.mul_by_nonresidue(); 109 | c0.sub_assign(&ab); 110 | self.c0 = c0; 111 | } 112 | 113 | fn mul_assign(&mut self, other: &Self) { 114 | let mut aa = self.c0; 115 | aa.mul_assign(&other.c0); 116 | let mut bb = self.c1; 117 | bb.mul_assign(&other.c1); 118 | let mut o = other.c0; 119 | o.add_assign(&other.c1); 120 | self.c1.add_assign(&self.c0); 121 | self.c1.mul_assign(&o); 122 | self.c1.sub_assign(&aa); 123 | self.c1.sub_assign(&bb); 124 | self.c0 = bb; 125 | self.c0.mul_by_nonresidue(); 126 | self.c0.add_assign(&aa); 127 | } 128 | 129 | fn inverse(&self) -> Option { 130 | let mut c0s = self.c0; 131 | c0s.square(); 132 | let mut c1s = self.c1; 133 | c1s.square(); 134 | c1s.mul_by_nonresidue(); 135 | c0s.sub_assign(&c1s); 136 | 137 | c0s.inverse().map(|t| { 138 | let mut tmp = Fq12 { c0: t, c1: t }; 139 | tmp.c0.mul_assign(&self.c0); 140 | tmp.c1.mul_assign(&self.c1); 141 | tmp.c1.negate(); 142 | 143 | tmp 144 | }) 145 | } 146 | } 147 | 148 | #[cfg(test)] 149 | use rand_core::SeedableRng; 150 | //use rand::{SeedableRng, XorShiftRng}; 151 | 152 | #[test] 153 | fn test_fq12_mul_by_014() { 154 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 155 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 156 | 0xe5, 157 | ]); 158 | for _ in 0..1000 { 159 | let c0 = Fq2::random(&mut rng); 160 | let c1 = Fq2::random(&mut rng); 161 | let c5 = Fq2::random(&mut rng); 162 | let mut a = Fq12::random(&mut rng); 163 | let mut b = a; 164 | 165 | a.mul_by_014(&c0, &c1, &c5); 166 | b.mul_assign(&Fq12 { 167 | c0: Fq6 { 168 | c0, 169 | c1, 170 | c2: Fq2::zero(), 171 | }, 172 | c1: Fq6 { 173 | c0: Fq2::zero(), 174 | c1: c5, 175 | c2: Fq2::zero(), 176 | }, 177 | }); 178 | 179 | assert_eq!(a, b); 180 | } 181 | } 182 | 183 | #[test] 184 | fn fq12_field_tests() { 185 | use ff::PrimeField; 186 | 187 | crate::tests::field::random_field_tests::(); 188 | crate::tests::field::random_frobenius_tests::(super::fq::Fq::char(), 13); 189 | } 190 | -------------------------------------------------------------------------------- /accumulator-ecc/accumulator/src/key.rs: -------------------------------------------------------------------------------- 1 | use crate::{accumulator::Element, generate_fr, BigArray, Polynomial}; 2 | use ff_zeroize::{Field, PrimeField}; 3 | use pairings::{ 4 | bls12_381::{Fr, FrRepr, G2}, 5 | serdes::SerDes, 6 | CurveProjective, 7 | }; 8 | use serde::{Deserialize, Serialize}; 9 | use std::convert::TryFrom; 10 | use zeroize::Zeroize; 11 | 12 | struct_impl!( 13 | /// Represents \alpha (secret key) on page 6 in 14 | /// 15 | #[derive(Clone, Debug, Zeroize)] 16 | #[zeroize(drop)] 17 | SecretKey, 18 | SecretKeyInner, 19 | Fr 20 | ); 21 | 22 | impl SecretKey { 23 | pub const BYTES: usize = 32; 24 | 25 | /// Create a new secret key 26 | pub fn new(seed: Option<&[u8]>) -> Self { 27 | // Giuseppe Vitto, Alex Biryukov = VB 28 | // Accumulator = ACC 29 | Self(generate_fr(b"VB-ACC-KEYGEN-SALT-", seed)) 30 | } 31 | 32 | /// Return the raw byte representation of the key 33 | pub fn to_bytes(&self) -> [u8; Self::BYTES] { 34 | let mut o = [0u8; Self::BYTES]; 35 | self.0.serialize(&mut o.as_mut(), true).unwrap(); 36 | o 37 | } 38 | 39 | pub fn batch_additions(&self, additions: &[Element]) -> Element { 40 | Element( 41 | additions 42 | .iter() 43 | .map(|v| { 44 | let mut vv = v.0; 45 | vv.add_assign(&self.0); 46 | vv 47 | }) 48 | .fold(Fr::one(), |mut a, y| { 49 | a.mul_assign(&y); 50 | a 51 | }), 52 | ) 53 | } 54 | 55 | pub fn batch_deletions(&self, deletions: &[Element]) -> Element { 56 | Element(self.batch_additions(deletions).0.inverse().unwrap()) 57 | } 58 | 59 | /// Create the Batch Polynomial coefficients 60 | pub fn create_coefficients( 61 | &self, 62 | additions: &[Element], 63 | deletions: &[Element], 64 | ) -> Vec { 65 | // vD(x) = ∑^{m}_{s=1}{ ∏ 1..s {yD_i + alpha}^-1 ∏ 1 ..s-1 {yD_j - x} 66 | let one = Fr::from_repr(FrRepr::from(1u64)).unwrap(); 67 | let mut m1 = one; 68 | m1.negate(); 69 | let mut v_d = Polynomial::with_capacity(deletions.len()); 70 | for s in 0..deletions.len() { 71 | // ∏ 1..s (yD_i + alpha)^-1 72 | let c = self.batch_deletions(&deletions[0..s + 1]).0; 73 | let mut poly = Polynomial::new(); 74 | poly.push(one); 75 | // ∏ 1..(s-1) (yD_j - x) 76 | for j in 0..s { 77 | let mut t = Polynomial::new(); 78 | t.push(deletions[j].0); 79 | t.push(m1); 80 | poly *= t; 81 | } 82 | poly *= c; 83 | v_d += poly; 84 | } 85 | 86 | //v_d(x) * ∏ 1..n (yA_i + alpha) 87 | v_d *= self.batch_additions(additions).0; 88 | 89 | // vA(x) = ∑^n_{s=1}{ ∏ 1..s-1 {yA_i + alpha} ∏ s+1..n {yA_j - x} } 90 | let mut v_a = Polynomial::with_capacity(additions.len()); 91 | for s in 0..additions.len() { 92 | // ∏ 1..s-1 {yA_i + alpha} 93 | let c = if s == 0 { 94 | one 95 | } else { 96 | self.batch_additions(&additions[0..s]).0 97 | }; 98 | let mut poly = Polynomial::new(); 99 | poly.push(one); 100 | // ∏ s+1..n {yA_j - x} 101 | for j in (s + 1)..additions.len() { 102 | let mut t = Polynomial::new(); 103 | t.push(additions[j].0); 104 | t.push(m1); 105 | poly *= t; 106 | } 107 | poly *= c; 108 | v_a += poly; 109 | } 110 | // vA - vD 111 | v_a -= v_d; 112 | 113 | v_a.0.iter().map(|b| Element(*b)).collect() 114 | } 115 | } 116 | 117 | struct_impl!( 118 | /// Represents \overline{Q} = \overline{P}*\alpha (public key) on page 6 in 119 | /// 120 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 121 | PublicKey, 122 | PublicKeyInner, 123 | G2 124 | ); 125 | display_impl!(PublicKey); 126 | 127 | impl PublicKey { 128 | pub const BYTES: usize = 96; 129 | 130 | pub fn to_bytes(&self) -> [u8; Self::BYTES] { 131 | let mut d = [0u8; Self::BYTES]; 132 | self.0.serialize(&mut d.as_mut(), true).unwrap(); 133 | d 134 | } 135 | } 136 | 137 | impl From<&SecretKey> for PublicKey { 138 | fn from(sk: &SecretKey) -> Self { 139 | let mut g2 = G2::one(); 140 | g2.mul_assign(sk.0); 141 | Self(g2) 142 | } 143 | } 144 | 145 | #[cfg(test)] 146 | mod tests { 147 | use super::*; 148 | use pairings::{bls12_381::G1, CurveProjective}; 149 | 150 | #[test] 151 | fn batch_test() { 152 | let key = SecretKey::new(None); 153 | let data = vec![Element::hash(b"value1"), Element::hash(b"value2")]; 154 | let add = key.batch_additions(data.as_slice()); 155 | let del = key.batch_deletions(data.as_slice()); 156 | let mut res = add.0; 157 | res.mul_assign(&del.0); 158 | assert_eq!(res, Fr::one()); 159 | 160 | let mut g1 = G1::one(); 161 | g1.mul_assign(add.0); 162 | g1.mul_assign(del.0); 163 | assert_eq!(g1, G1::one()); 164 | 165 | g1.mul_assign(res); 166 | assert_eq!(g1, G1::one()); 167 | } 168 | 169 | #[test] 170 | fn coefficient_test() { 171 | let key = SecretKey::new(Some(b"1234567890")); 172 | let data = vec![ 173 | Element::hash(b"1"), 174 | Element::hash(b"2"), 175 | Element::hash(b"3"), 176 | Element::hash(b"4"), 177 | Element::hash(b"5"), 178 | ]; 179 | let coefficients = key.create_coefficients(&data[0..2], &data[2..5]); 180 | assert_eq!(coefficients.len(), 3); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/README.md: -------------------------------------------------------------------------------- 1 | # BLS12-381 2 | 3 | This is an implementation of the BLS12-381 pairing-friendly elliptic curve construction. 4 | 5 | ## BLS12 Parameterization 6 | 7 | BLS12 curves are parameterized by a value *x* such that the base field modulus *q* and subgroup *r* can be computed by: 8 | 9 | * q = (x - 1)2 ((x4 - x2 + 1) / 3) + x 10 | * r = (x4 - x2 + 1) 11 | 12 | Given primes *q* and *r* parameterized as above, we can easily construct an elliptic curve over the prime field F*q* which contains a subgroup of order *r* such that *r* | (*q*12 - 1), giving it an embedding degree of 12. Instantiating its sextic twist over an extension field Fq2 gives rise to an efficient bilinear pairing function between elements of the order *r* subgroups of either curves, into an order *r* multiplicative subgroup of Fq12. 13 | 14 | In zk-SNARK schemes, we require Fr with large 2n roots of unity for performing efficient fast-fourier transforms. As such, guaranteeing that large 2n | (r - 1), or equivalently that *x* has a large 2n factor, gives rise to BLS12 curves suitable for zk-SNARKs. 15 | 16 | Due to recent research, it is estimated by many that *q* should be approximately 384 bits to target 128-bit security. Conveniently, *r* is approximately 256 bits when *q* is approximately 384 bits, making BLS12 curves ideal for 128-bit security. It also makes them ideal for many zk-SNARK applications, as the scalar field can be used for keying material such as embedded curve constructions. 17 | 18 | Many curves match our descriptions, but we require some extra properties for efficiency purposes: 19 | 20 | * *q* should be smaller than 2383, and *r* should be smaller than 2255, so that the most significant bit is unset when using 64-bit or 32-bit limbs. This allows for cheap reductions. 21 | * Fq12 is typically constructed using towers of extension fields. As a byproduct of [research](https://eprint.iacr.org/2011/465.pdf) for BLS curves of embedding degree 24, we can identify subfamilies of BLS12 curves (for our purposes, where x mod 72 = {16, 64}) that produce efficient extension field towers and twisting isomorphisms. 22 | * We desire *x* of small Hamming weight, to increase the performance of the pairing function. 23 | 24 | ## BLS12-381 Instantiation 25 | 26 | The BLS12-381 construction is instantiated by `x = -0xd201000000010000`, which produces the largest `q` and smallest Hamming weight of `x` that meets the above requirements. This produces: 27 | 28 | * q = `0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab` (381 bits) 29 | * r = `0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001` (255 bits) 30 | 31 | Our extension field tower is constructed as follows: 32 | 33 | 1. Fq2 is constructed as Fq(u) / (u2 - β) where β = -1. 34 | 2. Fq6 is constructed as Fq2(v) / (v3 - ξ) where ξ = u + 1 35 | 3. Fq12 is constructed as Fq6(w) / (w2 - γ) where γ = v 36 | 37 | Now, we instantiate the elliptic curve E(Fq) : y2 = x3 + 4, and the elliptic curve E'(Fq2) : y2 = x3 + 4(u + 1). 38 | 39 | The group G1 is the *r* order subgroup of E, which has cofactor (x - 1)2 / 3. The group G2 is the *r* order subgroup of E', which has cofactor (x8 - 4x7 + 5x6 - 4x4 + 6x3 - 4x2 - 4x + 13) / 9. 40 | 41 | ### Generators 42 | 43 | The generators of G1 and G2 are computed by finding the lexicographically smallest valid `x`-coordinate, and its lexicographically smallest `y`-coordinate and scaling it by the cofactor such that the result is not the point at infinity. 44 | 45 | #### G1 46 | 47 | ``` 48 | x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 49 | y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 50 | ``` 51 | 52 | #### G2 53 | 54 | ``` 55 | x = 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758*u + 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 56 | y = 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582*u + 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 57 | ``` 58 | 59 | ### Serialization 60 | 61 | * Fq elements are encoded in big-endian form. They occupy 48 bytes in this form. 62 | * Fq2 elements are encoded in big-endian form, meaning that the Fq element c0 + c1 * u is represented by the Fq element c1 followed by the Fq element c0. This means Fq2 elements occupy 96 bytes in this form. 63 | * The group G1 uses Fq elements for coordinates. The group G2 uses Fq2 elements for coordinates. 64 | * G1 and G2 elements can be encoded in uncompressed form (the x-coordinate followed by the y-coordinate) or in compressed form (just the x-coordinate). G1 elements occupy 96 bytes in uncompressed form, and 48 bytes in compressed form. G2 elements occupy 192 bytes in uncompressed form, and 96 bytes in compressed form. 65 | 66 | The most-significant three bits of a G1 or G2 encoding should be masked away before the coordinate(s) are interpreted. These bits are used to unambiguously represent the underlying element: 67 | 68 | * The most significant bit, when set, indicates that the point is in compressed form. Otherwise, the point is in uncompressed form. 69 | * The second-most significant bit indicates that the point is at infinity. If this bit is set, the remaining bits of the group element's encoding should be set to zero. 70 | * The third-most significant bit is set if (and only if) this point is in compressed form _and_ it is not the point at infinity _and_ its y-coordinate is the lexicographically largest of the two associated with the encoded x-coordinate. 71 | 72 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/wnaf.rs: -------------------------------------------------------------------------------- 1 | use super::{CurveProjective, PrimeField, PrimeFieldRepr}; 2 | 3 | /// Replaces the contents of `table` with a w-NAF window table for the given window size. 4 | pub(crate) fn wnaf_table(table: &mut Vec, mut base: G, window: usize) { 5 | table.truncate(0); 6 | table.reserve(1 << (window - 1)); 7 | 8 | let mut dbl = base; 9 | dbl.double(); 10 | 11 | for _ in 0..(1 << (window - 1)) { 12 | table.push(base); 13 | base.add_assign(&dbl); 14 | } 15 | } 16 | 17 | /// Replaces the contents of `wnaf` with the w-NAF representation of a scalar. 18 | pub(crate) fn wnaf_form(wnaf: &mut Vec, mut c: S, window: usize) { 19 | wnaf.truncate(0); 20 | 21 | while !c.is_zero() { 22 | let mut u; 23 | if c.is_odd() { 24 | u = (c.as_ref()[0] % (1 << (window + 1))) as i64; 25 | 26 | if u > (1 << window) { 27 | u -= 1 << (window + 1); 28 | } 29 | 30 | if u > 0 { 31 | c.sub_noborrow(&S::from(u as u64)); 32 | } else { 33 | c.add_nocarry(&S::from((-u) as u64)); 34 | } 35 | } else { 36 | u = 0; 37 | } 38 | 39 | wnaf.push(u); 40 | 41 | c.div2(); 42 | } 43 | } 44 | 45 | /// Performs w-NAF exponentiation with the provided window table and w-NAF form scalar. 46 | /// 47 | /// This function must be provided a `table` and `wnaf` that were constructed with 48 | /// the same window size; otherwise, it may panic or produce invalid results. 49 | pub(crate) fn wnaf_exp(table: &[G], wnaf: &[i64]) -> G { 50 | let mut result = G::zero(); 51 | 52 | let mut found_one = false; 53 | 54 | for n in wnaf.iter().rev() { 55 | if found_one { 56 | result.double(); 57 | } 58 | 59 | if *n != 0 { 60 | found_one = true; 61 | 62 | if *n > 0 { 63 | result.add_assign(&table[(n / 2) as usize]); 64 | } else { 65 | result.sub_assign(&table[((-n) / 2) as usize]); 66 | } 67 | } 68 | } 69 | 70 | result 71 | } 72 | 73 | /// A "w-ary non-adjacent form" exponentiation context. 74 | #[derive(Debug)] 75 | pub struct Wnaf { 76 | base: B, 77 | scalar: S, 78 | window_size: W, 79 | } 80 | 81 | impl Wnaf<(), Vec, Vec> { 82 | /// Construct a new wNAF context without allocating. 83 | pub fn new() -> Self { 84 | Wnaf { 85 | base: vec![], 86 | scalar: vec![], 87 | window_size: (), 88 | } 89 | } 90 | 91 | /// Given a base and a number of scalars, compute a window table and return a `Wnaf` object that 92 | /// can perform exponentiations with `.scalar(..)`. 93 | pub fn base(&mut self, base: G, num_scalars: usize) -> Wnaf> { 94 | // Compute the appropriate window size based on the number of scalars. 95 | let window_size = G::recommended_wnaf_for_num_scalars(num_scalars); 96 | 97 | // Compute a wNAF table for the provided base and window size. 98 | wnaf_table(&mut self.base, base, window_size); 99 | 100 | // Return a Wnaf object that immutably borrows the computed base storage location, 101 | // but mutably borrows the scalar storage location. 102 | Wnaf { 103 | base: &self.base[..], 104 | scalar: &mut self.scalar, 105 | window_size, 106 | } 107 | } 108 | 109 | /// Given a scalar, compute its wNAF representation and return a `Wnaf` object that can perform 110 | /// exponentiations with `.base(..)`. 111 | pub fn scalar( 112 | &mut self, 113 | scalar: <::Scalar as PrimeField>::Repr, 114 | ) -> Wnaf, &[i64]> { 115 | // Compute the appropriate window size for the scalar. 116 | let window_size = G::recommended_wnaf_for_scalar(scalar); 117 | 118 | // Compute the wNAF form of the scalar. 119 | wnaf_form(&mut self.scalar, scalar, window_size); 120 | 121 | // Return a Wnaf object that mutably borrows the base storage location, but 122 | // immutably borrows the computed wNAF form scalar location. 123 | Wnaf { 124 | base: &mut self.base, 125 | scalar: &self.scalar[..], 126 | window_size, 127 | } 128 | } 129 | } 130 | 131 | impl<'a, G: CurveProjective> Wnaf> { 132 | /// Constructs new space for the scalar representation while borrowing 133 | /// the computed window table, for sending the window table across threads. 134 | pub fn shared(&self) -> Wnaf> { 135 | Wnaf { 136 | base: self.base, 137 | scalar: vec![], 138 | window_size: self.window_size, 139 | } 140 | } 141 | } 142 | 143 | impl<'a, G: CurveProjective> Wnaf, &'a [i64]> { 144 | /// Constructs new space for the window table while borrowing 145 | /// the computed scalar representation, for sending the scalar representation 146 | /// across threads. 147 | pub fn shared(&self) -> Wnaf, &'a [i64]> { 148 | Wnaf { 149 | base: vec![], 150 | scalar: self.scalar, 151 | window_size: self.window_size, 152 | } 153 | } 154 | } 155 | 156 | impl> Wnaf { 157 | /// Performs exponentiation given a base. 158 | pub fn base(&mut self, base: G) -> G 159 | where 160 | B: AsMut>, 161 | { 162 | wnaf_table(self.base.as_mut(), base, self.window_size); 163 | wnaf_exp(self.base.as_mut(), self.scalar.as_ref()) 164 | } 165 | } 166 | 167 | impl>> Wnaf { 168 | /// Performs exponentiation given a scalar. 169 | pub fn scalar( 170 | &mut self, 171 | scalar: <::Scalar as PrimeField>::Repr, 172 | ) -> G 173 | where 174 | B: AsRef<[G]>, 175 | { 176 | wnaf_form(self.scalar.as_mut(), scalar, self.window_size); 177 | wnaf_exp(self.base.as_ref(), self.scalar.as_mut()) 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bn256/fq12.rs: -------------------------------------------------------------------------------- 1 | use super::fq::FROBENIUS_COEFF_FQ12_C1; 2 | use super::fq2::Fq2; 3 | use super::fq6::Fq6; 4 | use ff::Field; 5 | use rand_core::RngCore; 6 | 7 | /// An element of Fq12, represented by c0 + c1 * w. 8 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 9 | pub struct Fq12 { 10 | pub c0: Fq6, 11 | pub c1: Fq6, 12 | } 13 | 14 | impl ::std::fmt::Display for Fq12 { 15 | fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 16 | write!(f, "Fq12({} + {} * w)", self.c0, self.c1) 17 | } 18 | } 19 | 20 | // BN256 and BLS12 implementations should be the same 21 | // Defined over w^2 - v = 0 22 | 23 | impl Fq12 { 24 | pub fn conjugate(&mut self) { 25 | self.c1.negate(); 26 | } 27 | 28 | pub fn mul_by_014(&mut self, c0: &Fq2, c1: &Fq2, c4: &Fq2) { 29 | let mut aa = self.c0; 30 | aa.mul_by_01(c0, c1); 31 | let mut bb = self.c1; 32 | bb.mul_by_1(c4); 33 | let mut o = *c1; 34 | o.add_assign(c4); 35 | self.c1.add_assign(&self.c0); 36 | self.c1.mul_by_01(c0, &o); 37 | self.c1.sub_assign(&aa); 38 | self.c1.sub_assign(&bb); 39 | self.c0 = bb; 40 | self.c0.mul_by_nonresidue(); 41 | self.c0.add_assign(&aa); 42 | } 43 | // TODO make it hand optimized 44 | // // multiply by (c0, c1, c2) + (c3, c4, c5)*w where only c0, c3 and c4 are non-zero 45 | pub fn mul_by_034(&mut self, c0: &Fq2, c3: &Fq2, c4: &Fq2) { 46 | self.mul_assign(&Fq12 { 47 | c0: Fq6 { 48 | c0: *c0, 49 | c1: Fq2::zero(), 50 | c2: Fq2::zero(), 51 | }, 52 | c1: Fq6 { 53 | c0: *c3, 54 | c1: *c4, 55 | c2: Fq2::zero(), 56 | }, 57 | }); 58 | } 59 | } 60 | 61 | impl Field for Fq12 { 62 | fn random(rng: &mut R) -> Self { 63 | Fq12 { 64 | c0: Fq6::random(rng), 65 | c1: Fq6::random(rng), 66 | } 67 | } 68 | fn zero() -> Self { 69 | Fq12 { 70 | c0: Fq6::zero(), 71 | c1: Fq6::zero(), 72 | } 73 | } 74 | 75 | fn one() -> Self { 76 | Fq12 { 77 | c0: Fq6::one(), 78 | c1: Fq6::zero(), 79 | } 80 | } 81 | 82 | fn is_zero(&self) -> bool { 83 | self.c0.is_zero() && self.c1.is_zero() 84 | } 85 | 86 | fn double(&mut self) { 87 | self.c0.double(); 88 | self.c1.double(); 89 | } 90 | 91 | fn negate(&mut self) { 92 | self.c0.negate(); 93 | self.c1.negate(); 94 | } 95 | 96 | fn add_assign(&mut self, other: &Self) { 97 | self.c0.add_assign(&other.c0); 98 | self.c1.add_assign(&other.c1); 99 | } 100 | 101 | fn sub_assign(&mut self, other: &Self) { 102 | self.c0.sub_assign(&other.c0); 103 | self.c1.sub_assign(&other.c1); 104 | } 105 | 106 | fn frobenius_map(&mut self, power: usize) { 107 | self.c0.frobenius_map(power); 108 | self.c1.frobenius_map(power); 109 | 110 | self.c1.c0.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]); 111 | self.c1.c1.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]); 112 | self.c1.c2.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]); 113 | } 114 | 115 | fn square(&mut self) { 116 | let mut ab = self.c0; 117 | ab.mul_assign(&self.c1); 118 | let mut c0c1 = self.c0; 119 | c0c1.add_assign(&self.c1); 120 | let mut c0 = self.c1; 121 | c0.mul_by_nonresidue(); 122 | c0.add_assign(&self.c0); 123 | c0.mul_assign(&c0c1); 124 | c0.sub_assign(&ab); 125 | self.c1 = ab; 126 | self.c1.add_assign(&ab); 127 | ab.mul_by_nonresidue(); 128 | c0.sub_assign(&ab); 129 | self.c0 = c0; 130 | } 131 | 132 | fn mul_assign(&mut self, other: &Self) { 133 | let mut aa = self.c0; 134 | aa.mul_assign(&other.c0); 135 | let mut bb = self.c1; 136 | bb.mul_assign(&other.c1); 137 | let mut o = other.c0; 138 | o.add_assign(&other.c1); 139 | self.c1.add_assign(&self.c0); 140 | self.c1.mul_assign(&o); 141 | self.c1.sub_assign(&aa); 142 | self.c1.sub_assign(&bb); 143 | self.c0 = bb; 144 | self.c0.mul_by_nonresidue(); 145 | self.c0.add_assign(&aa); 146 | } 147 | 148 | fn inverse(&self) -> Option { 149 | let mut c0s = self.c0; 150 | c0s.square(); 151 | let mut c1s = self.c1; 152 | c1s.square(); 153 | c1s.mul_by_nonresidue(); 154 | c0s.sub_assign(&c1s); 155 | 156 | c0s.inverse().map(|t| { 157 | let mut tmp = Fq12 { c0: t, c1: t }; 158 | tmp.c0.mul_assign(&self.c0); 159 | tmp.c1.mul_assign(&self.c1); 160 | tmp.c1.negate(); 161 | 162 | tmp 163 | }) 164 | } 165 | } 166 | 167 | #[cfg(test)] 168 | use rand_core::SeedableRng; 169 | #[cfg(test)] 170 | use rand_xorshift::XorShiftRng; 171 | 172 | #[test] 173 | fn test_fq12_mul_by_014() { 174 | let mut rng = XorShiftRng::from_seed([0x5d, 0xbe, 0x62, 0x59, 0x8d, 0x31, 0x3d, 0x76, 0x32, 0x37, 0xdb, 0x17, 0xe5, 0xbc, 0x06, 0x54]); 175 | 176 | for _ in 0..1000 { 177 | let c0 = Fq2::random(&mut rng); 178 | let c1 = Fq2::random(&mut rng); 179 | let c5 = Fq2::random(&mut rng); 180 | let mut a = Fq12::random(&mut rng); 181 | let mut b = a; 182 | 183 | a.mul_by_014(&c0, &c1, &c5); 184 | b.mul_assign(&Fq12 { 185 | c0: Fq6 { 186 | c0, 187 | c1, 188 | c2: Fq2::zero(), 189 | }, 190 | c1: Fq6 { 191 | c0: Fq2::zero(), 192 | c1: c5, 193 | c2: Fq2::zero(), 194 | }, 195 | }); 196 | 197 | assert_eq!(a, b); 198 | } 199 | } 200 | 201 | #[test] 202 | fn test_squaring() { 203 | let mut rng = XorShiftRng::from_seed([0x5d, 0xbe, 0x62, 0x59, 0x8d, 0x31, 0x3d, 0x76, 0x32, 0x37, 0xdb, 0x17, 0xe5, 0xbc, 0x06, 0x54]); 204 | 205 | for _ in 0..1000 { 206 | let mut a = Fq12::random(&mut rng); 207 | let mut b = a; 208 | b.mul_assign(&a); 209 | a.square(); 210 | assert_eq!(a, b); 211 | } 212 | } 213 | 214 | #[test] 215 | fn fq12_field_tests() { 216 | use ff::PrimeField; 217 | use super::fq::Fq; 218 | 219 | crate::tests::field::random_field_tests::(); 220 | crate::tests::field::random_frobenius_tests::(Fq::char(), 13); 221 | } 222 | -------------------------------------------------------------------------------- /accumulator-ecc/accumulator/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate serde_big_array; 3 | 4 | pub extern crate pairings; 5 | 6 | big_array! { BigArray; 32,48,96,192 } 7 | 8 | use crate::accumulator::Element; 9 | use blake2::{digest::generic_array::GenericArray, Blake2b}; 10 | use ff_zeroize::Field; 11 | use pairings::{ 12 | bls12_381::{Fr, G1}, 13 | hash_to_curve::HashToCurve, 14 | hash_to_field::{BaseFromRO, ExpandMsgXmd}, 15 | CurveProjective, 16 | }; 17 | #[cfg(not(test))] 18 | use rand::prelude::*; 19 | use std::ops::{AddAssign, MulAssign, SubAssign}; 20 | 21 | #[cfg(test)] 22 | thread_local! { 23 | pub static MOCK_RNG: std::cell::RefCell = std::cell::RefCell::new(1); 24 | } 25 | 26 | /// Similar to https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04#section-2.3 27 | /// info is left blank 28 | #[cfg(not(test))] 29 | fn generate_fr(salt: &[u8], ikm: Option<&[u8]>) -> Fr { 30 | let info = [0u8, 32u8]; // I2OSP(L, 2) 31 | let ikm = match ikm { 32 | Some(v) => { 33 | let mut t = vec![0u8; v.len() + 1]; 34 | t[..v.len()].copy_from_slice(v); 35 | t 36 | } 37 | None => { 38 | let mut bytes = vec![0u8; 33]; 39 | thread_rng().fill_bytes(bytes.as_mut_slice()); 40 | bytes[32] = 0; 41 | bytes 42 | } 43 | }; 44 | let mut okm = [0u8; 48]; 45 | let h = hkdf::Hkdf::::new(Some(&salt[..]), &ikm); 46 | h.expand(&info[..], &mut okm).unwrap(); 47 | Fr::from_okm(GenericArray::from_slice(&okm[..])) 48 | } 49 | 50 | #[cfg(test)] 51 | fn generate_fr(salt: &[u8], seed: Option<&[u8]>) -> Fr { 52 | use ff_zeroize::PrimeField; 53 | 54 | match seed { 55 | Some(d) => { 56 | let info = [0u8, 32u8]; // I2OSP(L, 2) 57 | let mut okm = [0u8; 48]; 58 | let h = hkdf::Hkdf::::new(Some(&salt[..]), &d); 59 | h.expand(&info[..], &mut okm).unwrap(); 60 | Fr::from_okm(GenericArray::from_slice(&okm[..])) 61 | } 62 | None => MOCK_RNG.with(|v| { 63 | let mut t = v.borrow_mut(); 64 | *t = *t + 1; 65 | Fr::from_repr(pairings::bls12_381::FrRepr::from(*t as u64)).unwrap() 66 | }), 67 | } 68 | } 69 | 70 | fn hash_to_g1>(data: I) -> G1 { 71 | const DST: &[u8] = b"BLS12381G1_XMD:BLAKE2B_SSWU_RO_VB_ACCUMULATOR:1_0_0"; 72 | >>::hash_to_curve(data.as_ref(), DST) 73 | } 74 | 75 | /// dA(x) and dD(x) 76 | fn dad(values: &[Element], y: Fr) -> Fr { 77 | if values.len() == 1 { 78 | let mut a = values[0].0; 79 | a.sub_assign(&y); 80 | a 81 | } else { 82 | values 83 | .iter() 84 | .map(|v| { 85 | let mut vv = v.0; 86 | vv.sub_assign(&y); 87 | vv 88 | }) 89 | .fold(Fr::one(), |mut a, y| { 90 | a.mul_assign(&y); 91 | a 92 | }) 93 | } 94 | } 95 | 96 | /// Salt used for hashing values into the accumulator 97 | /// Giuseppe Vitto, Alex Biryukov = VB 98 | /// Accumulator = ACC 99 | const SALT: &'static [u8] = b"VB-ACC-HASH-SALT-"; 100 | 101 | struct PolynomialG1(Vec); 102 | 103 | impl PolynomialG1 { 104 | pub fn with_capacity(size: usize) -> Self { 105 | Self(Vec::with_capacity(size)) 106 | } 107 | 108 | pub fn evaluate(&self, x: Fr) -> Option { 109 | if self.0.is_empty() { 110 | return None; 111 | } 112 | 113 | let mut p = x; 114 | let mut res = self.0[0]; 115 | 116 | for i in 1..self.0.len() { 117 | let mut r = self.0[i]; 118 | r.mul_assign(p); 119 | res.add_assign(&r); 120 | p.mul_assign(&x); 121 | } 122 | Some(res) 123 | } 124 | } 125 | 126 | impl AddAssign for PolynomialG1 { 127 | fn add_assign(&mut self, rhs: Self) { 128 | let min_len = std::cmp::min(self.0.len(), rhs.0.len()); 129 | 130 | if self.0.len() == min_len { 131 | for i in min_len..rhs.0.len() { 132 | self.0.push(rhs.0[i]); 133 | } 134 | } 135 | for i in 0..min_len { 136 | self.0[i].add_assign(&rhs.0[i]) 137 | } 138 | } 139 | } 140 | 141 | impl MulAssign for PolynomialG1 { 142 | fn mul_assign(&mut self, rhs: Fr) { 143 | for i in 0..self.0.len() { 144 | self.0[i].mul_assign(rhs); 145 | } 146 | } 147 | } 148 | 149 | struct Polynomial(Vec); 150 | 151 | impl Polynomial { 152 | pub fn new() -> Self { 153 | Self(Vec::new()) 154 | } 155 | 156 | pub fn with_capacity(size: usize) -> Self { 157 | Self(Vec::with_capacity(size)) 158 | } 159 | 160 | pub fn push(&mut self, value: Fr) { 161 | self.0.push(value) 162 | } 163 | } 164 | 165 | impl Into> for Polynomial { 166 | fn into(self) -> Vec { 167 | self.0 168 | } 169 | } 170 | 171 | impl AddAssign for Polynomial { 172 | fn add_assign(&mut self, rhs: Self) { 173 | let min_len = std::cmp::min(self.0.len(), rhs.0.len()); 174 | 175 | if self.0.len() == min_len { 176 | for i in min_len..rhs.0.len() { 177 | self.0.push(rhs.0[i]); 178 | } 179 | } 180 | for i in 0..min_len { 181 | self.0[i].add_assign(&rhs.0[i]) 182 | } 183 | } 184 | } 185 | 186 | impl SubAssign for Polynomial { 187 | fn sub_assign(&mut self, rhs: Self) { 188 | let min_len = std::cmp::min(self.0.len(), rhs.0.len()); 189 | if self.0.len() == min_len { 190 | for i in min_len..rhs.0.len() { 191 | let mut r = rhs.0[i]; 192 | r.negate(); 193 | self.0.push(r); 194 | } 195 | } 196 | for i in 0..min_len { 197 | self.0[i].sub_assign(&rhs.0[i]); 198 | } 199 | } 200 | } 201 | 202 | impl MulAssign for Polynomial { 203 | fn mul_assign(&mut self, rhs: Self) { 204 | let orig = self.0.clone(); 205 | 206 | // Both vectors can't be empty 207 | if !self.0.is_empty() || !rhs.0.is_empty() { 208 | for i in 0..self.0.len() { 209 | self.0[i] = Fr::default(); 210 | } 211 | // M + N - 1 212 | self.0 213 | .resize_with(self.0.len() + rhs.0.len() - 1, || Fr::default()); 214 | 215 | // Calculate product 216 | for i in 0..orig.len() { 217 | for j in 0..rhs.0.len() { 218 | let mut f = orig[i]; 219 | f.mul_assign(&rhs.0[j]); 220 | self.0[i + j].add_assign(&f); 221 | } 222 | } 223 | } 224 | } 225 | } 226 | 227 | impl MulAssign for Polynomial { 228 | fn mul_assign(&mut self, rhs: Fr) { 229 | for i in 0..self.0.len() { 230 | self.0[i].mul_assign(&rhs); 231 | } 232 | } 233 | } 234 | 235 | #[macro_use] 236 | mod macros; 237 | 238 | pub mod accumulator; 239 | pub mod error; 240 | pub mod key; 241 | pub mod proof; 242 | pub mod witness; 243 | 244 | pub mod prelude { 245 | pub use super::accumulator::*; 246 | pub use super::error::*; 247 | pub use super::key::*; 248 | pub use super::proof::*; 249 | pub use super::witness::*; 250 | } 251 | -------------------------------------------------------------------------------- /accumulator-rsa/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny( 2 | // warnings, 3 | missing_docs, 4 | unsafe_code, 5 | unused_import_braces, 6 | unused_lifetimes, 7 | unused_qualifications, 8 | )] 9 | #![cfg_attr(feature = "nightly", feature(doc_cfg))] 10 | //! Implementation of a dynamic universal RSA accumulator 11 | #[macro_use] 12 | extern crate arrayref; 13 | #[macro_use] 14 | pub extern crate common; 15 | 16 | pub(crate) const MIN_SIZE_PRIME: usize = 1024; 17 | pub(crate) const FACTOR_SIZE: usize = MIN_SIZE_PRIME / 8; 18 | pub(crate) const MIN_BYTES: usize = FACTOR_SIZE * 6 + 4; 19 | pub(crate) const MEMBER_SIZE: usize = 32; 20 | pub(crate) const MEMBER_SIZE_BITS: usize = 256; 21 | 22 | /// Provides methods for creating and updating accumulators 23 | pub mod accumulator; 24 | /// Provides methods for hashing to prime 25 | pub mod hash; 26 | /// Provides an accumulator secret factors 27 | pub mod key; 28 | /// Proofs of set membership 29 | pub mod memproof; 30 | /// Proofs of set non-membership 31 | pub mod nonmemproof; 32 | /// Provides non-membership witness methods 33 | pub mod nonwitness; 34 | /// Provides witness methods 35 | pub mod memwitness; 36 | 37 | use crate::hash::hash_to_prime; 38 | use blake2::{digest::Digest, Blake2b}; 39 | use common::{ 40 | bigint::BigInteger, 41 | error::{AccumulatorError, AccumulatorErrorKind}, 42 | }; 43 | use std::convert::TryFrom; 44 | use crate::hash::hash_to_generator; 45 | 46 | /// Convenience module to include when using 47 | pub mod prelude { 48 | pub use crate::{ 49 | accumulator::Accumulator, 50 | common::{ 51 | bigint::{BigInteger, GcdResult}, 52 | error::*, 53 | }, 54 | key::AccumulatorSecretKey, 55 | memproof::MembershipProof, 56 | memwitness::MembershipWitness, 57 | nonmemproof::NonMembershipProof, 58 | nonwitness::NonMembershipWitness, 59 | }; 60 | } 61 | 62 | /// BigUint to fixed array 63 | pub(crate) fn b2fa(b: &BigInteger, expected_size: usize) -> Vec { 64 | let mut t = vec![0u8; expected_size]; 65 | let bt = b.to_bytes(); 66 | assert!( 67 | expected_size >= bt.len(), 68 | format!("expected = {}, found = {}", expected_size, bt.len()) 69 | ); 70 | t[(expected_size - bt.len())..].clone_from_slice(bt.as_slice()); 71 | t 72 | } 73 | 74 | pub(crate) fn hashed_generator>(u: &BigInteger, a: &BigInteger, n: &BigInteger, nonce: B) -> BigInteger { 75 | let mut transcript = u.to_bytes(); 76 | transcript.append(&mut a.to_bytes()); 77 | transcript.extend_from_slice(nonce.as_ref()); 78 | 79 | hash_to_generator(transcript.as_slice(), &n) 80 | } 81 | 82 | /// Represents a Proof of Knowledge of Exponents 2 from section 3.2 in 83 | /// 84 | #[derive(Debug, Eq, PartialEq, Clone)] 85 | pub(crate) struct Poke2Proof { 86 | u: BigInteger, 87 | z: BigInteger, 88 | q: BigInteger, 89 | r: BigInteger, 90 | } 91 | 92 | impl Poke2Proof { 93 | /// The size of this proof serialized 94 | pub const SIZE_BYTES: usize = 6 * FACTOR_SIZE + MEMBER_SIZE; 95 | 96 | /// Create a new proof of knowledge of exponents as described in 97 | /// Appendix D from 98 | /// 99 | pub fn new>( 100 | x: &BigInteger, 101 | u: &BigInteger, 102 | a: &BigInteger, 103 | n: &BigInteger, 104 | nonce: B, 105 | ) -> Self { 106 | let nonce = nonce.as_ref(); 107 | let g = hashed_generator(u, a, n, nonce); 108 | Self::create(x, u, a, &g, n, nonce) 109 | } 110 | 111 | /// Same as `new` but allow any generator vs according to the spec 112 | pub fn create>( 113 | x: &BigInteger, 114 | u: &BigInteger, 115 | a: &BigInteger, 116 | g: &BigInteger, 117 | n: &BigInteger, 118 | nonce: B, 119 | ) -> Self { 120 | let f = common::Field::new(n); 121 | let z = f.exp(&g, x); 122 | let (l, alpha) = Self::get_prime_and_alpha(&u, &a, &z, nonce.as_ref()); 123 | 124 | // q = x / l 125 | // r = x % l 126 | let (whole, r) = BigInteger::div_rem(&x, &l); 127 | 128 | // Q = u ^ q * g ^ {q * alpha} 129 | let q = f.mul(&f.exp(&u, &whole), &f.exp(&g, &(&alpha * &whole))); 130 | Self { 131 | u: u.clone(), 132 | q, 133 | r, 134 | z, 135 | } 136 | } 137 | 138 | /// Verify a proof of knowledge of exponents 139 | pub fn verify>(&self, value: &BigInteger, n: &BigInteger, nonce: B) -> bool { 140 | let nonce = nonce.as_ref(); 141 | let g = hashed_generator(&self.u, &value, &n, nonce); 142 | self.check(&g, &value, &n, nonce) 143 | } 144 | 145 | /// Same as `verify` but allow custom `g` 146 | pub fn check>(&self, g: &BigInteger, value: &BigInteger, n: &BigInteger, nonce: B) -> bool { 147 | let f = common::Field::new(n); 148 | let nonce = nonce.as_ref(); 149 | let (l, alpha) = Self::get_prime_and_alpha(&self.u, &value, &self.z, nonce); 150 | 151 | // Q ^ l 152 | // let p1 = f.exp(&self.q, &l); 153 | // u ^ r 154 | // let p2 = f.exp(&self.u, &self.r); 155 | // alpha * r 156 | // g ^ {alpha * r} 157 | // let p3 = f.exp(&g, &(&alpha * &self.r)); 158 | 159 | // Q^l * u^r * g^{x * r} 160 | // let left = f.mul(&p1, &f.mul(&p2, &p3)); 161 | let left = f.mul(&f.mul(&f.exp(&self.q, &l), &f.exp(&self.u, &self.r)), &f.exp(g, &(&alpha * &self.r))); 162 | 163 | // v * z^x 164 | let right = f.mul(&value, &f.exp(&self.z, &alpha)); 165 | 166 | left == right 167 | } 168 | 169 | /// Serialize this to bytes 170 | pub fn to_bytes(&self) -> Vec { 171 | let mut output = b2fa(&self.u, 2 * FACTOR_SIZE); 172 | output.append(&mut b2fa(&self.z, 2 * FACTOR_SIZE)); 173 | output.append(&mut b2fa(&self.q, 2 * FACTOR_SIZE)); 174 | output.append(&mut b2fa(&self.r, MEMBER_SIZE)); 175 | output 176 | } 177 | 178 | fn get_prime_and_alpha(u: &BigInteger, a: &BigInteger, z: &BigInteger, nonce: &[u8]) -> (BigInteger, BigInteger) { 179 | let mut data = u.to_bytes(); 180 | data.append(&mut a.to_bytes()); 181 | data.append(&mut z.to_bytes()); 182 | data.extend_from_slice(nonce); 183 | 184 | // l = H2P( u || A || z || n1 ) 185 | let l = hash_to_prime(data.as_slice()); 186 | 187 | data.append(&mut l.to_bytes()); 188 | // Fiat-Shamir 189 | // alpha = H(u || A || z || n1 || l) 190 | let alpha = BigInteger::try_from(Blake2b::digest(data.as_slice()).as_slice()).unwrap(); 191 | (l, alpha) 192 | } 193 | } 194 | 195 | impl TryFrom<&[u8]> for Poke2Proof { 196 | type Error = AccumulatorError; 197 | 198 | fn try_from(data: &[u8]) -> Result { 199 | if data.len() != Self::SIZE_BYTES { 200 | return Err(AccumulatorErrorKind::SerializationError.into()); 201 | } 202 | let u = BigInteger::try_from(&data[..(2 * FACTOR_SIZE)])?; 203 | let z = BigInteger::try_from(&data[(2 * FACTOR_SIZE)..(4 * FACTOR_SIZE)])?; 204 | let q = BigInteger::try_from(&data[(4 * FACTOR_SIZE)..(6 * FACTOR_SIZE)])?; 205 | let r = BigInteger::try_from(&data[(6 * FACTOR_SIZE)..])?; 206 | Ok(Self { u, z, q, r }) 207 | } 208 | } 209 | 210 | serdes_impl!(Poke2Proof); 211 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/tests/field.rs: -------------------------------------------------------------------------------- 1 | use ff::{Field, LegendreSymbol, PrimeField, SqrtField}; 2 | use rand_core::RngCore; 3 | use rand_core::SeedableRng; 4 | 5 | pub fn random_frobenius_tests>(characteristic: C, maxpower: usize) { 6 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 7 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 8 | 0xe5, 9 | ]); 10 | for _ in 0..100 { 11 | for i in 0..=maxpower { 12 | let mut a = F::random(&mut rng); 13 | let mut b = a; 14 | 15 | for _ in 0..i { 16 | a = a.pow(&characteristic); 17 | } 18 | b.frobenius_map(i); 19 | 20 | assert_eq!(a, b); 21 | } 22 | } 23 | } 24 | 25 | pub fn random_sqrt_tests() { 26 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 27 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 28 | 0xe5, 29 | ]); 30 | for _ in 0..10000 { 31 | let a = F::random(&mut rng); 32 | let mut b = a; 33 | b.square(); 34 | assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue); 35 | 36 | let b = b.sqrt().unwrap(); 37 | let mut negb = b; 38 | negb.negate(); 39 | 40 | assert!(a == b || a == negb); 41 | } 42 | 43 | let mut c = F::one(); 44 | for _ in 0..10000 { 45 | let mut b = c; 46 | b.square(); 47 | assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue); 48 | 49 | b = b.sqrt().unwrap(); 50 | 51 | if b != c { 52 | b.negate(); 53 | } 54 | 55 | assert_eq!(b, c); 56 | 57 | c.add_assign(&F::one()); 58 | } 59 | } 60 | 61 | pub fn random_field_tests() { 62 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 63 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 64 | 0xe5, 65 | ]); 66 | random_multiplication_tests::(&mut rng); 67 | random_addition_tests::(&mut rng); 68 | random_subtraction_tests::(&mut rng); 69 | random_negation_tests::(&mut rng); 70 | random_doubling_tests::(&mut rng); 71 | random_squaring_tests::(&mut rng); 72 | random_inversion_tests::(&mut rng); 73 | random_expansion_tests::(&mut rng); 74 | 75 | assert!(F::zero().is_zero()); 76 | { 77 | let mut z = F::zero(); 78 | z.negate(); 79 | assert!(z.is_zero()); 80 | } 81 | 82 | assert!(F::zero().inverse().is_none()); 83 | 84 | // Multiplication by zero 85 | { 86 | let mut a = F::random(&mut rng); 87 | a.mul_assign(&F::zero()); 88 | assert!(a.is_zero()); 89 | } 90 | 91 | // Addition by zero 92 | { 93 | let mut a = F::random(&mut rng); 94 | let copy = a; 95 | a.add_assign(&F::zero()); 96 | assert_eq!(a, copy); 97 | } 98 | } 99 | 100 | pub fn from_str_tests() { 101 | { 102 | let a = "84395729384759238745923745892374598234705297301958723458712394587103249587213984572934750213947582345792304758273458972349582734958273495872304598234"; 103 | let b = "38495729084572938457298347502349857029384609283450692834058293405982304598230458230495820394850293845098234059823049582309485203948502938452093482039"; 104 | let c = "3248875134290623212325429203829831876024364170316860259933542844758450336418538569901990710701240661702808867062612075657861768196242274635305077449545396068598317421057721935408562373834079015873933065667961469731886739181625866970316226171512545167081793907058686908697431878454091011239990119126"; 105 | 106 | let mut a = F::from_str(a).unwrap(); 107 | let b = F::from_str(b).unwrap(); 108 | let c = F::from_str(c).unwrap(); 109 | 110 | a.mul_assign(&b); 111 | 112 | assert_eq!(a, c); 113 | } 114 | 115 | { 116 | let mut rng = rand_xorshift::XorShiftRng::from_seed([ 117 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 118 | 0xbc, 0xe5, 119 | ]); 120 | for _ in 0..1000 { 121 | let n: u64 = rng.next_u64(); 122 | 123 | let a = F::from_str(&format!("{}", n)).unwrap(); 124 | let b = F::from_repr(n.into()).unwrap(); 125 | 126 | assert_eq!(a, b); 127 | } 128 | } 129 | 130 | assert!(F::from_str("").is_none()); 131 | assert!(F::from_str("0").unwrap().is_zero()); 132 | assert!(F::from_str("00").is_none()); 133 | assert!(F::from_str("00000000000").is_none()); 134 | } 135 | 136 | fn random_multiplication_tests(rng: &mut R) { 137 | for _ in 0..10000 { 138 | let a = F::random(rng); 139 | let b = F::random(rng); 140 | let c = F::random(rng); 141 | 142 | let mut t0 = a; // (a * b) * c 143 | t0.mul_assign(&b); 144 | t0.mul_assign(&c); 145 | 146 | let mut t1 = a; // (a * c) * b 147 | t1.mul_assign(&c); 148 | t1.mul_assign(&b); 149 | 150 | let mut t2 = b; // (b * c) * a 151 | t2.mul_assign(&c); 152 | t2.mul_assign(&a); 153 | 154 | assert_eq!(t0, t1); 155 | assert_eq!(t1, t2); 156 | } 157 | } 158 | 159 | fn random_addition_tests(rng: &mut R) { 160 | for _ in 0..10000 { 161 | let a = F::random(rng); 162 | let b = F::random(rng); 163 | let c = F::random(rng); 164 | 165 | let mut t0 = a; // (a + b) + c 166 | t0.add_assign(&b); 167 | t0.add_assign(&c); 168 | 169 | let mut t1 = a; // (a + c) + b 170 | t1.add_assign(&c); 171 | t1.add_assign(&b); 172 | 173 | let mut t2 = b; // (b + c) + a 174 | t2.add_assign(&c); 175 | t2.add_assign(&a); 176 | 177 | assert_eq!(t0, t1); 178 | assert_eq!(t1, t2); 179 | } 180 | } 181 | 182 | fn random_subtraction_tests(rng: &mut R) { 183 | for _ in 0..10000 { 184 | let a = F::random(rng); 185 | let b = F::random(rng); 186 | 187 | let mut t0 = a; // (a - b) 188 | t0.sub_assign(&b); 189 | 190 | let mut t1 = b; // (b - a) 191 | t1.sub_assign(&a); 192 | 193 | let mut t2 = t0; // (a - b) + (b - a) = 0 194 | t2.add_assign(&t1); 195 | 196 | assert!(t2.is_zero()); 197 | } 198 | } 199 | 200 | fn random_negation_tests(rng: &mut R) { 201 | for _ in 0..10000 { 202 | let a = F::random(rng); 203 | let mut b = a; 204 | b.negate(); 205 | b.add_assign(&a); 206 | 207 | assert!(b.is_zero()); 208 | } 209 | } 210 | 211 | fn random_doubling_tests(rng: &mut R) { 212 | for _ in 0..10000 { 213 | let mut a = F::random(rng); 214 | let mut b = a; 215 | a.add_assign(&b); 216 | b.double(); 217 | 218 | assert_eq!(a, b); 219 | } 220 | } 221 | 222 | fn random_squaring_tests(rng: &mut R) { 223 | for _ in 0..10000 { 224 | let mut a = F::random(rng); 225 | let mut b = a; 226 | a.mul_assign(&b); 227 | b.square(); 228 | 229 | assert_eq!(a, b); 230 | } 231 | } 232 | 233 | fn random_inversion_tests(rng: &mut R) { 234 | assert!(F::zero().inverse().is_none()); 235 | 236 | for _ in 0..10000 { 237 | let mut a = F::random(rng); 238 | let b = a.inverse().unwrap(); // probablistically nonzero 239 | a.mul_assign(&b); 240 | 241 | assert_eq!(a, F::one()); 242 | } 243 | } 244 | 245 | fn random_expansion_tests(rng: &mut R) { 246 | for _ in 0..10000 { 247 | // Compare (a + b)(c + d) and (a*c + b*c + a*d + b*d) 248 | 249 | let a = F::random(rng); 250 | let b = F::random(rng); 251 | let c = F::random(rng); 252 | let d = F::random(rng); 253 | 254 | let mut t0 = a; 255 | t0.add_assign(&b); 256 | let mut t1 = c; 257 | t1.add_assign(&d); 258 | t0.mul_assign(&t1); 259 | 260 | let mut t2 = a; 261 | t2.mul_assign(&c); 262 | let mut t3 = b; 263 | t3.mul_assign(&c); 264 | let mut t4 = a; 265 | t4.mul_assign(&d); 266 | let mut t5 = b; 267 | t5.mul_assign(&d); 268 | 269 | t2.add_assign(&t3); 270 | t2.add_assign(&t4); 271 | t2.add_assign(&t5); 272 | 273 | assert_eq!(t0, t2); 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /accumulator-rsa/src/witnessmem.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | accumulator::Accumulator, b2fa, hash::hash_to_prime, key::AccumulatorSecretKey, FACTOR_SIZE, 3 | MEMBER_SIZE, 4 | }; 5 | use common::{ 6 | bigint::BigInteger, 7 | error::{AccumulatorError, AccumulatorErrorKind}, 8 | Field, 9 | }; 10 | use rayon::prelude::*; 11 | use std::convert::TryFrom; 12 | 13 | /// A witness that can be used for membership proofs 14 | #[derive(Debug, Eq, PartialEq, Clone)] 15 | pub struct MembershipWitness { 16 | pub(crate) u: BigInteger, 17 | pub(crate) x: BigInteger, 18 | } 19 | 20 | impl MembershipWitness { 21 | /// Return a new membership witness 22 | pub fn new>(accumulator: &Accumulator, x: B) -> Result { 23 | let x = hash_to_prime(x.as_ref()); 24 | Self::new_prime(accumulator, &x) 25 | } 26 | 27 | /// Return a new membership witness with a value that is already prime 28 | pub fn new_prime(accumulator: &Accumulator, x: &BigInteger) -> Result { 29 | if !accumulator.members.contains(&x) { 30 | return Err(AccumulatorError::from_msg( 31 | AccumulatorErrorKind::InvalidMemberSupplied, 32 | "value is not in the accumulator", 33 | )); 34 | } 35 | let exp = accumulator 36 | .members 37 | .par_iter() 38 | .cloned() 39 | .filter(|b| b != x) 40 | .product(); 41 | let u = (&accumulator.generator).mod_exp(&exp, &accumulator.modulus); 42 | Ok(Self { u, x: x.clone() }) 43 | } 44 | 45 | /// Return a new membership witness. This is more efficient that `new` due to 46 | /// the ability to reduce by the totient 47 | pub fn with_secret_key>( 48 | accumulator: &Accumulator, 49 | secret_key: &AccumulatorSecretKey, 50 | x: B, 51 | ) -> Self { 52 | let x = hash_to_prime(x.as_ref()); 53 | Self::with_prime_and_secret_key(accumulator, secret_key, &x) 54 | } 55 | 56 | /// Return a new membership witness with a value already prime. 57 | /// This is more efficient that `new` due to 58 | /// the ability to reduce by the totient 59 | pub fn with_prime_and_secret_key( 60 | accumulator: &Accumulator, 61 | secret_key: &AccumulatorSecretKey, 62 | x: &BigInteger, 63 | ) -> Self { 64 | if !accumulator.members.contains(&x) { 65 | return MembershipWitness { 66 | u: accumulator.value.clone(), 67 | x: x.clone(), 68 | }; 69 | } 70 | let totient = secret_key.totient(); 71 | let f = common::Field::new(&totient); 72 | let exp = accumulator 73 | .members 74 | .par_iter() 75 | .cloned() 76 | .filter(|b| b != x) 77 | .reduce(|| BigInteger::from(1u32), |a, b| f.mul(&a, &b)); 78 | let u = (&accumulator.generator).mod_exp(&exp, &accumulator.modulus); 79 | Self { u, x: x.clone() } 80 | } 81 | 82 | /// Create a new witness to match `new_acc` from `old_acc` using this witness 83 | /// by applying the methods found in 4.2 in 84 | /// 85 | pub fn update( 86 | &self, 87 | old_acc: &Accumulator, 88 | new_acc: &Accumulator, 89 | ) -> Result { 90 | let mut w = self.clone(); 91 | w.update_assign(old_acc, new_acc)?; 92 | Ok(w) 93 | } 94 | 95 | /// Update this witness to match `new_acc` from `old_acc` 96 | /// by applying the methods found in 4.2 in 97 | /// 98 | pub fn update_assign( 99 | &mut self, 100 | old_acc: &Accumulator, 101 | new_acc: &Accumulator, 102 | ) -> Result<(), AccumulatorError> { 103 | if !new_acc.members.contains(&self.x) { 104 | return Err(AccumulatorErrorKind::InvalidMemberSupplied.into()); 105 | } 106 | if !old_acc.members.contains(&self.x) { 107 | return Err(AccumulatorErrorKind::InvalidMemberSupplied.into()); 108 | } 109 | 110 | let additions: Vec<&BigInteger> = new_acc.members.difference(&old_acc.members).collect(); 111 | let deletions: Vec<&BigInteger> = old_acc.members.difference(&new_acc.members).collect(); 112 | 113 | if additions.is_empty() && deletions.is_empty() { 114 | return Ok(()); 115 | } 116 | 117 | let f = Field::new(&new_acc.modulus); 118 | 119 | if !additions.is_empty() { 120 | let x_a = additions.into_par_iter().product(); 121 | self.u = f.exp(&self.u, &x_a); 122 | } 123 | 124 | if !deletions.is_empty() { 125 | let x_hat = deletions.into_par_iter().product(); 126 | let gcd_res = self.x.bezouts_coefficients(&x_hat); 127 | assert_eq!(gcd_res.value, BigInteger::from(1u32)); 128 | 129 | self.u = f.mul( 130 | &f.exp(&self.u, &gcd_res.b), 131 | &f.exp(&new_acc.value, &gcd_res.a), 132 | ); 133 | } 134 | 135 | Ok(()) 136 | } 137 | 138 | /// Serialize this to bytes 139 | pub fn to_bytes(&self) -> Vec { 140 | let mut output = b2fa(&self.u, FACTOR_SIZE * 2); 141 | output.append(&mut b2fa(&self.x, MEMBER_SIZE)); 142 | output 143 | } 144 | } 145 | 146 | impl TryFrom<&[u8]> for MembershipWitness { 147 | type Error = AccumulatorError; 148 | 149 | fn try_from(data: &[u8]) -> Result { 150 | if data.len() != FACTOR_SIZE * 2 + MEMBER_SIZE { 151 | return Err(AccumulatorErrorKind::SerializationError.into()); 152 | } 153 | let u = BigInteger::try_from(&data[..(FACTOR_SIZE * 2)])?; 154 | let x = BigInteger::try_from(&data[(FACTOR_SIZE * 2)..])?; 155 | Ok(Self { u, x }) 156 | } 157 | } 158 | 159 | serdes_impl!(MembershipWitness); 160 | 161 | #[cfg(test)] 162 | mod tests { 163 | use super::*; 164 | use crate::hash::hash_to_prime; 165 | 166 | #[test] 167 | fn witnesses() { 168 | let key = AccumulatorSecretKey::default(); 169 | let members: Vec<[u8; 8]> = vec![ 170 | 23u64.to_be_bytes(), 171 | 7u64.to_be_bytes(), 172 | 11u64.to_be_bytes(), 173 | 13u64.to_be_bytes(), 174 | ]; 175 | let mut acc = Accumulator::with_members(&key, &members); 176 | let witness = MembershipWitness::new(&acc, &members[0]).unwrap(); 177 | let x = hash_to_prime(&members[0]); 178 | assert_eq!(witness.x, x); 179 | 180 | acc.remove_assign(&key, &members[0]).unwrap(); 181 | 182 | assert_eq!(acc.value, witness.u); 183 | assert_eq!(witness.to_bytes().len(), 2 * FACTOR_SIZE + MEMBER_SIZE); 184 | } 185 | 186 | #[test] 187 | fn updates() { 188 | let key = AccumulatorSecretKey::default(); 189 | let members: Vec<[u8; 8]> = vec![ 190 | 23u64.to_be_bytes(), 191 | 7u64.to_be_bytes(), 192 | 11u64.to_be_bytes(), 193 | 13u64.to_be_bytes(), 194 | 17u64.to_be_bytes(), 195 | 19u64.to_be_bytes(), 196 | ]; 197 | let acc = Accumulator::with_members(&key, &members); 198 | let witness = MembershipWitness::new(&acc, &members[0]).unwrap(); 199 | 200 | let acc_prime = &acc + 29u64; 201 | 202 | let res = witness.update(&acc, &acc_prime); 203 | assert!(res.is_ok()); 204 | let new_w = res.unwrap(); 205 | let expected_witness = MembershipWitness::new(&acc_prime, &members[0]).unwrap(); 206 | assert_eq!(expected_witness.u, new_w.u); 207 | 208 | let mut acc = acc_prime.remove_u64(&key, 19u64).unwrap(); 209 | let res = new_w.update(&acc_prime, &acc); 210 | assert!(res.is_ok()); 211 | let new_w = res.unwrap(); 212 | let expected_witness = MembershipWitness::new(&acc, &members[0]).unwrap(); 213 | assert_eq!(expected_witness.u, new_w.u); 214 | 215 | let old_acc = acc.clone(); 216 | acc.remove_u64_assign(&key, 7u64).unwrap(); 217 | acc.remove_u64_assign(&key, 11u64).unwrap(); 218 | acc.remove_u64_assign(&key, 13u64).unwrap(); 219 | acc += 31u64; 220 | let res = new_w.update(&old_acc, &acc); 221 | assert!(res.is_ok()); 222 | let new_w = res.unwrap(); 223 | let expected_witness = MembershipWitness::new(&acc, &members[0]).unwrap(); 224 | assert_eq!(expected_witness.u, new_w.u); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /accumulator-ecc/accumulator/src/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! struct_impl { 2 | ($(#[$docs:meta])* 3 | $name:ident, $inner:ident, $ty:ident) => { 4 | $(#[$docs])* 5 | pub struct $name(pub(crate) $ty); 6 | 7 | inner_impl!($name, $inner, $ty); 8 | bytes_impl!($name, $ty); 9 | serdes_impl!($name, $inner); 10 | raw_impl!($name, $ty); 11 | }; 12 | ($(#[$docs:meta])* 13 | $name:ident, $inner:ident, $($field:ident: $ty:ty => $size:expr),+ $(,)?) => { 14 | $(#[$docs])* 15 | pub struct $name { 16 | $( 17 | pub(crate) $field: $ty, 18 | )+ 19 | } 20 | 21 | inner_impl!($name, $inner, $($field: $ty => $size,)+); 22 | bytes_impl!($name, $($field: $ty => $size,)+); 23 | serdes_impl!($name, $inner); 24 | }; 25 | } 26 | 27 | macro_rules! bytes_impl { 28 | ($name:ident) => { 29 | impl TryFrom> for $name { 30 | type Error = crate::error::Error; 31 | 32 | fn try_from(d: Vec) -> Result { 33 | Self::try_from(d.as_slice()) 34 | } 35 | } 36 | 37 | impl TryFrom<&Vec> for $name { 38 | type Error = crate::error::Error; 39 | 40 | fn try_from(d: &Vec) -> Result { 41 | Self::try_from(d.as_slice()) 42 | } 43 | } 44 | 45 | impl From<[u8; $name::BYTES]> for $name { 46 | fn from(d: [u8; Self::BYTES]) -> Self { 47 | Self::try_from(&d[..]).unwrap() 48 | } 49 | } 50 | 51 | impl From<&[u8; $name::BYTES]> for $name { 52 | fn from(d: &[u8; Self::BYTES]) -> Self { 53 | Self::try_from(&d[..]).unwrap() 54 | } 55 | } 56 | 57 | impl From> for $name { 58 | fn from(d: Box<[u8]>) -> Self { 59 | let d = d.to_vec(); 60 | Self::try_from(d).unwrap() 61 | } 62 | } 63 | 64 | impl From<&Box<[u8]>> for $name { 65 | fn from(d: &Box<[u8]>) -> Self { 66 | let d = d.to_vec(); 67 | Self::try_from(d).unwrap() 68 | } 69 | } 70 | 71 | impl Into> for $name { 72 | fn into(self) -> Box<[u8]> { 73 | self.to_bytes().to_vec().into_boxed_slice() 74 | } 75 | } 76 | }; 77 | ($name:ident, $ty:ident) => { 78 | impl TryFrom<&[u8]> for $name { 79 | type Error = crate::error::Error; 80 | 81 | fn try_from(d: &[u8]) -> Result { 82 | if d.len() != Self::BYTES { 83 | return Err(crate::error::Error::from_msg( 84 | 1, 85 | &format!("Invalid number of bytes: {}", d.len()), 86 | )); 87 | } 88 | let mut c = std::io::Cursor::new(d); 89 | let e = $ty::deserialize(&mut c, true) 90 | .map_err(|e| crate::error::Error::from_msg(1, &format!("{:?}", e)))?; 91 | Ok(Self(e)) 92 | } 93 | } 94 | 95 | bytes_impl!($name); 96 | }; 97 | ($name:ident, $($field:ident: $ty:ty => $size:expr),+ $(,)?) => { 98 | impl TryFrom<&[u8]> for $name { 99 | type Error = crate::error::Error; 100 | 101 | fn try_from(d: &[u8]) -> Result { 102 | if d.len() != Self::BYTES { 103 | return Err(crate::error::Error::from_msg( 104 | 1, 105 | &format!("Invalid number of bytes: {}", d.len()), 106 | )); 107 | } 108 | let mut c = std::io::Cursor::new(d); 109 | let t = Self { 110 | $( 111 | $field: <$ty>::deserialize(&mut c, true).map_err(|e| crate::error::Error::from_msg(1, &format!("{:?}", e)))?, 112 | )+ 113 | }; 114 | 115 | Ok(t) 116 | } 117 | } 118 | 119 | bytes_impl!($name); 120 | } 121 | } 122 | 123 | macro_rules! display_impl { 124 | ($name:ident) => { 125 | impl std::fmt::Display for $name { 126 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 127 | let bytes = self.to_bytes(); 128 | write!(f, "{} {{ {} }}", stringify!($name), hex::encode(&bytes[..])) 129 | } 130 | } 131 | }; 132 | } 133 | 134 | macro_rules! serdes_impl { 135 | ($name:ident, $inner:ident) => { 136 | impl Serialize for $name { 137 | fn serialize(&self, s: S) -> Result { 138 | let t = $inner::from(self); 139 | t.serialize(s) 140 | } 141 | } 142 | impl<'de> Deserialize<'de> for $name { 143 | fn deserialize>(d: D) -> Result { 144 | let inner = $inner::deserialize(d)?; 145 | $name::try_from(inner).map_err(|e| serde::de::Error::custom(e)) 146 | } 147 | } 148 | }; 149 | } 150 | 151 | macro_rules! raw_impl { 152 | ($name:ident, $ty:ident) => { 153 | impl AsRef<$ty> for $name { 154 | fn as_ref(&self) -> &$ty { 155 | &self.0 156 | } 157 | } 158 | 159 | impl Into<$ty> for $name { 160 | fn into(self) -> $ty { 161 | self.0 162 | } 163 | } 164 | 165 | impl From<$ty> for $name { 166 | fn from(d: $ty) -> Self { 167 | Self(d) 168 | } 169 | } 170 | }; 171 | } 172 | 173 | macro_rules! inner_impl { 174 | ($name:ident, $inner:ident, $ty:ident) => { 175 | #[derive(Serialize, Deserialize)] 176 | struct $inner( 177 | #[serde(with = "BigArray")] 178 | [u8; $name::BYTES] 179 | ); 180 | 181 | impl From<$name> for $inner { 182 | fn from(d: $name) -> Self { 183 | Self::from(&d) 184 | } 185 | } 186 | 187 | impl From<&$name> for $inner { 188 | fn from(d: &$name) -> Self { 189 | let mut c = [0u8; $name::BYTES]; 190 | d.0.serialize(&mut c.as_mut(), true).unwrap(); 191 | Self(c) 192 | } 193 | } 194 | 195 | impl TryFrom<&$inner> for $name { 196 | type Error = String; 197 | 198 | fn try_from(d: &$inner) -> Result { 199 | let mut cur = std::io::Cursor::new(d.0); 200 | let t = $ty::deserialize(&mut cur, true).map_err(|e| e.to_string())?; 201 | Ok(Self(t)) 202 | } 203 | } 204 | 205 | impl TryFrom<$inner> for $name { 206 | type Error = String; 207 | 208 | fn try_from(d: $inner) -> Result { 209 | Self::try_from(&d) 210 | } 211 | } 212 | }; 213 | ($name:ident, $inner:ident, $($field:ident: $ty:ty => $size:expr),+ $(,)?) => { 214 | #[derive(Serialize, Deserialize)] 215 | struct $inner { 216 | $( 217 | #[serde(with = "BigArray")] 218 | $field: [u8; $size] 219 | ),+ 220 | } 221 | 222 | impl From<$name> for $inner { 223 | fn from(d: $name) -> Self { 224 | Self::from(&d) 225 | } 226 | } 227 | 228 | impl From<&$name> for $inner { 229 | fn from(d: &$name) -> Self { 230 | Self { 231 | $( 232 | $field: { 233 | let mut c = [0u8; $size]; 234 | d.$field.serialize(&mut c.as_mut(), true).unwrap(); 235 | c 236 | } 237 | ),+ 238 | } 239 | } 240 | } 241 | 242 | impl TryFrom<&$inner> for $name { 243 | type Error = String; 244 | 245 | fn try_from(d: &$inner) -> Result { 246 | let t = Self { 247 | $( 248 | $field: { 249 | let mut cur = std::io::Cursor::new(d.$field); 250 | <$ty>::deserialize(&mut cur, true).map_err(|e| e.to_string())? 251 | }, 252 | )+ 253 | }; 254 | Ok(t) 255 | } 256 | } 257 | 258 | impl TryFrom<$inner> for $name { 259 | type Error = String; 260 | 261 | fn try_from(d: $inner) -> Result { 262 | Self::try_from(&d) 263 | } 264 | } 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/benches/bls12_381/fq.rs: -------------------------------------------------------------------------------- 1 | use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; 2 | use pairing::bls12_381::*; 3 | use rand_core::SeedableRng; 4 | use rand_xorshift::XorShiftRng; 5 | 6 | #[bench] 7 | fn bench_fq_repr_add_nocarry(b: &mut ::test::Bencher) { 8 | const SAMPLES: usize = 1000; 9 | 10 | let mut rng = XorShiftRng::from_seed([ 11 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 12 | 0xe5, 13 | ]); 14 | let v: Vec<(FqRepr, FqRepr)> = (0..SAMPLES) 15 | .map(|_| { 16 | let mut tmp1 = Fq::random(&mut rng).into_repr(); 17 | let mut tmp2 = Fq::random(&mut rng).into_repr(); 18 | // Shave a few bits off to avoid overflow. 19 | for _ in 0..3 { 20 | tmp1.div2(); 21 | tmp2.div2(); 22 | } 23 | (tmp1, tmp2) 24 | }) 25 | .collect(); 26 | 27 | let mut count = 0; 28 | b.iter(|| { 29 | let mut tmp = v[count].0; 30 | tmp.add_nocarry(&v[count].1); 31 | count = (count + 1) % SAMPLES; 32 | tmp 33 | }); 34 | } 35 | 36 | #[bench] 37 | fn bench_fq_repr_sub_noborrow(b: &mut ::test::Bencher) { 38 | const SAMPLES: usize = 1000; 39 | 40 | let mut rng = XorShiftRng::from_seed([ 41 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 42 | 0xe5, 43 | ]); 44 | let v: Vec<(FqRepr, FqRepr)> = (0..SAMPLES) 45 | .map(|_| { 46 | let tmp1 = Fq::random(&mut rng).into_repr(); 47 | let mut tmp2 = tmp1; 48 | // Ensure tmp2 is smaller than tmp1. 49 | for _ in 0..10 { 50 | tmp2.div2(); 51 | } 52 | (tmp1, tmp2) 53 | }) 54 | .collect(); 55 | 56 | let mut count = 0; 57 | b.iter(|| { 58 | let mut tmp = v[count].0; 59 | tmp.sub_noborrow(&v[count].1); 60 | count = (count + 1) % SAMPLES; 61 | tmp 62 | }); 63 | } 64 | 65 | #[bench] 66 | fn bench_fq_repr_num_bits(b: &mut ::test::Bencher) { 67 | const SAMPLES: usize = 1000; 68 | 69 | let mut rng = XorShiftRng::from_seed([ 70 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 71 | 0xe5, 72 | ]); 73 | let v: Vec = (0..SAMPLES) 74 | .map(|_| Fq::random(&mut rng).into_repr()) 75 | .collect(); 76 | 77 | let mut count = 0; 78 | b.iter(|| { 79 | let tmp = v[count].num_bits(); 80 | count = (count + 1) % SAMPLES; 81 | tmp 82 | }); 83 | } 84 | 85 | #[bench] 86 | fn bench_fq_repr_mul2(b: &mut ::test::Bencher) { 87 | const SAMPLES: usize = 1000; 88 | 89 | let mut rng = XorShiftRng::from_seed([ 90 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 91 | 0xe5, 92 | ]); 93 | let v: Vec = (0..SAMPLES) 94 | .map(|_| Fq::random(&mut rng).into_repr()) 95 | .collect(); 96 | 97 | let mut count = 0; 98 | b.iter(|| { 99 | let mut tmp = v[count]; 100 | tmp.mul2(); 101 | count = (count + 1) % SAMPLES; 102 | tmp 103 | }); 104 | } 105 | 106 | #[bench] 107 | fn bench_fq_repr_div2(b: &mut ::test::Bencher) { 108 | const SAMPLES: usize = 1000; 109 | 110 | let mut rng = XorShiftRng::from_seed([ 111 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 112 | 0xe5, 113 | ]); 114 | let v: Vec = (0..SAMPLES) 115 | .map(|_| Fq::random(&mut rng).into_repr()) 116 | .collect(); 117 | 118 | let mut count = 0; 119 | b.iter(|| { 120 | let mut tmp = v[count]; 121 | tmp.div2(); 122 | count = (count + 1) % SAMPLES; 123 | tmp 124 | }); 125 | } 126 | 127 | #[bench] 128 | fn bench_fq_add_assign(b: &mut ::test::Bencher) { 129 | const SAMPLES: usize = 1000; 130 | 131 | let mut rng = XorShiftRng::from_seed([ 132 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 133 | 0xe5, 134 | ]); 135 | let v: Vec<(Fq, Fq)> = (0..SAMPLES) 136 | .map(|_| (Fq::random(&mut rng), Fq::random(&mut rng))) 137 | .collect(); 138 | 139 | let mut count = 0; 140 | b.iter(|| { 141 | let mut tmp = v[count].0; 142 | tmp.add_assign(&v[count].1); 143 | count = (count + 1) % SAMPLES; 144 | tmp 145 | }); 146 | } 147 | 148 | #[bench] 149 | fn bench_fq_sub_assign(b: &mut ::test::Bencher) { 150 | const SAMPLES: usize = 1000; 151 | 152 | let mut rng = XorShiftRng::from_seed([ 153 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 154 | 0xe5, 155 | ]); 156 | let v: Vec<(Fq, Fq)> = (0..SAMPLES) 157 | .map(|_| (Fq::random(&mut rng), Fq::random(&mut rng))) 158 | .collect(); 159 | 160 | let mut count = 0; 161 | b.iter(|| { 162 | let mut tmp = v[count].0; 163 | tmp.sub_assign(&v[count].1); 164 | count = (count + 1) % SAMPLES; 165 | tmp 166 | }); 167 | } 168 | 169 | #[bench] 170 | fn bench_fq_mul_assign(b: &mut ::test::Bencher) { 171 | const SAMPLES: usize = 1000; 172 | 173 | let mut rng = XorShiftRng::from_seed([ 174 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 175 | 0xe5, 176 | ]); 177 | let v: Vec<(Fq, Fq)> = (0..SAMPLES) 178 | .map(|_| (Fq::random(&mut rng), Fq::random(&mut rng))) 179 | .collect(); 180 | 181 | let mut count = 0; 182 | b.iter(|| { 183 | let mut tmp = v[count].0; 184 | tmp.mul_assign(&v[count].1); 185 | count = (count + 1) % SAMPLES; 186 | tmp 187 | }); 188 | } 189 | 190 | #[bench] 191 | fn bench_fq_square(b: &mut ::test::Bencher) { 192 | const SAMPLES: usize = 1000; 193 | 194 | let mut rng = XorShiftRng::from_seed([ 195 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 196 | 0xe5, 197 | ]); 198 | let v: Vec = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect(); 199 | 200 | let mut count = 0; 201 | b.iter(|| { 202 | let mut tmp = v[count]; 203 | tmp.square(); 204 | count = (count + 1) % SAMPLES; 205 | tmp 206 | }); 207 | } 208 | 209 | #[bench] 210 | fn bench_fq_inverse(b: &mut ::test::Bencher) { 211 | const SAMPLES: usize = 1000; 212 | 213 | let mut rng = XorShiftRng::from_seed([ 214 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 215 | 0xe5, 216 | ]); 217 | let v: Vec = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect(); 218 | 219 | let mut count = 0; 220 | b.iter(|| { 221 | count = (count + 1) % SAMPLES; 222 | v[count].inverse() 223 | }); 224 | } 225 | 226 | #[bench] 227 | fn bench_fq_negate(b: &mut ::test::Bencher) { 228 | const SAMPLES: usize = 1000; 229 | 230 | let mut rng = XorShiftRng::from_seed([ 231 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 232 | 0xe5, 233 | ]); 234 | let v: Vec = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect(); 235 | 236 | let mut count = 0; 237 | b.iter(|| { 238 | let mut tmp = v[count]; 239 | tmp.negate(); 240 | count = (count + 1) % SAMPLES; 241 | tmp 242 | }); 243 | } 244 | 245 | #[bench] 246 | fn bench_fq_sqrt(b: &mut ::test::Bencher) { 247 | const SAMPLES: usize = 1000; 248 | 249 | let mut rng = XorShiftRng::from_seed([ 250 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 251 | 0xe5, 252 | ]); 253 | let v: Vec = (0..SAMPLES) 254 | .map(|_| { 255 | let mut tmp = Fq::random(&mut rng); 256 | tmp.square(); 257 | tmp 258 | }) 259 | .collect(); 260 | 261 | let mut count = 0; 262 | b.iter(|| { 263 | count = (count + 1) % SAMPLES; 264 | v[count].sqrt() 265 | }); 266 | } 267 | 268 | #[bench] 269 | fn bench_fq_into_repr(b: &mut ::test::Bencher) { 270 | const SAMPLES: usize = 1000; 271 | 272 | let mut rng = XorShiftRng::from_seed([ 273 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 274 | 0xe5, 275 | ]); 276 | let v: Vec = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect(); 277 | 278 | let mut count = 0; 279 | b.iter(|| { 280 | count = (count + 1) % SAMPLES; 281 | v[count].into_repr() 282 | }); 283 | } 284 | 285 | #[bench] 286 | fn bench_fq_from_repr(b: &mut ::test::Bencher) { 287 | const SAMPLES: usize = 1000; 288 | 289 | let mut rng = XorShiftRng::from_seed([ 290 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 291 | 0xe5, 292 | ]); 293 | let v: Vec = (0..SAMPLES) 294 | .map(|_| Fq::random(&mut rng).into_repr()) 295 | .collect(); 296 | 297 | let mut count = 0; 298 | b.iter(|| { 299 | count = (count + 1) % SAMPLES; 300 | Fq::from_repr(v[count]) 301 | }); 302 | } 303 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/benches/bls12_381/fr.rs: -------------------------------------------------------------------------------- 1 | use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; 2 | use pairing::bls12_381::*; 3 | use rand_core::SeedableRng; 4 | use rand_xorshift::XorShiftRng; 5 | 6 | #[bench] 7 | fn bench_fr_repr_add_nocarry(b: &mut ::test::Bencher) { 8 | const SAMPLES: usize = 1000; 9 | 10 | let mut rng = XorShiftRng::from_seed([ 11 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 12 | 0xe5, 13 | ]); 14 | let v: Vec<(FrRepr, FrRepr)> = (0..SAMPLES) 15 | .map(|_| { 16 | let mut tmp1 = Fr::random(&mut rng).into_repr(); 17 | let mut tmp2 = Fr::random(&mut rng).into_repr(); 18 | // Shave a few bits off to avoid overflow. 19 | for _ in 0..3 { 20 | tmp1.div2(); 21 | tmp2.div2(); 22 | } 23 | (tmp1, tmp2) 24 | }) 25 | .collect(); 26 | 27 | let mut count = 0; 28 | b.iter(|| { 29 | let mut tmp = v[count].0; 30 | tmp.add_nocarry(&v[count].1); 31 | count = (count + 1) % SAMPLES; 32 | tmp 33 | }); 34 | } 35 | 36 | #[bench] 37 | fn bench_fr_repr_sub_noborrow(b: &mut ::test::Bencher) { 38 | const SAMPLES: usize = 1000; 39 | 40 | let mut rng = XorShiftRng::from_seed([ 41 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 42 | 0xe5, 43 | ]); 44 | let v: Vec<(FrRepr, FrRepr)> = (0..SAMPLES) 45 | .map(|_| { 46 | let tmp1 = Fr::random(&mut rng).into_repr(); 47 | let mut tmp2 = tmp1; 48 | // Ensure tmp2 is smaller than tmp1. 49 | for _ in 0..10 { 50 | tmp2.div2(); 51 | } 52 | (tmp1, tmp2) 53 | }) 54 | .collect(); 55 | 56 | let mut count = 0; 57 | b.iter(|| { 58 | let mut tmp = v[count].0; 59 | tmp.sub_noborrow(&v[count].1); 60 | count = (count + 1) % SAMPLES; 61 | tmp 62 | }); 63 | } 64 | 65 | #[bench] 66 | fn bench_fr_repr_num_bits(b: &mut ::test::Bencher) { 67 | const SAMPLES: usize = 1000; 68 | 69 | let mut rng = XorShiftRng::from_seed([ 70 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 71 | 0xe5, 72 | ]); 73 | let v: Vec = (0..SAMPLES) 74 | .map(|_| Fr::random(&mut rng).into_repr()) 75 | .collect(); 76 | 77 | let mut count = 0; 78 | b.iter(|| { 79 | let tmp = v[count].num_bits(); 80 | count = (count + 1) % SAMPLES; 81 | tmp 82 | }); 83 | } 84 | 85 | #[bench] 86 | fn bench_fr_repr_mul2(b: &mut ::test::Bencher) { 87 | const SAMPLES: usize = 1000; 88 | 89 | let mut rng = XorShiftRng::from_seed([ 90 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 91 | 0xe5, 92 | ]); 93 | let v: Vec = (0..SAMPLES) 94 | .map(|_| Fr::random(&mut rng).into_repr()) 95 | .collect(); 96 | 97 | let mut count = 0; 98 | b.iter(|| { 99 | let mut tmp = v[count]; 100 | tmp.mul2(); 101 | count = (count + 1) % SAMPLES; 102 | tmp 103 | }); 104 | } 105 | 106 | #[bench] 107 | fn bench_fr_repr_div2(b: &mut ::test::Bencher) { 108 | const SAMPLES: usize = 1000; 109 | 110 | let mut rng = XorShiftRng::from_seed([ 111 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 112 | 0xe5, 113 | ]); 114 | let v: Vec = (0..SAMPLES) 115 | .map(|_| Fr::random(&mut rng).into_repr()) 116 | .collect(); 117 | 118 | let mut count = 0; 119 | b.iter(|| { 120 | let mut tmp = v[count]; 121 | tmp.div2(); 122 | count = (count + 1) % SAMPLES; 123 | tmp 124 | }); 125 | } 126 | 127 | #[bench] 128 | fn bench_fr_add_assign(b: &mut ::test::Bencher) { 129 | const SAMPLES: usize = 1000; 130 | 131 | let mut rng = XorShiftRng::from_seed([ 132 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 133 | 0xe5, 134 | ]); 135 | let v: Vec<(Fr, Fr)> = (0..SAMPLES) 136 | .map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))) 137 | .collect(); 138 | 139 | let mut count = 0; 140 | b.iter(|| { 141 | let mut tmp = v[count].0; 142 | tmp.add_assign(&v[count].1); 143 | count = (count + 1) % SAMPLES; 144 | tmp 145 | }); 146 | } 147 | 148 | #[bench] 149 | fn bench_fr_sub_assign(b: &mut ::test::Bencher) { 150 | const SAMPLES: usize = 1000; 151 | 152 | let mut rng = XorShiftRng::from_seed([ 153 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 154 | 0xe5, 155 | ]); 156 | let v: Vec<(Fr, Fr)> = (0..SAMPLES) 157 | .map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))) 158 | .collect(); 159 | 160 | let mut count = 0; 161 | b.iter(|| { 162 | let mut tmp = v[count].0; 163 | tmp.sub_assign(&v[count].1); 164 | count = (count + 1) % SAMPLES; 165 | tmp 166 | }); 167 | } 168 | 169 | #[bench] 170 | fn bench_fr_mul_assign(b: &mut ::test::Bencher) { 171 | const SAMPLES: usize = 1000; 172 | 173 | let mut rng = XorShiftRng::from_seed([ 174 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 175 | 0xe5, 176 | ]); 177 | let v: Vec<(Fr, Fr)> = (0..SAMPLES) 178 | .map(|_| (Fr::random(&mut rng), Fr::random(&mut rng))) 179 | .collect(); 180 | 181 | let mut count = 0; 182 | b.iter(|| { 183 | let mut tmp = v[count].0; 184 | tmp.mul_assign(&v[count].1); 185 | count = (count + 1) % SAMPLES; 186 | tmp 187 | }); 188 | } 189 | 190 | #[bench] 191 | fn bench_fr_square(b: &mut ::test::Bencher) { 192 | const SAMPLES: usize = 1000; 193 | 194 | let mut rng = XorShiftRng::from_seed([ 195 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 196 | 0xe5, 197 | ]); 198 | let v: Vec = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect(); 199 | 200 | let mut count = 0; 201 | b.iter(|| { 202 | let mut tmp = v[count]; 203 | tmp.square(); 204 | count = (count + 1) % SAMPLES; 205 | tmp 206 | }); 207 | } 208 | 209 | #[bench] 210 | fn bench_fr_inverse(b: &mut ::test::Bencher) { 211 | const SAMPLES: usize = 1000; 212 | 213 | let mut rng = XorShiftRng::from_seed([ 214 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 215 | 0xe5, 216 | ]); 217 | let v: Vec = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect(); 218 | 219 | let mut count = 0; 220 | b.iter(|| { 221 | count = (count + 1) % SAMPLES; 222 | v[count].inverse() 223 | }); 224 | } 225 | 226 | #[bench] 227 | fn bench_fr_negate(b: &mut ::test::Bencher) { 228 | const SAMPLES: usize = 1000; 229 | 230 | let mut rng = XorShiftRng::from_seed([ 231 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 232 | 0xe5, 233 | ]); 234 | let v: Vec = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect(); 235 | 236 | let mut count = 0; 237 | b.iter(|| { 238 | let mut tmp = v[count]; 239 | tmp.negate(); 240 | count = (count + 1) % SAMPLES; 241 | tmp 242 | }); 243 | } 244 | 245 | #[bench] 246 | fn bench_fr_sqrt(b: &mut ::test::Bencher) { 247 | const SAMPLES: usize = 1000; 248 | 249 | let mut rng = XorShiftRng::from_seed([ 250 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 251 | 0xe5, 252 | ]); 253 | let v: Vec = (0..SAMPLES) 254 | .map(|_| { 255 | let mut tmp = Fr::random(&mut rng); 256 | tmp.square(); 257 | tmp 258 | }) 259 | .collect(); 260 | 261 | let mut count = 0; 262 | b.iter(|| { 263 | count = (count + 1) % SAMPLES; 264 | v[count].sqrt() 265 | }); 266 | } 267 | 268 | #[bench] 269 | fn bench_fr_into_repr(b: &mut ::test::Bencher) { 270 | const SAMPLES: usize = 1000; 271 | 272 | let mut rng = XorShiftRng::from_seed([ 273 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 274 | 0xe5, 275 | ]); 276 | let v: Vec = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect(); 277 | 278 | let mut count = 0; 279 | b.iter(|| { 280 | count = (count + 1) % SAMPLES; 281 | v[count].into_repr() 282 | }); 283 | } 284 | 285 | #[bench] 286 | fn bench_fr_from_repr(b: &mut ::test::Bencher) { 287 | const SAMPLES: usize = 1000; 288 | 289 | let mut rng = XorShiftRng::from_seed([ 290 | 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc, 291 | 0xe5, 292 | ]); 293 | let v: Vec = (0..SAMPLES) 294 | .map(|_| Fr::random(&mut rng).into_repr()) 295 | .collect(); 296 | 297 | let mut count = 0; 298 | b.iter(|| { 299 | count = (count + 1) % SAMPLES; 300 | Fr::from_repr(v[count]) 301 | }); 302 | } 303 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/isogeny/g2.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Constants for G2 isogeny. 3 | */ 4 | 5 | use super::{eval_iso, IsogenyMap}; 6 | use crate::bls12_381::{Fq, Fq2, FqRepr, G2}; 7 | 8 | /// Coefficients of the 3-isogeny x map's numerator 9 | const XNUM: [Fq2; 4] = [ 10 | Fq2 { 11 | c0: Fq(FqRepr([ 12 | 0x47f671c71ce05e62u64, 13 | 0x06dd57071206393eu64, 14 | 0x7c80cd2af3fd71a2u64, 15 | 0x048103ea9e6cd062u64, 16 | 0xc54516acc8d037f6u64, 17 | 0x13808f550920ea41u64, 18 | ])), 19 | c1: Fq(FqRepr([ 20 | 0x47f671c71ce05e62u64, 21 | 0x06dd57071206393eu64, 22 | 0x7c80cd2af3fd71a2u64, 23 | 0x048103ea9e6cd062u64, 24 | 0xc54516acc8d037f6u64, 25 | 0x13808f550920ea41u64, 26 | ])), 27 | }, 28 | Fq2 { 29 | c0: Fq(FqRepr([ 30 | 0x0000000000000000u64, 31 | 0x0000000000000000u64, 32 | 0x0000000000000000u64, 33 | 0x0000000000000000u64, 34 | 0x0000000000000000u64, 35 | 0x0000000000000000u64, 36 | ])), 37 | c1: Fq(FqRepr([ 38 | 0x5fe55555554c71d0u64, 39 | 0x873fffdd236aaaa3u64, 40 | 0x6a6b4619b26ef918u64, 41 | 0x21c2888408874945u64, 42 | 0x2836cda7028cabc5u64, 43 | 0x0ac73310a7fd5abdu64, 44 | ])), 45 | }, 46 | Fq2 { 47 | c0: Fq(FqRepr([ 48 | 0x0a0c5555555971c3u64, 49 | 0xdb0c00101f9eaaaeu64, 50 | 0xb1fb2f941d797997u64, 51 | 0xd3960742ef416e1cu64, 52 | 0xb70040e2c20556f4u64, 53 | 0x149d7861e581393bu64, 54 | ])), 55 | c1: Fq(FqRepr([ 56 | 0xaff2aaaaaaa638e8u64, 57 | 0x439fffee91b55551u64, 58 | 0xb535a30cd9377c8cu64, 59 | 0x90e144420443a4a2u64, 60 | 0x941b66d3814655e2u64, 61 | 0x0563998853fead5eu64, 62 | ])), 63 | }, 64 | Fq2 { 65 | c0: Fq(FqRepr([ 66 | 0x40aac71c71c725edu64, 67 | 0x190955557a84e38eu64, 68 | 0xd817050a8f41abc3u64, 69 | 0xd86485d4c87f6fb1u64, 70 | 0x696eb479f885d059u64, 71 | 0x198e1a74328002d2u64, 72 | ])), 73 | c1: Fq(FqRepr([ 74 | 0x0000000000000000u64, 75 | 0x0000000000000000u64, 76 | 0x0000000000000000u64, 77 | 0x0000000000000000u64, 78 | 0x0000000000000000u64, 79 | 0x0000000000000000u64, 80 | ])), 81 | }, 82 | ]; 83 | 84 | /// Coefficients of the 3-isogeny x map's denominator 85 | const XDEN: [Fq2; 3] = [ 86 | Fq2 { 87 | c0: Fq(FqRepr([ 88 | 0x0000000000000000u64, 89 | 0x0000000000000000u64, 90 | 0x0000000000000000u64, 91 | 0x0000000000000000u64, 92 | 0x0000000000000000u64, 93 | 0x0000000000000000u64, 94 | ])), 95 | c1: Fq(FqRepr([ 96 | 0x1f3affffff13ab97u64, 97 | 0xf25bfc611da3ff3eu64, 98 | 0xca3757cb3819b208u64, 99 | 0x3e6427366f8cec18u64, 100 | 0x03977bc86095b089u64, 101 | 0x04f69db13f39a952u64, 102 | ])), 103 | }, 104 | Fq2 { 105 | c0: Fq(FqRepr([ 106 | 0x447600000027552eu64, 107 | 0xdcb8009a43480020u64, 108 | 0x6f7ee9ce4a6e8b59u64, 109 | 0xb10330b7c0a95bc6u64, 110 | 0x6140b1fcfb1e54b7u64, 111 | 0x0381be097f0bb4e1u64, 112 | ])), 113 | c1: Fq(FqRepr([ 114 | 0x7588ffffffd8557du64, 115 | 0x41f3ff646e0bffdfu64, 116 | 0xf7b1e8d2ac426acau64, 117 | 0xb3741acd32dbb6f8u64, 118 | 0xe9daf5b9482d581fu64, 119 | 0x167f53e0ba7431b8u64, 120 | ])), 121 | }, 122 | Fq2 { 123 | c0: Fq(FqRepr([ 124 | 0x760900000002fffdu64, 125 | 0xebf4000bc40c0002u64, 126 | 0x5f48985753c758bau64, 127 | 0x77ce585370525745u64, 128 | 0x5c071a97a256ec6du64, 129 | 0x15f65ec3fa80e493u64, 130 | ])), 131 | c1: Fq(FqRepr([ 132 | 0x0000000000000000u64, 133 | 0x0000000000000000u64, 134 | 0x0000000000000000u64, 135 | 0x0000000000000000u64, 136 | 0x0000000000000000u64, 137 | 0x0000000000000000u64, 138 | ])), 139 | }, 140 | ]; 141 | 142 | /// Coefficients of the 3-isogeny y map's numerator 143 | const YNUM: [Fq2; 4] = [ 144 | Fq2 { 145 | c0: Fq(FqRepr([ 146 | 0x96d8f684bdfc77beu64, 147 | 0xb530e4f43b66d0e2u64, 148 | 0x184a88ff379652fdu64, 149 | 0x57cb23ecfae804e1u64, 150 | 0x0fd2e39eada3eba9u64, 151 | 0x08c8055e31c5d5c3u64, 152 | ])), 153 | c1: Fq(FqRepr([ 154 | 0x96d8f684bdfc77beu64, 155 | 0xb530e4f43b66d0e2u64, 156 | 0x184a88ff379652fdu64, 157 | 0x57cb23ecfae804e1u64, 158 | 0x0fd2e39eada3eba9u64, 159 | 0x08c8055e31c5d5c3u64, 160 | ])), 161 | }, 162 | Fq2 { 163 | c0: Fq(FqRepr([ 164 | 0x0000000000000000u64, 165 | 0x0000000000000000u64, 166 | 0x0000000000000000u64, 167 | 0x0000000000000000u64, 168 | 0x0000000000000000u64, 169 | 0x0000000000000000u64, 170 | ])), 171 | c1: Fq(FqRepr([ 172 | 0xbf0a71c71c91b406u64, 173 | 0x4d6d55d28b7638fdu64, 174 | 0x9d82f98e5f205aeeu64, 175 | 0xa27aa27b1d1a18d5u64, 176 | 0x02c3b2b2d2938e86u64, 177 | 0x0c7d13420b09807fu64, 178 | ])), 179 | }, 180 | Fq2 { 181 | c0: Fq(FqRepr([ 182 | 0xd7f9555555531c74u64, 183 | 0x21cffff748daaaa8u64, 184 | 0x5a9ad1866c9bbe46u64, 185 | 0x4870a2210221d251u64, 186 | 0x4a0db369c0a32af1u64, 187 | 0x02b1ccc429ff56afu64, 188 | ])), 189 | c1: Fq(FqRepr([ 190 | 0xe205aaaaaaac8e37u64, 191 | 0xfcdc000768795556u64, 192 | 0x0c96011a8a1537ddu64, 193 | 0x1c06a963f163406eu64, 194 | 0x010df44c82a881e6u64, 195 | 0x174f45260f808febu64, 196 | ])), 197 | }, 198 | Fq2 { 199 | c0: Fq(FqRepr([ 200 | 0xa470bda12f67f35cu64, 201 | 0xc0fe38e23327b425u64, 202 | 0xc9d3d0f2c6f0678du64, 203 | 0x1c55c9935b5a982eu64, 204 | 0x27f6c0e2f0746764u64, 205 | 0x117c5e6e28aa9054u64, 206 | ])), 207 | c1: Fq(FqRepr([ 208 | 0x0000000000000000u64, 209 | 0x0000000000000000u64, 210 | 0x0000000000000000u64, 211 | 0x0000000000000000u64, 212 | 0x0000000000000000u64, 213 | 0x0000000000000000u64, 214 | ])), 215 | }, 216 | ]; 217 | 218 | /// Coefficients of the 3-isogeny y map's denominator 219 | const YDEN: [Fq2; 4] = [ 220 | Fq2 { 221 | c0: Fq(FqRepr([ 222 | 0x0162fffffa765adfu64, 223 | 0x8f7bea480083fb75u64, 224 | 0x561b3c2259e93611u64, 225 | 0x11e19fc1a9c875d5u64, 226 | 0xca713efc00367660u64, 227 | 0x03c6a03d41da1151u64, 228 | ])), 229 | c1: Fq(FqRepr([ 230 | 0x0162fffffa765adfu64, 231 | 0x8f7bea480083fb75u64, 232 | 0x561b3c2259e93611u64, 233 | 0x11e19fc1a9c875d5u64, 234 | 0xca713efc00367660u64, 235 | 0x03c6a03d41da1151u64, 236 | ])), 237 | }, 238 | Fq2 { 239 | c0: Fq(FqRepr([ 240 | 0x0000000000000000u64, 241 | 0x0000000000000000u64, 242 | 0x0000000000000000u64, 243 | 0x0000000000000000u64, 244 | 0x0000000000000000u64, 245 | 0x0000000000000000u64, 246 | ])), 247 | c1: Fq(FqRepr([ 248 | 0x5db0fffffd3b02c5u64, 249 | 0xd713f52358ebfdbau64, 250 | 0x5ea60761a84d161au64, 251 | 0xbb2c75a34ea6c44au64, 252 | 0x0ac6735921c1119bu64, 253 | 0x0ee3d913bdacfbf6u64, 254 | ])), 255 | }, 256 | Fq2 { 257 | c0: Fq(FqRepr([ 258 | 0x66b10000003affc5u64, 259 | 0xcb1400e764ec0030u64, 260 | 0xa73e5eb56fa5d106u64, 261 | 0x8984c913a0fe09a9u64, 262 | 0x11e10afb78ad7f13u64, 263 | 0x05429d0e3e918f52u64, 264 | ])), 265 | c1: Fq(FqRepr([ 266 | 0x534dffffffc4aae6u64, 267 | 0x5397ff174c67ffcfu64, 268 | 0xbff273eb870b251du64, 269 | 0xdaf2827152870915u64, 270 | 0x393a9cbaca9e2dc3u64, 271 | 0x14be74dbfaee5748u64, 272 | ])), 273 | }, 274 | Fq2 { 275 | c0: Fq(FqRepr([ 276 | 0x760900000002fffdu64, 277 | 0xebf4000bc40c0002u64, 278 | 0x5f48985753c758bau64, 279 | 0x77ce585370525745u64, 280 | 0x5c071a97a256ec6du64, 281 | 0x15f65ec3fa80e493u64, 282 | ])), 283 | c1: Fq(FqRepr([ 284 | 0x0000000000000000u64, 285 | 0x0000000000000000u64, 286 | 0x0000000000000000u64, 287 | 0x0000000000000000u64, 288 | 0x0000000000000000u64, 289 | 0x0000000000000000u64, 290 | ])), 291 | }, 292 | ]; 293 | 294 | impl IsogenyMap for G2 { 295 | fn isogeny_map(&mut self) { 296 | eval_iso(self, [&XNUM[..], &XDEN[..], &YNUM[..], &YDEN[..]]); 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /accumulator-rsa/src/witnessnon.rs: -------------------------------------------------------------------------------- 1 | use crate::{accumulator::Accumulator, b2fa, hash_to_prime, FACTOR_SIZE, MEMBER_SIZE}; 2 | use common::{bigint::BigInteger, Field, error::*}; 3 | use rayon::prelude::*; 4 | 5 | /// A witness that can be used for non-membership proofs 6 | #[derive(Debug, Eq, PartialEq, Clone)] 7 | pub struct NonMembershipWitness { 8 | pub(crate) a: BigInteger, 9 | pub(crate) b: BigInteger, 10 | pub(crate) x: BigInteger, 11 | } 12 | 13 | impl NonMembershipWitness { 14 | /// Return a new non-membership witness 15 | pub fn new>(accumulator: &Accumulator, x: B) -> Result { 16 | let x = hash_to_prime(x.as_ref()); 17 | Self::new_prime(accumulator, &x) 18 | } 19 | 20 | /// Return a new non-membership witness with a value that is already prime 21 | pub fn new_prime(accumulator: &Accumulator, x: &BigInteger) -> Result { 22 | if accumulator.members.contains(&x) { 23 | return Err(AccumulatorError::from_msg( 24 | AccumulatorErrorKind::InvalidMemberSupplied, 25 | "value is in the accumulator", 26 | )); 27 | } 28 | let f = Field::new(&accumulator.modulus); 29 | let s: BigInteger = accumulator.members.par_iter().product(); 30 | let gcd_res = s.bezouts_coefficients(x); 31 | let b = f.exp(&f.inv(&accumulator.generator), &gcd_res.b); 32 | debug_assert_eq!(f.exp(&b, &x), f.mul(&f.inv(&accumulator.generator), &f.exp(&accumulator.value, &gcd_res.a))); 33 | 34 | Ok(Self { 35 | a: gcd_res.a, 36 | b, 37 | x: x.clone(), 38 | }) 39 | } 40 | 41 | /// Create a new witness to match `new_acc` from `old_acc` using this witness 42 | /// by applying the methods found in 4.2 in 43 | /// 44 | pub fn update(&self, old_acc: &Accumulator, new_acc: &Accumulator) -> Result { 45 | let mut w = self.clone(); 46 | w.update_assign(old_acc, new_acc)?; 47 | Ok(w) 48 | } 49 | 50 | /// Update this witness to match `new_acc` from `old_acc` 51 | /// by applying the methods found in 4.2 in 52 | /// 53 | pub fn update_assign(&mut self, old_acc: &Accumulator, new_acc: &Accumulator) -> Result<(), AccumulatorError> { 54 | if new_acc.members.contains(&self.x) { 55 | return Err(AccumulatorErrorKind::InvalidMemberSupplied.into()); 56 | } 57 | if old_acc.members.contains(&self.x) { 58 | return Err(AccumulatorErrorKind::InvalidMemberSupplied.into()); 59 | } 60 | 61 | debug_assert_eq!(&old_acc.value.mod_exp(&self.a, &old_acc.modulus), &self.b.mod_exp(&self.x, &old_acc.modulus).mod_mul(&old_acc.generator, &old_acc.modulus)); 62 | 63 | let additions: Vec<&BigInteger> = new_acc.members.difference(&old_acc.members).collect(); 64 | let deletions: Vec<&BigInteger> = old_acc.members.difference(&new_acc.members).collect(); 65 | 66 | if additions.is_empty() && deletions.is_empty() { 67 | return Ok(()); 68 | } 69 | 70 | let f = Field::new(&new_acc.modulus); 71 | 72 | if !deletions.is_empty() { 73 | let x_hat = deletions.into_par_iter().product(); 74 | let r = &(&x_hat * &self.a) / &self.x; 75 | self.a = (&self.a * &x_hat) - (&r * &self.x); 76 | self.b = f.mul(&self.b, &f.exp(&f.inv(&new_acc.value), &r)); 77 | // Check if the assumption holds 78 | //\widehat{c}^\widehat{a} == g B^{x} 79 | debug_assert_eq!(f.exp(&new_acc.value, &self.a), f.mul(&new_acc.generator, &f.exp(&self.b, &self.x))); 80 | } 81 | 82 | // Section 4.2 in 83 | // 84 | if !additions.is_empty() { 85 | let x_hat: BigInteger = additions.into_par_iter().product(); 86 | let gcd_result = x_hat.bezouts_coefficients(&self.x); 87 | 88 | debug_assert_eq!(BigInteger::from(1), &x_hat * &gcd_result.a + &self.x * &gcd_result.b); 89 | 90 | let a_hat = self.a.mod_mul(&gcd_result.a, &self.x); 91 | 92 | debug_assert_eq!(&self.a % &self.x, a_hat.mod_mul(&x_hat, &self.x)); 93 | 94 | let r = &(&(&a_hat * &x_hat) - &self.a) / &self.x; 95 | 96 | debug_assert_eq!(&BigInteger::from(0), &(&(&self.a + &(&r * &self.x)) % &x_hat)); 97 | 98 | let field = Field::new(&self.a); 99 | 100 | debug_assert_eq!(field.mul(&a_hat, &x_hat), field.mul(&r, &self.x)); 101 | 102 | let b_hat = f.mul(&self.b, &f.exp(&old_acc.value, &r)); 103 | 104 | self.a = a_hat; 105 | self.b = b_hat; 106 | // c_hat^a_hat == b_hat^x g 107 | debug_assert_eq!(f.exp(&new_acc.value, &self.a), f.mul(&new_acc.generator, &f.exp(&self.b, &self.x))); 108 | } 109 | 110 | Ok(()) 111 | } 112 | 113 | /// Serialize this to bytes 114 | pub fn to_bytes(&self) -> Vec { 115 | let mut output = b2fa(&self.a, FACTOR_SIZE * 2); 116 | output.append(&mut b2fa(&self.b, FACTOR_SIZE * 2)); 117 | output.append(&mut b2fa(&self.x, MEMBER_SIZE)); 118 | output 119 | } 120 | } 121 | 122 | #[cfg(test)] 123 | mod tests { 124 | use super::*; 125 | use crate::key::SecretKey; 126 | use crate::MEMBER_SIZE_BITS; 127 | 128 | #[test] 129 | fn witnesses() { 130 | let key = SecretKey::default(); 131 | let members: Vec<[u8; 8]> = vec![ 132 | 23u64.to_be_bytes(), 133 | 7u64.to_be_bytes(), 134 | 11u64.to_be_bytes(), 135 | 13u64.to_be_bytes(), 136 | ]; 137 | let member = 17u64.to_be_bytes(); 138 | let acc = Accumulator::with_members(&key, &members); 139 | let witness = NonMembershipWitness::new(&acc, &member).unwrap(); 140 | let x = hash_to_prime(&member); 141 | assert_eq!(witness.x, x); 142 | assert_eq!( 143 | witness.a, 144 | BigInteger::from( 145 | "-15810496871052012929721951174424824308288730437435807996081044306834293553183" 146 | ) 147 | ); 148 | assert_eq!(witness.b, BigInteger::from("19731949503840799383004983499976351402593806159011822165741044085004905054673855363251385357597006492205730905650466488066773470871149400842396325545777674920024532296129116696323189577451048138544518857167383327747625073230517859862062456981747960458354502115002928340061239460009397008827664942646578083788378616855856348273253698783745015718408649373541254454588228353839211861287000689818331397142653546216894453995644059116432377166068316662466227209474894641100413409398337545057792037057027550522667399457451683638422319281726301941188118255274194652039389040737481315040156989596592391081668567908550005221922")); 149 | 150 | assert_eq!(witness.to_bytes().len(), 4 * FACTOR_SIZE + MEMBER_SIZE); 151 | } 152 | 153 | #[test] 154 | fn updates() { 155 | let key = SecretKey::default(); 156 | let members: Vec<[u8; 8]> = vec![ 157 | 23u64.to_be_bytes(), 158 | 7u64.to_be_bytes(), 159 | 11u64.to_be_bytes(), 160 | 13u64.to_be_bytes(), 161 | 17u64.to_be_bytes(), 162 | 19u64.to_be_bytes(), 163 | ]; 164 | let member = 37u64.to_be_bytes(); 165 | let acc = Accumulator::with_members(&key, &members); 166 | let witness = NonMembershipWitness::new(&acc, &member).unwrap(); 167 | 168 | // Test add update 169 | let acc_prime = &acc + 29u64; 170 | 171 | let res = witness.update(&acc, &acc_prime); 172 | assert!(res.is_ok()); 173 | let new_w = res.unwrap(); 174 | 175 | let expected_witness = NonMembershipWitness::new(&acc_prime, &member).unwrap(); 176 | assert_eq!(expected_witness.a, new_w.a); 177 | assert_eq!(expected_witness.b, new_w.b); 178 | 179 | // Test remove update 180 | let mut new_acc = acc_prime.remove_u64(&key, 19u64).unwrap(); 181 | let res = new_w.update(&acc_prime, &new_acc); 182 | assert!(res.is_ok()); 183 | let new_w = res.unwrap(); 184 | let expected_witness = NonMembershipWitness::new(&new_acc, &member).unwrap(); 185 | assert_eq!(expected_witness.a, new_w.a); 186 | assert_eq!(expected_witness.b, new_w.b); 187 | 188 | let acc_prime = new_acc.clone(); 189 | new_acc += 31u64; 190 | new_acc += 41u64; 191 | new_acc += 47u64; 192 | let res = new_w.update(&acc_prime, &new_acc); 193 | assert!(res.is_ok()); 194 | let new_w = res.unwrap(); 195 | let expected_witness = NonMembershipWitness::new(&new_acc, &member).unwrap(); 196 | assert_eq!(expected_witness.a, new_w.a); 197 | assert_eq!(expected_witness.b, new_w.b); 198 | } 199 | 200 | #[test] 201 | fn big_updates() { 202 | let key = SecretKey::default(); 203 | let members = (0..10).collect::>().par_iter().map(|_| BigInteger::generate_prime(MEMBER_SIZE_BITS)).collect::>(); 204 | let x = BigInteger::generate_prime(MEMBER_SIZE_BITS); 205 | 206 | let acc = Accumulator::with_prime_members(&key, &members).unwrap(); 207 | let witness = NonMembershipWitness::new_prime(&acc, &x).unwrap(); 208 | 209 | // let mut new_acc = acc.clone(); 210 | let mut new_members = Vec::new(); 211 | for _ in 0..3 { 212 | // acc.insert_prime(&BigInteger::generate_prime(MEMBER_SIZE_BITS)).unwrap(); 213 | new_members.push(BigInteger::generate_prime(MEMBER_SIZE_BITS)); 214 | } 215 | 216 | let new_acc = acc.add_prime_members(new_members.as_slice()); 217 | assert!(new_acc.is_ok()); 218 | let new_acc = new_acc.unwrap(); 219 | let res = witness.update(&acc, &new_acc); 220 | assert!(res.is_ok()); 221 | let new_w = res.unwrap(); 222 | 223 | let expected_w = NonMembershipWitness::new_prime(&new_acc, &x).unwrap(); 224 | assert_eq!(expected_w.a, new_w.a); 225 | assert_eq!(expected_w.b, new_w.b); 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/osswu_map/g2.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Constants for OSSWU map for G2 3 | */ 4 | 5 | use super::chain::chain_p2m9div16; 6 | use super::{osswu_help, OSSWUMap}; 7 | use crate::bls12_381::{Fq, Fq2, FqRepr, G2}; 8 | use crate::signum::Signum0; 9 | use ff::Field; 10 | 11 | pub(super) const ELLP_A: Fq2 = Fq2 { 12 | c0: Fq(FqRepr([ 13 | 0x0000000000000000u64, 14 | 0x0000000000000000u64, 15 | 0x0000000000000000u64, 16 | 0x0000000000000000u64, 17 | 0x0000000000000000u64, 18 | 0x0000000000000000u64, 19 | ])), 20 | c1: Fq(FqRepr([ 21 | 0xe53a000003135242u64, 22 | 0x01080c0fdef80285u64, 23 | 0xe7889edbe340f6bdu64, 24 | 0x0b51375126310601u64, 25 | 0x02d6985717c744abu64, 26 | 0x1220b4e979ea5467u64, 27 | ])), 28 | }; 29 | 30 | pub(super) const ELLP_B: Fq2 = Fq2 { 31 | c0: Fq(FqRepr([ 32 | 0x22ea00000cf89db2u64, 33 | 0x6ec832df71380aa4u64, 34 | 0x6e1b94403db5a66eu64, 35 | 0x75bf3c53a79473bau64, 36 | 0x3dd3a569412c0a34u64, 37 | 0x125cdb5e74dc4fd1u64, 38 | ])), 39 | c1: Fq(FqRepr([ 40 | 0x22ea00000cf89db2u64, 41 | 0x6ec832df71380aa4u64, 42 | 0x6e1b94403db5a66eu64, 43 | 0x75bf3c53a79473bau64, 44 | 0x3dd3a569412c0a34u64, 45 | 0x125cdb5e74dc4fd1u64, 46 | ])), 47 | }; 48 | 49 | const XI: Fq2 = Fq2 { 50 | c0: Fq(FqRepr([ 51 | 0x87ebfffffff9555cu64, 52 | 0x656fffe5da8ffffau64, 53 | 0xfd0749345d33ad2u64, 54 | 0xd951e663066576f4u64, 55 | 0xde291a3d41e980d3u64, 56 | 0x815664c7dfe040du64, 57 | ])), 58 | c1: Fq(FqRepr([ 59 | 0x43f5fffffffcaaaeu64, 60 | 0x32b7fff2ed47fffdu64, 61 | 0x7e83a49a2e99d69u64, 62 | 0xeca8f3318332bb7au64, 63 | 0xef148d1ea0f4c069u64, 64 | 0x40ab3263eff0206u64, 65 | ])), 66 | }; 67 | 68 | const ETAS: [Fq2; 4] = [ 69 | Fq2 { 70 | c0: Fq(FqRepr([ 71 | 0x5e514668ac736d2u64, 72 | 0x9089b4d6b84f3ea5u64, 73 | 0x603c384c224a8b32u64, 74 | 0xf3257909536afea6u64, 75 | 0x5c5cdbabae656d81u64, 76 | 0x75bfa0863c987e9u64, 77 | ])), 78 | c1: Fq(FqRepr([ 79 | 0x338d9bfe08087330u64, 80 | 0x7b8e48b2bd83cefeu64, 81 | 0x530dad5d306b5be7u64, 82 | 0x5a4d7e8e6c408b6du64, 83 | 0x6258f7a6232cab9bu64, 84 | 0xb985811cce14db5u64, 85 | ])), 86 | }, 87 | Fq2 { 88 | c0: Fq(FqRepr([ 89 | 0x86716401f7f7377bu64, 90 | 0xa31db74bf3d03101u64, 91 | 0x14232543c6459a3cu64, 92 | 0xa29ccf687448752u64, 93 | 0xe8c2b010201f013cu64, 94 | 0xe68b9d86c9e98e4u64, 95 | ])), 96 | c1: Fq(FqRepr([ 97 | 0x5e514668ac736d2u64, 98 | 0x9089b4d6b84f3ea5u64, 99 | 0x603c384c224a8b32u64, 100 | 0xf3257909536afea6u64, 101 | 0x5c5cdbabae656d81u64, 102 | 0x75bfa0863c987e9u64, 103 | ])), 104 | }, 105 | Fq2 { 106 | c0: Fq(FqRepr([ 107 | 0x718fdad24ee1d90fu64, 108 | 0xa58c025bed8276afu64, 109 | 0xc3a10230ab7976fu64, 110 | 0xf0c54df5c8f275e1u64, 111 | 0x4ec2478c28baf465u64, 112 | 0x1129373a90c508e6u64, 113 | ])), 114 | c1: Fq(FqRepr([ 115 | 0x19af5f980a3680cu64, 116 | 0x4ed7da0e66063afau64, 117 | 0x600354723b5d9972u64, 118 | 0x8b2f958b20d09d72u64, 119 | 0x474938f02d461dbu64, 120 | 0xdcf8b9e0684ab1cu64, 121 | ])), 122 | }, 123 | Fq2 { 124 | c0: Fq(FqRepr([ 125 | 0xb8640a067f5c429fu64, 126 | 0xcfd425f04b4dc505u64, 127 | 0x72d7e2ebb535cb1u64, 128 | 0xd947b5f9d2b4754du64, 129 | 0x46a7142740774afbu64, 130 | 0xc31864c32fb3b7eu64, 131 | ])), 132 | c1: Fq(FqRepr([ 133 | 0x718fdad24ee1d90fu64, 134 | 0xa58c025bed8276afu64, 135 | 0xc3a10230ab7976fu64, 136 | 0xf0c54df5c8f275e1u64, 137 | 0x4ec2478c28baf465u64, 138 | 0x1129373a90c508e6u64, 139 | ])), 140 | }, 141 | ]; 142 | 143 | pub(crate) const ROOTS_OF_UNITY: [Fq2; 4] = [ 144 | Fq2 { 145 | c0: Fq(FqRepr([ 146 | 0x760900000002fffdu64, 147 | 0xebf4000bc40c0002u64, 148 | 0x5f48985753c758bau64, 149 | 0x77ce585370525745u64, 150 | 0x5c071a97a256ec6du64, 151 | 0x15f65ec3fa80e493u64, 152 | ])), 153 | c1: Fq(FqRepr([ 154 | 0x0000000000000000u64, 155 | 0x0000000000000000u64, 156 | 0x0000000000000000u64, 157 | 0x0000000000000000u64, 158 | 0x0000000000000000u64, 159 | 0x0000000000000000u64, 160 | ])), 161 | }, 162 | Fq2 { 163 | c0: Fq(FqRepr([ 164 | 0x0000000000000000u64, 165 | 0x0000000000000000u64, 166 | 0x0000000000000000u64, 167 | 0x0000000000000000u64, 168 | 0x0000000000000000u64, 169 | 0x0000000000000000u64, 170 | ])), 171 | c1: Fq(FqRepr([ 172 | 0x760900000002fffdu64, 173 | 0xebf4000bc40c0002u64, 174 | 0x5f48985753c758bau64, 175 | 0x77ce585370525745u64, 176 | 0x5c071a97a256ec6du64, 177 | 0x15f65ec3fa80e493u64, 178 | ])), 179 | }, 180 | Fq2 { 181 | c0: Fq(FqRepr([ 182 | 0x7bcfa7a25aa30fdau64, 183 | 0xdc17dec12a927e7cu64, 184 | 0x2f088dd86b4ebef1u64, 185 | 0xd1ca2087da74d4a7u64, 186 | 0x2da2596696cebc1du64, 187 | 0x0e2b7eedbbfd87d2u64, 188 | ])), 189 | c1: Fq(FqRepr([ 190 | 0x7bcfa7a25aa30fdau64, 191 | 0xdc17dec12a927e7cu64, 192 | 0x2f088dd86b4ebef1u64, 193 | 0xd1ca2087da74d4a7u64, 194 | 0x2da2596696cebc1du64, 195 | 0x0e2b7eedbbfd87d2u64, 196 | ])), 197 | }, 198 | Fq2 { 199 | c0: Fq(FqRepr([ 200 | 0x7bcfa7a25aa30fdau64, 201 | 0xdc17dec12a927e7cu64, 202 | 0x2f088dd86b4ebef1u64, 203 | 0xd1ca2087da74d4a7u64, 204 | 0x2da2596696cebc1du64, 205 | 0x0e2b7eedbbfd87d2u64, 206 | ])), 207 | c1: Fq(FqRepr([ 208 | 0x3e2f585da55c9ad1u64, 209 | 0x4294213d86c18183u64, 210 | 0x382844c88b623732u64, 211 | 0x92ad2afd19103e18u64, 212 | 0x1d794e4fac7cf0b9u64, 213 | 0x0bd592fc7d825ec8u64, 214 | ])), 215 | }, 216 | ]; 217 | 218 | impl OSSWUMap for G2 { 219 | fn osswu_map(u: &Fq2) -> G2 { 220 | // compute x0 and g(x0) 221 | let [usq, xi_usq, xi2_u4, x0_num, x0_den, gx0_num, gx0_den] = 222 | osswu_help(u, &XI, &ELLP_A, &ELLP_B); 223 | 224 | // compute g(x0(u)) ^ ((p - 9) // 16) 225 | let sqrt_candidate = { 226 | let mut tmp1 = gx0_den; // v 227 | tmp1.square(); // v^2 228 | let mut tmp2 = tmp1; 229 | tmp1.square(); // v^4 230 | tmp2.mul_assign(&tmp1); // v^6 231 | tmp2.mul_assign(&gx0_den); // v^7 232 | tmp2.mul_assign(&gx0_num); // u v^7 233 | tmp1.square(); // v^8 234 | tmp1.mul_assign(&tmp2); // u v^15 235 | let tmp3 = tmp1; 236 | chain_p2m9div16(&mut tmp1, &tmp3); // (u v^15) ^ ((p - 9) // 16) 237 | tmp1.mul_assign(&tmp2); // u v^7 (u v^15) ^ ((p - 9) // 16) 238 | tmp1 239 | }; 240 | 241 | for root in &ROOTS_OF_UNITY[..] { 242 | let mut y0 = *root; 243 | y0.mul_assign(&sqrt_candidate); 244 | 245 | let mut tmp = y0; 246 | tmp.square(); 247 | tmp.mul_assign(&gx0_den); 248 | if tmp == gx0_num { 249 | let sgn0_y_xor_u = y0.sgn0() ^ u.sgn0(); 250 | y0.negate_if(sgn0_y_xor_u); 251 | y0.mul_assign(&gx0_den); // y * x0_den^3 / x0_den^3 = y 252 | 253 | tmp = x0_num; 254 | tmp.mul_assign(&x0_den); // x0_num * x0_den / x0_den^2 = x0_num / x0_den 255 | 256 | return G2 { 257 | x: tmp, 258 | y: y0, 259 | z: x0_den, 260 | }; 261 | } 262 | } 263 | 264 | // If we've gotten here, g(X0(u)) is not square. Use X1 instead. 265 | let x1_num = { 266 | let mut tmp = x0_num; 267 | tmp.mul_assign(&xi_usq); 268 | tmp 269 | }; 270 | let gx1_num = { 271 | let mut tmp = xi2_u4; 272 | tmp.mul_assign(&xi_usq); // xi^3 u^6 273 | tmp.mul_assign(&gx0_num); 274 | tmp 275 | }; 276 | let sqrt_candidate = { 277 | let mut tmp = sqrt_candidate; 278 | tmp.mul_assign(&usq); 279 | tmp.mul_assign(u); 280 | tmp 281 | }; 282 | for eta in &ETAS[..] { 283 | let mut y1 = *eta; 284 | y1.mul_assign(&sqrt_candidate); 285 | 286 | let mut tmp = y1; 287 | tmp.square(); 288 | tmp.mul_assign(&gx0_den); 289 | if tmp == gx1_num { 290 | let sgn0_y_xor_u = y1.sgn0() ^ u.sgn0(); 291 | y1.negate_if(sgn0_y_xor_u); 292 | y1.mul_assign(&gx0_den); // y * x0_den^3 / x0_den^3 = y 293 | 294 | tmp = x1_num; 295 | tmp.mul_assign(&x0_den); // x1_num * x0_den / x0_den^2 = x1_num / x0_den 296 | 297 | return G2 { 298 | x: tmp, 299 | y: y1, 300 | z: x0_den, 301 | }; 302 | } 303 | } 304 | 305 | panic!("Failed to find square root in G2 osswu_map"); 306 | } 307 | } 308 | 309 | #[test] 310 | fn print_consts_g2() { 311 | println!("ELLP_A = {:?}", ELLP_A); 312 | println!("ELLP_B = {:?}", ELLP_B); 313 | println!("XI = {:?}", XI); 314 | println!("ETAS = {:?}", ETAS); 315 | println!("ROU = {:?}", ROOTS_OF_UNITY); 316 | } -------------------------------------------------------------------------------- /accumulator-ecc/pairings/src/bls12_381/isogeny/tests.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Tests for isogenies. 3 | */ 4 | 5 | use super::IsogenyMap; 6 | use crate::{ 7 | bls12_381::{ 8 | transmute::{g1_projective, g2_projective}, 9 | Fq, Fq2, FqRepr, 10 | }, 11 | CurveProjective, 12 | }; 13 | use ff::{Field, PrimeField}; 14 | 15 | #[test] 16 | fn test_iso11() { 17 | let zero = Fq::zero(); 18 | let mut pt = unsafe { g1_projective(zero, zero, zero) }; 19 | pt.isogeny_map(); 20 | let (x, y, z) = pt.as_tuple(); 21 | assert_eq!(x, &zero); 22 | assert_eq!(y, &zero); 23 | assert_eq!(z, &zero); 24 | 25 | let one = Fq::one(); 26 | let mut pt = unsafe { g1_projective(one, one, one) }; 27 | pt.isogeny_map(); 28 | let (x, y, z) = pt.as_tuple(); 29 | assert_eq!( 30 | x, 31 | &Fq::from_repr(FqRepr([ 32 | 0xb129fab9bef88eddu64, 33 | 0x1c5429e2f4b8bc35u64, 34 | 0xcaab8cc9ec4893f2u64, 35 | 0x9e9c31f30a607c8bu64, 36 | 0x9661fcf22bedfddbu64, 37 | 0x10fc4a3ba5f48e07u64, 38 | ])) 39 | .unwrap() 40 | ); 41 | assert_eq!( 42 | y, 43 | &Fq::from_repr(FqRepr([ 44 | 0xaf52c5fbd490f370u64, 45 | 0x1533c0f27b46c02fu64, 46 | 0xc8890dd0987b134fu64, 47 | 0x43e2d5f172257d50u64, 48 | 0x538ebef63fb145beu64, 49 | 0x11eab1145b95cb9fu64, 50 | ])) 51 | .unwrap() 52 | ); 53 | assert_eq!( 54 | z, 55 | &Fq::from_repr(FqRepr([ 56 | 0x7441c43513e11f49u64, 57 | 0x620b0af2483ad30fu64, 58 | 0x678c5bf3ad4090b4u64, 59 | 0xc75152c6f387d070u64, 60 | 0x5f3cc0ed1bd3f0eeu64, 61 | 0x12514e630a486abbu64, 62 | ])) 63 | .unwrap() 64 | ); 65 | 66 | let xi = Fq::from_repr(FqRepr([ 67 | 0xf6adc4118ae592abu64, 68 | 0xa384a7ab165def35u64, 69 | 0x2365b1fb1c8a73bfu64, 70 | 0xc40dc338ca285231u64, 71 | 0x47ff3364428c59b3u64, 72 | 0x1789051238d025e3u64, 73 | ])) 74 | .unwrap(); 75 | let yi = Fq::from_repr(FqRepr([ 76 | 0x1a635634e9cced27u64, 77 | 0x03f604e47bc51aa9u64, 78 | 0x06f6ff472fa7276eu64, 79 | 0x0459ed10f1f8abb1u64, 80 | 0x8e76c82bd4a29d21u64, 81 | 0x088cb5712bf81924u64, 82 | ])) 83 | .unwrap(); 84 | let zi = Fq::from_repr(FqRepr([ 85 | 0x0416411fe2e97d06u64, 86 | 0xaced7fec7a63fe65u64, 87 | 0x683295bcaed54202u64, 88 | 0xbdc3405df9ff0a3bu64, 89 | 0xf9698f57510273fbu64, 90 | 0x064bb4b501466b2au64, 91 | ])) 92 | .unwrap(); 93 | let mut pt = unsafe { g1_projective(xi, yi, zi) }; 94 | pt.isogeny_map(); 95 | let (x, y, z) = pt.as_tuple(); 96 | assert_eq!( 97 | x, 98 | &Fq::from_repr(FqRepr([ 99 | 0xa51741657e71601du64, 100 | 0x1771cef34519b6f2u64, 101 | 0x2d1aff4e4ae28379u64, 102 | 0x9ddcd540391389adu64, 103 | 0x0db61b8544450f53u64, 104 | 0x0f34c6cea2fc0199u64, 105 | ])) 106 | .unwrap() 107 | ); 108 | assert_eq!( 109 | y, 110 | &Fq::from_repr(FqRepr([ 111 | 0xd1d70b485ea22464u64, 112 | 0xd3a592a3ffc2c77cu64, 113 | 0x72ef2afff097ad4fu64, 114 | 0xf1c66e0e000b5673u64, 115 | 0x1d32499c9f462716u64, 116 | 0x19284e38020f6072u64, 117 | ])) 118 | .unwrap() 119 | ); 120 | assert_eq!( 121 | z, 122 | &Fq::from_repr(FqRepr([ 123 | 0x583946b46d152c9fu64, 124 | 0xb7f34ad188fdc105u64, 125 | 0x47f7edb38429108au64, 126 | 0xb6602e02d0d7ac4du64, 127 | 0xc27121d0eb3d5efcu64, 128 | 0x16f4243bf7230576u64, 129 | ])) 130 | .unwrap() 131 | ); 132 | } 133 | 134 | #[test] 135 | fn test_iso3() { 136 | let zero = Fq2::zero(); 137 | let mut pt = unsafe { g2_projective(zero, zero, zero) }; 138 | pt.isogeny_map(); 139 | let (x, y, z) = pt.as_tuple(); 140 | assert_eq!(x, &zero); 141 | assert_eq!(y, &zero); 142 | assert_eq!(z, &zero); 143 | 144 | let one = Fq2::one(); 145 | let mut pt = unsafe { g2_projective(one, one, one) }; 146 | pt.isogeny_map(); 147 | let (x, y, z) = pt.as_tuple(); 148 | let c0 = FqRepr([ 149 | 0x57c6555579807bcau64, 150 | 0xc285c71b6d7a38e3u64, 151 | 0xde7b4e7d31a614c6u64, 152 | 0x31b21e4af64b0e94u64, 153 | 0x8fc02d1bfb73bf52u64, 154 | 0x1439b899baf1b35bu64, 155 | ]); 156 | let c1 = FqRepr([ 157 | 0xf58daaab358a307bu64, 158 | 0x665f8e3829a071c6u64, 159 | 0x55c5ca596c9b3369u64, 160 | 0xfeecf110f9110a6au64, 161 | 0xd464b281b39bd1ccu64, 162 | 0x0e725f493c63801cu64, 163 | ]); 164 | let x_expect = Fq2 { 165 | c0: Fq::from_repr(c0).unwrap(), 166 | c1: Fq::from_repr(c1).unwrap(), 167 | }; 168 | let c0 = FqRepr([ 169 | 0xa72f3db7cb8405a4u64, 170 | 0x221fda12b88ad097u64, 171 | 0x71ec98c879891123u64, 172 | 0x54f9a5b05305ae23u64, 173 | 0xf176e62b3bde9b44u64, 174 | 0x04d0ca6dbecbd55eu64, 175 | ]); 176 | let c1 = FqRepr([ 177 | 0xe1b3626ab65e39a9u64, 178 | 0x4e79097a56dc4bd9u64, 179 | 0xb0e977c69aa27452u64, 180 | 0x761b0f37a1e26286u64, 181 | 0xfbf7043de3811ad0u64, 182 | 0x124c9ad43b6cf79bu64, 183 | ]); 184 | let y_expect = Fq2 { 185 | c0: Fq::from_repr(c0).unwrap(), 186 | c1: Fq::from_repr(c1).unwrap(), 187 | }; 188 | let c0 = FqRepr([ 189 | 0xb9fefffffffebb2au64, 190 | 0x1eabfffeb153ffffu64, 191 | 0x6730d2a0f6b0f624u64, 192 | 0x64774b84f38512bfu64, 193 | 0x4b1ba7b6434bacd7u64, 194 | 0x1a0111ea397fe69au64, 195 | ]); 196 | let c1 = FqRepr([ 197 | 0x00000000000065b2u64, 198 | 0x0000000000000000u64, 199 | 0x0000000000000000u64, 200 | 0x0000000000000000u64, 201 | 0x0000000000000000u64, 202 | 0x0000000000000000u64, 203 | ]); 204 | let z_expect = Fq2 { 205 | c0: Fq::from_repr(c0).unwrap(), 206 | c1: Fq::from_repr(c1).unwrap(), 207 | }; 208 | assert_eq!(x, &x_expect); 209 | assert_eq!(y, &y_expect); 210 | assert_eq!(z, &z_expect); 211 | 212 | let c0 = FqRepr([ 213 | 0x0018c03388164247u64, 214 | 0xc4c8890b30d528ebu64, 215 | 0xd52d2a45caca6edau64, 216 | 0x89b3941228dae354u64, 217 | 0x3f3f7d07e4c40a93u64, 218 | 0x0530990b2b3e9a8au64, 219 | ]); 220 | let c1 = FqRepr([ 221 | 0x6b90db064d0030e9u64, 222 | 0xd6a6501c1871b906u64, 223 | 0x11c92e91687441adu64, 224 | 0xf974e31a71e5fe1fu64, 225 | 0x87933ab312f66f88u64, 226 | 0x117d0dba9f178439u64, 227 | ]); 228 | let xi = Fq2 { 229 | c0: Fq::from_repr(c0).unwrap(), 230 | c1: Fq::from_repr(c1).unwrap(), 231 | }; 232 | let c0 = FqRepr([ 233 | 0x6dee4915e87b601au64, 234 | 0xad55ed81ecc390ffu64, 235 | 0xa9c3c810a96f8ca7u64, 236 | 0x0c7d97874f6f026du64, 237 | 0x967de59661e37bb5u64, 238 | 0x11b94175e3be4de8u64, 239 | ]); 240 | let c1 = FqRepr([ 241 | 0x53563b5cfa722ba8u64, 242 | 0x41b7f7263e23c28eu64, 243 | 0x17cf622d5607fbcau64, 244 | 0xe8722180e02d0818u64, 245 | 0xf8c75b4c8b66c965u64, 246 | 0x035eea1ab1a2a087u64, 247 | ]); 248 | let yi = Fq2 { 249 | c0: Fq::from_repr(c0).unwrap(), 250 | c1: Fq::from_repr(c1).unwrap(), 251 | }; 252 | let c0 = FqRepr([ 253 | 0x71f8d78673dbfa39u64, 254 | 0x62d7bae1a74336dcu64, 255 | 0x53bf87ae6e302bd3u64, 256 | 0x4d197aa97c5317f5u64, 257 | 0xc41aa271acd3a3a1u64, 258 | 0x189add484077dd45u64, 259 | ]); 260 | let c1 = FqRepr([ 261 | 0x9a214bfcea21674fu64, 262 | 0x3a5d62187b013310u64, 263 | 0xc15f3a4db5bc86a7u64, 264 | 0x96b99fa5eb4f47c8u64, 265 | 0xb36b52b4a8696193u64, 266 | 0x0e613ba7c4916c20u64, 267 | ]); 268 | let zi = Fq2 { 269 | c0: Fq::from_repr(c0).unwrap(), 270 | c1: Fq::from_repr(c1).unwrap(), 271 | }; 272 | let mut pt = unsafe { g2_projective(xi, yi, zi) }; 273 | pt.isogeny_map(); 274 | let (x, y, z) = pt.as_tuple(); 275 | let c0 = FqRepr([ 276 | 0xf119e132b7ebd22cu64, 277 | 0x37932278669819e7u64, 278 | 0xdb71788e6d1c6512u64, 279 | 0x678934e396004f81u64, 280 | 0x55213880b7ed140du64, 281 | 0x181403b14aa19327u64, 282 | ]); 283 | let c1 = FqRepr([ 284 | 0xdaac25bd8310aef3u64, 285 | 0xbdaab7e27633f5d2u64, 286 | 0x2e8422b082fc8c69u64, 287 | 0xf6b6f9af2f2fc258u64, 288 | 0x8b649eeb97f5676eu64, 289 | 0x13f21dc8a4dfcc1au64, 290 | ]); 291 | let x_expect = Fq2 { 292 | c0: Fq::from_repr(c0).unwrap(), 293 | c1: Fq::from_repr(c1).unwrap(), 294 | }; 295 | let c0 = FqRepr([ 296 | 0xbe1f08d76520ec2au64, 297 | 0xd9ef23f135188a36u64, 298 | 0x3b97d6bb83c22918u64, 299 | 0x6a2ce7736962cd7cu64, 300 | 0x95d5421d9c9465deu64, 301 | 0x09cab53c88c263bdu64, 302 | ]); 303 | let c1 = FqRepr([ 304 | 0x3e6a004356660064u64, 305 | 0x0b182f682ab74743u64, 306 | 0xc53c7316655326eau64, 307 | 0x669c0d885b42452au64, 308 | 0x97df98a239aa957du64, 309 | 0x06299d091ec0ed11u64, 310 | ]); 311 | let y_expect = Fq2 { 312 | c0: Fq::from_repr(c0).unwrap(), 313 | c1: Fq::from_repr(c1).unwrap(), 314 | }; 315 | let c0 = FqRepr([ 316 | 0xe518e02aaa358acdu64, 317 | 0x4c00a671fa8fc185u64, 318 | 0xf88193c7dd618937u64, 319 | 0x2d6e07a3e0ca5733u64, 320 | 0x121d7ae073e479fdu64, 321 | 0x00644ae14e9341fbu64, 322 | ]); 323 | let c1 = FqRepr([ 324 | 0x9bed7fa96e783e15u64, 325 | 0xde7d5d396f73c236u64, 326 | 0x491857011bcac282u64, 327 | 0x82d08553b1dacca2u64, 328 | 0x41def4997b2fc93fu64, 329 | 0x14474088f5b1d2e3u64, 330 | ]); 331 | let z_expect = Fq2 { 332 | c0: Fq::from_repr(c0).unwrap(), 333 | c1: Fq::from_repr(c1).unwrap(), 334 | }; 335 | assert_eq!(x, &x_expect); 336 | assert_eq!(y, &y_expect); 337 | assert_eq!(z, &z_expect); 338 | } 339 | --------------------------------------------------------------------------------