78 Commits

Author SHA1 Message Date
Michele Orrù
e2d16a27e2 Update README.md (#189) 2023-12-18 09:24:04 -08:00
Pratyush Mishra
7854883b47 Add archival notice to README (#188) 2023-12-18 08:56:41 -08:00
Davide Galassi
ccf83923f8 Expose Bandersnatch generators (#184) 2023-10-14 17:44:58 +02:00
Andrew Z
0a64024ebc Fix #178: Make MNT{4,6}-753, cp6_782 tests run conditionally (#179) 2023-09-25 11:28:26 -07:00
Pratyush Mishra
8c0256ac9c Fix comments for Grumpkin curve generator (#175)
Co-authored-by: Weikeng Chen <w.k@berkeley.edu>
2023-09-19 04:47:35 -07:00
mmagician
72a18b6ecf GLV implementation for BLS12_377, BLS12_381 and BN254 (#158) 2023-09-11 17:29:38 -04:00
mmagician
8765798eb0 The scalar to be multiplied by should be at most num_limbs long (#171)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-09-11 12:44:41 -07:00
mmagician
7e4b4bf027 Non-canonical infinity point & bad flags in BLS12-381 serialization should fail (#176)
Co-authored-by: Kevaundray Wedderburn <kevtheappdev@gmail.com>
2023-09-11 12:21:37 -07:00
Carlos Pérez
4d1e504025 Add Grumpkin support for arkworks (#174)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-09-07 05:15:36 -07:00
Weikeng Chen
fc8379d9ed Add the small subgroup power for BN254 (#163)
Co-authored-by: mmagician <marcin.gorny.94@protonmail.com>
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-09-05 05:39:34 -07:00
mmagician
a0bd36f781 Revert "temp switch to bw6-optimization branch on algebra" (#172) 2023-09-04 11:38:00 -04:00
mmagician
1ce1fcf70f Bw6-761 optimized Miller loop (#155) 2023-09-03 09:38:44 -04:00
mmagician
379f23070c Use BigInt macro for defining curve config parameters (#170) 2023-09-01 09:43:12 -07:00
swasilyev
7e58260618 Add BW6-767 curve and update BW6-761 to use the new bw6 model (#156)
* Rework bw6-761 to bw6-767

use bls12-381 instead of 377 for test imports

fix the inline comments with correct name and params


Set the right base field


Equation for base curve is y2 = x3 + 1


fill in pairing params


adapt sage scripts with correct moduli


calculate the correct cubic non residue


correct the parameter B in the curve equation


remove the specialized method for mult by nonresidue

nonresidue is two, so default will be doubling

calculate more correct parameters for fq3

`TRACE_MINUS_ONE_DIV_TWO` and `QUADRATIC_NONRESIDUE_TO_T`

compute the right fq3 & fp6 frobenious coefficients


calculate the cofactor for g1


use the g1 generator from gnark's fork


use the right g2 equation


g2 cofactor is slightly smaller than g1 cofactor


get the g2 generators from gnark's fork


update g1 and g2 curve info in the comments


fill in `COFACTOR_INV` value for g1


fill in `COFACTOR_INV` value for g2

* update module description

author information
2-adicity of the scalar field

* update changelog

* remove trailing comma

* remove todo

* 2nd loop count is x^3 - x^2 - x

* Revert "2nd loop count is x^3 - x^2 - x"

This reverts commit 2b323db3baff06a6077fd7505ff489fa31be7282.

* fix comment regarding non-residue

* first loop count should be X

* 1. Generic BW6 params added to BW6-761
2. Curve specific hard part of the final exp moved from algebra

* 1. Generic BW6 params added to BW6-767
2. Miller loop params changed to the "unoptimized" version

* cargo fmt

* changelog updated

* X_MINUS_1_DIV_3 added to BW6Config

* imports fixed

---------

Co-authored-by: mmagician <marcin.gorny.94@protonmail.com>
2023-09-01 10:06:45 +02:00
Chris Sosnin
3fded1fbcc patch dependencies and fix imports (#167)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-08-19 13:13:13 -07:00
Hossein Moghaddas
32b487e7fd Adding AdditiveGroup and PrimeGroup (#159)
Co-authored-by: Michele Orrù <michele.orru@berkeley.edu>
Co-authored-by: Weikeng Chen <w.k@berkeley.edu>
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-08-19 12:09:04 -07:00
swasilyev
5a41d7f27a Ed on bls12 377 bench (#152)
Co-authored-by: mmagician <marcin.gorny.94@protonmail.com>
2023-03-01 10:42:20 -08:00
Davide Galassi
4ab8ba6eb7 Publish some generators xy values (#150)
* Publish some generators xy values

* Publish all generators xy values
2023-03-01 19:12:08 +01:00
Michele Orrù
ab9be6d8f4 Add benchmarks for curve25519. 2023-01-29 14:47:03 -08:00
Michele Orrù
d5447dec42 Add benchmarks for secp256k1 2023-01-29 14:47:03 -08:00
mmagician
3668338023 Merge releases into master, keeping the patch.crates-io section 2023-01-19 16:36:44 -08:00
Ruben De Smet
69a9c3513b More NIST curves (#142)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2023-01-10 04:59:32 -08:00
drskalman
bf8c488263 Implement WB hash2curve for BLS12-377 and BLS12-381 (#138)
* include the coefficients of bls12-377 G1 and G2 isogenies for wb hash2curve

* replacing the ark-ec dependency to w3f/arkworks-algebra

* added parameters for isogenous curve to bls12-377 g1 curve for swu map

* fix dependency inconsistency problem

* implement WBParams and its isogenous curve for BLS12-377 G1

* implement the SWUParameters for isogenous curve to BLS12-377 g2 curve.

* implement WBParams for BLS12-377 G2 curve

* replacing const generic arrays with const slice in g1 and g2 iso coefficients

* - Implement WB hash to curve for BLS12-381 G1
- Improvement to WB hash to curve code for BLS12-377
- Update sage code for generating isogeny coefficients for arkworks.

* Implement WB hash to curve for BLS12-381 G2

* - fix the bug with base order for field_new for Fq2
- fix the polynomial coeffcient order for bls12-381 g1 and g2 isogenies.
- fix the polynomial coeffcient order for bls12-377 g1.
377-g2 needs to be fixed still.

* fix bls12-377 wb hash to curve isogeny coeffcients

* fixed sage code for generating the isogeny coefficients

* use patch.crates-io hack to resolve dependancy issues on w3f fork

* Rename `Parameters` to `Config` for all fields

* Rename `field_new` to `MontFp`

* Rename `field_new` to `QuadExt` and `CubicExt`

* Refactor bls12_381 crate based on update-ff branch. Close #9

* adapt bls12 wb hashing to new changes in algebra

* update bls12-381 dependancies and g1, g2 definition to pass tests

* adapt bls12-377 hash to curve to algebar updates

* depend on upstream for pull request

* cargo fmt

* - move the isogeny finder script from sage to script folder
- delete auxiliary isogeny coeff file

* add unit tests for wb hashing to bls12-377 g1 and g2

* - Use IsogenyMap struct to specify WB Isogeny for bls12-381 and bls12-377
- Do not use auxiliary constants to define generators of g2_swu_iso curve.
- Update change log

* Bump the Algebra dependencies of bls12_381 and bls12_377 to 0.4.0-alpha.4 so they could use the IsogenyMap struct.

* Add h2c tests for BLS12-381 curve

* Drop alpha sub-version in dependancies because it takes the lastest sub version

* Parameters → Config for bls12-377/381 curves

* do cargo fmt

* do SwuIsoParameters → SwuIsoConfig for bls12-377/381

* Adapt to new macro

* Fix macro invocation

should be semicolon not comma

* curves master should use algebra/r1cs default branch

* Add h2c test invocation for bls12-377 curve

no actual test vectors yet

* add faster cofactor clearing and tests for g1

* add faster cofactor clearing and tests for g2

parameters of endomorphisms are wrong for now

* add test vectors for bls12-377

* add h_eff to g2 tests for correctness


test

* improve cofactor tests g2

* add a test for psi(psi(P)) == psi2(P)

* fix bls12-377 psi & psi2 computation parameters

* rename const to DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0 and make private

* fix clippy warnings in changed code

* use the same zeta as test suites

* update code comments, make methods private

* update changelog

Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
Co-authored-by: mmagician <marcin.gorny.94@protonmail.com>
2023-01-10 08:35:16 +01:00
mmagician
0d2142c001 Fast cofactor clearing for BLS12-377 (#141)
* add faster cofactor clearing and tests for g1

* add faster cofactor clearing and tests for g2

parameters of endomorphisms are wrong for now

* add h_eff to g2 tests for correctness


test

* improve cofactor tests g2

* add a test for psi(psi(P)) == psi2(P)

* fix bls12-377 psi & psi2 computation parameters

* rename const to DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0 and make private

* fix clippy warnings in changed code

* remove bls12-381-specific in line comment

* update code comments, make methods private

* master should be patched with master

* update changelog
2023-01-01 15:53:39 +01:00
Pratyush Mishra
cba0c7ef0d Add frobenius_map_in_place (#140) 2022-12-28 12:19:38 +01:00
Weikeng Chen
a82486db1d Add supplementary small group bases for some common fields (#137)
* update

* use r1cs std

* fix

* rem

* Apply suggestions from code review

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-12-21 18:06:24 -08:00
Pratyush Mishra
febd7635fb Rename all *Parameters to *Config (#136)
* Rename all `*Parameters` to `*Config`

* Tweak
2022-12-16 19:35:32 -08:00
Weikeng Chen
f8a6a4050e Add the secp256k1 and secq256k1 curves (#122)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-12-09 10:41:40 -08:00
mmagician
cdf4d182a6 Prepare release 0.4 (#133) 2022-11-29 08:22:09 -08:00
Weikeng Chen
99831650f8 Prepared G2 consistency test (#70)
* add the g2 check

* fmt

* fix

* fix

* fix

* fix

* changelog

* test macos for curve tests

* use macos only for mnt6-753

* fix

* fix name consistency

* adjust the order

* mnt4 753

* fix

Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-10-31 17:12:52 -07:00
Weikeng Chen
db03d405b5 Add the curve25519 curve (#124)
* add ed25519 curve

* changelog

* curve info

* fix

* edit

* update

* add more explanation

* Update curve25519/src/curves/mod.rs

* Update curve25519/src/curves/mod.rs

* fixed the comment

* Update curve25519/src/curves/mod.rs

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-10-29 19:55:35 -07:00
Weikeng Chen
a7d266f73d Add the ed25519 curve (#121)
* add ed25519 curve

* changelog

* curve info

* fix

* cleanup the script

* Update ed25519/src/curves/mod.rs

* Update ed25519/src/curves/mod.rs

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-10-29 19:33:55 -07:00
Weikeng Chen
5d6d31d213 Fix the location of BitIteratorBE (#132)
* fix

* fix

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-10-29 11:29:45 -07:00
mmagician
df39c78a5b Update changelog (#131) 2022-10-19 10:06:42 -07:00
mmagician
138b23f2fa Zcash-style serialization for BLS12-381 (#129)
Co-authored-by: kevaundray <37423678+kevaundray@users.noreply.github.com>
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2022-10-18 22:44:43 -07:00
mmagician
4bcf87de22 Faster cofactor clearing for G1 & G2 of bls12-381 + benchmarking (#103) 2022-10-16 10:13:57 -07:00
Pratyush Mishra
efefa209d6 Fix mul-by-non-residue for bw6::fq3 2022-10-02 09:15:25 -07:00
Pratyush Mishra
1833cbfb29 Tweaks 2022-10-02 09:15:25 -07:00
Pratyush Mishra
f43d59c958 Rename 2022-10-02 09:15:25 -07:00
Pratyush Mishra
68f500da01 Optimizations to field and curve arithmetic 2022-10-02 09:15:25 -07:00
Pratyush Mishra
363426c1d4 Update to new benchmarking framework (#126) 2022-09-09 19:24:33 -07:00
Pratyush Mishra
55a092a6c7 is_identity -> is_zero (#125) 2022-09-09 11:07:42 -07:00
Weikeng Chen
f74378c017 Add serialization for CP6-782 (#120)
Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-09-03 22:55:16 -07:00
Weikeng Chen
3af6ec17d6 Fix Bandersnatch parameters and the constraint tests (#119)
Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-09-03 12:32:28 -07:00
Weikeng Chen
dc555882cd Fix the remaining curve and field tests (#118)
* push

* push

* cargo ready

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
2022-09-03 00:34:13 -07:00
Weikeng Chen
3c4c67f114 Sync with the recent changes in ark-algebra on pairing and testing (#116)
* Fix another typo in the Jubjub curve comment

* fix

* progress

* get_point_from_x_unchecked

* fix

* soft link

* Fix Bandersnatch

* Fix Edwards form of Bandersnatch

* Actually fix ed_on_bls12_381_bandersnatch/src/curves/mod.rs

* fix

* fix

* curve-benches

* fix the last mul_by_a; fmt

Co-authored-by: onewayfunc <onewayfunc@gmail.com>
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2022-09-02 16:31:58 -07:00
mmagician
42289245a6 Replace ATE_LOOP_COUNT with its 2-NAF for MNT curves (#107)
* Replace ATE_LOOP_COUNT by its 2-NAF

* Add constant references

* Apply suggestions from code review

Co-authored-by: Weikeng Chen <w.k@berkeley.edu>
2022-09-02 08:19:51 -07:00
Weikeng Chen
b433045f4d Fix a typo in the Jubjub curve comment (#114) 2022-08-27 14:17:37 -07:00
Weikeng Chen
52577f93ba Last PR to get the curve tests to work (#113) 2022-08-21 21:08:38 -07:00
Weikeng Chen
6d94362894 Let ark-curve-constraint-tests work with latest arkworks-rs algebra (#112) 2022-08-21 19:58:41 -07:00
Weikeng Chen
435de9fc36 Let cargo build work again for the new arkworks-rs algebra (#111) 2022-08-21 18:22:43 -07:00
Pratyush Mishra
e75546313a Fix benchmarks and fix accidental renaming of Pallas/Vesta (#108) 2022-08-01 13:46:52 -07:00
kevaundray
67d5a8582e Document Bandersnatch as an incomplete twisted Edwards curve (#85) 2022-08-01 10:32:08 -07:00
Marcin
93e64df895 Catch up with algebra (#106)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2022-07-29 12:16:16 -07:00
Marcin
76579d0fbb QUADRATIC_NONRESIDUE is never used, remove (#104)
* `QUADRATIC_NONRESIDUE` is never used, remove

* Update CHANGELOG.md

* Remove unused imports
2022-06-30 11:00:01 -07:00
Marcin
9a89ea8adc Pull ark-std from latest master (#100) 2022-04-11 15:17:18 -07:00
Pratyush Mishra
5a1e16e2b7 Fix benchmark imports (#99) 2022-03-07 21:01:29 -08:00
Pratyush Mishra
1551d6d76c Upgrade to work with latest ark-ff (#95)
Co-authored-by: Sun <huachuang20@gmail.com>
2022-03-07 13:12:03 -08:00
Marcin
d0dc200f22 Sqrt fq2 bls12 381 regression (#89)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2022-01-11 09:28:17 -08:00
Marcin
6a5cf1d84a BigInt fixes corresponding to algebra#372
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2022-01-10 11:03:40 -08:00
Pratyush Mishra
d1ced15cc2 Upgrade for algebra/365 (#92)
* Upgrade for algebra/365

* Merge fix

* Fix
2021-12-29 17:07:52 +01:00
Yuncong Hu
677b4ae751 Simplify the field and curve tests using macros (#90)
* Simplify the field and curve tests using macros

* minor

* remove redundant code

Co-authored-by: weikeng <w.k@berkeley.edu>
2021-12-06 00:03:29 -08:00
Michael Rosenberg
c5547905d0 Fixed curve-bench compile error (#83)
* Fixed benchmarking compile error

* Updated CHANGELOG

* patch `algebra-test-templates` due to breaking changes since the last release

Co-authored-by: Marcin Górny <marcin.gorny.94@protonmail.com>
2021-12-05 17:48:33 +01:00
Popog
f1e36c5bed Documentation provides incorrect calculation (#81) 2021-11-15 10:55:32 -08:00
Weikeng Chen
3a0f858adb Revise the version number of Bandersnatch (#80) 2021-11-10 22:20:01 -08:00
zhenfei
461e4190b1 adding SW parameters for Bandersnatch curve (#67)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2021-10-20 10:12:15 -07:00
zhenfei
5fe1862c9a Twisted Edwards parameters for BLS12-377 (#76)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
2021-10-19 11:30:41 -07:00
Simon Masson
2118e14b6a Use Scott's subgroup membership tests for G1 and G2 of BLS12-381. (#74)
* implementation of the fast subgroup check for bls12_381

* add a bench

* subgroup check for g1

* subgroup check modifications

* remove useless test

* fmt

* need the last version of arkworks/algebra

* remove Parameters0

* using projective points is more efficient

* use of projective coordinates in G2

* fmt

* documentation on the constants and the psi function

* references for algorithms of eprint 2021/1130

* fmt

* sed ^ **

* minor improvement

* fmt

* fix Cargo toml

* nits

* some cleanup for g1

* add the beta test back

* fmt

* g2

* changelog

* add a  note on the Cargo.toml

* nits

* avoid variable name conflicts

* add the early-out optimization

Co-authored-by: weikeng <w.k@berkeley.edu>
2021-09-25 10:34:13 -07:00
Weikeng Chen
b5c2d8eba3 Fix a comment on Bandersnatch's TEModelParameters (#65)
Pratyush noticed a comment regarding COEFF_A has not been updated. This PR fixes so.
2021-06-30 20:14:37 -07:00
zhenfei
129795aa4c Implement the Bandersnatch curve (#64)
* impl bandersnatch

* clean up

* update changelog

* Relocate the readme so they show up in the doc

* Delete README.md

* Relocate the changelog entry

* rename & fmt

Co-authored-by: Weikeng Chen <w.k@berkeley.edu>
2021-06-29 18:04:08 -07:00
George Gkitsas
a9cb9bfcb2 Fix incorrect repository links in Cargo.toml files (#63)
* fixes repository in cargo files

* lint fixes
2021-06-23 08:58:50 -07:00
Weikeng Chen
d2c998736e Release v0.3.0 (#62)
* release

* update CHANGELOG.md
2021-06-06 13:47:19 -07:00
Alex Ozdemir
ada1fdac07 Fix Bls12-377 scalar group generator (#60)
* Fix Bls12-377 scalar group generator

Previously we used 11 as a generator, which has order (p-1)/35.

Now we use 22, which has the right order.

Fixed the two-adic root of unity in accordance with the new generator.

fixes #47

* add the CHANGE LOG

Co-authored-by: weikeng <w.k@berkeley.edu>
2021-05-06 16:46:22 -07:00
Weikeng Chen
8c795ec0cf Update the documentation of BN254's field parameters (#59) 2021-05-06 08:22:07 -07:00
Daira Hopwood
9d232a7dcd Fix a comment describing BN254. (#55)
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
2021-04-16 14:54:33 -07:00
Daira Hopwood
4d6c49640c Add benchmarks for Pallas and Vesta curves. (#53)
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
2021-04-16 10:18:06 -07:00
Pratyush Mishra
880a010f5e Reduce CI time by parallelizing per-curve tests (#52) 2021-04-11 14:53:06 -07:00
Dev Ojha
269fe97519 Release v0.2 (#51) 2021-03-24 20:18:59 -05:00
458 changed files with 11011 additions and 9185 deletions

View File

@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
@@ -29,8 +29,8 @@ jobs:
command: fmt
args: --all -- --check
test:
name: Test
check:
name: Check
runs-on: ubuntu-latest
env:
RUSTFLAGS: -Dwarnings
@@ -41,7 +41,7 @@ jobs:
- nightly
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install Rust (${{ matrix.rust }})
uses: actions-rs/toolchain@v1
@@ -50,7 +50,7 @@ jobs:
toolchain: ${{ matrix.rust }}
override: true
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: |
~/.cargo/registry
@@ -78,13 +78,146 @@ jobs:
args: --all-features --examples --workspace --benches
if: matrix.rust == 'nightly'
- name: Test
uses: actions-rs/cargo@v1
directories: # Job that list subdirectories
name: List directories for parallelizing tests
runs-on: ubuntu-latest
outputs:
dir: ${{ steps.set-dirs.outputs.dir }} # generate output name dir by using inner step output
steps:
- uses: actions/checkout@v3
- id: set-dirs # Give it an id to handle to get step outputs in the outputs key above
run: echo "::set-output name=dir::$(ls -d */ | jq -R -s -c 'split("\n")[:-1]')"
# Define step output named dir base on ls command transformed to JSON thanks to jq
test:
name: Test
runs-on: ubuntu-latest
needs: [directories] # Depends on previous job
strategy:
matrix:
dir: ${{fromJson(needs.directories.outputs.dir)}} # List matrix strategy from directories dynamically
# rust:
# - stable
# - nightly
exclude:
- dir: scripts/
- dir: curve-constraint-tests/
- dir: mnt4_753/
- dir: mnt6_753/
- dir: cp6_782/
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Run tests
run: |
cd ${{matrix.dir}}
cargo test --all-features
test-mnt4-753:
name: Test (mnt4_753/)
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check if source code updated
uses: dorny/paths-filter@v2.11.1
id: check-diff
with:
command: test
args: "--workspace \
--all-features \
--exclude curve-benches"
filters: |
mnt4_753_is_updated:
- 'mnt4_753/**'
- name: Generate lockfile
run: cargo generate-lockfile
- name: Check if deps updated
id: deps-updated
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Conditionally run the tests
# if source code updated OR dependencies updated
if: ${{ steps.check-diff.outputs.mnt4_753_is_updated == 'true' || steps.deps-updated.outputs.cache-hit != 'true' }}
run: |
cd mnt4_753/
cargo test --all-features
test-mnt6-753:
name: Test (mnt6_753/)
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check if source code updated
uses: dorny/paths-filter@v2.11.1
id: check-diff
with:
filters: |
mnt6_753_is_updated:
- 'mnt6_753/**'
- name: Generate lockfile
run: cargo generate-lockfile
- name: Check if deps updated
id: deps-updated
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Conditionally run the tests
# if source code updated OR dependencies updated
if: ${{ steps.check-diff.outputs.mnt6_753_is_updated == 'true' || steps.deps-updated.outputs.cache-hit != 'true' }}
run: |
cd mnt6_753/
cargo test --all-features
test-cp6_782:
name: Test (cp6_782/)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check if source code updated
uses: dorny/paths-filter@v2.11.1
id: check-diff
with:
filters: |
cp6_782_is_updated:
- 'cp6_782/**'
- name: Generate lockfile
run: cargo generate-lockfile
- name: Check if deps updated
id: deps-updated
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Conditionally run the tests
# if source code updated OR dependencies updated
if: ${{ steps.check-diff.outputs.cp6_782_is_updated == 'true' || steps.deps-updated.outputs.cache-hit != 'true' }}
run: |
cd cp6_782/
cargo test --all-features
docs:
name: Check Documentation
@@ -92,7 +225,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
@@ -112,16 +245,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install Rust (${{ matrix.rust }})
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: aarch64-unknown-none
target: thumbv6m-none-eabi
override: true
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: |
~/.cargo/registry
@@ -133,10 +266,10 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: check
args: --examples --workspace --exclude ark-curve-constraint-tests --exclude ark-curve-benches --target aarch64-unknown-none
args: --examples --workspace --exclude ark-curve-constraint-tests --target thumbv6m-none-eabi
- name: build
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --exclude ark-curve-constraint-tests --exclude ark-curve-benches --target aarch64-unknown-none
args: --workspace --exclude ark-curve-constraint-tests --target thumbv6m-none-eabi

View File

@@ -1,9 +1,73 @@
# CHANGELOG
## Pending
### Breaking changes
### Features
- [\#156](https://github.com/arkworks-rs/curves/pull/156) Add the bw6-767 curve.
- [\#174](https://github.com/arkworks-rs/curves/pull/174) Add the "grumpkin" curve.
### Improvements
- [\#156](https://github.com/arkworks-rs/curves/pull/156) The hard part of the final exponentiation for bw6-761 relocated from arkworks/algebra.
- [\#158](https://github.com/arkworks-rs/curves/pull/158) Enabled GLV as the default scalar multiplication for BLS12-377, BLS12-381 and BN254.
### Bugfixes
- [\#176](https://github.com/arkworks-rs/curves/pull/176) Non-canonical infinity point and bad flags in BLS12-381 serialization should fail.
## v0.4.0
- [\#76](https://github.com/arkworks-rs/curves/pull/76) twisted Edwards parameters for bls12-377
- Fixed curve benches
### Breaking changes
- [\#104](https://github.com/arkworks-rs/curves/pull/104) Remove `QUADRATIC_NONRESIDUE` parameter from implementors of `Fp2Config`.
- [\#129](https://github.com/arkworks-rs/curves/pull/129) Implement custom serialization for BLS12-381 for compatibility with the [Zcash lib](https://github.com/zkcrypto/bls12_381).
### Features
- [\#121](https://github.com/arkworks-rs/curves/pull/121) Add the ed25519 curve.
- [\#122](https://github.com/arkworks-rs/curves/pull/122) Add the secp256k1 and secq256k1 curves.
- [\#124](https://github.com/arkworks-rs/curves/pull/124) Add the curve25519 curve.
### Improvements
- [\#70](https://github.com/arkworks-rs/curves/pull/70) Add prepared G2 pairing consistency test.
- [\#74](https://github.com/arkworks-rs/curves/pull/74) Use Scott's subgroup membership tests for `G1` and `G2` of BLS12-381.
- [\#103](https://github.com/arkworks-rs/curves/pull/103) Faster cofactor clearing for BLS12-381.
- [\#107](https://github.com/arkworks-rs/curves/pull/107/) Use 2-NAF of `ATE_LOOP_COUNT` to speed up the Miller loop in MNT curves.
- [\#141](https://github.com/arkworks-rs/curves/pull/103) Faster cofactor clearing for BLS12-377.
- [\#138](https://github.com/arkworks-rs/curves/pull/138) Implement WB Hash-to-Curve for bls12-381 and bls12-377
### Bug fixes
## v0.3.0
### Breaking changes
- [\#60](https://github.com/arkworks-rs/curves/pull/60) Change the scalar group generator of `Fr` of `bls12_377` Fr from `11` to `22`.
- [\#61](https://github.com/arkworks-rs/curves/pull/61) Remove `ATE_LOOP_COUNT_IS_NEGATIVE` from BN254 curve parameter.
### Features
- [\#64](https://github.com/arkworks-rs/curves/pull/64) Implement the Bandersnatch curve, another twisted Edwards curve for BLS12-381.
### Improvements
### Bug fixes
## v0.2.0
### Breaking changes
- Requires all crates from `arkworks-rs/algebra` to have version `v0.2.0` or greater.
### Features
- [\#3](https://github.com/arkworks-rs/curves/pull/3) Add constraints for
`ark-bls12-377`,
`ark-ed-on-bls12-377`,
@@ -19,11 +83,14 @@
`ark-mnt6-753`.
- [\#7](https://github.com/arkworks-rs/curves/pull/7) Add benchmarks for Edwards curves.
- [\#19](https://github.com/arkworks-rs/curves/pull/19) Change field constants to be provided as normal strings, instead of in Montgomery form.
- [\#53](https://github.com/arkworks-rs/curves/pull/53) Add benchmarks for Pallas and Vesta curves.
### Improvements
- [\#42](https://github.com/arkworks-rs/curves/pull/42) Remove the dependency of `rand_xorshift`.
### Bug fixes
- [\#28](https://github.com/arkworks-rs/curves/pull/28), [\#49](https://github.com/arkworks-rs/curves/pull/49) Fix broken documentation links.
- [\#38](https://github.com/arkworks-rs/curves/pull/38) Compile with `panic='abort'` in release mode, for safety of the library across FFI boundaries.
- [\#45](https://github.com/arkworks-rs/curves/pull/45) Fix `ark-ed-on-mnt4-753`.

View File

@@ -1,7 +1,6 @@
[workspace]
members = [
"curve-benches",
"curve-constraint-tests",
"bls12_377",
@@ -10,14 +9,18 @@ members = [
"bw6_761",
"ed_on_bw6_761",
"bw6_767",
"cp6_782",
"ed_on_cp6_782",
"bls12_381",
"ed_on_bls12_381",
"ed_on_bls12_381_bandersnatch",
"bn254",
"ed_on_bn254",
"grumpkin",
"mnt4_298",
"mnt6_298",
@@ -29,7 +32,16 @@ members = [
"pallas",
"vesta",
"secp256k1",
"secp256r1",
"secp384r1",
"secq256k1",
"curve25519",
"ed25519",
]
resolver = "2"
[profile.release]
opt-level = 3
@@ -55,3 +67,12 @@ lto = "thin"
incremental = true
debug-assertions = true
debug = true
[patch.crates-io]
ark-ff = { git = "https://github.com/arkworks-rs/algebra/" }
ark-ec = { git = "https://github.com/arkworks-rs/algebra/" }
ark-poly = { git = "https://github.com/arkworks-rs/algebra/" }
ark-serialize = { git = "https://github.com/arkworks-rs/algebra/" }
ark-algebra-test-templates = { git = "https://github.com/arkworks-rs/algebra/" }
ark-algebra-bench-templates = { git = "https://github.com/arkworks-rs/algebra/" }
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std/" }

View File

@@ -1,10 +1,15 @@
# Curve implementations
# Notice
This repository is no longer maintained, and PRs to add or modify curves should instead be made against [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra); all the curves implemented here have moved to the [`curves` folder](https://github.com/arkworks-rs/algebra/tree/master/curves) of that repository.
## Curve implementations
This repository contains implementations of some popular elliptic curves. The curve API implemented here matches the curve traits defined [here](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs) in the [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra) repository.
### BLS12-381 and embedded curves
* [`ark-bls12-381`](bls12_381): Implements the BLS12-381 pairing-friendly curve
* [`ark-ed-on-bls12-381`](ed_on_bls12_381): Implements a Twisted Edwards curve atop the scalar field of BLS12-381
* [`ark-ed-on-bls12-381-bandersnatch`](ed_on_bls12_381_bandersnatch): Implements Bandersnatch, another Twisted Edwards curve atop the scalar field of BLS12-381
### BLS12-377 and related curves
* [`ark-bls12-377`](bls12_377): Implements the BLS12-377 pairing-friendly curve
@@ -19,6 +24,7 @@ This repository contains implementations of some popular elliptic curves. The cu
### BN254 and related curves
* [`ark-bn254`](bn254): Implements the BN254 pairing-friendly curve
* [`ark-ed-on-bn254`](ed_on_bn254): Implements a Twisted Edwards curve atop the scalar field of BN254
* [`ark-grumpkin`](grumpkin): Implements the Grumpkin curve. A curve that forms a cycle with bn254.
### MNT-298 cycle of curves and related curves
* [`ark-mnt4-298`](mnt4_298): Implements the MNT4-298 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT6-298

View File

@@ -1,28 +1,30 @@
[package]
name = "ark-bls12-377"
version = "0.1.0"
version = "0.4.0"
authors = [ "arkworks contributors" ]
description = "The BLS12-377 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/algebra"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/ark-bls12-377/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
edition = "2021"
[dependencies]
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false, optional = true }
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
ark-ff = { version= "0.4.0", default-features = false }
ark-ec = { version= "0.4.0", default-features = false }
ark-r1cs-std = { version= "0.4.0", default-features = false, optional = true }
ark-std = { version = "0.4.0", default-features = false }
[dev-dependencies]
ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false }
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-algebra-test-templates = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-relations = { version= "0.4.0", default-features = false }
ark-serialize = { version = "0.4.0", default-features = false }
ark-algebra-test-templates = { version = "0.4.0", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0", default-features = false }
ark-curve-constraint-tests = { path = "../curve-constraint-tests", default-features = false }
sha2 = { version = "0.10", default-features = false }
[features]
default = [ "curve" ]
@@ -32,3 +34,8 @@ curve = [ "scalar_field", "base_field" ]
scalar_field = []
base_field = []
r1cs = [ "base_field", "ark-r1cs-std" ]
[[bench]]
name = "bls12_377"
path = "benches/bls12_377.rs"
harness = false

View File

@@ -0,0 +1,16 @@
use ark_algebra_bench_templates::*;
use ark_bls12_377::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_377, Fq12, G1Projective as G1, G2Projective as G2,
};
bench!(
Name = "Bls12_377",
Pairing = Bls12_377,
G1 = G1,
G2 = G2,
ScalarField = Fr,
G1BaseField = Fq,
G2BaseField = Fq2,
TargetField = Fq12,
);

View File

@@ -0,0 +1,28 @@
modulus = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
modulus = 8444461749428370424248824938781546531375899335154063827935233455917409239041
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 30):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -1,29 +1,39 @@
use crate::Parameters;
use ark_r1cs_std::groups::bls12;
use ark_ec::{bls12::Bls12Config, CurveConfig};
use ark_r1cs_std::{
fields::fp::FpVar,
groups::{bls12, curves::twisted_edwards::AffineVar as TEAffineVar},
};
use crate::Config;
/// An element of G1 in the BLS12-377 bilinear group.
pub type G1Var = bls12::G1Var<Parameters>;
pub type G1Var = bls12::G1Var<Config>;
/// An element of G2 in the BLS12-377 bilinear group.
pub type G2Var = bls12::G2Var<Parameters>;
pub type G2Var = bls12::G2Var<Config>;
/// An element of G1 (in TE Affine form) in the BLS12-377 bilinear group.
pub type G1TEAffineVar = TEAffineVar<
<Config as Bls12Config>::G1Config,
FpVar<<<Config as Bls12Config>::G1Config as CurveConfig>::BaseField>,
>;
/// Represents the cached precomputation that can be performed on a G1 element
/// which enables speeding up pairing computation.
pub type G1PreparedVar = bls12::G1PreparedVar<Parameters>;
pub type G1PreparedVar = bls12::G1PreparedVar<Config>;
/// Represents the cached precomputation that can be performed on a G2 element
/// which enables speeding up pairing computation.
pub type G2PreparedVar = bls12::G2PreparedVar<Parameters>;
pub type G2PreparedVar = bls12::G2PreparedVar<Config>;
#[test]
fn test() {
use ark_ec::models::bls12::Bls12Parameters;
ark_curve_constraint_tests::curves::sw_test::<
<Parameters as Bls12Parameters>::G1Parameters,
G1Var,
use ark_ec::models::bls12::Bls12Config;
ark_curve_constraint_tests::curves::sw_test::<<Config as Bls12Config>::G1Config, G1Var>()
.unwrap();
ark_curve_constraint_tests::curves::te_test::<
<Config as Bls12Config>::G1Config,
G1TEAffineVar,
>()
.unwrap();
ark_curve_constraint_tests::curves::sw_test::<
<Parameters as Bls12Parameters>::G2Parameters,
G2Var,
>()
ark_curve_constraint_tests::curves::sw_test::<<Config as Bls12Config>::G2Config, G2Var>()
.unwrap();
}

View File

@@ -1,16 +1,16 @@
use crate::{Fq, Fq12Parameters, Fq2Parameters, Fq6Parameters};
use ark_r1cs_std::fields::{fp::FpVar, fp12::Fp12Var, fp2::Fp2Var, fp6_3over2::Fp6Var};
use crate::{Fq, Fq12Config, Fq2Config, Fq6Config};
/// A variable that is the R1CS equivalent of `crate::Fq`.
pub type FqVar = FpVar<Fq>;
/// A variable that is the R1CS equivalent of `crate::Fq2`.
pub type Fq2Var = Fp2Var<Fq2Parameters>;
pub type Fq2Var = Fp2Var<Fq2Config>;
/// A variable that is the R1CS equivalent of `crate::Fq6`.
pub type Fq6Var = Fp6Var<Fq6Parameters>;
pub type Fq6Var = Fp6Var<Fq6Config>;
/// A variable that is the R1CS equivalent of `crate::Fq12`.
pub type Fq12Var = Fp12Var<Fq12Parameters>;
pub type Fq12Var = Fp12Var<Fq12Config>;
#[test]
fn bls12_377_field_test() {

View File

@@ -106,7 +106,7 @@
//! ```
//! # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
//! # use ark_std::UniformRand;
//! # use ark_ec::PairingEngine;
//! # use ark_ec::pairing::Pairing;
//! # use ark_relations::r1cs::*;
//! # use ark_r1cs_std::prelude::*;
//! # use ark_bls12_377::{*, constraints::*};
@@ -135,7 +135,7 @@
//! let pairing_result = constraints::PairingVar::pairing(a_prep, b_prep)?;
//!
//! // Check that the value of &a + &b is correct.
//! assert_eq!(pairing_result.value()?, pairing_result_native);
//! assert_eq!(pairing_result.value()?, pairing_result_native.0);
//!
//! // Check that operations on variables and constants are equivalent.
//! let a_prep_const = constraints::PairingVar::prepare_g1(&a_const)?;

View File

@@ -1,10 +1,13 @@
use crate::Parameters;
use crate::Config;
/// Specifies the constraints for computing a pairing in the BLS12-377 bilinear group.
pub type PairingVar = ark_r1cs_std::pairing::bls12::PairingVar<Parameters>;
/// Specifies the constraints for computing a pairing in the BLS12-377 bilinear
/// group.
pub type PairingVar = ark_r1cs_std::pairing::bls12::PairingVar<Config>;
#[test]
fn test() {
use crate::Bls12_377;
ark_curve_constraint_tests::pairing::bilinearity_test::<Bls12_377, PairingVar>().unwrap()
ark_curve_constraint_tests::pairing::bilinearity_test::<Bls12_377, PairingVar>().unwrap();
ark_curve_constraint_tests::pairing::g2_prepare_consistency_test::<Bls12_377, PairingVar>()
.unwrap();
}

View File

@@ -1,51 +1,306 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{field_new, Zero};
use crate::{
fields::{FQ_ONE, FQ_ZERO},
Fq, Fr,
use ark_ec::{
bls12,
bls12::Bls12Config,
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
models::{
short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig},
twisted_edwards::{
Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig,
},
},
scalar_mul::glv::GLVConfig,
CurveConfig,
};
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
use ark_std::{ops::Neg, One};
use super::g1_swu_iso::{SwuIsoConfig, ISOGENY_MAP_TO_G1};
use crate::{Fq, Fr};
pub type G1Affine = bls12::G1Affine<crate::Config>;
pub type G1Projective = bls12::G1Projective<crate::Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
pub struct Config;
impl ModelParameters for Parameters {
impl CurveConfig for Config {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
const COEFF_A: Fq = FQ_ZERO;
/// COEFF_B = 1
#[rustfmt::skip]
const COEFF_B: Fq = FQ_ONE;
/// COFACTOR = (x - 1)^2 / 3 = 30631250834960419227450344600217059328
const COFACTOR: &'static [u64] = &[0x0, 0x170b5d4430000000];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 5285428838741532253824584287042945485047145357130994810877
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, "5285428838741532253824584287042945485047145357130994810877");
const COFACTOR_INV: Fr = MontFp!("5285428838741532253824584287042945485047145357130994810877");
}
impl SWCurveConfig for Config {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = 1
const COEFF_B: Fq = Fq::ONE;
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
const GENERATOR: G1SWAffine = G1SWAffine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
#[inline]
fn mul_projective(p: &G1Projective, scalar: &[u64]) -> G1Projective {
let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
GLVConfig::glv_mul_projective(*p, s)
}
#[inline]
fn clear_cofactor(p: &G1SWAffine) -> G1SWAffine {
// Using the effective cofactor.
//
// It is enough to multiply by (x - 1), instead of (x - 1)^2 / 3
let h_eff = x_minus_one().into_bigint();
<Config as SWCurveConfig>::mul_affine(p, h_eff.as_ref()).into()
}
}
impl GLVConfig for Config {
const ENDO_COEFFS: &'static[Self::BaseField] = &[
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231")
];
const LAMBDA: Self::ScalarField =
MontFp!("8444461749428370424248824938781546531284005582649182570233710176290576793600");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(true, BigInt!("91893752504881257701523279626832445441")),
(true, BigInt!("1")),
(false, BigInt!("1")),
(true, BigInt!("91893752504881257701523279626832445440")),
];
fn endomorphism(p: &SWProjective<Self>) -> SWProjective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &SWAffine<Self>) -> SWAffine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
fn x_minus_one() -> Fr {
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
X - Fr::one()
}
pub type G1SWAffine = SWAffine<Config>;
pub type G1TEAffine = TEAffine<Config>;
pub type G1TEProjective = TEProjective<Config>;
/// Bls12_377::G1 also has a twisted Edwards form.
/// It can be obtained via the following script, implementing
/// 1. SW -> Montgomery -> TE1 transformation: <https://en.wikipedia.org/wiki/Montgomery_curve>
/// 2. TE1 -> TE2 normalization (enforcing `a = -1`)
/// ``` sage
/// # modulus
/// p = 0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001
/// Fp = Zmod(p)
///
/// #####################################################
/// # Weierstrass curve: y² = x³ + A * x + B
/// #####################################################
/// # curve y^2 = x^3 + 1
/// WA = Fp(0)
/// WB = Fp(1)
///
/// #####################################################
/// # Montgomery curve: By² = x³ + A * x² + x
/// #####################################################
/// # root for x^3 + 1 = 0
/// alpha = -1
/// # s = 1 / (sqrt(3alpha^2 + a))
/// s = 1/(Fp(3).sqrt())
///
/// # MA = 3 * alpha * s
/// MA = Fp(228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384)
/// # MB = s
/// MB = Fp(10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931)
///
/// # #####################################################
/// # # Twisted Edwards curve 1: a * x² + y² = 1 + d * x² * y²
/// # #####################################################
/// # We first convert to TE form obtaining a curve with a != -1, and then
/// # apply a transformation to obtain a TE curve with a = -1.
/// # a = (MA+2)/MB
/// TE1a = Fp(61134141799337779744243169579317764548490943457438569789767076791016838392692895365021181670618017873462480451583)
/// # b = (MA-2)/MB
/// TE1d = Fp(197530284213631314266409564115575768987902569297476090750117185875703629955647927409947706468955342250977841006588)
///
/// # #####################################################
/// # # Twisted Edwards curve 2: a * x² + y² = 1 + d * x² * y²
/// # #####################################################
/// # a = -1
/// TE2a = Fp(-1)
/// # b = -TE1d/TE1a
/// TE2d = Fp(122268283598675559488486339158635529096981886914877139579534153582033676785385790730042363341236035746924960903179)
/// ```
impl TECurveConfig for Config {
/// COEFF_A = -1
const COEFF_A: Fq = MontFp!("-1");
/// COEFF_D = 122268283598675559488486339158635529096981886914877139579534153582033676785385790730042363341236035746924960903179 mod q
const COEFF_D: Fq = MontFp!("122268283598675559488486339158635529096981886914877139579534153582033676785385790730042363341236035746924960903179");
/// AFFINE_GENERATOR_COEFFS = (GENERATOR_X, GENERATOR_Y)
const GENERATOR: G1TEAffine = G1TEAffine::new_unchecked(TE_GENERATOR_X, TE_GENERATOR_Y);
type MontCurveConfig = Config;
/// Multiplication by `a` is multiply by `-1`.
#[inline(always)]
fn mul_by_a(elem: Self::BaseField) -> Self::BaseField {
elem.neg()
}
}
// BLS12-377::G1 also has a Montgomery form.
// BLS12-377::G1 also has a twisted Edwards form.
// It can be obtained via the following script, implementing
// SW -> Montgomery transformation: <https://en.wikipedia.org/wiki/Montgomery_curve>
// ``` sage
// # modulus
// p=0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001
// Fp=Zmod(p)
//
// #####################################################
// # Weierstrass curve: y² = x³ + A * x + B
// #####################################################
// # curve y^2 = x^3 + 1
// WA=Fp(0)
// WB=Fp(1)
//
// #####################################################
// # Montgomery curve: By² = x³ + A * x² + x
// #####################################################
// # root for x^3 + 1 = 0
// alpha = -1
// # s = 1 / (sqrt(3alpha^2 + a))
// s = 1/(Fp(3).sqrt())
//
// # MA = 3 * alpha * s
// MA=Fp(228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384)
// # MB = s
// MB=Fp(10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931)
// ```
impl MontCurveConfig for Config {
/// COEFF_A = 228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384
const COEFF_A: Fq = MontFp!("228097355113300204138531148905234651262148041026195375645000724271212049151994375092458297304264351187709081232384");
/// COEFF_B = 10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931
const COEFF_B: Fq = MontFp!("10189023633222963290707194929886294091415157242906428298294512798502806398782149227503530278436336312243746741931");
type TECurveConfig = Config;
}
/// G1_GENERATOR_X =
/// 81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695
#[rustfmt::skip]
pub const G1_GENERATOR_X: Fq = field_new!(Fq, "81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695");
pub const G1_GENERATOR_X: Fq = MontFp!("81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695");
/// G1_GENERATOR_Y =
/// 241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030
#[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, "241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030");
pub const G1_GENERATOR_Y: Fq = MontFp!("241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030");
impl WBConfig for Config {
type IsogenousCurve = SwuIsoConfig;
const ISOGENY_MAP: IsogenyMap<'static, Self::IsogenousCurve, Self> = ISOGENY_MAP_TO_G1;
}
// The generator for twisted Edward form is the same SW generator converted into
// the normalized TE form (TE2).
//``` sage
// # following scripts in previous section
// #####################################################
// # Weierstrass curve generator
// #####################################################
// Wx = Fp(81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695)
// Wy = Fp(241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030)
//
// assert(Wy^2 - Wx^3 - WA * Wx - WB == 0)
//
// #####################################################
// # Montgomery curve generator
// #####################################################
// # x = s * (x - alpha)
// Mx = Fp(251803586774461569862800610331871502335378228972505599912537082323947581271784390797244487924068052270360793200630)
// # y = s * y
// My = Fp(77739247071951651095607889637653357561348174979132042929587539214321586851215673796661346812932566642719051699820)
//
// assert(MB * My^2 == Mx^3+ MA * Mx^2 + Mx)
//
// # #####################################################
// # # Twisted Edwards curve 1 generator
// # #####################################################
// # x = Mx/My
// TE1x = Fp(82241236807150726090333472814441006963902378430536027612759193445733851062772474760677400112551677454953925168208)
// # y = (Mx - 1)/(Mx+1)
// TE1y = Fp(6177051365529633638563236407038680211609544222665285371549726196884440490905471891908272386851767077598415378235)
//
// assert( TE1a * TE1x^2 + TE1y^2 == 1 + TE1d * TE1x^2 * TE1y^2 )
//
//
// # #####################################################
// # # Twisted Edwards curve 2 generator
// # #####################################################
// beta = (-TE1a).sqrt()
// # x = TE1x * sqrt(-TE1a)
// TE2x = Fp(71222569531709137229370268896323705690285216175189308202338047559628438110820800641278662592954630774340654489393)
// # y = TE1y
// TE2y = Fp(6177051365529633638563236407038680211609544222665285371549726196884440490905471891908272386851767077598415378235)
//
// assert( TE2a * TE2x^2 + TE2y^2 == 1 + TE2d * TE2x^2 * TE2y^2 )
// ```
/// TE_GENERATOR_X =
/// 71222569531709137229370268896323705690285216175189308202338047559628438110820800641278662592954630774340654489393
pub const TE_GENERATOR_X: Fq = MontFp!("71222569531709137229370268896323705690285216175189308202338047559628438110820800641278662592954630774340654489393");
/// TE_GENERATOR_Y =
/// 6177051365529633638563236407038680211609544222665285371549726196884440490905471891908272386851767077598415378235
pub const TE_GENERATOR_Y: Fq = MontFp!("6177051365529633638563236407038680211609544222665285371549726196884440490905471891908272386851767077598415378235");
#[cfg(test)]
mod test {
use super::*;
use crate::g1;
use ark_std::{rand::Rng, UniformRand};
fn sample_unchecked() -> SWAffine<g1::Config> {
let mut rng = ark_std::test_rng();
loop {
let x = Fq::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = SWAffine::get_point_from_x_unchecked(x, greatest) {
return p;
}
}
}
#[test]
fn test_cofactor_clearing() {
const SAMPLES: usize = 100;
for _ in 0..SAMPLES {
let p: SWAffine<g1::Config> = sample_unchecked();
let p = <Config as SWCurveConfig>::clear_cofactor(&p);
assert!(p.is_on_curve());
assert!(p.is_in_correct_subgroup_assuming_on_curve());
}
}
}

View File

@@ -0,0 +1,107 @@
use ark_ec::{
hashing::curve_maps::{swu::SWUConfig, wb::IsogenyMap},
models::{
short_weierstrass::{Affine, SWCurveConfig},
CurveConfig,
},
};
use ark_ff::MontFp;
use crate::{g1, Fq, Fr};
type G1Affine = Affine<SwuIsoConfig>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct SwuIsoConfig;
impl CurveConfig for SwuIsoConfig {
type BaseField = Fq;
type ScalarField = Fr;
/// COFACTOR = (x - 1)^2 / 3 = iso_G1.domain().order() /
/// 8444461749428370424248824938781546531375899335154063827935233455917409239041
// 30631250834960419227450344600217059328
const COFACTOR: &'static [u64] = &[0x0, 0x170b5d4430000000];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 5285428838741532253824584287042945485047145357130994810877
const COFACTOR_INV: Fr = MontFp!("5285428838741532253824584287042945485047145357130994810877");
}
// sage: iso_G1
// Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 +
// 258664426012969092796408009721202742408018065645352501567204841856062976176281513834280849065051431927238430294002*
// x + 22 over Finite Field of size
// 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
// to Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size
// 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
impl SWCurveConfig for SwuIsoConfig {
/// COEFF_A
const COEFF_A: Fq = MontFp!("258664426012969092796408009721202742408018065645352501567204841856062976176281513834280849065051431927238430294002");
/// COEFF_B
const COEFF_B: Fq = MontFp!("22");
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
}
// sage: G1_gen = iso_G1.domain().random_point()
// sage: G1_gen = 30631250834960419227450344600217059328* G1_gen
// sage: G1_gen.order() ==
// 8444461749428370424248824938781546531375899335154063827935233455917409239041
// True
// sage: G1_gen
// (183898640136580512316530045470998831691790391453237259434516336279447756609241220664846162561503820562316877867830 : 69018534046895515891776145953191511526693172354818719412306559690461416836925400134233128432719372819569406562974 : 1)
/// G1_GENERATOR_X =
/// 183898640136580512316530045470998831691790391453237259434516336279447756609241220664846162561503820562316877867830
pub const G1_GENERATOR_X: Fq = MontFp!("183898640136580512316530045470998831691790391453237259434516336279447756609241220664846162561503820562316877867830");
/// G1_GENERATOR_Y =
/// 69018534046895515891776145953191511526693172354818719412306559690461416836925400134233128432719372819569406562974
pub const G1_GENERATOR_Y: Fq = MontFp!("69018534046895515891776145953191511526693172354818719412306559690461416836925400134233128432719372819569406562974");
impl SWUConfig for SwuIsoConfig {
const ZETA: Fq = MontFp!("-11"); // arbitatry primitive root of unity (element)
}
pub const ISOGENY_MAP_TO_G1 : IsogenyMap<'_, SwuIsoConfig, g1::Config, > = IsogenyMap {
x_map_numerator : &[
MontFp!("193998319509726820447277314072485610595876362210707887456279225959507476652652651634192264150953923683470146535424"),
MontFp!("40474824132456359704279181570318738632422647360355249739068643631356267969150730939906729705473"),
MontFp!("193998319509726820507989550271170150152295134566185995404913197000040351261255617081226666104680020093330241093633"),
],
x_map_denominator : &[
MontFp!("161899296529825438817116726281274954529690589441420998956274574525425071876602923759626918821892"),
MontFp!("1"),
],
y_map_numerator : &[
MontFp!("193998319509726820507989550271170150152295134566185995404913197000040351261255617081226666104680020093330241093631"),
MontFp!("32333053251621136903112182208573040583096119983059602439070460434672245065050016464457115901761911040205276577794"),
MontFp!("129332213006484547066038603046131306324615528732935438218576102373893108782773376834518846023512776472080255287298"),
MontFp!("226331372761347957259321141983031841844344323660550327972398729833380409804798219928097777122126690108885281275905"),
],
y_map_denominator : &[
MontFp!("258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458169"),
MontFp!("971395779178952632902700357687649727178143536648525993737647447152550431259617542557761512931340"),
MontFp!("485697889589476316451350178843824863589071768324262996868823723576275215629808771278880756465676"),
MontFp!("1"),
],
};
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_gen() {
let gen: G1Affine = SwuIsoConfig::GENERATOR;
assert!(gen.is_on_curve());
assert!(gen.is_in_correct_subgroup_assuming_on_curve());
}
}

View File

@@ -1,35 +1,28 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{field_new, Zero};
use ark_ec::{
bls12,
bls12::Bls12Config,
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective, SWCurveConfig},
AffineRepr, CurveConfig, CurveGroup, PrimeGroup,
};
use crate::{fields::FQ_ZERO, g1, Fq, Fq2, Fr};
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
use ark_std::ops::Neg;
use crate::*;
use super::g2_swu_iso::{SwuIsoConfig, ISOGENY_MAP_TO_G2};
pub type G2Affine = bls12::G2Affine<crate::Config>;
pub type G2Projective = bls12::G2Projective<crate::Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
pub struct Config;
impl ModelParameters for Parameters {
impl CurveConfig for Config {
type BaseField = Fq2;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = [0, 0]
#[rustfmt::skip]
const COEFF_A: Fq2 = field_new!(Fq2,
g1::Parameters::COEFF_A,
g1::Parameters::COEFF_A,
);
// As per https://eprint.iacr.org/2012/072.pdf,
// this curve has b' = b/i, where b is the COEFF_B of G1, and x^6 -i is
// the irreducible poly used to extend from Fp2 to Fp12.
// In our case, i = u (App A.3, T_6).
/// COEFF_B = [0,
/// 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906]
#[rustfmt::skip]
const COEFF_B: Fq2 = field_new!(Fq2,
FQ_ZERO,
field_new!(Fq, "155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906"),
);
/// COFACTOR =
/// 7923214915284317143930293550643874566881017850177945424769256759165301436616933228209277966774092486467289478618404761412630691835764674559376407658497
@@ -47,40 +40,230 @@ impl SWModelParameters for Parameters {
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 6764900296503390671038341982857278410319949526107311149686707033187604810669
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, "6764900296503390671038341982857278410319949526107311149686707033187604810669");
const COFACTOR_INV: Fr =
MontFp!("6764900296503390671038341982857278410319949526107311149686707033187604810669");
}
impl SWCurveConfig for Config {
/// COEFF_A = [0, 0]
const COEFF_A: Fq2 = Fq2::new(g1::Config::COEFF_A, g1::Config::COEFF_A);
// As per https://eprint.iacr.org/2012/072.pdf,
// this curve has b' = b/i, where b is the COEFF_B of G1, and x^6 -i is
// the irreducible poly used to extend from Fp2 to Fp12.
// In our case, i = u (App A.3, T_6).
/// COEFF_B = [0,
/// 155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906]
const COEFF_B: Fq2 = Fq2::new(
Fq::ZERO,
MontFp!("155198655607781456406391640216936120121836107652948796323930557600032281009004493664981332883744016074664192874906"),
);
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
#[inline]
fn clear_cofactor(p: &G2Affine) -> G2Affine {
// Based on Section 4.1 of https://eprint.iacr.org/2017/419.pdf
// [h(ψ)]P = [x^2 x 1]P + [x 1]ψ(P) + (ψ^2)(2P)
let x: &'static [u64] = crate::Config::X;
let p_projective = p.into_group();
// [x]P
let x_p = Config::mul_affine(p, x);
// ψ(P)
let psi_p = p_power_endomorphism(p);
// (ψ^2)(2P)
let mut psi2_p2 = double_p_power_endomorphism(&p_projective.double());
// tmp = [x]P + ψ(P)
let mut tmp = x_p;
tmp += &psi_p;
// tmp2 = [x^2]P + [x]ψ(P)
let mut tmp2: Projective<Config> = tmp;
tmp2 = tmp2.mul_bigint(x);
// add up all the terms
psi2_p2 += tmp2;
psi2_p2 -= x_p;
psi2_p2 += &-psi_p;
(psi2_p2 - p_projective).into_affine()
}
}
#[rustfmt::skip]
pub const G2_GENERATOR_X: Fq2 = field_new!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
#[rustfmt::skip]
pub const G2_GENERATOR_Y: Fq2 = field_new!(Fq2, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
impl GLVConfig for Config {
const ENDO_COEFFS: &'static[Self::BaseField] = &[
Fq2::new(
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
Fq::ZERO
)
];
const LAMBDA: Self::ScalarField = MontFp!("91893752504881257701523279626832445440");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("91893752504881257701523279626832445440")),
(true, BigInt!("1")),
(false, BigInt!("1")),
(false, BigInt!("91893752504881257701523279626832445441")),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
/// G2_GENERATOR_X_C0 =
/// 233578398248691099356572568220835526895379068987715365179118596935057653620464273615301663571204657964920925606294
#[rustfmt::skip]
pub const G2_GENERATOR_X_C0: Fq = field_new!(Fq, "233578398248691099356572568220835526895379068987715365179118596935057653620464273615301663571204657964920925606294");
pub const G2_GENERATOR_X_C0: Fq = MontFp!("233578398248691099356572568220835526895379068987715365179118596935057653620464273615301663571204657964920925606294");
/// G2_GENERATOR_X_C1 =
/// 140913150380207355837477652521042157274541796891053068589147167627541651775299824604154852141315666357241556069118
#[rustfmt::skip]
pub const G2_GENERATOR_X_C1: Fq = field_new!(Fq, "140913150380207355837477652521042157274541796891053068589147167627541651775299824604154852141315666357241556069118");
pub const G2_GENERATOR_X_C1: Fq = MontFp!("140913150380207355837477652521042157274541796891053068589147167627541651775299824604154852141315666357241556069118");
/// G2_GENERATOR_Y_C0 =
/// 63160294768292073209381361943935198908131692476676907196754037919244929611450776219210369229519898517858833747423
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, "63160294768292073209381361943935198908131692476676907196754037919244929611450776219210369229519898517858833747423");
pub const G2_GENERATOR_Y_C0: Fq = MontFp!("63160294768292073209381361943935198908131692476676907196754037919244929611450776219210369229519898517858833747423");
/// G2_GENERATOR_Y_C1 =
/// 149157405641012693445398062341192467754805999074082136895788947234480009303640899064710353187729182149407503257491
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, "149157405641012693445398062341192467754805999074082136895788947234480009303640899064710353187729182149407503257491");
pub const G2_GENERATOR_Y_C1: Fq = MontFp!("149157405641012693445398062341192467754805999074082136895788947234480009303640899064710353187729182149407503257491");
// PSI_X = u^((p-1)/3)
const P_POWER_ENDOMORPHISM_COEFF_0 : Fq2 = Fq2::new(
MontFp!(
"80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946"
),
Fq::ZERO,
);
// PSI_Y = u^((p-1)/2)
const P_POWER_ENDOMORPHISM_COEFF_1: Fq2 = Fq2::new(
MontFp!(
"216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499"),
Fq::ZERO,
);
// PSI_2_X = u^((p^2 - 1)/3)
const DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0: Fq2 = Fq2::new(
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"),
Fq::ZERO
);
/// psi(x,y) is the untwist-Frobenius-twist endomorhism on E'(Fq2)
fn p_power_endomorphism(p: &Affine<Config>) -> Affine<Config> {
// The p-power endomorphism for G2 is defined as follows:
// 1. Note that G2 is defined on curve E': y^2 = x^3 + 1/u.
// To map a point (x, y) in E' to (s, t) in E,
// one set s = x * (u ^ (1/3)), t = y * (u ^ (1/2)),
// because E: y^2 = x^3 + 1.
// 2. Apply the Frobenius endomorphism (s, t) => (s', t'),
// another point on curve E, where s' = s^p, t' = t^p.
// 3. Map the point from E back to E'; that is,
// one set x' = s' / ((u) ^ (1/3)), y' = t' / ((u) ^ (1/2)).
//
// To sum up, it maps
// (x,y) -> (x^p * (u ^ ((p-1)/3)), y^p * (u ^ ((p-1)/2)))
// as implemented in the code as follows.
let mut res = *p;
res.x.frobenius_map_in_place(1);
res.y.frobenius_map_in_place(1);
res.x *= P_POWER_ENDOMORPHISM_COEFF_0;
res.y *= P_POWER_ENDOMORPHISM_COEFF_1;
res
}
/// For a p-power endomorphism psi(P), compute psi(psi(P))
fn double_p_power_endomorphism(p: &Projective<Config>) -> Projective<Config> {
// p_power_endomorphism(&p_power_endomorphism(&p.into_affine())).into()
let mut res = *p;
res.x *= DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0;
// u^((p^2 - 1)/2) == -1
res.y = res.y.neg();
res
}
impl WBConfig for Config {
type IsogenousCurve = SwuIsoConfig;
const ISOGENY_MAP: IsogenyMap<'static, Self::IsogenousCurve, Self> = ISOGENY_MAP_TO_G2;
}
#[cfg(test)]
mod test {
use super::*;
use ark_std::{rand::Rng, UniformRand};
fn sample_unchecked() -> Affine<g2::Config> {
let mut rng = ark_std::test_rng();
loop {
let x1 = Fq::rand(&mut rng);
let x2 = Fq::rand(&mut rng);
let greatest = rng.gen();
let x = Fq2::new(x1, x2);
if let Some(p) = Affine::get_point_from_x_unchecked(x, greatest) {
return p;
}
}
}
#[test]
fn test_psi_2() {
let p = sample_unchecked();
let psi_p = p_power_endomorphism(&p);
let psi2_p_composed = p_power_endomorphism(&psi_p);
let psi2_p_optimised = double_p_power_endomorphism(&p.into());
assert_eq!(psi2_p_composed, psi2_p_optimised);
}
#[test]
fn test_cofactor_clearing() {
let h_eff = &[
0x1e34800000000000,
0xcf664765b0000003,
0x8e8e73ad8a538800,
0x78ba279637388559,
0xb85860aaaad29276,
0xf7ee7c4b03103b45,
0x8f6ade35a5c7d769,
0xa951764c46f4edd2,
0x53648d3d9502abfb,
0x1f60243677e306,
];
const SAMPLES: usize = 10;
for _ in 0..SAMPLES {
let p: Affine<g2::Config> = sample_unchecked();
let optimised = p.clear_cofactor();
let naive = g2::Config::mul_affine(&p, h_eff);
assert_eq!(optimised.into_group(), naive);
assert!(optimised.is_on_curve());
assert!(optimised.is_in_correct_subgroup_assuming_on_curve());
}
}
}

View File

@@ -0,0 +1,457 @@
use ark_ec::{
hashing::curve_maps::{swu::SWUConfig, wb::IsogenyMap},
models::{
short_weierstrass::{Affine, SWCurveConfig},
CurveConfig,
},
};
use ark_ff::MontFp;
use crate::{g2, Fq2, Fr};
type G2Affine = Affine<SwuIsoConfig>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct SwuIsoConfig;
impl CurveConfig for SwuIsoConfig {
type BaseField = Fq2;
type ScalarField = Fr;
/// COFACTOR =
/// 7923214915284317143930293550643874566881017850177945424769256759165301436616933228209277966774092486467289478618404761412630691835764674559376407658497
/// same as the original g2 curve
/// sage: iso_G2.domain().order() == iso_G2.codomain().order()
/// True
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x0000000000000001,
0x452217cc90000000,
0xa0f3622fba094800,
0xd693e8c36676bd09,
0x8c505634fae2e189,
0xfbb36b00e1dcc40c,
0xddd88d99a6f6a829,
0x26ba558ae9562a,
];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 6764900296503390671038341982857278410319949526107311149686707033187604810669
const COFACTOR_INV: Fr =
MontFp!("6764900296503390671038341982857278410319949526107311149686707033187604810669");
}
// sage: E2p = iso_G2.domain()
// sage: r = 8444461749428370424248824938781546531375899335154063827935233455917409239041
// sage: E2p.order()/r
// 7923214915284317143930293550643874566881017850177945424769256759165301436616933228209277966774092486467289478618404761412630691835764674559376407658497
// sage: E2p
// Elliptic Curve defined by y^2 = x^3 +
// (69357795553467368835766998649443114298653120475771922004522583893765862042427351483161253261358624703462995261783*
// X2+203567575243095400658685394654545117908398249146024925306257919445062693445414588103741379252427065422417496933054)*
// x + (806998283981877041862626354975415285020485827233942100233224759047656510577433749137260740227904569833498998565*
// X2+249039961697346248294162904170316935273494032138504221215795383014884687447192317932476994472315647695087734549420)
// over Finite Field in X2 of size
// 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177^2
impl SWCurveConfig for SwuIsoConfig {
/// COEFF_A =
#[rustfmt::skip]
const COEFF_A: Fq2 = Fq2::new(
MontFp!("203567575243095400658685394654545117908398249146024925306257919445062693445414588103741379252427065422417496933054"),
MontFp!("69357795553467368835766998649443114298653120475771922004522583893765862042427351483161253261358624703462995261783"),
);
/// COEFF_B =
#[rustfmt::skip]
const COEFF_B: Fq2 = Fq2::new(
MontFp!("249039961697346248294162904170316935273494032138504221215795383014884687447192317932476994472315647695087734549420"),
MontFp!("806998283981877041862626354975415285020485827233942100233224759047656510577433749137260740227904569833498998565"),
);
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
}
const G2_GENERATOR_X: Fq2 = Fq2::new(
MontFp!("44471777796618567688228760095584248343372454885978087674329841655595593880133139294404651664057692271364857231527"),
MontFp!("152209914092745808277594956866181055187624831129109767937025242463317365117655129123148193049673425418513926319001"),
);
const G2_GENERATOR_Y: Fq2 = Fq2::new(
MontFp!("115206687171448860889110309021279060303629519187879257051215751573842462972180856243991157572371972099444077110343"),
MontFp!("191377956145194479040228903677940355038998863371661730030204479850936075480341608934735952709786495341106477933498"),
);
impl SWUConfig for SwuIsoConfig {
// sage: F2.primitive_element()
// X2 + 12
const ZETA: Fq2 = Fq2::new(MontFp!("12"), MontFp!("1")); // arbitatry primitive root of unity (element)
}
pub const ISOGENY_MAP_TO_G2 : IsogenyMap<'_, SwuIsoConfig, g2::Config> = IsogenyMap {
x_map_numerator : &[
Fq2::new(
MontFp!("165752316658948679552567650341600213993620343632797226373648182250196112194084163699689918190990441453209217107673"),
MontFp!("172182978063994664796636281648715261218877265445686511820228400278128135165425091257965367402286789184662480399420")),
Fq2::new(
MontFp!("49078863819486020728803126419770411403544927967564775122533948145670810135602221046611632159195633125363688522753"),
MontFp!("133330677606878026253733532636681674371349711466687180056118155523679405609126901243884039337337134962627419965345")),
Fq2::new(
MontFp!("88440326308038176392218244342168484162310820452393341528824316035047758188693394849605113877264996124652991932266"),
MontFp!("26460985441766134300772651139298255538590921173641559533448371120006177647448359485069994828122162245692248966113")),
Fq2::new(
MontFp!("240831597672798022181780196442988629902557797416422752447288392631352072879531084668083129009311685341499602842359"),
MontFp!("124795068789978952575783920730487695370136831800946532752608526840944057283524691812795315973894625798220920082767")),
Fq2::new(
MontFp!("231856156439094824000656216233999389240375109059054378946071472571709648546048606758615235778059505184730503731408"),
MontFp!("134026238756820071135251263743482298414233385640297868129438877114735051445009051866011097877494554014116371908672")),
Fq2::new(
MontFp!("161628978970526519329329822295337582413127505041035400390544637404697415598883543152357105789965717470570494458589"),
MontFp!("116602947282570158568911982642223012726308726836613908383578383334370050655181609483409110122767402070015216413338")),
Fq2::new(
MontFp!("231615170079008089001496386178968115998492752668752266579314749799030868007672086089822600816657899022828734321418"),
MontFp!("141639542381992520856560441410242716791591163086143661904501184306161835850893036003163803884002896297253767009574")),
Fq2::new(
MontFp!("96957224446676123824350918241672464825735454895610578698586352322390662445273628285471423071856275085141118045105"),
MontFp!("97587419381711441517698658129839468394457401157021696651597713140291602428957555768352336399994179660880524139808")),
Fq2::new(
MontFp!("18662780664429933771192510151421557554668611953190652639195940454142648933454488952361465779870877163142807899993"),
MontFp!("55517007457989983858891530398020104232682844055600438506715652841000901588962918721851719951820185832313468320365")),
Fq2::new(
MontFp!("188864327416940344326229259749844123042825201085435432627935318423081174922012610651352346391417830722940140585036"),
MontFp!("233542978062801907184831603532041452683131033894029390005010898310417350737942550513935694209129350870817277172583")),
Fq2::new(
MontFp!("33702103741469458207888758659069786556456463428431771947788685622778743201883736580054112022350187936628758294279"),
MontFp!("7531651998638745138624528632013700806848273210661661935097722938692087106885113623803921367479582718152259987647")),
Fq2::new(
MontFp!("129405180560592211762572081137246817341681076084973348177153469170177032429929182033872985192027066614650754524309"),
MontFp!("71494892585734577638768956295356005795556178117525317604450863442514001295461407965931789120761632296953990284809")),
Fq2::new(
MontFp!("121805396188033590038927712795579559087103093135515082191363074395734682090746320669474388875423586929711608364404"),
MontFp!("75932324143801627944771670190157701465835368459121478812142087933983158148741884038298732552979549182443318608554")),
Fq2::new(
MontFp!("205121513164720886728676669276499362266139599046368626660027529707299170205603076104821498121463983514654737906998"),
MontFp!("168051662766288660516992486993594951443897767271245608184500932350745292043277998040372769419920145370014740823389")),
Fq2::new(
MontFp!("224387508661509885922784938707800296916307265709615639996851552571542396031861010679067114387017955365668256976459"),
MontFp!("139097554917981907719834170888130444861465074977932740823078016609751284491153969166862091045221603146530147099779")),
Fq2::new(
MontFp!("142477190388553987083175296028785369398580520754966744245694134692905987471896623788336582063245356609279657681007"),
MontFp!("140302880976816076816721836344737338071783799730513599397010923016385668972882234545823525686327074617973208860421")),
Fq2::new(
MontFp!("205538184807792915395400814312734290381492118179294333381188081024280220461983210331268164749465891791515156713363"),
MontFp!("13030331252003455924520111292282390143014750833628314421882396445822808054003584720817672388894671968339344750750")),
Fq2::new(
MontFp!("139197805910452438551419010260519164074855817417063470117576949912038778696248952069759607969690314639425179841530"),
MontFp!("134745690770497208213126494241047670387239583870118646766457825646403640347226342104549240830903829682059982326727")),
Fq2::new(
MontFp!("46999088780962505530452862218145506822520603893157196954987630663398814970386085186714696215299498862118704356116"),
MontFp!("239220883081126775212690475926873251881459118214247205003758844846022330659109168499739536107988232402392010148915")),
Fq2::new(
MontFp!("137461512605659170682300574841422927080299499340556631216517745531687218204749421916211266297116812992348911035943"),
MontFp!("126932856673577834557989832150639712812952235385146245135235966945536973066700604316981524138335070494135486842267")),
Fq2::new(
MontFp!("57815299880375466472857931022912171296473275308202666945592250229771936329503691945881925004852905385160277065937"),
MontFp!("207900273391847649346738694548609379565855077833395139615718913929125517933139374225345876078131155102796477330196")),
Fq2::new(
MontFp!("182397511129719455005407008314265069548677727690813781407770284951663734172103638427690475141072553074575221965383"),
MontFp!("225121846650282460844501132545123914298308844633699320249517374760159461135641190512758348530493533776082794775238")),
Fq2::new(
MontFp!("42757221749971324771094873984161893488770713619971906650868412147150411626107692517374735631529074208182971223761"),
MontFp!("111424637101855455933266154646364284011426845669269128135151076357862608862363255550023430066507374024948118755170")),
Fq2::new(
MontFp!("257686488674545770403807165703608491821700153538449954828958424244540050698630649531963334687249831352703307010320"),
MontFp!("0")),
],
x_map_denominator : &[
Fq2::new(
MontFp!("196537929755540830130458921156910352741196129560556501635658595085779576490417628044619830744899117989899096675116"),
MontFp!("106967816747202586221026040614608875779671819314280336591550617355334247302203894951925800601923998790402234025494")),
Fq2::new(
MontFp!("73314120416427646620569455169905724114883313094893949291513517502168861559767103394033744003864213510722887906274"),
MontFp!("38999017135204040984255776995893429123212353273299706702441986090800506456890730978953545316903022073202240280957")),
Fq2::new(
MontFp!("133779461364688439286044255858523747234865723284672664672066362220940987786797573428234566651244275384657571315397"),
MontFp!("154931903368935230733381648548242132592387960818255334523314635613616976204585469590179605887364646535250639335453")),
Fq2::new(
MontFp!("247957910140234524214324761874381439955705875777136703199106095643204254634304448830280410483013931961038942096519"),
MontFp!("214943806307523271117409515396321303330984956986022871981067208079182219051826091487389512723678609613943324945884")),
Fq2::new(
MontFp!("11697862001088266121450094179739500241088837734277696824118211258364151630931186792937914301859707394679202145393"),
MontFp!("95980723944521770226526824868742386994509079773043937452565624851192578861364669763702851513923262074687274763858")),
Fq2::new(
MontFp!("168096269708683796856556357930292925811554548435612382636199127159818409693729567946366892866365435246772528367031"),
MontFp!("99720174640078175171062115168656883367851695095484071724968247253018133737453004325770034298778522431209097310502")),
Fq2::new(
MontFp!("33059404918884325948584592996172619413923041143099424466021368531149134447772287601175965141235934645074697267050"),
MontFp!("10757428905957703588038877674336794621171834192483169256644941002565404396356505770991807551250572677872221995215")),
Fq2::new(
MontFp!("142027935684179419855710336591935481541662612521926997142809731189880364304749483394981554800161483370077741056896"),
MontFp!("1943403947563275150997369785095274118967148389261968103605246462390957897712088493386683316483490223770940902453")),
Fq2::new(
MontFp!("200535851812830711305923885193456283997079838967145939474743725430895019937175928830731575175640901984178880783011"),
MontFp!("73874168720549156282270730246833500558176745413797996774310087510749148634278604002052708223696920208907646881989")),
Fq2::new(
MontFp!("220384543328043309613139993483671702409123249316603413540407457441864555087013622511692877380446192851630287225413"),
MontFp!("39000405073743042346296304484168728185850505353133307908773204457381817815206498660334035187329579833299098854925")),
Fq2::new(
MontFp!("219195224293908756855578672234544437367397890301565855376597788842679778002659222115121213889017072727428356719234"),
MontFp!("247894577734607804564008327202067464850944943412136922154651844411293409127507835027401641672218158657943826643185")),
Fq2::new(
MontFp!("146699001487357489560227247646638441970227213145065178169054120124066032784405371946823057532199624317631250110158"),
MontFp!("196336324454181158449524835117699225596467237400207491815838252818724619960701247377784788803043096102210425517795")),
Fq2::new(
MontFp!("155939253194251956164424003889230633804182501306742152137449150503013281009623802843490858570697615902305132709111"),
MontFp!("172261303485740204844677209985093962119870302741179905216184157502752680126595180139007438892219460422745105017475")),
Fq2::new(
MontFp!("137972103666241533333852948884443545062916813938500094392929132716673981519930321922556812217620174550912349461419"),
MontFp!("47600282095791674213992406796226738606147801920837771594412659335039656256887529097801732359033209329929517773020")),
Fq2::new(
MontFp!("135098057022357227608956235549944366234286127511416070373827898662879730495316177891045223676768538262860577751087"),
MontFp!("218641591773893348322227471378547165043111820723080862748702228639502320411481947789769811366015509814793754417785")),
Fq2::new(
MontFp!("228687493726193558146661770435566220015197012398911029567178581932152080915557441338298274247922585720118620741642"),
MontFp!("48223421552324743764826987807666420223567068651197810526658625431719723647078135623842652870214605734395702563953")),
Fq2::new(
MontFp!("82401683815523491481199527201592079745651015539510634295850130611233688561451492330603949648060220533354045095181"),
MontFp!("159070381032762485827712709726121404273458384870681735035622289092845201234785949112608113110663482448286550123895")),
Fq2::new(
MontFp!("61539107135026562717413992304341045078777699607129438878970720148394005607774781361280841945254066290447512808860"),
MontFp!("258564647705165711537697112631909171171984598885182416737094411313452565619624851452883996847677936536536427515609")),
Fq2::new(
MontFp!("219867891253233227579149075701158020315633373195728794672342716359369374905471205886891783929214978430681990036959"),
MontFp!("40524381030862708561992431051313657250449208728762250622105264621614810013551839533882876237430311293361821844681")),
Fq2::new(
MontFp!("88800087516399959501800534486349824688877578947555023348699585957763763180753947498274724426567091309571649023166"),
MontFp!("122245180850560437899129167839042992977076962956306963014567407897293197200681367630073717776421484831646532593850")),
Fq2::new(
MontFp!("69204740140688189359361744597982172008615446130082862488352885921056331761951244674105352971861180999345144984246"),
MontFp!("38216467720351249271557670250657907497353617320059247139049052120842234439257669911851800147147313339669901995490")),
Fq2::new(
MontFp!("114765242606519624982400506165904237893471895287563151339459173837887003905317760268941880935997925302483810508170"),
MontFp!("226808321937551848279625259185874129283473963677740840941191767963773773116795416044456897499248110949601850478751")),
Fq2::new(
MontFp!("1"),
MontFp!("0")),
],
y_map_numerator : &[
Fq2::new(
MontFp!("243169287995837894205750503657473181252400776697661357268613577074201794943537027717771587727860769419520957117060"),
MontFp!("154445371651863854130996979206021232172872232688365227537444264835087932826365764405635125797374865965304745730822")),
Fq2::new(
MontFp!("109149004424675517113489432756837393820953128532207867425106578478986226345054217066591849467433110788215195319750"),
MontFp!("30408441237651674477115309504276625429344634933425091999725383701660094027885762738289460271315609173544614563248")),
Fq2::new(
MontFp!("8414285408102090292522571401032945098403423241877066651551931468973120658567171350501434823318074450118610388181"),
MontFp!("226047422399128874433860903177676209375847937545805175562415311468986239012130226120019081492247088609694678876810")),
Fq2::new(
MontFp!("228308803559737454633222698485074629499383737811342884536963429506633258142551503400414163815852158951494613610809"),
MontFp!("220909287290837789818195731110558629271153823543746871132117978761339034747123501189473420274677281822601971748563")),
Fq2::new(
MontFp!("116623955280658732717402646061913268461869836841204913444259922610012147799771656282704605878638711580234302879520"),
MontFp!("251345693404812657374633929641944735274020119374936409701199723189056283828393555325905238148261248120379910778583")),
Fq2::new(
MontFp!("142632909729670553826438094523500302011158161959746397893981306350515911350319381478896794266740222044724793183031"),
MontFp!("135097007131619291616144192105571840182910366835929043414300810591005223344182310684819863256436016908585466099814")),
Fq2::new(
MontFp!("159262246805999098136860288248138175456624792734939305704793543040582454889431805248352849370505960249829264037333"),
MontFp!("256411146327954053251262434650444473133439725697572806395735688747939610541453396276159230618136278790246160635595")),
Fq2::new(
MontFp!("106675525854808944323662773997719159035717496275254424840883415090817949089664218352587480756720528552217297479523"),
MontFp!("142202207982399429498494980946602932891398916434890751210930378360132151108127041093945093575972538591541631204396")),
Fq2::new(
MontFp!("115853993705912938985758922127173369175321347209545356726288637524744651943071927137158115778405271676616612170666"),
MontFp!("188439202506521797668192307957766105517906171778775206324453830870041256388075168650527562921934698697140423464142")),
Fq2::new(
MontFp!("199891426461397900698689228549412057991574595606781836622700872746783962617889812808189413859146835266670353365164"),
MontFp!("123487321384490387195094801639396482206262484603737596281845841408384878196277195829349272799617445074531384638014")),
Fq2::new(
MontFp!("203453160391122297114764634999687500867096029894782931052056493086745424054313508850135956093450854351511962568248"),
MontFp!("3933321808920817665892338621688661599151270488240879901971434149901647580182088988848276352998263499828820719486")),
Fq2::new(
MontFp!("216229669548325266866202681779047392389311278655704899819569794547799955366773265486059541504823551138048188296915"),
MontFp!("41448968894064940344019909320065089603789758666259308674991068396259424208998703895462327945020441899649105710894")),
Fq2::new(
MontFp!("202678826482051686554967485240375873611017127444692775767942717540980994219310434688309713205309853725035377739266"),
MontFp!("48778316120483961415587198479185523835826749642473845435889717611018677968038563827240090688089889339896065735651")),
Fq2::new(
MontFp!("43364741387169348753014627410136368149262698966106150910900756728904165177527487078077667350512959263803465594111"),
MontFp!("61944739699039529393579599024212698483276675572994284564132452254474389809816373777333943401872462638231436446348")),
Fq2::new(
MontFp!("1902545032251691771730077590223241149624964994150687591044314892275508885163105731414463515832696686914784357054"),
MontFp!("67221897212365550931740188657735915316732820967428518278153545138481072202717711417949297443415145931349647354864")),
Fq2::new(
MontFp!("232464396645736057215489125286424902556417590819993013568149210848680788030572385843387291711255018198764185991688"),
MontFp!("41800154023275681622180037448850007404785328883356603798952195956734186941687720006035939799906615555216990599152")),
Fq2::new(
MontFp!("187038260664272653235271156369560372695631446985830424056061915935191103410794701043280599214000281588074544657045"),
MontFp!("38290302770763423573829549940707041833171456153861823771988991461936307395626028842226881832323571911777783325552")),
Fq2::new(
MontFp!("8193038016485856982946817225511231096542148907426451941320763511467909442967073658628847889502238964737537651732"),
MontFp!("9418692556935347898382092734571186686450013671235254851703843297990915553970523788207837029694342875454233715193")),
Fq2::new(
MontFp!("134073844001083825421215848942909782702386338984309026786345170296027964134133613977422644522116018820345983847098"),
MontFp!("153830492090479629579603390014414329445124716355506854714467139884353350218676155251380590350715220577136073627555")),
Fq2::new(
MontFp!("24894203921911934571199160858232802417038583022586807490232139245280305064770051397858560092019807972764914216208"),
MontFp!("120208242722200714489749801697072499732825359039071841003310452443348308205795253556381720202955786470886397257982")),
Fq2::new(
MontFp!("190392008574458975806418600277835706985376229847531539152452591238358119216217627352637258288556199770365835067627"),
MontFp!("236947842470057836630333692287445445381482585314120394670322793497639860754696181540315462907276465780536189751938")),
Fq2::new(
MontFp!("128014602802339573117431114877417430852771121268703430430938496966993823548956133449208721198231566864014207876438"),
MontFp!("76313913933214383311039506294052736258824720597935452573279680967713148986901401959316819572744945391130691484709")),
Fq2::new(
MontFp!("25945524144868616798377005434321968607597029473408456417628770501736226577600936996306306386148517051252174176056"),
MontFp!("93302878136439028547402102681387844515310157832968167882878653011659204369510932686206718073261314562836132094987")),
Fq2::new(
MontFp!("89345438915485267000169594163110872264018138861479961667441187849751112704236404111089533981719810422892295971197"),
MontFp!("225199447663521472758596124691205483139271667363437613911741821442536429098852529066869544898685674003162780468715")),
Fq2::new(
MontFp!("133226465537371725791207823007732608016851433266603356824246032571600774858733596680855277271698121233692296984412"),
MontFp!("214026235442364760645768878901893433888530027239186932434340221483611429797860448445573321733516533800376783586849")),
Fq2::new(
MontFp!("209865017468509971341642462085093919192185569139223034709204939485243056860760867821924437786503336074163109167043"),
MontFp!("219490420378012040044597900078465204875085141304274262719756064241884227366143829466191943246131284770521917871841")),
Fq2::new(
MontFp!("107794270350250727824303719264349327362253764840855494366195678657690526275364378542854833701549538802096418248084"),
MontFp!("214497132288922282410470995366492104127705853917251639956391350188219443322307620708083843529019036699996096662829")),
Fq2::new(
MontFp!("216436913923048926393371382639334167145590308917722616640273699755872914758105310937706004925121569777096571773501"),
MontFp!("14821532235517245029225575994881495294340097494060025842437989195232333244802578196149414170959605497405878582540")),
Fq2::new(
MontFp!("149340524242957423974772893433814190392014381473852786295383636551096665463613496468840974015807625484823068784839"),
MontFp!("92602205576740019970555092291786069878442230185393269119060098961688837594116147683652993589116622567477525635445")),
Fq2::new(
MontFp!("187289608720372854303118076618428364941868395899689208696722069999084187290922488892094161492110977423619035272649"),
MontFp!("138246251209835932037747211155451146889753321830881007441732932302281412878493276648902633332871835811473542877960")),
Fq2::new(
MontFp!("165653628641840315664303139225783620502451401675361521932235743336920154286645843675719999005591028855021909439672"),
MontFp!("221484407095875062109245088271905042727631591858266177514520864715688286361376419124935364810076972840743950061836")),
Fq2::new(
MontFp!("133980604703672698089766182661998480874540278232523164821108522954758888202993741126021280431373622479768313949356"),
MontFp!("38886256490758184304393553179653915986060051480245869194662478974097783410818598716423697164666847852998235320966")),
Fq2::new(
MontFp!("8411654157888762354868203383638678565276209861191964793314989111047210939710084789719415109438273538021505111510"),
MontFp!("187207294428708203829145346569036650547801585764458185253951079008883539428999915118458145884040644479498579194069")),
Fq2::new(
MontFp!("191144230647045707590184821948778479495825928592047153194222027257046414968351470170933284561757547536684715232224"),
MontFp!("0")),
],
y_map_denominator : &[
Fq2::new(
MontFp!("177304823246185962354212404236288831041380791662214394697399928748373114098169675564032904690251242875327747673679"),
MontFp!("234106598974619695004693596968258258794247055108931498762994964636371479098512727352039267846913406623802246782945")),
Fq2::new(
MontFp!("255874157960252694683645508260848371559149621054025374393554376526882940742514793344046680765937904153005134511200"),
MontFp!("19068358873460915055376626440913257473060029137260026174266944920186136734103362122730468957229595374427187617425")),
Fq2::new(
MontFp!("83946178094995839681455048029661822915614318352963730526672352524233381944447759416757234629624830143848209247040"),
MontFp!("36167189440196390196320129647971031300455228428629866775570898825049060037811108115927676106354625467897211624573")),
Fq2::new(
MontFp!("214137118009637944275213937166601531498145257806838837034827533674793291112410824873653425491233537265355337125438"),
MontFp!("75310151275642225944994533227518963961512910025529659163648069668626195571780520556481029340507362571133885889206")),
Fq2::new(
MontFp!("107140053800026140817203074526089346919722280052456645787788712045148531978814339001150298053597504647766497707422"),
MontFp!("114397460921328140828185121166450637136573513025702964340164304518654108540682577087979875141067314446917571826582")),
Fq2::new(
MontFp!("42398151340378868438123040588425908782227436520374323184618125390984068793920538080412999034838310511981244418952"),
MontFp!("82194329196840936158921467961561828669469444994699107543787160001285217807552090667641931153824104285439311091477")),
Fq2::new(
MontFp!("32044478312863504453978511975839237915357713065285858656377527520925624222082496835678894223326750023304346513708"),
MontFp!("224732340440722096332247540469311391766792864305974461767563394934556509366444399113606207665094042937608880394380")),
Fq2::new(
MontFp!("53290030879673160724264978063216325707183784347799183367929912851157629196486013218134779085284663628473135140615"),
MontFp!("42967590874964323361920860309631969474991176192252393149421408476343364383848642144439727879920981862569415477634")),
Fq2::new(
MontFp!("250488593850017034090300371968459931740406675270099747930030660805939980644430804509506597720682995099971419762057"),
MontFp!("131736273443849165304852712527070616520885505701320868662058330388440710419459541866884603770735894010610491333882")),
Fq2::new(
MontFp!("251064692215092635541196206457923985861467397867989080397969990645886126152674833092283559946890888232618697517884"),
MontFp!("171430383391121065822039978510482289343958135960126315509375831831735263180943544895493884988847947752888720502133")),
Fq2::new(
MontFp!("255810123836950778051032251049468471118744836441263107437005316697409810175422976454215094737538073112171964000966"),
MontFp!("78363344687446114757879143124020926645520829625790622079288990711202726499291972408305265373741655103522048633806")),
Fq2::new(
MontFp!("94953611600133917480746113251669332369937157892937924494319507354263981756523698288726321437604686331762128114942"),
MontFp!("224037954053161681052577381077631881138732983068288196649494577229506443999757164090758954620762136536790092765707")),
Fq2::new(
MontFp!("18177910449767953614338723180992575758462819793657888834925741153507922227776503487306285172452430778418239589878"),
MontFp!("55976309667093193926953058482403983650044130588205371047077237394269232758375928755579870418413040530924659710422")),
Fq2::new(
MontFp!("108398849957050915959578499238335172000970311919637037913625633347326921657585237193100994767528244599176367431882"),
MontFp!("204809230842263072415312635210643987712012160534293694062738501600937603588267937911969298058204043106501986725326")),
Fq2::new(
MontFp!("40836628940164991036725499428168139451294386215534361893839871958837737306822281294361671587764896498700322394958"),
MontFp!("119396884503349014053839666170414789560955868303656326650021743484252346209353246139311353657707899076368015332219")),
Fq2::new(
MontFp!("57449149099548285338146473529383255206310079371370663992648410210841833627207062160011080280732475904935527767063"),
MontFp!("53213606042373287683153647684084583002441527525177758051678463570615020765660540938870067881706148841340293404257")),
Fq2::new(
MontFp!("136011650568921952309089811450436645471254909718073766303847394446918967077385999380499048535832357755732371368738"),
MontFp!("167478505497067957490757520193067128323382872103395718848436244112857102765738573826312783708349214669979612036158")),
Fq2::new(
MontFp!("124201488690791095020042847186337439989685011854729481246272047846908500431421470344897520044190299684207452017073"),
MontFp!("206045464105062318563700338460670926332476051084269665075012377410704353049241671458557389593362582538704238377616")),
Fq2::new(
MontFp!("141307886851791570111930048284226290849958071383456038631306928334570275405889250568493573543543795501685612269615"),
MontFp!("33695298953151791677564491610276872092952551110021466172491397823758283921068636555353240048692541883780027233962")),
Fq2::new(
MontFp!("248265339860070148327157063205450906034372346050742532250909040050681913704941472496789561564874787781299103889328"),
MontFp!("246735083688655178976599901436968434779493759990448799231310864308891009496294971885106650388027197609829556319894")),
Fq2::new(
MontFp!("242374981274128257174433646391488180576863913259197526647513270422870835725158808599624055920155693832356361192562"),
MontFp!("228823832066259533984346839854456963456061412139464585495219844904598927917971403987214543635705786807302526573779")),
Fq2::new(
MontFp!("252218794556637183364789705825049189219556217519670190016584589877973440046635828866291293002549365274213665103495"),
MontFp!("246226868929550107779875102413192686259972538740042993595504829761267272514998892312681511407413880843390092913913")),
Fq2::new(
MontFp!("194440756770673250653849096711805826346541581797630354589253365569405779009028682866443842541588052010949210024484"),
MontFp!("75265817091612360444217709043194311507703596250641164601263089234422086318666070167810083868284770450890779266774")),
Fq2::new(
MontFp!("30126025128311053094362231518416999154688680759401769180563223025361877725315179695978985780460875616652938854146"),
MontFp!("53390417057360854696711134553867053334956120915983753729596602193155006833056717338565729257476036879055975910097")),
Fq2::new(
MontFp!("101332532133743769759178027285109552486478973958553103055307446365529747250973790438239230671819476569086244438727"),
MontFp!("148745905560783494991892238622790396213255789465409808038709750840775025617296316699696997331989504328034553213894")),
Fq2::new(
MontFp!("64805743514968884017432304617184871899075979363892814607985017391426869625002757534871594116135107848421987411961"),
MontFp!("6046324386958113626500748531301314307229746408846776295678625368971798823548167403538529285882066298168231669149")),
Fq2::new(
MontFp!("42585898388361518080924198789209195881860509830112816215046001795045034138585747974649960102171072364466234418812"),
MontFp!("132695208880203057798268960407754614753345990251279710979596670783892175104478291787481794529190706739877760089560")),
Fq2::new(
MontFp!("212862020601301354783026588297306531610140885387724836359356800753780855161155144746080869191538655229274242914307"),
MontFp!("157598266513011182093451150345114371606842593014102635902061162138398777778450012845089379844999350325670077782200")),
Fq2::new(
MontFp!("4121090928751590306336774011079865996138664888804166805010515676212588791761189056383637824656513752764121888675"),
MontFp!("183219245849642047090141657656072708461001592401873575143115550847958265143529306190408825011434780265059908079650")),
Fq2::new(
MontFp!("79081485025787885179619178550309706744599846607596447880706626420512740963985633088538634502003788677250834958908"),
MontFp!("183808890703436998546164599111050972902808423546263572335175957576564587842514119276068990911067829699066843757937")),
Fq2::new(
MontFp!("212106075999882114389916784897163150756429321557076536924307653148222968665985018997130331497354557069316538670523"),
MontFp!("6765896997590927451499527318422027932088882822980873934837948553969718709492787823596776070132570199077127482065")),
Fq2::new(
MontFp!("234716866510887739589745422464313597883163631119309437461957606368046054279070563732715561665778636277317684644515"),
MontFp!("97451989647642778641795555357790293895920858058713680518946629728091416392679362160653023502048556793761866531581")),
Fq2::new(
MontFp!("172147863909779437473600759248856356840207842931344727009188760756830505857976640403412821403996887953725715762255"),
MontFp!("210880269899843225414111521931364427157014189139153931141845520612300425501022712679200902179085486362182614989038")),
Fq2::new(
MontFp!("1"),
MontFp!("0")),
],
};
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_gen() {
let gen: G2Affine = SwuIsoConfig::GENERATOR;
assert!(gen.is_on_curve());
assert!(gen.is_in_correct_subgroup_assuming_on_curve());
}
}

View File

@@ -1,33 +1,39 @@
use crate::*;
use ark_ec::{
bls12,
bls12::{Bls12, Bls12Parameters, TwistType},
bls12::{Bls12, Bls12Config, TwistType},
};
use crate::*;
pub mod g1;
pub mod g2;
mod g1_swu_iso;
mod g2_swu_iso;
#[cfg(test)]
mod tests;
pub struct Parameters;
pub struct Config;
impl Bls12Parameters for Parameters {
impl Bls12Config for Config {
const X: &'static [u64] = &[0x8508c00000000001];
/// `x` is positive.
const X_IS_NEGATIVE: bool = false;
const TWIST_TYPE: TwistType = TwistType::D;
type Fp = Fq;
type Fp2Params = Fq2Parameters;
type Fp6Params = Fq6Parameters;
type Fp12Params = Fq12Parameters;
type G1Parameters = g1::Parameters;
type G2Parameters = g2::Parameters;
type Fp2Config = Fq2Config;
type Fp6Config = Fq6Config;
type Fp12Config = Fq12Config;
type G1Config = g1::Config;
type G2Config = g2::Config;
}
pub type Bls12_377 = Bls12<Parameters>;
pub type Bls12_377 = Bls12<Config>;
pub type G1Affine = bls12::G1Affine<Parameters>;
pub type G1Projective = bls12::G1Projective<Parameters>;
pub type G2Affine = bls12::G2Affine<Parameters>;
pub type G2Projective = bls12::G2Projective<Parameters>;
pub type G1Affine = bls12::G1Affine<Config>;
pub type G1Projective = bls12::G1Projective<Config>;
pub type G2Affine = bls12::G2Affine<Config>;
pub type G2Projective = bls12::G2Projective<Config>;
pub use g1::{G1TEAffine, G1TEProjective};

View File

@@ -1,122 +0,0 @@
#![allow(unused_imports)]
use ark_ff::{
fields::{Field, FpParameters, PrimeField, SquareRootField},
One, Zero,
};
use ark_serialize::CanonicalSerialize;
use ark_std::test_rng;
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_std::rand::Rng;
use core::ops::{AddAssign, MulAssign};
use crate::{g1, g2, Bls12_377, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_algebra_test_templates::{
curves::{curve_tests, sw_tests},
groups::group_test,
};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let mut sa = a;
sa.mul_assign(s);
let mut sb = b;
sb.mul_assign(s);
let ans1 = Bls12_377::pairing(sa, b);
let ans2 = Bls12_377::pairing(a, sb);
let ans3 = Bls12_377::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq12::one());
assert_ne!(ans2, Fq12::one());
assert_ne!(ans3, Fq12::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq12::one());
}
#[test]
fn test_g1_generator_raw() {
let mut x = Fq::zero();
let mut i = 0;
loop {
// y^2 = x^3 + b
let mut rhs = x;
rhs.square_in_place();
rhs.mul_assign(&x);
rhs.add_assign(&g1::Parameters::COEFF_B);
if let Some(y) = rhs.sqrt() {
let p = G1Affine::new(x, if y < -y { y } else { -y }, false);
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
let g1 = p.scale_by_cofactor();
if !g1.is_zero() {
assert_eq!(i, 1);
let g1 = G1Affine::from(g1);
assert!(g1.is_in_correct_subgroup_assuming_on_curve());
assert_eq!(g1, G1Affine::prime_subgroup_generator());
break;
}
}
i += 1;
x.add_assign(&Fq::one());
}
}

View File

@@ -0,0 +1,115 @@
{
"L": "0x40",
"Z": "0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508bffffffffff6",
"ciphersuite": "BLS12377G1_XMD:SHA-256_SSWU_RO_",
"curve": "BLS12-377 G1",
"dst": "QUUX-V01-CS02-with-BLS12377G1_XMD:SHA-256_SSWU_RO_",
"expand": "XMD",
"field": {
"m": "0x1",
"p": "0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001"
},
"hash": "sha256",
"k": "0x80",
"map": {
"name": "SSWU"
},
"randomOracle": true,
"vectors": [
{
"P": {
"x": "0x0123184bf576b5d69c00311c57eb503e3df99ab60156a2bc34228e46cd1b0c8a15304f0de63602ae32bbb08a7f44c2c9",
"y": "0x017c05a4f658399a64f5028b1c5d8a928f6a955bf28525d906592b9e6aabdad838102c6b1b4a9108898931fa42ef0cdf"
},
"Q0": {
"x": "0x00e10a1e6c2853d3416288652f6cda34fd2363c993f4c4fdebb38f185855fd17fdae6f8b35f6586abf39b746e14c0297",
"y": "0x0132b86c328a4c52e82db1a43257ca0cb5a8f8e2546b92a854117ab26cf6607e9d8c207854d8597426c6987ebca42d97"
},
"Q1": {
"x": "0x005648e0f6aa7131780c1ae8d396bdac0dc8e76426b8a2adf6b0dee3a0f80b7152343332a9c2ad5c83113b8956fe2685",
"y": "0x0196b1ffad506901d481b632f7dc9ebad6e3eed84c7d03edab2c7df0b1566c5b5d376aa2bbd4c7c169abc449f3129f9c"
},
"msg": "",
"u": [
"0x00e91c93755d4dce58b4277d109ca11cb178e160d0209f0b97c0ef0a9d03206bdb93498faaaba98969d4a50f91d8fed3",
"0x01442032ceae5c549af8f3222a0b9fafe5ef19a001ab399c2ddbb9f7dd59671150a067bd104604bc7d7fb9b909a2b276"
]
},
{
"P": {
"x": "0x015756bc7b5a8140577878f75009f8a0009bf1820719354863a52057d0758b27ff7d843e177fc618146edec267d1510f",
"y": "0x013b4be1db30d04593dc965b804044c2f92e366543f32377463a0deeddf7ddaa0e62e843d5590e948e5a0d9af2b917cd"
},
"Q0": {
"x": "0x01029fe43eca43ce7adca5d31a84b66b28fc00de3adcddd393c3ad1bd993e24cf70a9dd99b8233d2a657536943cc5000",
"y": "0x0011e54e8956bfbfdd17dab8b91e571a49ef5c5c7a5b3c00f9ecb045c39c6f59e3c60c3cc0d290c0e5effde15672ce8f"
},
"Q1": {
"x": "0x009e6c4f23e3590fb40b0a622a3cda01addda2a4ebd860ba4d87615c299f87e02c190035e593e6b80b18282d37168f3a",
"y": "0x0090c6fac6f33662a3b50631e367b087e144315a4400bbfbcea7c16366cba865893c85bfa79d82cad31954925363219b"
},
"msg": "abc",
"u": [
"0x00cf409921dcdce7de4b3541144bbb5c41592a95278af448bb6f6287e5a71b71c8148a03b8f98cf6e654b2a93bf89c5b",
"0x00bccdefe8cbec53dad21b03a0d1f05e1e4c401a7f20ff349043ff1afe8074ea4edb457a2181d6388a41be08445f1099"
]
},
{
"P": {
"x": "0x01a6d66a21a28362895c867fa2a65e5e54fd85171a0a8327faec0f7272dd5fbfeaafb311d7e83c85dfabbc790fb8031f",
"y": "0x01183a9c2d97c91c06cb090e69cfdf0e89e92baa780b8e3c5e1d92488d3a2422896c4ab808ab099f0b4d9203c7499147"
},
"Q0": {
"x": "0x017397c57e444777264e21318d6e0096779eccafd05f7a95a87acad1f8730fe7fe9e1d1dbf1ddf11539515596ad71861",
"y": "0x01660b0335de45c1d4e7edc3b1230bbedaf598cc3943ce854fc2d86d84080486c4b0f325dbcbef0212b99ee3d0994f58"
},
"Q1": {
"x": "0x00cfcc6e7987859db4156bd643a7ac69357f0fa86c6fec36e039b2822001c90fd852c4afa98a5dcb00e65280299520ed",
"y": "0x01823e2bce6d7769163f6646e6d80944572a6c473d7760b0b55911697437e7bedbc6674a4cf55850d03bc238128e9479"
},
"msg": "abcdef0123456789",
"u": [
"0x019061c2817582abc25c57a58f08f5239bd8d0eb1980d2b911e38131a779e0991c5a5662eb8a6aad8ce0bbc0cdfb67b8",
"0x003d673f221f321f652ad6baac32fd04ad1c06a2c03e4974f752e9b87f5fe222b120e853c7a7c767255adda229c71a49"
]
},
{
"P": {
"x": "0x009574af6ebc91ea9e337178cbd5c83ecb9d42fed22b3272c3e50b1840c5089fe5bec9808eaaba8a06ced26a30b82747",
"y": "0x00ccbad45957f1d493c1859e325c27dca3c63ac49177a1b2a9b5e22e14fd23845a638214e85506f46260db2827e2869a"
},
"Q0": {
"x": "0x00a4721db398949969915611e7a65cc43d167bc9c6b11fa69e871663aac40266a4a01ae64ac380dcce313f9975fe8f2b",
"y": "0x002123e943b9a1943d7a57e69e30c84c9bcebc96905b920365f2fc5a4af2f9c42bc1c7c5660d3b10de8c8b1381b8163c"
},
"Q1": {
"x": "0x00860490ade9e09cbf22a1f32cfe14bd1e82721b73a244d1e3e03a38ea45b0332dca194a5f43bbc8e9bc6319399a0a13",
"y": "0x00279ad50592f1a5b92430020566b2bca7837bef7fe0f8e08d456962b7ff6a25b4839863baa4a9659bee69af343d8ed9"
},
"msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
"u": [
"0x000ec0c5ca9fd63019bd1f989f8b054b29a0a1833a0e3078031da7bb6446de321ddd6ba40a7cb9dfc70afca8bac538ff",
"0x000e110ff18deec2d60a2dfc92642fdebd6d70712114a6310e1f3eadf56e608a05058d378413fdb819c8274437f0d440"
]
},
{
"P": {
"x": "0x00c54bd72909539ce2c7558b081a7ab7cf8643cb5c02e87d233f6458c69c1a9270ebb0a6c42083ba38835a2698a57cde",
"y": "0x01a9529726f7d9994634d1d02c1ab474e2b9c20f2cb0cfec7e566ea033f40438548e737c43d4e7d1cb2fb75bf7686533"
},
"Q0": {
"x": "0x003ca77f5b09d595550a258c0480381569c8ed1caf4bf69e3c8a530d1d910d3ee941a53f6abc452219aa79f22734e61c",
"y": "0x004d376f45eb23e03be43ea5c1e00f9290d800d01ff0141c8faa8d1b0bd88c2ee8f3bb8c7ce17ddfe21633ec2b223780"
},
"Q1": {
"x": "0x011f325cc402afd10b3b92a6ea9f52440d9fda541cd2fe6bf58040bf803f23a22c59c3dd494c1392f911ffec1a283b98",
"y": "0x00346cb1d6116a329e755b913f5d2d9c7f5405b21e8e400853791ffaefc18a1b1aa8610bbbd4961fe112aa78d1859a40"
},
"msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"u": [
"0x00d5ca54c4622a2f8ec71843ce327959689ae7ff37e7509a88212b3b852e213cbef248471eac50bfdbca3c9ce733d8e8",
"0x00b91b02d867e03924593529ae87f35a2adf317a87209bed9c91d5c886e801191676a272422454c7d9692b8368b02e21"
]
}
]
}

View File

@@ -0,0 +1,115 @@
{
"L": "0x40",
"Z": "0xc,0x1",
"ciphersuite": "BLS12377G2_XMD:SHA-256_SSWU_RO_",
"curve": "BLS12-377 G2",
"dst": "QUUX-V01-CS02-with-BLS12377G2_XMD:SHA-256_SSWU_RO_",
"expand": "XMD",
"field": {
"m": "0x2",
"p": "0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001"
},
"hash": "sha256",
"k": "0x80",
"map": {
"name": "SSWU"
},
"randomOracle": true,
"vectors": [
{
"P": {
"x": "0x012988d49df0158335f268551a0121a3fd5509580e675ed2e26f66ffb8ec1089b9db4a69bd19db25f7cae34619b8542a,0x0060eecba902692a7f95900c6501ea3f6e6f52b2e951586f60c9f31585c4fb63cb5486d155df4bc394a872f6e0bc3eea",
"y": "0x00e07c09af8c992a920bdfcdba4db43b542c5799258f2a01897d5a0c621db77c29f02ca2afa99d78dad2abdd4e180d89,0x00020a02b4d45959b67af782b737915298c203dada50f9d4941ada19ea7e986e91a83cb33d01af449dc540244b418561"
},
"Q0": {
"x": "0x0040618d422085e035e06f0333349c4630b7e47d96c45b803db208243cfe176cc9b89710c0ac9b6c25387772b0253de9,0x016e1c02056c1c0d179c0225b37845f1ea7fdeede136d731b2365248003829bee421b65f64b43c579ad9b30469d6cdd1",
"y": "0x0011e6e3019b9c453e3b930a091fb514b082e0353dbd58185d8e9211ec33d036c7c1d535ba020ad2b5cf584aab23fcf0,0x014063792b5a789670e1f75fd996a22fa9174888dd315fdb8b4597bdd7572edbb145817b933a0f79c467dabf473ed98c"
},
"Q1": {
"x": "0x00d0ec3127b58d178301f9f63be6932d2bf84a71fc79e50004efe7d13ab9ebd80cb7a958a369a1061e5aeb5365d657d2,0x00a69c72d1855528334e08529d9d304d39326e5670943f2fa3d57f32b4e1ce215a7df744bff01574e5ef35826e61cdef",
"y": "0x0158d9d3ea783058becfbde70cf6215c53a9afd702308c551c5d8b02e00240e20ff93d2d4515d3033b92d44b76f063fa,0x0111257e46569bdb27e1c54c51b57a0aef5c5b287e28205b6b08bb585087774993895c2886dcc500c98fc3af92f114dd"
},
"msg": "",
"u": [
"0x00bad459056ed98adf92ddc87a4b9970b8ce50e5c1d811f72a5631f0ee41eeba11bdc1fcbf135ab259f7be9dbf44c3f4,0x018d496adfe469a57596f015eebd869b7bed74083c573bb4b9d40a471e082517e5b744dac07eb67dac975bb8411766c6",
"0x0022395aab1038ade247f4b17deb81f4b00cabc04ad532fd3ac580ddbfcb44b3cb9d1d1976b09de603a0a228e713ae7d,0x01a366c20f9c2c1bc6b766e25856a85967a104d616680f4a79d97745c224fdadff08940f11ae0b26ea96f656f28b5e78"
]
},
{
"P": {
"x": "0x001346f07170e2ed45d08def787101795af173163239e7a1ee3297fd4e2b4fb6d76380058612e745a62a6fa6186744b7,0x00977c6b055e2b80e68afb986a05870294628464393619a2d92a698abcbc8927fe9729b4b72daac63e7f0c76ef711992",
"y": "0x016896c5571627fb322a371c57528f98131c51b1dc4ceb2be384610dc3f1a224236febd2c501bcea4d387a3c0c7b4e1c,0x007a86495cf20600a5d066b91a726df0b7d67f8758d7ed3fedb797d8772805c52eba9a7bd4661d37932f855b05f19892"
},
"Q0": {
"x": "0x00af89668bbc75ea1818bde76c0d126f516356b5b4da3f06603a0c4af5c68e44e8984ce185b756287b9aead31fc54c4c,0x0013b1d55b0cf613f54d056541daea78edc693750cb992564a9a7861e66f26b3cd4da71a30295dea0e40f0809847a030",
"y": "0x0127448b51269ac893ef00a585646b14371c0af69cafafaf3176e663f4e033b29a85e332116d8d9a3bfc8d1873730866,0x009a3aad06b68199b2e66fc1dafe20dcc5af8dd740be98fe7db529b424f098ae27759d7613f1942e9b1602664868c17b"
},
"Q1": {
"x": "0x009fc985f056445b2f6156a8021faff087f9b8d4690653346ca74b4420589fdbe511491fec0c535b52d521c1bb4be400,0x00f920679bd77a0d50d624513cf2296e4565f57dc3d7a578ddb19bfa60f05de1d5954ce247979fbc6501af72cd62e334",
"y": "0x0164c6cd007aba3e295df8310a2da71ef40022cec7a2e51dcab9f3850795ac823c7bb65082a88199d7c378b0ac4e9257,0x0028633591401d7da706fcb4a4da6f8999a7aff7b167bb96fd92511dca61f62f4b4e0be3213f0d68841a110b39c5a685"
},
"msg": "abc",
"u": [
"0x014a48b15756981016043ea1be11e30a728877c090f3beb8bd56cdadeb98792c0f47246c99c92c6a6d9b4f2ccef6d09f,0x01445002d867fb15a2d50311d23ace363b27befbe88d5feecababd66082e6b056d306f7f9dec8d3f4dfb1b2314963cec",
"0x001559a97f7639b2b5122e90b51a35c6714903b15cdab56bbe16eac4f8a0bd1514b412867f46f6948362c6f29d88c9fb,0x015556fa42d21cb9c6af6de63f6fbfcd6cae7c788e1b74c978f9c2ad1aae724912ff47bd4bab7d77c2af68b9c45b8c49"
]
},
{
"P": {
"x": "0x00dceaed928808d01aff4fc8c762d8cda12cc7ba1f6e721887606ee40ed0df1186f8cde71550636425de7b5ec0137fca,0x0166a7280c74d1bb3f0fd8c48aae30b855ba1a59a1dc309fb743f44b958ee721f1c273ee9ccc17e5ae931d566cf93671",
"y": "0x003125c58959ccbbca6e456a531833720d87dd039068ec1c4dbeab97230db643c71fb47e6be54eda3a470f452f3d6b1c,0x00d070fa5ebd18f6af02f65102b74cc379af99ab9d2b797a316c736bda39fb209bdaee9b59877cd0925c9d0949d91b0a"
},
"Q0": {
"x": "0x013c8c7d3aa93cb082f1b83edfd76a44a17aba8253a4b0a183b679b9e4d85e1e9653145b4947320187e99825d1846149,0x014e9afc495733168d15ebddd8d5177563e2b33a584a9993cef5536a1bba557590f37fc79651825cdf7bb6516ab54a88",
"y": "0x008a53b0d7d5a96b9fb7a15c60374028f1ab06c6545c69cfbb6ad7320e3933c64bb13b5139009ae7fb4dc0d29a1eacbd,0x0081a61008d4e7204c4a0268c1b4a369d142f4cfbfc8ee794d9653d89dc42d9b27e208ae0f11167d7eadfb56c7d4d1da"
},
"Q1": {
"x": "0x0062e543539c61cbfeb512fd1ec5f58bedec3ecc8bfec05de8043bfa92fec6fd7a671c9d3c9b0f86278ec6fbf4ae02a6,0x00f9402ce08a6d603d17d45dbaeda0babc9188a7837dba10c4aaad3e4dba9b5208b8df01d0635c30cb913ab16d9d23dc",
"y": "0x001c23bb7a1789b4afb3d896e497e8c9d5d4018721ac1303836265bd3d54e7eaa5f63ba45fa8e3776642fa27f049d792,0x00cd3bf5161c9ac44a3a490beb0e12c91de09706c4c86b369da263ee63560e84c30ba0ebd72536fa7f874539f2d590b1"
},
"msg": "abcdef0123456789",
"u": [
"0x014058fb0e66728eb352ca096e0ff6534512d1b8da4391b192da08e1d45d86064c92f01568889b13318cc3ad8144190a,0x004f706e3d9a2a46f32f2953cb7a305d092ffb332f085d6ff4ec063d24686c8917a9036e0699c7dcf48f884f1e47ab2e",
"0x00cf38b24a429230e04edbaf3b759aacfd37dc8dcc9b297b65b1b9705858f4d3bffee8b10324be05d7e4a18bcc4cd863,0x00c478b8e924194155ae97dd29ed2374cf8e207049e32bfb1519ead43702d49f22208ce12b058e7ff31ae7866f05959e"
]
},
{
"P": {
"x": "0x00cdb3038598c178025dbaf99dcd440d99c2b38d5b8041893d67002e7c6bab93beaff51439845d06c63f6ddd7c5c401e,0x011d2a48f51437628dd6508f6bbb306da621acadf14fbe9e8f47ddf1915beea1e4e3286319c172a32742d7faa45a5b7f",
"y": "0x00cac5a0278869557095a63c6a7203468a71d58ad123aaa82f72381cd94250c01479ea8cbe643a8341678679305bc01d,0x01a91041b5c1406e643b44d4564babe6f2bdf5fa3c1620419fb6cdb4ba294f1494a33fc829784cc14cbc8066c5310a87"
},
"Q0": {
"x": "0x012f22361e00eb23ffe9082f1b4bf4822553cd42c8367588e5329fa166efdcf09c53e0e0b5f06e2a610f42c6b278050c,0x01aade240952b9e4db24fd88e0b0552904b3cb8bab3e4cfbaf2a5c35da48127ef75d1348d76225e8fb896c62766902b5",
"y": "0x00f205ed12fd5bdeac9a95349e8383ab854dd59690992b6240357652246388e3224ddfa5ce06de195dfe4e9dc2c5a901,0x01203782b3fa65de7ab229eafae08b4ea9bae437e195491b03fab30ddce83881a0b940b33f0f3e7bd7feca2c76e139d6"
},
"Q1": {
"x": "0x0171cca78371628178ecc12072e263eda9725524b5de48e340ccc8514897834b81cf36466ef7e2473f88aca8830fd0c7,0x017273b33c0259339fac166bf927a66da0a6b40b751048a0093bb4e5d37c35f2a7318e393d4aaef61435ad4471603662",
"y": "0x008fe7352facf00e07a74b1315db5b308827577c53a950607fe25974039598f017ed7cc054c1d279dd4957a19435d16d,0x0083382ba5e521808254bf1e058dd663336bf591c564d15a0df71791c4124c2ab38baee90d1d4435f4d6c3967df0f9ef"
},
"msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
"u": [
"0x017afe7f987942b49e66831d61b785992f3172b2387f55e97863062e81734b0001bd64ed508d6721956741688dc9af0b,0x00631bcf5d854071890838210f50dfa1359da5ff4694255b7cd6ed630e4c6dfca746c69a9c5f3d76ee3cceae20bb355b",
"0x00b1fc859bd156b84a8b95d503db388a604c7a05ead79f8cd08cb21b677f3bd77143d8334ff51ddbc77ebf670b7839fa,0x00df8ed5ad61dced6490d9b58585fa3803f04f0b7d4efee366296339e634201c6f8924c8c3794c45685f49c6f974cf7e"
]
},
{
"P": {
"x": "0x00bc60ec05a3e54f000d07e4ef4d86c9f5bbc8d17aae021f547615a1c89a374bb47fdd25aa488ce8ad6e4b45483cf70f,0x00dac74d2a7d021f868b1ba53075fbb5d8b44fa709ba1b94d904d18cd79373bf23e277ca808bc70b64bd47fa877e81aa",
"y": "0x010dc70c8b009d9013768bef31ebf18db9ae405fbbdebf7cb8ced20d10ef633e66e3c2301e233e375e75c972f9dc11f1,0x0040e8b8abcd97f7bb841fb35655830456be9b0e931db9dbd40307ce7380b53351d22557ca29204b55eb7298cc3b1e0a"
},
"Q0": {
"x": "0x01891e447beb5b70294a6f5f7e0230faed4b3119353bf55ad2afa86cc266359350c07d1eb974389a67533c07f15d506b,0x0164482864c5fabe4716cc80bfd8776a8037d87dd141058737c5cf407aa39ec76b78564621637edb6c2ef6b8921d72c9",
"y": "0x003b6cffeb0e47c6bd294263d38fb8908707502415d850d06b524a61e1de100d8a768996c6cb8c8d67b8e88cd3dcb4d7,0x008ac2f1ea197c81aab704952b808f0cb418d63df22b39d5b88c000c40890200934e8695aac7345e3da11493d76c4231"
},
"Q1": {
"x": "0x00f507c2c5090a0e1d5c8e8db72e168c461cb99cbab2f9672934a3a2d92b81501553fce7bc3da3d53fc487dfe7512dd0,0x004d70e612013e7b66829a9d3e7d0f8a865fa3cddb794ce30e3b145d4287e4eca91977889f0a6a3837089c34c4ca035e",
"y": "0x0055eb01ee257e72fc09d0cb36162af8d98bbb9cad244715cfd63dc30e66ff452d6f4519c418654b4110eabcdf701f76,0x00a20ce3bdb4d1da6b8047caf4b7c2285265021dff3b1c1a760badef8d5b108aff67a13d964218711613330b3f0c3344"
},
"msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"u": [
"0x011c761e1ea0285445d16b6982d2c58b8ac14ac32dcecd59a76d652c86adacb8643fabc49f6340a9bbb85220ae3272db,0x00a340146d9af76164b2aac1026bb445b0f4a9d8d65725c2b26051c905b40146548056e0828590573efb151312ed97de",
"0x000edd1a63bc707aef87eed2bd7bf933247a697404d4ed1abebf8db4670cf14c9ebf6b138c642be96bc7fa9616284e7a,0x00521fae4b02b3a025c08bbeb2c4783786f82816b7f4c8d496f4715906a3b1085cd48d9d2b58588c138ae4757e220a91"
]
}
]
}

View File

@@ -0,0 +1,59 @@
use crate::{Bls12_377, G1Projective, G2Projective};
use ark_algebra_test_templates::*;
test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_377>; msm);
test_pairing!(pairing; crate::Bls12_377);
test_group!(g1_glv; G1Projective; glv);
test_group!(g2_glv; G2Projective; glv);
test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12377G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);
test_h2c!(g2_hc2; "./src/curves/tests"; "BLS12377G2"; crate::g2::Config; crate::Fq2; crate::Fq; 2);
#[cfg(test)]
mod test {
use ark_ec::{
hashing::{
curve_maps::wb::{WBConfig, WBMap},
map_to_curve_hasher::MapToCurveBasedHasher,
HashToCurve,
},
short_weierstrass::Projective,
};
use ark_ff::field_hashers::DefaultFieldHasher;
use ark_std::Zero;
/// make a simple hash
fn wb_hash_arbitrary_string_to_curve<WBCurve: WBConfig>() {
use sha2::Sha256;
let test_wb_to_curve_hasher = MapToCurveBasedHasher::<
Projective<WBCurve>,
DefaultFieldHasher<Sha256, 128>,
WBMap<WBCurve>,
>::new(&[1])
.unwrap();
let hash_result = test_wb_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve");
assert!(
hash_result.x != WBCurve::BaseField::zero()
&& hash_result.y != WBCurve::BaseField::zero(),
"we assume that not both a and b coefficienst are zero for the test curve"
);
assert!(
hash_result.is_on_curve(),
"hash results into a point off the curve"
);
}
#[test]
fn wb_hash_arbitrary_string_to_g1() {
wb_hash_arbitrary_string_to_curve::<crate::g1::Config>();
}
#[test]
fn wb_hash_arbitrary_string_to_g2() {
wb_hash_arbitrary_string_to_curve::<crate::g2::Config>();
}
}

View File

@@ -1,118 +1,7 @@
use ark_ff::{biginteger::BigInteger384 as BigInteger, fields::*};
use ark_ff::fields::{Fp384, MontBackend, MontConfig};
pub type Fq = Fp384<FqParameters>;
pub struct FqParameters;
impl Fp384Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 46u32;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
2022196864061697551u64,
17419102863309525423u64,
8564289679875062096u64,
17152078065055548215u64,
17966377291017729567u64,
68610905582439508u64,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0x8508c00000000001,
0x170b5d4430000000,
0x1ef3622fba094800,
0x1a22d9f300f5138f,
0xc63b05c06ca1493b,
0x1ae3a4617c510ea,
]);
const MODULUS_BITS: u32 = 377;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 7;
/// R = 85013442423176922659824578519796707547925331718418265885885478904210582549405549618995257669764901891699128663912
#[rustfmt::skip]
const R: BigInteger = BigInteger([
202099033278250856u64,
5854854902718660529u64,
11492539364873682930u64,
8885205928937022213u64,
5545221690922665192u64,
39800542322357402u64,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0xb786686c9400cd22,
0x329fcaab00431b1,
0x22a5f11162d6b46d,
0xbfdf7d03827dc3ac,
0x837e92f041790bf9,
0x6dfccb1e914b88,
]);
const INV: u64 = 9586122913090633727u64;
/// GENERATOR = -5
/// Encoded in Montgomery form, so the value here is
/// (-5 * R) % q = 92261639910053574722182574790803529333160366917737991650341130812388023949653897454961487930322210790384999596794
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
0xfc0b8000000002fa,
0x97d39cf6e000018b,
0x2072420fbfa05044,
0xcbbcbd50d97c3802,
0xbaf1ec35813f9eb,
0x9974a2c0945ad2,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x4284600000000000,
0xb85aea218000000,
0x8f79b117dd04a400,
0x8d116cf9807a89c7,
0x631d82e03650a49d,
0xd71d230be28875,
]);
// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
// For T coprime to 2
// T = (MODULUS - 1) // 2^S =
// 3675842578061421676390135839012792950148785745837396071634149488243117337281387659330802195819009059
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x7510c00000021423,
0x88bee82520005c2d,
0x67cc03d44e3c7bcd,
0x1701b28524ec688b,
0xe9185f1443ab18ec,
0x6b8,
]);
// (T - 1) // 2 =
// 1837921289030710838195067919506396475074392872918698035817074744121558668640693829665401097909504529
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xba88600000010a11,
0xc45f741290002e16,
0xb3e601ea271e3de6,
0xb80d94292763445,
0x748c2f8a21d58c76,
0x35c,
]);
}
#[allow(dead_code)]
pub const FQ_ONE: Fq = Fq::new(FqParameters::R);
#[allow(dead_code)]
pub const FQ_ZERO: Fq = Fq::new(BigInteger([0, 0, 0, 0, 0, 0]));
#[derive(MontConfig)]
#[modulus = "258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177"]
#[generator = "15"]
pub struct FqConfig;
pub type Fq = Fp384<MontBackend<FqConfig, 6>>;

View File

@@ -1,74 +1,74 @@
use super::*;
use ark_ff::{field_new, fields::*};
use ark_ff::{fields::*, MontFp};
pub type Fq12 = Fp12<Fq12Parameters>;
use crate::*;
pub type Fq12 = Fp12<Fq12Config>;
#[derive(Clone, Copy)]
pub struct Fq12Parameters;
pub struct Fq12Config;
impl Fp12Parameters for Fq12Parameters {
type Fp6Params = Fq6Parameters;
impl Fp12Config for Fq12Config {
type Fp6Config = Fq6Config;
const NONRESIDUE: Fq6 = field_new!(Fq6, FQ2_ZERO, FQ2_ONE, FQ2_ZERO);
const NONRESIDUE: Fq6 = Fq6::new(Fq2::ZERO, Fq2::ONE, Fq2::ZERO);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP12_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 6)
field_new!(Fq2, FQ_ONE, FQ_ZERO),
Fq2::new(Fq::ONE, Fq::ZERO),
// Fp2::NONRESIDUE^(((q^1) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "92949345220277864758624960506473182677953048909283248980960104381795901929519566951595905490535835115111760994353"),
FQ_ZERO,
Fq2::new(
MontFp!("92949345220277864758624960506473182677953048909283248980960104381795901929519566951595905490535835115111760994353"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946"),
FQ_ZERO,
Fq2::new(
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499"),
FQ_ZERO,
Fq2::new(
MontFp!("216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"),
FQ_ZERO,
Fq2::new(
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "123516416119946754630746545296132064952198520638002533875843642777304321125866014634106496325844844051843001220146"),
FQ_ZERO,
Fq2::new(
MontFp!("123516416119946754630746545296132064952198520638002533875843642777304321125866014634106496325844844051843001220146"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^6) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "-1"),
FQ_ZERO,
Fq2::new(
MontFp!("-1"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^7) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "165715080792691229252027773188420350858440463845631411558924158284924566418821255823372982649037525009328560463824"),
FQ_ZERO,
Fq2::new(
MontFp!("165715080792691229252027773188420350858440463845631411558924158284924566418821255823372982649037525009328560463824"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^8) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
FQ_ZERO,
Fq2::new(
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^9) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "42198664672744474621281227892288285906241943207628877683080515507620245292955241189266486323192680957485559243678"),
FQ_ZERO,
Fq2::new(
MontFp!("42198664672744474621281227892288285906241943207628877683080515507620245292955241189266486323192680957485559243678"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^10) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047232"),
FQ_ZERO,
Fq2::new(
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047232"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^11) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "135148009893022339379906188398761468584194992116912126664040619889416147222474808140862391813728516072597320238031"),
FQ_ZERO,
Fq2::new(
MontFp!("135148009893022339379906188398761468584194992116912126664040619889416147222474808140862391813728516072597320238031"),
Fq::ZERO,
),
];
}

View File

@@ -1,38 +1,51 @@
use super::*;
use ark_ff::{field_new, fields::*};
use ark_ff::{fields::*, MontFp};
pub type Fq2 = Fp2<Fq2Parameters>;
use crate::*;
pub struct Fq2Parameters;
pub type Fq2 = Fp2<Fq2Config>;
impl Fp2Parameters for Fq2Parameters {
pub struct Fq2Config;
impl Fp2Config for Fq2Config {
type Fp = Fq;
/// NONRESIDUE = -5
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, "-5");
/// QUADRATIC_NONRESIDUE = U
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE: (Fq, Fq) = (FQ_ZERO, FQ_ONE);
const NONRESIDUE: Fq = MontFp!("-5");
/// Coefficients for the Frobenius automorphism.
#[rustfmt::skip]
const FROBENIUS_COEFF_FP2_C1: &'static [Fq] = &[
// NONRESIDUE**(((q^0) - 1) / 2)
FQ_ONE,
Fq::ONE,
// NONRESIDUE**(((q^1) - 1) / 2)
field_new!(Fq, "-1"),
MontFp!("-1"),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
let original = fe;
let mut fe = -fe.double();
fe.double_in_place();
fe - original
}
fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
fe.neg_in_place();
*fe = *fe + fe.double_in_place().double_in_place();
fe
}
pub const FQ2_ZERO: Fq2 = field_new!(Fq2, FQ_ZERO, FQ_ZERO);
pub const FQ2_ONE: Fq2 = field_new!(Fq2, FQ_ONE, FQ_ZERO);
#[inline(always)]
fn sub_and_mul_fp_by_nonresidue(y: &mut Self::Fp, x: &Self::Fp) {
let mut original = *y;
original += x;
y.double_in_place().double_in_place();
*y += original;
}
#[inline(always)]
fn mul_fp_by_nonresidue_plus_one_and_add(y: &mut Self::Fp, x: &Self::Fp) {
y.double_in_place().double_in_place().neg_in_place();
*y += x;
}
fn mul_fp_by_nonresidue_and_add(y: &mut Self::Fp, x: &Self::Fp) {
let mut original = *y;
original.double_in_place().double_in_place();
original += &*y;
*y = *x;
*y -= original;
}
}

View File

@@ -1,78 +1,79 @@
use super::*;
use ark_ff::{field_new, fields::*};
use ark_ff::{fields::*, MontFp};
pub type Fq6 = Fp6<Fq6Parameters>;
use crate::*;
pub type Fq6 = Fp6<Fq6Config>;
#[derive(Clone, Copy)]
pub struct Fq6Parameters;
pub struct Fq6Config;
impl Fp6Parameters for Fq6Parameters {
type Fp2Params = Fq2Parameters;
impl Fp6Config for Fq6Config {
type Fp2Config = Fq2Config;
/// NONRESIDUE = U
#[rustfmt::skip]
const NONRESIDUE: Fq2 = field_new!(Fq2, FQ_ZERO, FQ_ONE);
const NONRESIDUE: Fq2 = Fq2::new(Fq::ZERO, Fq::ONE);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 3)
field_new!(Fq2, FQ_ONE, FQ_ZERO),
Fq2::new(Fq::ONE, Fq::ZERO),
// Fp2::NONRESIDUE^(((q^1) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946"),
FQ_ZERO,
Fq2::new(
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"),
FQ_ZERO,
Fq2::new(
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 3)
field_new!(Fq2, field_new!(Fq, "-1"), FQ_ZERO),
Fq2::new(MontFp!("-1"), Fq::ZERO),
// Fp2::NONRESIDUE^(((q^4) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
FQ_ZERO,
Fq2::new(
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047232"),
FQ_ZERO,
Fq2::new(
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047232"),
Fq::ZERO,
),
];
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C2: &'static [Fq2] = &[
// Fp2::NONRESIDUE^((2*(q^0) - 2) / 3)
field_new!(Fq2, FQ_ONE, FQ_ZERO),
Fq2::new(Fq::ONE, Fq::ZERO),
// Fp2::NONRESIDUE^((2*(q^1) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"),
FQ_ZERO
Fq2::new(
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"),
Fq::ZERO
),
// Fp2::NONRESIDUE^((2*(q^2) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
FQ_ZERO,
Fq2::new(
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^((2*(q^3) - 2) / 3)
field_new!(Fq2, FQ_ONE, FQ_ZERO),
Fq2::new(Fq::ONE, Fq::ZERO),
// Fp2::NONRESIDUE^((2*(q^4) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"),
FQ_ZERO,
Fq2::new(
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^((2*(q^5) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
FQ_ZERO,
Fq2::new(
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231"),
Fq::ZERO,
),
];
#[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
fn mul_fp2_by_nonresidue_in_place(fe: &mut Fq2) -> &mut Fq2 {
// Karatsuba multiplication with constant other = u.
let c0 = Fq2Parameters::mul_fp_by_nonresidue(&fe.c1);
let c1 = fe.c0;
field_new!(Fq2, c0, c1)
let old_c0 = fe.c0;
fe.c0 = fe.c1;
Fq2Config::mul_fp_by_nonresidue_in_place(&mut fe.c0);
fe.c1 = old_c0;
fe
}
}

View File

@@ -1,99 +1,27 @@
use ark_ff::{biginteger::BigInteger256 as BigInteger, fields::*};
//! Bls12-377 scalar field.
/// Roots of unity computed from modulus and R using this sage code:
///
/// ```ignore
/// q = 8444461749428370424248824938781546531375899335154063827935233455917409239041
/// R = 6014086494747379908336260804527802945383293308637734276299549080986809532403 # Montgomery R
/// s = 47
/// o = q - 1
/// F = GF(q)
/// g = F.multiplicative_generator()
/// g = F.multiplicative_generator()
/// assert g.multiplicative_order() == o
/// g2 = g ** (o/2**s)
/// assert g2.multiplicative_order() == 2**s
/// def into_chunks(val, width, n):
/// return [int(int(val) // (2 ** (width * i)) % 2 ** width) for i in range(n)]
/// print("Gen: ", g * R % q)
/// print("Gen: ", into_chunks(g * R % q, 64, 4))
/// print("2-adic gen: ", into_chunks(g2 * R % q, 64, 4))
/// ```
use ark_ff::fields::{Fp256, MontBackend, MontConfig};
pub type Fr = Fp256<FrParameters>;
pub struct FrParameters;
impl Fp256Parameters for FrParameters {}
impl FftParameters for FrParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 47;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
0x3c3d3ca739381fb2,
0x9a14cda3ec99772b,
0xd7aacc7c59724826,
0xd1ba211c5cc349c,
]);
}
impl FpParameters for FrParameters {
/// MODULUS = 8444461749428370424248824938781546531375899335154063827935233455917409239041
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
725501752471715841u64,
6461107452199829505u64,
6968279316240510977u64,
1345280370688173398u64,
]);
const MODULUS_BITS: u32 = 253;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 3;
/// R = 6014086494747379908336260804527802945383293308637734276299549080986809532403
#[rustfmt::skip]
const R: BigInteger = BigInteger([
9015221291577245683u64,
8239323489949974514u64,
1646089257421115374u64,
958099254763297437u64,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
2726216793283724667u64,
14712177743343147295u64,
12091039717619697043u64,
81024008013859129u64,
]);
const INV: u64 = 725501752471715839u64;
/// GENERATOR = 11
/// Encoded in Montgomery form, so the value is
/// (11 * R) % q = 7043719196222586021957094278335006679584931048936630243748405699433040183146
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
1855201571499933546u64,
8511318076631809892u64,
6222514765367795509u64,
1122129207579058019u64,
]);
/// (r - 1)/2 =
/// 4222230874714185212124412469390773265687949667577031913967616727958704619520
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x8508c00000000000,
0xacd53b7f68000000,
0x305a268f2e1bd800,
0x955b2af4d1652ab,
]);
// T and T_MINUS_ONE_DIV_TWO, where r - 1 = 2^s * t
// For T coprime to 2
/// t = (r - 1) / 2^s =
/// 60001509534603559531609739528203892656505753216962260608619555
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0xedfda00000021423,
0x9a3cb86f6002b354,
0xcabd34594aacc168,
0x2556,
]);
/// (t - 1) / 2 =
/// 30000754767301779765804869764101946328252876608481130304309777
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x76fed00000010a11,
0x4d1e5c37b00159aa,
0x655e9a2ca55660b4,
0x12ab,
]);
}
#[derive(MontConfig)]
#[modulus = "8444461749428370424248824938781546531375899335154063827935233455917409239041"]
#[generator = "22"]
pub struct FrConfig;
pub type Fr = Fp256<MontBackend<FrConfig, 4>>;

View File

@@ -1,128 +1,52 @@
use ark_algebra_test_templates::*;
use ark_ff::{
biginteger::{BigInteger, BigInteger384},
fields::{
fp6_3over2::Fp6Parameters, FftField, FftParameters, Field, Fp2Parameters, FpParameters,
PrimeField, SquareRootField,
},
One, UniformRand, Zero,
biginteger::{BigInt, BigInteger, BigInteger384},
fields::{FftField, Field, Fp6Config, PrimeField},
Fp384, One, UniformRand, Zero,
};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use ark_std::rand::Rng;
use ark_std::test_rng;
use core::{
use ark_std::{
cmp::Ordering,
ops::{AddAssign, MulAssign, SubAssign},
ops::{AddAssign, MulAssign},
test_rng,
};
use crate::{Fq, Fq12, Fq2, Fq2Parameters, Fq6, Fq6Parameters, FqParameters, Fr};
use crate::{Fq, Fq12, Fq2, Fq6, Fq6Config, Fr};
use ark_algebra_test_templates::fields::*;
pub(crate) const ITERATIONS: usize = 5;
#[test]
fn test_fr() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fr = rng.gen();
let b: Fr = rng.gen();
field_test(a, b);
primefield_test::<Fr>();
sqrt_field_test(b);
let byte_size = a.serialized_size();
field_serialization_test::<Fr>(byte_size);
}
}
#[test]
fn test_fq() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq = rng.gen();
let b: Fq = rng.gen();
field_test(a, b);
primefield_test::<Fq>();
sqrt_field_test(a);
let byte_size = a.serialized_size();
let (_, buffer_size) = buffer_bit_byte_size(Fq::size_in_bits());
assert_eq!(byte_size, buffer_size);
field_serialization_test::<Fq>(byte_size);
}
}
#[test]
fn test_fq2() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq2 = rng.gen();
let b: Fq2 = rng.gen();
field_test(a, b);
sqrt_field_test(a);
}
frobenius_test::<Fq2, _>(Fq::characteristic(), 13);
let byte_size = Fq2::zero().serialized_size();
field_serialization_test::<Fq2>(byte_size);
}
#[test]
fn test_fq6() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq6 = rng.gen();
let h: Fq6 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq6, _>(Fq::characteristic(), 13);
let byte_size = Fq6::zero().serialized_size();
field_serialization_test::<Fq6>(byte_size);
}
#[test]
fn test_fq12() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq12 = rng.gen();
let h: Fq12 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq12, _>(Fq::characteristic(), 13);
let byte_size = Fq12::zero().serialized_size();
field_serialization_test::<Fq12>(byte_size);
}
test_field!(fr; Fr; mont_prime_field);
test_field!(fq; Fq; mont_prime_field);
test_field!(fq2; Fq2);
test_field!(fq6; Fq6);
test_field!(fq12; Fq12);
#[test]
fn test_fq_repr_from() {
assert_eq!(
BigInteger384::from(100),
BigInteger384([100, 0, 0, 0, 0, 0])
);
assert_eq!(BigInt::from(100u64), BigInt::new([100, 0, 0, 0, 0, 0]));
}
#[test]
fn test_fq_repr_is_odd() {
assert!(!BigInteger384::from(0).is_odd());
assert!(BigInteger384::from(0).is_even());
assert!(BigInteger384::from(1).is_odd());
assert!(!BigInteger384::from(1).is_even());
assert!(!BigInteger384::from(324834872).is_odd());
assert!(BigInteger384::from(324834872).is_even());
assert!(BigInteger384::from(324834873).is_odd());
assert!(!BigInteger384::from(324834873).is_even());
assert!(!BigInteger384::from(0u64).is_odd());
assert!(BigInteger384::from(0u64).is_even());
assert!(BigInteger384::from(1u64).is_odd());
assert!(!BigInteger384::from(1u64).is_even());
assert!(!BigInteger384::from(324834872u64).is_odd());
assert!(BigInteger384::from(324834872u64).is_even());
assert!(BigInteger384::from(324834873u64).is_odd());
assert!(!BigInteger384::from(324834873u64).is_even());
}
#[test]
fn test_fq_repr_is_zero() {
assert!(BigInteger384::from(0).is_zero());
assert!(!BigInteger384::from(1).is_zero());
assert!(!BigInteger384([0, 0, 0, 0, 1, 0]).is_zero());
assert!(BigInteger384::from(0u64).is_zero());
assert!(!BigInteger384::from(1u64).is_zero());
assert!(!BigInt::new([0, 0, 0, 0, 1, 0]).is_zero());
}
#[test]
fn test_fq_repr_num_bits() {
let mut a = BigInteger384::from(0);
let mut a = BigInteger384::from(0u64);
assert_eq!(0, a.num_bits());
a = BigInteger384::from(1);
a = BigInteger384::from(1u64);
for i in 1..385 {
assert_eq!(i, a.num_bits());
a.mul2();
@@ -130,229 +54,16 @@ fn test_fq_repr_num_bits() {
assert_eq!(0, a.num_bits());
}
#[test]
fn test_fq_add_assign() {
// Test associativity
let mut rng = test_rng();
for _ in 0..1000 {
// Generate a, b, c and ensure (a + b) + c == a + (b + c).
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
let mut tmp2 = b;
tmp2.add_assign(&c);
tmp2.add_assign(&a);
assert_eq!(tmp1, tmp2);
}
}
#[test]
fn test_fq_sub_assign() {
let mut rng = test_rng();
for _ in 0..1000 {
// Ensure that (a - b) + (b - a) = 0.
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.sub_assign(&b);
let mut tmp2 = b;
tmp2.sub_assign(&a);
tmp1.add_assign(&tmp2);
assert!(tmp1.is_zero());
}
}
#[test]
fn test_fq_mul_assign() {
let mut rng = test_rng();
for _ in 0..1000000 {
// Ensure that (a * b) * c = a * (b * c)
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.mul_assign(&b);
tmp1.mul_assign(&c);
let mut tmp2 = b;
tmp2.mul_assign(&c);
tmp2.mul_assign(&a);
assert_eq!(tmp1, tmp2);
}
for _ in 0..1000000 {
// Ensure that r * (a + b + c) = r*a + r*b + r*c
let r = Fq::rand(&mut rng);
let mut a = Fq::rand(&mut rng);
let mut b = Fq::rand(&mut rng);
let mut c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
tmp1.mul_assign(&r);
a.mul_assign(&r);
b.mul_assign(&r);
c.mul_assign(&r);
a.add_assign(&b);
a.add_assign(&c);
assert_eq!(tmp1, a);
}
}
#[test]
fn test_fq_squaring() {
let mut rng = test_rng();
for _ in 0..1000000 {
// Ensure that (a * a) = a^2
let a = Fq::rand(&mut rng);
let mut tmp = a;
tmp.square_in_place();
let mut tmp2 = a;
tmp2.mul_assign(&a);
assert_eq!(tmp, tmp2);
}
}
#[test]
fn test_fq_inverse() {
assert!(Fq::zero().inverse().is_none());
let mut rng = test_rng();
let one = Fq::one();
for _ in 0..1000 {
// Ensure that a * a^-1 = 1
let mut a = Fq::rand(&mut rng);
let ainv = a.inverse().unwrap();
a.mul_assign(&ainv);
assert_eq!(a, one);
}
}
#[test]
fn test_fq_double_in_place() {
let mut rng = test_rng();
for _ in 0..1000 {
// Ensure doubling a is equivalent to adding a to itself.
let mut a = Fq::rand(&mut rng);
let mut b = a;
b.add_assign(&a);
a.double_in_place();
assert_eq!(a, b);
}
}
#[test]
fn test_fq_negate() {
{
let a = -Fq::zero();
assert!(a.is_zero());
}
let mut rng = test_rng();
for _ in 0..1000 {
// Ensure (a - (-a)) = 0.
let mut a = Fq::rand(&mut rng);
let b = -a;
a.add_assign(&b);
assert!(a.is_zero());
}
}
#[test]
fn test_fq_pow() {
let mut rng = test_rng();
for i in 0..1000 {
// Exponentiate by various small numbers and ensure it consists with repeated
// multiplication.
let a = Fq::rand(&mut rng);
let target = a.pow(&[i]);
let mut c = Fq::one();
for _ in 0..i {
c.mul_assign(&a);
}
assert_eq!(c, target);
}
for _ in 0..1000 {
// Exponentiating by the modulus should have no effect in a prime field.
let a = Fq::rand(&mut rng);
assert_eq!(a, a.pow(Fq::characteristic()));
}
}
#[test]
fn test_fq_sqrt() {
let mut rng = test_rng();
assert_eq!(Fq::zero().sqrt().unwrap(), Fq::zero());
for _ in 0..1000 {
// Ensure sqrt(a^2) = a or -a
let a = Fq::rand(&mut rng);
let nega = -a;
let mut b = a;
b.square_in_place();
let b = b.sqrt().unwrap();
assert!(a == b || nega == b);
}
for _ in 0..1000 {
// Ensure sqrt(a)^2 = a for random a
let a = Fq::rand(&mut rng);
if let Some(mut tmp) = a.sqrt() {
tmp.square_in_place();
assert_eq!(a, tmp);
}
}
}
#[test]
fn test_fq_num_bits() {
assert_eq!(FqParameters::MODULUS_BITS, 377);
assert_eq!(FqParameters::CAPACITY, 376);
assert_eq!(Fq::MODULUS_BIT_SIZE, 377);
}
#[test]
fn test_fq_root_of_unity() {
assert_eq!(FqParameters::TWO_ADICITY, 46);
assert_eq!(Fq::TWO_ADICITY, 46);
assert_eq!(
Fq::multiplicative_generator().pow([
Fq::GENERATOR.pow([
0x7510c00000021423,
0x88bee82520005c2d,
0x67cc03d44e3c7bcd,
@@ -360,21 +71,21 @@ fn test_fq_root_of_unity() {
0xe9185f1443ab18ec,
0x6b8
]),
Fq::two_adic_root_of_unity()
Fq::TWO_ADIC_ROOT_OF_UNITY
);
assert_eq!(
Fq::two_adic_root_of_unity().pow([1 << FqParameters::TWO_ADICITY]),
Fq::TWO_ADIC_ROOT_OF_UNITY.pow([1 << Fq::TWO_ADICITY]),
Fq::one()
);
assert!(Fq::multiplicative_generator().sqrt().is_none());
assert!(Fq::GENERATOR.sqrt().is_none());
}
#[test]
fn test_fq_ordering() {
// BigInteger384's ordering is well-tested, but we still need to make sure the
// Fq elements aren't being compared in Montgomery form.
for i in 0..100 {
assert!(Fq::from(BigInteger384::from(i + 1)) > Fq::from(BigInteger384::from(i)));
for i in 0..100u64 {
assert!(Fq::from(Fp384::from(i + 1)) > Fq::from(Fp384::from(i)));
}
}
@@ -384,14 +95,8 @@ fn test_fq_legendre() {
assert_eq!(QuadraticResidue, Fq::one().legendre());
assert_eq!(Zero, Fq::zero().legendre());
assert_eq!(
QuadraticResidue,
Fq::from(BigInteger384::from(4)).legendre()
);
assert_eq!(
QuadraticNonResidue,
Fq::from(BigInteger384::from(5)).legendre()
);
assert_eq!(QuadraticResidue, Fq::from(Fp384::from(4u64)).legendre());
assert_eq!(QuadraticNonResidue, Fq::from(Fp384::from(5u64)).legendre());
}
#[test]
@@ -431,30 +136,10 @@ fn test_fq2_legendre() {
// i^2 = -1
let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Parameters::mul_fp2_by_nonresidue(&m1);
Fq6Config::mul_fp2_by_nonresidue_in_place(&mut m1);
assert_eq!(QuadraticNonResidue, m1.legendre());
}
#[test]
fn test_fq2_mul_nonresidue() {
let mut rng = test_rng();
let nqr = Fq2::new(Fq::zero(), Fq::one());
let quadratic_non_residue = Fq2::new(
Fq2Parameters::QUADRATIC_NONRESIDUE.0,
Fq2Parameters::QUADRATIC_NONRESIDUE.1,
);
for _ in 0..1000 {
let mut a = Fq2::rand(&mut rng);
let mut b = a;
a = quadratic_non_residue * &a;
b.mul_assign(&nqr);
assert_eq!(a, b);
}
}
#[test]
fn test_fq6_mul_by_1() {
let mut rng = test_rng();

12
bls12_377/src/lib.rs Normal file → Executable file
View File

@@ -9,15 +9,17 @@
#![forbid(unsafe_code)]
//! This library implements the BLS12_377 curve generated in [\[BCGMMW20, “Zexe”\]](https://eprint.iacr.org/2018/962).
//! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree 12,
//! defined over a 377-bit (prime) field. The main feature of this curve is that
//! both the scalar field and the base field are highly 2-adic.
//! (This is in contrast to the BLS12_381 curve for which only the scalar field is highly 2-adic.)
//! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree
//! 12, defined over a 377-bit (prime) field. The main feature of this curve is
//! that both the scalar field and the base field are highly 2-adic.
//! (This is in contrast to the BLS12_381 curve for which only the scalar field
//! is highly 2-adic.)
//!
//!
//! Curve information:
//! * Base field: q = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
//! * Scalar field: r = 8444461749428370424248824938781546531375899335154063827935233455917409239041
//! * Scalar field: r =
//! 8444461749428370424248824938781546531375899335154063827935233455917409239041
//! * valuation(q - 1, 2) = 46
//! * valuation(r - 1, 2) = 47
//! * G1 curve equation: y^2 = x^3 + 1

View File

@@ -1,25 +1,27 @@
[package]
name = "ark-bls12-381"
version = "0.1.0"
version = "0.4.0"
authors = [ "arkworks contributors" ]
description = "The BLS12-381 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/algebra"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/ark-bls12-381/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
edition = "2021"
[dependencies]
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
ark-ff = { version= "0.4.0", default-features = false }
ark-ec = { version= "0.4.0" }
ark-std = { version = "0.4.0", default-features = false }
ark-serialize = { version = "0.4.0", default-features = false }
[dev-dependencies]
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-algebra-test-templates = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-algebra-test-templates = { version = "0.4.0", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0", default-features = false }
hex = "^0.4.0"
[features]
default = [ "curve" ]
@@ -27,3 +29,8 @@ std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
curve = [ "scalar_field" ]
scalar_field = []
[[bench]]
name = "bls12_381"
path = "benches/bls12_381.rs"
harness = false

View File

@@ -0,0 +1,15 @@
use ark_algebra_bench_templates::*;
use ark_bls12_381::{
fq::Fq, fq2::Fq2, fr::Fr, Bls12_381, Fq12, G1Projective as G1, G2Projective as G2,
};
bench!(
Name = "Bls12_381",
Pairing = Bls12_381,
G1 = G1,
G2 = G2,
ScalarField = Fr,
G1BaseField = Fq,
G2BaseField = Fq2,
TargetField = Fq12,
);

View File

@@ -0,0 +1,28 @@
modulus = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -0,0 +1,28 @@
modulus = 52435875175126190479447740508185965837690552500527637822603658699938581184513
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -1,53 +1,294 @@
use crate::*;
use ark_ec::{
bls12,
models::{ModelParameters, SWModelParameters},
bls12::Bls12Config,
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
models::CurveConfig,
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, SWCurveConfig},
AffineRepr, PrimeGroup,
};
use ark_ff::{field_new, Zero};
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField, Zero};
use ark_serialize::{Compress, SerializationError};
use ark_std::{ops::Neg, One};
pub type G1Affine = bls12::G1Affine<crate::Parameters>;
pub type G1Projective = bls12::G1Projective<crate::Parameters>;
use super::g1_swu_iso;
use crate::{
util::{
read_g1_compressed, read_g1_uncompressed, serialize_fq, EncodingFlags, G1_SERIALIZED_SIZE,
},
Fq, Fr,
};
pub type G1Affine = bls12::G1Affine<crate::Config>;
pub type G1Projective = bls12::G1Projective<crate::Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
pub struct Config;
impl ModelParameters for Parameters {
impl CurveConfig for Config {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
const COEFF_A: Fq = field_new!(Fq, "0");
/// COEFF_B = 4
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, "4");
/// COFACTOR = (x - 1)^2 / 3 = 76329603384216526031706109802092473003
const COFACTOR: &'static [u64] = &[0x8c00aaab0000aaab, 0x396c8c005555e156];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 52435875175126190458656871551744051925719901746859129887267498875565241663483
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, "52435875175126190458656871551744051925719901746859129887267498875565241663483");
const COFACTOR_INV: Fr =
MontFp!("52435875175126190458656871551744051925719901746859129887267498875565241663483");
}
impl SWCurveConfig for Config {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = 4
const COEFF_B: Fq = MontFp!("4");
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
#[inline]
fn mul_projective(p: &G1Projective, scalar: &[u64]) -> G1Projective {
let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
GLVConfig::glv_mul_projective(*p, s)
}
#[inline]
fn is_in_correct_subgroup_assuming_on_curve(p: &G1Affine) -> bool {
// Algorithm from Section 6 of https://eprint.iacr.org/2021/1130.
//
// Check that endomorphism_p(P) == -[X^2]P
// An early-out optimization described in Section 6.
// If uP == P but P != point of infinity, then the point is not in the right
// subgroup.
let x_times_p = p.mul_bigint(crate::Config::X);
if x_times_p.eq(p) && !p.infinity {
return false;
}
let minus_x_squared_times_p = x_times_p.mul_bigint(crate::Config::X).neg();
let endomorphism_p = endomorphism(p);
minus_x_squared_times_p.eq(&endomorphism_p)
}
#[inline]
fn clear_cofactor(p: &G1Affine) -> G1Affine {
// Using the effective cofactor, as explained in
// Section 5 of https://eprint.iacr.org/2019/403.pdf.
//
// It is enough to multiply by (1 - x), instead of (x - 1)^2 / 3
let h_eff = one_minus_x().into_bigint();
Config::mul_affine(&p, h_eff.as_ref()).into()
}
fn deserialize_with_mode<R: ark_serialize::Read>(
mut reader: R,
compress: ark_serialize::Compress,
validate: ark_serialize::Validate,
) -> Result<Affine<Self>, ark_serialize::SerializationError> {
let p = if compress == ark_serialize::Compress::Yes {
read_g1_compressed(&mut reader)?
} else {
read_g1_uncompressed(&mut reader)?
};
if validate == ark_serialize::Validate::Yes && !p.is_in_correct_subgroup_assuming_on_curve()
{
return Err(SerializationError::InvalidData);
}
Ok(p)
}
fn serialize_with_mode<W: ark_serialize::Write>(
item: &Affine<Self>,
mut writer: W,
compress: ark_serialize::Compress,
) -> Result<(), SerializationError> {
let encoding = EncodingFlags {
is_compressed: compress == ark_serialize::Compress::Yes,
is_infinity: item.is_zero(),
is_lexographically_largest: item.y > -item.y,
};
let mut p = *item;
if encoding.is_infinity {
p = G1Affine::zero();
}
// need to access the field struct `x` directly, otherwise we get None from xy()
// method
let x_bytes = serialize_fq(p.x);
if encoding.is_compressed {
let mut bytes: [u8; G1_SERIALIZED_SIZE] = x_bytes;
encoding.encode_flags(&mut bytes);
writer.write_all(&bytes)?;
} else {
let mut bytes = [0u8; 2 * G1_SERIALIZED_SIZE];
bytes[0..G1_SERIALIZED_SIZE].copy_from_slice(&x_bytes[..]);
bytes[G1_SERIALIZED_SIZE..].copy_from_slice(&serialize_fq(p.y)[..]);
encoding.encode_flags(&mut bytes);
writer.write_all(&bytes)?;
};
Ok(())
}
fn serialized_size(compress: Compress) -> usize {
if compress == Compress::Yes {
G1_SERIALIZED_SIZE
} else {
G1_SERIALIZED_SIZE * 2
}
}
}
impl GLVConfig for Config {
const ENDO_COEFFS: &'static[Self::BaseField] = &[
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350")
];
const LAMBDA: Self::ScalarField =
MontFp!("52435875175126190479447740508185965837461563690374988244538805122978187051009");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(true, BigInt!("228988810152649578064853576960394133504")),
(true, BigInt!("1")),
(false, BigInt!("1")),
(true, BigInt!("228988810152649578064853576960394133503")),
];
fn endomorphism(p: &G1Projective) -> G1Projective {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
fn one_minus_x() -> Fr {
const X: Fr = Fr::from_sign_and_limbs(!crate::Config::X_IS_NEGATIVE, crate::Config::X);
Fr::one() - X
}
// Parameters from the [IETF draft v16, section E.2](https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-11-isogeny-map-for-bls12-381).
impl WBConfig for Config {
type IsogenousCurve = g1_swu_iso::SwuIsoConfig;
const ISOGENY_MAP: IsogenyMap<'static, Self::IsogenousCurve, Self> =
g1_swu_iso::ISOGENY_MAP_TO_G1;
}
/// G1_GENERATOR_X =
/// 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
#[rustfmt::skip]
pub const G1_GENERATOR_X: Fq = field_new!(Fq, "3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507");
pub const G1_GENERATOR_X: Fq = MontFp!("3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507");
/// G1_GENERATOR_Y =
/// 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
#[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, "1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569");
pub const G1_GENERATOR_Y: Fq = MontFp!("1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569");
/// BETA is a non-trivial cubic root of unity in Fq.
pub const BETA: Fq = MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350");
pub fn endomorphism(p: &Affine<Config>) -> Affine<Config> {
// Endomorphism of the points on the curve.
// endomorphism_p(x,y) = (BETA * x, y)
// where BETA is a non-trivial cubic root of unity in Fq.
let mut res = (*p).clone();
res.x *= BETA;
res
}
#[cfg(test)]
mod test {
use super::*;
use crate::g1;
use ark_serialize::CanonicalDeserialize;
use ark_std::{rand::Rng, UniformRand};
fn sample_unchecked() -> Affine<g1::Config> {
let mut rng = ark_std::test_rng();
loop {
let x = Fq::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = Affine::get_point_from_x_unchecked(x, greatest) {
return p;
}
}
}
#[test]
fn test_cofactor_clearing() {
const SAMPLES: usize = 100;
for _ in 0..SAMPLES {
let p: Affine<g1::Config> = sample_unchecked();
let p = p.clear_cofactor();
assert!(p.is_on_curve());
assert!(p.is_in_correct_subgroup_assuming_on_curve());
}
}
#[test]
fn non_canonical_identity_point() {
let non_canonical_hex = "c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
let non_canonical_bytes = hex::decode(non_canonical_hex).unwrap();
assert_eq!(non_canonical_bytes.len(), 48);
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
CanonicalDeserialize::deserialize_compressed(&non_canonical_bytes[..]);
assert!(maybe_affine_point.is_err());
let non_canonical_hex_uncompressed = "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
let non_canonical_bytes = hex::decode(non_canonical_hex_uncompressed).unwrap();
assert_eq!(non_canonical_bytes.len(), 96);
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
CanonicalDeserialize::deserialize_uncompressed(&non_canonical_bytes[..]);
assert!(maybe_affine_point.is_err())
}
#[test]
fn bad_flag_combination() {
// See https://github.com/zkcrypto/pairing/tree/fa8103764a07bd273927447d434de18aace252d3/src/bls12_381#serialization
// - Bit 1 is compressed/uncompressed
// - Bit 2 is infinity
// - Bit 3 is lexicographical order for compressed point deserialization
// Hence `0b1110` ("e" in hex) or `0b0110` ("6" in hex") are both nonsensical.
// uncompressed, but lexicographically largest flag is set
let non_canonical_hex = "600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
let non_canonical_bytes = hex::decode(non_canonical_hex).unwrap();
assert_eq!(non_canonical_bytes.len(), 48);
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
CanonicalDeserialize::deserialize_compressed(&non_canonical_bytes[..]);
assert!(maybe_affine_point.is_err());
// compressed, but infinity flag is set and lexicographically largest flag is
// set
let non_canonical_hex_2 = "e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
let non_canonical_bytes = hex::decode(non_canonical_hex_2).unwrap();
assert_eq!(non_canonical_bytes.len(), 48);
let maybe_affine_point: Result<G1Affine, ark_serialize::SerializationError> =
CanonicalDeserialize::deserialize_compressed(&non_canonical_bytes[..]);
assert!(maybe_affine_point.is_err());
}
}

View File

@@ -0,0 +1,140 @@
use crate::{g1, Fq, Fr};
use ark_ec::{
hashing::curve_maps::{swu::SWUConfig, wb::IsogenyMap},
models::{
short_weierstrass::{Affine, SWCurveConfig},
CurveConfig,
},
};
use ark_ff::MontFp;
type G1Affine = Affine<SwuIsoConfig>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct SwuIsoConfig;
impl CurveConfig for SwuIsoConfig {
type BaseField = Fq;
type ScalarField = Fr;
/// COFACTOR = (x - 1)^2 / 3 = 76329603384216526031706109802092473003
const COFACTOR: &'static [u64] = &[0x8c00aaab0000aaab, 0x396c8c005555e156];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// = 52435875175126190458656871551744051925719901746859129887267498875565241663483
const COFACTOR_INV: Fr =
MontFp!("52435875175126190458656871551744051925719901746859129887267498875565241663483");
}
// https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/
// Hashing to Elliptic Curves
// 8.8.1. BLS12-381 G1
// BLS12381G1_XMD:SHA-256_SSWU_RO_ is defined as follows:
// * E': y'^2 = x'^3 + A' * x' + B', where
// - A' = 0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d
// - B' = 0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0
// - A' = 12190336318893619529228877361869031420615612348429846051986726275283378313155663745811710833465465981901188123677
// - B' = 2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280
// * Z: 11
impl SWCurveConfig for SwuIsoConfig {
const COEFF_A: Fq = MontFp!("12190336318893619529228877361869031420615612348429846051986726275283378313155663745811710833465465981901188123677");
#[rustfmt::skip]
const COEFF_B: Fq = MontFp!("2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280");
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
}
/// Lexicographically smallest, valid x-coordinate of a point P on the curve
/// (with its corresponding y) multiplied by the cofactor. P_x = 2
/// P_y = 658522096176515125667361255350269797307718222519385801637008089782287711363858559738763090642304321670226247205569
/// P = E(P_x, P_y)
/// G = P * COFACTOR
const G1_GENERATOR_X: Fq = MontFp!("1677416608493238977774703213729589714082762656433187746258164626835771660734158898989765932111853529350617333597651");
const G1_GENERATOR_Y: Fq = MontFp!("1405098061573104639413728190240719229571583960971553962991897960445246185035342568402755187331334546673157015627211");
impl SWUConfig for SwuIsoConfig {
// ZETA = 0xb as per the IETF draft.
const ZETA: Fq = MontFp!("11");
}
pub const ISOGENY_MAP_TO_G1 : IsogenyMap<'_, SwuIsoConfig, g1::Config, > = IsogenyMap {
x_map_numerator : &[
MontFp!("2712959285290305970661081772124144179193819192423276218370281158706191519995889425075952244140278856085036081760695"),
MontFp!("3564859427549639835253027846704205725951033235539816243131874237388832081954622352624080767121604606753339903542203"),
MontFp!("2051387046688339481714726479723076305756384619135044672831882917686431912682625619320120082313093891743187631791280"),
MontFp!("3612713941521031012780325893181011392520079402153354595775735142359240110423346445050803899623018402874731133626465"),
MontFp!("2247053637822768981792833880270996398470828564809439728372634811976089874056583714987807553397615562273407692740057"),
MontFp!("3415427104483187489859740871640064348492611444552862448295571438270821994900526625562705192993481400731539293415811"),
MontFp!("2067521456483432583860405634125513059912765526223015704616050604591207046392807563217109432457129564962571408764292"),
MontFp!("3650721292069012982822225637849018828271936405382082649291891245623305084633066170122780668657208923883092359301262"),
MontFp!("1239271775787030039269460763652455868148971086016832054354147730155061349388626624328773377658494412538595239256855"),
MontFp!("3479374185711034293956731583912244564891370843071137483962415222733470401948838363051960066766720884717833231600798"),
MontFp!("2492756312273161536685660027440158956721981129429869601638362407515627529461742974364729223659746272460004902959995"),
MontFp!("1058488477413994682556770863004536636444795456512795473806825292198091015005841418695586811009326456605062948114985"),
],
x_map_denominator : &[
MontFp!("1353092447850172218905095041059784486169131709710991428415161466575141675351394082965234118340787683181925558786844"),
MontFp!("2822220997908397120956501031591772354860004534930174057793539372552395729721474912921980407622851861692773516917759"),
MontFp!("1717937747208385987946072944131378949849282930538642983149296304709633281382731764122371874602115081850953846504985"),
MontFp!("501624051089734157816582944025690868317536915684467868346388760435016044027032505306995281054569109955275640941784"),
MontFp!("3025903087998593826923738290305187197829899948335370692927241015584233559365859980023579293766193297662657497834014"),
MontFp!("2224140216975189437834161136818943039444741035168992629437640302964164227138031844090123490881551522278632040105125"),
MontFp!("1146414465848284837484508420047674663876992808692209238763293935905506532411661921697047880549716175045414621825594"),
MontFp!("3179090966864399634396993677377903383656908036827452986467581478509513058347781039562481806409014718357094150199902"),
MontFp!("1549317016540628014674302140786462938410429359529923207442151939696344988707002602944342203885692366490121021806145"),
MontFp!("1442797143427491432630626390066422021593505165588630398337491100088557278058060064930663878153124164818522816175370"),
MontFp!("1"),
],
y_map_numerator : &[
MontFp!("1393399195776646641963150658816615410692049723305861307490980409834842911816308830479576739332720113414154429643571"),
MontFp!("2968610969752762946134106091152102846225411740689724909058016729455736597929366401532929068084731548131227395540630"),
MontFp!("122933100683284845219599644396874530871261396084070222155796123161881094323788483360414289333111221370374027338230"),
MontFp!("303251954782077855462083823228569901064301365507057490567314302006681283228886645653148231378803311079384246777035"),
MontFp!("1353972356724735644398279028378555627591260676383150667237975415318226973994509601413730187583692624416197017403099"),
MontFp!("3443977503653895028417260979421240655844034880950251104724609885224259484262346958661845148165419691583810082940400"),
MontFp!("718493410301850496156792713845282235942975872282052335612908458061560958159410402177452633054233549648465863759602"),
MontFp!("1466864076415884313141727877156167508644960317046160398342634861648153052436926062434809922037623519108138661903145"),
MontFp!("1536886493137106337339531461344158973554574987550750910027365237255347020572858445054025958480906372033954157667719"),
MontFp!("2171468288973248519912068884667133903101171670397991979582205855298465414047741472281361964966463442016062407908400"),
MontFp!("3915937073730221072189646057898966011292434045388986394373682715266664498392389619761133407846638689998746172899634"),
MontFp!("3802409194827407598156407709510350851173404795262202653149767739163117554648574333789388883640862266596657730112910"),
MontFp!("1707589313757812493102695021134258021969283151093981498394095062397393499601961942449581422761005023512037430861560"),
MontFp!("349697005987545415860583335313370109325490073856352967581197273584891698473628451945217286148025358795756956811571"),
MontFp!("885704436476567581377743161796735879083481447641210566405057346859953524538988296201011389016649354976986251207243"),
MontFp!("3370924952219000111210625390420697640496067348723987858345031683392215988129398381698161406651860675722373763741188"),
],
y_map_denominator : &[
MontFp!("3396434800020507717552209507749485772788165484415495716688989613875369612529138640646200921379825018840894888371137"),
MontFp!("3907278185868397906991868466757978732688957419873771881240086730384895060595583602347317992689443299391009456758845"),
MontFp!("854914566454823955479427412036002165304466268547334760894270240966182605542146252771872707010378658178126128834546"),
MontFp!("3496628876382137961119423566187258795236027183112131017519536056628828830323846696121917502443333849318934945158166"),
MontFp!("1828256966233331991927609917644344011503610008134915752990581590799656305331275863706710232159635159092657073225757"),
MontFp!("1362317127649143894542621413133849052553333099883364300946623208643344298804722863920546222860227051989127113848748"),
MontFp!("3443845896188810583748698342858554856823966611538932245284665132724280883115455093457486044009395063504744802318172"),
MontFp!("3484671274283470572728732863557945897902920439975203610275006103818288159899345245633896492713412187296754791689945"),
MontFp!("3755735109429418587065437067067640634211015783636675372165599470771975919172394156249639331555277748466603540045130"),
MontFp!("3459661102222301807083870307127272890283709299202626530836335779816726101522661683404130556379097384249447658110805"),
MontFp!("742483168411032072323733249644347333168432665415341249073150659015707795549260947228694495111018381111866512337576"),
MontFp!("1662231279858095762833829698537304807741442669992646287950513237989158777254081548205552083108208170765474149568658"),
MontFp!("1668238650112823419388205992952852912407572045257706138925379268508860023191233729074751042562151098884528280913356"),
MontFp!("369162719928976119195087327055926326601627748362769544198813069133429557026740823593067700396825489145575282378487"),
MontFp!("2164195715141237148945939585099633032390257748382945597506236650132835917087090097395995817229686247227784224263055"),
MontFp!("1"),
],
};
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_gen() {
let gen: G1Affine = SwuIsoConfig::GENERATOR;
assert!(gen.is_on_curve());
assert!(gen.is_in_correct_subgroup_assuming_on_curve());
}
}

View File

@@ -1,27 +1,35 @@
use crate::*;
use ark_std::ops::Neg;
use ark_ec::{
bls12,
models::{ModelParameters, SWModelParameters},
bls12::Bls12Config,
hashing::curve_maps::wb::{IsogenyMap, WBConfig},
models::CurveConfig,
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective, SWCurveConfig},
AffineRepr, CurveGroup, PrimeGroup,
};
use ark_ff::{field_new, Zero};
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
use ark_serialize::{Compress, SerializationError};
pub type G2Affine = bls12::G2Affine<crate::Parameters>;
pub type G2Projective = bls12::G2Projective<crate::Parameters>;
use super::{
g2_swu_iso,
util::{serialize_fq, EncodingFlags, G2_SERIALIZED_SIZE},
};
use crate::{
util::{read_g2_compressed, read_g2_uncompressed},
*,
};
pub type G2Affine = bls12::G2Affine<crate::Config>;
pub type G2Projective = bls12::G2Projective<crate::Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
pub struct Config;
impl ModelParameters for Parameters {
impl CurveConfig for Config {
type BaseField = Fq2;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = [0, 0]
const COEFF_A: Fq2 = field_new!(Fq2, g1::Parameters::COEFF_A, g1::Parameters::COEFF_A,);
/// COEFF_B = [4, 4]
const COEFF_B: Fq2 = field_new!(Fq2, g1::Parameters::COEFF_B, g1::Parameters::COEFF_B,);
/// COFACTOR = (x^8 - 4 x^7 + 5 x^6) - (4 x^4 + 6 x^3 - 4 x^2 - 4 x + 13) //
/// 9
@@ -40,38 +48,316 @@ impl SWModelParameters for Parameters {
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// 26652489039290660355457965112010883481355318854675681319708643586776743290055
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, "26652489039290660355457965112010883481355318854675681319708643586776743290055");
const COFACTOR_INV: Fr =
MontFp!("26652489039290660355457965112010883481355318854675681319708643586776743290055");
}
impl SWCurveConfig for Config {
/// COEFF_A = [0, 0]
const COEFF_A: Fq2 = Fq2::new(g1::Config::COEFF_A, g1::Config::COEFF_A);
/// COEFF_B = [4, 4]
const COEFF_B: Fq2 = Fq2::new(g1::Config::COEFF_B, g1::Config::COEFF_B);
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
fn is_in_correct_subgroup_assuming_on_curve(point: &G2Affine) -> bool {
// Algorithm from Section 4 of https://eprint.iacr.org/2021/1130.
//
// Checks that [p]P = [X]P
let mut x_times_point = point.mul_bigint(crate::Config::X);
if crate::Config::X_IS_NEGATIVE {
x_times_point = -x_times_point;
}
let p_times_point = p_power_endomorphism(point);
x_times_point.eq(&p_times_point)
}
#[inline]
fn clear_cofactor(p: &G2Affine) -> G2Affine {
// Based on Section 4.1 of https://eprint.iacr.org/2017/419.pdf
// [h(ψ)]P = [x^2 x 1]P + [x 1]ψ(P) + (ψ^2)(2P)
// x = -15132376222941642752
// When multiplying, use -c1 instead, and then negate the result. That's much
// more efficient, since the scalar -c1 has less limbs and a much lower Hamming
// weight.
let x: &'static [u64] = crate::Config::X;
let p_projective = p.into_group();
// [x]P
let x_p = Config::mul_affine(p, &x).neg();
// ψ(P)
let psi_p = p_power_endomorphism(&p);
// (ψ^2)(2P)
let mut psi2_p2 = double_p_power_endomorphism(&p_projective.double());
// tmp = [x]P + ψ(P)
let mut tmp = x_p.clone();
tmp += &psi_p;
// tmp2 = [x^2]P + [x]ψ(P)
let mut tmp2: Projective<Config> = tmp;
tmp2 = tmp2.mul_bigint(x).neg();
// add up all the terms
psi2_p2 += tmp2;
psi2_p2 -= x_p;
psi2_p2 += &-psi_p;
(psi2_p2 - p_projective).into_affine()
}
fn deserialize_with_mode<R: ark_serialize::Read>(
mut reader: R,
compress: ark_serialize::Compress,
validate: ark_serialize::Validate,
) -> Result<Affine<Self>, ark_serialize::SerializationError> {
let p = if compress == ark_serialize::Compress::Yes {
read_g2_compressed(&mut reader)?
} else {
read_g2_uncompressed(&mut reader)?
};
if validate == ark_serialize::Validate::Yes && !p.is_in_correct_subgroup_assuming_on_curve()
{
return Err(SerializationError::InvalidData);
}
Ok(p)
}
fn serialize_with_mode<W: ark_serialize::Write>(
item: &Affine<Self>,
mut writer: W,
compress: ark_serialize::Compress,
) -> Result<(), SerializationError> {
let encoding = EncodingFlags {
is_compressed: compress == ark_serialize::Compress::Yes,
is_infinity: item.is_zero(),
is_lexographically_largest: item.y > -item.y,
};
let mut p = *item;
if encoding.is_infinity {
p = G2Affine::zero();
}
let mut x_bytes = [0u8; G2_SERIALIZED_SIZE];
let c1_bytes = serialize_fq(p.x.c1);
let c0_bytes = serialize_fq(p.x.c0);
x_bytes[0..48].copy_from_slice(&c1_bytes[..]);
x_bytes[48..96].copy_from_slice(&c0_bytes[..]);
if encoding.is_compressed {
let mut bytes: [u8; G2_SERIALIZED_SIZE] = x_bytes;
encoding.encode_flags(&mut bytes);
writer.write_all(&bytes)?;
} else {
let mut bytes = [0u8; 2 * G2_SERIALIZED_SIZE];
let mut y_bytes = [0u8; G2_SERIALIZED_SIZE];
let c1_bytes = serialize_fq(p.y.c1);
let c0_bytes = serialize_fq(p.y.c0);
y_bytes[0..48].copy_from_slice(&c1_bytes[..]);
y_bytes[48..96].copy_from_slice(&c0_bytes[..]);
bytes[0..G2_SERIALIZED_SIZE].copy_from_slice(&x_bytes);
bytes[G2_SERIALIZED_SIZE..].copy_from_slice(&y_bytes);
encoding.encode_flags(&mut bytes);
writer.write_all(&bytes)?;
};
Ok(())
}
fn serialized_size(compress: ark_serialize::Compress) -> usize {
if compress == Compress::Yes {
G2_SERIALIZED_SIZE
} else {
2 * G2_SERIALIZED_SIZE
}
}
}
pub const G2_GENERATOR_X: Fq2 = field_new!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
pub const G2_GENERATOR_Y: Fq2 = field_new!(Fq2, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
impl GLVConfig for Config {
const ENDO_COEFFS: &'static[Self::BaseField] = &[
Fq2::new(
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
Fq::ZERO
)
];
const LAMBDA: Self::ScalarField = MontFp!("228988810152649578064853576960394133503");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("228988810152649578064853576960394133503")),
(true, BigInt!("1")),
(false, BigInt!("1")),
(false, BigInt!("228988810152649578064853576960394133504")),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
/// G2_GENERATOR_X_C0 =
/// 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160
#[rustfmt::skip]
pub const G2_GENERATOR_X_C0: Fq = field_new!(Fq, "352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160");
pub const G2_GENERATOR_X_C0: Fq = MontFp!("352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160");
/// G2_GENERATOR_X_C1 =
/// 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758
#[rustfmt::skip]
pub const G2_GENERATOR_X_C1: Fq = field_new!(Fq, "3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758");
pub const G2_GENERATOR_X_C1: Fq = MontFp!("3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758");
/// G2_GENERATOR_Y_C0 =
/// 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, "1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905");
pub const G2_GENERATOR_Y_C0: Fq = MontFp!("1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905");
/// G2_GENERATOR_Y_C1 =
/// 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, "927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582");
pub const G2_GENERATOR_Y_C1: Fq = MontFp!("927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582");
// PSI_X = 1/(u+1)^((p-1)/3)
const P_POWER_ENDOMORPHISM_COEFF_0 : Fq2 = Fq2::new(
Fq::ZERO,
MontFp!(
"4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437"
)
);
// PSI_Y = 1/(u+1)^((p-1)/2)
const P_POWER_ENDOMORPHISM_COEFF_1: Fq2 = Fq2::new(
MontFp!(
"2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"),
MontFp!(
"1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257")
);
// PSI_2_X = (u+1)^((1-p^2)/3)
const DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0: Fq2 = Fq2::new(
MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
Fq::ZERO
);
/// psi(P) is the untwist-Frobenius-twist endomorhism on E'(Fq2)
fn p_power_endomorphism(p: &Affine<Config>) -> Affine<Config> {
// The p-power endomorphism for G2 is defined as follows:
// 1. Note that G2 is defined on curve E': y^2 = x^3 + 4(u+1).
// To map a point (x, y) in E' to (s, t) in E,
// set s = x / ((u+1) ^ (1/3)), t = y / ((u+1) ^ (1/2)),
// because E: y^2 = x^3 + 4.
// 2. Apply the Frobenius endomorphism (s, t) => (s', t'),
// another point on curve E, where s' = s^p, t' = t^p.
// 3. Map the point from E back to E'; that is,
// set x' = s' * ((u+1) ^ (1/3)), y' = t' * ((u+1) ^ (1/2)).
//
// To sum up, it maps
// (x,y) -> (x^p / ((u+1)^((p-1)/3)), y^p / ((u+1)^((p-1)/2)))
// as implemented in the code as follows.
let mut res = *p;
res.x.frobenius_map_in_place(1);
res.y.frobenius_map_in_place(1);
let tmp_x = res.x.clone();
res.x.c0 = -P_POWER_ENDOMORPHISM_COEFF_0.c1 * &tmp_x.c1;
res.x.c1 = P_POWER_ENDOMORPHISM_COEFF_0.c1 * &tmp_x.c0;
res.y *= P_POWER_ENDOMORPHISM_COEFF_1;
res
}
/// For a p-power endomorphism psi(P), compute psi(psi(P))
fn double_p_power_endomorphism(p: &Projective<Config>) -> Projective<Config> {
let mut res = *p;
res.x *= DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0;
res.y = res.y.neg();
res
}
// Parametres from the [IETF draft v16, section E.3](https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-3-isogeny-map-for-bls12-381).
impl WBConfig for Config {
type IsogenousCurve = g2_swu_iso::SwuIsoConfig;
const ISOGENY_MAP: IsogenyMap<'static, Self::IsogenousCurve, Self> =
g2_swu_iso::ISOGENY_MAP_TO_G2;
}
#[cfg(test)]
mod test {
use super::*;
use ark_std::{rand::Rng, UniformRand};
fn sample_unchecked() -> Affine<g2::Config> {
let mut rng = ark_std::test_rng();
loop {
let x1 = Fq::rand(&mut rng);
let x2 = Fq::rand(&mut rng);
let greatest = rng.gen();
let x = Fq2::new(x1, x2);
if let Some(p) = Affine::get_point_from_x_unchecked(x, greatest) {
return p;
}
}
}
#[test]
fn test_psi_2() {
let p = sample_unchecked();
let psi_p = p_power_endomorphism(&p);
let psi2_p_composed = p_power_endomorphism(&psi_p);
let psi2_p_optimised = double_p_power_endomorphism(&p.into());
assert_eq!(psi2_p_composed, psi2_p_optimised);
}
#[test]
fn test_cofactor_clearing() {
// multiplying by h_eff and clearing the cofactor by the efficient
// endomorphism-based method should yield the same result.
let h_eff: &'static [u64] = &[
0xe8020005aaa95551,
0x59894c0adebbf6b4,
0xe954cbc06689f6a3,
0x2ec0ec69d7477c1a,
0x6d82bf015d1212b0,
0x329c2f178731db95,
0x9986ff031508ffe1,
0x88e2a8e9145ad768,
0x584c6a0ea91b3528,
0xbc69f08f2ee75b3,
];
const SAMPLES: usize = 10;
for _ in 0..SAMPLES {
let p: Affine<g2::Config> = sample_unchecked();
let optimised = p.clear_cofactor();
let naive = g2::Config::mul_affine(&p, h_eff);
assert_eq!(optimised.into_group(), naive);
assert!(optimised.is_on_curve());
assert!(optimised.is_in_correct_subgroup_assuming_on_curve());
}
}
}

View File

@@ -0,0 +1,151 @@
use crate::*;
use ark_ec::{
hashing::curve_maps::{swu::SWUConfig, wb::IsogenyMap},
models::{
short_weierstrass::{Affine, SWCurveConfig},
CurveConfig,
},
};
use ark_ff::MontFp;
type G2Affine = Affine<SwuIsoConfig>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct SwuIsoConfig;
impl CurveConfig for SwuIsoConfig {
type BaseField = Fq2;
type ScalarField = Fr;
/// Cofactors of g2_iso and g2 are the same.
/// COFACTOR = (x^8 - 4 x^7 + 5 x^6) - (4 x^4 + 6 x^3 - 4 x^2 - 4 x + 13) //
/// 9
/// = 3055023339312683442009997531931215042144660192541881426676640329822676041829718840265074273592599778478322728390416166612858038233783720963550777062779109
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0xcf1c38e31c7238e5,
0x1616ec6e786f0c70,
0x21537e293a6691ae,
0xa628f1cb4d9e82ef,
0xa68a205b2e5a7ddf,
0xcd91de4547085aba,
0x91d50792876a202,
0x5d543a95414e7f1,
];
/// COFACTOR_INV = COFACTOR^{-1} mod r
/// 26652489039290660355457965112010883481355318854675681319708643586776743290055
const COFACTOR_INV: Fr =
MontFp!("26652489039290660355457965112010883481355318854675681319708643586776743290055");
}
// https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/
// Hashing to Elliptic Curves
// 8.8.2. BLS12-381 G2
// * E': y'^2 = x'^3 + A' * x' + B', where
//
// - A' = 240 * I
//
// - B' = 1012 * (1 + I)
//
// * Z: -(2 + I)
impl SWCurveConfig for SwuIsoConfig {
/// COEFF_A = 240 * I
const COEFF_A: Fq2 = Fq2::new(MontFp!("0"), MontFp!("240"));
/// COEFF_B = 1012 + 1012 * I
const COEFF_B: Fq2 = Fq2::new(MontFp!("1012"), MontFp!("1012"));
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
}
/// Lexicographically smallest, valid x-coordinate of a point P on the curve
/// (with its corresponding y) multiplied by the cofactor. P_x = 1
/// P_y = 1199519624119946820355795551601605892701128025883245860600494152840508171012839086684258857614063467038089173303263 + 2721622435888802346851223931977585460571674503470326381323808470905804676865417627238564067834747838523978879375704 * I
/// P = E(P_x, P_y)
/// G = P * COFACTOR
const G2_GENERATOR_X: Fq2 = Fq2::new(
MontFp!("2595569946714414516067015540153643524656442638788025933727967960306287756885400469291119095920626560658971252184199"),
MontFp!("1037079738597573406765355774006601850633656296583542639082316151670128374872040593053087014315526494961765370307992")
);
const G2_GENERATOR_Y: Fq2 = Fq2::new(
MontFp!("3927929472994661655038722055497331445175131868678630546921475383290711810401295661250673209427965906654429357114487"),
MontFp!("3300326318345570015758639333209189167876318321385223785506096497597561910823001330832964776707374262378602791224889")
);
impl SWUConfig for SwuIsoConfig {
// ZETA = -(2 + u) as per IETF draft.
const ZETA: Fq2 = Fq2::new(MontFp!("-2"), MontFp!("-1"));
}
pub const ISOGENY_MAP_TO_G2 : IsogenyMap<'_, SwuIsoConfig, g2::Config> = IsogenyMap {
x_map_numerator: &[
Fq2::new(
MontFp!("889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235542"),
MontFp!("889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235542")),
Fq2::new(
MontFp!("0"),
MontFp!("2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706522")),
Fq2::new(
MontFp!("2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706526"),
MontFp!("1334136518407222464472596608578634718852294273313002628444019378708010550163612621480895876376338554679298090853261")),
Fq2::new(
MontFp!("3557697382419259905260257622876359250272784728834673675850718343221361467102966990615722337003569479144794908942033"),
MontFp!("0")),
],
x_map_denominator: &[
Fq2::new(
MontFp!("0"),
MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559715")),
Fq2::new(
MontFp!("12"),
MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559775")),
Fq2::new(
MontFp!("1"),
MontFp!("0")),
],
y_map_numerator: &[
Fq2::new(
MontFp!("3261222600550988246488569487636662646083386001431784202863158481286248011511053074731078808919938689216061999863558"),
MontFp!("3261222600550988246488569487636662646083386001431784202863158481286248011511053074731078808919938689216061999863558")),
Fq2::new(
MontFp!("0"),
MontFp!("889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235518")),
Fq2::new(
MontFp!("2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706524"),
MontFp!("1334136518407222464472596608578634718852294273313002628444019378708010550163612621480895876376338554679298090853263")),
Fq2::new(
MontFp!("2816510427748580758331037284777117739799287910327449993381818688383577828123182200904113516794492504322962636245776"),
MontFp!("0")),
],
y_map_denominator: &[
Fq2::new(
MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559355"),
MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559355")),
Fq2::new(
MontFp!("0"),
MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559571")),
Fq2::new(
MontFp!("18"),
MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559769")),
Fq2::new(
MontFp!("1"),
MontFp!("0")),
],
};
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_gen() {
let gen: G2Affine = curves::g2_swu_iso::SwuIsoConfig::GENERATOR;
assert!(gen.is_on_curve());
assert!(gen.is_in_correct_subgroup_assuming_on_curve());
}
}

View File

@@ -1,9 +1,13 @@
use ark_ec::bls12::{Bls12, Bls12Parameters, TwistType};
use ark_ec::bls12::{Bls12, Bls12Config, TwistType};
use crate::{Fq, Fq12Parameters, Fq2Parameters, Fq6Parameters};
use crate::{Fq, Fq12Config, Fq2Config, Fq6Config};
pub mod g1;
pub mod g2;
pub(crate) mod util;
mod g1_swu_iso;
mod g2_swu_iso;
#[cfg(test)]
mod tests;
@@ -13,18 +17,18 @@ pub use self::{
g2::{G2Affine, G2Projective},
};
pub type Bls12_381 = Bls12<Parameters>;
pub type Bls12_381 = Bls12<Config>;
pub struct Parameters;
pub struct Config;
impl Bls12Parameters for Parameters {
impl Bls12Config for Config {
const X: &'static [u64] = &[0xd201000000010000];
const X_IS_NEGATIVE: bool = true;
const TWIST_TYPE: TwistType = TwistType::M;
type Fp = Fq;
type Fp2Params = Fq2Parameters;
type Fp6Params = Fq6Parameters;
type Fp12Params = Fq12Parameters;
type G1Parameters = self::g1::Parameters;
type G2Parameters = self::g2::Parameters;
type Fp2Config = Fq2Config;
type Fp6Config = Fq6Config;
type Fp12Config = Fq12Config;
type G1Config = self::g1::Config;
type G2Config = self::g2::Config;
}

View File

@@ -1,117 +0,0 @@
#![allow(unused_imports)]
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{
fields::{Field, FpParameters, PrimeField, SquareRootField},
One, Zero,
};
use ark_serialize::CanonicalSerialize;
use ark_std::rand::Rng;
use ark_std::test_rng;
use core::ops::{AddAssign, MulAssign};
use crate::{g1, g2, Bls12_381, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use ark_algebra_test_templates::{curves::*, groups::*};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let mut sa = a;
sa.mul_assign(s);
let mut sb = b;
sb.mul_assign(s);
let ans1 = Bls12_381::pairing(sa, b);
let ans2 = Bls12_381::pairing(a, sb);
let ans3 = Bls12_381::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq12::one());
assert_ne!(ans2, Fq12::one());
assert_ne!(ans3, Fq12::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq12::one());
}
#[test]
fn test_g1_generator_raw() {
let mut x = Fq::zero();
let mut i = 0;
loop {
// y^2 = x^3 + b
let mut rhs = x;
rhs.square_in_place();
rhs.mul_assign(&x);
rhs.add_assign(&g1::Parameters::COEFF_B);
if let Some(y) = rhs.sqrt() {
let p = G1Affine::new(x, if y < -y { y } else { -y }, false);
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
let g1 = p.scale_by_cofactor();
if !g1.is_zero() {
assert_eq!(i, 4);
let g1 = G1Affine::from(g1);
assert!(g1.is_in_correct_subgroup_assuming_on_curve());
assert_eq!(g1, G1Affine::prime_subgroup_generator());
break;
}
}
i += 1;
x.add_assign(&Fq::one());
}
}

View File

@@ -0,0 +1,115 @@
{
"L": "0x40",
"Z": "0xb",
"ciphersuite": "BLS12381G1_XMD:SHA-256_SSWU_RO_",
"curve": "BLS12-381 G1",
"dst": "QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_",
"expand": "XMD",
"field": {
"m": "0x1",
"p": "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"
},
"hash": "sha256",
"k": "0x80",
"map": {
"name": "SSWU"
},
"randomOracle": true,
"vectors": [
{
"P": {
"x": "0x052926add2207b76ca4fa57a8734416c8dc95e24501772c814278700eed6d1e4e8cf62d9c09db0fac349612b759e79a1",
"y": "0x08ba738453bfed09cb546dbb0783dbb3a5f1f566ed67bb6be0e8c67e2e81a4cc68ee29813bb7994998f3eae0c9c6a265"
},
"Q0": {
"x": "0x11a3cce7e1d90975990066b2f2643b9540fa40d6137780df4e753a8054d07580db3b7f1f03396333d4a359d1fe3766fe",
"y": "0x0eeaf6d794e479e270da10fdaf768db4c96b650a74518fc67b04b03927754bac66f3ac720404f339ecdcc028afa091b7"
},
"Q1": {
"x": "0x160003aaf1632b13396dbad518effa00fff532f604de1a7fc2082ff4cb0afa2d63b2c32da1bef2bf6c5ca62dc6b72f9c",
"y": "0x0d8bb2d14e20cf9f6036152ed386d79189415b6d015a20133acb4e019139b94e9c146aaad5817f866c95d609a361735e"
},
"msg": "",
"u": [
"0x0ba14bd907ad64a016293ee7c2d276b8eae71f25a4b941eece7b0d89f17f75cb3ae5438a614fb61d6835ad59f29c564f",
"0x019b9bd7979f12657976de2884c7cce192b82c177c80e0ec604436a7f538d231552f0d96d9f7babe5fa3b19b3ff25ac9"
]
},
{
"P": {
"x": "0x03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903",
"y": "0x0b9c15f3fe6e5cf4211f346271d7b01c8f3b28be689c8429c85b67af215533311f0b8dfaaa154fa6b88176c229f2885d"
},
"Q0": {
"x": "0x125435adce8e1cbd1c803e7123f45392dc6e326d292499c2c45c5865985fd74fe8f042ecdeeec5ecac80680d04317d80",
"y": "0x0e8828948c989126595ee30e4f7c931cbd6f4570735624fd25aef2fa41d3f79cfb4b4ee7b7e55a8ce013af2a5ba20bf2"
},
"Q1": {
"x": "0x11def93719829ecda3b46aa8c31fc3ac9c34b428982b898369608e4f042babee6c77ab9218aad5c87ba785481eff8ae4",
"y": "0x0007c9cef122ccf2efd233d6eb9bfc680aa276652b0661f4f820a653cec1db7ff69899f8e52b8e92b025a12c822a6ce6"
},
"msg": "abc",
"u": [
"0x0d921c33f2bad966478a03ca35d05719bdf92d347557ea166e5bba579eea9b83e9afa5c088573c2281410369fbd32951",
"0x003574a00b109ada2f26a37a91f9d1e740dffd8d69ec0c35e1e9f4652c7dba61123e9dd2e76c655d956e2b3462611139"
]
},
{
"P": {
"x": "0x11e0b079dea29a68f0383ee94fed1b940995272407e3bb916bbf268c263ddd57a6a27200a784cbc248e84f357ce82d98",
"y": "0x03a87ae2caf14e8ee52e51fa2ed8eefe80f02457004ba4d486d6aa1f517c0889501dc7413753f9599b099ebcbbd2d709"
},
"Q0": {
"x": "0x08834484878c217682f6d09a4b51444802fdba3d7f2df9903a0ddadb92130ebbfa807fffa0eabf257d7b48272410afff",
"y": "0x0b318f7ecf77f45a0f038e62d7098221d2dbbca2a394164e2e3fe953dc714ac2cde412d8f2d7f0c03b259e6795a2508e"
},
"Q1": {
"x": "0x158418ed6b27e2549f05531a8281b5822b31c3bf3144277fbb977f8d6e2694fedceb7011b3c2b192f23e2a44b2bd106e",
"y": "0x1879074f344471fac5f839e2b4920789643c075792bec5af4282c73f7941cda5aa77b00085eb10e206171b9787c4169f"
},
"msg": "abcdef0123456789",
"u": [
"0x062d1865eb80ebfa73dcfc45db1ad4266b9f3a93219976a3790ab8d52d3e5f1e62f3b01795e36834b17b70e7b76246d4",
"0x0cdc3e2f271f29c4ff75020857ce6c5d36008c9b48385ea2f2bf6f96f428a3deb798aa033cd482d1cdc8b30178b08e3a"
]
},
{
"P": {
"x": "0x15f68eaa693b95ccb85215dc65fa81038d69629f70aeee0d0f677cf22285e7bf58d7cb86eefe8f2e9bc3f8cb84fac488",
"y": "0x1807a1d50c29f430b8cafc4f8638dfeeadf51211e1602a5f184443076715f91bb90a48ba1e370edce6ae1062f5e6dd38"
},
"Q0": {
"x": "0x0cbd7f84ad2c99643fea7a7ac8f52d63d66cefa06d9a56148e58b984b3dd25e1f41ff47154543343949c64f88d48a710",
"y": "0x052c00e4ed52d000d94881a5638ae9274d3efc8bc77bc0e5c650de04a000b2c334a9e80b85282a00f3148dfdface0865"
},
"Q1": {
"x": "0x06493fb68f0d513af08be0372f849436a787e7b701ae31cb964d968021d6ba6bd7d26a38aaa5a68e8c21a6b17dc8b579",
"y": "0x02e98f2ccf5802b05ffaac7c20018bc0c0b2fd580216c4aa2275d2909dc0c92d0d0bdc979226adeb57a29933536b6bb4"
},
"msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
"u": [
"0x010476f6a060453c0b1ad0b628f3e57c23039ee16eea5e71bb87c3b5419b1255dc0e5883322e563b84a29543823c0e86",
"0x0b1a912064fb0554b180e07af7e787f1f883a0470759c03c1b6509eb8ce980d1670305ae7b928226bb58fdc0a419f46e"
]
},
{
"P": {
"x": "0x082aabae8b7dedb0e78aeb619ad3bfd9277a2f77ba7fad20ef6aabdc6c31d19ba5a6d12283553294c1825c4b3ca2dcfe",
"y": "0x05b84ae5a942248eea39e1d91030458c40153f3b654ab7872d779ad1e942856a20c438e8d99bc8abfbf74729ce1f7ac8"
},
"Q0": {
"x": "0x0cf97e6dbd0947857f3e578231d07b309c622ade08f2c08b32ff372bd90db19467b2563cc997d4407968d4ac80e154f8",
"y": "0x127f0cddf2613058101a5701f4cb9d0861fd6c2a1b8e0afe194fccf586a3201a53874a2761a9ab6d7220c68661a35ab3"
},
"Q1": {
"x": "0x092f1acfa62b05f95884c6791fba989bbe58044ee6355d100973bf9553ade52b47929264e6ae770fb264582d8dce512a",
"y": "0x028e6d0169a72cfedb737be45db6c401d3adfb12c58c619c82b93a5dfcccef12290de530b0480575ddc8397cda0bbebf"
},
"msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"u": [
"0x0a8ffa7447f6be1c5a2ea4b959c9454b431e29ccc0802bc052413a9c5b4f9aac67a93431bd480d15be1e057c8a08e8c6",
"0x05d487032f602c90fa7625dbafe0f4a49ef4a6b0b33d7bb349ff4cf5410d297fd6241876e3e77b651cfc8191e40a68b7"
]
}
]
}

View File

@@ -0,0 +1,115 @@
{
"L": "0x40",
"Z": "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaa9,0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa",
"ciphersuite": "BLS12381G2_XMD:SHA-256_SSWU_RO_",
"curve": "BLS12-381 G2",
"dst": "QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_",
"expand": "XMD",
"field": {
"m": "0x2",
"p": "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"
},
"hash": "sha256",
"k": "0x80",
"map": {
"name": "SSWU"
},
"randomOracle": true,
"vectors": [
{
"P": {
"x": "0x0141ebfbdca40eb85b87142e130ab689c673cf60f1a3e98d69335266f30d9b8d4ac44c1038e9dcdd5393faf5c41fb78a,0x05cb8437535e20ecffaef7752baddf98034139c38452458baeefab379ba13dff5bf5dd71b72418717047f5b0f37da03d",
"y": "0x0503921d7f6a12805e72940b963c0cf3471c7b2a524950ca195d11062ee75ec076daf2d4bc358c4b190c0c98064fdd92,0x12424ac32561493f3fe3c260708a12b7c620e7be00099a974e259ddc7d1f6395c3c811cdd19f1e8dbf3e9ecfdcbab8d6"
},
"Q0": {
"x": "0x019ad3fc9c72425a998d7ab1ea0e646a1f6093444fc6965f1cad5a3195a7b1e099c050d57f45e3fa191cc6d75ed7458c,0x171c88b0b0efb5eb2b88913a9e74fe111a4f68867b59db252ce5868af4d1254bfab77ebde5d61cd1a86fb2fe4a5a1c1d",
"y": "0x0ba10604e62bdd9eeeb4156652066167b72c8d743b050fb4c1016c31b505129374f76e03fa127d6a156213576910fef3,0x0eb22c7a543d3d376e9716a49b72e79a89c9bfe9feee8533ed931cbb5373dde1fbcd7411d8052e02693654f71e15410a"
},
"Q1": {
"x": "0x113d2b9cd4bd98aee53470b27abc658d91b47a78a51584f3d4b950677cfb8a3e99c24222c406128c91296ef6b45608be,0x13855912321c5cb793e9d1e88f6f8d342d49c0b0dbac613ee9e17e3c0b3c97dfbb5a49cc3fb45102fdbaf65e0efe2632",
"y": "0x0fd3def0b7574a1d801be44fde617162aa2e89da47f464317d9bb5abc3a7071763ce74180883ad7ad9a723a9afafcdca,0x056f617902b3c0d0f78a9a8cbda43a26b65f602f8786540b9469b060db7b38417915b413ca65f875c130bebfaa59790c"
},
"msg": "",
"u": [
"0x03dbc2cce174e91ba93cbb08f26b917f98194a2ea08d1cce75b2b9cc9f21689d80bd79b594a613d0a68eb807dfdc1cf8,0x05a2acec64114845711a54199ea339abd125ba38253b70a92c876df10598bd1986b739cad67961eb94f7076511b3b39a",
"0x02f99798e8a5acdeed60d7e18e9120521ba1f47ec090984662846bc825de191b5b7641148c0dbc237726a334473eee94,0x145a81e418d4010cc027a68f14391b30074e89e60ee7a22f87217b2f6eb0c4b94c9115b436e6fa4607e95a98de30a435"
]
},
{
"P": {
"x": "0x02c2d18e033b960562aae3cab37a27ce00d80ccd5ba4b7fe0e7a210245129dbec7780ccc7954725f4168aff2787776e6,0x139cddbccdc5e91b9623efd38c49f81a6f83f175e80b06fc374de9eb4b41dfe4ca3a230ed250fbe3a2acf73a41177fd8",
"y": "0x1787327b68159716a37440985269cf584bcb1e621d3a7202be6ea05c4cfe244aeb197642555a0645fb87bf7466b2ba48,0x00aa65dae3c8d732d10ecd2c50f8a1baf3001578f71c694e03866e9f3d49ac1e1ce70dd94a733534f106d4cec0eddd16"
},
"Q0": {
"x": "0x12b2e525281b5f4d2276954e84ac4f42cf4e13b6ac4228624e17760faf94ce5706d53f0ca1952f1c5ef75239aeed55ad,0x05d8a724db78e570e34100c0bc4a5fa84ad5839359b40398151f37cff5a51de945c563463c9efbdda569850ee5a53e77",
"y": "0x02eacdc556d0bdb5d18d22f23dcb086dd106cad713777c7e6407943edbe0b3d1efe391eedf11e977fac55f9b94f2489c,0x04bbe48bfd5814648d0b9e30f0717b34015d45a861425fabc1ee06fdfce36384ae2c808185e693ae97dcde118f34de41"
},
"Q1": {
"x": "0x19f18cc5ec0c2f055e47c802acc3b0e40c337256a208001dde14b25afced146f37ea3d3ce16834c78175b3ed61f3c537,0x15b0dadc256a258b4c68ea43605dffa6d312eef215c19e6474b3e101d33b661dfee43b51abbf96fee68fc6043ac56a58",
"y": "0x05e47c1781286e61c7ade887512bd9c2cb9f640d3be9cf87ea0bad24bd0ebfe946497b48a581ab6c7d4ca74b5147287f,0x19f98db2f4a1fcdf56a9ced7b320ea9deecf57c8e59236b0dc21f6ee7229aa9705ce9ac7fe7a31c72edca0d92370c096"
},
"msg": "abc",
"u": [
"0x15f7c0aa8f6b296ab5ff9c2c7581ade64f4ee6f1bf18f55179ff44a2cf355fa53dd2a2158c5ecb17d7c52f63e7195771,0x01c8067bf4c0ba709aa8b9abc3d1cef589a4758e09ef53732d670fd8739a7274e111ba2fcaa71b3d33df2a3a0c8529dd",
"0x187111d5e088b6b9acfdfad078c4dacf72dcd17ca17c82be35e79f8c372a693f60a033b461d81b025864a0ad051a06e4,0x08b852331c96ed983e497ebc6dee9b75e373d923b729194af8e72a051ea586f3538a6ebb1e80881a082fa2b24df9f566"
]
},
{
"P": {
"x": "0x121982811d2491fde9ba7ed31ef9ca474f0e1501297f68c298e9f4c0028add35aea8bb83d53c08cfc007c1e005723cd0,0x190d119345b94fbd15497bcba94ecf7db2cbfd1e1fe7da034d26cbba169fb3968288b3fafb265f9ebd380512a71c3f2c",
"y": "0x05571a0f8d3c08d094576981f4a3b8eda0a8e771fcdcc8ecceaf1356a6acf17574518acb506e435b639353c2e14827c8,0x0bb5e7572275c567462d91807de765611490205a941a5a6af3b1691bfe596c31225d3aabdf15faff860cb4ef17c7c3be"
},
"Q0": {
"x": "0x0f48f1ea1318ddb713697708f7327781fb39718971d72a9245b9731faaca4dbaa7cca433d6c434a820c28b18e20ea208,0x06051467c8f85da5ba2540974758f7a1e0239a5981de441fdd87680a995649c211054869c50edbac1f3a86c561ba3162",
"y": "0x168b3d6df80069dbbedb714d41b32961ad064c227355e1ce5fac8e105de5e49d77f0c64867f3834848f152497eb76333,0x134e0e8331cee8cb12f9c2d0742714ed9eee78a84d634c9a95f6a7391b37125ed48bfc6e90bf3546e99930ff67cc97bc"
},
"Q1": {
"x": "0x004fd03968cd1c99a0dd84551f44c206c84dcbdb78076c5bfee24e89a92c8508b52b88b68a92258403cbe1ea2da3495f,0x1674338ea298281b636b2eb0fe593008d03171195fd6dcd4531e8a1ed1f02a72da238a17a635de307d7d24aa2d969a47",
"y": "0x0dc7fa13fff6b12558419e0a1e94bfc3cfaf67238009991c5f24ee94b632c3d09e27eca329989aee348a67b50d5e236c,0x169585e164c131103d85324f2d7747b23b91d66ae5d947c449c8194a347969fc6bbd967729768da485ba71868df8aed2"
},
"msg": "abcdef0123456789",
"u": [
"0x0313d9325081b415bfd4e5364efaef392ecf69b087496973b229303e1816d2080971470f7da112c4eb43053130b785e1,0x062f84cb21ed89406890c051a0e8b9cf6c575cf6e8e18ecf63ba86826b0ae02548d83b483b79e48512b82a6c0686df8f",
"0x1739123845406baa7be5c5dc74492051b6d42504de008c635f3535bb831d478a341420e67dcc7b46b2e8cba5379cca97,0x01897665d9cb5db16a27657760bbea7951f67ad68f8d55f7113f24ba6ddd82caef240a9bfa627972279974894701d975"
]
},
{
"P": {
"x": "0x19a84dd7248a1066f737cc34502ee5555bd3c19f2ecdb3c7d9e24dc65d4e25e50d83f0f77105e955d78f4762d33c17da,0x0934aba516a52d8ae479939a91998299c76d39cc0c035cd18813bec433f587e2d7a4fef038260eef0cef4d02aae3eb91",
"y": "0x14f81cd421617428bc3b9fe25afbb751d934a00493524bc4e065635b0555084dd54679df1536101b2c979c0152d09192,0x09bcccfa036b4847c9950780733633f13619994394c23ff0b32fa6b795844f4a0673e20282d07bc69641cee04f5e5662"
},
"Q0": {
"x": "0x09eccbc53df677f0e5814e3f86e41e146422834854a224bf5a83a50e4cc0a77bfc56718e8166ad180f53526ea9194b57,0x0c3633943f91daee715277bd644fba585168a72f96ded64fc5a384cce4ec884a4c3c30f08e09cd2129335dc8f67840ec",
"y": "0x0eb6186a0457d5b12d132902d4468bfeb7315d83320b6c32f1c875f344efcba979952b4aa418589cb01af712f98cc555,0x119e3cf167e69eb16c1c7830e8df88856d48be12e3ff0a40791a5cd2f7221311d4bf13b1847f371f467357b3f3c0b4c7"
},
"Q1": {
"x": "0x0eb3aabc1ddfce17ff18455fcc7167d15ce6b60ddc9eb9b59f8d40ab49420d35558686293d046fc1e42f864b7f60e381,0x198bdfb19d7441ebcca61e8ff774b29d17da16547d2c10c273227a635cacea3f16826322ae85717630f0867539b5ed8b",
"y": "0x0aaf1dee3adf3ed4c80e481c09b57ea4c705e1b8d25b897f0ceeec3990748716575f92abff22a1c8f4582aff7b872d52,0x0d058d9061ed27d4259848a06c96c5ca68921a5d269b078650c882cb3c2bd424a8702b7a6ee4e0ead9982baf6843e924"
},
"msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
"u": [
"0x025820cefc7d06fd38de7d8e370e0da8a52498be9b53cba9927b2ef5c6de1e12e12f188bbc7bc923864883c57e49e253,0x034147b77ce337a52e5948f66db0bab47a8d038e712123bb381899b6ab5ad20f02805601e6104c29df18c254b8618c7b",
"0x0930315cae1f9a6017c3f0c8f2314baa130e1cf13f6532bff0a8a1790cd70af918088c3db94bda214e896e1543629795,0x10c4df2cacf67ea3cb3108b00d4cbd0b3968031ebc8eac4b1ebcefe84d6b715fde66bef0219951ece29d1facc8a520ef"
]
},
{
"P": {
"x": "0x01a6ba2f9a11fa5598b2d8ace0fbe0a0eacb65deceb476fbbcb64fd24557c2f4b18ecfc5663e54ae16a84f5ab7f62534,0x11fca2ff525572795a801eed17eb12785887c7b63fb77a42be46ce4a34131d71f7a73e95fee3f812aea3de78b4d01569",
"y": "0x0b6798718c8aed24bc19cb27f866f1c9effcdbf92397ad6448b5c9db90d2b9da6cbabf48adc1adf59a1a28344e79d57e,0x03a47f8e6d1763ba0cad63d6114c0accbef65707825a511b251a660a9b3994249ae4e63fac38b23da0c398689ee2ab52"
},
"Q0": {
"x": "0x17cadf8d04a1a170f8347d42856526a24cc466cb2ddfd506cff01191666b7f944e31244d662c904de5440516a2b09004,0x0d13ba91f2a8b0051cf3279ea0ee63a9f19bc9cb8bfcc7d78b3cbd8cc4fc43ba726774b28038213acf2b0095391c523e",
"y": "0x17ef19497d6d9246fa94d35575c0f8d06ee02f21a284dbeaa78768cb1e25abd564e3381de87bda26acd04f41181610c5,0x12c3c913ba4ed03c24f0721a81a6be7430f2971ffca8fd1729aafe496bb725807531b44b34b59b3ae5495e5a2dcbd5c8"
},
"Q1": {
"x": "0x16ec57b7fe04c71dfe34fb5ad84dbce5a2dbbd6ee085f1d8cd17f45e8868976fc3c51ad9eeda682c7869024d24579bfd,0x13103f7aace1ae1420d208a537f7d3a9679c287208026e4e3439ab8cd534c12856284d95e27f5e1f33eec2ce656533b0",
"y": "0x0958b2c4c2c10fcef5a6c59b9e92c4a67b0fae3e2e0f1b6b5edad9c940b8f3524ba9ebbc3f2ceb3cfe377655b3163bd7,0x0ccb594ed8bd14ca64ed9cb4e0aba221be540f25dd0d6ba15a4a4be5d67bcf35df7853b2d8dad3ba245f1ea3697f66aa"
},
"msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"u": [
"0x190b513da3e66fc9a3587b78c76d1d132b1152174d0b83e3c1114066392579a45824c5fa17649ab89299ddd4bda54935,0x12ab625b0fe0ebd1367fe9fac57bb1168891846039b4216b9d94007b674de2d79126870e88aeef54b2ec717a887dcf39",
"0x0e6a42010cf435fb5bacc156a585e1ea3294cc81d0ceb81924d95040298380b164f702275892cedd81b62de3aba3f6b5,0x117d9a0defc57a33ed208428cb84e54c85a6840e7648480ae428838989d25d97a0af8e3255be62b25c2a85630d2dddd8"
]
}
]
}

123
bls12_381/src/curves/tests/mod.rs Executable file
View File

@@ -0,0 +1,123 @@
use ark_algebra_test_templates::*;
use ark_ec::{AffineRepr, CurveGroup, PrimeGroup};
use ark_ff::{fields::Field, One, UniformRand, Zero};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate};
use ark_std::{rand::Rng, test_rng, vec};
use crate::{Bls12_381, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw);
test_group!(g1_glv; G1Projective; glv);
test_group!(g2_glv; G2Projective; glv);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bls12_381>; msm);
test_pairing!(pairing; crate::Bls12_381);
test_h2c!(g1_h2c; "./src/curves/tests"; "BLS12381G1"; crate::g1::Config; crate::Fq; crate::Fq; 1);
test_h2c!(g2_hc2; "./src/curves/tests"; "BLS12381G2"; crate::g2::Config; crate::Fq2; crate::Fq; 2);
#[test]
fn test_g1_endomorphism_beta() {
assert!(crate::g1::BETA.pow(&[3u64]).is_one());
}
#[test]
fn test_g1_subgroup_membership_via_endomorphism() {
let mut rng = test_rng();
let generator = G1Projective::rand(&mut rng).into_affine();
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g1_subgroup_non_membership_via_endomorphism() {
let mut rng = test_rng();
loop {
let x = Fq::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = G1Affine::get_point_from_x_unchecked(x, greatest) {
if !p.mul_bigint(Fr::characteristic()).is_zero() {
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
return;
}
}
}
}
#[test]
fn test_g2_subgroup_membership_via_endomorphism() {
let mut rng = test_rng();
let generator = G2Projective::rand(&mut rng).into_affine();
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_subgroup_non_membership_via_endomorphism() {
let mut rng = test_rng();
loop {
let x = Fq2::rand(&mut rng);
let greatest = rng.gen();
if let Some(p) = G2Affine::get_point_from_x_unchecked(x, greatest) {
if !p.mul_bigint(Fr::characteristic()).is_zero() {
assert!(!p.is_in_correct_subgroup_assuming_on_curve());
return;
}
}
}
}
// Test vectors and macro adapted from https://github.com/zkcrypto/bls12_381/blob/e224ad4ea1babfc582ccd751c2bf128611d10936/src/tests/mod.rs
macro_rules! test_vectors {
($projective:ident, $affine:ident, $compress:expr, $expected:ident) => {
let mut e = $projective::zero();
let mut v = vec![];
{
let mut expected = $expected;
for _ in 0..1000 {
let e_affine = $affine::from(e);
let mut serialized = vec![0u8; e.serialized_size($compress)];
e_affine
.serialize_with_mode(serialized.as_mut_slice(), $compress)
.unwrap();
v.extend_from_slice(&serialized[..]);
let mut decoded = serialized;
let len_of_encoding = decoded.len();
(&mut decoded[..]).copy_from_slice(&expected[0..len_of_encoding]);
expected = &expected[len_of_encoding..];
let decoded =
$affine::deserialize_with_mode(&decoded[..], $compress, Validate::Yes).unwrap();
assert_eq!(e_affine, decoded);
e += &$projective::generator();
}
}
assert_eq!(&v[..], $expected);
};
}
#[test]
fn g1_compressed_valid_test_vectors() {
let bytes: &'static [u8] = include_bytes!("g1_compressed_valid_test_vectors.dat");
test_vectors!(G1Projective, G1Affine, Compress::Yes, bytes);
}
#[test]
fn g1_uncompressed_valid_test_vectors() {
let bytes: &'static [u8] = include_bytes!("g1_uncompressed_valid_test_vectors.dat");
test_vectors!(G1Projective, G1Affine, Compress::No, bytes);
}
#[test]
fn g2_compressed_valid_test_vectors() {
let bytes: &'static [u8] = include_bytes!("g2_compressed_valid_test_vectors.dat");
test_vectors!(G2Projective, G2Affine, Compress::Yes, bytes);
}
#[test]
fn g2_uncompressed_valid_test_vectors() {
let bytes: &'static [u8] = include_bytes!("g2_uncompressed_valid_test_vectors.dat");
test_vectors!(G2Projective, G2Affine, Compress::No, bytes);
}

View File

@@ -0,0 +1,258 @@
use ark_ec::{short_weierstrass::Affine, AffineRepr};
use ark_ff::{BigInteger384, PrimeField};
use ark_serialize::SerializationError;
use crate::{g1::Config as G1Config, g2::Config as G2Config, Fq, Fq2, G1Affine, G2Affine};
pub const G1_SERIALIZED_SIZE: usize = 48;
pub const G2_SERIALIZED_SIZE: usize = 96;
pub struct EncodingFlags {
pub is_compressed: bool,
pub is_infinity: bool,
pub is_lexographically_largest: bool,
}
impl EncodingFlags {
/// Fetches the flags from the byte-string
pub fn get_flags(bytes: &[u8]) -> Result<Self, SerializationError> {
let compression_flag_set = (bytes[0] >> 7) & 1;
let infinity_flag_set = (bytes[0] >> 6) & 1;
let sort_flag_set = (bytes[0] >> 5) & 1;
let is_compressed = compression_flag_set == 1;
let is_infinity = infinity_flag_set == 1;
let is_lexographically_largest = sort_flag_set == 1;
if is_lexographically_largest && (!is_compressed || is_infinity) {
return Err(SerializationError::InvalidData);
}
Ok(Self {
is_compressed,
is_infinity,
is_lexographically_largest,
})
}
/// Encodes the flags into the byte-string
pub fn encode_flags(&self, bytes: &mut [u8]) {
if self.is_compressed {
bytes[0] |= 1 << 7;
}
if self.is_infinity {
bytes[0] |= 1 << 6;
}
if self.is_compressed && !self.is_infinity && self.is_lexographically_largest {
bytes[0] |= 1 << 5;
}
}
/// Removes the flags from the byte-string.
///
/// This reverses the effects of `encode_flags`.
pub fn remove_flags(bytes: &mut [u8]) {
bytes[0] &= 0b0001_1111;
}
}
pub(crate) fn deserialize_fq(bytes: [u8; 48]) -> Option<Fq> {
let mut tmp = BigInteger384::new([0, 0, 0, 0, 0, 0]);
// Note: The following unwraps are if the compiler cannot convert
// the byte slice into [u8;8], we know this is infallible since we
// are providing the indices at compile time and bytes has a fixed size
tmp.0[5] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[0..8]).unwrap());
tmp.0[4] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap());
tmp.0[3] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[16..24]).unwrap());
tmp.0[2] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[24..32]).unwrap());
tmp.0[1] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[32..40]).unwrap());
tmp.0[0] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[40..48]).unwrap());
Fq::from_bigint(tmp)
}
pub(crate) fn serialize_fq(field: Fq) -> [u8; 48] {
let mut result = [0u8; 48];
let rep = field.into_bigint();
result[0..8].copy_from_slice(&rep.0[5].to_be_bytes());
result[8..16].copy_from_slice(&rep.0[4].to_be_bytes());
result[16..24].copy_from_slice(&rep.0[3].to_be_bytes());
result[24..32].copy_from_slice(&rep.0[2].to_be_bytes());
result[32..40].copy_from_slice(&rep.0[1].to_be_bytes());
result[40..48].copy_from_slice(&rep.0[0].to_be_bytes());
result
}
fn read_bytes_with_offset(bytes: &[u8], offset: usize, mask: bool) -> [u8; G1_SERIALIZED_SIZE] {
let mut tmp = [0; G1_SERIALIZED_SIZE];
// read `G1_SERIALIZED_SIZE` bytes
tmp.copy_from_slice(&bytes[offset * G1_SERIALIZED_SIZE..G1_SERIALIZED_SIZE * (offset + 1)]);
if mask {
EncodingFlags::remove_flags(&mut tmp);
}
tmp
}
pub(crate) fn read_g1_compressed<R: ark_serialize::Read>(
mut reader: R,
) -> Result<Affine<G1Config>, ark_serialize::SerializationError> {
let mut bytes = [0u8; G1_SERIALIZED_SIZE];
reader
.read_exact(&mut bytes)
.ok()
.ok_or(SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes[..])?;
// We expect to be deserializing a compressed point
if !flags.is_compressed {
return Err(SerializationError::UnexpectedFlags);
}
// Attempt to obtain the x-coordinate
let x_bytes = read_bytes_with_offset(&bytes, 0, true);
if flags.is_infinity {
// Check that the `x` co-ordinate was `0`
if x_bytes != [0u8; 48] {
return Err(SerializationError::InvalidData);
}
return Ok(G1Affine::zero());
}
let x = deserialize_fq(x_bytes).ok_or(SerializationError::InvalidData)?;
let p = G1Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
.ok_or(SerializationError::InvalidData)?;
Ok(p)
}
pub(crate) fn read_g1_uncompressed<R: ark_serialize::Read>(
mut reader: R,
) -> Result<Affine<G1Config>, ark_serialize::SerializationError> {
let mut bytes = [0u8; 2 * G1_SERIALIZED_SIZE];
reader
.read_exact(&mut bytes)
.map_err(|_| SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes[..])?;
// we expect to be deserializing an uncompressed point
if flags.is_compressed {
return Err(SerializationError::UnexpectedFlags);
}
let x_bytes = read_bytes_with_offset(&bytes, 0, true);
let y_bytes = read_bytes_with_offset(&bytes, 1, false);
if flags.is_infinity {
if x_bytes != [0u8; 48] || y_bytes != [0u8; 48] {
return Err(SerializationError::InvalidData);
}
return Ok(G1Affine::zero());
}
// Attempt to obtain the x-coordinate
let x = deserialize_fq(x_bytes).ok_or(SerializationError::InvalidData)?;
// Attempt to obtain the y-coordinate
let y = deserialize_fq(y_bytes).ok_or(SerializationError::InvalidData)?;
let p = G1Affine::new_unchecked(x, y);
Ok(p)
}
pub(crate) fn read_g2_compressed<R: ark_serialize::Read>(
mut reader: R,
) -> Result<Affine<G2Config>, ark_serialize::SerializationError> {
let mut bytes = [0u8; G2_SERIALIZED_SIZE];
reader
.read_exact(&mut bytes)
.map_err(|_| SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes)?;
// we expect to be deserializing a compressed point
if !flags.is_compressed {
return Err(SerializationError::UnexpectedFlags);
}
let xc1_bytes = read_bytes_with_offset(&bytes, 0, true);
let xc0_bytes = read_bytes_with_offset(&bytes, 1, false);
if flags.is_infinity {
if xc1_bytes != [0u8; 48] || xc0_bytes != [0u8; 48] {
return Err(SerializationError::InvalidData);
}
return Ok(G2Affine::zero());
}
// Attempt to obtain the x-coordinate
let xc1 = deserialize_fq(xc1_bytes).ok_or(SerializationError::InvalidData)?;
let xc0 = deserialize_fq(xc0_bytes).ok_or(SerializationError::InvalidData)?;
let x = Fq2::new(xc0, xc1);
let p = G2Affine::get_point_from_x_unchecked(x, flags.is_lexographically_largest)
.ok_or(SerializationError::InvalidData)?;
Ok(p)
}
pub(crate) fn read_g2_uncompressed<R: ark_serialize::Read>(
mut reader: R,
) -> Result<Affine<G2Config>, ark_serialize::SerializationError> {
let mut bytes = [0u8; 2 * G2_SERIALIZED_SIZE];
reader
.read_exact(&mut bytes)
.map_err(|_| SerializationError::InvalidData)?;
// Obtain the three flags from the start of the byte sequence
let flags = EncodingFlags::get_flags(&bytes)?;
// we expect to be deserializing an uncompressed point
if flags.is_compressed {
return Err(SerializationError::UnexpectedFlags);
}
let xc1_bytes = read_bytes_with_offset(&bytes, 0, true);
let xc0_bytes = read_bytes_with_offset(&bytes, 1, false);
let yc1_bytes = read_bytes_with_offset(&bytes, 2, false);
let yc0_bytes = read_bytes_with_offset(&bytes, 3, false);
if flags.is_infinity {
if xc1_bytes != [0u8; 48]
|| xc0_bytes != [0u8; 48]
|| yc1_bytes != [0u8; 48]
|| yc0_bytes != [0u8; 48]
{
return Err(SerializationError::InvalidData);
}
return Ok(G2Affine::zero());
}
let xc1 = deserialize_fq(xc1_bytes).ok_or(SerializationError::InvalidData)?;
let xc0 = deserialize_fq(xc0_bytes).ok_or(SerializationError::InvalidData)?;
let yc1 = deserialize_fq(yc1_bytes).ok_or(SerializationError::InvalidData)?;
let yc0 = deserialize_fq(yc0_bytes).ok_or(SerializationError::InvalidData)?;
// Attempt to obtain the x-coordinate
let x = Fq2::new(xc0, xc1);
// Attempt to obtain the y-coordinate
let y = Fq2::new(yc0, yc1);
let p = G2Affine::new_unchecked(x, y);
Ok(p)
}

View File

@@ -1,115 +1,12 @@
use ark_ff::{
biginteger::BigInteger384 as BigInteger,
field_new,
fields::{FftParameters, Fp384, Fp384Parameters, FpParameters},
};
use ark_ff::fields::{Fp384, MontBackend, MontConfig};
pub type Fq = Fp384<FqParameters>;
#[derive(MontConfig)]
#[modulus = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787"]
#[generator = "2"]
#[small_subgroup_base = "3"]
#[small_subgroup_power = "2"]
pub struct FqConfig;
pub type Fq = Fp384<MontBackend<FqConfig, 6>>;
pub struct FqParameters;
impl Fp384Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 1;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
0x43f5fffffffcaaae,
0x32b7fff2ed47fffd,
0x7e83a49a2e99d69,
0xeca8f3318332bb7a,
0xef148d1ea0f4c069,
0x40ab3263eff0206,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0xb9feffffffffaaab,
0x1eabfffeb153ffff,
0x6730d2a0f6b0f624,
0x64774b84f38512bf,
0x4b1ba7b6434bacd7,
0x1a0111ea397fe69a,
]);
const MODULUS_BITS: u32 = 381;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 3;
/// R = 3380320199399472671518931668520476396067793891014375699959770179129436917079669831430077592723774664465579537268733
#[rustfmt::skip]
const R: BigInteger = BigInteger([
0x760900000002fffd,
0xebf4000bc40c0002,
0x5f48985753c758ba,
0x77ce585370525745,
0x5c071a97a256ec6d,
0x15f65ec3fa80e493,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0xf4df1f341c341746,
0xa76e6a609d104f1,
0x8de5476c4c95b6d5,
0x67eb88a9939d83c0,
0x9a793e85b519952d,
0x11988fe592cae3aa,
]);
const INV: u64 = 0x89f3fffcfffcfffd;
/// GENERATOR = 2
/// Encoded in Montgomery form, so the value is
/// 2 * R % q = 2758230843577277949620073511305048635578704962089743514587482222134842183668501798417467556318533664893264801977679
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
0x321300000006554f,
0xb93c0018d6c40005,
0x57605e0db0ddbb51,
0x8b256521ed1f9bcb,
0x6cf28d7901622c03,
0x11ebab9dbb81e28c,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xdcff7fffffffd555,
0xf55ffff58a9ffff,
0xb39869507b587b12,
0xb23ba5c279c2895f,
0x258dd3db21a5d66b,
0xd0088f51cbff34d,
]);
/// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
/// For T coprime to 2
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0xdcff7fffffffd555,
0xf55ffff58a9ffff,
0xb39869507b587b12,
0xb23ba5c279c2895f,
0x258dd3db21a5d66b,
0xd0088f51cbff34d,
]);
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xee7fbfffffffeaaa,
0x7aaffffac54ffff,
0xd9cc34a83dac3d89,
0xd91dd2e13ce144af,
0x92c6e9ed90d2eb35,
0x680447a8e5ff9a6,
]);
}
pub const FQ_ONE: Fq = field_new!(Fq, "1");
pub const FQ_ZERO: Fq = field_new!(Fq, "0");
pub const FQ_ONE: Fq = ark_ff::MontFp!("1");
pub const FQ_ZERO: Fq = ark_ff::MontFp!("0");

View File

@@ -1,76 +1,77 @@
use crate::*;
use ark_ff::{field_new, fields::*};
use ark_ff::{fields::*, MontFp};
pub type Fq12 = Fp12<Fq12Parameters>;
use crate::*;
pub type Fq12 = Fp12<Fq12Config>;
#[derive(Clone, Copy)]
pub struct Fq12Parameters;
pub struct Fq12Config;
impl Fp12Parameters for Fq12Parameters {
type Fp6Params = Fq6Parameters;
impl Fp12Config for Fq12Config {
type Fp6Config = Fq6Config;
const NONRESIDUE: Fq6 = field_new!(Fq6, FQ2_ZERO, FQ2_ONE, FQ2_ZERO);
const NONRESIDUE: Fq6 = Fq6::new(Fq2::ZERO, Fq2::ONE, Fq2::ZERO);
const FROBENIUS_COEFF_FP12_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "1"),
field_new!(Fq, "0"),
Fq2::new(
Fq::ONE,
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^1) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760"),
field_new!(Fq, "151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027"),
Fq2::new(
MontFp!("3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760"),
MontFp!("151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027"),
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"),
field_new!(Fq, "1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257"),
Fq2::new(
MontFp!("2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"),
MontFp!("1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257"),
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557"),
field_new!(Fq, "877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230"),
Fq2::new(
MontFp!("3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557"),
MontFp!("877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230"),
),
// Fp2::NONRESIDUE^(((q^6) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "-1"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("-1"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^7) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027"),
field_new!(Fq, "3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760"),
Fq2::new(
MontFp!("151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027"),
MontFp!("3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760"),
),
// Fp2::NONRESIDUE^(((q^8) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^9) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257"),
field_new!(Fq, "2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"),
Fq2::new(
MontFp!("1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257"),
MontFp!("2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"),
),
// Fp2::NONRESIDUE^(((q^10) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^11) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230"),
field_new!(Fq, "3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557"),
Fq2::new(
MontFp!("877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230"),
MontFp!("3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557"),
),
];
}

View File

@@ -1,35 +1,42 @@
use ark_ff::{fields::*, MontFp};
use crate::*;
use ark_ff::{field_new, fields::*};
pub type Fq2 = Fp2<Fq2Parameters>;
pub type Fq2 = Fp2<Fq2Config>;
pub struct Fq2Parameters;
pub struct Fq2Config;
impl Fp2Parameters for Fq2Parameters {
impl Fp2Config for Fq2Config {
type Fp = Fq;
/// NONRESIDUE = -1
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, "-1");
/// QUADRATIC_NONRESIDUE = (U + 1)
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE: (Fq, Fq) = (FQ_ONE, FQ_ONE);
const NONRESIDUE: Fq = MontFp!("-1");
/// Coefficients for the Frobenius automorphism.
#[rustfmt::skip]
const FROBENIUS_COEFF_FP2_C1: &'static [Fq] = &[
// Fq(-1)**(((q^0) - 1) / 2)
field_new!(Fq, "1"),
Fq::ONE,
// Fq(-1)**(((q^1) - 1) / 2)
field_new!(Fq, "-1"),
MontFp!("-1"),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fp: &Self::Fp) -> Self::Fp {
-(*fp)
}
fn mul_fp_by_nonresidue_in_place(fp: &mut Self::Fp) -> &mut Self::Fp {
fp.neg_in_place()
}
pub const FQ2_ZERO: Fq2 = field_new!(Fq2, FQ_ZERO, FQ_ZERO);
pub const FQ2_ONE: Fq2 = field_new!(Fq2, FQ_ONE, FQ_ZERO);
#[inline(always)]
fn sub_and_mul_fp_by_nonresidue(y: &mut Self::Fp, x: &Self::Fp) {
*y += x;
}
#[inline(always)]
fn mul_fp_by_nonresidue_plus_one_and_add(y: &mut Self::Fp, x: &Self::Fp) {
*y = *x;
}
fn mul_fp_by_nonresidue_and_add(y: &mut Self::Fp, x: &Self::Fp) {
y.neg_in_place();
*y += x;
}
}

View File

@@ -1,96 +1,91 @@
use crate::*;
use ark_ff::{field_new, fields::*};
use ark_ff::{fields::*, MontFp};
pub type Fq6 = Fp6<Fq6Parameters>;
use crate::*;
pub type Fq6 = Fp6<Fq6Config>;
#[derive(Clone, Copy)]
pub struct Fq6Parameters;
pub struct Fq6Config;
impl Fp6Parameters for Fq6Parameters {
type Fp2Params = Fq2Parameters;
impl Fp6Config for Fq6Config {
type Fp2Config = Fq2Config;
/// NONRESIDUE = (U + 1)
#[rustfmt::skip]
const NONRESIDUE: Fq2 = field_new!(Fq2,
field_new!(Fq, "1"),
field_new!(Fq, "1"),
);
const NONRESIDUE: Fq2 = Fq2::new(Fq::ONE, Fq::ONE);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "1"),
field_new!(Fq, "0"),
Fq2::new(
Fq::ONE,
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^1) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "0"),
field_new!(Fq, "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
Fq2::new(
Fq::ZERO,
MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "0"),
field_new!(Fq, "1"),
Fq2::new(
Fq::ZERO,
Fq::ONE,
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "0"),
field_new!(Fq, "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
Fq2::new(
Fq::ZERO,
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
),
];
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C2: &'static [Fq2] = &[
// Fq2(u + 1)**(((2q^0) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "1"),
field_new!(Fq, "0"),
Fq2::new(
Fq::ONE,
Fq::ZERO,
),
// Fq2(u + 1)**(((2q^1) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437"),
Fq::ZERO,
),
// Fq2(u + 1)**(((2q^2) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
Fq::ZERO,
),
// Fq2(u + 1)**(((2q^3) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "-1"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("-1"),
Fq::ZERO,
),
// Fq2(u + 1)**(((2q^4) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"),
Fq::ZERO,
),
// Fq2(u + 1)**(((2q^5) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351"),
Fq::ZERO,
),
];
/// Multiply this element by the quadratic nonresidue 1 + u.
/// Make this generic.
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
let mut copy = *fe;
let t0 = copy.c0;
copy.c0 -= &fe.c1;
copy.c1 += &t0;
copy
fn mul_fp2_by_nonresidue_in_place(fe: &mut Fq2) -> &mut Fq2 {
let t0 = fe.c0;
fe.c0 -= &fe.c1;
fe.c1 += &t0;
fe
}
}

View File

@@ -1,100 +1,9 @@
use ark_ff::{
biginteger::BigInteger256 as BigInteger,
fields::{FftParameters, Fp256, Fp256Parameters, FpParameters},
};
use ark_ff::fields::{Fp256, MontBackend, MontConfig};
pub type Fr = Fp256<FrParameters>;
pub struct FrParameters;
impl Fp256Parameters for FrParameters {}
impl FftParameters for FrParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 32;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
0xb9b58d8c5f0e466a,
0x5b1b4c801819d7ec,
0xaf53ae352a31e64,
0x5bf3adda19e9b27b,
]);
}
impl FpParameters for FrParameters {
/// MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0xffffffff00000001,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]);
const MODULUS_BITS: u32 = 255;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 1;
/// R = 10920338887063814464675503992315976177888879664585288394250266608035967270910
#[rustfmt::skip]
const R: BigInteger = BigInteger([
0x1fffffffe,
0x5884b7fa00034802,
0x998c4fefecbc4ff5,
0x1824b159acc5056f,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0xc999e990f3f29c6d,
0x2b6cedcb87925c23,
0x5d314967254398f,
0x748d9d99f59ff11,
]);
const INV: u64 = 0xfffffffeffffffff;
/// GENERATOR = 7
/// Encoded in Montgomery form, so the value here is
/// 7 * R % q = 24006497034320510773280787438025867407531605151569380937148207556313189711857
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
0xefffffff1,
0x17e363d300189c0f,
0xff9c57876f8457b0,
0x351332208fc5a8c4,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x7fffffff80000000,
0xa9ded2017fff2dff,
0x199cec0404d0ec02,
0x39f6d3a994cebea4,
]);
// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
// For T coprime to 2
// T = (MODULUS - 1) / 2^S =
// 12208678567578594777604504606729831043093128246378069236549469339647
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0xfffe5bfeffffffff,
0x9a1d80553bda402,
0x299d7d483339d808,
0x73eda753,
]);
// (T - 1) / 2 =
// 6104339283789297388802252303364915521546564123189034618274734669823
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x7fff2dff7fffffff,
0x4d0ec02a9ded201,
0x94cebea4199cec04,
0x39f6d3a9,
]);
}
#[derive(MontConfig)]
#[modulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
#[generator = "7"]
#[small_subgroup_base = "3"]
#[small_subgroup_power = "1"]
pub struct FrConfig;
pub type Fr = Fp256<MontBackend<FrConfig, 4>>;

View File

@@ -23,5 +23,5 @@ pub mod fq12;
#[cfg(feature = "curve")]
pub use self::fq12::*;
#[cfg(all(feature = "curve", feature = "std", test))]
#[cfg(all(feature = "curve", test))]
mod tests;

File diff suppressed because it is too large Load Diff

11
bls12_381/src/lib.rs Normal file → Executable file
View File

@@ -9,15 +9,16 @@
#![forbid(unsafe_code)]
//! This library implements the BLS12_381 curve generated by [Sean Bowe](https://electriccoin.co/blog/new-snark-curve/).
//! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree 12,
//! defined over a 381-bit (prime) field.
//! This curve was intended to replace the BN254 curve to provide a higher security
//! level without incurring a large performance overhead.
//! The name denotes that it is a Barreto--Lynn--Scott curve of embedding degree
//! 12, defined over a 381-bit (prime) field.
//! This curve was intended to replace the BN254 curve to provide a higher
//! security level without incurring a large performance overhead.
//!
//!
//! Curve information:
//! * Base field: q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
//! * Scalar field: r = 52435875175126190479447740508185965837690552500527637822603658699938581184513
//! * Scalar field: r =
//! 52435875175126190479447740508185965837690552500527637822603658699938581184513
//! * valuation(q - 1, 2) = 1
//! * valuation(r - 1, 2) = 32
//! * G1 curve equation: y^2 = x^3 + 4

View File

@@ -1,25 +1,26 @@
[package]
name = "ark-bn254"
version = "0.1.0"
version = "0.4.0"
authors = [ "arkworks contributors" ]
description = "The BN254 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/algebra"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/ark-bn254/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
edition = "2021"
[dependencies]
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
ark-ff = { version= "0.4.0", default-features = false }
ark-ec = { version= "0.4.0", default-features = false }
ark-std = { version = "0.4.0", default-features = false }
[dev-dependencies]
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-algebra-test-templates = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-serialize = { version = "0.4.0", default-features = false }
ark-algebra-test-templates = { version = "0.4.0", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0", default-features = false }
[features]
default = [ "curve" ]
@@ -27,3 +28,8 @@ std = [ "ark-std/std", "ark-ff/std", "ark-ec/std" ]
curve = [ "scalar_field" ]
scalar_field = []
[[bench]]
name = "bn254"
path = "benches/bn254.rs"
harness = false

13
bn254/benches/bn254.rs Normal file
View File

@@ -0,0 +1,13 @@
use ark_algebra_bench_templates::*;
use ark_bn254::{fq::Fq, fq2::Fq2, fr::Fr, Bn254, Fq12, G1Projective as G1, G2Projective as G2};
bench!(
Name = "BN254",
Pairing = Bn254,
G1 = G1,
G2 = G2,
ScalarField = Fr,
G1BaseField = Fq,
G2BaseField = Fq2,
TargetField = Fq12,
);

View File

@@ -0,0 +1,28 @@
modulus = 21888242871839275222246405745257275088696311157297823662689037894645226208583
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -0,0 +1,28 @@
modulus = 21888242871839275222246405745257275088548364400416034343698204186575808495617
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -1,41 +1,83 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{field_new, Zero};
use ark_ec::{
bn,
models::{short_weierstrass::SWCurveConfig, CurveConfig},
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective},
};
use ark_ff::{AdditiveGroup, BigInt, Field, MontFp, PrimeField, Zero};
use crate::{Fq, Fr};
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
pub struct Config;
impl ModelParameters for Parameters {
pub type G1Affine = Affine<Config>;
impl CurveConfig for Config {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
const COEFF_A: Fq = field_new!(Fq, "0");
/// COEFF_B = 3
const COEFF_B: Fq = field_new!(Fq, "3");
/// COFACTOR = 1
const COFACTOR: &'static [u64] = &[0x1];
/// COFACTOR_INV = COFACTOR^{-1} mod r = 1
const COFACTOR_INV: Fr = field_new!(Fr, "1");
const COFACTOR_INV: Fr = Fr::ONE;
}
impl SWCurveConfig for Config {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = 3
const COEFF_B: Fq = MontFp!("3");
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
#[inline]
fn mul_projective(
p: &bn::G1Projective<crate::Config>,
scalar: &[u64],
) -> bn::G1Projective<crate::Config> {
let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
GLVConfig::glv_mul_projective(*p, s)
}
}
impl GLVConfig for Config {
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
"21888242871839275220042445260109153167277707414472061641714758635765020556616"
)];
const LAMBDA: Self::ScalarField =
MontFp!("21888242871839275217838484774961031246154997185409878258781734729429964517155");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("147946756881789319000765030803803410728")),
(true, BigInt!("9931322734385697763")),
(false, BigInt!("9931322734385697763")),
(false, BigInt!("147946756881789319010696353538189108491")),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
/// G1_GENERATOR_X = 1
pub const G1_GENERATOR_X: Fq = field_new!(Fq, "1");
pub const G1_GENERATOR_X: Fq = Fq::ONE;
/// G1_GENERATOR_Y = 2
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, "2");
pub const G1_GENERATOR_Y: Fq = MontFp!("2");

View File

@@ -1,31 +1,23 @@
use ark_ec::models::{ModelParameters, SWModelParameters};
use ark_ff::{field_new, Zero};
use ark_ec::{
models::{short_weierstrass::SWCurveConfig, CurveConfig},
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective},
};
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField, Zero};
use crate::{Fq, Fq2, Fr};
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
pub type G2Affine = Affine<Config>;
impl ModelParameters for Parameters {
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Config;
impl CurveConfig for Config {
type BaseField = Fq2;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = [0, 0]
#[rustfmt::skip]
const COEFF_A: Fq2 = field_new!(Fq2, field_new!(Fq, "0"), field_new!(Fq, "0"));
/// COEFF_B = 3/(u+9)
/// = (19485874751759354771024239261021720505790618469301721065564631296452457478373, 266929791119991161246907387137283842545076965332900288569378510910307636690)
#[rustfmt::skip]
const COEFF_B: Fq2 = field_new!(Fq2,
field_new!(Fq, "19485874751759354771024239261021720505790618469301721065564631296452457478373"),
field_new!(Fq, "266929791119991161246907387137283842545076965332900288569378510910307636690"),
);
/// COFACTOR = (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1
/// = 21888242871839275222246405745257275088844257914179612981679871602714643921549
/// 21888242871839275222246405745257275088844257914179612981679871602714643921549
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x345f2299c0f9fa8d,
@@ -35,40 +27,78 @@ impl SWModelParameters for Parameters {
];
/// COFACTOR_INV = COFACTOR^{-1} mod r
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, "10944121435919637613327163357776759465618812564592884533313067514031822496649");
const COFACTOR_INV: Fr =
MontFp!("10944121435919637613327163357776759465618812564592884533313067514031822496649");
}
impl SWCurveConfig for Config {
/// COEFF_A = [0, 0]
const COEFF_A: Fq2 = Fq2::ZERO;
/// COEFF_B = 3/(u+9)
/// (19485874751759354771024239261021720505790618469301721065564631296452457478373, 266929791119991161246907387137283842545076965332900288569378510910307636690)
const COEFF_B: Fq2 = Fq2::new(
MontFp!("19485874751759354771024239261021720505790618469301721065564631296452457478373"),
MontFp!("266929791119991161246907387137283842545076965332900288569378510910307636690"),
);
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
Self::BaseField::zero()
}
}
#[rustfmt::skip]
pub const G2_GENERATOR_X: Fq2 = field_new!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
#[rustfmt::skip]
pub const G2_GENERATOR_Y: Fq2 = field_new!(Fq2, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
impl GLVConfig for Config {
const ENDO_COEFFS: &'static [Self::BaseField] = &[Fq2::new(
MontFp!("21888242871839275220042445260109153167277707414472061641714758635765020556616"),
Fq::ZERO,
)];
const LAMBDA: Self::ScalarField =
MontFp!("4407920970296243842393367215006156084916469457145843978461");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(false, BigInt!("147946756881789319010696353538189108491")),
(false, BigInt!("9931322734385697763")),
(true, BigInt!("9931322734385697763")),
(false, BigInt!("147946756881789319000765030803803410728")),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
/// G2_GENERATOR_X_C0 =
/// 10857046999023057135944570762232829481370756359578518086990519993285655852781
#[rustfmt::skip]
pub const G2_GENERATOR_X_C0: Fq = field_new!(Fq, "10857046999023057135944570762232829481370756359578518086990519993285655852781");
pub const G2_GENERATOR_X_C0: Fq =
MontFp!("10857046999023057135944570762232829481370756359578518086990519993285655852781");
/// G2_GENERATOR_X_C1 =
/// 11559732032986387107991004021392285783925812861821192530917403151452391805634
#[rustfmt::skip]
pub const G2_GENERATOR_X_C1: Fq = field_new!(Fq, "11559732032986387107991004021392285783925812861821192530917403151452391805634");
pub const G2_GENERATOR_X_C1: Fq =
MontFp!("11559732032986387107991004021392285783925812861821192530917403151452391805634");
/// G2_GENERATOR_Y_C0 =
/// 8495653923123431417604973247489272438418190587263600148770280649306958101930
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C0: Fq = field_new!(Fq, "8495653923123431417604973247489272438418190587263600148770280649306958101930");
pub const G2_GENERATOR_Y_C0: Fq =
MontFp!("8495653923123431417604973247489272438418190587263600148770280649306958101930");
/// G2_GENERATOR_Y_C1 =
/// 4082367875863433681332203403145435568316851327593401208105741076214120093531
#[rustfmt::skip]
pub const G2_GENERATOR_Y_C1: Fq = field_new!(Fq, "4082367875863433681332203403145435568316851327593401208105741076214120093531");
pub const G2_GENERATOR_Y_C1: Fq =
MontFp!("4082367875863433681332203403145435568316851327593401208105741076214120093531");

View File

@@ -1,18 +1,20 @@
use crate::*;
use ark_ec::{
bn,
bn::{Bn, BnParameters, TwistType},
bn::{Bn, BnConfig, TwistType},
};
use ark_ff::field_new;
use ark_ff::MontFp;
use crate::*;
pub mod g1;
pub mod g2;
#[cfg(test)]
mod tests;
pub struct Parameters;
pub struct Config;
impl BnParameters for Parameters {
impl BnConfig for Config {
const X: &'static [u64] = &[4965661367192848881];
/// `x` is positive.
const X_IS_NEGATIVE: bool = false;
@@ -21,43 +23,27 @@ impl BnParameters for Parameters {
0, 1, 1, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 0, 1, 1, 0,
-1, 0, 0, 1, 0, 1, 1,
];
/// `ate_loop_count` is positive.
const ATE_LOOP_COUNT_IS_NEGATIVE: bool = false;
const TWIST_MUL_BY_Q_X: Fq2 = field_new!(
Fq2,
field_new!(
Fq,
"21575463638280843010398324269430826099269044274347216827212613867836435027261"
),
field_new!(
Fq,
"10307601595873709700152284273816112264069230130616436755625194854815875713954"
),
const TWIST_MUL_BY_Q_X: Fq2 = Fq2::new(
MontFp!("21575463638280843010398324269430826099269044274347216827212613867836435027261"),
MontFp!("10307601595873709700152284273816112264069230130616436755625194854815875713954"),
);
const TWIST_MUL_BY_Q_Y: Fq2 = field_new!(
Fq2,
field_new!(
Fq,
"2821565182194536844548159561693502659359617185244120367078079554186484126554"
),
field_new!(
Fq,
"3505843767911556378687030309984248845540243509899259641013678093033130930403"
),
const TWIST_MUL_BY_Q_Y: Fq2 = Fq2::new(
MontFp!("2821565182194536844548159561693502659359617185244120367078079554186484126554"),
MontFp!("3505843767911556378687030309984248845540243509899259641013678093033130930403"),
);
const TWIST_TYPE: TwistType = TwistType::D;
type Fp = Fq;
type Fp2Params = Fq2Parameters;
type Fp6Params = Fq6Parameters;
type Fp12Params = Fq12Parameters;
type G1Parameters = g1::Parameters;
type G2Parameters = g2::Parameters;
type Fp2Config = Fq2Config;
type Fp6Config = Fq6Config;
type Fp12Config = Fq12Config;
type G1Config = g1::Config;
type G2Config = g2::Config;
}
pub type Bn254 = Bn<Parameters>;
pub type Bn254 = Bn<Config>;
pub type G1Affine = bn::G1Affine<Parameters>;
pub type G1Projective = bn::G1Projective<Parameters>;
pub type G2Affine = bn::G2Affine<Parameters>;
pub type G2Projective = bn::G2Projective<Parameters>;
pub type G1Affine = bn::G1Affine<Config>;
pub type G1Projective = bn::G1Projective<Config>;
pub type G2Affine = bn::G2Affine<Config>;
pub type G2Projective = bn::G2Projective<Config>;

93
bn254/src/curves/tests.rs Normal file → Executable file
View File

@@ -1,86 +1,11 @@
#![allow(unused_imports)]
use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{
fields::{Field, FpParameters, PrimeField, SquareRootField},
One, Zero,
};
use ark_serialize::CanonicalSerialize;
use ark_std::rand::Rng;
use ark_std::test_rng;
use core::ops::{AddAssign, MulAssign};
use ark_algebra_test_templates::*;
use ark_ff::fields::Field;
use crate::{g1, g2, Bn254, Fq, Fq12, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective};
use crate::{Bn254, G1Projective, G2Projective};
use ark_algebra_test_templates::{curves::*, groups::*};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let mut sa = a;
sa.mul_assign(s);
let mut sb = b;
sb.mul_assign(s);
let ans1 = Bn254::pairing(sa, b);
let ans2 = Bn254::pairing(a, sb);
let ans3 = Bn254::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq12::one());
assert_ne!(ans2, Fq12::one());
assert_ne!(ans3, Fq12::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq12::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq12::one());
}
test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<Bn254>; msm);
test_pairing!(pairing; crate::Bn254);
test_group!(g1_glv; G1Projective; glv);
test_group!(g2_glv; G2Projective; glv);

View File

@@ -1,96 +1,7 @@
use ark_ff::{biginteger::BigInteger256 as BigInteger, field_new, fields::*};
use ark_ff::fields::{Fp256, MontBackend, MontConfig};
pub type Fq = Fp256<FqParameters>;
pub struct FqParameters;
impl Fp256Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 1;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
0x68c3488912edefaa,
0x8d087f6872aabf4f,
0x51e1a24709081231,
0x2259d6b14729c0fa,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0x3c208c16d87cfd47,
0x97816a916871ca8d,
0xb85045b68181585d,
0x30644e72e131a029,
]);
const MODULUS_BITS: u32 = 254;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 2;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
0xd35d438dc58f0d9d,
0x0a78eb28f5c70b3d,
0x666ea36f7879462c,
0xe0a77c19a07df2f,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
0xf32cfc5b538afa89,
0xb5e71911d44501fb,
0x47ab1eff0a417ff6,
0x6d89f71cab8351f,
]);
const INV: u64 = 9786893198990664585u64;
// GENERATOR = 3
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
0x7a17caa950ad28d7,
0x1f6ac17ae15521b9,
0x334bea4e696bd284,
0x2a1f6744ce179d8e,
]);
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x9e10460b6c3e7ea3,
0xcbc0b548b438e546,
0xdc2822db40c0ac2e,
0x183227397098d014,
]);
// T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T
// T = (MODULUS - 1) // 2^S =
// 10944121435919637611123202872628637544348155578648911831344518947322613104291
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x9e10460b6c3e7ea3,
0xcbc0b548b438e546,
0xdc2822db40c0ac2e,
0x183227397098d014,
]);
// (T - 1) // 2 =
// 1837921289030710838195067919506396475074392872918698035817074744121558668640693829665401097909504529
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x4f082305b61f3f51,
0x65e05aa45a1c72a3,
0x6e14116da0605617,
0xc19139cb84c680a,
]);
}
pub const FQ_ONE: Fq = field_new!(Fq, "1");
pub const FQ_ZERO: Fq = field_new!(Fq, "0");
#[derive(MontConfig)]
#[modulus = "21888242871839275222246405745257275088696311157297823662689037894645226208583"]
#[generator = "3"]
pub struct FqConfig;
pub type Fq = Fp256<MontBackend<FqConfig, 4>>;

View File

@@ -1,77 +1,89 @@
use super::*;
use ark_ff::{field_new, fields::*};
use ark_ff::{fields::*, MontFp};
pub type Fq12 = Fp12<Fq12Parameters>;
use crate::*;
pub type Fq12 = Fp12<Fq12Config>;
#[derive(Clone, Copy)]
pub struct Fq12Parameters;
pub struct Fq12Config;
impl Fp12Parameters for Fq12Parameters {
type Fp6Params = Fq6Parameters;
impl Fp12Config for Fq12Config {
type Fp6Config = Fq6Config;
const NONRESIDUE: Fq6 = field_new!(Fq6, FQ2_ZERO, FQ2_ONE, FQ2_ZERO);
const NONRESIDUE: Fq6 = Fq6::new(Fq2::ZERO, Fq2::ONE, Fq2::ZERO);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP12_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "1"),
field_new!(Fq, "0"),
),
Fq2::new(Fq::ONE, Fq::ZERO),
// Fp2::NONRESIDUE^(((q^1) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "8376118865763821496583973867626364092589906065868298776909617916018768340080"),
field_new!(Fq, "16469823323077808223889137241176536799009286646108169935659301613961712198316"),
Fq2::new(
MontFp!("8376118865763821496583973867626364092589906065868298776909617916018768340080"),
MontFp!(
"16469823323077808223889137241176536799009286646108169935659301613961712198316"
),
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "21888242871839275220042445260109153167277707414472061641714758635765020556617"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!(
"21888242871839275220042445260109153167277707414472061641714758635765020556617"
),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "11697423496358154304825782922584725312912383441159505038794027105778954184319"),
field_new!(Fq, "303847389135065887422783454877609941456349188919719272345083954437860409601"),
Fq2::new(
MontFp!(
"11697423496358154304825782922584725312912383441159505038794027105778954184319"
),
MontFp!("303847389135065887422783454877609941456349188919719272345083954437860409601"),
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "21888242871839275220042445260109153167277707414472061641714758635765020556616"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!(
"21888242871839275220042445260109153167277707414472061641714758635765020556616"
),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "3321304630594332808241809054958361220322477375291206261884409189760185844239"),
field_new!(Fq, "5722266937896532885780051958958348231143373700109372999374820235121374419868"),
Fq2::new(
MontFp!("3321304630594332808241809054958361220322477375291206261884409189760185844239"),
MontFp!("5722266937896532885780051958958348231143373700109372999374820235121374419868"),
),
// Fp2::NONRESIDUE^(((q^6) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "-1"),
field_new!(Fq, "0"),
),
Fq2::new(MontFp!("-1"), Fq::ZERO),
// Fp2::NONRESIDUE^(((q^7) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "13512124006075453725662431877630910996106405091429524885779419978626457868503"),
field_new!(Fq, "5418419548761466998357268504080738289687024511189653727029736280683514010267"),
Fq2::new(
MontFp!(
"13512124006075453725662431877630910996106405091429524885779419978626457868503"
),
MontFp!("5418419548761466998357268504080738289687024511189653727029736280683514010267"),
),
// Fp2::NONRESIDUE^(((q^8) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "2203960485148121921418603742825762020974279258880205651966"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("2203960485148121921418603742825762020974279258880205651966"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^9) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "10190819375481120917420622822672549775783927716138318623895010788866272024264"),
field_new!(Fq, "21584395482704209334823622290379665147239961968378104390343953940207365798982"),
Fq2::new(
MontFp!(
"10190819375481120917420622822672549775783927716138318623895010788866272024264"
),
MontFp!(
"21584395482704209334823622290379665147239961968378104390343953940207365798982"
),
),
// Fp2::NONRESIDUE^(((q^10) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "2203960485148121921418603742825762020974279258880205651967"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("2203960485148121921418603742825762020974279258880205651967"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^11) - 1) / 6)
field_new!(Fq2,
field_new!(Fq, "18566938241244942414004596690298913868373833782006617400804628704885040364344"),
field_new!(Fq, "16165975933942742336466353786298926857552937457188450663314217659523851788715"),
Fq2::new(
MontFp!(
"18566938241244942414004596690298913868373833782006617400804628704885040364344"
),
MontFp!(
"16165975933942742336466353786298926857552937457188450663314217659523851788715"
),
),
];
}

View File

@@ -1,38 +1,27 @@
use super::*;
use ark_ff::{field_new, fields::*};
use ark_ff::{fields::*, MontFp};
pub type Fq2 = Fp2<Fq2Parameters>;
use crate::*;
pub struct Fq2Parameters;
pub type Fq2 = Fp2<Fq2Config>;
impl Fp2Parameters for Fq2Parameters {
pub struct Fq2Config;
impl Fp2Config for Fq2Config {
type Fp = Fq;
/// NONRESIDUE = -1
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, "-1");
/// QUADRATIC_NONRESIDUE = U+2
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE: (Fq, Fq) = (
field_new!(Fq, "2"),
field_new!(Fq, "1"),
);
const NONRESIDUE: Fq = MontFp!("-1");
/// Coefficients for the Frobenius automorphism.
#[rustfmt::skip]
const FROBENIUS_COEFF_FP2_C1: &'static [Fq] = &[
// NONRESIDUE**(((q^0) - 1) / 2)
field_new!(Fq, "1"),
Fq::ONE,
// NONRESIDUE**(((q^1) - 1) / 2)
field_new!(Fq, "-1"),
MontFp!("-1"),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
-(*fe)
fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
fe.neg_in_place()
}
}
pub const FQ2_ZERO: Fq2 = field_new!(Fq2, FQ_ZERO, FQ_ZERO);
pub const FQ2_ONE: Fq2 = field_new!(Fq2, FQ_ONE, FQ_ZERO);

View File

@@ -1,92 +1,105 @@
use super::*;
use ark_ff::{field_new, fields::*};
use ark_ff::{fields::*, MontFp};
pub type Fq6 = Fp6<Fq6Parameters>;
use crate::*;
pub type Fq6 = Fp6<Fq6Config>;
#[derive(Clone, Copy)]
pub struct Fq6Parameters;
pub struct Fq6Config;
impl Fp6Parameters for Fq6Parameters {
type Fp2Params = Fq2Parameters;
impl Fp6Config for Fq6Config {
type Fp2Config = Fq2Config;
/// NONRESIDUE = U+9
#[rustfmt::skip]
const NONRESIDUE: Fq2 = field_new!(Fq2, field_new!(Fq, "9"), field_new!(Fq, "1"));
const NONRESIDUE: Fq2 = Fq2::new(MontFp!("9"), Fq::ONE);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq2] = &[
// Fp2::NONRESIDUE^(((q^0) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "1"),
field_new!(Fq, "0"),
),
Fq2::new(Fq::ONE, Fq::ZERO),
// Fp2::NONRESIDUE^(((q^1) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "21575463638280843010398324269430826099269044274347216827212613867836435027261"),
field_new!(Fq, "10307601595873709700152284273816112264069230130616436755625194854815875713954"),
Fq2::new(
MontFp!(
"21575463638280843010398324269430826099269044274347216827212613867836435027261"
),
MontFp!(
"10307601595873709700152284273816112264069230130616436755625194854815875713954"
),
),
// Fp2::NONRESIDUE^(((q^2) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "21888242871839275220042445260109153167277707414472061641714758635765020556616"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!(
"21888242871839275220042445260109153167277707414472061641714758635765020556616"
),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^3) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "3772000881919853776433695186713858239009073593817195771773381919316419345261"),
field_new!(Fq, "2236595495967245188281701248203181795121068902605861227855261137820944008926"),
Fq2::new(
MontFp!("3772000881919853776433695186713858239009073593817195771773381919316419345261"),
MontFp!("2236595495967245188281701248203181795121068902605861227855261137820944008926"),
),
// Fp2::NONRESIDUE^(((q^4) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "2203960485148121921418603742825762020974279258880205651966"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("2203960485148121921418603742825762020974279258880205651966"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^(((q^5) - 1) / 3)
field_new!(Fq2,
field_new!(Fq, "18429021223477853657660792034369865839114504446431234726392080002137598044644"),
field_new!(Fq, "9344045779998320333812420223237981029506012124075525679208581902008406485703"),
Fq2::new(
MontFp!(
"18429021223477853657660792034369865839114504446431234726392080002137598044644"
),
MontFp!("9344045779998320333812420223237981029506012124075525679208581902008406485703"),
),
];
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C2: &'static [Fq2] = &[
// Fp2::NONRESIDUE^((2*(q^0) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "1"),
field_new!(Fq, "0"),
),
Fq2::new(Fq::ONE, Fq::ZERO),
// Fp2::NONRESIDUE^((2*(q^1) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "2581911344467009335267311115468803099551665605076196740867805258568234346338"),
field_new!(Fq, "19937756971775647987995932169929341994314640652964949448313374472400716661030"),
Fq2::new(
MontFp!("2581911344467009335267311115468803099551665605076196740867805258568234346338"),
MontFp!(
"19937756971775647987995932169929341994314640652964949448313374472400716661030"
),
),
// Fp2::NONRESIDUE^((2*(q^2) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "2203960485148121921418603742825762020974279258880205651966"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!("2203960485148121921418603742825762020974279258880205651966"),
Fq::ZERO,
),
// Fp2::NONRESIDUE^((2*(q^3) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "5324479202449903542726783395506214481928257762400643279780343368557297135718"),
field_new!(Fq, "16208900380737693084919495127334387981393726419856888799917914180988844123039"),
Fq2::new(
MontFp!("5324479202449903542726783395506214481928257762400643279780343368557297135718"),
MontFp!(
"16208900380737693084919495127334387981393726419856888799917914180988844123039"
),
),
// Fp2::NONRESIDUE^((2*(q^4) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "21888242871839275220042445260109153167277707414472061641714758635765020556616"),
field_new!(Fq, "0"),
Fq2::new(
MontFp!(
"21888242871839275220042445260109153167277707414472061641714758635765020556616"
),
Fq::ZERO,
),
// Fp2::NONRESIDUE^((2*(q^5) - 2) / 3)
field_new!(Fq2,
field_new!(Fq, "13981852324922362344252311234282257507216387789820983642040889267519694726527"),
field_new!(Fq, "7629828391165209371577384193250820201684255241773809077146787135900891633097"),
Fq2::new(
MontFp!(
"13981852324922362344252311234282257507216387789820983642040889267519694726527"
),
MontFp!("7629828391165209371577384193250820201684255241773809077146787135900891633097"),
),
];
#[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
fn mul_fp2_by_nonresidue_in_place(fe: &mut Fq2) -> &mut Fq2 {
// (c0+u*c1)*(9+u) = (9*c0-c1)+u*(9*c1+c0)
let mut f = *fe;
f.double_in_place().double_in_place().double_in_place();
let c0 = f.c0 + fe.c0 + Fq2Parameters::mul_fp_by_nonresidue(&fe.c1);
let mut c0 = fe.c1;
Fq2Config::mul_fp_by_nonresidue_in_place(&mut c0);
c0 += &f.c0;
c0 += &fe.c0;
let c1 = f.c1 + fe.c1 + fe.c0;
field_new!(Fq2, c0, c1)
*fe = Fq2::new(c0, c1);
fe
}
}

View File

@@ -1,95 +1,9 @@
use ark_ff::{biginteger::BigInteger256 as BigInteger, fields::*};
use ark_ff::fields::{Fp256, MontBackend, MontConfig};
pub type Fr = Fp256<FrParameters>;
pub struct FrParameters;
impl Fp256Parameters for FrParameters {}
impl FftParameters for FrParameters {
type BigInt = BigInteger;
const TWO_ADICITY: u32 = 28;
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
7164790868263648668u64,
11685701338293206998u64,
6216421865291908056u64,
1756667274303109607u64,
]);
}
impl FpParameters for FrParameters {
/// MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
4891460686036598785u64,
2896914383306846353u64,
13281191951274694749u64,
3486998266802970665u64,
]);
const MODULUS_BITS: u32 = 254;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
const REPR_SHAVE_BITS: u32 = 2;
#[rustfmt::skip]
const R: BigInteger = BigInteger([
12436184717236109307u64,
3962172157175319849u64,
7381016538464732718u64,
1011752739694698287u64,
]);
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
1997599621687373223u64,
6052339484930628067u64,
10108755138030829701u64,
150537098327114917u64,
]);
const INV: u64 = 14042775128853446655u64;
// GENERATOR = 5
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
1949230679015292902u64,
16913946402569752895u64,
5177146667339417225u64,
1571765431670520771u64,
]);
/// (r - 1)/2 =
/// 10944121435919637611123202872628637544274182200208017171849102093287904247808
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xa1f0fac9f8000000,
0x9419f4243cdcb848,
0xdc2822db40c0ac2e,
0x183227397098d014,
]);
// T and T_MINUS_ONE_DIV_TWO, where r - 1 = 2^s * t
/// t = (r - 1) / 2^s =
/// 81540058820840996586704275553141814055101440848469862132140264610111
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x9b9709143e1f593f,
0x181585d2833e8487,
0x131a029b85045b68,
0x30644e72e,
]);
/// (t - 1) / 2 =
/// 40770029410420498293352137776570907027550720424234931066070132305055
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xcdcb848a1f0fac9f,
0x0c0ac2e9419f4243,
0x098d014dc2822db4,
0x183227397,
]);
}
#[derive(MontConfig)]
#[modulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"]
#[generator = "5"]
#[small_subgroup_base = "3"]
#[small_subgroup_power = "2"]
pub struct FrConfig;
pub type Fr = Fp256<MontBackend<FrConfig, 4>>;

View File

@@ -1,123 +1,51 @@
use ark_algebra_test_templates::*;
use ark_ff::{
biginteger::{BigInteger, BigInteger256},
fields::{
fp6_3over2::Fp6Parameters, FftField, FftParameters, Field, FpParameters, PrimeField,
SquareRootField,
},
biginteger::{BigInt, BigInteger, BigInteger256},
fields::{FftField, Field, Fp6Config, PrimeField},
One, UniformRand, Zero,
};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use ark_std::rand::Rng;
use ark_std::test_rng;
use core::{
use ark_std::{
cmp::Ordering,
ops::{AddAssign, MulAssign, SubAssign},
ops::{AddAssign, MulAssign},
};
use crate::{Fq, Fq12, Fq2, Fq6, Fq6Parameters, FqParameters, Fr};
use ark_algebra_test_templates::fields::*;
use crate::{Fq, Fq12, Fq2, Fq6, Fq6Config, Fr};
pub(crate) const ITERATIONS: usize = 5;
#[test]
fn test_fr() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fr = rng.gen();
let b: Fr = rng.gen();
field_test(a, b);
primefield_test::<Fr>();
sqrt_field_test(b);
let byte_size = a.serialized_size();
field_serialization_test::<Fr>(byte_size);
}
}
#[test]
fn test_fq() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq = rng.gen();
let b: Fq = rng.gen();
field_test(a, b);
primefield_test::<Fq>();
sqrt_field_test(a);
let byte_size = a.serialized_size();
let (_, buffer_size) = buffer_bit_byte_size(Fq::size_in_bits());
assert_eq!(byte_size, buffer_size);
field_serialization_test::<Fq>(byte_size);
}
}
#[test]
fn test_fq2() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let a: Fq2 = rng.gen();
let b: Fq2 = rng.gen();
field_test(a, b);
sqrt_field_test(a);
}
frobenius_test::<Fq2, _>(Fq::characteristic(), 13);
let byte_size = Fq2::zero().serialized_size();
field_serialization_test::<Fq2>(byte_size);
}
#[test]
fn test_fq6() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq6 = rng.gen();
let h: Fq6 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq6, _>(Fq::characteristic(), 13);
let byte_size = Fq6::zero().serialized_size();
field_serialization_test::<Fq6>(byte_size);
}
#[test]
fn test_fq12() {
let mut rng = test_rng();
for _ in 0..ITERATIONS {
let g: Fq12 = rng.gen();
let h: Fq12 = rng.gen();
field_test(g, h);
}
frobenius_test::<Fq12, _>(Fq::characteristic(), 13);
let byte_size = Fq12::zero().serialized_size();
field_serialization_test::<Fq12>(byte_size);
}
test_field!(fr; Fr; mont_prime_field);
test_field!(fq; Fq; mont_prime_field);
test_field!(fq2; Fq2);
test_field!(fq6; Fq6);
test_field!(fq12; Fq12);
#[test]
fn test_fq_repr_from() {
assert_eq!(BigInteger256::from(100), BigInteger256([100, 0, 0, 0]));
assert_eq!(BigInteger256::from(100u64), BigInt::new([100, 0, 0, 0]));
}
#[test]
fn test_fq_repr_is_odd() {
assert!(!BigInteger256::from(0).is_odd());
assert!(BigInteger256::from(0).is_even());
assert!(BigInteger256::from(1).is_odd());
assert!(!BigInteger256::from(1).is_even());
assert!(!BigInteger256::from(324834872).is_odd());
assert!(BigInteger256::from(324834872).is_even());
assert!(BigInteger256::from(324834873).is_odd());
assert!(!BigInteger256::from(324834873).is_even());
assert!(!BigInteger256::from(0u64).is_odd());
assert!(BigInteger256::from(0u64).is_even());
assert!(BigInteger256::from(1u64).is_odd());
assert!(!BigInteger256::from(1u64).is_even());
assert!(!BigInteger256::from(324834872u64).is_odd());
assert!(BigInteger256::from(324834872u64).is_even());
assert!(BigInteger256::from(324834873u64).is_odd());
assert!(!BigInteger256::from(324834873u64).is_even());
}
#[test]
fn test_fq_repr_is_zero() {
assert!(BigInteger256::from(0).is_zero());
assert!(!BigInteger256::from(1).is_zero());
assert!(!BigInteger256([0, 0, 1, 0]).is_zero());
assert!(BigInteger256::from(0u64).is_zero());
assert!(!BigInteger256::from(1u64).is_zero());
assert!(!BigInt::new([0, 0, 1, 0]).is_zero());
}
#[test]
fn test_fq_repr_num_bits() {
let mut a = BigInteger256::from(0);
let mut a = BigInteger256::from(0u64);
assert_eq!(0, a.num_bits());
a = BigInteger256::from(1);
a = BigInteger256::from(1u64);
for i in 1..257 {
assert_eq!(i, a.num_bits());
a.mul2();
@@ -125,248 +53,35 @@ fn test_fq_repr_num_bits() {
assert_eq!(0, a.num_bits());
}
#[test]
fn test_fq_add_assign() {
// Test associativity
let mut rng = ark_std::test_rng();
for _ in 0..1000 {
// Generate a, b, c and ensure (a + b) + c == a + (b + c).
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
let mut tmp2 = b;
tmp2.add_assign(&c);
tmp2.add_assign(&a);
assert_eq!(tmp1, tmp2);
}
}
#[test]
fn test_fq_sub_assign() {
let mut rng = ark_std::test_rng();
for _ in 0..1000 {
// Ensure that (a - b) + (b - a) = 0.
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.sub_assign(&b);
let mut tmp2 = b;
tmp2.sub_assign(&a);
tmp1.add_assign(&tmp2);
assert!(tmp1.is_zero());
}
}
#[test]
fn test_fq_mul_assign() {
let mut rng = ark_std::test_rng();
for _ in 0..1000000 {
// Ensure that (a * b) * c = a * (b * c)
let a = Fq::rand(&mut rng);
let b = Fq::rand(&mut rng);
let c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.mul_assign(&b);
tmp1.mul_assign(&c);
let mut tmp2 = b;
tmp2.mul_assign(&c);
tmp2.mul_assign(&a);
assert_eq!(tmp1, tmp2);
}
for _ in 0..1000000 {
// Ensure that r * (a + b + c) = r*a + r*b + r*c
let r = Fq::rand(&mut rng);
let mut a = Fq::rand(&mut rng);
let mut b = Fq::rand(&mut rng);
let mut c = Fq::rand(&mut rng);
let mut tmp1 = a;
tmp1.add_assign(&b);
tmp1.add_assign(&c);
tmp1.mul_assign(&r);
a.mul_assign(&r);
b.mul_assign(&r);
c.mul_assign(&r);
a.add_assign(&b);
a.add_assign(&c);
assert_eq!(tmp1, a);
}
}
#[test]
fn test_fq_squaring() {
let mut rng = ark_std::test_rng();
for _ in 0..1000000 {
// Ensure that (a * a) = a^2
let a = Fq::rand(&mut rng);
let mut tmp = a;
tmp.square_in_place();
let mut tmp2 = a;
tmp2.mul_assign(&a);
assert_eq!(tmp, tmp2);
}
}
#[test]
fn test_fq_inverse() {
assert!(Fq::zero().inverse().is_none());
let mut rng = ark_std::test_rng();
let one = Fq::one();
for _ in 0..1000 {
// Ensure that a * a^-1 = 1
let mut a = Fq::rand(&mut rng);
let ainv = a.inverse().unwrap();
a.mul_assign(&ainv);
assert_eq!(a, one);
}
}
#[test]
fn test_fq_double_in_place() {
let mut rng = ark_std::test_rng();
for _ in 0..1000 {
// Ensure doubling a is equivalent to adding a to itself.
let mut a = Fq::rand(&mut rng);
let mut b = a;
b.add_assign(&a);
a.double_in_place();
assert_eq!(a, b);
}
}
#[test]
fn test_fq_negate() {
{
let a = -Fq::zero();
assert!(a.is_zero());
}
let mut rng = ark_std::test_rng();
for _ in 0..1000 {
// Ensure (a - (-a)) = 0.
let mut a = Fq::rand(&mut rng);
let b = -a;
a.add_assign(&b);
assert!(a.is_zero());
}
}
#[test]
fn test_fq_pow() {
let mut rng = ark_std::test_rng();
for i in 0..1000 {
// Exponentiate by various small numbers and ensure it consists with repeated
// multiplication.
let a = Fq::rand(&mut rng);
let target = a.pow(&[i]);
let mut c = Fq::one();
for _ in 0..i {
c.mul_assign(&a);
}
assert_eq!(c, target);
}
for _ in 0..1000 {
// Exponentiating by the modulus should have no effect in a prime field.
let a = Fq::rand(&mut rng);
assert_eq!(a, a.pow(Fq::characteristic()));
}
}
#[test]
fn test_fq_sqrt() {
let mut rng = ark_std::test_rng();
assert_eq!(Fq::zero().sqrt().unwrap(), Fq::zero());
for _ in 0..1000 {
// Ensure sqrt(a^2) = a or -a
let a = Fq::rand(&mut rng);
let nega = -a;
let mut b = a;
b.square_in_place();
let b = b.sqrt().unwrap();
assert!(a == b || nega == b);
}
for _ in 0..1000 {
// Ensure sqrt(a)^2 = a for random a
let a = Fq::rand(&mut rng);
if let Some(mut tmp) = a.sqrt() {
tmp.square_in_place();
assert_eq!(a, tmp);
}
}
}
#[test]
fn test_fq_num_bits() {
assert_eq!(FqParameters::MODULUS_BITS, 254);
assert_eq!(FqParameters::CAPACITY, 253);
assert_eq!(Fq::MODULUS_BIT_SIZE, 254);
}
#[test]
fn test_fq_root_of_unity() {
assert_eq!(FqParameters::TWO_ADICITY, 1);
assert_eq!(Fq::TWO_ADICITY, 1);
assert_eq!(
Fq::multiplicative_generator().pow([
Fq::GENERATOR.pow([
0x9e10460b6c3e7ea3,
0xcbc0b548b438e546,
0xdc2822db40c0ac2e,
0x183227397098d014,
]),
Fq::two_adic_root_of_unity()
Fq::TWO_ADIC_ROOT_OF_UNITY
);
assert_eq!(
Fq::two_adic_root_of_unity().pow([1 << FqParameters::TWO_ADICITY]),
Fq::TWO_ADIC_ROOT_OF_UNITY.pow([1 << Fq::TWO_ADICITY]),
Fq::one()
);
assert!(Fq::multiplicative_generator().sqrt().is_none());
assert!(Fq::GENERATOR.sqrt().is_none());
}
#[test]
fn test_fq_ordering() {
// BigInteger256's ordering is well-tested, but we still need to make sure the
// Fq elements aren't being compared in Montgomery form.
for i in 0..100 {
for i in 0..100u64 {
assert!(Fq::from(BigInteger256::from(i + 1)) > Fq::from(BigInteger256::from(i)));
}
}
@@ -379,11 +94,11 @@ fn test_fq_legendre() {
assert_eq!(Zero, Fq::zero().legendre());
assert_eq!(
QuadraticResidue,
Fq::from(BigInteger256::from(4)).legendre()
Fq::from(BigInteger256::from(4u64)).legendre()
);
assert_eq!(
QuadraticNonResidue,
Fq::from(BigInteger256::from(5)).legendre()
Fq::from(BigInteger256::from(5u64)).legendre()
);
}
@@ -424,7 +139,7 @@ fn test_fq2_legendre() {
// i^2 = -1
let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Parameters::mul_fp2_by_nonresidue(&m1);
Fq6Config::mul_fp2_by_nonresidue_in_place(&mut m1);
assert_eq!(QuadraticNonResidue, m1.legendre());
}

11
bn254/src/lib.rs Normal file → Executable file
View File

@@ -20,14 +20,17 @@
//!
//!
//! Curve information:
//! * Base field: q = 21888242871839275222246405745257275088696311157297823662689037894645226208583
//! * Scalar field: r = 21888242871839275222246405745257275088548364400416034343698204186575808495617
//! * Base field: q =
//! 21888242871839275222246405745257275088696311157297823662689037894645226208583
//! * Scalar field: r =
//! 21888242871839275222246405745257275088548364400416034343698204186575808495617
//! * valuation(q - 1, 2) = 1
//! * valuation(r - 1, 2) = 28
//! * G1 curve equation: y^2 = x^3 + 3
//! * G2 curve equation: y^2 = x^3 + B, where
//! * B = 3/(u+9) where Fq2\[u\]=Fq/u+1
//! = Fq2(19485874751759354771024239261021720505790618469301721065564631296452457478373, 266929791119991161246907387137283842545076965332900288569378510910307636690)
//! * B = 3/(u+9) where Fq2 is represented as Fq\[u\]/(u^2+1) =
//! Fq2(19485874751759354771024239261021720505790618469301721065564631296452457478373,
//! 266929791119991161246907387137283842545076965332900288569378510910307636690)
#[cfg(feature = "curve")]
mod curves;

View File

@@ -1,27 +1,33 @@
[package]
name = "ark-bw6-761"
version = "0.1.0"
version = "0.4.0"
authors = [ "arkworks contributors" ]
description = "The BW6-761 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/algebra"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/ark-bw6-761/"
keywords = ["cryptography", "finite fields", "elliptic curves" ]
keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2018"
edition = "2021"
[dependencies]
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
ark-bls12-377 = { path = "../bls12_377", default-features = false, features = [ "base_field" ] }
ark-ff = { version= "0.4.0", default-features = false }
ark-ec = { version= "0.4.0", default-features = false }
ark-std = { version = "0.4.0", default-features = false }
ark-bls12-377 = { version = "0.4.0", path = "../bls12_377", default-features = false, features = [ "base_field" ] }
[dev-dependencies]
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-algebra-test-templates = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-serialize = { version = "0.4.0", default-features = false }
ark-algebra-test-templates = { version = "0.4.0", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0", default-features = false }
[features]
default = []
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-377/std" ]
[[bench]]
name = "bw6_761"
path = "benches/bw6_761.rs"
harness = false

View File

@@ -0,0 +1,16 @@
use ark_algebra_bench_templates::*;
use ark_bw6_761::{
fq::Fq, fq3::Fq3, fq6::Fq6, fr::Fr, g1::G1Projective as G1, g2::G2Projective as G2, BW6_761,
};
bench!(
Name = "BW6_761",
Pairing = BW6_761,
G1 = G1,
G2 = G2,
ScalarField = Fr,
G1BaseField = Fq,
G2BaseField = Fq3,
TargetField = Fq6,
);

View File

@@ -0,0 +1,28 @@
modulus = 6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -0,0 +1,28 @@
modulus = 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -1,30 +1,21 @@
use crate::{Fq, Fr};
use ark_ec::{
models::{ModelParameters, SWModelParameters},
short_weierstrass_jacobian::{GroupAffine, GroupProjective},
models::{short_weierstrass::SWCurveConfig, CurveConfig},
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective},
};
use ark_ff::field_new;
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField};
pub type G1Affine = GroupAffine<Parameters>;
pub type G1Projective = GroupProjective<Parameters>;
use crate::{Fq, Fr};
pub type G1Affine = Affine<Config>;
pub type G1Projective = Projective<Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
pub struct Config;
impl ModelParameters for Parameters {
impl CurveConfig for Config {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
#[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, "0");
/// COEFF_B = -1
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, "-1");
/// COFACTOR =
/// 26642435879335816683987677701488073867751118270052650655942102502312977592501693353047140953112195348280268661194876
@@ -40,25 +31,69 @@ impl SWModelParameters for Parameters {
/// COFACTOR^(-1) mod r =
/// 91141326767669940707819291241958318717982251277713150053234367522357946997763584490607453720072232540829942217804
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, "91141326767669940707819291241958318717982251277713150053234367522357946997763584490607453720072232540829942217804");
const COFACTOR_INV: Fr = MontFp!("91141326767669940707819291241958318717982251277713150053234367522357946997763584490607453720072232540829942217804");
}
impl SWCurveConfig for Config {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = -1
const COEFF_B: Fq = MontFp!("-1");
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G1_GENERATOR_X, G1_GENERATOR_Y);
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_elem: &Self::BaseField) -> Self::BaseField {
fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField {
use ark_ff::Zero;
Self::BaseField::zero()
}
}
impl GLVConfig for Config {
const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
"4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"
)];
const LAMBDA: Self::ScalarField =
MontFp!("258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(
true,
BigInt!("293634935485640680722085584138834120324914961969255022593"),
),
(
false,
BigInt!("293634935485640680722085584138834120315328839056164388863"),
),
(
true,
BigInt!("293634935485640680722085584138834120315328839056164388863"),
),
(
true,
BigInt!("587269870971281361444171168277668240640243801025419411456"),
),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
/// G1_GENERATOR_X =
/// 6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237
#[rustfmt::skip]
pub const G1_GENERATOR_X: Fq = field_new!(Fq, "6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237");
pub const G1_GENERATOR_X: Fq = MontFp!("6238772257594679368032145693622812838779005809760824733138787810501188623461307351759238099287535516224314149266511977132140828635950940021790489507611754366317801811090811367945064510304504157188661901055903167026722666149426237");
/// G1_GENERATOR_Y =
/// 2101735126520897423911504562215834951148127555913367997162789335052900271653517958562461315794228241561913734371411178226936527683203879553093934185950470971848972085321797958124416462268292467002957525517188485984766314758624099
#[rustfmt::skip]
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, "2101735126520897423911504562215834951148127555913367997162789335052900271653517958562461315794228241561913734371411178226936527683203879553093934185950470971848972085321797958124416462268292467002957525517188485984766314758624099");
pub const G1_GENERATOR_Y: Fq = MontFp!("2101735126520897423911504562215834951148127555913367997162789335052900271653517958562461315794228241561913734371411178226936527683203879553093934185950470971848972085321797958124416462268292467002957525517188485984766314758624099");

View File

@@ -1,30 +1,21 @@
use crate::{Fq, Fr};
use ark_ec::{
models::{ModelParameters, SWModelParameters},
short_weierstrass_jacobian::{GroupAffine, GroupProjective},
models::{short_weierstrass::SWCurveConfig, CurveConfig},
scalar_mul::glv::GLVConfig,
short_weierstrass::{Affine, Projective},
};
use ark_ff::field_new;
use ark_ff::{AdditiveGroup, BigInt, MontFp, PrimeField};
pub type G2Affine = GroupAffine<Parameters>;
pub type G2Projective = GroupProjective<Parameters>;
use crate::{Fq, Fr};
pub type G2Affine = Affine<Config>;
pub type G2Projective = Projective<Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Parameters;
pub struct Config;
impl ModelParameters for Parameters {
impl CurveConfig for Config {
type BaseField = Fq;
type ScalarField = Fr;
}
impl SWModelParameters for Parameters {
/// COEFF_A = 0
#[rustfmt::skip]
const COEFF_A: Fq = field_new!(Fq, "0");
/// COEFF_B = 4
#[rustfmt::skip]
const COEFF_B: Fq = field_new!(Fq, "4");
/// COFACTOR =
/// 26642435879335816683987677701488073867751118270052650655942102502312977592501693353047140953112195348280268661194869
@@ -40,25 +31,70 @@ impl SWModelParameters for Parameters {
/// COFACTOR^(-1) mod r =
/// 214911522365886453591244899095480747723790054550866810551297776298664428889000553861210287833206024638187939842124
#[rustfmt::skip]
const COFACTOR_INV: Fr = field_new!(Fr, "214911522365886453591244899095480747723790054550866810551297776298664428889000553861210287833206024638187939842124");
const COFACTOR_INV: Fr = MontFp!("214911522365886453591244899095480747723790054550866810551297776298664428889000553861210287833206024638187939842124");
}
impl SWCurveConfig for Config {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = 4
const COEFF_B: Fq = MontFp!("4");
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) =
(G2_GENERATOR_X, G2_GENERATOR_Y);
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_elem: &Self::BaseField) -> Self::BaseField {
fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField {
use ark_ff::Zero;
Self::BaseField::zero()
}
}
impl GLVConfig for Config {
const ENDO_COEFFS: &'static [Self::BaseField] = &[
MontFp!("4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"),
];
const LAMBDA: Self::ScalarField =
MontFp!("80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945");
const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
(
true,
BigInt!("293634935485640680722085584138834120315328839056164388863"),
),
(
false,
BigInt!("293634935485640680722085584138834120324914961969255022593"),
),
(
true,
BigInt!("293634935485640680722085584138834120324914961969255022593"),
),
(
true,
BigInt!("587269870971281361444171168277668240640243801025419411456"),
),
];
fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
let mut res = (*p).clone();
res.x *= Self::ENDO_COEFFS[0];
res
}
}
/// G2_GENERATOR_X =
/// 6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428
#[rustfmt::skip]
pub const G2_GENERATOR_X: Fq = field_new!(Fq, "6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428");
pub const G2_GENERATOR_X: Fq = MontFp!("6445332910596979336035888152774071626898886139774101364933948236926875073754470830732273879639675437155036544153105017729592600560631678554299562762294743927912429096636156401171909259073181112518725201388196280039960074422214428");
/// G2_GENERATOR_Y =
/// 562923658089539719386922163444547387757586534741080263946953401595155211934630598999300396317104182598044793758153214972605680357108252243146746187917218885078195819486220416605630144001533548163105316661692978285266378674355041
#[rustfmt::skip]
pub const G2_GENERATOR_Y: Fq = field_new!(Fq, "562923658089539719386922163444547387757586534741080263946953401595155211934630598999300396317104182598044793758153214972605680357108252243146746187917218885078195819486220416605630144001533548163105316661692978285266378674355041");
pub const G2_GENERATOR_Y: Fq = MontFp!("562923658089539719386922163444547387757586534741080263946953401595155211934630598999300396317104182598044793758153214972605680357108252243146746187917218885078195819486220416605630144001533548163105316661692978285266378674355041");

View File

@@ -1,9 +1,12 @@
use crate::*;
use ark_ec::{
bw6,
bw6::{BW6Parameters, TwistType, BW6},
bw6::{BW6Config, TwistType, BW6},
};
use ark_ff::biginteger::BigInteger768 as BigInteger;
use ark_ff::{
biginteger::BigInteger768 as BigInteger, fp6_2over3::Fp6, BigInt, CyclotomicMultSubgroup, Field,
};
use crate::*;
pub mod g1;
pub mod g2;
@@ -12,50 +15,149 @@ pub mod g2;
mod tests;
#[derive(PartialEq, Eq)]
pub struct Parameters;
pub struct Config;
impl BW6Parameters for Parameters {
const X: BigInteger = BigInteger([
0x8508c00000000001,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
]);
impl BW6Config for Config {
const X: BigInteger = BigInt!("0x8508c00000000001");
/// `x` is positive.
const X_IS_NEGATIVE: bool = false;
// X
const ATE_LOOP_COUNT_1: &'static [u64] = &[0x8508c00000000001];
// (X-1)/3
const X_MINUS_1_DIV_3: BigInteger = BigInt!("0x2c58400000000000");
// X+1
const ATE_LOOP_COUNT_1: &'static [u64] = &[0x8508c00000000002];
const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = false;
// X^3-X^2-X
// X^2-X-1
const ATE_LOOP_COUNT_2: &'static [i8] = &[
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, -1, 0, 0,
1, 0, 0, 0, -1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, -1, 0, 1, 0, 1, 0, 0, 0, 1,
0, -1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
0, 1, 0, 1, 0, 0, 0, 1,
];
const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false;
const TWIST_TYPE: TwistType = TwistType::M;
const H_T: i64 = 13;
const H_Y: i64 = 9;
const T_MOD_R_IS_ZERO: bool = false;
type Fp = Fq;
type Fp3Params = Fq3Parameters;
type Fp6Params = Fq6Parameters;
type G1Parameters = g1::Parameters;
type G2Parameters = g2::Parameters;
type Fp3Config = Fq3Config;
type Fp6Config = Fq6Config;
type G1Config = g1::Config;
type G2Config = g2::Config;
fn final_exponentiation_hard_part(f: &Fp6<Self::Fp6Config>) -> Fp6<Self::Fp6Config> {
// hard_part
// From https://eprint.iacr.org/2020/351.pdf, Alg.6
#[rustfmt::skip]
// R0(x) := (-103*x^7 + 70*x^6 + 269*x^5 - 197*x^4 - 314*x^3 - 73*x^2 - 263*x - 220)
// R1(x) := (103*x^9 - 276*x^8 + 77*x^7 + 492*x^6 - 445*x^5 - 65*x^4 + 452*x^3 - 181*x^2 + 34*x + 229)
// f ^ R0(u) * (f ^ q) ^ R1(u) in a 2-NAF multi-exp fashion.
// steps 1,2,3
let f0 = *f;
let mut f0p = f0;
f0p.frobenius_map_in_place(1);
let f1 = Self::exp_by_x(&f0);
let mut f1p = f1;
f1p.frobenius_map_in_place(1);
let f2 = Self::exp_by_x(&f1);
let mut f2p = f2;
f2p.frobenius_map_in_place(1);
let f3 = Self::exp_by_x(&f2);
let mut f3p = f3;
f3p.frobenius_map_in_place(1);
let f4 = Self::exp_by_x(&f3);
let mut f4p = f4;
f4p.frobenius_map_in_place(1);
let f5 = Self::exp_by_x(&f4);
let mut f5p = f5;
f5p.frobenius_map_in_place(1);
let f6 = Self::exp_by_x(&f5);
let mut f6p = f6;
f6p.frobenius_map_in_place(1);
let f7 = Self::exp_by_x(&f6);
let mut f7p = f7;
f7p.frobenius_map_in_place(1);
// step 4
let f8p = Self::exp_by_x(&f7p);
let f9p = Self::exp_by_x(&f8p);
// step 5
let mut f5p_p3 = f5p;
f5p_p3.cyclotomic_inverse_in_place();
let result1 = f3p * &f6p * &f5p_p3;
// step 6
let result2 = result1.square();
let f4_2p = f4 * &f2p;
let mut tmp1_p3 = f0 * &f1 * &f3 * &f4_2p * &f8p;
tmp1_p3.cyclotomic_inverse_in_place();
let result3 = result2 * &f5 * &f0p * &tmp1_p3;
// step 7
let result4 = result3.square();
let mut f7_p3 = f7;
f7_p3.cyclotomic_inverse_in_place();
let result5 = result4 * &f9p * &f7_p3;
// step 8
let result6 = result5.square();
let f2_4p = f2 * &f4p;
let f4_2p_5p = f4_2p * &f5p;
let mut tmp2_p3 = f2_4p * &f3 * &f3p;
tmp2_p3.cyclotomic_inverse_in_place();
let result7 = result6 * &f4_2p_5p * &f6 * &f7p * &tmp2_p3;
// step 9
let result8 = result7.square();
let mut tmp3_p3 = f0p * &f9p;
tmp3_p3.cyclotomic_inverse_in_place();
let result9 = result8 * &f0 * &f7 * &f1p * &tmp3_p3;
// step 10
let result10 = result9.square();
let f6p_8p = f6p * &f8p;
let f5_7p = f5 * &f7p;
let mut tmp4_p3 = f6p_8p;
tmp4_p3.cyclotomic_inverse_in_place();
let result11 = result10 * &f5_7p * &f2p * &tmp4_p3;
// step 11
let result12 = result11.square();
let f3_6 = f3 * &f6;
let f1_7 = f1 * &f7;
let mut tmp5_p3 = f1_7 * &f2;
tmp5_p3.cyclotomic_inverse_in_place();
let result13 = result12 * &f3_6 * &f9p * &tmp5_p3;
// step 12
let result14 = result13.square();
let mut tmp6_p3 = f4_2p * &f5_7p * &f6p_8p;
tmp6_p3.cyclotomic_inverse_in_place();
let result15 = result14 * &f0 * &f0p * &f3p * &f5p * &tmp6_p3;
// step 13
let result16 = result15.square();
let mut tmp7_p3 = f3_6;
tmp7_p3.cyclotomic_inverse_in_place();
let result17 = result16 * &f1p * &tmp7_p3;
// step 14
let result18 = result17.square();
let mut tmp8_p3 = f2_4p * &f4_2p_5p * &f9p;
tmp8_p3.cyclotomic_inverse_in_place();
let result19 = result18 * &f1_7 * &f5_7p * &f0p * &tmp8_p3;
result19
}
}
pub type BW6_761 = BW6<Parameters>;
pub type BW6_761 = BW6<Config>;
pub type G1Affine = bw6::G1Affine<Parameters>;
pub type G1Projective = bw6::G1Projective<Parameters>;
pub type G2Affine = bw6::G2Affine<Parameters>;
pub type G2Projective = bw6::G2Projective<Parameters>;
pub type G1Affine = bw6::G1Affine<Config>;
pub type G1Projective = bw6::G1Projective<Config>;
pub type G2Affine = bw6::G2Affine<Config>;
pub type G2Projective = bw6::G2Projective<Config>;

View File

@@ -1,78 +1,10 @@
use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{Field, One, PrimeField};
use ark_std::rand::Rng;
use ark_std::test_rng;
use crate::*;
use ark_algebra_test_templates::*;
use ark_ff::Field;
use ark_algebra_test_templates::{curves::*, groups::*};
#[test]
fn test_g1_projective_curve() {
curve_tests::<G1Projective>();
sw_tests::<g1::Parameters>();
}
#[test]
fn test_g1_projective_group() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g1_generator() {
let generator = G1Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_g2_projective_curve() {
curve_tests::<G2Projective>();
sw_tests::<g2::Parameters>();
}
#[test]
fn test_g2_projective_group() {
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
group_test(a, b);
}
#[test]
fn test_g2_generator() {
let generator = G2Affine::prime_subgroup_generator();
assert!(generator.is_on_curve());
assert!(generator.is_in_correct_subgroup_assuming_on_curve());
}
#[test]
fn test_bilinearity() {
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G2Projective = rng.gen();
let s: Fr = rng.gen();
let sa = a.mul(s.into_repr());
let sb = b.mul(s.into_repr());
let ans1 = BW6_761::pairing(sa, b);
let ans2 = BW6_761::pairing(a, sb);
let ans3 = BW6_761::pairing(a, b).pow(s.into_repr());
assert_eq!(ans1, ans2);
assert_eq!(ans2, ans3);
assert_ne!(ans1, Fq6::one());
assert_ne!(ans2, Fq6::one());
assert_ne!(ans3, Fq6::one());
assert_eq!(ans1.pow(Fr::characteristic()), Fq6::one());
assert_eq!(ans2.pow(Fr::characteristic()), Fq6::one());
assert_eq!(ans3.pow(Fr::characteristic()), Fq6::one());
}
test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_761>; msm);
test_pairing!(pairing; crate::BW6_761);
test_group!(g1_glv; G1Projective; glv);
test_group!(g2_glv; G2Projective; glv);

View File

@@ -1,175 +1,7 @@
use ark_ff::{
biginteger::BigInteger768 as BigInteger,
field_new,
fields::{FftParameters, Fp768, Fp768Parameters, FpParameters},
};
use ark_ff::fields::{Fp768, MontBackend, MontConfig};
pub type Fq = Fp768<FqParameters>;
pub struct FqParameters;
pub const FQ_ONE: Fq = field_new!(Fq, "1");
pub const FQ_ZERO: Fq = field_new!(Fq, "0");
impl Fp768Parameters for FqParameters {}
impl FftParameters for FqParameters {
type BigInt = BigInteger;
// The internal representation of this type is six 64-bit unsigned
// integers in little-endian order. Values are always in
// Montgomery form; i.e., Scalar(a) = aR mod p, with R=2^768.
// (MODULUS - 1) % 2^TWO_ADICITY == 0
const TWO_ADICITY: u32 = 1;
// least_quadratic_nonresidue(MODULUS) in Sage.
#[rustfmt::skip]
const TWO_ADIC_ROOT_OF_UNITY: BigInteger = BigInteger([
17481284903592032950u64,
10104133845767975835u64,
8607375506753517913u64,
13706168424391191299u64,
9580010308493592354u64,
14241333420363995524u64,
6665632285037357566u64,
5559902898979457045u64,
15504799981718861253u64,
8332096944629367896u64,
18005297320867222879u64,
58811391084848524u64,
]);
}
impl FpParameters for FqParameters {
/// MODULUS = 6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299
#[rustfmt::skip]
const MODULUS: BigInteger = BigInteger([
0xf49d00000000008b,
0xe6913e6870000082,
0x160cf8aeeaf0a437,
0x98a116c25667a8f8,
0x71dcd3dc73ebff2e,
0x8689c8ed12f9fd90,
0x03cebaff25b42304,
0x707ba638e584e919,
0x528275ef8087be41,
0xb926186a81d14688,
0xd187c94004faff3e,
0x122e824fb83ce0a
]);
const MODULUS_BITS: u32 = 761;
const CAPACITY: u32 = Self::MODULUS_BITS - 1;
// gap to 64-bit machine word
const REPR_SHAVE_BITS: u32 = 7;
// 2^768 % MODULUS
#[rustfmt::skip]
const R: BigInteger = BigInteger([
144959613005956565u64,
6509995272855063783u64,
11428286765660613342u64,
15738672438262922740u64,
17071399330169272331u64,
13899911246788437003u64,
12055474021000362245u64,
2545351818702954755u64,
8887388221587179644u64,
5009280847225881135u64,
15539704305423854047u64,
23071597697427581u64,
]);
// R^2
#[rustfmt::skip]
const R2: BigInteger = BigInteger([
14305184132582319705u64,
8868935336694416555u64,
9196887162930508889u64,
15486798265448570248u64,
5402985275949444416u64,
10893197322525159598u64,
3204916688966998390u64,
12417238192559061753u64,
12426306557607898622u64,
1305582522441154384u64,
10311846026977660324u64,
48736111365249031u64,
]);
// (-1/MODULUS) % 2^64
const INV: u64 = 744663313386281181u64;
/// GENERATOR = 2
// primitive_root(MODULUS)
#[rustfmt::skip]
const GENERATOR: BigInteger = BigInteger([
289919226011913130u64,
13019990545710127566u64,
4409829457611675068u64,
13030600802816293865u64,
15696054586628993047u64,
9353078419867322391u64,
5664203968291172875u64,
5090703637405909511u64,
17774776443174359288u64,
10018561694451762270u64,
12632664537138156478u64,
46143195394855163u64,
]);
// (MODULUS - 1) / 2
#[rustfmt::skip]
const MODULUS_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0x7a4e800000000045,
0xf3489f3438000041,
0x0b067c577578521b,
0x4c508b612b33d47c,
0x38ee69ee39f5ff97,
0x4344e476897cfec8,
0x81e75d7f92da1182,
0xb83dd31c72c2748c,
0x29413af7c043df20,
0x5c930c3540e8a344,
0x68c3e4a0027d7f9f,
0x9174127dc1e705,
]);
// T =
// 3445725192157866269698394841137828771239834456268075054756895080104811711121745868043841591644705843820432283876893306725580879560277123879674755849562650799475802549689254425186271815711798397975949850214984556421382456559534149
// (MODULUS - 1) / 2 ^ TWO_ADICITY
#[rustfmt::skip]
const T: BigInteger = BigInteger([
0x7a4e800000000045,
0xf3489f3438000041,
0x0b067c577578521b,
0x4c508b612b33d47c,
0x38ee69ee39f5ff97,
0x4344e476897cfec8,
0x81e75d7f92da1182,
0xb83dd31c72c2748c,
0x29413af7c043df20,
0x5c930c3540e8a344,
0x68c3e4a0027d7f9f,
0x9174127dc1e705,
]);
// (T - 1)/2 =
// 1722862596078933134849197420568914385619917228134037527378447540052405855560872934021920795822352921910216141938446653362790439780138561939837377924781325399737901274844627212593135907855899198987974925107492278210691228279767074
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: BigInteger = BigInteger([
0xbd27400000000022,
0xf9a44f9a1c000020,
0x05833e2bbabc290d,
0xa62845b09599ea3e,
0x1c7734f71cfaffcb,
0x21a2723b44be7f64,
0x40f3aebfc96d08c1,
0x5c1ee98e39613a46,
0x14a09d7be021ef90,
0xae49861aa07451a2,
0xb461f250013ebfcf,
0x48ba093ee0f382,
]);
}
#[derive(MontConfig)]
#[modulus = "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299"]
#[generator = "2"]
pub struct FqConfig;
pub type Fq = Fp768<MontBackend<FqConfig, 12>>;

View File

@@ -1,31 +1,27 @@
use ark_ff::{
field_new,
fields::fp3::{Fp3, Fp3Parameters},
fields::fp3::{Fp3, Fp3Config},
AdditiveGroup, Field, MontFp,
};
use crate::{
fields::{FQ_ONE, FQ_ZERO},
Fq,
};
use crate::Fq;
pub type Fq3 = Fp3<Fq3Parameters>;
pub type Fq3 = Fp3<Fq3Config>;
pub struct Fq3Parameters;
pub struct Fq3Config;
impl Fp3Parameters for Fq3Parameters {
impl Fp3Config for Fq3Config {
type Fp = Fq;
/// NONRESIDUE = -4
// Fq3 = Fq\[u\]/u^3+4
#[rustfmt::skip]
const NONRESIDUE: Fq = field_new!(Fq, "-4");
const NONRESIDUE: Fq = MontFp!("-4");
// (MODULUS^3 - 1) % 2^TWO_ADICITY == 0
const TWO_ADICITY: u32 = 1;
// (T-1)/2 with T = (MODULUS^3-1) / 2^TWO_ADICITY
#[rustfmt::skip]
const T_MINUS_ONE_DIV_TWO: &'static [u64] = &[
const TRACE_MINUS_ONE_DIV_TWO: &'static [u64] = &[
0xb5e7c000000a3eac,
0xf79b99dbf41cf4ab,
0xe9372b1919e55ee5,
@@ -65,33 +61,28 @@ impl Fp3Parameters for Fq3Parameters {
];
// NONRESIDUE^T % q
#[rustfmt::skip]
const QUADRATIC_NONRESIDUE_TO_T: (Fq, Fq, Fq) = (
field_new!(Fq, "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298"),
FQ_ZERO,
FQ_ZERO,
const QUADRATIC_NONRESIDUE_TO_T: Fq3 = Fq3::new(
MontFp!("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298"),
Fq::ZERO,
Fq::ZERO,
);
// NQR ^ (MODULUS^i - 1)/3, i=0,1,2 with NQR = u = (0,1,0)
#[rustfmt::skip]
const FROBENIUS_COEFF_FP3_C1: &'static [Fq] = &[
FQ_ONE,
field_new!(Fq, "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"),
field_new!(Fq, "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650"),
Fq::ONE,
MontFp!("4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"),
MontFp!("1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650"),
];
// NQR ^ (2*MODULUS^i - 2)/3, i=0,1,2 with NQR = u = (0,1,0)
#[rustfmt::skip]
const FROBENIUS_COEFF_FP3_C2: &'static [Fq] = &[
FQ_ONE,
field_new!(Fq, "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650"),
field_new!(Fq, "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"),
Fq::ONE,
MontFp!("1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650"),
MontFp!("4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"),
];
#[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
let original = -(*fe);
let double = original + &original;
double + &double
fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
fe.double_in_place().double_in_place().neg_in_place()
}
}

View File

@@ -1,27 +1,26 @@
use crate::{Fq, Fq3, Fq3Parameters, FQ_ONE, FQ_ZERO};
use ark_ff::{
field_new,
fields::fp6_2over3::{Fp6, Fp6Parameters},
fields::fp6_2over3::{Fp6, Fp6Config},
AdditiveGroup, Field, MontFp,
};
pub type Fq6 = Fp6<Fq6Parameters>;
use crate::{Fq, Fq3, Fq3Config};
pub struct Fq6Parameters;
pub type Fq6 = Fp6<Fq6Config>;
impl Fp6Parameters for Fq6Parameters {
type Fp3Params = Fq3Parameters;
pub struct Fq6Config;
impl Fp6Config for Fq6Config {
type Fp3Config = Fq3Config;
/// NONRESIDUE = (0, 1, 0)
#[rustfmt::skip]
const NONRESIDUE: Fq3 = field_new!(Fq3, FQ_ZERO, FQ_ONE, FQ_ZERO);
const NONRESIDUE: Fq3 = Fq3::new(Fq::ZERO, Fq::ONE, Fq::ZERO);
#[rustfmt::skip]
const FROBENIUS_COEFF_FP6_C1: &'static [Fq] = &[
field_new!(Fq, "1"),
field_new!(Fq, "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649"),
field_new!(Fq, "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"),
field_new!(Fq, "-1"),
field_new!(Fq, "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650"),
field_new!(Fq, "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292651"),
Fq::ONE,
MontFp!("4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649"),
MontFp!("4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648"),
MontFp!("-1"),
MontFp!("1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650"),
MontFp!("1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292651"),
];
}

View File

@@ -1 +1 @@
pub use ark_bls12_377::{Fq as Fr, FqParameters as FrParameters};
pub use ark_bls12_377::{Fq as Fr, FqConfig as FrConfig};

View File

@@ -1,52 +1,7 @@
use ark_ff::{Field, PrimeField};
use ark_serialize::{buffer_bit_byte_size, CanonicalSerialize};
use ark_std::rand::Rng;
use ark_std::test_rng;
use crate::*;
use ark_algebra_test_templates::*;
use ark_algebra_test_templates::fields::*;
#[test]
fn test_fr() {
let mut rng = test_rng();
let a: Fr = rng.gen();
let b: Fr = rng.gen();
field_test(a, b);
sqrt_field_test(a);
primefield_test::<Fr>();
}
#[test]
fn test_fq() {
let mut rng = test_rng();
let a: Fq = rng.gen();
let b: Fq = rng.gen();
field_test(a, b);
primefield_test::<Fq>();
sqrt_field_test(a);
let byte_size = a.serialized_size();
let (_, buffer_size) = buffer_bit_byte_size(Fq::size_in_bits());
assert_eq!(byte_size, buffer_size);
field_serialization_test::<Fq>(byte_size);
}
#[test]
fn test_fq3() {
let mut rng = test_rng();
let a: Fq3 = rng.gen();
let b: Fq3 = rng.gen();
field_test(a, b);
sqrt_field_test(a);
frobenius_test::<Fq3, _>(Fq::characteristic(), 13);
}
#[test]
fn test_fq6() {
let mut rng = test_rng();
let a: Fq6 = rng.gen();
let b: Fq6 = rng.gen();
field_test(a, b);
frobenius_test::<Fq6, _>(Fq::characteristic(), 13);
}
test_field!(fr; Fr; mont_prime_field);
test_field!(fq; Fq; mont_prime_field);
test_field!(fq3; Fq3);
test_field!(fq6; Fq6);

7
bw6_761/src/lib.rs Normal file → Executable file
View File

@@ -9,9 +9,10 @@
#![forbid(unsafe_code)]
//! This library implements the BW6_761 curve generated in [\[EG20\]](https://eprint.iacr.org/2020/351).
//! The name denotes that it is a curve generated using the Brezing--Weng method, and that
//! its embedding degree is 6.
//! The main feature of this curve is that the scalar field equals the base field of the BLS12_377 curve.
//! The name denotes that it is a curve generated using the Brezing--Weng
//! method, and that its embedding degree is 6.
//! The main feature of this curve is that the scalar field equals the base
//! field of the BLS12_377 curve.
//!
//! Curve information:
//! * Base field: q = 6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299

33
bw6_767/Cargo.toml Normal file
View File

@@ -0,0 +1,33 @@
[package]
name = "ark-bw6-767"
version = "0.4.0"
authors = [ "arkworks contributors" ]
description = "The BW6-767 pairing-friendly elliptic curve"
homepage = "https://arkworks.rs"
repository = "https://github.com/arkworks-rs/curves"
documentation = "https://docs.rs/ark-bw6-767/"
keywords = ["cryptography", "finite-fields", "elliptic-curves" ]
categories = ["cryptography"]
include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
license = "MIT/Apache-2.0"
edition = "2021"
[dependencies]
ark-ff = { version= "0.4.0", default-features = false }
ark-ec = { version= "0.4.0", default-features = false }
ark-std = { version = "0.4.0", default-features = false }
ark-bls12-381 = { version = "0.4.0", path = "../bls12_381", default-features = false, features = [ "curve" ] }
[dev-dependencies]
ark-serialize = { version = "0.4.0", default-features = false }
ark-algebra-test-templates = { version = "0.4.0", default-features = false }
ark-algebra-bench-templates = { version = "0.4.0", default-features = false }
[features]
default = []
std = [ "ark-std/std", "ark-ff/std", "ark-ec/std", "ark-bls12-381/std" ]
[[bench]]
name = "bw6_767"
path = "benches/bw6_767.rs"
harness = false

1
bw6_767/LICENSE-APACHE Symbolic link
View File

@@ -0,0 +1 @@
../LICENSE-APACHE

1
bw6_767/LICENSE-MIT Symbolic link
View File

@@ -0,0 +1 @@
../LICENSE-MIT

View File

@@ -0,0 +1,16 @@
use ark_algebra_bench_templates::*;
use ark_bw6_767::{
fq::Fq, fq3::Fq3, fq6::Fq6, fr::Fr, g1::G1Projective as G1, g2::G2Projective as G2, BW6_767,
};
bench!(
Name = "BW6_767",
Pairing = BW6_767,
G1 = G1,
G2 = G2,
ScalarField = Fr,
G1BaseField = Fq,
G2BaseField = Fq3,
TargetField = Fq6,
);

View File

@@ -0,0 +1,28 @@
modulus = 496597749679620867773432037469214230242402307330180853437434581099336634619713640485778675608223760166307530047354464605410050411581079376994803852937842168733702867087556948851016246640584660942486895230518034810309227309966899431
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

View File

@@ -0,0 +1,28 @@
modulus = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
assert(modulus.is_prime())
Fp = GF(modulus)
generator = Fp(0);
for i in range(0, 20):
i = Fp(i);
neg_i = Fp(-i)
if not(i.is_primitive_root() or neg_i.is_primitive_root()):
continue
elif i.is_primitive_root():
assert(i.is_primitive_root());
print("Generator: %d" % i)
generator = i
break
else:
assert(neg_i.is_primitive_root());
print("Generator: %d" % neg_i)
generator = neg_i
break
two_adicity = valuation(modulus - 1, 2);
trace = (modulus - 1) / 2**two_adicity;
two_adic_root_of_unity = generator^trace
print("2-adic Root of Unity: %d " % two_adic_root_of_unity)

59
bw6_767/src/curves/g1.rs Normal file
View File

@@ -0,0 +1,59 @@
use ark_ec::{
models::{short_weierstrass::SWCurveConfig, CurveConfig},
short_weierstrass::{Affine, Projective},
};
use ark_ff::{AdditiveGroup, MontFp};
use crate::{Fq, Fr};
pub type G1Affine = Affine<Config>;
pub type G1Projective = Projective<Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Config;
impl CurveConfig for Config {
type BaseField = Fq;
type ScalarField = Fr;
/// COFACTOR =
/// 124074696211871689196744963988542244365937182994917792082847997279938522233341057826255097957635256182243502012934844
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x9fed0006fffaaabc,
0xfae29bffb34d7c0d,
0xc51e35fba8145036,
0x58c9927410ca3a62,
0x7772b64205a0bc67,
0x26212b5cf67cecaf,
0x3,
];
/// COFACTOR^(-1) mod r =
/// 1707860402533867312515920333330662452399178546610458136488910471176197226039103222144872611321997303708365553992812
const COFACTOR_INV: Fr = MontFp!("1707860402533867312515920333330662452399178546610458136488910471176197226039103222144872611321997303708365553992812");
}
impl SWCurveConfig for Config {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = 1
const COEFF_B: Fq = MontFp!("1");
/// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField {
use ark_ff::Zero;
Self::BaseField::zero()
}
}
/// G1_GENERATOR_X =
/// 127687253511432941835499154999732953539969793860764514205013635996439242747457934431893570832266740963864950713809357287070846939000367049554519743864924323440810949629217677483481194663331926309250818003412838087592587472550707218
pub const G1_GENERATOR_X: Fq = MontFp!("127687253511432941835499154999732953539969793860764514205013635996439242747457934431893570832266740963864950713809357287070846939000367049554519743864924323440810949629217677483481194663331926309250818003412838087592587472550707218");
/// G1_GENERATOR_Y =
/// 415570529523170147223250223671601071129165798689804006717876771297003017718159840368703823786319144396618898691682149260290217115399107531975419658973137909698922937988511368601419289861827304905241655385035120916874417442125721204
pub const G1_GENERATOR_Y: Fq = MontFp!("415570529523170147223250223671601071129165798689804006717876771297003017718159840368703823786319144396618898691682149260290217115399107531975419658973137909698922937988511368601419289861827304905241655385035120916874417442125721204");

60
bw6_767/src/curves/g2.rs Normal file
View File

@@ -0,0 +1,60 @@
use ark_ec::{
models::{short_weierstrass::SWCurveConfig, CurveConfig},
short_weierstrass::{Affine, Projective},
};
use ark_ff::{AdditiveGroup, MontFp};
use crate::{Fq, Fr};
pub type G2Affine = Affine<Config>;
pub type G2Projective = Projective<Config>;
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Config;
impl CurveConfig for Config {
type BaseField = Fq;
type ScalarField = Fr;
/// COFACTOR =
/// 124074696211871689196744963988542244365937182994917792082847997279938522233341057826255097957635256182243502012934833
#[rustfmt::skip]
const COFACTOR: &'static [u64] = &[
0x9fed0006fffaaab1,
0xfae29bffb34d7c0d,
0xc51e35fba8145036,
0x58c9927410ca3a62,
0x7772b64205a0bc67,
0x26212b5cf67cecaf,
0x3,
];
/// COFACTOR^(-1) mod r =
/// 1034808299677096100380606582404873291173913026971901593767142419502683535585229274705219741821274468081298550569313
const COFACTOR_INV: Fr = MontFp!("1034808299677096100380606582404873291173913026971901593767142419502683535585229274705219741821274468081298550569313");
}
impl SWCurveConfig for Config {
/// COEFF_A = 0
const COEFF_A: Fq = Fq::ZERO;
/// COEFF_B = 4
const COEFF_B: Fq = MontFp!("3");
/// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y)
const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
#[inline(always)]
fn mul_by_a(_elem: Self::BaseField) -> Self::BaseField {
use ark_ff::Zero;
Self::BaseField::zero()
}
}
/// G2_GENERATOR_X =
/// 370611171465172359348863648443534520144617072349884185652206813771489664034831143983178049920510836078361116088420840622225267322852644540540617123958979924966938307707664543525950567252218300954395355151658118858470703533448342222
pub const G2_GENERATOR_X: Fq = MontFp!("370611171465172359348863648443534520144617072349884185652206813771489664034831143983178049920510836078361116088420840622225267322852644540540617123958979924966938307707664543525950567252218300954395355151658118858470703533448342222");
/// G2_GENERATOR_Y =
/// 455144308204607096185992716699045373884508292978508084510087807751472279103896568109582325400258900176330927780121791269969939391813736974371796892558810828460226121428602798229282770695472612961143258458821149661074127679136388603
pub const G2_GENERATOR_Y: Fq = MontFp!("455144308204607096185992716699045373884508292978508084510087807751472279103896568109582325400258900176330927780121791269969939391813736974371796892558810828460226121428602798229282770695472612961143258458821149661074127679136388603");

51
bw6_767/src/curves/mod.rs Normal file
View File

@@ -0,0 +1,51 @@
use ark_ec::{
bw6,
bw6::{BW6Config, TwistType, BW6},
};
use ark_ff::{biginteger::BigInteger768 as BigInteger, BigInt};
use crate::*;
pub mod g1;
pub mod g2;
#[cfg(test)]
mod tests;
#[derive(PartialEq, Eq)]
pub struct Config;
impl BW6Config for Config {
// X is the same as in bls12_381
const X: BigInteger = BigInt!("0xd201000000010000");
const X_IS_NEGATIVE: bool = true;
// X
const ATE_LOOP_COUNT_1: &'static [u64] = &[0xd201000000010000];
const X_MINUS_1_DIV_3: BigInteger = BigInt!("0x460055555555aaab");
const ATE_LOOP_COUNT_1_IS_NEGATIVE: bool = true;
// X^2-X-1
const ATE_LOOP_COUNT_2: &'static [i8] = &[
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1, 0, -1, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, -1, 0, -1, 0, 1, 0, 0, 1,
0, 0, 0, -1, 0, -1, 0, -1, 0, 1,
];
const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool = false;
const TWIST_TYPE: TwistType = TwistType::M;
const H_T: i64 = -4;
const H_Y: i64 = -6;
const T_MOD_R_IS_ZERO: bool = true;
type Fp = Fq;
type Fp3Config = Fq3Config;
type Fp6Config = Fq6Config;
type G1Config = g1::Config;
type G2Config = g2::Config;
}
pub type BW6_767 = BW6<Config>;
pub type G1Affine = bw6::G1Affine<Config>;
pub type G1Projective = bw6::G1Projective<Config>;
pub type G2Affine = bw6::G2Affine<Config>;
pub type G2Projective = bw6::G2Projective<Config>;

View File

@@ -0,0 +1,8 @@
use crate::*;
use ark_algebra_test_templates::*;
use ark_ff::Field;
test_group!(g1; G1Projective; sw);
test_group!(g2; G2Projective; sw);
test_group!(pairing_output; ark_ec::pairing::PairingOutput<BW6_767>; msm);
test_pairing!(pairing; crate::BW6_767);

7
bw6_767/src/fields/fq.rs Normal file
View File

@@ -0,0 +1,7 @@
use ark_ff::fields::{Fp768, MontBackend, MontConfig};
#[derive(MontConfig)]
#[modulus = "496597749679620867773432037469214230242402307330180853437434581099336634619713640485778675608223760166307530047354464605410050411581079376994803852937842168733702867087556948851016246640584660942486895230518034810309227309966899431"]
#[generator = "3"]
pub struct FqConfig;
pub type Fq = Fp768<MontBackend<FqConfig, 12>>;

79
bw6_767/src/fields/fq3.rs Normal file
View File

@@ -0,0 +1,79 @@
use ark_ff::{
fields::fp3::{Fp3, Fp3Config},
AdditiveGroup, Field, MontFp,
};
use crate::Fq;
pub type Fq3 = Fp3<Fq3Config>;
pub struct Fq3Config;
impl Fp3Config for Fq3Config {
type Fp = Fq;
/// NONRESIDUE = 3
// Fq3 = Fq\[u\]/u^3-3
const NONRESIDUE: Fq = MontFp!("3");
// (MODULUS^3 - 1) % 2^TWO_ADICITY == 0
const TWO_ADICITY: u32 = 1;
// (T-1)/2 with T = (MODULUS^3-1) / 2^TWO_ADICITY
#[rustfmt::skip]
const TRACE_MINUS_ONE_DIV_TWO: &'static [u64] = &[
0x22d18a101ce54f7d,
0x354335b0e7c460e8,
0x8014efd2b7ade04d,
0x3a3c62ab52e0a2c1,
0x79ce8405b95dd2ee,
0x24f75cbd8559a2b6,
0x2519d1267e548214,
0xea0034421965f6c8,
0xbbaa92b6aca7d134,
0x9ec0892af11e70cc,
0x06e6ab40a2fd09ec,
0xd333987617c1542a,
0xdcb52167b1f0ae0f,
0xeffa098d77a86e52,
0x9fe0d744c24ed062,
0x7df249c9ef981da1,
0x01337d754cef36fa,
0xf84c4f79c259bd8b,
0x6552e19d7dc57335,
0x9f2cab11727d9c89,
0xe5cc4da17a684263,
0xaab0632027470c14,
0xb841a2fe447f48a3,
0x6e705db09cb2c6c9,
0x51d3c82bd5de018d,
0xf0bb21ffbef26bd1,
0x294ce678e6a4c0ff,
0x130ad731f57d4c85,
0xa1e367e5eb70a85b,
0xd1b2d73d567515cd,
0x0527dddbc3e9f165,
0x1d9c04e0098344e7,
0x5db616f391729475,
0xd2834b1fae1c2c1b,
0x7cf1b8c728557851,
0x218325db61d6ebd,
];
// NONRESIDUE^T % q
const QUADRATIC_NONRESIDUE_TO_T: Fq3 = Fq3::new(Fq::ONE, Fq::ZERO, Fq::ZERO);
// NQR ^ (MODULUS^i - 1)/3, i=0,1,2 with NQR = u = (0,1,0)
const FROBENIUS_COEFF_FP3_C1: &'static [Fq] = &[
Fq::ONE,
MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550170"),
MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349260"),
];
// NQR ^ (2*MODULUS^i - 2)/3, i=0,1,2 with NQR = u = (0,1,0)
const FROBENIUS_COEFF_FP3_C2: &'static [Fq] = &[
Fq::ONE,
MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349260"),
MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550170"),
];
}

26
bw6_767/src/fields/fq6.rs Normal file
View File

@@ -0,0 +1,26 @@
use ark_ff::{
fields::fp6_2over3::{Fp6, Fp6Config},
AdditiveGroup, Field, MontFp,
};
use crate::{Fq, Fq3, Fq3Config};
pub type Fq6 = Fp6<Fq6Config>;
pub struct Fq6Config;
impl Fp6Config for Fq6Config {
type Fp3Config = Fq3Config;
/// NONRESIDUE = (0, 1, 0)
const NONRESIDUE: Fq3 = Fq3::new(Fq::ZERO, Fq::ONE, Fq::ZERO);
const FROBENIUS_COEFF_FP6_C1: &'static [Fq] = &[
Fq::ONE,
MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550171"),
MontFp!("451452499708746243421442696394275804592767119751118962106882058158528025766103643615697202253207413006991058800455542766924935899310685166148099708594514571753800103096705086912881023032622324847956780035251378028187894066092550170"),
MontFp!("-1"),
MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349260"),
MontFp!("45145249970874624351989341074938425649635187579061891330552522940808608853609996870081473355016347159316471246898921838485114512270394210846704144343327596979902763990851861938135223607962336094530115195266656782121333243874349261"),
];
}

1
bw6_767/src/fields/fr.rs Normal file
View File

@@ -0,0 +1 @@
pub use ark_bls12_381::{Fq as Fr, FqConfig as FrConfig};

Some files were not shown because too many files have changed in this diff Show More