From 21ac6a5ed287112f685174b482d36392c594f0e8 Mon Sep 17 00:00:00 2001 From: Wei-Ning Huang Date: Thu, 11 Apr 2019 18:32:33 +0800 Subject: vendor: use BLS-12_384 curve and update dependencies (#356) --- Dockerfile | 7 +- Dockerfile.alltools | 3 +- Makefile | 10 +- vendor/github.com/dexon-foundation/bls/.gitignore | 7 + vendor/github.com/dexon-foundation/bls/.travis.yml | 39 + .../github.com/dexon-foundation/bls/CMakeLists.txt | 33 + vendor/github.com/dexon-foundation/bls/Makefile | 108 +- .../github.com/dexon-foundation/bls/bin/.emptydir | 0 .../dexon-foundation/bls/ffi/cs/App.config | 6 + .../bls/ffi/cs/Properties/AssemblyInfo.cs | 36 + .../github.com/dexon-foundation/bls/ffi/cs/bls.cs | 351 +++++ .../dexon-foundation/bls/ffi/cs/bls.csproj | 97 ++ .../github.com/dexon-foundation/bls/ffi/cs/bls.sln | 25 + .../dexon-foundation/bls/ffi/cs/bls256.cs | 298 ++++ .../dexon-foundation/bls/ffi/cs/bls256.csproj | 62 + .../dexon-foundation/bls/ffi/cs/bls256.sln | 22 + .../dexon-foundation/bls/ffi/cs/bls256_test.cs | 126 ++ .../dexon-foundation/bls/ffi/cs/bls_test.cs | 176 +++ .../dexon-foundation/bls/ffi/cs/readme-ja.md | 188 +++ .../dexon-foundation/bls/ffi/cs/readme.md | 185 +++ .../dexon-foundation/bls/ffi/go/bls/bls.go | 127 +- .../dexon-foundation/bls/ffi/go/bls/bls_test.go | 690 +++++++++ .../dexon-foundation/bls/ffi/go/bls/callback.go | 12 + .../dexon-foundation/bls/ffi/go/bls/config.h | 6 + .../dexon-foundation/bls/ffi/go/bls/dummy.cpp | 3 + .../dexon-foundation/bls/ffi/go/bls/mcl.go | 16 +- .../bls/images/bls-go-alpine/Dockerfile | 12 + .../dexon-foundation/bls/include/bls/bls.h | 51 +- .../dexon-foundation/bls/include/bls/bls.hpp | 44 +- vendor/github.com/dexon-foundation/bls/mk.bat | 1 + vendor/github.com/dexon-foundation/bls/mklib.bat | 4 + vendor/github.com/dexon-foundation/bls/readme.md | 23 +- .../dexon-foundation/bls/sample/bls_smpl.cpp | 168 +++ vendor/github.com/dexon-foundation/bls/setvar.bat | 4 +- .../dexon-foundation/bls/src/bls_c384_256.cpp | 4 + .../dexon-foundation/bls/src/bls_c_impl.hpp | 299 +++- .../dexon-foundation/bls/test/bls256_test.cpp | 3 + .../dexon-foundation/bls/test/bls384_256_test.cpp | 4 + .../dexon-foundation/bls/test/bls384_test.cpp | 3 + .../dexon-foundation/bls/test/bls_c256_test.cpp | 2 + .../bls/test/bls_c384_256_test.cpp | 3 + .../dexon-foundation/bls/test/bls_c384_test.cpp | 2 + .../dexon-foundation/bls/test/bls_c_test.hpp | 437 ++++++ .../dexon-foundation/bls/test/bls_test.hpp | 545 +++++++ .../bls/test/proj/bls_test/bls_test.vcxproj | 88 ++ .../dexon-consensus/core/crypto/dkg/constant.go | 2 +- vendor/github.com/dexon-foundation/mcl/.gitignore | 13 + vendor/github.com/dexon-foundation/mcl/.travis.yml | 17 + .../github.com/dexon-foundation/mcl/CMakeLists.txt | 16 +- vendor/github.com/dexon-foundation/mcl/Makefile | 66 +- vendor/github.com/dexon-foundation/mcl/common.mk | 2 +- .../dexon-foundation/mcl/ffi/cs/App.config | 6 + .../mcl/ffi/cs/Properties/AssemblyInfo.cs | 36 + .../dexon-foundation/mcl/ffi/cs/bn256.cs | 475 ++++++ .../dexon-foundation/mcl/ffi/cs/bn256.csproj | 62 + .../dexon-foundation/mcl/ffi/cs/bn256.sln | 22 + .../dexon-foundation/mcl/ffi/cs/bn256_test.cs | 149 ++ .../dexon-foundation/mcl/ffi/go/mcl/mcl.go | 659 +++++++++ .../dexon-foundation/mcl/ffi/go/mcl/mcl_test.go | 157 ++ .../dexon-foundation/mcl/ffi/java/Bn256Test.java | 104 ++ .../dexon-foundation/mcl/ffi/java/ElgamalTest.java | 144 ++ .../dexon-foundation/mcl/ffi/java/Makefile | 64 + .../dexon-foundation/mcl/ffi/java/bn256.i | 31 + .../dexon-foundation/mcl/ffi/java/bn256_impl.hpp | 249 ++++ .../dexon-foundation/mcl/ffi/java/bn256_wrap.cxx | 1542 ++++++++++++++++++++ .../dexon-foundation/mcl/ffi/java/elgamal.i | 28 + .../dexon-foundation/mcl/ffi/java/elgamal_impl.hpp | 147 ++ .../dexon-foundation/mcl/ffi/java/elgamal_wrap.cxx | 1129 ++++++++++++++ .../dexon-foundation/mcl/ffi/java/java.md | 95 ++ .../dexon-foundation/mcl/ffi/java/make_wrap.bat | 23 + .../dexon-foundation/mcl/ffi/java/run-bn256.bat | 9 + .../dexon-foundation/mcl/ffi/java/run-elgamal.bat | 9 + .../mcl/ffi/java/set-java-path.bat | 8 + .../mcl/ffi/js/export-functions.py | 73 + .../dexon-foundation/mcl/ffi/js/pre-mcl.js | 5 + .../dexon-foundation/mcl/ffi/python/pairing.py | 80 + .../dexon-foundation/mcl/ffi/python/she.py | 298 ++++ .../mcl/include/cybozu/random_generator.hpp | 34 +- .../dexon-foundation/mcl/include/cybozu/sha2.hpp | 345 +++-- .../mcl/include/cybozu/xorshift.hpp | 113 +- .../dexon-foundation/mcl/include/mcl/array.hpp | 25 +- .../dexon-foundation/mcl/include/mcl/bn.h | 62 +- .../dexon-foundation/mcl/include/mcl/bn.hpp | 119 +- .../dexon-foundation/mcl/include/mcl/curve_type.h | 19 +- .../dexon-foundation/mcl/include/mcl/ec.hpp | 104 +- .../dexon-foundation/mcl/include/mcl/ecparam.hpp | 51 +- .../dexon-foundation/mcl/include/mcl/elgamal.hpp | 18 +- .../dexon-foundation/mcl/include/mcl/fp.hpp | 66 +- .../dexon-foundation/mcl/include/mcl/fp_tower.hpp | 330 +++-- .../dexon-foundation/mcl/include/mcl/gmp_util.hpp | 95 +- .../mcl/include/mcl/impl/bn_c_impl.hpp | 643 ++++++++ .../dexon-foundation/mcl/include/mcl/lagrange.hpp | 22 +- .../dexon-foundation/mcl/include/mcl/op.hpp | 24 +- .../dexon-foundation/mcl/include/mcl/randgen.hpp | 58 +- .../dexon-foundation/mcl/include/mcl/vint.hpp | 71 +- .../github.com/dexon-foundation/mcl/misc/bench.txt | 21 + .../dexon-foundation/mcl/misc/karatsuba.cpp | 75 + .../github.com/dexon-foundation/mcl/misc/mul.cpp | 58 + .../dexon-foundation/mcl/misc/precompute.cpp | 30 + .../dexon-foundation/mcl/misc/she/bench.sh | 6 + .../dexon-foundation/mcl/misc/she/bench4.txt | 99 ++ .../dexon-foundation/mcl/misc/she/bench6.txt | 99 ++ .../dexon-foundation/mcl/misc/she/bench8.txt | 99 ++ .../dexon-foundation/mcl/misc/she/nizkp.pdf | Bin 0 -> 28787 bytes .../dexon-foundation/mcl/misc/she/she-api-ja.md | 314 ++++ .../dexon-foundation/mcl/misc/she/she-api.md | 322 ++++ .../dexon-foundation/mcl/misc/she/she.pdf | Bin 0 -> 25716 bytes vendor/github.com/dexon-foundation/mcl/mklib.bat | 5 + vendor/github.com/dexon-foundation/mcl/readme.md | 140 +- .../dexon-foundation/mcl/sample/bench.cpp | 233 +++ .../dexon-foundation/mcl/sample/bls_sig.cpp | 70 + .../dexon-foundation/mcl/sample/ecdh.cpp | 64 + .../dexon-foundation/mcl/sample/large.cpp | 125 ++ .../dexon-foundation/mcl/sample/pairing.cpp | 56 + .../dexon-foundation/mcl/sample/pairing_c.c | 52 + .../dexon-foundation/mcl/sample/random.cpp | 29 + .../dexon-foundation/mcl/sample/rawbench.cpp | 180 +++ .../mcl/sample/she_make_dlp_table.cpp | 69 + .../dexon-foundation/mcl/sample/she_smpl.cpp | 125 ++ .../dexon-foundation/mcl/sample/tri-dh.cpp | 97 ++ .../dexon-foundation/mcl/sample/vote.cpp | 206 +++ .../dexon-foundation/mcl/src/bn_c256.cpp | 2 +- .../dexon-foundation/mcl/src/bn_c384.cpp | 2 +- .../dexon-foundation/mcl/src/bn_c384_256.cpp | 2 +- .../dexon-foundation/mcl/src/bn_c512.cpp | 2 +- vendor/github.com/dexon-foundation/mcl/src/fp.cpp | 83 +- .../dexon-foundation/mcl/src/fp_generator.hpp | 1460 ++++++++++++------ .../dexon-foundation/mcl/src/she_c_impl.hpp | 2 +- .../dexon-foundation/mcl/src/xbyak/xbyak.h | 53 +- .../mcl/src/xbyak/xbyak_mnemonic.h | 2 +- .../mcl/test/aggregate_sig_test.cpp | 74 + .../dexon-foundation/mcl/test/array_test.cpp | 104 ++ .../dexon-foundation/mcl/test/base_test.cpp | 392 +++++ .../github.com/dexon-foundation/mcl/test/bench.hpp | 192 +++ .../dexon-foundation/mcl/test/bls12_test.cpp | 720 +++++++++ .../dexon-foundation/mcl/test/bn384_test.cpp | 83 ++ .../dexon-foundation/mcl/test/bn512_test.cpp | 68 + .../dexon-foundation/mcl/test/bn_c256_test.cpp | 6 + .../dexon-foundation/mcl/test/bn_c384_256_test.cpp | 7 + .../dexon-foundation/mcl/test/bn_c384_test.cpp | 6 + .../dexon-foundation/mcl/test/bn_c512_test.cpp | 6 + .../dexon-foundation/mcl/test/bn_c_test.hpp | 699 +++++++++ .../dexon-foundation/mcl/test/bn_test.cpp | 408 ++++++ .../dexon-foundation/mcl/test/conversion_test.cpp | 96 ++ .../dexon-foundation/mcl/test/ec_test.cpp | 573 ++++++++ .../dexon-foundation/mcl/test/ecdsa_c_test.cpp | 51 + .../dexon-foundation/mcl/test/ecdsa_test.cpp | 69 + .../dexon-foundation/mcl/test/elgamal_test.cpp | 155 ++ .../mcl/test/fp_generator_test.cpp | 207 +++ .../dexon-foundation/mcl/test/fp_test.cpp | 1046 +++++++++++++ .../dexon-foundation/mcl/test/fp_tower_test.cpp | 477 ++++++ .../dexon-foundation/mcl/test/fp_util_test.cpp | 270 ++++ .../dexon-foundation/mcl/test/glv_test.cpp | 209 +++ .../dexon-foundation/mcl/test/gmp_test.cpp | 70 + .../dexon-foundation/mcl/test/low_test.cpp | 73 + .../github.com/dexon-foundation/mcl/test/mk32.sh | 1 + .../dexon-foundation/mcl/test/modp_test.cpp | 37 + .../dexon-foundation/mcl/test/mont_fp_test.cpp | 332 +++++ .../dexon-foundation/mcl/test/paillier_test.cpp | 24 + .../mcl/test/proj/bn_test/bn_test.vcxproj | 88 ++ .../mcl/test/proj/ec_test/ec_test.vcxproj | 88 ++ .../mcl/test/proj/fp_test/fp_test.vcxproj | 88 ++ .../test/proj/fp_tower_test/fp_tower_test.vcxproj | 88 ++ .../dexon-foundation/mcl/test/she_c256_test.cpp | 2 + .../dexon-foundation/mcl/test/she_c384_test.cpp | 2 + .../dexon-foundation/mcl/test/she_c_test.hpp | 535 +++++++ .../dexon-foundation/mcl/test/she_test.cpp | 756 ++++++++++ .../dexon-foundation/mcl/test/sq_test.cpp | 21 + .../dexon-foundation/mcl/test/vint_test.cpp | 1353 +++++++++++++++++ .../mcl/test/window_method_test.cpp | 70 + vendor/vendor.json | 42 +- 171 files changed, 24751 insertions(+), 1268 deletions(-) create mode 100644 vendor/github.com/dexon-foundation/bls/.gitignore create mode 100644 vendor/github.com/dexon-foundation/bls/.travis.yml create mode 100644 vendor/github.com/dexon-foundation/bls/CMakeLists.txt create mode 100644 vendor/github.com/dexon-foundation/bls/bin/.emptydir create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/App.config create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/Properties/AssemblyInfo.cs create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/bls.cs create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/bls.csproj create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/bls.sln create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.cs create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.csproj create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.sln create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/bls256_test.cs create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/bls_test.cs create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/readme-ja.md create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/cs/readme.md create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls_test.go create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/go/bls/callback.go create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/go/bls/config.h create mode 100644 vendor/github.com/dexon-foundation/bls/ffi/go/bls/dummy.cpp create mode 100644 vendor/github.com/dexon-foundation/bls/images/bls-go-alpine/Dockerfile create mode 100644 vendor/github.com/dexon-foundation/bls/sample/bls_smpl.cpp create mode 100644 vendor/github.com/dexon-foundation/bls/src/bls_c384_256.cpp create mode 100644 vendor/github.com/dexon-foundation/bls/test/bls256_test.cpp create mode 100644 vendor/github.com/dexon-foundation/bls/test/bls384_256_test.cpp create mode 100644 vendor/github.com/dexon-foundation/bls/test/bls384_test.cpp create mode 100644 vendor/github.com/dexon-foundation/bls/test/bls_c256_test.cpp create mode 100644 vendor/github.com/dexon-foundation/bls/test/bls_c384_256_test.cpp create mode 100644 vendor/github.com/dexon-foundation/bls/test/bls_c384_test.cpp create mode 100644 vendor/github.com/dexon-foundation/bls/test/bls_c_test.hpp create mode 100644 vendor/github.com/dexon-foundation/bls/test/bls_test.hpp create mode 100644 vendor/github.com/dexon-foundation/bls/test/proj/bls_test/bls_test.vcxproj create mode 100644 vendor/github.com/dexon-foundation/mcl/.gitignore create mode 100644 vendor/github.com/dexon-foundation/mcl/.travis.yml create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/cs/App.config create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/cs/Properties/AssemblyInfo.cs create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.cs create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.csproj create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.sln create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256_test.cs create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl.go create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl_test.go create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/Bn256Test.java create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/ElgamalTest.java create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/Makefile create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/bn256.i create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_impl.hpp create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_wrap.cxx create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal.i create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_impl.hpp create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_wrap.cxx create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/java.md create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/make_wrap.bat create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/run-bn256.bat create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/run-elgamal.bat create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/java/set-java-path.bat create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/js/export-functions.py create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/js/pre-mcl.js create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/python/pairing.py create mode 100644 vendor/github.com/dexon-foundation/mcl/ffi/python/she.py create mode 100644 vendor/github.com/dexon-foundation/mcl/include/mcl/impl/bn_c_impl.hpp create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/bench.txt create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/karatsuba.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/mul.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/precompute.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/she/bench.sh create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/she/bench4.txt create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/she/bench6.txt create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/she/bench8.txt create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/she/nizkp.pdf create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/she/she-api-ja.md create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/she/she-api.md create mode 100644 vendor/github.com/dexon-foundation/mcl/misc/she/she.pdf create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/bench.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/bls_sig.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/ecdh.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/large.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/pairing.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/pairing_c.c create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/random.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/rawbench.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/she_make_dlp_table.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/she_smpl.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/tri-dh.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/sample/vote.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/array_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/base_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bench.hpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bls12_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bn384_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bn512_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bn_c256_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bn_c384_256_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bn_c384_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bn_c512_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bn_c_test.hpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/bn_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/conversion_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/ec_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/ecdsa_c_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/ecdsa_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/elgamal_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/fp_generator_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/fp_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/fp_tower_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/fp_util_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/glv_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/gmp_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/low_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/mk32.sh create mode 100644 vendor/github.com/dexon-foundation/mcl/test/modp_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/mont_fp_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/paillier_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj create mode 100644 vendor/github.com/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj create mode 100644 vendor/github.com/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj create mode 100644 vendor/github.com/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj create mode 100644 vendor/github.com/dexon-foundation/mcl/test/she_c256_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/she_c384_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/she_c_test.hpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/she_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/sq_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/vint_test.cpp create mode 100644 vendor/github.com/dexon-foundation/mcl/test/window_method_test.cpp diff --git a/Dockerfile b/Dockerfile index 01490d5b8..89bf55ecc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,15 @@ FROM golang:1.12-alpine as builder -RUN apk add --no-cache make gcc musl-dev linux-headers g++ gmp-dev openssl-dev pkgconfig +RUN apk add --no-cache make gcc musl-dev linux-headers g++ gmp-dev pkgconfig ADD . /dexon -RUN cd /dexon && make clean && DOCKER=alpine make gdex all +RUN cd /dexon && make clean-cgo && DOCKER=alpine make gdex +RUN cd /dexon && build/env.sh go build -o build/bin/bootnode ./cmd/bootnode # Pull Gdex into a second stage deploy alpine container FROM alpine:latest -RUN apk add --no-cache ca-certificates libstdc++ curl gmp openssl +RUN apk add --no-cache ca-certificates curl COPY --from=builder /dexon/build/bin/gdex /usr/local/bin/ COPY --from=builder /dexon/build/bin/bootnode /usr/local/bin/ diff --git a/Dockerfile.alltools b/Dockerfile.alltools index 9c85a8802..1809f797d 100644 --- a/Dockerfile.alltools +++ b/Dockerfile.alltools @@ -1,7 +1,7 @@ # Build Geth in a stock Go builder container FROM golang:1.12-alpine as builder -RUN apk add --no-cache make gcc musl-dev linux-headers g++ gmp-dev openssl-dev pkgconfig +RUN apk add --no-cache make gcc musl-dev linux-headers g++ gmp-dev pkgconfig ADD . /dexon RUN cd /dexon && make clean && DOCKER=alpine make all @@ -9,7 +9,6 @@ RUN cd /dexon && make clean && DOCKER=alpine make all # Pull all binaries into a second stage deploy alpine container FROM alpine:latest -RUN apk add --no-cache ca-certificates libstdc++ gmp openssl COPY --from=builder /dexon/build/bin/* /usr/local/bin/ EXPOSE 8545 8546 30303 30303/udp diff --git a/Makefile b/Makefile index 9cdd9e5b0..14f79c8ef 100644 --- a/Makefile +++ b/Makefile @@ -41,14 +41,16 @@ lint: ## Run linters. build/env.sh go run build/ci.go lint libbls: - make -C vendor/github.com/dexon-foundation/bls lib/libbls384.a + make -C vendor/github.com/dexon-foundation/bls MCL_USE_OPENSSL=0 lib/libbls384.a -clean: - ./build/clean_go_build_cache.sh - rm -fr build/_workspace/pkg/ $(GOBIN)/* +clean-cgo: make -C vendor/github.com/dexon-foundation/bls clean make -C vendor/github.com/dexon-foundation/mcl clean +clean: clean-cgo + ./build/clean_go_build_cache.sh + rm -fr build/_workspace/pkg/ $(GOBIN)/* + # The devtools target installs tools required for 'go generate'. # You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'. diff --git a/vendor/github.com/dexon-foundation/bls/.gitignore b/vendor/github.com/dexon-foundation/bls/.gitignore new file mode 100644 index 000000000..dacdfc906 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/.gitignore @@ -0,0 +1,7 @@ +CVS +bin/*.exe +lib/*.a +lib/*.so +lib/*.dylib +obj/*.d +obj/*.o diff --git a/vendor/github.com/dexon-foundation/bls/.travis.yml b/vendor/github.com/dexon-foundation/bls/.travis.yml new file mode 100644 index 000000000..71a667a2e --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/.travis.yml @@ -0,0 +1,39 @@ +sudo: true +dist: xenial +services: +- docker +env: + global: + - IMAGE_TAG=dexonfoundation/bls-go-alpine + - DOCKER_USER=spiderpowadeploy + - secure: mqNCngWukyjE3UARxaPjqS0xgC1dsnWfmPhpH2mq7nR6S2cGfJ3xBfyiTS//Clz//7sAL+Tp62r3fxyMjDogrSHZUUssCAwf17RM6vnALqaVbc3wXcTNudiDB5cVKe9C9gZqn1Ivd+qbmtuCezSrOG5Xih1gh4bPTyiFvU1sp9C2icMHkJZkjsP0QqCbHlQrMeECSIPlEGIOXUUSp+WmrZAdi2rHezKeZxuaT73RX1+N/+1RfWXo2MR4ydQU3eALl5s5UA9JweQO+MYIVr8EEpGNqJRYUyURx/5G/Sy2v6Z3imUvXZv1J5aplW/UDls92Olla1JHuvFW6ptRO+PHITNwvEkhxPFj+HcOpqEuSISsdk9rkHUrM0wEYPv6A4vQPUjMHrLQs2tQShVCelM1HtNvDDjttKMmVyRLusFP9eS7uvmmXu2l6efJjsMSFkY5WKbu2U0MQ1j708KH9k2WunU6sjJ+b74PkkZVtkQMIqgTokC0IOqbbrnwh4I9PpVpHAQrewRimMH+lDHk+HlMUCWk7/IcIFUl+mh6RzW2vkZTTr2ctSBI6QzK5smdPmqQpp2lqkGv/hQCBp5ICzFSkU6Djqe3hG8ta3+/Zhi10fPU2HcHDi+gR79CG8dvy+iOeTS2csXZx+YoN2BVkfu9AnrjZ9Kjkf9BMay4CehBUWE= +language: cpp +compiler: +- gcc +- clang +addons: + apt: + packages: + - libgmp-dev +install: +- git clone --depth 1 https://github.com/dexon-foundation/mcl.git $TRAVIS_BUILD_DIR/../mcl +script: +- make -j3 +- make test_ci DISABLE_THREAD_TEST=1 +- make test_go +- env LD_LIBRARY_PATH=../mcl/lib bin/bls_c384_test.exe +- make clean && make -C ../mcl clean +- make -j3 MCL_USE_OPENSSL=0 +- make test_ci DISABLE_THREAD_TEST=1 MCL_USE_OPENSSL=0 +- docker build --tag "$IMAGE_TAG" . -f images/bls-go-alpine/Dockerfile --no-cache +before_deploy: +- echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin +- git_commit="$(git rev-parse --short HEAD)" +- docker tag "$IMAGE_TAG" "${IMAGE_TAG}:${git_commit}" +- docker tag "$IMAGE_TAG" "${IMAGE_TAG}:latest" +deploy: + provider: script + script: docker push "${IMAGE_TAG}:latest" && docker push "${IMAGE_TAG}:${git_commit}" + on: + branch: dev + condition: "$CC = gcc" diff --git a/vendor/github.com/dexon-foundation/bls/CMakeLists.txt b/vendor/github.com/dexon-foundation/bls/CMakeLists.txt new file mode 100644 index 000000000..30fb90fd5 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required (VERSION 2.6) +project(bls CXX ASM) + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +set(LIBS mcl gmp) + +include_directories(include/) + +add_library(bls_c256 SHARED src/bls_c256.cpp) +add_library(bls_c384 SHARED src/bls_c384.cpp) +add_library(bls_c384_256 SHARED src/bls_c384_256.cpp) +target_link_libraries(bls_c256 ${LIBS}) +target_link_libraries(bls_c384 ${LIBS}) +target_link_libraries(bls_c384_256 ${LIBS}) + +file(GLOB BLS_HEADERS include/bls/bls.h include/bls/bls.hpp) + +install(TARGETS bls_c256 DESTINATION lib) +install(TARGETS bls_c384 DESTINATION lib) +install(TARGETS bls_c384_256 DESTINATION lib) +install(FILES ${BLS_HEADERS} DESTINATION include/bls) + +set(TEST_LIBS pthread gmpxx) + +add_executable(bls_c256_test test/bls_c256_test.cpp) +target_link_libraries(bls_c256_test bls_c256 ${TEST_LIBS}) +add_executable(bls_c384_test test/bls_c384_test.cpp) +target_link_libraries(bls_c384_test bls_c384 ${TEST_LIBS}) +add_executable(bls_c384_256_test test/bls_c384_256_test.cpp) +target_link_libraries(bls_c384_256_test bls_c384_256 ${TEST_LIBS}) diff --git a/vendor/github.com/dexon-foundation/bls/Makefile b/vendor/github.com/dexon-foundation/bls/Makefile index 556f625ec..efea22274 100644 --- a/vendor/github.com/dexon-foundation/bls/Makefile +++ b/vendor/github.com/dexon-foundation/bls/Makefile @@ -1,55 +1,73 @@ -include ../mcl/common.mk +ifeq ($(findstring MINGW64,$(shell uname -s)),MINGW64) + # cgo accepts not '/c/path' but 'c:/path' + PWD=$(shell pwd|sed s'@^/\([a-z]\)@\1:@') +else + PWD=$(shell pwd) +endif +MCL_DIR?=$(PWD)/../mcl +include $(MCL_DIR)/common.mk LIB_DIR=lib OBJ_DIR=obj EXE_DIR=bin CFLAGS += -std=c++11 LDFLAGS += -lpthread -SRC_SRC=bls_c256.cpp bls_c384.cpp -TEST_SRC=bls256_test.cpp bls384_test.cpp bls_c256_test.cpp bls_c384_test.cpp +SRC_SRC=bls_c256.cpp bls_c384.cpp bls_c384_256.cpp +TEST_SRC=bls256_test.cpp bls384_test.cpp bls384_256_test.cpp bls_c256_test.cpp bls_c384_test.cpp bls_c384_256_test.cpp SAMPLE_SRC=bls256_smpl.cpp bls384_smpl.cpp -CFLAGS+=-I../mcl/include -I./ +CFLAGS+=-I$(MCL_DIR)/include ifneq ($(MCL_MAX_BIT_SIZE),) CFLAGS+=-DMCL_MAX_BIT_SIZE=$(MCL_MAX_BIT_SIZE) endif ifeq ($(DISABLE_THREAD_TEST),1) CFLAGS+=-DDISABLE_THREAD_TEST endif - -SHARE_BASENAME_SUF?=_dy +ifeq ($(BLS_SWAP_G),1) + CFLAGS+=-DBLS_SWAP_G +endif BLS256_LIB=$(LIB_DIR)/libbls256.a BLS384_LIB=$(LIB_DIR)/libbls384.a -BLS256_SNAME=bls256$(SHARE_BASENAME_SUF) -BLS384_SNAME=bls384$(SHARE_BASENAME_SUF) +BLS384_256_LIB=$(LIB_DIR)/libbls384_256.a +BLS256_SNAME=bls256 +BLS384_SNAME=bls384 +BLS384_256_SNAME=bls384_256 BLS256_SLIB=$(LIB_DIR)/lib$(BLS256_SNAME).$(LIB_SUF) BLS384_SLIB=$(LIB_DIR)/lib$(BLS384_SNAME).$(LIB_SUF) -all: $(BLS256_LIB) $(BLS256_SLIB) $(BLS384_LIB) $(BLS384_SLIB) +BLS384_256_SLIB=$(LIB_DIR)/lib$(BLS384_256_SNAME).$(LIB_SUF) +all: $(BLS256_LIB) $(BLS256_SLIB) $(BLS384_LIB) $(BLS384_SLIB) $(BLS384_256_LIB) $(BLS384_256_SLIB) -MCL_LIB=../mcl/lib/libmcl.a +MCL_LIB=$(MCL_DIR)/lib/libmcl.a $(MCL_LIB): - $(MAKE) -C ../mcl lib/libmcl.a + $(MAKE) -C $(MCL_DIR) -$(BLS256_LIB): $(OBJ_DIR)/bls_c256.o +$(BLS256_LIB): $(OBJ_DIR)/bls_c256.o $(MCL_LIB) $(AR) $@ $< $(BLS384_LIB): $(OBJ_DIR)/bls_c384.o $(MCL_LIB) $(AR) $@ $< +$(BLS384_256_LIB): $(OBJ_DIR)/bls_c384_256.o $(MCL_LIB) + $(AR) $@ $< ifneq ($(findstring $(OS),mac/mingw64),) - BLS256_SLIB_LDFLAGS+=-lgmpxx -lgmp -lcrypto -lstdc++ - BLS384_SLIB_LDFLAGS+=-lgmpxx -lgmp -lcrypto -lstdc++ + COMMON_LIB=$(GMP_LIB) $(OPENSSL_LIB) -lstdc++ + BLS256_SLIB_LDFLAGS+=$(COMMON_LIB) + BLS384_SLIB_LDFLAGS+=$(COMMON_LIB) + BLS384_256_SLIB_LDFLAGS+=$(COMMON_LIB) endif ifeq ($(OS),mingw64) - CFLAGS+=-I../mcl + CFLAGS+=-I$(MCL_DIR) BLS256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BLS256_SNAME).a BLS384_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BLS384_SNAME).a + BLS384_256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BLS384_256_SNAME).a endif $(BLS256_SLIB): $(OBJ_DIR)/bls_c256.o $(MCL_LIB) - $(PRE)$(CXX) -shared -o $@ $< $(MCL_LIB) $(BLS256_SLIB_LDFLAGS) + $(PRE)$(CXX) -shared -o $@ $< -L$(MCL_DIR)/lib -lmcl $(BLS256_SLIB_LDFLAGS) $(LDFLAGS) $(BLS384_SLIB): $(OBJ_DIR)/bls_c384.o $(MCL_LIB) - $(PRE)$(CXX) -shared -o $@ $< $(MCL_LIB) $(BLS384_SLIB_LDFLAGS) + $(PRE)$(CXX) -shared -o $@ $< -L$(MCL_DIR)/lib -lmcl $(BLS384_SLIB_LDFLAGS) $(LDFLAGS) +$(BLS384_256_SLIB): $(OBJ_DIR)/bls_c384_256.o $(MCL_LIB) + $(PRE)$(CXX) -shared -o $@ $< -L$(MCL_DIR)/lib -lmcl $(BLS384_256_SLIB_LDFLAGS) $(LDFLAGS) VPATH=test sample src @@ -58,35 +76,58 @@ VPATH=test sample src $(OBJ_DIR)/%.o: %.cpp $(PRE)$(CXX) $(CFLAGS) -c $< -o $@ -MMD -MP -MF $(@:.o=.d) +$(EXE_DIR)/%384_256_test.exe: $(OBJ_DIR)/%384_256_test.o $(BLS384_256_LIB) $(MCL_LIB) + $(PRE)$(CXX) $< -o $@ $(BLS384_256_LIB) -L$(MCL_DIR)/lib -lmcl $(LDFLAGS) + $(EXE_DIR)/%384_test.exe: $(OBJ_DIR)/%384_test.o $(BLS384_LIB) $(MCL_LIB) - $(PRE)$(CXX) $< -o $@ $(BLS384_LIB) -lmcl -L../mcl/lib $(LDFLAGS) + $(PRE)$(CXX) $< -o $@ $(BLS384_LIB) -L$(MCL_DIR)/lib -lmcl $(LDFLAGS) $(EXE_DIR)/%256_test.exe: $(OBJ_DIR)/%256_test.o $(BLS256_LIB) $(MCL_LIB) - $(PRE)$(CXX) $< -o $@ $(BLS256_LIB) -lmcl -L../mcl/lib $(LDFLAGS) + $(PRE)$(CXX) $< -o $@ $(BLS256_LIB) -L$(MCL_DIR)/lib -lmcl $(LDFLAGS) # sample exe links libbls256.a $(EXE_DIR)/%.exe: $(OBJ_DIR)/%.o $(BLS256_LIB) $(MCL_LIB) - $(PRE)$(CXX) $< -o $@ $(BLS256_LIB) -lmcl -L../mcl/lib $(LDFLAGS) + $(PRE)$(CXX) $< -o $@ $(BLS256_LIB) -L$(MCL_DIR)/lib -lmcl $(LDFLAGS) +ifeq ($(OS),mac) + install_name_tool bin/bls_smpl.exe -change lib/libmcl.dylib $(MCL_DIR)/lib/libmcl.dylib +endif SAMPLE_EXE=$(addprefix $(EXE_DIR)/,$(SAMPLE_SRC:.cpp=.exe)) sample: $(SAMPLE_EXE) TEST_EXE=$(addprefix $(EXE_DIR)/,$(TEST_SRC:.cpp=.exe)) +ifeq ($(OS),mac) + LIBPATH_KEY=DYLD_LIBRARY_PATH +else + LIBPATH_KEY=LD_LIBRARY_PATH +endif +test_ci: $(TEST_EXE) + @sh -ec 'for i in $(TEST_EXE); do echo $$i; env PATH=$$PATH:../mcl/lib $(LIBPATH_KEY)=../mcl/lib LSAN_OPTIONS=verbosity=1 log_threads=1 $$i; done' + $(MAKE) sample_test + test: $(TEST_EXE) @echo test $(TEST_EXE) - @sh -ec 'for i in $(TEST_EXE); do $$i|grep "ctest:name"; done' > result.txt + @sh -ec 'for i in $(TEST_EXE); do env PATH=$$PATH:../mcl/lib $(LIBPATH_KEY)=../mcl/lib $$i|grep "ctest:name"; done' > result.txt @grep -v "ng=0, exception=0" result.txt; if [ $$? -eq 1 ]; then echo "all unit tests succeed"; else exit 1; fi $(MAKE) sample_test sample_test: $(EXE_DIR)/bls_smpl.exe - python bls_smpl.py - -ifeq ($(OS),mac) - MAC_GO_LDFLAGS="-ldflags=-s" -endif -# PATH is for mingw, LD_RUN_PATH is for linux, DYLD_LIBRARY_PATH is for mac -test_go: ffi/go/bls/bls.go ffi/go/bls/bls_test.go $(BLS384_LIB) - cd ffi/go/bls && go test $(MAC_GO_LDFLAGS) . + env PATH=$$PATH:../mcl/lib $(LIBPATH_KEY)=../mcl/lib python bls_smpl.py + +# PATH is for mingw, LD_LIBRARY_PATH is for linux, DYLD_LIBRARY_PATH is for mac +COMMON_LIB_PATH="../../../lib:../../../../mcl/lib" +PATH_VAL=$$PATH:$(COMMON_LIB_PATH) LD_LIBRARY_PATH=$(COMMON_LIB_PATH) DYLD_LIBRARY_PATH=$(COMMON_LIB_PATH) +test_go256: ffi/go/bls/bls.go ffi/go/bls/bls_test.go $(BLS256_LIB) + cd ffi/go/bls && env PATH=$(PATH_VAL) go test -tags bn256 . +test_go384: ffi/go/bls/bls.go ffi/go/bls/bls_test.go $(BLS384_LIB) + cd ffi/go/bls && env PATH=$(PATH_VAL) go test -tags bn384 . +test_go384_256: ffi/go/bls/bls.go ffi/go/bls/bls_test.go $(BLS384_256_LIB) + cd ffi/go/bls && env PATH=$(PATH_VAL) go test -tags bn384_256 . + +test_go: + $(MAKE) test_go256 + $(MAKE) test_go384 + $(MAKE) test_go384_256 EMCC_OPT=-I./include -I./src -I../mcl/include -I./ -Wall -Wextra EMCC_OPT+=-O3 -DNDEBUG @@ -103,12 +144,19 @@ bls-wasm: $(MAKE) ../bls-wasm/bls_c.js clean: - $(RM) $(OBJ_DIR)/*.d $(OBJ_DIR)/*.o $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_SRC) $(ASM_OBJ) $(LLVM_SRC) $(BLS256_LIB) $(BLS256_SLIB) $(BLS384_LIB) $(BLS384_SLIB) + $(RM) $(OBJ_DIR)/*.d $(OBJ_DIR)/*.o $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_SRC) $(ASM_OBJ) $(LLVM_SRC) $(BLS256_LIB) $(BLS256_SLIB) $(BLS384_LIB) $(BLS384_SLIB) $(BLS384_256_LIB) $(BLS384_256_SLIB) ALL_SRC=$(SRC_SRC) $(TEST_SRC) $(SAMPLE_SRC) DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(ALL_SRC:.cpp=.d)) -include $(DEPEND_FILE) +PREFIX?=/usr/local +install: lib/libbls256.a lib/libbls256.$(LIB_SUF) lib/libbls384.a lib/libbls384.$(LIB_SUF) lib/libbls384_256.a lib/libbls384_256.$(LIB_SUF) + $(MKDIR) $(PREFIX)/include/bls + cp -a include/bls/ $(PREFIX)/include/ + $(MKDIR) $(PREFIX)/lib + cp -a lib/libbls256.a lib/libbls256.$(LIB_SUF) lib/libbls384.a lib/libbls384.$(LIB_SUF) lib/libbls384_256.a lib/libbls384_256.$(LIB_SUF) $(PREFIX)/lib/ + .PHONY: test bls-wasm # don't remove these files automatically diff --git a/vendor/github.com/dexon-foundation/bls/bin/.emptydir b/vendor/github.com/dexon-foundation/bls/bin/.emptydir new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/App.config b/vendor/github.com/dexon-foundation/bls/ffi/cs/App.config new file mode 100644 index 000000000..8d234373a --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/Properties/AssemblyInfo.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..201222c55 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 +// アセンブリに関連付けられている情報を変更するには、 +// これらの属性値を変更してください。 +[assembly: AssemblyTitle("bls256")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("bls256")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから +// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、 +// その型の ComVisible 属性を true に設定してください。 +[assembly: ComVisible(false)] + +// このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります +[assembly: Guid("e9d06b1b-ea22-4ef4-ba4b-422f7625966c")] + +// アセンブリのバージョン情報は次の 4 つの値で構成されています: +// +// メジャー バージョン +// マイナー バージョン +// ビルド番号 +// Revision +// +// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を +// 既定値にすることができます: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.cs new file mode 100644 index 000000000..6bcaf07fb --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.cs @@ -0,0 +1,351 @@ +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace mcl +{ + class BLS + { + public const int BN254 = 0; + public const int BLS12_381 = 5; + + const int IoEcComp = 512; // fixed byte representation + public const int FR_UNIT_SIZE = 4; + public const int FP_UNIT_SIZE = 6; // 4 if bls256.dll is used + public const int COMPILED_TIME_VAR = FR_UNIT_SIZE * 10 + FP_UNIT_SIZE; + + public const int ID_UNIT_SIZE = FR_UNIT_SIZE; + public const int SECRETKEY_UNIT_SIZE = FR_UNIT_SIZE; + public const int PUBLICKEY_UNIT_SIZE = FP_UNIT_SIZE * 3 * 2; + public const int SIGNATURE_UNIT_SIZE = FP_UNIT_SIZE * 3; + + public const int ID_SERIALIZE_SIZE = FR_UNIT_SIZE * 8; + public const int SECRETKEY_SERIALIZE_SIZE = FR_UNIT_SIZE * 8; + public const int PUBLICKEY_SERIALIZE_SIZE = FP_UNIT_SIZE * 8 * 2; + public const int SIGNATURE_SERIALIZE_SIZE = FP_UNIT_SIZE * 8; + + public const string dllName = FP_UNIT_SIZE == 4 ? "bls256.dll" : "bls384_256.dll"; + [DllImport(dllName)] + public static extern int blsInit(int curveType, int compiledTimeVar); + + [DllImport(dllName)] public static extern void blsIdSetInt(ref Id id, int x); + [DllImport(dllName)] public static extern int blsIdSetDecStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport(dllName)] public static extern int blsIdSetHexStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport(dllName)] public static extern ulong blsIdGetDecStr([Out]StringBuilder buf, ulong maxBufSize, in Id id); + [DllImport(dllName)] public static extern ulong blsIdGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in Id id); + + [DllImport(dllName)] public static extern ulong blsIdSerialize([Out]byte[] buf, ulong maxBufSize, in Id id); + [DllImport(dllName)] public static extern ulong blsSecretKeySerialize([Out]byte[] buf, ulong maxBufSize, in SecretKey sec); + [DllImport(dllName)] public static extern ulong blsPublicKeySerialize([Out]byte[] buf, ulong maxBufSize, in PublicKey pub); + [DllImport(dllName)] public static extern ulong blsSignatureSerialize([Out]byte[] buf, ulong maxBufSize, in Signature sig); + [DllImport(dllName)] public static extern ulong blsIdDeserialize(ref Id id, [In]byte[] buf, ulong bufSize); + [DllImport(dllName)] public static extern ulong blsSecretKeyDeserialize(ref SecretKey sec, [In]byte[] buf, ulong bufSize); + [DllImport(dllName)] public static extern ulong blsPublicKeyDeserialize(ref PublicKey pub, [In]byte[] buf, ulong bufSize); + [DllImport(dllName)] public static extern ulong blsSignatureDeserialize(ref Signature sig, [In]byte[] buf, ulong bufSize); + + [DllImport(dllName)] public static extern int blsIdIsEqual(in Id lhs, in Id rhs); + [DllImport(dllName)] public static extern int blsSecretKeyIsEqual(in SecretKey lhs, in SecretKey rhs); + [DllImport(dllName)] public static extern int blsPublicKeyIsEqual(in PublicKey lhs, in PublicKey rhs); + [DllImport(dllName)] public static extern int blsSignatureIsEqual(in Signature lhs, in Signature rhs); + // add + [DllImport(dllName)] public static extern void blsSecretKeyAdd(ref SecretKey sec, in SecretKey rhs); + [DllImport(dllName)] public static extern void blsPublicKeyAdd(ref PublicKey pub, in PublicKey rhs); + [DllImport(dllName)] public static extern void blsSignatureAdd(ref Signature sig, in Signature rhs); + // hash buf and set + [DllImport(dllName)] public static extern int blsHashToSecretKey(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + /* + set secretKey if system has /dev/urandom or CryptGenRandom + return 0 if success else -1 + */ + [DllImport(dllName)] public static extern int blsSecretKeySetByCSPRNG(ref SecretKey sec); + + [DllImport(dllName)] public static extern void blsGetPublicKey(ref PublicKey pub, in SecretKey sec); + [DllImport(dllName)] public static extern void blsGetPop(ref Signature sig, in SecretKey sec); + + // return 0 if success + [DllImport(dllName)] public static extern int blsSecretKeyShare(ref SecretKey sec, in SecretKey msk, ulong k, in Id id); + [DllImport(dllName)] public static extern int blsPublicKeyShare(ref PublicKey pub, in PublicKey mpk, ulong k, in Id id); + + + [DllImport(dllName)] public static extern int blsSecretKeyRecover(ref SecretKey sec, in SecretKey secVec, in Id idVec, ulong n); + [DllImport(dllName)] public static extern int blsPublicKeyRecover(ref PublicKey pub, in PublicKey pubVec, in Id idVec, ulong n); + [DllImport(dllName)] public static extern int blsSignatureRecover(ref Signature sig, in Signature sigVec, in Id idVec, ulong n); + + [DllImport(dllName)] public static extern void blsSign(ref Signature sig, in SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size); + + // return 1 if valid + [DllImport(dllName)] public static extern int blsVerify(in Signature sig, in PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size); + [DllImport(dllName)] public static extern int blsVerifyPop(in Signature sig, in PublicKey pub); + + ////////////////////////////////////////////////////////////////////////// + // the following apis will be removed + + // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r + [DllImport(dllName)] public static extern int blsIdSetLittleEndian(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + /* + return written byte size if success else 0 + */ + [DllImport(dllName)] public static extern ulong blsIdGetLittleEndian([Out]StringBuilder buf, ulong maxBufSize, in Id id); + + // return 0 if success + // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r + [DllImport(dllName)] public static extern int blsSecretKeySetLittleEndian(ref SecretKey sec, [In]byte[] buf, ulong bufSize); + [DllImport(dllName)] public static extern int blsSecretKeySetDecStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport(dllName)] public static extern int blsSecretKeySetHexStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + /* + return written byte size if success else 0 + */ + [DllImport(dllName)] public static extern ulong blsSecretKeyGetLittleEndian([Out]byte[] buf, ulong maxBufSize, in SecretKey sec); + /* + return strlen(buf) if success else 0 + buf is '\0' terminated + */ + [DllImport(dllName)] public static extern ulong blsSecretKeyGetDecStr([Out]StringBuilder buf, ulong maxBufSize, in SecretKey sec); + [DllImport(dllName)] public static extern ulong blsSecretKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in SecretKey sec); + [DllImport(dllName)] public static extern int blsPublicKeySetHexStr(ref PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport(dllName)] public static extern ulong blsPublicKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in PublicKey pub); + [DllImport(dllName)] public static extern int blsSignatureSetHexStr(ref Signature sig, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport(dllName)] public static extern ulong blsSignatureGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in Signature sig); + + public static void Init(int curveType = BN254) { + if (!System.Environment.Is64BitProcess) { + throw new PlatformNotSupportedException("not 64-bit system"); + } + int err = blsInit(curveType, COMPILED_TIME_VAR); + if (err != 0) { + throw new ArgumentException("blsInit"); + } + } + [StructLayout(LayoutKind.Sequential)] + public unsafe struct Id + { + private fixed ulong v[ID_UNIT_SIZE]; + public byte[] Serialize() { + byte[] buf = new byte[ID_SERIALIZE_SIZE]; + ulong n = blsIdSerialize(buf, (ulong)buf.Length, this); + if (n == 0) { + throw new ArithmeticException("blsIdSerialize"); + } + return buf; + } + public void Deserialize(byte[] buf) { + ulong n = blsIdDeserialize(ref this, buf, (ulong)buf.Length); + if (n == 0) { + throw new ArithmeticException("blsIdDeserialize"); + } + } + public bool IsEqual(in Id rhs) { + return blsIdIsEqual(this, rhs) != 0; + } + public void SetDecStr(string s) { + if (blsIdSetDecStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsIdSetDecSt:" + s); + } + } + public void SetHexStr(string s) { + if (blsIdSetHexStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsIdSetHexStr:" + s); + } + } + public void SetInt(int x) { + blsIdSetInt(ref this, x); + } + public string GetDecStr() { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsIdGetDecStr(sb, (ulong)sb.Capacity, this); + if (size == 0) { + throw new ArgumentException("blsIdGetDecStr"); + } + return sb.ToString(0, (int)size); + } + public string GetHexStr() { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsIdGetHexStr(sb, (ulong)sb.Capacity, this); + if (size == 0) { + throw new ArgumentException("blsIdGetHexStr"); + } + return sb.ToString(0, (int)size); + } + } + [StructLayout(LayoutKind.Sequential)] + public unsafe struct SecretKey + { + private fixed ulong v[SECRETKEY_UNIT_SIZE]; + public byte[] Serialize() { + byte[] buf = new byte[SECRETKEY_SERIALIZE_SIZE]; + ulong n = blsSecretKeySerialize(buf, (ulong)buf.Length, this); + if (n == 0) { + throw new ArithmeticException("blsSecretKeySerialize"); + } + return buf; + } + public void Deserialize(byte[] buf) { + ulong n = blsSecretKeyDeserialize(ref this, buf, (ulong)buf.Length); + if (n == 0) { + throw new ArithmeticException("blsSecretKeyDeserialize"); + } + } + public bool IsEqual(in SecretKey rhs) { + return blsSecretKeyIsEqual(this, rhs) != 0; + } + public void SetHexStr(string s) { + if (blsSecretKeySetHexStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsSecretKeySetHexStr:" + s); + } + } + public string GetHexStr() { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsSecretKeyGetHexStr(sb, (ulong)sb.Capacity, this); + if (size == 0) { + throw new ArgumentException("mclBnFr_getStr"); + } + return sb.ToString(0, (int)size); + } + public void Add(in SecretKey rhs) { + blsSecretKeyAdd(ref this, rhs); + } + public void SetByCSPRNG() { + blsSecretKeySetByCSPRNG(ref this); + } + public void SetHashOf(string s) { + if (blsHashToSecretKey(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsHashToSecretKey"); + } + } + public PublicKey GetPublicKey() { + PublicKey pub; + blsGetPublicKey(ref pub, this); + return pub; + } + public Signature Sign(string m) { + Signature sig; + blsSign(ref sig, this, m, (ulong)m.Length); + return sig; + } + public Signature GetPop() { + Signature sig; + blsGetPop(ref sig, this); + return sig; + } + } + // secretKey = sum_{i=0}^{msk.Length - 1} msk[i] * id^i + public static SecretKey ShareSecretKey(in SecretKey[] msk, in Id id) { + SecretKey sec; + if (blsSecretKeyShare(ref sec, msk[0], (ulong)msk.Length, id) != 0) { + throw new ArgumentException("GetSecretKeyForId:" + id.ToString()); + } + return sec; + } + public static SecretKey RecoverSecretKey(in SecretKey[] secVec, in Id[] idVec) { + SecretKey sec; + if (blsSecretKeyRecover(ref sec, secVec[0], idVec[0], (ulong)secVec.Length) != 0) { + throw new ArgumentException("Recover"); + } + return sec; + } + [StructLayout(LayoutKind.Sequential)] + public unsafe struct PublicKey + { + private fixed ulong v[PUBLICKEY_UNIT_SIZE]; + public byte[] Serialize() { + byte[] buf = new byte[PUBLICKEY_SERIALIZE_SIZE]; + ulong n = blsPublicKeySerialize(buf, (ulong)buf.Length, this); + if (n == 0) { + throw new ArithmeticException("blsPublicKeySerialize"); + } + return buf; + } + public void Deserialize(byte[] buf) { + ulong n = blsPublicKeyDeserialize(ref this, buf, (ulong)buf.Length); + if (n == 0) { + throw new ArithmeticException("blsPublicKeyDeserialize"); + } + } + public bool IsEqual(in PublicKey rhs) { + return blsPublicKeyIsEqual(this, rhs) != 0; + } + public void SetStr(string s) { + if (blsPublicKeySetHexStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsPublicKeySetStr:" + s); + } + } + public string GetHexStr() { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsPublicKeyGetHexStr(sb, (ulong)sb.Capacity, this); + if (size == 0) { + throw new ArgumentException("blsPublicKeyGetStr"); + } + return sb.ToString(0, (int)size); + } + public void Add(in PublicKey rhs) { + blsPublicKeyAdd(ref this, rhs); + } + public bool Verify(in Signature sig, string m) { + return blsVerify(sig, this, m, (ulong)m.Length) == 1; + } + public bool VerifyPop(in Signature pop) { + return blsVerifyPop(pop, this) == 1; + } + } + // publicKey = sum_{i=0}^{mpk.Length - 1} mpk[i] * id^i + public static PublicKey SharePublicKey(in PublicKey[] mpk, in Id id) { + PublicKey pub; + if (blsPublicKeyShare(ref pub, mpk[0], (ulong)mpk.Length, id) != 0) { + throw new ArgumentException("GetPublicKeyForId:" + id.ToString()); + } + return pub; + } + public static PublicKey RecoverPublicKey(in PublicKey[] pubVec, in Id[] idVec) { + PublicKey pub; + if (blsPublicKeyRecover(ref pub, pubVec[0], idVec[0], (ulong)pubVec.Length) != 0) { + throw new ArgumentException("Recover"); + } + return pub; + } + [StructLayout(LayoutKind.Sequential)] + public unsafe struct Signature + { + private fixed ulong v[SIGNATURE_UNIT_SIZE]; + public byte[] Serialize() { + byte[] buf = new byte[SIGNATURE_SERIALIZE_SIZE]; + ulong n = blsSignatureSerialize(buf, (ulong)buf.Length, this); + if (n == 0) { + throw new ArithmeticException("blsSignatureSerialize"); + } + return buf; + } + public void Deserialize(byte[] buf) { + ulong n = blsSignatureDeserialize(ref this, buf, (ulong)buf.Length); + if (n == 0) { + throw new ArithmeticException("blsSignatureDeserialize"); + } + } + public bool IsEqual(in Signature rhs) { + return blsSignatureIsEqual(this, rhs) != 0; + } + public void SetStr(string s) { + if (blsSignatureSetHexStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsSignatureSetStr:" + s); + } + } + public string GetHexStr() { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsSignatureGetHexStr(sb, (ulong)sb.Capacity, this); + if (size == 0) { + throw new ArgumentException("blsSignatureGetStr"); + } + return sb.ToString(0, (int)size); + } + public void Add(in Signature rhs) { + blsSignatureAdd(ref this, rhs); + } + } + public static Signature RecoverSign(in Signature[] sigVec, in Id[] idVec) { + Signature sig; + if (blsSignatureRecover(ref sig, sigVec[0], idVec[0], (ulong)sigVec.Length) != 0) { + throw new ArgumentException("Recover"); + } + return sig; + } + } +} diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.csproj b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.csproj new file mode 100644 index 000000000..c03afa436 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.csproj @@ -0,0 +1,97 @@ + + + + + Debug + AnyCPU + {E9D06B1B-EA22-4EF4-BA4B-422F7625966D} + Exe + Properties + bls + bls + v4.6.2 + 512 + true + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + ..\..\bin\ + DEBUG;TRACE + true + full + x64 + prompt + MinimumRecommendedRules.ruleset + 7.2 + false + + + ..\..\bin\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + false + true + 7.2 + + + true + + + + + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4.5.2 %28x86 および x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + \ No newline at end of file diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.sln b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.sln new file mode 100644 index 000000000..7c3dfba7b --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.539 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bls", "bls.csproj", "{E9D06B1B-EA22-4EF4-BA4B-422F7625966D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E9D06B1B-EA22-4EF4-BA4B-422F7625966D}.Debug|x64.ActiveCfg = Debug|x64 + {E9D06B1B-EA22-4EF4-BA4B-422F7625966D}.Debug|x64.Build.0 = Debug|x64 + {E9D06B1B-EA22-4EF4-BA4B-422F7625966D}.Release|x64.ActiveCfg = Release|x64 + {E9D06B1B-EA22-4EF4-BA4B-422F7625966D}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1935C301-6478-4F82-9587-6A66B531E327} + EndGlobalSection +EndGlobal diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.cs new file mode 100644 index 000000000..3ef5fab9a --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.cs @@ -0,0 +1,298 @@ +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace mcl { + class BLS256 { + const int IoEcComp = 512; // fixed byte representation + public const int MCLBN_FR_UNIT_SIZE = 4; + public const int MCLBN_FP_UNIT_SIZE = 4; + public const int MCLBN_COMPILED_TIME_VAR = MCLBN_FR_UNIT_SIZE * 10 + MCLBN_FP_UNIT_SIZE; + [DllImport("bls256.dll")] + public static extern int blsInit(int curve, int compiledTimeVar); + + [DllImport("bls256.dll")] public static extern void blsIdSetInt(ref Id id, int x); + [DllImport("bls256.dll")] public static extern int blsIdSetDecStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport("bls256.dll")] public static extern int blsIdSetHexStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport("bls256.dll")] public static extern ulong blsIdGetDecStr([Out]StringBuilder buf, ulong maxBufSize, ref Id id); + [DllImport("bls256.dll")] public static extern ulong blsIdGetHexStr([Out]StringBuilder buf, ulong maxBufSize, ref Id id); + + + [DllImport("bls256.dll")] public static extern ulong blsIdSerialize([Out]StringBuilder buf, ulong maxBufSize, ref Id id); + [DllImport("bls256.dll")] public static extern ulong blsSecretKeySerialize([Out]StringBuilder buf, ulong maxBufSize, ref SecretKey sec); + [DllImport("bls256.dll")] public static extern ulong blsPublicKeySerialize([Out]StringBuilder buf, ulong maxBufSize, ref PublicKey pub); + [DllImport("bls256.dll")] public static extern ulong blsSignatureSerialize([Out]StringBuilder buf, ulong maxBufSize, ref Signature sig); + + [DllImport("bls256.dll")] public static extern int blsIdDeserialize(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport("bls256.dll")] public static extern int blsSecretKeyDeserialize(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport("bls256.dll")] public static extern int blsPublicKeyDeserialize(ref PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport("bls256.dll")] public static extern int blsSignatureDeserialize(ref Signature sig, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + + [DllImport("bls256.dll")] public static extern int blsIdIsEqual(ref Id lhs, ref Id rhs); + [DllImport("bls256.dll")] public static extern int blsSecretKeyIsEqual(ref SecretKey lhs, ref SecretKey rhs); + [DllImport("bls256.dll")] public static extern int blsPublicKeyIsEqual(ref PublicKey lhs, ref PublicKey rhs); + [DllImport("bls256.dll")] public static extern int blsSignatureIsEqual(ref Signature lhs, ref Signature rhs); + + // add + [DllImport("bls256.dll")] public static extern void blsSecretKeyAdd(ref SecretKey sec, ref SecretKey rhs); + [DllImport("bls256.dll")] public static extern void blsPublicKeyAdd(ref PublicKey pub, ref PublicKey rhs); + [DllImport("bls256.dll")] public static extern void blsSignatureAdd(ref Signature sig, ref Signature rhs); + + // hash buf and set + [DllImport("bls256.dll")] public static extern int blsHashToSecretKey(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + /* + set secretKey if system has /dev/urandom or CryptGenRandom + return 0 if success else -1 + */ + [DllImport("bls256.dll")] public static extern int blsSecretKeySetByCSPRNG(ref SecretKey sec); + + [DllImport("bls256.dll")] public static extern void blsGetPublicKey(ref PublicKey pub, ref SecretKey sec); + [DllImport("bls256.dll")] public static extern void blsGetPop(ref Signature sig, ref SecretKey sec); + + // return 0 if success + [DllImport("bls256.dll")] public static extern int blsSecretKeyShare(ref SecretKey sec, ref SecretKey msk, ulong k, ref Id id); + [DllImport("bls256.dll")] public static extern int blsPublicKeyShare(ref PublicKey pub, ref PublicKey mpk, ulong k, ref Id id); + + + [DllImport("bls256.dll")] public static extern int blsSecretKeyRecover(ref SecretKey sec, ref SecretKey secVec, ref Id idVec, ulong n); + [DllImport("bls256.dll")] public static extern int blsPublicKeyRecover(ref PublicKey pub, ref PublicKey pubVec, ref Id idVec, ulong n); + [DllImport("bls256.dll")] public static extern int blsSignatureRecover(ref Signature sig, ref Signature sigVec, ref Id idVec, ulong n); + + [DllImport("bls256.dll")] public static extern void blsSign(ref Signature sig, ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size); + + // return 1 if valid + [DllImport("bls256.dll")] public static extern int blsVerify(ref Signature sig, ref PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size); + [DllImport("bls256.dll")] public static extern int blsVerifyPop(ref Signature sig, ref PublicKey pub); + + ////////////////////////////////////////////////////////////////////////// + // the following apis will be removed + + // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r + [DllImport("bls256.dll")] public static extern int blsIdSetLittleEndian(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + /* + return written byte size if success else 0 + */ + [DllImport("bls256.dll")] public static extern ulong blsIdGetLittleEndian([Out]StringBuilder buf, ulong maxBufSize, ref Id id); + + // return 0 if success + // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r + [DllImport("bls256.dll")] public static extern int blsSecretKeySetLittleEndian(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport("bls256.dll")] public static extern int blsSecretKeySetDecStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport("bls256.dll")] public static extern int blsSecretKeySetHexStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + /* + return written byte size if success else 0 + */ + [DllImport("bls256.dll")] public static extern ulong blsSecretKeyGetLittleEndian([Out]StringBuilder buf, ulong maxBufSize, ref SecretKey sec); + /* + return strlen(buf) if success else 0 + buf is '\0' terminated + */ + [DllImport("bls256.dll")] public static extern ulong blsSecretKeyGetDecStr([Out]StringBuilder buf, ulong maxBufSize, ref SecretKey sec); + [DllImport("bls256.dll")] public static extern ulong blsSecretKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, ref SecretKey sec); + [DllImport("bls256.dll")] public static extern int blsPublicKeySetHexStr(ref PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport("bls256.dll")] public static extern ulong blsPublicKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, ref PublicKey pub); + [DllImport("bls256.dll")] public static extern int blsSignatureSetHexStr(ref Signature sig, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize); + [DllImport("bls256.dll")] public static extern ulong blsSignatureGetHexStr([Out]StringBuilder buf, ulong maxBufSize, ref Signature sig); + + public static void Init() + { + const int CurveFp254BNb = 0; + if (!System.Environment.Is64BitProcess) { + throw new PlatformNotSupportedException("not 64-bit system"); + } + int err = blsInit(CurveFp254BNb, MCLBN_COMPILED_TIME_VAR); + if (err != 0) { + throw new ArgumentException("blsInit"); + } + } + + public struct Id { + private ulong v0, v1, v2, v3; + public bool IsEqual(Id rhs) + { + return blsIdIsEqual(ref this, ref rhs) != 0; + } + public void SetDecStr(String s) + { + if (blsIdSetDecStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsIdSetDecSt:" + s); + } + } + public void SetHexStr(String s) + { + if (blsIdSetHexStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsIdSetHexStr:" + s); + } + } + public void SetInt(int x) + { + blsIdSetInt(ref this, x); + } + public string GetDecStr() + { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsIdGetDecStr(sb, (ulong)sb.Capacity, ref this); + if (size == 0) { + throw new ArgumentException("blsIdGetDecStr"); + } + return sb.ToString(0, (int)size); + } + public string GetHexStr() + { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsIdGetHexStr(sb, (ulong)sb.Capacity, ref this); + if (size == 0) { + throw new ArgumentException("blsIdGetHexStr"); + } + return sb.ToString(0, (int)size); + } + } + public struct SecretKey { + private ulong v0, v1, v2, v3; + public bool IsEqual(SecretKey rhs) + { + return blsSecretKeyIsEqual(ref this, ref rhs) != 0; + } + public void SetHexStr(String s) + { + if (blsSecretKeySetHexStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsSecretKeySetHexStr:" + s); + } + } + public string GetHexStr() + { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsSecretKeyGetHexStr(sb, (ulong)sb.Capacity, ref this); + if (size == 0) { + throw new ArgumentException("mclBnFr_getStr"); + } + return sb.ToString(0, (int)size); + } + public void Add(SecretKey rhs) + { + blsSecretKeyAdd(ref this, ref rhs); + } + public void SetByCSPRNG() + { + blsSecretKeySetByCSPRNG(ref this); + } + public void SetHashOf(string s) + { + if (blsHashToSecretKey(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsHashToSecretKey"); + } + } + public PublicKey GetPublicKey() + { + PublicKey pub = new PublicKey(); + blsGetPublicKey(ref pub, ref this); + return pub; + } + public Signature Signature(String m) + { + Signature Signature = new Signature(); + blsSign(ref Signature, ref this, m, (ulong)m.Length); + return Signature; + } + } + // secretKey = sum_{i=0}^{msk.Length - 1} msk[i] * id^i + public static SecretKey ShareSecretKey(SecretKey[] msk, Id id) + { + SecretKey sec = new SecretKey(); + if (blsSecretKeyShare(ref sec, ref msk[0], (ulong)msk.Length, ref id) != 0) { + throw new ArgumentException("GetSecretKeyForId:" + id.ToString()); + } + return sec; + } + public static SecretKey RecoverSecretKey(SecretKey[] secs, Id[] ids) + { + SecretKey sec = new SecretKey(); + if (blsSecretKeyRecover(ref sec, ref secs[0], ref ids[0], (ulong)secs.Length) != 0) { + throw new ArgumentException("Recover"); + } + return sec; + } + public struct PublicKey { + private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11; + private ulong v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23; + public bool IsEqual(PublicKey rhs) + { + return blsPublicKeyIsEqual(ref this, ref rhs) != 0; + } + public void SetStr(String s) + { + if (blsPublicKeySetHexStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsPublicKeySetStr:" + s); + } + } + public string GetHexStr() + { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsPublicKeyGetHexStr(sb, (ulong)sb.Capacity, ref this); + if (size == 0) { + throw new ArgumentException("blsPublicKeyGetStr"); + } + return sb.ToString(0, (int)size); + } + public void Add(PublicKey rhs) + { + blsPublicKeyAdd(ref this, ref rhs); + } + public bool Verify(Signature Signature, string m) + { + return blsVerify(ref Signature, ref this, m, (ulong)m.Length) == 1; + } + } + // publicKey = sum_{i=0}^{mpk.Length - 1} mpk[i] * id^i + public static PublicKey SharePublicKey(PublicKey[] mpk, Id id) + { + PublicKey pub = new PublicKey(); + if (blsPublicKeyShare(ref pub, ref mpk[0], (ulong)mpk.Length, ref id) != 0) { + throw new ArgumentException("GetPublicKeyForId:" + id.ToString()); + } + return pub; + } + public static PublicKey RecoverPublicKey(PublicKey[] pubs, Id[] ids) + { + PublicKey pub = new PublicKey(); + if (blsPublicKeyRecover(ref pub, ref pubs[0], ref ids[0], (ulong)pubs.Length) != 0) { + throw new ArgumentException("Recover"); + } + return pub; + } + public struct Signature { + private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11; + public bool IsEqual(Signature rhs) + { + return blsSignatureIsEqual(ref this, ref rhs) != 0; + } + public void SetStr(String s) + { + if (blsSignatureSetHexStr(ref this, s, (ulong)s.Length) != 0) { + throw new ArgumentException("blsSignatureSetStr:" + s); + } + } + public string GetHexStr() + { + StringBuilder sb = new StringBuilder(1024); + ulong size = blsSignatureGetHexStr(sb, (ulong)sb.Capacity, ref this); + if (size == 0) { + throw new ArgumentException("blsSignatureGetStr"); + } + return sb.ToString(0, (int)size); + } + public void Add(Signature rhs) + { + blsSignatureAdd(ref this, ref rhs); + } + } + public static Signature RecoverSign(Signature[] signs, Id[] ids) + { + Signature Signature = new Signature(); + if (blsSignatureRecover(ref Signature, ref signs[0], ref ids[0], (ulong)signs.Length) != 0) { + throw new ArgumentException("Recover"); + } + return Signature; + } + } +} diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.csproj b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.csproj new file mode 100644 index 000000000..032a1d347 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.csproj @@ -0,0 +1,62 @@ + + + + + Debug + AnyCPU + {E9D06B1B-EA22-4EF4-BA4B-422F7625966C} + Exe + Properties + bls256 + bls256 + v4.5.2 + 512 + true + + + true + ..\..\bin\ + DEBUG;TRACE + false + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + ..\..\bin\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.sln b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.sln new file mode 100644 index 000000000..eb29af97b --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBD}") = "bls256", "bls256.csproj", "{E9D06B1B-EA22-4EF4-BA4B-422F7625966C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E9D06B1B-EA22-4EF4-BA4B-422F7625966C}.Debug|x64.ActiveCfg = Debug|x64 + {E9D06B1B-EA22-4EF4-BA4B-422F7625966C}.Debug|x64.Build.0 = Debug|x64 + {E9D06B1B-EA22-4EF4-BA4B-422F7625966C}.Release|x64.ActiveCfg = Release|x64 + {E9D06B1B-EA22-4EF4-BA4B-422F7625966C}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256_test.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256_test.cs new file mode 100644 index 000000000..989993e0f --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls256_test.cs @@ -0,0 +1,126 @@ +using System; + +namespace mcl { + using static BLS256; + class BLS256Test { + static int err = 0; + static void assert(string msg, bool b) + { + if (b) return; + Console.WriteLine("ERR {0}", msg); + err++; + } + static void TestId() + { + Console.WriteLine("TestId"); + Id id = new Id(); + id.SetDecStr("255"); + assert("GetStr(10)", id.GetDecStr() == "255"); + assert("GetStr(16)", id.GetHexStr() == "ff"); + } + static void TestSecretKey() + { + Console.WriteLine("TestSecretKey"); + SecretKey sec = new SecretKey(); + sec.SetHexStr("ff"); + assert("GetHexStr()", sec.GetHexStr() == "ff"); + { + SecretKey sec2 = new SecretKey(); + sec.SetHexStr("321"); + sec2.SetHexStr("4000"); + sec.Add(sec2); + assert("sec.Add", sec.GetHexStr() == "4321"); + sec.SetByCSPRNG(); + Console.WriteLine("sec.Init={0}", sec.GetHexStr()); + } + } + static void TestPublicKey() + { + Console.WriteLine("TestPublicKey"); + SecretKey sec = new SecretKey(); + sec.SetByCSPRNG(); + PublicKey pub = sec.GetPublicKey(); + String s = pub.GetHexStr(); + Console.WriteLine("pub={0}", s); + PublicKey pub2 = new PublicKey(); + pub2.SetStr(s); + assert("pub.SetStr", pub.IsEqual(pub2)); + } + static void TestSign() + { + Console.WriteLine("TestSign"); + SecretKey sec = new SecretKey(); + sec.SetByCSPRNG(); + PublicKey pub = sec.GetPublicKey(); + String m = "abc"; + Signature sig = sec.Signature(m); + assert("verify", pub.Verify(sig, m)); + assert("not verify", !pub.Verify(sig, m + "a")); + } + static void TestSharing() + { + Console.WriteLine("TestSharing"); + int k = 5; + SecretKey[] msk = new SecretKey[k]; + PublicKey[] mpk = new PublicKey[k]; + // make master secretkey + for (int i = 0; i < k; i++) { + msk[i].SetByCSPRNG(); + mpk[i] = msk[i].GetPublicKey(); + } + int n = 30; + Id[] ids = new Id[n]; + SecretKey[] secs = new SecretKey[n]; + PublicKey[] pubs = new PublicKey[n]; + for (int i = 0; i < n; i++) { + ids[i].SetInt(i * i + 123); + secs[i] = ShareSecretKey(msk, ids[i]); + pubs[i] = SharePublicKey(mpk, ids[i]); + assert("share publicKey", secs[i].GetPublicKey().IsEqual(pubs[i])); + } + string m = "doremi"; + for (int i = 0; i < n; i++) { + Signature Signature = secs[i].Signature(m); + assert("Signature.Verify", pubs[i].Verify(Signature, m)); + } + { + int[] idxTbl = { 0, 2, 5, 8, 10 }; + assert("idxTbl.Length=k", idxTbl.Length == k); + Id[] subIds = new Id[k]; + SecretKey[] subSecs = new SecretKey[k]; + PublicKey[] subPubs = new PublicKey[k]; + Signature[] subSigns = new Signature[k]; + for (int i = 0; i < k; i++) { + int idx = idxTbl[i]; + subIds[i] = ids[idx]; + subSecs[i] = secs[idx]; + subPubs[i] = pubs[idx]; + subSigns[i] = secs[idx].Signature(m); + } + SecretKey sec = RecoverSecretKey(subSecs, subIds); + PublicKey pub = RecoverPublicKey(subPubs, subIds); + assert("check pub", pub.IsEqual(sec.GetPublicKey())); + Signature Signature = RecoverSign(subSigns, subIds); + assert("Signature.verify", pub.Verify(Signature, m)); + } + } + static void Main(string[] args) + { + try { + Init(); + TestId(); + TestSecretKey(); + TestPublicKey(); + TestSign(); + TestSharing(); + if (err == 0) { + Console.WriteLine("all tests succeed"); + } else { + Console.WriteLine("err={0}", err); + } + } catch (Exception e) { + Console.WriteLine("ERR={0}", e); + } + } + } +} diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/bls_test.cs b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls_test.cs new file mode 100644 index 000000000..2eb451ba9 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/bls_test.cs @@ -0,0 +1,176 @@ +using System; + +namespace mcl +{ + using static BLS; + class BLSTest + { + static int err = 0; + static void assert(string msg, bool b) { + if (b) return; + Console.WriteLine("ERR {0}", msg); + err++; + } + static void TestId() { + Console.WriteLine("TestId"); + Id id1; + id1.SetDecStr("255"); + assert("GetStr(10)", id1.GetDecStr() == "255"); + assert("GetStr(16)", id1.GetHexStr() == "ff"); + Id id2; + id2.SetInt(255); + assert("IsEqual", id1.IsEqual(id2)); + } + static void TestSecretKey() { + Console.WriteLine("TestSecretKey"); + SecretKey sec; + sec.SetHexStr("ff"); + assert("GetHexStr()", sec.GetHexStr() == "ff"); + { + SecretKey sec2; + sec.SetHexStr("321"); + sec2.SetHexStr("4000"); + sec.Add(sec2); + assert("sec.Add", sec.GetHexStr() == "4321"); + sec.SetByCSPRNG(); + Console.WriteLine("sec.Init={0}", sec.GetHexStr()); + } + { + SecretKey sec2; + byte[] buf = sec.Serialize(); + sec2.Deserialize(buf); + assert("serialize", sec2.IsEqual(sec)); + } + } + static void TestPublicKey() { + Console.WriteLine("TestPublicKey"); + SecretKey sec; + sec.SetByCSPRNG(); + PublicKey pub = sec.GetPublicKey(); + string s = pub.GetHexStr(); + Console.WriteLine("pub={0}", s); + { + PublicKey pub2; + pub2.SetStr(s); + assert("pub.SetStr", pub.IsEqual(pub2)); + } + { + PublicKey pub2; + byte[] buf = pub.Serialize(); + pub2.Deserialize(buf); + assert("serialize", pub2.IsEqual(pub)); + } + } + static void TestSign() { + Console.WriteLine("TestSign"); + SecretKey sec; + sec.SetByCSPRNG(); + PublicKey pub = sec.GetPublicKey(); + string m = "abc"; + Signature sig = sec.Sign(m); + Console.WriteLine("sig={0}", sig.GetHexStr()); + assert("verify", pub.Verify(sig, m)); + assert("not verify", !pub.Verify(sig, m + "a")); + { + Signature sig2; + byte[] buf = sig.Serialize(); + sig2.Deserialize(buf); + assert("serialize", sig2.IsEqual(sig)); + } + } + static void TestSharing() { + Console.WriteLine("TestSharing"); + int k = 5; + SecretKey[] msk = new SecretKey[k]; + PublicKey[] mpk = new PublicKey[k]; + // make master secretkey + for (int i = 0; i < k; i++) { + msk[i].SetByCSPRNG(); + mpk[i] = msk[i].GetPublicKey(); + } + int n = 30; + Id[] ids = new Id[n]; + SecretKey[] secs = new SecretKey[n]; + PublicKey[] pubs = new PublicKey[n]; + for (int i = 0; i < n; i++) { + ids[i].SetInt(i * i + 123); + secs[i] = ShareSecretKey(msk, ids[i]); + pubs[i] = SharePublicKey(mpk, ids[i]); + assert("share publicKey", secs[i].GetPublicKey().IsEqual(pubs[i])); + } + string m = "doremi"; + for (int i = 0; i < n; i++) { + Signature Signature = secs[i].Sign(m); + assert("Signature.Verify", pubs[i].Verify(Signature, m)); + } + { + int[] idxTbl = { 0, 2, 5, 8, 10 }; + assert("idxTbl.Length=k", idxTbl.Length == k); + Id[] subIds = new Id[k]; + SecretKey[] subSecs = new SecretKey[k]; + PublicKey[] subPubs = new PublicKey[k]; + Signature[] subSigns = new Signature[k]; + for (int i = 0; i < k; i++) { + int idx = idxTbl[i]; + subIds[i] = ids[idx]; + subSecs[i] = secs[idx]; + subPubs[i] = pubs[idx]; + subSigns[i] = secs[idx].Sign(m); + } + SecretKey sec = RecoverSecretKey(subSecs, subIds); + PublicKey pub = RecoverPublicKey(subPubs, subIds); + assert("check pub", pub.IsEqual(sec.GetPublicKey())); + Signature Signature = RecoverSign(subSigns, subIds); + assert("Signature.verify", pub.Verify(Signature, m)); + } + } + static void TestAggregate() { + Console.WriteLine("TestAggregate"); + const int n = 10; + const string m = "abc"; + SecretKey[] secVec = new SecretKey[n]; + PublicKey[] pubVec = new PublicKey[n]; + Signature[] popVec = new Signature[n]; + Signature[] sigVec = new Signature[n]; + for (int i = 0; i < n; i++) { + secVec[i].SetByCSPRNG(); + pubVec[i] = secVec[i].GetPublicKey(); + popVec[i] = secVec[i].GetPop(); + sigVec[i] = secVec[i].Sign(m); + } + SecretKey secAgg; + PublicKey pubAgg; + Signature sigAgg; + for (int i = 0; i < n; i++) { + secAgg.Add(secVec[i]); + assert("verify pop", pubVec[i].VerifyPop(popVec[i])); + pubAgg.Add(pubVec[i]); + sigAgg.Add(sigVec[i]); + } + assert("aggregate sec", secAgg.Sign(m).IsEqual(sigAgg)); + assert("aggregate", pubAgg.Verify(sigAgg, m)); + } + static void Main(string[] args) { + try { + int[] curveTypeTbl = { BN254, BLS12_381 }; + foreach (int curveType in curveTypeTbl) { + Console.WriteLine("curveType={0}", curveType); + Init(curveType); + TestId(); + TestSecretKey(); + TestPublicKey(); + TestSign(); + TestSharing(); + TestAggregate(); + if (err == 0) { + Console.WriteLine("all tests succeed"); + } else { + Console.WriteLine("err={0}", err); + } + } + } catch (Exception e) { + Console.WriteLine("ERR={0}", e); + } + } + } +} diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/readme-ja.md b/vendor/github.com/dexon-foundation/bls/ffi/cs/readme-ja.md new file mode 100644 index 000000000..199135725 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/readme-ja.md @@ -0,0 +1,188 @@ +# BLS署名のC#バインディング + +# 必要環境 + +* Visual Studio 2017(x64) or later +* C# 7.2 or later +* .NET Framework 4.5.2 or later + +# DLLのビルド方法 + +Visual Studio 2017の64bit用コマンドプロンプトを開いて +``` +md work +cd work +git clone https://github.com/herumi/cybozulib_ext +git clone https://github.com/herumi/mcl +git clone https://github.com/herumi/bls +cd bls +mklib dll +``` +`bls/bin/*.dll`が作成される。 + +# サンプルのビルド方法 + +bls/ffi/cs/bls.slnを開いて実行する。 + +* 注意 bls256.slnは古いため使わないでください。 + +# クラスとAPI + +## API + +* `Init(int curveType = BN254);` + * ライブラリを曲線curveTypeで初期化する。 + * curveType = BN254 or BLS12_381 +* `SecretKey ShareSecretKey(in SecretKey[] msk, in Id id);` + * マスター秘密鍵の列mskに対するidの秘密鍵を生成(共有)する。 +* `SecretKey RecoverSecretKey(in SecretKey[] secVec, in Id[] idVec);` + * 秘密鍵secVecとID idVecのペアから秘密鍵を復元する。 +* `PublicKey SharePublicKey(in PublicKey[] mpk, in Id id);` + * マスター公開鍵の列mpkに対するidの公開鍵を生成(共有)する。 +* `PublicKey RecoverPublicKey(in PublicKey[] pubVec, in Id[] idVec);` + * 公開鍵pubVecとID idVecのペアから公開鍵を復元する。 +* `Signature RecoverSign(in Signature[] sigVec, in Id[] idVec);` + * 署名sigVecとID idVecのペアから署名を復元する。 + +## Id + +識別子クラス + +* `byte[] Serialize();` + * Idをシリアライズする。 +* `void Deserialize(byte[] buf);` + * バイト列bufからIdをデシリアライズする。 +* `bool IsEqual(in Id rhs);` + * 同値判定。 +* `void SetDecStr(string s);` + * 10進数文字列を設定する。 +* `void SetHexStr(string s);` + * 16進数文字列を設定する。 +* `void SetInt(int x);` + * 整数xを設定する。 +* `string GetDecStr();` + * 10進数表記を取得する。 +* `string GetHexStr();` + * 16進数表記を取得する。 + +## SecretKey + +* `byte[] Serialize();` + * Idをシリアライズする。 +* `void Deserialize(byte[] buf);` + * バイト列bufからSecretKeyをデシリアライズする。 +* `bool IsEqual(in SecretKey rhs);` + * 同値判定。 +* `void SetHexStr(string s);` + * 16進数文字列を設定する。 +* `string GetHexStr();` + * 16進数表記を取得する。 +* `void Add(in SecretKey rhs);` + * 秘密鍵rhsを加算する。 +* `void SetByCSPRNG();` + * 暗号学的乱数で設定する。 +* `void SetHashOf(string s);` + * 文字列sのハッシュ値を設定する。 +* `PublicKey GetPublicKey();` + * 対応する公開鍵を取得する。 +* `Signature Sign(string m);` + * 文字列mの署名を生成する。 +* `Signature GetPop();` + * 自身の秘密鍵による署名(Proof Of Posession)を生成する。 + +## PublicKey + +* `byte[] Serialize();` + * PublicKeyをシリアライズする。 +* `void Deserialize(byte[] buf);` + * バイト列bufからPublicKeyをデシリアライズする。 +* `bool IsEqual(in PublicKey rhs);` + * 同値判定。 +* `void Add(in PublicKey rhs);` + * 公開鍵rhsを加算する。 +* `void SetHexStr(string s);` + * 16進数文字列を設定する。 +* `string GetHexStr();` + * 16進数表記を取得する。 +* `bool Verify(in Signature sig, string m);` + * 文字列mに対する署名sigの正当性を確認する。 +* `bool VerifyPop(in Signature pop);` + * PoPの正当性を確認する。 + +## Signature + +* `byte[] Serialize();` + * Signatureをシリアライズする。 +* `void Deserialize(byte[] buf);` + * バイト列bufからSignatureをデシリアライズする。 +* `bool IsEqual(in Signature rhs);` + * 同値判定。 +* `void Add(in Signature rhs);` + * 署名rhsを加算する。 +* `void SetHexStr(string s);` + * 16進数文字列を設定する。 +* `string GetHexStr();` + * 16進数表記を取得する。 + +## 使い方 + +### 最小サンプル + +``` +using static BLS; + +Init(BN254); // ライブラリ初期化 +SecretKey sec; +sec.SetByCSPRNG(); // 秘密鍵の初期化 +PublicKey pub = sec.GetPublicKey(); // 公開鍵の取得 +string m = "abc"; +Signature sig = sec.Sign(m); // 署名の作成 +if (pub.Verify(sig, m))) { + // 署名の確認 +} +``` + +### 集約署名 +``` +Init(BN254); // ライブラリ初期化 +const int n = 10; +const string m = "abc"; +SecretKey[] secVec = new SecretKey[n]; +PublicKey[] pubVec = new PublicKey[n]; +Signature[] popVec = new Signature[n]; +Signature[] sigVec = new Signature[n]; + +for (int i = 0; i < n; i++) { + secVec[i].SetByCSPRNG(); // 秘密鍵の初期化 + pubVec[i] = secVec[i].GetPublicKey(); // 公開鍵の取得 + popVec[i] = secVec[i].GetPop(); // 所有(PoP)の証明 + sigVec[i] = secVec[i].Sign(m); // 署名 +} + +SecretKey secAgg; +PublicKey pubAgg; +Signature sigAgg; +for (int i = 0; i < n; i++) { + // PoPの確認 + if (pubVec[i].VerifyPop(popVec[i]))) { + // エラー + return; + } + pubAgg.Add(pubVec[i]); // 公開鍵の集約 + sigAgg.Add(sigVec[i]); // 署名の集約 +} +if (pubAgg.Verify(sigAgg, m)) { + // 署名の確認 +} +``` + +# ライセンス + +modified new BSD License +http://opensource.org/licenses/BSD-3-Clause + +# 著者 + +(C)2019 光成滋生 MITSUNARI Shigeo(herumi@nifty.com) All rights reserved. +本コンテンツの著作権、および本コンテンツ中に出てくる商標権、団体名、ロゴ、製品、 +サービスなどはそれぞれ、各権利保有者に帰属します diff --git a/vendor/github.com/dexon-foundation/bls/ffi/cs/readme.md b/vendor/github.com/dexon-foundation/bls/ffi/cs/readme.md new file mode 100644 index 000000000..2b7191871 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/cs/readme.md @@ -0,0 +1,185 @@ +# C# binding of BLS threshold signature library + +# Installation Requirements + +* Visual Studio 2017 or later +* C# 7.2 or later +* .NET Framework 4.5.2 or later + +# How to build + +``` +md work +cd work +git clone https://github.com/herumi/cybozulib_ext +git clone https://github.com/herumi/mcl +git clone https://github.com/herumi/bls +cd bls +mklib dll +``` +bls/bin/*.dll are created + +# How to build a sample + +Open bls/ffi/cs/bls.sln and exec it. + +* Remark. bls256 is obsolete. Please use bls.sln. + +# class and API + +## API + +* `Init(int curveType = BN254);` + * initialize this library with a curve `curveType`. + * curveType = BN254 or BLS12_381 +* `SecretKey ShareSecretKey(in SecretKey[] msk, in Id id);` + * generate the shared secret key from a sequence of master secret keys msk and Id. +* `SecretKey RecoverSecretKey(in SecretKey[] secVec, in Id[] idVec);` + * recover the secret key from a sequence of secret keys secVec and idVec. +* `PublicKey SharePublicKey(in PublicKey[] mpk, in Id id);` + * generate the shared public key from a sequence of master public keys mpk and Id. +* `PublicKey RecoverPublicKey(in PublicKey[] pubVec, in Id[] idVec);` + * recover the public key from a sequence of public keys pubVec and idVec. +* `Signature RecoverSign(in Signature[] sigVec, in Id[] idVec);` + * recover the signature from a sequence of signatures siVec and idVec. + +## Id + +Identifier class + +* `byte[] Serialize();` + * serialize Id +* `void Deserialize(byte[] buf);` + * deserialize from byte[] buf +* `bool IsEqual(in Id rhs);` + * equality +* `void SetDecStr(string s);` + * set by a decimal string s +* `void SetHexStr(string s);` + * set by a hexadecimal string s +* `void SetInt(int x);` + * set an integer x +* `string GetDecStr();` + * get a decimal string +* `string GetHexStr();` + * get a hexadecimal string + +## SecretKey + +* `byte[] Serialize();` + * serialize SecretKey +* `void Deserialize(byte[] buf);` + * deserialize from byte[] buf +* `bool IsEqual(in SecretKey rhs);` + * equality +* `string GetDecStr();` + * get a decimal string +* `string GetHexStr();` + * get a hexadecimal string +* `void Add(in SecretKey rhs);` + * add a secret key rhs +* `void SetByCSPRNG();` + * set a secret key by cryptographically secure pseudo random number generator +* `void SetHashOf(string s);` + * set a secret key by a hash of string s +* `PublicKey GetPublicKey();` + * get the corresponding public key to a secret key +* `Signature Sign(string m);` + * sign a string m +* `Signature GetPop();` + * get a PoP (Proof Of Posession) for a secret key + +## PublicKey + +* `byte[] Serialize();` + * serialize PublicKey +* `void Deserialize(byte[] buf);` + * deserialize from byte[] buf +* `bool IsEqual(in PublicKey rhs);` + * equality +* `void Add(in PublicKey rhs);` + * add a public key rhs +* `string GetDecStr();` + * get a decimal string +* `string GetHexStr();` + * get a hexadecimal string +* `bool Verify(in Signature sig, string m);` + * verify the validness of the sig with m +* `bool VerifyPop(in Signature pop);` + * verify the validness of PoP + +## Signature + +* `byte[] Serialize();` + * serialize Signature +* `void Deserialize(byte[] buf);` + * deserialize from byte[] buf +* `bool IsEqual(in Signature rhs);` + * equality +* `void Add(in Signature rhs);` + * add a signature key rhs +* `string GetDecStr();` + * get a decimal string +* `string GetHexStr();` + * get a hexadecimal string + +## How to use + +### A minimum sample + +``` +using static BLS; + +Init(BN254); // init library +SecretKey sec; +sec.SetByCSPRNG(); // init secret key +PublicKey pub = sec.GetPublicKey(); // get public key +string m = "abc"; +Signature sig = sec.Sign(m); // create signature +if (pub.Verify(sig, m))) { + // signature is verified +} +``` + +### Aggregate signature +``` +Init(BN254); // init library +const int n = 10; +const string m = "abc"; +SecretKey[] secVec = new SecretKey[n]; +PublicKey[] pubVec = new PublicKey[n]; +Signature[] popVec = new Signature[n]; +Signature[] sigVec = new Signature[n]; + +for (int i = 0; i < n; i++) { + secVec[i].SetByCSPRNG(); // init secret key + pubVec[i] = secVec[i].GetPublicKey(); // get public key + popVec[i] = secVec[i].GetPop(); // get a proof of Possesion (PoP) + sigVec[i] = secVec[i].Sign(m); // create signature +} + +SecretKey secAgg; +PublicKey pubAgg; +Signature sigAgg; +for (int i = 0; i < n; i++) { + // verify PoP + if (pubVec[i].VerifyPop(popVec[i]))) { + // error + return; + } + pubAgg.Add(pubVec[i]); // aggregate public key + sigAgg.Add(sigVec[i]); // aggregate signature +} +if (pubAgg.Verify(sigAgg, m)) { + // aggregated signature is verified +} +``` + +# License + +modified new BSD License +http://opensource.org/licenses/BSD-3-Clause + +# Author + +(C)2019 MITSUNARI Shigeo(herumi@nifty.com) All rights reserved. diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls.go b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls.go index 5123a07e6..c83a4e658 100644 --- a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls.go +++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls.go @@ -1,16 +1,25 @@ package bls /* -#cgo CFLAGS:-I../../../include -I../../../../mcl/include/ -#cgo LDFLAGS:${SRCDIR}/../../../lib/libbls384.a ${SRCDIR}/../../../../mcl/lib/libmcl.a -lgmpxx -lgmp -lstdc++ -#cgo CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -#cgo pkg-config: libcrypto -#cgo static pkg-config: --static +#cgo bn256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=4 +#cgo bn256 LDFLAGS:${SRCDIR}/../../../lib/libbls256.a +#cgo bn384 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 +#cgo bn384 LDFLAGS:${SRCDIR}/../../../lib/libbls384.a +#cgo bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -DMCLBN_FR_UNIT_SIZE=4 +#cgo bn384_256 LDFLAGS:${SRCDIR}/../../../lib/libbls384_256.a +#cgo !bn256,!bn384,!bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 +#cgo !bn256,!bn384,!bn384_256 LDFLAGS:${SRCDIR}/../../../lib/libbls384.a +#cgo CFLAGS:-I${SRCDIR}/../../../include -I${SRCDIR}/../../../../mcl/include +#cgo LDFLAGS:${SRCDIR}/../../../../mcl/lib/libmcl.a -lgmpxx -lgmp +#cgo linux LDFLAGS:-static +typedef unsigned int (*ReadRandFunc)(void *, void *, unsigned int); +int wrapReadRandCgo(void *self, void *buf, unsigned int n); #include */ import "C" import "fmt" import "unsafe" +import "io" import "encoding/json" // Init -- @@ -67,6 +76,9 @@ func (id *ID) SetDecString(s string) error { // IsEqual -- func (id *ID) IsEqual(rhs *ID) bool { + if id == nil || rhs == nil { + return false + } return id.v.IsEqual(&rhs.v) } @@ -146,6 +158,9 @@ func (sec *SecretKey) SetDecString(s string) error { // IsEqual -- func (sec *SecretKey) IsEqual(rhs *SecretKey) bool { + if sec == nil || rhs == nil { + return false + } return sec.v.IsEqual(&rhs.v) } @@ -264,6 +279,9 @@ func (pub *PublicKey) SetHexString(s string) error { // IsEqual -- func (pub *PublicKey) IsEqual(rhs *PublicKey) bool { + if pub == nil || rhs == nil { + return false + } return pub.v.IsEqual(&rhs.v) } @@ -350,6 +368,9 @@ func (sign *Sign) SetHexString(s string) error { // IsEqual -- func (sign *Sign) IsEqual(rhs *Sign) bool { + if sign == nil || rhs == nil { + return false + } return sign.v.IsEqual(&rhs.v) } @@ -389,6 +410,9 @@ func (sign *Sign) Verify(pub *PublicKey, m string) bool { // VerifyPop -- func (sign *Sign) VerifyPop(pub *PublicKey) bool { + if pub.getPointer() == nil { + return false + } return C.blsVerifyPop(sign.getPointer(), pub.getPointer()) == 1 } @@ -420,3 +444,96 @@ func DHKeyExchange(sec *SecretKey, pub *PublicKey) (out PublicKey) { C.blsDHKeyExchange(out.getPointer(), sec.getPointer(), pub.getPointer()) return out } + +// HashAndMapToSignature -- +func HashAndMapToSignature(buf []byte) *Sign { + sig := new(Sign) + err := sig.v.HashAndMapTo(buf) + if err == nil { + return sig + } else { + return nil + } +} + +// VerifyPairing -- +func VerifyPairing(X *Sign, Y *Sign, pub *PublicKey) bool { + if X.getPointer() == nil || Y.getPointer() == nil || pub.getPointer() == nil { + return false + } + return C.blsVerifyPairing(X.getPointer(), Y.getPointer(), pub.getPointer()) == 1 +} + +// SignHash -- +func (sec *SecretKey) SignHash(hash []byte) (sign *Sign) { + sign = new(Sign) + // #nosec + err := C.blsSignHash(sign.getPointer(), sec.getPointer(), unsafe.Pointer(&hash[0]), C.size_t(len(hash))) + if err == 0 { + return sign + } else { + return nil + } +} + +// VerifyHash -- +func (sign *Sign) VerifyHash(pub *PublicKey, hash []byte) bool { + if pub.getPointer() == nil { + return false + } + // #nosec + return C.blsVerifyHash(sign.getPointer(), pub.getPointer(), unsafe.Pointer(&hash[0]), C.size_t(len(hash))) == 1 +} + +func Min(x, y int) int { + if x < y { + return x + } + return y +} + +// VerifyAggregateHashes -- +func (sign *Sign) VerifyAggregateHashes(pubVec []PublicKey, hash [][]byte) bool { + hashByte := GetOpUnitSize() * 8 + n := len(hash) + h := make([]byte, n*hashByte) + for i := 0; i < n; i++ { + hn := len(hash[i]) + copy(h[i*hashByte:(i+1)*hashByte], hash[i][0:Min(hn, hashByte)]) + } + if pubVec[0].getPointer() == nil { + return false + } + return C.blsVerifyAggregatedHashes(sign.getPointer(), pubVec[0].getPointer(), unsafe.Pointer(&h[0]), C.size_t(hashByte), C.size_t(n)) == 1 +} + +/// + +var s_randReader io.Reader + +func createSlice(buf *C.char, n C.uint) []byte { + size := int(n) + return (*[1 << 30]byte)(unsafe.Pointer(buf))[:size:size] +} + +// this function can't be put in callback.go +//export wrapReadRandGo +func wrapReadRandGo(buf *C.char, n C.uint) C.uint { + slice := createSlice(buf, n) + ret, err := s_randReader.Read(slice) + if ret == int(n) && err == nil { + return n + } + return 0 +} + +// SetRandFunc -- +func SetRandFunc(randReader io.Reader) { + s_randReader = randReader + if randReader != nil { + C.blsSetRandFunc(nil, C.ReadRandFunc(unsafe.Pointer(C.wrapReadRandCgo))) + } else { + // use default random generator + C.blsSetRandFunc(nil, C.ReadRandFunc(unsafe.Pointer(nil))) + } +} diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls_test.go b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls_test.go new file mode 100644 index 000000000..a13ee02f4 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/bls_test.go @@ -0,0 +1,690 @@ +package bls + +import "testing" +import "strconv" +import "crypto/sha256" +import "crypto/sha512" +import "fmt" +import "crypto/rand" + +var unitN = 0 + +// Tests (for Benchmarks see below) + +func testPre(t *testing.T) { + t.Log("init") + { + var id ID + err := id.SetLittleEndian([]byte{6, 5, 4, 3, 2, 1}) + if err != nil { + t.Error(err) + } + t.Log("id :", id.GetHexString()) + var id2 ID + err = id2.SetHexString(id.GetHexString()) + if err != nil { + t.Fatal(err) + } + if !id.IsEqual(&id2) { + t.Errorf("not same id\n%s\n%s", id.GetHexString(), id2.GetHexString()) + } + err = id2.SetDecString(id.GetDecString()) + if err != nil { + t.Fatal(err) + } + if !id.IsEqual(&id2) { + t.Errorf("not same id\n%s\n%s", id.GetDecString(), id2.GetDecString()) + } + } + { + var sec SecretKey + err := sec.SetLittleEndian([]byte{1, 2, 3, 4, 5, 6}) + if err != nil { + t.Error(err) + } + t.Log("sec=", sec.GetHexString()) + } + + t.Log("create secret key") + m := "this is a bls sample for go" + var sec SecretKey + sec.SetByCSPRNG() + t.Log("sec:", sec.GetHexString()) + t.Log("create public key") + pub := sec.GetPublicKey() + t.Log("pub:", pub.GetHexString()) + sign := sec.Sign(m) + t.Log("sign:", sign.GetHexString()) + if !sign.Verify(pub, m) { + t.Error("Signature does not verify") + } + + // How to make array of SecretKey + { + sec := make([]SecretKey, 3) + for i := 0; i < len(sec); i++ { + sec[i].SetByCSPRNG() + t.Log("sec=", sec[i].GetHexString()) + } + } +} + +func testStringConversion(t *testing.T) { + t.Log("testRecoverSecretKey") + var sec SecretKey + var s string + if unitN == 6 { + s = "16798108731015832284940804142231733909759579603404752749028378864165570215949" + } else { + s = "40804142231733909759579603404752749028378864165570215949" + } + err := sec.SetDecString(s) + if err != nil { + t.Fatal(err) + } + if s != sec.GetDecString() { + t.Error("not equal") + } + s = sec.GetHexString() + var sec2 SecretKey + err = sec2.SetHexString(s) + if err != nil { + t.Fatal(err) + } + if !sec.IsEqual(&sec2) { + t.Error("not equal") + } +} + +func testRecoverSecretKey(t *testing.T) { + t.Log("testRecoverSecretKey") + k := 3000 + var sec SecretKey + sec.SetByCSPRNG() + t.Logf("sec=%s\n", sec.GetHexString()) + + // make master secret key + msk := sec.GetMasterSecretKey(k) + + n := k + secVec := make([]SecretKey, n) + idVec := make([]ID, n) + for i := 0; i < n; i++ { + err := idVec[i].SetLittleEndian([]byte{byte(i & 255), byte(i >> 8), 2, 3, 4, 5}) + if err != nil { + t.Error(err) + } + err = secVec[i].Set(msk, &idVec[i]) + if err != nil { + t.Error(err) + } + // t.Logf("idVec[%d]=%s\n", i, idVec[i].GetHexString()) + } + // recover sec2 from secVec and idVec + var sec2 SecretKey + err := sec2.Recover(secVec, idVec) + if err != nil { + t.Error(err) + } + if !sec.IsEqual(&sec2) { + t.Errorf("Mismatch in recovered secret key:\n %s\n %s.", sec.GetHexString(), sec2.GetHexString()) + } +} + +func testEachSign(t *testing.T, m string, msk []SecretKey, mpk []PublicKey) ([]ID, []SecretKey, []PublicKey, []Sign) { + idTbl := []byte{3, 5, 193, 22, 15} + n := len(idTbl) + + secVec := make([]SecretKey, n) + pubVec := make([]PublicKey, n) + signVec := make([]Sign, n) + idVec := make([]ID, n) + + for i := 0; i < n; i++ { + err := idVec[i].SetLittleEndian([]byte{idTbl[i], 0, 0, 0, 0, 0}) + if err != nil { + t.Error(err) + } + t.Logf("idVec[%d]=%s\n", i, idVec[i].GetHexString()) + + err = secVec[i].Set(msk, &idVec[i]) + if err != nil { + t.Error(err) + } + + err = pubVec[i].Set(mpk, &idVec[i]) + if err != nil { + t.Error(err) + } + t.Logf("pubVec[%d]=%s\n", i, pubVec[i].GetHexString()) + + if !pubVec[i].IsEqual(secVec[i].GetPublicKey()) { + t.Errorf("Pubkey derivation does not match\n%s\n%s", pubVec[i].GetHexString(), secVec[i].GetPublicKey().GetHexString()) + } + + signVec[i] = *secVec[i].Sign(m) + if !signVec[i].Verify(&pubVec[i], m) { + t.Error("Pubkey derivation does not match") + } + } + return idVec, secVec, pubVec, signVec +} +func testSign(t *testing.T) { + m := "testSign" + t.Log(m) + + var sec0 SecretKey + sec0.SetByCSPRNG() + pub0 := sec0.GetPublicKey() + s0 := sec0.Sign(m) + if !s0.Verify(pub0, m) { + t.Error("Signature does not verify") + } + + k := 3 + msk := sec0.GetMasterSecretKey(k) + mpk := GetMasterPublicKey(msk) + idVec, secVec, pubVec, signVec := testEachSign(t, m, msk, mpk) + + var sec1 SecretKey + err := sec1.Recover(secVec, idVec) + if err != nil { + t.Error(err) + } + if !sec0.IsEqual(&sec1) { + t.Error("Mismatch in recovered seckey.") + } + var pub1 PublicKey + err = pub1.Recover(pubVec, idVec) + if err != nil { + t.Error(err) + } + if !pub0.IsEqual(&pub1) { + t.Error("Mismatch in recovered pubkey.") + } + var s1 Sign + err = s1.Recover(signVec, idVec) + if err != nil { + t.Error(err) + } + if !s0.IsEqual(&s1) { + t.Error("Mismatch in recovered signature.") + } +} + +func testAdd(t *testing.T) { + t.Log("testAdd") + var sec1 SecretKey + var sec2 SecretKey + sec1.SetByCSPRNG() + sec2.SetByCSPRNG() + + pub1 := sec1.GetPublicKey() + pub2 := sec2.GetPublicKey() + + m := "test test" + sign1 := sec1.Sign(m) + sign2 := sec2.Sign(m) + + t.Log("sign1 :", sign1.GetHexString()) + sign1.Add(sign2) + t.Log("sign1 add:", sign1.GetHexString()) + pub1.Add(pub2) + if !sign1.Verify(pub1, m) { + t.Fail() + } +} + +func testPop(t *testing.T) { + t.Log("testPop") + var sec SecretKey + sec.SetByCSPRNG() + pop := sec.GetPop() + if !pop.VerifyPop(sec.GetPublicKey()) { + t.Errorf("Valid Pop does not verify") + } + sec.SetByCSPRNG() + if pop.VerifyPop(sec.GetPublicKey()) { + t.Errorf("Invalid Pop verifies") + } +} + +func testData(t *testing.T) { + t.Log("testData") + var sec1, sec2 SecretKey + sec1.SetByCSPRNG() + b := sec1.GetLittleEndian() + err := sec2.SetLittleEndian(b) + if err != nil { + t.Fatal(err) + } + if !sec1.IsEqual(&sec2) { + t.Error("SecretKey not same") + } + pub1 := sec1.GetPublicKey() + b = pub1.Serialize() + var pub2 PublicKey + err = pub2.Deserialize(b) + if err != nil { + t.Fatal(err) + } + if !pub1.IsEqual(&pub2) { + t.Error("PublicKey not same") + } + m := "doremi" + sign1 := sec1.Sign(m) + b = sign1.Serialize() + var sign2 Sign + err = sign2.Deserialize(b) + if err != nil { + t.Fatal(err) + } + if !sign1.IsEqual(&sign2) { + t.Error("Sign not same") + } +} + +func testSerializeToHexStr(t *testing.T) { + t.Log("testSerializeToHexStr") + var sec1, sec2 SecretKey + sec1.SetByCSPRNG() + s := sec1.SerializeToHexStr() + err := sec2.DeserializeHexStr(s) + if err != nil { + t.Fatal(err) + } + if !sec1.IsEqual(&sec2) { + t.Error("SecretKey not same") + } + pub1 := sec1.GetPublicKey() + s = pub1.SerializeToHexStr() + var pub2 PublicKey + err = pub2.DeserializeHexStr(s) + if err != nil { + t.Fatal(err) + } + if !pub1.IsEqual(&pub2) { + t.Error("PublicKey not same") + } + m := "doremi" + sign1 := sec1.Sign(m) + s = sign1.SerializeToHexStr() + var sign2 Sign + err = sign2.DeserializeHexStr(s) + if err != nil { + t.Fatal(err) + } + if !sign1.IsEqual(&sign2) { + t.Error("Sign not same") + } +} + +func testOrder(t *testing.T, c int) { + var curve string + var field string + if c == CurveFp254BNb { + curve = "16798108731015832284940804142231733909759579603404752749028378864165570215949" + field = "16798108731015832284940804142231733909889187121439069848933715426072753864723" + } else if c == CurveFp382_1 { + curve = "5540996953667913971058039301942914304734176495422447785042938606876043190415948413757785063597439175372845535461389" + field = "5540996953667913971058039301942914304734176495422447785045292539108217242186829586959562222833658991069414454984723" + } else if c == CurveFp382_2 { + curve = "5541245505022739011583672869577435255026888277144126952448297309161979278754528049907713682488818304329661351460877" + field = "5541245505022739011583672869577435255026888277144126952450651294188487038640194767986566260919128250811286032482323" + } else if c == BLS12_381 { + curve = "52435875175126190479447740508185965837690552500527637822603658699938581184513" + field = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787" + } else { + t.Fatal("bad c", c) + } + s := GetCurveOrder() + if s != curve { + t.Errorf("bad curve order\n%s\n%s\n", s, curve) + } + s = GetFieldOrder() + if s != field { + t.Errorf("bad field order\n%s\n%s\n", s, field) + } +} + +func testDHKeyExchange(t *testing.T) { + var sec1, sec2 SecretKey + sec1.SetByCSPRNG() + sec2.SetByCSPRNG() + pub1 := sec1.GetPublicKey() + pub2 := sec2.GetPublicKey() + out1 := DHKeyExchange(&sec1, pub2) + out2 := DHKeyExchange(&sec2, pub1) + if !out1.IsEqual(&out2) { + t.Errorf("DH key is not equal") + } +} + +func testPairing(t *testing.T) { + var sec SecretKey + sec.SetByCSPRNG() + pub := sec.GetPublicKey() + m := "abc" + sig1 := sec.Sign(m) + sig2 := HashAndMapToSignature([]byte(m)) + if !VerifyPairing(sig1, sig2, pub) { + t.Errorf("VerifyPairing") + } +} + +func testAggregate(t *testing.T) { + var sec SecretKey + sec.SetByCSPRNG() + pub := sec.GetPublicKey() + msgTbl := []string{"abc", "def", "123"} + n := len(msgTbl) + sigVec := make([]*Sign, n) + for i := 0; i < n; i++ { + m := msgTbl[i] + sigVec[i] = sec.Sign(m) + } + aggSign := sigVec[0] + for i := 1; i < n; i++ { + aggSign.Add(sigVec[i]) + } + hashPt := HashAndMapToSignature([]byte(msgTbl[0])) + for i := 1; i < n; i++ { + hashPt.Add(HashAndMapToSignature([]byte(msgTbl[i]))) + } + if !VerifyPairing(aggSign, hashPt, pub) { + t.Errorf("aggregate2") + } +} + +func Hash(buf []byte) []byte { + if GetOpUnitSize() == 4 { + d := sha256.Sum256([]byte(buf)) + return d[:] + } else { + // use SHA512 if bitSize > 256 + d := sha512.Sum512([]byte(buf)) + return d[:] + } +} + +func testHash(t *testing.T) { + var sec SecretKey + sec.SetByCSPRNG() + pub := sec.GetPublicKey() + m := "abc" + h := Hash([]byte(m)) + sig1 := sec.Sign(m) + sig2 := sec.SignHash(h) + if !sig1.IsEqual(sig2) { + t.Errorf("SignHash") + } + if !sig1.Verify(pub, m) { + t.Errorf("sig1.Verify") + } + if !sig2.VerifyHash(pub, h) { + t.Errorf("sig2.VerifyHash") + } +} + +func testAggregateHashes(t *testing.T) { + n := 1000 + pubVec := make([]PublicKey, n) + sigVec := make([]*Sign, n) + h := make([][]byte, n) + for i := 0; i < n; i++ { + sec := new(SecretKey) + sec.SetByCSPRNG() + pubVec[i] = *sec.GetPublicKey() + m := fmt.Sprintf("abc-%d", i) + h[i] = Hash([]byte(m)) + sigVec[i] = sec.SignHash(h[i]) + } + // aggregate sig + sig := sigVec[0] + for i := 1; i < n; i++ { + sig.Add(sigVec[i]) + } + if !sig.VerifyAggregateHashes(pubVec, h) { + t.Errorf("sig.VerifyAggregateHashes") + } +} + +type SeqRead struct { +} + +func (self *SeqRead) Read(buf []byte) (int, error) { + n := len(buf) + for i := 0; i < n; i++ { + buf[i] = byte(i) + } + return n, nil +} + +func testReadRand(t *testing.T) { + s1 := new(SeqRead) + SetRandFunc(s1) + var sec SecretKey + sec.SetByCSPRNG() + buf := sec.GetLittleEndian() + fmt.Printf("(SeqRead) buf=%x\n", buf) + for i := 0; i < len(buf)-1; i++ { + // ommit buf[len(buf) - 1] because it may be masked + if buf[i] != byte(i) { + t.Fatal("buf") + } + } + SetRandFunc(rand.Reader) + sec.SetByCSPRNG() + buf = sec.GetLittleEndian() + fmt.Printf("(rand.Reader) buf=%x\n", buf) + SetRandFunc(nil) + sec.SetByCSPRNG() + buf = sec.GetLittleEndian() + fmt.Printf("(default) buf=%x\n", buf) +} + +func test(t *testing.T, c int) { + err := Init(c) + if err != nil { + t.Fatal(err) + } + unitN = GetOpUnitSize() + t.Logf("unitN=%d\n", unitN) + testReadRand(t) + testPre(t) + testRecoverSecretKey(t) + testAdd(t) + testSign(t) + testPop(t) + testData(t) + testStringConversion(t) + testOrder(t, c) + testDHKeyExchange(t) + testSerializeToHexStr(t) + testPairing(t) + testAggregate(t) + testHash(t) + testAggregateHashes(t) +} + +func TestMain(t *testing.T) { + t.Logf("GetMaxOpUnitSize() = %d\n", GetMaxOpUnitSize()) + t.Log("CurveFp254BNb") + test(t, CurveFp254BNb) + if GetMaxOpUnitSize() == 6 { + if GetFrUnitSize() == 6 { + t.Log("CurveFp382_1") + test(t, CurveFp382_1) + } + t.Log("BLS12_381") + test(t, BLS12_381) + } +} + +// Benchmarks + +var curve = CurveFp382_1 + +//var curve = CurveFp254BNb + +func BenchmarkPubkeyFromSeckey(b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + for n := 0; n < b.N; n++ { + sec.SetByCSPRNG() + b.StartTimer() + sec.GetPublicKey() + b.StopTimer() + } +} + +func BenchmarkSigning(b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + for n := 0; n < b.N; n++ { + sec.SetByCSPRNG() + b.StartTimer() + sec.Sign(strconv.Itoa(n)) + b.StopTimer() + } +} + +func BenchmarkValidation(b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + for n := 0; n < b.N; n++ { + sec.SetByCSPRNG() + pub := sec.GetPublicKey() + m := strconv.Itoa(n) + sig := sec.Sign(m) + b.StartTimer() + sig.Verify(pub, m) + b.StopTimer() + } +} + +func benchmarkDeriveSeckeyShare(k int, b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + sec.SetByCSPRNG() + msk := sec.GetMasterSecretKey(k) + var id ID + for n := 0; n < b.N; n++ { + err = id.SetLittleEndian([]byte{1, 2, 3, 4, 5, byte(n)}) + if err != nil { + b.Error(err) + } + b.StartTimer() + err := sec.Set(msk, &id) + b.StopTimer() + if err != nil { + b.Error(err) + } + } +} + +//func BenchmarkDeriveSeckeyShare100(b *testing.B) { benchmarkDeriveSeckeyShare(100, b) } +//func BenchmarkDeriveSeckeyShare200(b *testing.B) { benchmarkDeriveSeckeyShare(200, b) } +func BenchmarkDeriveSeckeyShare500(b *testing.B) { benchmarkDeriveSeckeyShare(500, b) } + +//func BenchmarkDeriveSeckeyShare1000(b *testing.B) { benchmarkDeriveSeckeyShare(1000, b) } + +func benchmarkRecoverSeckey(k int, b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + sec.SetByCSPRNG() + msk := sec.GetMasterSecretKey(k) + + // derive n shares + n := k + secVec := make([]SecretKey, n) + idVec := make([]ID, n) + for i := 0; i < n; i++ { + err := idVec[i].SetLittleEndian([]byte{1, 2, 3, 4, 5, byte(i)}) + if err != nil { + b.Error(err) + } + err = secVec[i].Set(msk, &idVec[i]) + if err != nil { + b.Error(err) + } + } + + // recover from secVec and idVec + var sec2 SecretKey + b.StartTimer() + for n := 0; n < b.N; n++ { + err := sec2.Recover(secVec, idVec) + if err != nil { + b.Errorf("%s\n", err) + } + } +} + +func BenchmarkRecoverSeckey100(b *testing.B) { benchmarkRecoverSeckey(100, b) } +func BenchmarkRecoverSeckey200(b *testing.B) { benchmarkRecoverSeckey(200, b) } +func BenchmarkRecoverSeckey500(b *testing.B) { benchmarkRecoverSeckey(500, b) } +func BenchmarkRecoverSeckey1000(b *testing.B) { benchmarkRecoverSeckey(1000, b) } + +func benchmarkRecoverSignature(k int, b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + sec.SetByCSPRNG() + msk := sec.GetMasterSecretKey(k) + + // derive n shares + n := k + idVec := make([]ID, n) + secVec := make([]SecretKey, n) + signVec := make([]Sign, n) + for i := 0; i < n; i++ { + err := idVec[i].SetLittleEndian([]byte{1, 2, 3, 4, 5, byte(i)}) + if err != nil { + b.Error(err) + } + err = secVec[i].Set(msk, &idVec[i]) + if err != nil { + b.Error(err) + } + signVec[i] = *secVec[i].Sign("test message") + } + + // recover signature + var sig Sign + b.StartTimer() + for n := 0; n < b.N; n++ { + err := sig.Recover(signVec, idVec) + if err != nil { + b.Error(err) + } + } +} + +func BenchmarkRecoverSignature100(b *testing.B) { benchmarkRecoverSignature(100, b) } +func BenchmarkRecoverSignature200(b *testing.B) { benchmarkRecoverSignature(200, b) } +func BenchmarkRecoverSignature500(b *testing.B) { benchmarkRecoverSignature(500, b) } +func BenchmarkRecoverSignature1000(b *testing.B) { benchmarkRecoverSignature(1000, b) } diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/callback.go b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/callback.go new file mode 100644 index 000000000..ba73a5e15 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/callback.go @@ -0,0 +1,12 @@ +package bls + +/* +// exported from bls.go +unsigned int wrapReadRandGo(void *buf, unsigned int n); +int wrapReadRandCgo(void *self, void *buf, unsigned int n) +{ + (void)self; + return wrapReadRandGo(buf, n); +} +*/ +import "C" diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/config.h b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/config.h new file mode 100644 index 000000000..07e148137 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/config.h @@ -0,0 +1,6 @@ +#pragma +// use bn384 unless tags is specified +#ifndef MCLBN_FP_UNIT_SIZE + #define MCLBN_FP_UNIT_SIZE 6 +#endif + diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/dummy.cpp b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/dummy.cpp new file mode 100644 index 000000000..a5103a1c5 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/dummy.cpp @@ -0,0 +1,3 @@ +// This is a dummy source file which forces cgo to use the C++ linker instead +// of the default C linker. We can therefore eliminate non-portable linker +// flags such as -lstdc++, which is likely to break on FreeBSD and OpenBSD. diff --git a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/mcl.go b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/mcl.go index 9771201ec..ca8d7f02b 100644 --- a/vendor/github.com/dexon-foundation/bls/ffi/go/bls/mcl.go +++ b/vendor/github.com/dexon-foundation/bls/ffi/go/bls/mcl.go @@ -1,7 +1,10 @@ package bls /* -#cgo CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 +#cgo bn256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=4 +#cgo bn384 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 +#cgo bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -DMCLBN_FR_UNIT_SIZE=4 +#cgo !bn256,!bn384,!bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 #include */ import "C" @@ -23,6 +26,17 @@ const BLS12_381 = C.MCL_BLS12_381 // IoSerializeHexStr const IoSerializeHexStr = C.MCLBN_IO_SERIALIZE_HEX_STR +// GetFrUnitSize() -- +func GetFrUnitSize() int { + return int(C.MCLBN_FR_UNIT_SIZE) +} + +// GetFpUnitSize() -- +// same as GetMaxOpUnitSize() +func GetFpUnitSize() int { + return int(C.MCLBN_FP_UNIT_SIZE) +} + // GetMaxOpUnitSize -- func GetMaxOpUnitSize() int { return int(C.MCLBN_FP_UNIT_SIZE) diff --git a/vendor/github.com/dexon-foundation/bls/images/bls-go-alpine/Dockerfile b/vendor/github.com/dexon-foundation/bls/images/bls-go-alpine/Dockerfile new file mode 100644 index 000000000..edd49eb4b --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/images/bls-go-alpine/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:alpine +MAINTAINER Jimmy Hu + +# Install dependencies +RUN apk add --update-cache build-base gmp-dev openssl-dev git + +# Build bls library +RUN mkdir work ; cd work +RUN git clone --depth 1 git://github.com/dexon-foundation/mcl.git +RUN mkdir bls +COPY . bls/ +RUN cd bls ; make clean && make test_go DOCKER=alpine -j && cp lib/* /usr/lib/ diff --git a/vendor/github.com/dexon-foundation/bls/include/bls/bls.h b/vendor/github.com/dexon-foundation/bls/include/bls/bls.h index 6b7cbdd68..cb300bc49 100644 --- a/vendor/github.com/dexon-foundation/bls/include/bls/bls.h +++ b/vendor/github.com/dexon-foundation/bls/include/bls/bls.h @@ -8,6 +8,14 @@ */ #include +#ifdef BLS_SWAP_G + /* + error if BLS_SWAP_G is inconsistently used between library and exe + */ + #undef MCLBN_COMPILED_TIME_VAR + #define MCLBN_COMPILED_TIME_VAR ((MCLBN_FR_UNIT_SIZE) * 10 + (MCLBN_FP_UNIT_SIZE) + 100) +#endif + #ifdef _MSC_VER #ifdef BLS_DONT_EXPORT #define BLS_DLL_API @@ -21,7 +29,9 @@ #ifndef BLS_NO_AUTOLINK #if MCLBN_FP_UNIT_SIZE == 4 #pragma comment(lib, "bls256.lib") - #elif MCLBN_FP_UNIT_SIZE == 6 + #elif (MCLBN_FP_UNIT_SIZE == 6) && (MCLBN_FR_UNIT_SIZE == 4) + #pragma comment(lib, "bls384_256.lib") + #elif (MCLBN_FP_UNIT_SIZE == 6) && (MCLBN_FR_UNIT_SIZE == 6) #pragma comment(lib, "bls384.lib") #endif #endif @@ -46,11 +56,19 @@ typedef struct { } blsSecretKey; typedef struct { +#ifdef BLS_SWAP_G + mclBnG1 v; +#else mclBnG2 v; +#endif } blsPublicKey; typedef struct { +#ifdef BLS_SWAP_G + mclBnG2 v; +#else mclBnG1 v; +#endif } blsSignature; /* @@ -68,9 +86,13 @@ BLS_DLL_API int blsInit(int curve, int compiledTimeVar); BLS_DLL_API void blsIdSetInt(blsId *id, int x); -// return 0 if success -// mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r +// sec = buf & (1 << bitLen(r)) - 1 +// if (sec >= r) sec &= (1 << (bitLen(r) - 1)) - 1 +// always return 0 BLS_DLL_API int blsSecretKeySetLittleEndian(blsSecretKey *sec, const void *buf, mclSize bufSize); +// return 0 if success (bufSize <= 64) else -1 +// set (buf mod r) to sec +BLS_DLL_API int blsSecretKeySetLittleEndianMod(blsSecretKey *sec, const void *buf, mclSize bufSize); BLS_DLL_API void blsGetPublicKey(blsPublicKey *pub, const blsSecretKey *sec); @@ -125,6 +147,15 @@ BLS_DLL_API int blsPublicKeyIsValidOrder(const blsPublicKey *pub); #ifndef BLS_MINIMUM_API +/* + verify X == sY by checking e(X, sQ) = e(Y, Q) + @param X [in] + @param Y [in] + @param pub [in] pub = sQ + @return 1 if e(X, pub) = e(Y, Q) else 0 +*/ +BLS_DLL_API int blsVerifyPairing(const blsSignature *X, const blsSignature *Y, const blsPublicKey *pub); + /* sign the hash use the low (bitSize of r) - 1 bit of h @@ -162,8 +193,13 @@ BLS_DLL_API int blsGetG1ByteSize(void); // return bytes for serialized Fr BLS_DLL_API int blsGetFrByteSize(void); +#ifdef BLS_SWAP_G +// get a generator of G1 +BLS_DLL_API void blsGetGeneratorOfG1(blsPublicKey *pub); +#else // get a generator of G2 BLS_DLL_API void blsGetGeneratorOfG2(blsPublicKey *pub); +#endif // return 0 if success BLS_DLL_API int blsIdSetDecStr(blsId *id, const char *buf, mclSize bufSize); @@ -184,6 +220,15 @@ BLS_DLL_API int blsHashToSecretKey(blsSecretKey *sec, const void *buf, mclSize b return 0 if success else -1 */ BLS_DLL_API int blsSecretKeySetByCSPRNG(blsSecretKey *sec); +/* + set user-defined random function for setByCSPRNG + @param self [in] user-defined pointer + @param readFunc [in] user-defined function, + which writes random bufSize bytes to buf and returns bufSize if success else returns 0 + @note if self == 0 and readFunc == 0 then set default random function + @note not threadsafe +*/ +BLS_DLL_API void blsSetRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)); #endif BLS_DLL_API void blsGetPop(blsSignature *sig, const blsSecretKey *sec); diff --git a/vendor/github.com/dexon-foundation/bls/include/bls/bls.hpp b/vendor/github.com/dexon-foundation/bls/include/bls/bls.hpp index b32b7e1fa..741334555 100644 --- a/vendor/github.com/dexon-foundation/bls/include/bls/bls.hpp +++ b/vendor/github.com/dexon-foundation/bls/include/bls/bls.hpp @@ -250,7 +250,7 @@ public: */ void recover(const SecretKeyVec& secVec, const IdVec& idVec) { - if (secVec.size() != idVec.size()) throw std::invalid_argument("SecretKey::recover"); + if (secVec.size() != idVec.size()) throw std::invalid_argument("SecretKey:recover"); recover(secVec.data(), idVec.data(), idVec.size()); } /* @@ -300,7 +300,12 @@ public: if (str != "0") { // 1 std::string t; - for (int i = 0; i < 4; i++) { +#ifdef BLS_SWAP_G + const int elemNum = 2; +#else + const int elemNum = 4; +#endif + for (int i = 0; i < elemNum; i++) { is >> t; str += ' '; str += t; @@ -312,14 +317,22 @@ public: void getStr(std::string& str, int ioMode = 0) const { str.resize(1024); +#ifdef BLS_SWAP_G + size_t n = mclBnG1_getStr(&str[0], str.size(), &self_.v, ioMode); +#else size_t n = mclBnG2_getStr(&str[0], str.size(), &self_.v, ioMode); - if (n == 0) throw std::runtime_error("mclBnG2_getStr"); +#endif + if (n == 0) throw std::runtime_error("PublicKey:getStr"); str.resize(n); } void setStr(const std::string& str, int ioMode = 0) { +#ifdef BLS_SWAP_G + int ret = mclBnG1_setStr(&self_.v, str.c_str(), str.size(), ioMode); +#else int ret = mclBnG2_setStr(&self_.v, str.c_str(), str.size(), ioMode); - if (ret != 0) throw std::runtime_error("mclBnG2_setStr"); +#endif + if (ret != 0) throw std::runtime_error("PublicKey:setStr"); } /* set public for id from mpk @@ -333,7 +346,7 @@ public: */ void recover(const PublicKeyVec& pubVec, const IdVec& idVec) { - if (pubVec.size() != idVec.size()) throw std::invalid_argument("PublicKey::recover"); + if (pubVec.size() != idVec.size()) throw std::invalid_argument("PublicKey:recover"); recover(pubVec.data(), idVec.data(), idVec.size()); } /* @@ -382,7 +395,12 @@ public: if (str != "0") { // 1 std::string t; - for (int i = 0; i < 2; i++) { +#ifdef BLS_SWAP_G + const int elemNum = 4; +#else + const int elemNum = 2; +#endif + for (int i = 0; i < elemNum; i++) { is >> t; str += ' '; str += t; @@ -394,14 +412,22 @@ public: void getStr(std::string& str, int ioMode = 0) const { str.resize(1024); +#ifdef BLS_SWAP_G + size_t n = mclBnG2_getStr(&str[0], str.size(), &self_.v, ioMode); +#else size_t n = mclBnG1_getStr(&str[0], str.size(), &self_.v, ioMode); - if (n == 0) throw std::runtime_error("mclBnG1_getStr"); +#endif + if (n == 0) throw std::runtime_error("Signature:tgetStr"); str.resize(n); } void setStr(const std::string& str, int ioMode = 0) { +#ifdef BLS_SWAP_G + int ret = mclBnG2_setStr(&self_.v, str.c_str(), str.size(), ioMode); +#else int ret = mclBnG1_setStr(&self_.v, str.c_str(), str.size(), ioMode); - if (ret != 0) throw std::runtime_error("mclBnG1_setStr"); +#endif + if (ret != 0) throw std::runtime_error("Signature:setStr"); } bool verify(const PublicKey& pub, const void *m, size_t size) const { @@ -437,7 +463,7 @@ public: */ void recover(const SignatureVec& sigVec, const IdVec& idVec) { - if (sigVec.size() != idVec.size()) throw std::invalid_argument("Signature::recover"); + if (sigVec.size() != idVec.size()) throw std::invalid_argument("Signature:recover"); recover(sigVec.data(), idVec.data(), idVec.size()); } /* diff --git a/vendor/github.com/dexon-foundation/bls/mk.bat b/vendor/github.com/dexon-foundation/bls/mk.bat index c5dfac91a..9bf8dd9e6 100644 --- a/vendor/github.com/dexon-foundation/bls/mk.bat +++ b/vendor/github.com/dexon-foundation/bls/mk.bat @@ -8,6 +8,7 @@ if "%1"=="-s" ( echo "mk (-s|-d) " goto exit ) +set CFLAGS=%CFLAGS% -I../mcl/include set SRC=%2 set EXE=%SRC:.cpp=.exe% set EXE=%EXE:.c=.exe% diff --git a/vendor/github.com/dexon-foundation/bls/mklib.bat b/vendor/github.com/dexon-foundation/bls/mklib.bat index fca9333fc..4a60d7196 100644 --- a/vendor/github.com/dexon-foundation/bls/mklib.bat +++ b/vendor/github.com/dexon-foundation/bls/mklib.bat @@ -10,13 +10,17 @@ call setvar.bat if "%1"=="dll" ( cl /c %CFLAGS% /Foobj/bls_c256.obj src/bls_c256.cpp /DBLS_NO_AUTOLINK cl /c %CFLAGS% /Foobj/bls_c384.obj src/bls_c384.cpp /DBLS_NO_AUTOLINK + cl /c %CFLAGS% /Foobj/bls_c384_256.obj src/bls_c384_256.cpp /DBLS_NO_AUTOLINK cl /c %CFLAGS% /Foobj/fp.obj ../mcl/src/fp.cpp link /nologo /DLL /OUT:bin\bls256.dll obj\bls_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\bls256.lib link /nologo /DLL /OUT:bin\bls384.dll obj\bls_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\bls384.lib + link /nologo /DLL /OUT:bin\bls384_256.dll obj\bls_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\bls384_256.lib ) else ( cl /c %CFLAGS% /Foobj/bls_c256.obj src/bls_c256.cpp cl /c %CFLAGS% /Foobj/bls_c384.obj src/bls_c384.cpp + cl /c %CFLAGS% /Foobj/bls_c384_256.obj src/bls_c384_256.cpp cl /c %CFLAGS% /Foobj/fp.obj ../mcl/src/fp.cpp /DMCLBN_DONT_EXPORT lib /OUT:lib/bls256.lib /nodefaultlib obj/bls_c256.obj obj/fp.obj %LDFLAGS% lib /OUT:lib/bls384.lib /nodefaultlib obj/bls_c384.obj obj/fp.obj %LDFLAGS% + lib /OUT:lib/bls384_256.lib /nodefaultlib obj/bls_c384_256.obj obj/fp.obj %LDFLAGS% ) diff --git a/vendor/github.com/dexon-foundation/bls/readme.md b/vendor/github.com/dexon-foundation/bls/readme.md index 08aac6ca1..b1efb3f36 100644 --- a/vendor/github.com/dexon-foundation/bls/readme.md +++ b/vendor/github.com/dexon-foundation/bls/readme.md @@ -15,7 +15,23 @@ git clone git://github.com/dexon-foundation/bls.git git clone git://github.com/herumi/cybozulib_ext ; for only Windows ``` -# **REMARK** libbls.a for C++ interface(bls/bls.hpp) is removed +# News +* (Break backward compatibility) The suffix `_dy` of library name is removed and bls\*.a requires libmcl.so set LD_LIBRARY_PATH to the directory. +* -tags option for Go bindings + * -tags bn256 + * -tags bn384\_256 + * -tags bn384 ; default mode +* Support swap of G1 and G2 + * `make BLS_SWAP_G=1` then G1 is assigned to PublicKey and G2 is assigned to Signature. + * golang binding does not support this feature yet. +* Build option without GMP + * `make MCL_USE_GMP=0` +* Build option without OpenSSL + * `make MCL_USE_OPENSSL=0` +* Build option to specify `mcl` directory + * `make MCL_DIR=` + +* (old) libbls.a for C++ interface(bls/bls.hpp) is removed Link `lib/libbls256.a` or `lib/libbls384.a` to use `bls/bls.hpp` according to MCLBN_FP_UNIT_SIZE = 4 or 6. # Build and test for Linux @@ -45,8 +61,9 @@ bin\bls_c384_test.exe ``` # Library -* libbls256.a/libbls256_dy.so ; for BN254 compiled with MCLBN_FP_UNIT_SIZE=4 -* libbls384.a/libbls384_dy.so ; for BN254/BN381_1/BLS12_381 compiled with MCLBN_FP_UNIT_SIZE=6 +* libbls256.a/libbls256.so ; for BN254 compiled with MCLBN_FP_UNIT_SIZE=4 +* libbls384.a/libbls384.so ; for BN254/BN381_1/BLS12_381 compiled with MCLBN_FP_UNIT_SIZE=6 +* libbls384_256.a/libbls384_256.so ; for BN254/BLS12_381 compiled with MCLBN_FP_UNIT_SIZE=6 and MCLBN_FR_UNIT_SIZE=4 See `mcl/include/curve_type.h` for curve parameter diff --git a/vendor/github.com/dexon-foundation/bls/sample/bls_smpl.cpp b/vendor/github.com/dexon-foundation/bls/sample/bls_smpl.cpp new file mode 100644 index 000000000..e812cd500 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/sample/bls_smpl.cpp @@ -0,0 +1,168 @@ +#define MCLBN_FP_UNIT_SIZE 4 +#include +#include +#include +#include + +const std::string pubFile = "sample/publickey"; +const std::string secFile = "sample/secretkey"; +const std::string signFile = "sample/sign"; + +std::string makeName(const std::string& name, const bls::Id& id) +{ + const std::string suf = ".txt"; + if (id.isZero()) return name + suf; + std::ostringstream os; + os << name << '.' << id << suf; + return os.str(); +} + +template +void save(const std::string& file, const T& t, const bls::Id& id = 0) +{ + const std::string name = makeName(file, id); + std::ofstream ofs(name.c_str(), std::ios::binary); + if (!(ofs << t)) { + throw cybozu::Exception("can't save") << name; + } +} + +template +void load(T& t, const std::string& file, const bls::Id& id = 0) +{ + const std::string name = makeName(file, id); + std::ifstream ifs(name.c_str(), std::ios::binary); + if (!(ifs >> t)) { + throw cybozu::Exception("can't load") << name; + } +} + +int init() +{ + printf("make %s and %s files\n", secFile.c_str(), pubFile.c_str()); + bls::SecretKey sec; + sec.init(); + save(secFile, sec); + bls::PublicKey pub; + sec.getPublicKey(pub); + save(pubFile, pub); + return 0; +} + +int sign(const std::string& m, int id) +{ + printf("sign message `%s` by id=%d\n", m.c_str(), id); + bls::SecretKey sec; + load(sec, secFile, id); + bls::Signature s; + sec.sign(s, m); + save(signFile, s, id); + return 0; +} + +int verify(const std::string& m, int id) +{ + printf("verify message `%s` by id=%d\n", m.c_str(), id); + bls::PublicKey pub; + load(pub, pubFile, id); + bls::Signature s; + load(s, signFile, id); + if (s.verify(pub, m)) { + puts("verify ok"); + return 0; + } else { + puts("verify err"); + return 1; + } +} + +int share(size_t n, size_t k) +{ + printf("%d-out-of-%d threshold sharing\n", (int)k, (int)n); + bls::SecretKey sec; + load(sec, secFile); + bls::SecretKeyVec msk; + sec.getMasterSecretKey(msk, k); + bls::SecretKeyVec secVec(n); + bls::IdVec ids(n); + for (size_t i = 0; i < n; i++) { + int id = i + 1; + ids[i] = id; + secVec[i].set(msk, id); + } + for (size_t i = 0; i < n; i++) { + save(secFile, secVec[i], ids[i]); + bls::PublicKey pub; + secVec[i].getPublicKey(pub); + save(pubFile, pub, ids[i]); + } + return 0; +} + +int recover(const bls::IdVec& ids) +{ + printf("recover from"); + for (size_t i = 0; i < ids.size(); i++) { + std::cout << ' ' << ids[i]; + } + printf("\n"); + bls::SignatureVec sigVec(ids.size()); + for (size_t i = 0; i < sigVec.size(); i++) { + load(sigVec[i], signFile, ids[i]); + } + bls::Signature s; + s.recover(sigVec, ids); + save(signFile, s); + return 0; +} + +int main(int argc, char *argv[]) + try +{ + bls::init(); // use BN254 + + std::string mode; + std::string m; + size_t n; + size_t k; + int id; + bls::IdVec ids; + + cybozu::Option opt; + opt.appendParam(&mode, "init|sign|verify|share|recover"); + opt.appendOpt(&n, 10, "n", ": k-out-of-n threshold"); + opt.appendOpt(&k, 3, "k", ": k-out-of-n threshold"); + opt.appendOpt(&m, "", "m", ": message to be signed"); + opt.appendOpt(&id, 0, "id", ": id of secretKey"); + opt.appendVec(&ids, "ids", ": select k id in [0, n). this option should be last"); + opt.appendHelp("h"); + if (!opt.parse(argc, argv)) { + goto ERR_EXIT; + } + + if (mode == "init") { + return init(); + } else if (mode == "sign") { + if (m.empty()) goto ERR_EXIT; + return sign(m, id); + } else if (mode == "verify") { + if (m.empty()) goto ERR_EXIT; + return verify(m, id); + } else if (mode == "share") { + return share(n, k); + } else if (mode == "recover") { + if (ids.empty()) { + fprintf(stderr, "use -ids option. ex. share -ids 1 3 5\n"); + goto ERR_EXIT; + } + return recover(ids); + } else { + fprintf(stderr, "bad mode %s\n", mode.c_str()); + } +ERR_EXIT: + opt.usage(); + return 1; +} catch (std::exception& e) { + fprintf(stderr, "ERR %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/bls/setvar.bat b/vendor/github.com/dexon-foundation/bls/setvar.bat index b45af24b9..0ff286ab8 100755 --- a/vendor/github.com/dexon-foundation/bls/setvar.bat +++ b/vendor/github.com/dexon-foundation/bls/setvar.bat @@ -1,6 +1,6 @@ @echo off call ..\mcl\setvar.bat -set CFLAGS=%CFLAGS% /I ..\mcl\include /I .\ +set CFLAGS=%CFLAGS% /I ..\mcl\include /I ./ set LDFLAGS=%LDFLAGS% /LIBPATH:..\mcl\lib echo CFLAGS=%CFLAGS% -echo LDFLAGS=%LDFLAGS% \ No newline at end of file +echo LDFLAGS=%LDFLAGS% diff --git a/vendor/github.com/dexon-foundation/bls/src/bls_c384_256.cpp b/vendor/github.com/dexon-foundation/bls/src/bls_c384_256.cpp new file mode 100644 index 000000000..3dcb3e7d7 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/src/bls_c384_256.cpp @@ -0,0 +1,4 @@ +#define MCLBN_FP_UNIT_SIZE 6 +#define MCLBN_FR_UNIT_SIZE 4 +#include "bls_c_impl.hpp" + diff --git a/vendor/github.com/dexon-foundation/bls/src/bls_c_impl.hpp b/vendor/github.com/dexon-foundation/bls/src/bls_c_impl.hpp index 16b79f913..b38c1ad06 100644 --- a/vendor/github.com/dexon-foundation/bls/src/bls_c_impl.hpp +++ b/vendor/github.com/dexon-foundation/bls/src/bls_c_impl.hpp @@ -3,30 +3,81 @@ #include -#include "../mcl/src/bn_c_impl.hpp" +#if 1 +#include "mcl/impl/bn_c_impl.hpp" +#else +#if MCLBN_FP_UNIT_SIZE == 4 && MCLBN_FR_UNIT_SIZE == 4 +#include +#elif MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 6 +#include +#elif MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 4 +#include +#elif MCLBN_FP_UNIT_SIZE == 8 && MCLBN_FR_UNIT_SIZE == 8 +#include +#else + #error "not supported size" +#endif +#include +using namespace mcl::bn; +inline Fr *cast(mclBnFr *p) { return reinterpret_cast(p); } +inline const Fr *cast(const mclBnFr *p) { return reinterpret_cast(p); } + +inline G1 *cast(mclBnG1 *p) { return reinterpret_cast(p); } +inline const G1 *cast(const mclBnG1 *p) { return reinterpret_cast(p); } + +inline G2 *cast(mclBnG2 *p) { return reinterpret_cast(p); } +inline const G2 *cast(const mclBnG2 *p) { return reinterpret_cast(p); } + +inline Fp12 *cast(mclBnGT *p) { return reinterpret_cast(p); } +inline const Fp12 *cast(const mclBnGT *p) { return reinterpret_cast(p); } + +inline Fp6 *cast(uint64_t *p) { return reinterpret_cast(p); } +inline const Fp6 *cast(const uint64_t *p) { return reinterpret_cast(p); } +#endif + +void Gmul(G1& z, const G1& x, const Fr& y) { G1::mul(z, x, y); } +void Gmul(G2& z, const G2& x, const Fr& y) { G2::mul(z, x, y); } +void GmulCT(G1& z, const G1& x, const Fr& y) { G1::mulCT(z, x, y); } +void GmulCT(G2& z, const G2& x, const Fr& y) { G2::mulCT(z, x, y); } /* BLS signature - e : G1 x G2 -> Fp12 + e : G1 x G2 -> GT Q in G2 ; fixed global parameter H : {str} -> G1 s : secret key sQ ; public key s H(m) ; signature of m verify ; e(sQ, H(m)) = e(Q, s H(m)) + + swap G1 and G2 if BLS_SWAP_G is defined + @note the current implementation does not support precomputed miller loop */ +#ifdef BLS_SWAP_G +static G1 g_P; +inline const G1& getBasePoint() { return g_P; } +#else static G2 g_Q; const size_t maxQcoeffN = 128; static mcl::FixedArray g_Qcoeff; // precomputed Q -inline const G2& getQ() { return g_Q; } +inline const G2& getBasePoint() { return g_Q; } inline const mcl::FixedArray& getQcoeff() { return g_Qcoeff; } +#endif int blsInitNotThreadSafe(int curve, int compiledTimeVar) { - int ret = mclBn_init(curve, compiledTimeVar); - if (ret < 0) return ret; + if (compiledTimeVar != MCLBN_COMPILED_TIME_VAR) { + return -(compiledTimeVar | (MCLBN_COMPILED_TIME_VAR * 100)); + } + const mcl::CurveParam& cp = mcl::getCurveParam(curve); bool b; + initPairing(&b, cp); + if (!b) return -1; + +#ifdef BLS_SWAP_G + mapToG1(&b, g_P, 1); +#else if (curve == MCL_BN254) { const char *Qx_BN254 = "11ccb44e77ac2c5dc32a6009594dbe331ec85a61290d6bbac8cc7ebb2dceb128 f204a14bbdac4a05be9a25176de827f2e60085668becdd4fc5fa914c9ee0d9a"; @@ -41,7 +92,7 @@ int blsInitNotThreadSafe(int curve, int compiledTimeVar) if (curve == MCL_BN254) { #include "./qcoeff-bn254.hpp" g_Qcoeff.resize(BN::param.precomputedQcoeffSize); - assert(g_Qcoeff.size() == CYBOZU_NUM_OF_ARRAY(tbl)); + assert(g_Qcoeff.size() == CYBOZU_NUM_OF_ARRAY(QcoeffTblBN254)); for (size_t i = 0; i < g_Qcoeff.size(); i++) { Fp6& x6 = g_Qcoeff[i]; for (size_t j = 0; j < 6; j++) { @@ -53,8 +104,9 @@ int blsInitNotThreadSafe(int curve, int compiledTimeVar) } } } else { - precomputeG2(&b, g_Qcoeff, getQ()); + precomputeG2(&b, g_Qcoeff, getBasePoint()); } +#endif if (!b) return -101; return 0; } @@ -103,26 +155,55 @@ static inline const mclBnG2 *cast(const G2* x) { return (const mclBnG2*)x; } void blsIdSetInt(blsId *id, int x) { - mclBnFr_setInt(&id->v, x); + *cast(&id->v) = x; } int blsSecretKeySetLittleEndian(blsSecretKey *sec, const void *buf, mclSize bufSize) { - return mclBnFr_setLittleEndian(&sec->v, buf, bufSize); + cast(&sec->v)->setArrayMask((const char *)buf, bufSize); + return 0; +} +int blsSecretKeySetLittleEndianMod(blsSecretKey *sec, const void *buf, mclSize bufSize) +{ + bool b; + cast(&sec->v)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod); + return b ? 0 : -1; } void blsGetPublicKey(blsPublicKey *pub, const blsSecretKey *sec) { - mclBnG2_mul(&pub->v, cast(&getQ()), &sec->v); + Gmul(*cast(&pub->v), getBasePoint(), *cast(&sec->v)); } void blsSign(blsSignature *sig, const blsSecretKey *sec, const void *m, mclSize size) { +#ifdef BLS_SWAP_G + G2 Hm; + hashAndMapToG2(Hm, m, size); +#else G1 Hm; hashAndMapToG1(Hm, m, size); - mclBnG1_mulCT(&sig->v, cast(&Hm), &sec->v); +#endif + GmulCT(*cast(&sig->v), Hm, *cast(&sec->v)); } +#ifdef BLS_SWAP_G +/* + e(P, sHm) == e(sP, Hm) + <=> finalExp(ML(P, sHm) * e(-sP, Hm)) == 1 +*/ +bool isEqualTwoPairings(const G2& sHm, const G1& sP, const G2& Hm) +{ + GT e1, e2; + millerLoop(e1, getBasePoint(), sHm); + G1 neg_sP; + G1::neg(neg_sP, sP); + millerLoop(e2, neg_sP, Hm); + e1 *= e2; + finalExp(e1, e1); + return e1.isOne(); +} +#else /* e(P1, Q1) == e(P2, Q2) <=> finalExp(ML(P1, Q1)) == finalExp(ML(P2, Q2)) @@ -132,14 +213,20 @@ void blsSign(blsSignature *sig, const blsSecretKey *sec, const void *m, mclSize */ bool isEqualTwoPairings(const G1& P1, const Fp6* Q1coeff, const G1& P2, const G2& Q2) { - Fp12 e; + GT e; precomputedMillerLoop2mixed(e, P2, Q2, -P1, Q1coeff); finalExp(e, e); return e.isOne(); } +#endif int blsVerify(const blsSignature *sig, const blsPublicKey *pub, const void *m, mclSize size) { +#ifdef BLS_SWAP_G + G2 Hm; + hashAndMapToG2(Hm, m, size); + return isEqualTwoPairings(*cast(&sig->v), *cast(&pub->v), Hm); +#else G1 Hm; hashAndMapToG1(Hm, m, size); /* @@ -147,187 +234,238 @@ int blsVerify(const blsSignature *sig, const blsPublicKey *pub, const void *m, m e(sig, Q) = e(Hm, pub) */ return isEqualTwoPairings(*cast(&sig->v), getQcoeff().data(), Hm, *cast(&pub->v)); +#endif } mclSize blsIdSerialize(void *buf, mclSize maxBufSize, const blsId *id) { - return mclBnFr_serialize(buf, maxBufSize, &id->v); + return cast(&id->v)->serialize(buf, maxBufSize); } mclSize blsSecretKeySerialize(void *buf, mclSize maxBufSize, const blsSecretKey *sec) { - return mclBnFr_serialize(buf, maxBufSize, &sec->v); + return cast(&sec->v)->serialize(buf, maxBufSize); } mclSize blsPublicKeySerialize(void *buf, mclSize maxBufSize, const blsPublicKey *pub) { - return mclBnG2_serialize(buf, maxBufSize, &pub->v); + return cast(&pub->v)->serialize(buf, maxBufSize); } mclSize blsSignatureSerialize(void *buf, mclSize maxBufSize, const blsSignature *sig) { - return mclBnG1_serialize(buf, maxBufSize, &sig->v); + return cast(&sig->v)->serialize(buf, maxBufSize); } mclSize blsIdDeserialize(blsId *id, const void *buf, mclSize bufSize) { - return mclBnFr_deserialize(&id->v, buf, bufSize); + return cast(&id->v)->deserialize(buf, bufSize); } -mclSize blsSecretKeyDeserialize(blsSecretKey *sig, const void *buf, mclSize bufSize) +mclSize blsSecretKeyDeserialize(blsSecretKey *sec, const void *buf, mclSize bufSize) { - return mclBnFr_deserialize(&sig->v, buf, bufSize); + return cast(&sec->v)->deserialize(buf, bufSize); } mclSize blsPublicKeyDeserialize(blsPublicKey *pub, const void *buf, mclSize bufSize) { - return mclBnG2_deserialize(&pub->v, buf, bufSize); + return cast(&pub->v)->deserialize(buf, bufSize); } mclSize blsSignatureDeserialize(blsSignature *sig, const void *buf, mclSize bufSize) { - return mclBnG1_deserialize(&sig->v, buf, bufSize); + return cast(&sig->v)->deserialize(buf, bufSize); } int blsIdIsEqual(const blsId *lhs, const blsId *rhs) { - return mclBnFr_isEqual(&lhs->v, &rhs->v); + return *cast(&lhs->v) == *cast(&rhs->v); } int blsSecretKeyIsEqual(const blsSecretKey *lhs, const blsSecretKey *rhs) { - return mclBnFr_isEqual(&lhs->v, &rhs->v); + return *cast(&lhs->v) == *cast(&rhs->v); } int blsPublicKeyIsEqual(const blsPublicKey *lhs, const blsPublicKey *rhs) { - return mclBnG2_isEqual(&lhs->v, &rhs->v); + return *cast(&lhs->v) == *cast(&rhs->v); } int blsSignatureIsEqual(const blsSignature *lhs, const blsSignature *rhs) { - return mclBnG1_isEqual(&lhs->v, &rhs->v); + return *cast(&lhs->v) == *cast(&rhs->v); } int blsSecretKeyShare(blsSecretKey *sec, const blsSecretKey* msk, mclSize k, const blsId *id) { - return mclBn_FrEvaluatePolynomial(&sec->v, &msk->v, k, &id->v); + bool b; + mcl::evaluatePolynomial(&b, *cast(&sec->v), cast(&msk->v), k, *cast(&id->v)); + return b ? 0 : -1; } int blsPublicKeyShare(blsPublicKey *pub, const blsPublicKey *mpk, mclSize k, const blsId *id) { - return mclBn_G2EvaluatePolynomial(&pub->v, &mpk->v, k, &id->v); + bool b; + mcl::evaluatePolynomial(&b, *cast(&pub->v), cast(&mpk->v), k, *cast(&id->v)); + return b ? 0 : -1; } int blsSecretKeyRecover(blsSecretKey *sec, const blsSecretKey *secVec, const blsId *idVec, mclSize n) { - return mclBn_FrLagrangeInterpolation(&sec->v, &idVec->v, &secVec->v, n); + bool b; + mcl::LagrangeInterpolation(&b, *cast(&sec->v), cast(&idVec->v), cast(&secVec->v), n); + return b ? 0 : -1; } int blsPublicKeyRecover(blsPublicKey *pub, const blsPublicKey *pubVec, const blsId *idVec, mclSize n) { - return mclBn_G2LagrangeInterpolation(&pub->v, &idVec->v, &pubVec->v, n); + bool b; + mcl::LagrangeInterpolation(&b, *cast(&pub->v), cast(&idVec->v), cast(&pubVec->v), n); + return b ? 0 : -1; } int blsSignatureRecover(blsSignature *sig, const blsSignature *sigVec, const blsId *idVec, mclSize n) { - return mclBn_G1LagrangeInterpolation(&sig->v, &idVec->v, &sigVec->v, n); + bool b; + mcl::LagrangeInterpolation(&b, *cast(&sig->v), cast(&idVec->v), cast(&sigVec->v), n); + return b ? 0 : -1; } void blsSecretKeyAdd(blsSecretKey *sec, const blsSecretKey *rhs) { - mclBnFr_add(&sec->v, &sec->v, &rhs->v); + *cast(&sec->v) += *cast(&rhs->v); } void blsPublicKeyAdd(blsPublicKey *pub, const blsPublicKey *rhs) { - mclBnG2_add(&pub->v, &pub->v, &rhs->v); + *cast(&pub->v) += *cast(&rhs->v); } void blsSignatureAdd(blsSignature *sig, const blsSignature *rhs) { - mclBnG1_add(&sig->v, &sig->v, &rhs->v); + *cast(&sig->v) += *cast(&rhs->v); } void blsSignatureVerifyOrder(int doVerify) { - mclBn_verifyOrderG1(doVerify); +#ifdef BLS_SWAP_G + verifyOrderG2(doVerify != 0); +#else + verifyOrderG1(doVerify != 0); +#endif } void blsPublicKeyVerifyOrder(int doVerify) { - mclBn_verifyOrderG2(doVerify); +#ifdef BLS_SWAP_G + verifyOrderG1(doVerify != 0); +#else + verifyOrderG2(doVerify != 0); +#endif } int blsSignatureIsValidOrder(const blsSignature *sig) { - return mclBnG1_isValidOrder(&sig->v); + return cast(&sig->v)->isValidOrder(); } int blsPublicKeyIsValidOrder(const blsPublicKey *pub) { - return mclBnG2_isValidOrder(&pub->v); + return cast(&pub->v)->isValidOrder(); } #ifndef BLS_MINIMUM_API -inline bool toG1(G1& Hm, const void *h, mclSize size) +template +inline bool toG(G& Hm, const void *h, mclSize size) { Fp t; t.setArrayMask((const char *)h, size); bool b; +#ifdef BLS_SWAP_G + BN::mapToG2(&b, Hm, Fp2(t, 0)); +#else BN::mapToG1(&b, Hm, t); +#endif return b; } int blsVerifyAggregatedHashes(const blsSignature *aggSig, const blsPublicKey *pubVec, const void *hVec, size_t sizeofHash, mclSize n) { if (n == 0) return 0; + GT e1, e2; + const char *ph = (const char*)hVec; +#ifdef BLS_SWAP_G + millerLoop(e1, getBasePoint(), -*cast(&aggSig->v)); + G2 h; + if (!toG(h, &ph[0], sizeofHash)) return 0; + BN::millerLoop(e2, *cast(&pubVec[0].v), h); + e1 *= e2; + for (size_t i = 1; i < n; i++) { + if (!toG(h, &ph[i * sizeofHash], sizeofHash)) return 0; + millerLoop(e2, *cast(&pubVec[i].v), h); + e1 *= e2; + } +#else /* e(aggSig, Q) = prod_i e(hVec[i], pubVec[i]) <=> finalExp(ML(-aggSig, Q) * prod_i ML(hVec[i], pubVec[i])) == 1 */ - GT e1, e2; BN::precomputedMillerLoop(e1, -*cast(&aggSig->v), g_Qcoeff.data()); - const char *ph = (const char*)hVec; G1 h; - if (!toG1(h, &ph[0], sizeofHash)) return 0; + if (!toG(h, &ph[0], sizeofHash)) return 0; BN::millerLoop(e2, h, *cast(&pubVec[0].v)); e1 *= e2; for (size_t i = 1; i < n; i++) { - if (!toG1(h, &ph[i * sizeofHash], sizeofHash)) return 0; + if (!toG(h, &ph[i * sizeofHash], sizeofHash)) return 0; BN::millerLoop(e2, h, *cast(&pubVec[i].v)); e1 *= e2; } +#endif BN::finalExp(e1, e1); return e1.isOne(); } int blsSignHash(blsSignature *sig, const blsSecretKey *sec, const void *h, mclSize size) { +#ifdef BLS_SWAP_G + G2 Hm; +#else G1 Hm; - if (!toG1(Hm, h, size)) return -1; - mclBnG1_mulCT(&sig->v, cast(&Hm), &sec->v); +#endif + if (!toG(Hm, h, size)) return -1; + GmulCT(*cast(&sig->v), Hm, *cast(&sec->v)); return 0; } +int blsVerifyPairing(const blsSignature *X, const blsSignature *Y, const blsPublicKey *pub) +{ +#ifdef BLS_SWAP_G + return isEqualTwoPairings(*cast(&X->v), *cast(&pub->v), *cast(&Y->v)); +#else + return isEqualTwoPairings(*cast(&X->v), getQcoeff().data(), *cast(&Y->v), *cast(&pub->v)); +#endif +} + int blsVerifyHash(const blsSignature *sig, const blsPublicKey *pub, const void *h, mclSize size) { - G1 Hm; - if (!toG1(Hm, h, size)) return 0; - return isEqualTwoPairings(*cast(&sig->v), getQcoeff().data(), Hm, *cast(&pub->v)); + blsSignature Hm; + if (!toG(*cast(&Hm.v), h, size)) return 0; + return blsVerifyPairing(sig, &Hm, pub); } void blsSecretKeySub(blsSecretKey *sec, const blsSecretKey *rhs) { - mclBnFr_sub(&sec->v, &sec->v, &rhs->v); + *cast(&sec->v) -= *cast(&rhs->v); } void blsPublicKeySub(blsPublicKey *pub, const blsPublicKey *rhs) { - mclBnG2_sub(&pub->v, &pub->v, &rhs->v); + *cast(&pub->v) -= *cast(&rhs->v); } void blsSignatureSub(blsSignature *sig, const blsSignature *rhs) { - mclBnG1_sub(&sig->v, &sig->v, &rhs->v); + *cast(&sig->v) -= *cast(&rhs->v); } + mclSize blsGetOpUnitSize() // FpUint64Size { return Fp::getUnitSize() * sizeof(mcl::fp::Unit) / sizeof(uint64_t); @@ -345,52 +483,67 @@ int blsGetFieldOrder(char *buf, mclSize maxBufSize) int blsGetG1ByteSize() { - return mclBn_getG1ByteSize(); + return (int)Fp::getByteSize(); } int blsGetFrByteSize() { - return mclBn_getFrByteSize(); + return (int)Fr::getByteSize(); } +#ifdef BLS_SWAP_G +void blsGetGeneratorOfG1(blsPublicKey *pub) +{ + *cast(&pub->v) = getBasePoint(); +} +#else void blsGetGeneratorOfG2(blsPublicKey *pub) { - *(G2*)pub = getQ(); + *cast(&pub->v) = getBasePoint(); } +#endif int blsIdSetDecStr(blsId *id, const char *buf, mclSize bufSize) { - return mclBnFr_setStr(&id->v, buf, bufSize, 10); + return cast(&id->v)->deserialize(buf, bufSize, 10) > 0 ? 0 : -1; } int blsIdSetHexStr(blsId *id, const char *buf, mclSize bufSize) { - return mclBnFr_setStr(&id->v, buf, bufSize, 16); + return cast(&id->v)->deserialize(buf, bufSize, 16) > 0 ? 0 : -1; } int blsIdSetLittleEndian(blsId *id, const void *buf, mclSize bufSize) { - return mclBnFr_setLittleEndian(&id->v, buf, bufSize); + cast(&id->v)->setArrayMask((const char *)buf, bufSize); + return 0; } mclSize blsIdGetDecStr(char *buf, mclSize maxBufSize, const blsId *id) { - return mclBnFr_getStr(buf, maxBufSize, &id->v, 10); + return cast(&id->v)->getStr(buf, maxBufSize, 10); } mclSize blsIdGetHexStr(char *buf, mclSize maxBufSize, const blsId *id) { - return mclBnFr_getStr(buf, maxBufSize, &id->v, 16); + return cast(&id->v)->getStr(buf, maxBufSize, 16); } int blsHashToSecretKey(blsSecretKey *sec, const void *buf, mclSize bufSize) { - return mclBnFr_setHashOf(&sec->v, buf, bufSize); + cast(&sec->v)->setHashOf(buf, bufSize); + return 0; } #ifndef MCL_DONT_USE_CSPRNG int blsSecretKeySetByCSPRNG(blsSecretKey *sec) { - return mclBnFr_setByCSPRNG(&sec->v); + bool b; + cast(&sec->v)->setByCSPRNG(&b); + return b ? 0 : -1; +} +void blsSetRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)) +{ + mcl::fp::RandGen::setRandFunc(self, readFunc); } #endif @@ -399,7 +552,7 @@ void blsGetPop(blsSignature *sig, const blsSecretKey *sec) blsPublicKey pub; blsGetPublicKey(&pub, sec); char buf[1024]; - mclSize n = mclBnG2_serialize(buf, sizeof(buf), &pub.v); + mclSize n = cast(&pub.v)->serialize(buf, sizeof(buf)); assert(n); blsSign(sig, sec, buf, n); } @@ -407,54 +560,54 @@ void blsGetPop(blsSignature *sig, const blsSecretKey *sec) int blsVerifyPop(const blsSignature *sig, const blsPublicKey *pub) { char buf[1024]; - mclSize n = mclBnG2_serialize(buf, sizeof(buf), &pub->v); + mclSize n = cast(&pub->v)->serialize(buf, sizeof(buf)); if (n == 0) return 0; return blsVerify(sig, pub, buf, n); } mclSize blsIdGetLittleEndian(void *buf, mclSize maxBufSize, const blsId *id) { - return mclBnFr_serialize(buf, maxBufSize, &id->v); + return cast(&id->v)->serialize(buf, maxBufSize); } int blsSecretKeySetDecStr(blsSecretKey *sec, const char *buf, mclSize bufSize) { - return mclBnFr_setStr(&sec->v, buf, bufSize, 10); + return cast(&sec->v)->deserialize(buf, bufSize, 10) > 0 ? 0 : -1; } int blsSecretKeySetHexStr(blsSecretKey *sec, const char *buf, mclSize bufSize) { - return mclBnFr_setStr(&sec->v, buf, bufSize, 16); + return cast(&sec->v)->deserialize(buf, bufSize, 16) > 0 ? 0 : -1; } mclSize blsSecretKeyGetLittleEndian(void *buf, mclSize maxBufSize, const blsSecretKey *sec) { - return mclBnFr_serialize(buf, maxBufSize, &sec->v); + return cast(&sec->v)->serialize(buf, maxBufSize); } mclSize blsSecretKeyGetDecStr(char *buf, mclSize maxBufSize, const blsSecretKey *sec) { - return mclBnFr_getStr(buf, maxBufSize, &sec->v, 10); + return cast(&sec->v)->getStr(buf, maxBufSize, 10); } mclSize blsSecretKeyGetHexStr(char *buf, mclSize maxBufSize, const blsSecretKey *sec) { - return mclBnFr_getStr(buf, maxBufSize, &sec->v, 16); + return cast(&sec->v)->getStr(buf, maxBufSize, 16); } int blsPublicKeySetHexStr(blsPublicKey *pub, const char *buf, mclSize bufSize) { - return mclBnG2_setStr(&pub->v, buf, bufSize, 16); + return cast(&pub->v)->deserialize(buf, bufSize, 16) > 0 ? 0 : -1; } mclSize blsPublicKeyGetHexStr(char *buf, mclSize maxBufSize, const blsPublicKey *pub) { - return mclBnG2_getStr(buf, maxBufSize, &pub->v, 16); + return cast(&pub->v)->getStr(buf, maxBufSize, 16); } int blsSignatureSetHexStr(blsSignature *sig, const char *buf, mclSize bufSize) { - return mclBnG1_setStr(&sig->v, buf, bufSize, 16); + return cast(&sig->v)->deserialize(buf, bufSize, 16) > 0 ? 0 : -1; } mclSize blsSignatureGetHexStr(char *buf, mclSize maxBufSize, const blsSignature *sig) { - return mclBnG1_getStr(buf, maxBufSize, &sig->v, 16); + return cast(&sig->v)->getStr(buf, maxBufSize, 16); } void blsDHKeyExchange(blsPublicKey *out, const blsSecretKey *sec, const blsPublicKey *pub) { - mclBnG2_mulCT(&out->v, &pub->v, &sec->v); + GmulCT(*cast(&out->v), *cast(&pub->v), *cast(&sec->v)); } #endif diff --git a/vendor/github.com/dexon-foundation/bls/test/bls256_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls256_test.cpp new file mode 100644 index 000000000..e53a87057 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/test/bls256_test.cpp @@ -0,0 +1,3 @@ +#define MCLBN_FP_UNIT_SIZE 4 +#include "bls_test.hpp" + diff --git a/vendor/github.com/dexon-foundation/bls/test/bls384_256_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls384_256_test.cpp new file mode 100644 index 000000000..ea8126567 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/test/bls384_256_test.cpp @@ -0,0 +1,4 @@ +#define MCLBN_FP_UNIT_SIZE 6 +#define MCLBN_FR_UNIT_SIZE 4 +#include "bls_test.hpp" + diff --git a/vendor/github.com/dexon-foundation/bls/test/bls384_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls384_test.cpp new file mode 100644 index 000000000..2212f8e6b --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/test/bls384_test.cpp @@ -0,0 +1,3 @@ +#define MCLBN_FP_UNIT_SIZE 6 +#include "bls_test.hpp" + diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_c256_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls_c256_test.cpp new file mode 100644 index 000000000..8613720b4 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/test/bls_c256_test.cpp @@ -0,0 +1,2 @@ +#define MCLBN_FP_UNIT_SIZE 4 +#include "bls_c_test.hpp" diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_c384_256_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls_c384_256_test.cpp new file mode 100644 index 000000000..6f153f9d8 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/test/bls_c384_256_test.cpp @@ -0,0 +1,3 @@ +#define MCLBN_FP_UNIT_SIZE 6 +#define MCLBN_FR_UNIT_SIZE 4 +#include "bls_c_test.hpp" diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_c384_test.cpp b/vendor/github.com/dexon-foundation/bls/test/bls_c384_test.cpp new file mode 100644 index 000000000..b6886dd04 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/test/bls_c384_test.cpp @@ -0,0 +1,2 @@ +#define MCLBN_FP_UNIT_SIZE 6 +#include "bls_c_test.hpp" diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_c_test.hpp b/vendor/github.com/dexon-foundation/bls/test/bls_c_test.hpp new file mode 100644 index 000000000..e9b6e6302 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/test/bls_c_test.hpp @@ -0,0 +1,437 @@ +#include +#include +#include +#include +#include +#include + +size_t pubSize(size_t FrSize) +{ +#ifdef BLS_SWAP_G + return FrSize; +#else + return FrSize * 2; +#endif +} +size_t sigSize(size_t FrSize) +{ +#ifdef BLS_SWAP_G + return FrSize * 2; +#else + return FrSize; +#endif +} + +void bls_use_stackTest() +{ + blsSecretKey sec; + blsPublicKey pub; + blsSignature sig; + const char *msg = "this is a pen"; + const size_t msgSize = strlen(msg); + + blsSecretKeySetByCSPRNG(&sec); + + blsGetPublicKey(&pub, &sec); + + blsSign(&sig, &sec, msg, msgSize); + + CYBOZU_TEST_ASSERT(blsVerify(&sig, &pub, msg, msgSize)); +} + +void blsDataTest() +{ + const char *msg = "test test"; + const size_t msgSize = strlen(msg); + const size_t FrSize = blsGetFrByteSize(); + const size_t FpSize = blsGetG1ByteSize(); + blsSecretKey sec1, sec2; + blsSecretKeySetByCSPRNG(&sec1); + char buf[1024]; + size_t n; + size_t ret; + n = blsSecretKeyGetHexStr(buf, sizeof(buf), &sec1); + CYBOZU_TEST_ASSERT(0 < n && n <= FrSize * 2); + ret = blsSecretKeySetHexStr(&sec2, buf, n); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2)); + + memset(&sec2, 0, sizeof(sec2)); + n = blsSecretKeySerialize(buf, sizeof(buf), &sec1); + CYBOZU_TEST_EQUAL(n, FrSize); + ret = blsSecretKeyDeserialize(&sec2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2)); + + blsPublicKey pub1, pub2; + blsGetPublicKey(&pub1, &sec1); + n = blsPublicKeySerialize(buf, sizeof(buf), &pub1); + CYBOZU_TEST_EQUAL(n, pubSize(FpSize)); + ret = blsPublicKeyDeserialize(&pub2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2)); + blsSignature sig1, sig2; + blsSign(&sig1, &sec1, msg, msgSize); + n = blsSignatureSerialize(buf, sizeof(buf), &sig1); + CYBOZU_TEST_EQUAL(n, sigSize(FpSize)); + ret = blsSignatureDeserialize(&sig2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig1, &sig2)); +} + +void blsOrderTest(const char *curveOrder/*Fr*/, const char *fieldOrder/*Fp*/) +{ + char buf[1024]; + size_t len; + len = blsGetCurveOrder(buf, sizeof(buf)); + CYBOZU_TEST_ASSERT(len > 0); + CYBOZU_TEST_EQUAL(buf, curveOrder); + len = blsGetFieldOrder(buf, sizeof(buf)); + CYBOZU_TEST_ASSERT(len > 0); + CYBOZU_TEST_EQUAL(buf, fieldOrder); +} + +#if !defined(DISABLE_THREAD_TEST) || defined(__clang__) +#if defined(CYBOZU_CPP_VERSION) && CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 +#include +#include +struct Thread { + std::unique_ptr t; + Thread() : t() {} + ~Thread() + { + if (t) { + t->join(); + } + } + template + void run(F func, int p1, int p2) + { + t.reset(new std::thread(func, p1, p2)); + } +}; + +CYBOZU_TEST_AUTO(multipleInit) +{ + const size_t n = 100; + { + std::vector vt(n); + for (size_t i = 0; i < n; i++) { + vt[i].run(blsInit, MCL_BN254, MCLBN_COMPILED_TIME_VAR); + } + } + CYBOZU_TEST_EQUAL(blsGetOpUnitSize(), 4u); +#if MCLBN_FP_UNIT_SIZE == 6 + { + std::vector vt(n); + for (size_t i = 0; i < n; i++) { + vt[i].run(blsInit, MCL_BLS12_381, MCLBN_COMPILED_TIME_VAR); + } + } + CYBOZU_TEST_EQUAL(blsGetOpUnitSize(), 6u); +#endif +} +#endif +#endif + +void blsSerializeTest() +{ + const size_t FrSize = blsGetFrByteSize(); + const size_t FpSize = blsGetG1ByteSize(); + printf("FrSize=%d, FpSize=%d\n", (int)FrSize, (int)FpSize); + blsId id1, id2; + blsSecretKey sec1, sec2; + blsPublicKey pub1, pub2; + blsSignature sig1, sig2; + char buf[1024]; + size_t n; + size_t expectSize; + size_t ret; + const char dummyChar = '1'; + + // Id + expectSize = FrSize; + blsIdSetInt(&id1, -1); + n = blsIdSerialize(buf, sizeof(buf), &id1); + CYBOZU_TEST_EQUAL(n, expectSize); + + ret = blsIdDeserialize(&id2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsIdIsEqual(&id1, &id2)); + + ret = blsIdDeserialize(&id2, buf, n - 1); + CYBOZU_TEST_EQUAL(ret, 0); + + memset(&id2, 0, sizeof(id2)); + buf[n] = dummyChar; + ret = blsIdDeserialize(&id2, buf, n + 1); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsIdIsEqual(&id1, &id2)); + + n = blsIdSerialize(buf, expectSize, &id1); + CYBOZU_TEST_EQUAL(n, expectSize); + + // SecretKey + expectSize = FrSize; + blsSecretKeySetDecStr(&sec1, "-1", 2); + n = blsSecretKeySerialize(buf, sizeof(buf), &sec1); + CYBOZU_TEST_EQUAL(n, expectSize); + + ret = blsSecretKeyDeserialize(&sec2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2)); + + ret = blsSecretKeyDeserialize(&sec2, buf, n - 1); + CYBOZU_TEST_EQUAL(ret, 0); + + memset(&sec2, 0, sizeof(sec2)); + buf[n] = dummyChar; + ret = blsSecretKeyDeserialize(&sec2, buf, n + 1); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2)); + + n = blsSecretKeySerialize(buf, expectSize, &sec1); + CYBOZU_TEST_EQUAL(n, expectSize); + + // PublicKey + expectSize = pubSize(FpSize); + blsGetPublicKey(&pub1, &sec1); + n = blsPublicKeySerialize(buf, sizeof(buf), &pub1); + CYBOZU_TEST_EQUAL(n, expectSize); + CYBOZU_TEST_ASSERT(blsPublicKeyIsValidOrder(&pub1)); + + ret = blsPublicKeyDeserialize(&pub2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2)); + + ret = blsPublicKeyDeserialize(&pub2, buf, n - 1); + CYBOZU_TEST_EQUAL(ret, 0); + + memset(&pub2, 0, sizeof(pub2)); + buf[n] = dummyChar; + ret = blsPublicKeyDeserialize(&pub2, buf, n + 1); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2)); + + n = blsPublicKeySerialize(buf, expectSize, &pub1); + CYBOZU_TEST_EQUAL(n, expectSize); + + // Signature +#ifdef BLS_SWAP_G + expectSize = FpSize * 2; +#else + expectSize = FpSize; +#endif + blsSign(&sig1, &sec1, "abc", 3); + n = blsSignatureSerialize(buf, sizeof(buf), &sig1); + CYBOZU_TEST_EQUAL(n, expectSize); + CYBOZU_TEST_ASSERT(blsSignatureIsValidOrder(&sig1)); + + ret = blsSignatureDeserialize(&sig2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig1, &sig2)); + + ret = blsSignatureDeserialize(&sig2, buf, n - 1); + CYBOZU_TEST_EQUAL(ret, 0); + + memset(&sig2, 0, sizeof(sig2)); + buf[n] = dummyChar; + ret = blsSignatureDeserialize(&sig2, buf, n + 1); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig1, &sig2)); + + n = blsSignatureSerialize(buf, expectSize, &sig1); + CYBOZU_TEST_EQUAL(n, expectSize); +} + +void blsVerifyOrderTest() +{ + puts("blsVerifyOrderTest"); +#ifdef BLS_SWAP_G + const uint8_t Qs[] = +#else + const uint8_t Ps[] = +#endif + { +0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + }; +#ifdef BLS_SWAP_G + const uint8_t Ps[] = +#else + const uint8_t Qs[] = +#endif + { +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + }; + size_t n; + blsPublicKey pub; + n = blsPublicKeyDeserialize(&pub, Ps, sizeof(Ps)); + CYBOZU_TEST_EQUAL(n, 0); + blsPublicKeyVerifyOrder(0); + n = blsPublicKeyDeserialize(&pub, Ps, sizeof(Ps)); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_ASSERT(!blsPublicKeyIsValidOrder(&pub)); + blsPublicKeyVerifyOrder(1); + + blsSignature sig; + n = blsSignatureDeserialize(&sig, Qs, sizeof(Qs)); + CYBOZU_TEST_EQUAL(n, 0); + blsSignatureVerifyOrder(0); + n = blsSignatureDeserialize(&sig, Qs, sizeof(Qs)); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_ASSERT(!blsSignatureIsValidOrder(&sig)); + blsSignatureVerifyOrder(1); +} + +void blsAddSubTest() +{ + blsSecretKey sec[3]; + blsPublicKey pub[3]; + blsSignature sig[3]; + const char *msg = "this is a pen"; + const size_t msgSize = strlen(msg); + + const char *secHexStr[8] = { "12", "34" }; + for (int i = 0; i < 2; i++) { + blsSecretKeySetHexStr(&sec[i], secHexStr[i], strlen(secHexStr[i])); + blsGetPublicKey(&pub[i], &sec[i]); + blsSign(&sig[i], &sec[i], msg, msgSize); + } + sec[2] = sec[0]; + blsSecretKeyAdd(&sec[2], &sec[1]); + char buf[1024]; + size_t n = blsSecretKeyGetHexStr(buf, sizeof(buf), &sec[2]); + CYBOZU_TEST_EQUAL(n, 2); + CYBOZU_TEST_EQUAL(buf, "46"); // "12" + "34" + + pub[2] = pub[0]; + blsPublicKeyAdd(&pub[2], &pub[1]); + sig[2] = sig[0]; + blsSignatureAdd(&sig[2], &sig[1]); // sig[2] = sig[0] + sig[1] + blsSignature sig2; + blsSign(&sig2, &sec[2], msg, msgSize); // sig2 = signature by sec[2] + CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig2, &sig[2])); + CYBOZU_TEST_ASSERT(blsVerify(&sig[2], &pub[2], msg, msgSize)); // verify by pub[2] + + blsSecretKeySub(&sec[2], &sec[1]); + CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec[2], &sec[0])); + blsPublicKeySub(&pub[2], &pub[1]); + CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub[2], &pub[0])); + blsSignatureSub(&sig[2], &sig[1]); + CYBOZU_TEST_ASSERT(blsSignatureIsEqual(&sig[2], &sig[0])); +} + +void blsTrivialShareTest() +{ + blsSecretKey sec1, sec2; + blsPublicKey pub1, pub2; + blsId id; + blsIdSetInt(&id, 123); + + blsSecretKeySetByCSPRNG(&sec1); + blsGetPublicKey(&pub1, &sec1); + int ret; + + memset(&sec2, 0, sizeof(sec2)); + ret = blsSecretKeyShare(&sec2, &sec1, 1, &id); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2)); + memset(&sec2, 0, sizeof(sec2)); + ret = blsSecretKeyRecover(&sec2, &sec1, &id, 1); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(blsSecretKeyIsEqual(&sec1, &sec2)); + + memset(&pub2, 0, sizeof(pub2)); + ret = blsPublicKeyShare(&pub2, &pub1, 1, &id); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2)); + memset(&pub2, 0, sizeof(pub2)); + ret = blsPublicKeyRecover(&pub2, &pub1, &id, 1); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(blsPublicKeyIsEqual(&pub1, &pub2)); +} + +void modTest(const char *rStr) +{ + unsigned char buf[1024] = {}; + int ret; + blsSecretKey sec; + const size_t maxByte = 64; // 512-bit + memset(buf, 0xff, maxByte); + ret = blsSecretKeySetLittleEndianMod(&sec, buf, maxByte); + CYBOZU_TEST_EQUAL(ret, 0); + const mpz_class x = (mpz_class(1) << (maxByte * 8)) - 1; // 512-bit 0xff....ff + const mpz_class r(rStr); + size_t n = blsSecretKeySerialize(buf, sizeof(buf), &sec); + CYBOZU_TEST_ASSERT(n > 0); + // serialized data to mpz_class + mpz_class y = 0; + for (size_t i = 0; i < n; i++) { + y <<= 8; + y += buf[n - 1 - i]; + } + CYBOZU_TEST_EQUAL(y, x % r); +} + +void blsBench() +{ + blsSecretKey sec; + blsPublicKey pub; + blsSignature sig; + const char *msg = "this is a pen"; + const size_t msgSize = strlen(msg); + + blsSecretKeySetByCSPRNG(&sec); + + blsGetPublicKey(&pub, &sec); + + CYBOZU_BENCH_C("sign", 10000, blsSign, &sig, &sec, msg, msgSize); + CYBOZU_BENCH_C("verify", 1000, blsVerify, &sig, &pub, msg, msgSize); +} + +CYBOZU_TEST_AUTO(all) +{ + const struct { + int curveType; + const char *r; + const char *p; + } tbl[] = { + { + MCL_BN254, + "16798108731015832284940804142231733909759579603404752749028378864165570215949", + "16798108731015832284940804142231733909889187121439069848933715426072753864723", + }, +#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 6 + { + MCL_BN381_1, + "5540996953667913971058039301942914304734176495422447785042938606876043190415948413757785063597439175372845535461389", + "5540996953667913971058039301942914304734176495422447785045292539108217242186829586959562222833658991069414454984723", + }, +#endif +#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE >= 4 + { + MCL_BLS12_381, + "52435875175126190479447740508185965837690552500527637822603658699938581184513", + "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787", + }, +#endif + }; + for (size_t i = 0; i < sizeof(tbl) / sizeof(tbl[0]); i++) { + printf("i=%d\n", (int)i); + int ret = blsInit(tbl[i].curveType, MCLBN_COMPILED_TIME_VAR); + CYBOZU_TEST_EQUAL(ret, 0); + if (ret) { + printf("ERR %d\n", ret); + exit(1); + } + bls_use_stackTest(); + blsDataTest(); + blsOrderTest(tbl[i].r, tbl[i].p); + blsSerializeTest(); + if (tbl[i].curveType == MCL_BLS12_381) blsVerifyOrderTest(); + blsAddSubTest(); + blsTrivialShareTest(); + modTest(tbl[i].r); + blsBench(); + } +} diff --git a/vendor/github.com/dexon-foundation/bls/test/bls_test.hpp b/vendor/github.com/dexon-foundation/bls/test/bls_test.hpp new file mode 100644 index 000000000..346fafe15 --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/test/bls_test.hpp @@ -0,0 +1,545 @@ +#include +#include +#include +#include +#include +#include +#include + +template +void streamTest(const T& t) +{ + std::ostringstream oss; + oss << t; + std::istringstream iss(oss.str()); + T t2; + iss >> t2; + CYBOZU_TEST_EQUAL(t, t2); +} + +template +void testSetForBN254() +{ + /* + mask value to be less than r if the value >= (1 << (192 + 62)) + */ + const uint64_t fff = uint64_t(-1); + const uint64_t one = uint64_t(1); + const struct { + uint64_t in; + uint64_t expected; + } tbl[] = { + { fff, (one << 61) - 1 }, // masked with (1 << 61) - 1 + { one << 62, 0 }, // masked + { (one << 62) | (one << 61), (one << 61) }, // masked + { (one << 61) - 1, (one << 61) - 1 }, // same + }; + T t1, t2; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + uint64_t v1[] = { fff, fff, fff, tbl[i].in }; + uint64_t v2[] = { fff, fff, fff, tbl[i].expected }; + t1.set(v1); + t2.set(v2); + CYBOZU_TEST_EQUAL(t1, t2); + } +} + +void testForBN254() +{ + CYBOZU_TEST_EQUAL(bls::getOpUnitSize(), 4); + bls::Id id; + CYBOZU_TEST_ASSERT(id.isZero()); + id = 5; + CYBOZU_TEST_EQUAL(id, 5); + { + const uint64_t id1[] = { 1, 2, 3, 4 }; + id.set(id1); + std::ostringstream os; + os << id; + CYBOZU_TEST_EQUAL(os.str(), "0x4000000000000000300000000000000020000000000000001"); + } + testSetForBN254(); + testSetForBN254(); +} + +void hashTest(int type) +{ + bls::SecretKey sec; + sec.init(); + bls::PublicKey pub; + sec.getPublicKey(pub); + const std::string h = "\x01\x02\x03"; + bls::Signature sig; + sec.signHash(sig, h); + CYBOZU_TEST_ASSERT(sig.verifyHash(pub, h)); + CYBOZU_TEST_ASSERT(!sig.verifyHash(pub, "\x01\x02\04")); + if (type == MCL_BN254) { + CYBOZU_TEST_EXCEPTION(sec.signHash(sig, "", 0), std::exception); + CYBOZU_TEST_EXCEPTION(sec.signHash(sig, "\x00", 1), std::exception); + CYBOZU_TEST_EXCEPTION(sec.signHash(sig, "\x00\x00", 2), std::exception); +#ifndef BLS_SWAP_G + const uint64_t c1[] = { 0x0c00000000000004ull, 0xcf0f000000000006ull, 0x26cd890000000003ull, 0x2523648240000001ull }; + const uint64_t mc1[] = { 0x9b0000000000000full, 0x921200000000000dull, 0x9366c48000000004ull }; + CYBOZU_TEST_EXCEPTION(sec.signHash(sig, c1, 32), std::exception); + CYBOZU_TEST_EXCEPTION(sec.signHash(sig, mc1, 24), std::exception); +#endif + } +} + +void blsTest() +{ + bls::SecretKey sec; + sec.init(); + streamTest(sec); + bls::PublicKey pub; + sec.getPublicKey(pub); + streamTest(pub); + for (int i = 0; i < 5; i++) { + std::string m = "hello"; + m += char('0' + i); + bls::Signature sig; + sec.sign(sig, m); + CYBOZU_TEST_ASSERT(sig.verify(pub, m)); + CYBOZU_TEST_ASSERT(!sig.verify(pub, m + "a")); + streamTest(sig); + CYBOZU_BENCH_C("sign", 10000, sec.sign, sig, m); + CYBOZU_BENCH_C("verify", 1000, sig.verify, pub, m); + } +} + +void k_of_nTest() +{ + const std::string m = "abc"; + const int n = 5; + const int k = 3; + bls::SecretKey sec0; + sec0.init(); + bls::Signature sig0; + sec0.sign(sig0, m); + bls::PublicKey pub0; + sec0.getPublicKey(pub0); + CYBOZU_TEST_ASSERT(sig0.verify(pub0, m)); + + bls::SecretKeyVec msk; + sec0.getMasterSecretKey(msk, k); + + bls::SecretKeyVec allPrvVec(n); + bls::IdVec allIdVec(n); + for (int i = 0; i < n; i++) { + int id = i + 1; + allPrvVec[i].set(msk, id); + allIdVec[i] = id; + + bls::SecretKey p; + p.set(msk.data(), k, id); + CYBOZU_TEST_EQUAL(allPrvVec[i], p); + } + + bls::SignatureVec allSigVec(n); + for (int i = 0; i < n; i++) { + CYBOZU_TEST_ASSERT(allPrvVec[i] != sec0); + allPrvVec[i].sign(allSigVec[i], m); + bls::PublicKey pub; + allPrvVec[i].getPublicKey(pub); + CYBOZU_TEST_ASSERT(pub != pub0); + CYBOZU_TEST_ASSERT(allSigVec[i].verify(pub, m)); + } + + /* + 3-out-of-n + can recover + */ + bls::SecretKeyVec secVec(3); + bls::IdVec idVec(3); + for (int a = 0; a < n; a++) { + secVec[0] = allPrvVec[a]; + idVec[0] = allIdVec[a]; + for (int b = a + 1; b < n; b++) { + secVec[1] = allPrvVec[b]; + idVec[1] = allIdVec[b]; + for (int c = b + 1; c < n; c++) { + secVec[2] = allPrvVec[c]; + idVec[2] = allIdVec[c]; + bls::SecretKey sec; + sec.recover(secVec, idVec); + CYBOZU_TEST_EQUAL(sec, sec0); + bls::SecretKey sec2; + sec2.recover(secVec.data(), idVec.data(), secVec.size()); + CYBOZU_TEST_EQUAL(sec, sec2); + } + } + } + { + secVec[0] = allPrvVec[0]; + secVec[1] = allPrvVec[1]; + secVec[2] = allPrvVec[0]; // same of secVec[0] + idVec[0] = allIdVec[0]; + idVec[1] = allIdVec[1]; + idVec[2] = allIdVec[0]; + bls::SecretKey sec; + CYBOZU_TEST_EXCEPTION_MESSAGE(sec.recover(secVec, idVec), std::exception, "same id"); + } + { + /* + n-out-of-n + can recover + */ + bls::SecretKey sec; + sec.recover(allPrvVec, allIdVec); + CYBOZU_TEST_EQUAL(sec, sec0); + } + /* + 2-out-of-n + can't recover + */ + secVec.resize(2); + idVec.resize(2); + for (int a = 0; a < n; a++) { + secVec[0] = allPrvVec[a]; + idVec[0] = allIdVec[a]; + for (int b = a + 1; b < n; b++) { + secVec[1] = allPrvVec[b]; + idVec[1] = allIdVec[b]; + bls::SecretKey sec; + sec.recover(secVec, idVec); + CYBOZU_TEST_ASSERT(sec != sec0); + } + } + /* + 3-out-of-n + can recover + */ + bls::SignatureVec sigVec(3); + idVec.resize(3); + for (int a = 0; a < n; a++) { + sigVec[0] = allSigVec[a]; + idVec[0] = allIdVec[a]; + for (int b = a + 1; b < n; b++) { + sigVec[1] = allSigVec[b]; + idVec[1] = allIdVec[b]; + for (int c = b + 1; c < n; c++) { + sigVec[2] = allSigVec[c]; + idVec[2] = allIdVec[c]; + bls::Signature sig; + sig.recover(sigVec, idVec); + CYBOZU_TEST_EQUAL(sig, sig0); + } + } + } + { + sigVec[0] = allSigVec[1]; idVec[0] = allIdVec[1]; + sigVec[1] = allSigVec[4]; idVec[1] = allIdVec[4]; + sigVec[2] = allSigVec[3]; idVec[2] = allIdVec[3]; + bls::Signature sig; + CYBOZU_BENCH_C("sig.recover", 100, sig.recover, sigVec, idVec); + } + { + /* + n-out-of-n + can recover + */ + bls::Signature sig; + sig.recover(allSigVec, allIdVec); + CYBOZU_TEST_EQUAL(sig, sig0); + } + /* + 2-out-of-n + can't recover + */ + sigVec.resize(2); + idVec.resize(2); + for (int a = 0; a < n; a++) { + sigVec[0] = allSigVec[a]; + idVec[0] = allIdVec[a]; + for (int b = a + 1; b < n; b++) { + sigVec[1] = allSigVec[b]; + idVec[1] = allIdVec[b]; + bls::Signature sig; + sig.recover(sigVec, idVec); + CYBOZU_TEST_ASSERT(sig != sig0); + } + } + // return same value if n = 1 + sigVec.resize(1); + idVec.resize(1); + sigVec[0] = allSigVec[0]; + idVec[0] = allIdVec[0]; + { + bls::Signature sig; + sig.recover(sigVec, idVec); + CYBOZU_TEST_EQUAL(sig, sigVec[0]); + } + // share and recover publicKey + { + bls::PublicKeyVec pubVec(k); + idVec.resize(k); + // select [0, k) publicKey + for (int i = 0; i < k; i++) { + allPrvVec[i].getPublicKey(pubVec[i]); + idVec[i] = allIdVec[i]; + } + bls::PublicKey pub; + pub.recover(pubVec, idVec); + CYBOZU_TEST_EQUAL(pub, pub0); + bls::PublicKey pub2; + pub2.recover(pubVec.data(), idVec.data(), pubVec.size()); + CYBOZU_TEST_EQUAL(pub, pub2); + } +} + +void popTest() +{ + const size_t k = 3; + const size_t n = 6; + const std::string m = "pop test"; + bls::SecretKey sec0; + sec0.init(); + bls::PublicKey pub0; + sec0.getPublicKey(pub0); + bls::Signature sig0; + sec0.sign(sig0, m); + CYBOZU_TEST_ASSERT(sig0.verify(pub0, m)); + + bls::SecretKeyVec msk; + sec0.getMasterSecretKey(msk, k); + + bls::PublicKeyVec mpk; + bls::getMasterPublicKey(mpk, msk); + bls::SignatureVec popVec; + bls::getPopVec(popVec, msk); + + for (size_t i = 0; i < popVec.size(); i++) { + CYBOZU_TEST_ASSERT(popVec[i].verify(mpk[i])); + } + + const int idTbl[n] = { + 3, 5, 193, 22, 15 + }; + bls::SecretKeyVec secVec(n); + bls::PublicKeyVec pubVec(n); + bls::SignatureVec sVec(n); + for (size_t i = 0; i < n; i++) { + int id = idTbl[i]; + secVec[i].set(msk, id); + secVec[i].getPublicKey(pubVec[i]); + bls::PublicKey pub; + pub.set(mpk, id); + CYBOZU_TEST_EQUAL(pubVec[i], pub); + + bls::Signature pop; + secVec[i].getPop(pop); + CYBOZU_TEST_ASSERT(pop.verify(pubVec[i])); + + secVec[i].sign(sVec[i], m); + CYBOZU_TEST_ASSERT(sVec[i].verify(pubVec[i], m)); + } + secVec.resize(k); + sVec.resize(k); + bls::IdVec idVec(k); + for (size_t i = 0; i < k; i++) { + idVec[i] = idTbl[i]; + } + bls::SecretKey sec; + sec.recover(secVec, idVec); + CYBOZU_TEST_EQUAL(sec, sec0); + bls::Signature sig; + sig.recover(sVec, idVec); + CYBOZU_TEST_EQUAL(sig, sig0); + bls::Signature sig2; + sig2.recover(sVec.data(), idVec.data(), sVec.size()); + CYBOZU_TEST_EQUAL(sig, sig2); +} + +void addTest() +{ + bls::SecretKey sec1, sec2; + sec1.init(); + sec2.init(); + CYBOZU_TEST_ASSERT(sec1 != sec2); + + bls::PublicKey pub1, pub2; + sec1.getPublicKey(pub1); + sec2.getPublicKey(pub2); + + const std::string m = "doremi"; + bls::Signature sig1, sig2; + sec1.sign(sig1, m); + sec2.sign(sig2, m); + CYBOZU_TEST_ASSERT((sig1 + sig2).verify(pub1 + pub2, m)); +} + +void aggregateTest() +{ + const size_t n = 10; + bls::SecretKey secs[n]; + bls::PublicKey pubs[n], pub; + bls::Signature sigs[n], sig; + const std::string m = "abc"; + for (size_t i = 0; i < n; i++) { + secs[i].init(); + secs[i].getPublicKey(pubs[i]); + secs[i].sign(sigs[i], m); + } + pub = pubs[0]; + sig = sigs[0]; + for (size_t i = 1; i < n; i++) { + pub.add(pubs[i]); + sig.add(sigs[i]); + } + CYBOZU_TEST_ASSERT(sig.verify(pub, m)); +} + +void dataTest() +{ + const size_t FrSize = bls::getFrByteSize(); + const size_t FpSize = bls::getG1ByteSize(); + bls::SecretKey sec; + sec.init(); + std::string str; + sec.getStr(str, bls::IoFixedByteSeq); + { + CYBOZU_TEST_EQUAL(str.size(), FrSize); + bls::SecretKey sec2; + sec2.setStr(str, bls::IoFixedByteSeq); + CYBOZU_TEST_EQUAL(sec, sec2); + } + bls::PublicKey pub; + sec.getPublicKey(pub); + pub.getStr(str, bls::IoFixedByteSeq); + { +#ifdef BLS_SWAP_G + CYBOZU_TEST_EQUAL(str.size(), FpSize); +#else + CYBOZU_TEST_EQUAL(str.size(), FpSize * 2); +#endif + bls::PublicKey pub2; + pub2.setStr(str, bls::IoFixedByteSeq); + CYBOZU_TEST_EQUAL(pub, pub2); + } + std::string m = "abc"; + bls::Signature sign; + sec.sign(sign, m); + sign.getStr(str, bls::IoFixedByteSeq); + { +#ifdef BLS_SWAP_G + CYBOZU_TEST_EQUAL(str.size(), FpSize * 2); +#else + CYBOZU_TEST_EQUAL(str.size(), FpSize); +#endif + bls::Signature sign2; + sign2.setStr(str, bls::IoFixedByteSeq); + CYBOZU_TEST_EQUAL(sign, sign2); + } + bls::Id id; + const uint64_t v[] = { 1, 2, 3, 4, 5, 6, }; + id.set(v); + id.getStr(str, bls::IoFixedByteSeq); + { + CYBOZU_TEST_EQUAL(str.size(), FrSize); + bls::Id id2; + id2.setStr(str, bls::IoFixedByteSeq); + CYBOZU_TEST_EQUAL(id, id2); + } +} + +void verifyAggregateTest() +{ + const size_t n = 10; + bls::SecretKey secs[n]; + bls::PublicKey pubs[n]; + bls::Signature sigs[n], sig; + const size_t sizeofHash = 32; + struct Hash { char data[sizeofHash]; }; + std::vector h(n); + for (size_t i = 0; i < n; i++) { + char msg[128]; + CYBOZU_SNPRINTF(msg, sizeof(msg), "abc-%d", (int)i); + const size_t msgSize = strlen(msg); + cybozu::Sha256().digest(h[i].data, sizeofHash, msg, msgSize); + secs[i].init(); + secs[i].getPublicKey(pubs[i]); + secs[i].signHash(sigs[i], h[i].data, sizeofHash); + } + sig = sigs[0]; + for (size_t i = 1; i < n; i++) { + sig.add(sigs[i]); + } + CYBOZU_TEST_ASSERT(sig.verifyAggregatedHashes(pubs, h.data(), sizeofHash, n)); + bls::Signature invalidSig = sigs[0] + sigs[1]; + CYBOZU_TEST_ASSERT(!invalidSig.verifyAggregatedHashes(pubs, h.data(), sizeofHash, n)); + h[0].data[0]++; + CYBOZU_TEST_ASSERT(!sig.verifyAggregatedHashes(pubs, h.data(), sizeofHash, n)); +} + +unsigned int writeSeq(void *self, void *buf, unsigned int bufSize) +{ + int& seq = *(int*)self; + char *p = (char *)buf; + for (unsigned int i = 0; i < bufSize; i++) { + p[i] = char(seq++); + } + return bufSize; +} + +void setRandFuncTest() +{ + blsSecretKey sec; + const int seqInit1 = 5; + int seq = seqInit1; + blsSetRandFunc(&seq, writeSeq); + blsSecretKeySetByCSPRNG(&sec); + unsigned char buf[128]; + size_t n = blsSecretKeySerialize(buf, sizeof(buf), &sec); + CYBOZU_TEST_ASSERT(n > 0); + for (size_t i = 0; i < n - 1; i++) { + // ommit buf[n - 1] because it may be masked + CYBOZU_TEST_EQUAL(buf[i], seqInit1 + i); + } + // use default CSPRNG + blsSetRandFunc(0, 0); + blsSecretKeySetByCSPRNG(&sec); + n = blsSecretKeySerialize(buf, sizeof(buf), &sec); + CYBOZU_TEST_ASSERT(n > 0); + printf("sec="); + for (size_t i = 0; i < n; i++) { + printf("%02x", buf[i]); + } + printf("\n"); +} + +void testAll() +{ + blsTest(); + k_of_nTest(); + popTest(); + addTest(); + dataTest(); + aggregateTest(); + verifyAggregateTest(); + setRandFuncTest(); +} +CYBOZU_TEST_AUTO(all) +{ + const struct { + int type; + const char *name; + } tbl[] = { + { MCL_BN254, "BN254" }, +#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 6 + { MCL_BN381_1, "BN381_1" }, +#endif +#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 4 + { MCL_BLS12_381, "BLS12_381" }, +#endif + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + printf("curve=%s\n", tbl[i].name); + int type = tbl[i].type; + bls::init(type); + if (type == MCL_BN254) { + testForBN254(); + } + testAll(); + hashTest(type); + } +} diff --git a/vendor/github.com/dexon-foundation/bls/test/proj/bls_test/bls_test.vcxproj b/vendor/github.com/dexon-foundation/bls/test/proj/bls_test/bls_test.vcxproj new file mode 100644 index 000000000..1755135fb --- /dev/null +++ b/vendor/github.com/dexon-foundation/bls/test/proj/bls_test/bls_test.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {51266DE6-B57B-4AE3-B85C-282F170E1728} + Win32Proj + fp_test + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/constant.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/constant.go index 3e7ef4574..37d873d6f 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/constant.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/crypto/dkg/constant.go @@ -22,5 +22,5 @@ import ( ) const ( - curve = bls.CurveFp382_2 + curve = bls.BLS12_381 ) diff --git a/vendor/github.com/dexon-foundation/mcl/.gitignore b/vendor/github.com/dexon-foundation/mcl/.gitignore new file mode 100644 index 000000000..f5edb3706 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/.gitignore @@ -0,0 +1,13 @@ +CVS +java/*_wrap.cxx +lib/*.so +lib/*.a +*.class +GPATH +GRTAGS +GTAGS +*.o +*.d +*.exe +*.swp +.cvsignore diff --git a/vendor/github.com/dexon-foundation/mcl/.travis.yml b/vendor/github.com/dexon-foundation/mcl/.travis.yml new file mode 100644 index 000000000..73a97e6aa --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/.travis.yml @@ -0,0 +1,17 @@ +sudo: true +dist: trusty +language: cpp +compiler: + - gcc + - clang +addons: + apt: + packages: + - libgmp-dev +script: + - make test_ci DEBUG=1 -j3 + - make clean + - make test_ci CFLAGS_USER=-DMCL_DONT_USE_XBYAK -j3 + - make clean + - make test_go + diff --git a/vendor/github.com/dexon-foundation/mcl/CMakeLists.txt b/vendor/github.com/dexon-foundation/mcl/CMakeLists.txt index 8ac418098..aaa0a8cf2 100644 --- a/vendor/github.com/dexon-foundation/mcl/CMakeLists.txt +++ b/vendor/github.com/dexon-foundation/mcl/CMakeLists.txt @@ -36,6 +36,10 @@ else() add_definitions(-DMCL_USE_LLVM=1) set(SRCS ${SRCS} src/asm/aarch64.s) set(CPU arch64) + elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm") + add_definitions(-DMCL_USE_LLVM=1) + set(SRCS ${SRCS} src/asm/arm.s) + set(CPU arm) elseif(APPLE) add_definitions(-DMCL_USE_LLVM=1) set(SRCS ${SRCS} src/asm/x86-64mac.s src/asm/x86-64mac.bmi2.s) @@ -85,18 +89,20 @@ include_directories( ) add_library(mcl STATIC ${SRCS}) -if(NOT MSVC) add_library(mcl_dy SHARED ${SRCS}) -endif() +target_link_libraries(mcl_dy ${LIBS}) +set_target_properties(mcl_dy PROPERTIES OUTPUT_NAME mcl) +#set_target_properties(mcl_dy PROPERTIES OUTPUT_NAME mcl VERSION 1.0.0 SOVERSION 1) +# For semantics of ABI compatibility including when you must bump SOVERSION, see: +# https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B#The_Do.27s_and_Don.27ts -file(GLOB MCL_HEADERS include/mcl/*.hpp include/mcl/*.h) +file(GLOB MCL_HEADERS include/mcl/*.hpp include/mcl/bn.h include/mcl/curve_type.h) file(GLOB CYBOZULIB_HEADERS include/cybozu/*.hpp) install(TARGETS mcl DESTINATION lib) -if(NOT MSVC) install(TARGETS mcl_dy DESTINATION lib) -endif() install(FILES ${MCL_HEADERS} DESTINATION include/mcl) +install(FILES include/mcl/impl/bn_c_impl.hpp DESTINATION include/mcl/impl) install(FILES ${CYBOZULIB_HEADERS} DESTINATION include/cybozu) set(TEST_BASE fp_test ec_test fp_util_test window_method_test elgamal_test fp_tower_test gmp_test bn_test glv_test) diff --git a/vendor/github.com/dexon-foundation/mcl/Makefile b/vendor/github.com/dexon-foundation/mcl/Makefile index fae248aba..7df1dd300 100644 --- a/vendor/github.com/dexon-foundation/mcl/Makefile +++ b/vendor/github.com/dexon-foundation/mcl/Makefile @@ -8,6 +8,7 @@ TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c384_256_test.cpp bn_c512_test.cp TEST_SRC+=aggregate_sig_test.cpp array_test.cpp TEST_SRC+=bls12_test.cpp TEST_SRC+=ecdsa_c_test.cpp +TEST_SRC+=modp_test.cpp ifeq ($(CPU),x86-64) MCL_USE_XBYAK?=1 TEST_SRC+=mont_fp_test.cpp sq_test.cpp @@ -26,15 +27,14 @@ endif ifeq ($(MCL_USE_XBYAK),0) CFLAGS+=-DMCL_DONT_USE_XBYAK endif -SHARE_BASENAME_SUF?=_dy ################################################################## MCL_LIB=$(LIB_DIR)/libmcl.a -MCL_SNAME=mcl$(SHARE_BASENAME_SUF) -BN256_SNAME=mclbn256$(SHARE_BASENAME_SUF) -BN384_SNAME=mclbn384$(SHARE_BASENAME_SUF) -BN384_256_SNAME=mclbn384_256$(SHARE_BASENAME_SUF) -BN512_SNAME=mclbn512$(SHARE_BASENAME_SUF) -SHE256_SNAME=mclshe256$(SHARE_BASENAME_SUF) +MCL_SNAME=mcl +BN256_SNAME=mclbn256 +BN384_SNAME=mclbn384 +BN384_256_SNAME=mclbn384_256 +BN512_SNAME=mclbn512 +SHE256_SNAME=mclshe256 MCL_SLIB=$(LIB_DIR)/lib$(MCL_SNAME).$(LIB_SUF) BN256_LIB=$(LIB_DIR)/libmclbn256.a BN256_SLIB=$(LIB_DIR)/lib$(BN256_SNAME).$(LIB_SUF) @@ -45,9 +45,10 @@ BN384_256_SLIB=$(LIB_DIR)/lib$(BN384_256_SNAME).$(LIB_SUF) BN512_LIB=$(LIB_DIR)/libmclbn512.a BN512_SLIB=$(LIB_DIR)/lib$(BN512_SNAME).$(LIB_SUF) SHE256_LIB=$(LIB_DIR)/libmclshe256.a +SHE256_SLIB=$(LIB_DIR)/lib$(SHE256_SNAME).$(LIB_SUF) SHE384_LIB=$(LIB_DIR)/libmclshe384.a ECDSA_LIB=$(LIB_DIR)/libmclecdsa.a -all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN384_256_LIB) $(BN384_256_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE256_LIB) $(SHE384_lib) $(ECDSA_LIB) +all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN384_256_LIB) $(BN384_256_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE256_LIB) $(SHE256_SLIB) $(SHE384_lib) $(ECDSA_LIB) #LLVM_VER=-3.8 LLVM_LLC=llc$(LLVM_VER) @@ -121,6 +122,7 @@ ifneq ($(findstring $(OS),mac/mingw64),) BN384_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib BN384_256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib BN512_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib + SHE256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib endif ifeq ($(OS),mingw64) MCL_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(MCL_SNAME).a @@ -128,6 +130,7 @@ ifeq ($(OS),mingw64) BN384_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN384_SNAME).a BN384_256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN384_256_SNAME).a BN512_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN512_SNAME).a + SHE256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(SHE256_SNAME).a endif $(MCL_LIB): $(LIB_OBJ) @@ -142,6 +145,9 @@ $(BN256_LIB): $(BN256_OBJ) $(SHE256_LIB): $(SHE256_OBJ) $(AR) $@ $(SHE256_OBJ) +$(SHE256_SLIB): $(SHE256_OBJ) $(MCL_LIB) + $(PRE)$(CXX) -o $@ $(SHE256_OBJ) $(MCL_LIB) -shared $(LDFLAGS) $(SHE256_SLIB_LDFLAGS) + $(SHE384_LIB): $(SHE384_OBJ) $(AR) $@ $(SHE384_OBJ) @@ -199,7 +205,7 @@ else endif $(GEN_EXE): src/gen.cpp src/llvm_gen.hpp - $(CXX) -o $@ $< $(CFLAGS) -O0 + $(CXX) -o $@ $< $(CFLAGS) asm: $(LLVM_SRC) $(LLVM_OPT) -O3 -o - $(LLVM_SRC) | $(LLVM_LLC) -O3 $(LLVM_FLAGS) -x86-asm-syntax=intel @@ -207,21 +213,27 @@ asm: $(LLVM_SRC) $(LOW_ASM_OBJ): $(LOW_ASM_SRC) $(ASM) $< -ifeq ($(OS),mac) - MAC_GO_LDFLAGS="-ldflags=-s" -endif -# set PATH for mingw, set LD_RUN_PATH is for other env +# set PATH for mingw, set LD_LIBRARY_PATH is for other env +COMMON_LIB_PATH="../../../lib" +PATH_VAL=$$PATH:$(COMMON_LIB_PATH) LD_LIBRARY_PATH=$(COMMON_LIB_PATH) DYLD_LIBRARY_PATH=$(COMMON_LIB_PATH) CGO_CFLAGS="-I$(shell pwd)/include" CGO_LDFLAGS="-L../../../lib" test_go256: $(MCL_SLIB) $(BN256_SLIB) -# cd ffi/go/mcl && env PATH="$$PATH:../../../lib" LD_RUN_PATH="../../../lib" CGO_LDFLAGS="-L../../../lib -l$(BN256_SNAME) -l$(MCL_SNAME) -lgmpxx -lgmp -lcrypto -lstdc++" go test $(MAC_GO_LDFLAGS) -tags bn256 . - cd ffi/go/mcl && env PATH="$$PATH:../../../lib" LD_RUN_PATH="../../../lib" go test $(MAC_GO_LDFLAGS) -tags bn256 . + cd ffi/go/mcl && env PATH=$(PATH_VAL) go test -tags bn256 . test_go384: $(MCL_SLIB) $(BN384_SLIB) -# cd ffi/go/mcl && env LD_RUN_PATH="../../../lib" CGO_CFLAGS="-I../../../include" CGO_LDFLAGS="-L../../../lib -l$(BN384_SNAME) -l$(MCL_SNAME) -lgmpxx -lgmp -lcrypto -lstdc++" go test $(MAC_GO_LDFLAGS) . - cd ffi/go/mcl && env PATH="$$PATH:../../../lib" LD_RUN_PATH="../../../lib" go test $(MAC_GO_LDFLAGS) -tags bn384 . + cd ffi/go/mcl && env PATH=$(PATH_VAL) go test -tags bn384 . + +test_go384_256: $(MCL_SLIB) $(BN384_256_SLIB) + cd ffi/go/mcl && env PATH=$(PATH_VAL) go test -tags bn384_256 . test_go: $(MAKE) test_go256 $(MAKE) test_go384 + $(MAKE) test_go384_256 + +test_python_she: $(SHE256_SLIB) + cd ffi/python && env LD_LIBRARY_PATH="../../lib" DYLD_LIBRARY_PATH="../../lib" PATH=$$PATH:"../../lib" python3 she.py +test_python: + $(MAKE) test_python_she test_java: $(MAKE) -C ffi/java test @@ -265,10 +277,18 @@ $(EXE_DIR)/she_c384_test.exe: $(OBJ_DIR)/she_c384_test.o $(SHE384_LIB) $(MCL_LIB $(EXE_DIR)/ecdsa_c_test.exe: $(OBJ_DIR)/ecdsa_c_test.o $(ECDSA_LIB) $(MCL_LIB) src/ecdsa_c.cpp include/mcl/ecdsa.hpp include/mcl/ecdsa.h $(PRE)$(CXX) $< -o $@ $(ECDSA_LIB) $(MCL_LIB) $(LDFLAGS) +$(OBJ_DIR)/modp_test.o: test/modp_test.cpp + $(PRE)$(CXX) -c $< -o $@ -MMD -MP -MF $(@:.o=.d) -DMCL_USE_VINT -DMCL_MAX_BIT_SIZE=384 -DMCL_VINT_64BIT_PORTABLE -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -I./include -O2 $(CFLAGS_WARN) + +$(EXE_DIR)/modp_test.exe: $(OBJ_DIR)/modp_test.o + $(PRE)$(CXX) $< -o $@ + SAMPLE_EXE=$(addprefix $(EXE_DIR)/,$(addsuffix .exe,$(basename $(SAMPLE_SRC)))) sample: $(SAMPLE_EXE) $(MCL_LIB) TEST_EXE=$(addprefix $(EXE_DIR)/,$(TEST_SRC:.cpp=.exe)) +test_ci: $(TEST_EXE) + @sh -ec 'for i in $(TEST_EXE); do echo $$i; env LSAN_OPTIONS=verbosity=1:log_threads=1 $$i; done' test: $(TEST_EXE) @echo test $(TEST_EXE) @sh -ec 'for i in $(TEST_EXE); do $$i|grep "ctest:name"; done' > result.txt @@ -279,8 +299,8 @@ EMCC_OPT+=-O3 -DNDEBUG -DMCLSHE_WIN_SIZE=8 EMCC_OPT+=-s WASM=1 -s NO_EXIT_RUNTIME=1 -s MODULARIZE=1 #-s ASSERTIONS=1 EMCC_OPT+=-DCYBOZU_MINIMUM_EXCEPTION EMCC_OPT+=-s ABORTING_MALLOC=0 -SHE_C_DEP=src/fp.cpp src/she_c_impl.hpp include/mcl/she.hpp include/mcl/she.h Makefile -MCL_C_DEP=src/fp.cpp src/bn_c_impl.hpp include/mcl/bn.hpp include/mcl/bn.h Makefile +SHE_C_DEP=src/fp.cpp src/she_c_impl.hpp include/mcl/she.hpp include/mcl/fp.hpp include/mcl/op.hpp include/mcl/she.h Makefile +MCL_C_DEP=src/fp.cpp include/mcl/impl/bn_c_impl.hpp include/mcl/bn.hpp include/mcl/fp.hpp include/mcl/op.hpp include/mcl/bn.h Makefile ifeq ($(MCL_USE_LLVM),2) EMCC_OPT+=src/base64m.ll -DMCL_USE_LLVM SHE_C_DEP+=src/base64m.ll @@ -328,21 +348,23 @@ make_tbl: update_xbyak: cp -a ../xbyak/xbyak/xbyak.h ../xbyak/xbyak/xbyak_util.h ../xbyak/xbyak/xbyak_mnemonic.h src/xbyak/ +update_cybozulib: + cp -a $(addprefix ../cybozulib/,$(wildcard include/cybozu/*.hpp)) include/cybozu/ clean: - $(RM) $(LIB_DIR)/*.a $(EXE_DIR)/*.$(LIB_SUF) $(OBJ_DIR)/*.o $(OBJ_DIR)/*.d $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_OBJ) $(LIB_OBJ) $(BN256_OBJ) $(BN384_OBJ) $(BN512_OBJ) $(LLVM_SRC) $(FUNC_LIST) src/*.ll lib/*.a + $(RM) $(LIB_DIR)/*.a $(LIB_DIR)/*.$(LIB_SUF) $(OBJ_DIR)/*.o $(OBJ_DIR)/*.obj $(OBJ_DIR)/*.d $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_OBJ) $(LIB_OBJ) $(BN256_OBJ) $(BN384_OBJ) $(BN512_OBJ) $(LLVM_SRC) $(FUNC_LIST) src/*.ll lib/*.a ALL_SRC=$(SRC_SRC) $(TEST_SRC) $(SAMPLE_SRC) DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC)))) -include $(DEPEND_FILE) PREFIX?=/usr/local -install: lib/libmcl.a lib/libmcl$(SHARE_BASENAME_SUF).$(LIB_SUF) +install: lib/libmcl.a lib/libmcl.$(LIB_SUF) $(MKDIR) $(PREFIX)/include/mcl cp -a include/mcl/ $(PREFIX)/include/ cp -a include/cybozu/ $(PREFIX)/include/ $(MKDIR) $(PREFIX)/lib - cp -a lib/libmcl.a lib/libmcl$(SHARE_BASENAME_SUF).$(LIB_SUF) $(PREFIX)/lib/ + cp -a lib/libmcl.a lib/libmcl.$(LIB_SUF) $(PREFIX)/lib/ .PHONY: test mcl-wasm she-wasm bin/emu diff --git a/vendor/github.com/dexon-foundation/mcl/common.mk b/vendor/github.com/dexon-foundation/mcl/common.mk index a05f5c9cb..5c749e1a6 100644 --- a/vendor/github.com/dexon-foundation/mcl/common.mk +++ b/vendor/github.com/dexon-foundation/mcl/common.mk @@ -78,7 +78,7 @@ else endif ifeq ($(MARCH),) ifeq ($(INTEL),1) - CFLAGS_OPT+=-march=native +# CFLAGS_OPT+=-march=native endif else CFLAGS_OPT+=$(MARCH) diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/App.config b/vendor/github.com/dexon-foundation/mcl/ffi/cs/App.config new file mode 100644 index 000000000..88fa4027b --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/Properties/AssemblyInfo.cs b/vendor/github.com/dexon-foundation/mcl/ffi/cs/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..c87e1d44b --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 +// アセンブリに関連付けられている情報を変更するには、 +// これらの属性値を変更してください。 +[assembly: AssemblyTitle("bn256")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("bn256")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから +// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、 +// その型の ComVisible 属性を true に設定してください。 +[assembly: ComVisible(false)] + +// このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります +[assembly: Guid("e9d06b1b-ea22-4ef4-ba4b-422f7625966b")] + +// アセンブリのバージョン情報は次の 4 つの値で構成されています: +// +// メジャー バージョン +// マイナー バージョン +// ビルド番号 +// Revision +// +// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を +// 既定値にすることができます: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.cs b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.cs new file mode 100644 index 000000000..0e1ed032c --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.cs @@ -0,0 +1,475 @@ +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace mcl { + public class BN256 { + [DllImport("mclBn256.dll")] + public static extern int mclBn_init(int curve, int maxUnitSize); + [DllImport("mclBn256.dll")] + public static extern void mclBnFr_clear(ref Fr x); + [DllImport("mclBn256.dll")] + public static extern void mclBnFr_setInt(ref Fr y, int x); + [DllImport("mclBn256.dll")] + public static extern int mclBnFr_setStr(ref Fr x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode); + [DllImport("mclBn256.dll")] + public static extern int mclBnFr_isValid(ref Fr x); + [DllImport("mclBn256.dll")] + public static extern int mclBnFr_isEqual(ref Fr x, ref Fr y); + [DllImport("mclBn256.dll")] + public static extern int mclBnFr_isZero(ref Fr x); + [DllImport("mclBn256.dll")] + public static extern int mclBnFr_isOne(ref Fr x); + [DllImport("mclBn256.dll")] + public static extern void mclBnFr_setByCSPRNG(ref Fr x); + + [DllImport("mclBn256.dll")] + public static extern int mclBnFr_setHashOf(ref Fr x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize); + [DllImport("mclBn256.dll")] + public static extern int mclBnFr_getStr([Out]StringBuilder buf, long maxBufSize, ref Fr x, int ioMode); + + [DllImport("mclBn256.dll")] + public static extern void mclBnFr_neg(ref Fr y, ref Fr x); + [DllImport("mclBn256.dll")] + public static extern void mclBnFr_inv(ref Fr y, ref Fr x); + [DllImport("mclBn256.dll")] + public static extern void mclBnFr_add(ref Fr z, ref Fr x, ref Fr y); + [DllImport("mclBn256.dll")] + public static extern void mclBnFr_sub(ref Fr z, ref Fr x, ref Fr y); + [DllImport("mclBn256.dll")] + public static extern void mclBnFr_mul(ref Fr z, ref Fr x, ref Fr y); + [DllImport("mclBn256.dll")] + public static extern void mclBnFr_div(ref Fr z, ref Fr x, ref Fr y); + + [DllImport("mclBn256.dll")] + public static extern void mclBnG1_clear(ref G1 x); + [DllImport("mclBn256.dll")] + public static extern int mclBnG1_setStr(ref G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode); + [DllImport("mclBn256.dll")] + public static extern int mclBnG1_isValid(ref G1 x); + [DllImport("mclBn256.dll")] + public static extern int mclBnG1_isEqual(ref G1 x, ref G1 y); + [DllImport("mclBn256.dll")] + public static extern int mclBnG1_isZero(ref G1 x); + [DllImport("mclBn256.dll")] + public static extern int mclBnG1_hashAndMapTo(ref G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize); + [DllImport("mclBn256.dll")] + public static extern long mclBnG1_getStr([Out]StringBuilder buf, long maxBufSize, ref G1 x, int ioMode); + [DllImport("mclBn256.dll")] + public static extern void mclBnG1_neg(ref G1 y, ref G1 x); + [DllImport("mclBn256.dll")] + public static extern void mclBnG1_dbl(ref G1 y, ref G1 x); + [DllImport("mclBn256.dll")] + public static extern void mclBnG1_add(ref G1 z, ref G1 x, ref G1 y); + [DllImport("mclBn256.dll")] + public static extern void mclBnG1_sub(ref G1 z, ref G1 x, ref G1 y); + [DllImport("mclBn256.dll")] + public static extern void mclBnG1_mul(ref G1 z, ref G1 x, ref Fr y); + + [DllImport("mclBn256.dll")] + public static extern void mclBnG2_clear(ref G2 x); + [DllImport("mclBn256.dll")] + public static extern int mclBnG2_setStr(ref G2 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode); + [DllImport("mclBn256.dll")] + public static extern int mclBnG2_isValid(ref G2 x); + [DllImport("mclBn256.dll")] + public static extern int mclBnG2_isEqual(ref G2 x, ref G2 y); + [DllImport("mclBn256.dll")] + public static extern int mclBnG2_isZero(ref G2 x); + [DllImport("mclBn256.dll")] + public static extern int mclBnG2_hashAndMapTo(ref G2 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize); + [DllImport("mclBn256.dll")] + public static extern long mclBnG2_getStr([Out]StringBuilder buf, long maxBufSize, ref G2 x, int ioMode); + [DllImport("mclBn256.dll")] + public static extern void mclBnG2_neg(ref G2 y, ref G2 x); + [DllImport("mclBn256.dll")] + public static extern void mclBnG2_dbl(ref G2 y, ref G2 x); + [DllImport("mclBn256.dll")] + public static extern void mclBnG2_add(ref G2 z, ref G2 x, ref G2 y); + [DllImport("mclBn256.dll")] + public static extern void mclBnG2_sub(ref G2 z, ref G2 x, ref G2 y); + [DllImport("mclBn256.dll")] + public static extern void mclBnG2_mul(ref G2 z, ref G2 x, ref Fr y); + + [DllImport("mclBn256.dll")] + public static extern void mclBnGT_clear(ref GT x); + [DllImport("mclBn256.dll")] + public static extern int mclBnGT_setStr(ref GT x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode); + [DllImport("mclBn256.dll")] + public static extern int mclBnGT_isEqual(ref GT x, ref GT y); + [DllImport("mclBn256.dll")] + public static extern int mclBnGT_isZero(ref GT x); + [DllImport("mclBn256.dll")] + public static extern int mclBnGT_isOne(ref GT x); + [DllImport("mclBn256.dll")] + public static extern long mclBnGT_getStr([Out]StringBuilder buf, long maxBufSize, ref GT x, int ioMode); + [DllImport("mclBn256.dll")] + public static extern void mclBnGT_neg(ref GT y, ref GT x); + [DllImport("mclBn256.dll")] + public static extern void mclBnGT_inv(ref GT y, ref GT x); + [DllImport("mclBn256.dll")] + public static extern void mclBnGT_add(ref GT z, ref GT x, ref GT y); + [DllImport("mclBn256.dll")] + public static extern void mclBnGT_sub(ref GT z, ref GT x, ref GT y); + [DllImport("mclBn256.dll")] + public static extern void mclBnGT_mul(ref GT z, ref GT x, ref GT y); + [DllImport("mclBn256.dll")] + public static extern void mclBnGT_div(ref GT z, ref GT x, ref GT y); + + [DllImport("mclBn256.dll")] + public static extern void mclBnGT_pow(ref GT z, ref GT x, ref Fr y); + [DllImport("mclBn256.dll")] + public static extern void mclBn_pairing(ref GT z, ref G1 x, ref G2 y); + [DllImport("mclBn256.dll")] + public static extern void mclBn_finalExp(ref GT y, ref GT x); + [DllImport("mclBn256.dll")] + public static extern void mclBn_millerLoop(ref GT z, ref G1 x, ref G2 y); + + public static void init() + { + const int curveFp254BNb = 0; + const int maxUnitSize = 4; + if (mclBn_init(curveFp254BNb, maxUnitSize) != 0) { + throw new InvalidOperationException("mclBn_init"); + } + } + [StructLayout(LayoutKind.Sequential)] + public struct Fr { + private ulong v0, v1, v2, v3; + public void Clear() + { + mclBnFr_clear(ref this); + } + public void SetInt(int x) + { + mclBnFr_setInt(ref this, x); + } + public void SetStr(string s, int ioMode) + { + if (mclBnFr_setStr(ref this, s, s.Length, ioMode) != 0) { + throw new ArgumentException("mclBnFr_setStr" + s); + } + } + public bool IsValid() + { + return mclBnFr_isValid(ref this) == 1; + } + public bool Equals(Fr rhs) + { + return mclBnFr_isEqual(ref this, ref rhs) == 1; + } + public bool IsZero() + { + return mclBnFr_isZero(ref this) == 1; + } + public bool IsOne() + { + return mclBnFr_isOne(ref this) == 1; + } + public void SetByCSPRNG() + { + mclBnFr_setByCSPRNG(ref this); + } + public void SetHashOf(String s) + { + if (mclBnFr_setHashOf(ref this, s, s.Length) != 0) { + throw new InvalidOperationException("mclBnFr_setHashOf:" + s); + } + } + public string GetStr(int ioMode) + { + StringBuilder sb = new StringBuilder(1024); + long size = mclBnFr_getStr(sb, sb.Capacity, ref this, ioMode); + if (size == 0) { + throw new InvalidOperationException("mclBnFr_getStr:"); + } + return sb.ToString(); + } + public void Neg(Fr x) + { + mclBnFr_neg(ref this, ref x); + } + public void Inv(Fr x) + { + mclBnFr_inv(ref this, ref x); + } + public void Add(Fr x, Fr y) + { + mclBnFr_add(ref this, ref x, ref y); + } + public void Sub(Fr x, Fr y) + { + mclBnFr_sub(ref this, ref x, ref y); + } + public void Mul(Fr x, Fr y) + { + mclBnFr_mul(ref this, ref x, ref y); + } + public void Div(Fr x, Fr y) + { + mclBnFr_div(ref this, ref x, ref y); + } + public static Fr operator -(Fr x) + { + Fr y = new Fr(); + y.Neg(x); + return y; + } + public static Fr operator +(Fr x, Fr y) + { + Fr z = new Fr(); + z.Add(x, y); + return z; + } + public static Fr operator -(Fr x, Fr y) + { + Fr z = new Fr(); + z.Sub(x, y); + return z; + } + public static Fr operator *(Fr x, Fr y) + { + Fr z = new Fr(); + z.Mul(x, y); + return z; + } + public static Fr operator /(Fr x, Fr y) + { + Fr z = new Fr(); + z.Div(x, y); + return z; + } + } + [StructLayout(LayoutKind.Sequential)] + public struct G1 { + private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11; + public void Clear() + { + mclBnG1_clear(ref this); + } + public void setStr(String s, int ioMode) + { + if (mclBnG1_setStr(ref this, s, s.Length, ioMode) != 0) { + throw new ArgumentException("mclBnG1_setStr:" + s); + } + } + public bool IsValid() + { + return mclBnG1_isValid(ref this) == 1; + } + public bool Equals(G1 rhs) + { + return mclBnG1_isEqual(ref this, ref rhs) == 1; + } + public bool IsZero() + { + return mclBnG1_isZero(ref this) == 1; + } + public void HashAndMapTo(String s) + { + if (mclBnG1_hashAndMapTo(ref this, s, s.Length) != 0) { + throw new ArgumentException("mclBnG1_hashAndMapTo:" + s); + } + } + public string GetStr(int ioMode) + { + StringBuilder sb = new StringBuilder(1024); + long size = mclBnG1_getStr(sb, sb.Capacity, ref this, ioMode); + if (size == 0) { + throw new InvalidOperationException("mclBnG1_getStr:"); + } + return sb.ToString(); + } + public void Neg(G1 x) + { + mclBnG1_neg(ref this, ref x); + } + public void Dbl(G1 x) + { + mclBnG1_dbl(ref this, ref x); + } + public void Add(G1 x, G1 y) + { + mclBnG1_add(ref this, ref x, ref y); + } + public void Sub(G1 x, G1 y) + { + mclBnG1_sub(ref this, ref x, ref y); + } + public void Mul(G1 x, Fr y) + { + mclBnG1_mul(ref this, ref x, ref y); + } + } + [StructLayout(LayoutKind.Sequential)] + public struct G2 { + private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11; + private ulong v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23; + public void Clear() + { + mclBnG2_clear(ref this); + } + public void setStr(String s, int ioMode) + { + if (mclBnG2_setStr(ref this, s, s.Length, ioMode) != 0) { + throw new ArgumentException("mclBnG2_setStr:" + s); + } + } + public bool IsValid() + { + return mclBnG2_isValid(ref this) == 1; + } + public bool Equals(G2 rhs) + { + return mclBnG2_isEqual(ref this, ref rhs) == 1; + } + public bool IsZero() + { + return mclBnG2_isZero(ref this) == 1; + } + public void HashAndMapTo(String s) + { + if (mclBnG2_hashAndMapTo(ref this, s, s.Length) != 0) { + throw new ArgumentException("mclBnG2_hashAndMapTo:" + s); + } + } + public string GetStr(int ioMode) + { + StringBuilder sb = new StringBuilder(1024); + long size = mclBnG2_getStr(sb, sb.Capacity, ref this, ioMode); + if (size == 0) { + throw new InvalidOperationException("mclBnG2_getStr:"); + } + return sb.ToString(); + } + public void Neg(G2 x) + { + mclBnG2_neg(ref this, ref x); + } + public void Dbl(G2 x) + { + mclBnG2_dbl(ref this, ref x); + } + public void Add(G2 x, G2 y) + { + mclBnG2_add(ref this, ref x, ref y); + } + public void Sub(G2 x, G2 y) + { + mclBnG2_sub(ref this, ref x, ref y); + } + public void Mul(G2 x, Fr y) + { + mclBnG2_mul(ref this, ref x, ref y); + } + } + [StructLayout(LayoutKind.Sequential)] + public struct GT { + private ulong v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11; + private ulong v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23; + private ulong v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35; + private ulong v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47; + public void Clear() + { + mclBnGT_clear(ref this); + } + public void setStr(String s, int ioMode) + { + if (mclBnGT_setStr(ref this, s, s.Length, ioMode) != 0) { + throw new ArgumentException("mclBnGT_setStr:" + s); + } + } + public bool Equals(GT rhs) + { + return mclBnGT_isEqual(ref this, ref rhs) == 1; + } + public bool IsZero() + { + return mclBnGT_isZero(ref this) == 1; + } + public bool IsOne() + { + return mclBnGT_isOne(ref this) == 1; + } + public string GetStr(int ioMode) + { + StringBuilder sb = new StringBuilder(1024); + long size = mclBnGT_getStr(sb, sb.Capacity, ref this, ioMode); + if (size == 0) { + throw new InvalidOperationException("mclBnGT_getStr:"); + } + return sb.ToString(); + } + public void Neg(GT x) + { + mclBnGT_neg(ref this, ref x); + } + public void Inv(GT x) + { + mclBnGT_inv(ref this, ref x); + } + public void Add(GT x, GT y) + { + mclBnGT_add(ref this, ref x, ref y); + } + public void Sub(GT x, GT y) + { + mclBnGT_sub(ref this, ref x, ref y); + } + public void Mul(GT x, GT y) + { + mclBnGT_mul(ref this, ref x, ref y); + } + public void Div(GT x, GT y) + { + mclBnGT_div(ref this, ref x, ref y); + } + public static GT operator -(GT x) + { + GT y = new GT(); + y.Neg(x); + return y; + } + public static GT operator +(GT x, GT y) + { + GT z = new GT(); + z.Add(x, y); + return z; + } + public static GT operator -(GT x, GT y) + { + GT z = new GT(); + z.Sub(x, y); + return z; + } + public static GT operator *(GT x, GT y) + { + GT z = new GT(); + z.Mul(x, y); + return z; + } + public static GT operator /(GT x, GT y) + { + GT z = new GT(); + z.Div(x, y); + return z; + } + public void Pow(GT x, Fr y) + { + mclBnGT_pow(ref this, ref x, ref y); + } + public void Pairing(G1 x, G2 y) + { + mclBn_pairing(ref this, ref x, ref y); + } + public void FinalExp(GT x) + { + mclBn_finalExp(ref this, ref x); + } + public void MillerLoop(G1 x, G2 y) + { + mclBn_millerLoop(ref this, ref x, ref y); + } + } + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.csproj b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.csproj new file mode 100644 index 000000000..21a049f01 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.csproj @@ -0,0 +1,62 @@ + + + + + Debug + AnyCPU + {E9D06B1B-EA22-4EF4-BA4B-422F7625966B} + Exe + Properties + bn256 + bn256 + v4.5.2 + 512 + true + + + true + ..\..\bin\ + DEBUG;TRACE + false + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + ..\..\bin\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.sln b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.sln new file mode 100644 index 000000000..6e6aa67ee --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bn256", "bn256.csproj", "{E9D06B1B-EA22-4EF4-BA4B-422F7625966B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E9D06B1B-EA22-4EF4-BA4B-422F7625966B}.Debug|x64.ActiveCfg = Debug|x64 + {E9D06B1B-EA22-4EF4-BA4B-422F7625966B}.Debug|x64.Build.0 = Debug|x64 + {E9D06B1B-EA22-4EF4-BA4B-422F7625966B}.Release|x64.ActiveCfg = Release|x64 + {E9D06B1B-EA22-4EF4-BA4B-422F7625966B}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256_test.cs b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256_test.cs new file mode 100644 index 000000000..cad8c03d3 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/cs/bn256_test.cs @@ -0,0 +1,149 @@ +using System; + +namespace mcl { + using static BN256; + class BN256Test { + static int err = 0; + static void assert(string msg, bool b) + { + if (b) return; + Console.WriteLine("ERR {0}", msg); + err++; + } + static void Main(string[] args) + { + try { + assert("64bit system", System.Environment.Is64BitProcess); + init(); + TestFr(); + TestG1(); + TestG2(); + TestPairing(); + if (err == 0) { + Console.WriteLine("all tests succeed"); + } else { + Console.WriteLine("err={0}", err); + } + } catch (Exception e) { + Console.WriteLine("ERR={0}", e); + } + } + static void TestFr() + { + Console.WriteLine("TestFr"); + Fr x = new Fr(); + x.Clear(); + assert("0", x.GetStr(10) == "0"); + assert("0.IzZero", x.IsZero()); + assert("!0.IzOne", !x.IsOne()); + x.SetInt(1); + assert("1", x.GetStr(10) == "1"); + assert("!1.IzZero", !x.IsZero()); + assert("1.IzOne", x.IsOne()); + x.SetInt(3); + assert("3", x.GetStr(10) == "3"); + assert("!3.IzZero", !x.IsZero()); + assert("!3.IzOne", !x.IsOne()); + x.SetInt(-5); + x = -x; + assert("5", x.GetStr(10) == "5"); + x.SetInt(4); + x = x * x; + assert("16", x.GetStr(10) == "16"); + assert("10", x.GetStr(16) == "10"); + Fr y; + y = x; + assert("x == y", x.Equals(y)); + x.SetInt(123); + assert("123", x.GetStr(10) == "123"); + assert("7b", x.GetStr(16) == "7b"); + assert("y != x", !x.Equals(y)); + try { + x.SetStr("1234567891234x", 10); + Console.WriteLine("x = {0}", x); + } catch (Exception e) { + Console.WriteLine("exception test OK\n'{0}'", e); + } + x.SetStr("1234567891234", 10); + assert("1234567891234", x.GetStr(10) == "1234567891234"); + } + static void TestG1() + { + Console.WriteLine("TestG1"); + G1 P = new G1(); + P.Clear(); + assert("P.IsValid", P.IsValid()); + assert("P.IsZero", P.IsZero()); + P.HashAndMapTo("abc"); + assert("P.IsValid", P.IsValid()); + assert("!P.IsZero", !P.IsZero()); + G1 Q = new G1(); + Q = P; + assert("P == Q", Q.Equals(P)); + Q.Neg(P); + Q.Add(Q, P); + assert("P = Q", Q.IsZero()); + Q.Dbl(P); + G1 R = new G1(); + R.Add(P, P); + assert("Q == R", Q.Equals(R)); + Fr x = new Fr(); + x.SetInt(3); + R.Add(R, P); + Q.Mul(P, x); + assert("Q == R", Q.Equals(R)); + } + static void TestG2() + { + Console.WriteLine("TestG2"); + G2 P = new G2(); + P.Clear(); + assert("P is valid", P.IsValid()); + assert("P is zero", P.IsZero()); + P.HashAndMapTo("abc"); + assert("P is valid", P.IsValid()); + assert("P is not zero", !P.IsZero()); + G2 Q = new G2(); + Q = P; + assert("P == Q", Q.Equals(P)); + Q.Neg(P); + Q.Add(Q, P); + assert("Q is zero", Q.IsZero()); + Q.Dbl(P); + G2 R = new G2(); + R.Add(P, P); + assert("Q == R", Q.Equals(R)); + Fr x = new Fr(); + x.SetInt(3); + R.Add(R, P); + Q.Mul(P, x); + assert("Q == R", Q.Equals(R)); + } + static void TestPairing() + { + Console.WriteLine("TestG2"); + G1 P = new G1(); + P.HashAndMapTo("123"); + G2 Q = new G2(); + Q.HashAndMapTo("1"); + Fr a = new Fr(); + Fr b = new Fr(); + a.SetStr("12345678912345673453", 10); + b.SetStr("230498230982394243424", 10); + G1 aP = new G1(); + G2 bQ = new G2(); + aP.Mul(P, a); + bQ.Mul(Q, b); + GT e1 = new GT(); + GT e2 = new GT(); + GT e3 = new GT(); + e1.Pairing(P, Q); + e2.Pairing(aP, Q); + e3.Pow(e1, a); + assert("e2.Equals(e3)", e2.Equals(e3)); + e2.Pairing(P, bQ); + e3.Pow(e1, b); + assert("e2.Equals(e3)", e2.Equals(e3)); + } + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl.go b/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl.go new file mode 100644 index 000000000..a0c8bb4d3 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl.go @@ -0,0 +1,659 @@ +package mcl + +/* +#cgo bn256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=4 +#cgo bn384 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 +#cgo bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -DMCLBN_FR_UNIT_SIZE=4 +#cgo bn256 LDFLAGS:-lmclbn256 -lmcl +#cgo bn384 LDFLAGS:-lmclbn384 -lmcl +#cgo bn384_256 LDFLAGS:-lmclbn384_256 -lmcl +#include +*/ +import "C" +import "fmt" +import "unsafe" + +// CurveFp254BNb -- 254 bit curve +const CurveFp254BNb = C.mclBn_CurveFp254BNb + +// CurveFp382_1 -- 382 bit curve 1 +const CurveFp382_1 = C.mclBn_CurveFp382_1 + +// CurveFp382_2 -- 382 bit curve 2 +const CurveFp382_2 = C.mclBn_CurveFp382_2 + +// BLS12_381 +const BLS12_381 = C.MCL_BLS12_381 + +// IoSerializeHexStr +const IoSerializeHexStr = C.MCLBN_IO_SERIALIZE_HEX_STR + +// Init -- +// call this function before calling all the other operations +// this function is not thread safe +func Init(curve int) error { + err := C.mclBn_init(C.int(curve), C.MCLBN_COMPILED_TIME_VAR) + if err != 0 { + return fmt.Errorf("ERR mclBn_init curve=%d", curve) + } + return nil +} + +// GetFrUnitSize() -- +func GetFrUnitSize() int { + return int(C.MCLBN_FR_UNIT_SIZE) +} + +// GetFpUnitSize() -- +// same as GetMaxOpUnitSize() +func GetFpUnitSize() int { + return int(C.MCLBN_FP_UNIT_SIZE) +} + +// GetMaxOpUnitSize -- +func GetMaxOpUnitSize() int { + return int(C.MCLBN_FP_UNIT_SIZE) +} + +// GetOpUnitSize -- +// the length of Fr is GetOpUnitSize() * 8 bytes +func GetOpUnitSize() int { + return int(C.mclBn_getOpUnitSize()) +} + +// GetCurveOrder -- +// return the order of G1 +func GetCurveOrder() string { + buf := make([]byte, 1024) + // #nosec + n := C.mclBn_getCurveOrder((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))) + if n == 0 { + panic("implementation err. size of buf is small") + } + return string(buf[:n]) +} + +// GetFieldOrder -- +// return the characteristic of the field where a curve is defined +func GetFieldOrder() string { + buf := make([]byte, 1024) + // #nosec + n := C.mclBn_getFieldOrder((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))) + if n == 0 { + panic("implementation err. size of buf is small") + } + return string(buf[:n]) +} + +// Fr -- +type Fr struct { + v C.mclBnFr +} + +// getPointer -- +func (x *Fr) getPointer() (p *C.mclBnFr) { + // #nosec + return (*C.mclBnFr)(unsafe.Pointer(x)) +} + +// Clear -- +func (x *Fr) Clear() { + // #nosec + C.mclBnFr_clear(x.getPointer()) +} + +// SetInt64 -- +func (x *Fr) SetInt64(v int64) { + // #nosec + C.mclBnFr_setInt(x.getPointer(), C.int64_t(v)) +} + +// SetString -- +func (x *Fr) SetString(s string, base int) error { + buf := []byte(s) + // #nosec + err := C.mclBnFr_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) + if err != 0 { + return fmt.Errorf("err mclBnFr_setStr %x", err) + } + return nil +} + +// Deserialize -- +func (x *Fr) Deserialize(buf []byte) error { + // #nosec + err := C.mclBnFr_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err == 0 { + return fmt.Errorf("err mclBnFr_deserialize %x", buf) + } + return nil +} + +// SetLittleEndian -- +func (x *Fr) SetLittleEndian(buf []byte) error { + // #nosec + err := C.mclBnFr_setLittleEndian(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err != 0 { + return fmt.Errorf("err mclBnFr_setLittleEndian %x", err) + } + return nil +} + +// IsEqual -- +func (x *Fr) IsEqual(rhs *Fr) bool { + return C.mclBnFr_isEqual(x.getPointer(), rhs.getPointer()) == 1 +} + +// IsZero -- +func (x *Fr) IsZero() bool { + return C.mclBnFr_isZero(x.getPointer()) == 1 +} + +// IsOne -- +func (x *Fr) IsOne() bool { + return C.mclBnFr_isOne(x.getPointer()) == 1 +} + +// SetByCSPRNG -- +func (x *Fr) SetByCSPRNG() { + err := C.mclBnFr_setByCSPRNG(x.getPointer()) + if err != 0 { + panic("err mclBnFr_setByCSPRNG") + } +} + +// SetHashOf -- +func (x *Fr) SetHashOf(buf []byte) bool { + // #nosec + return C.mclBnFr_setHashOf(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) == 0 +} + +// GetString -- +func (x *Fr) GetString(base int) string { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnFr_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) + if n == 0 { + panic("err mclBnFr_getStr") + } + return string(buf[:n]) +} + +// Serialize -- +func (x *Fr) Serialize() []byte { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnFr_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) + if n == 0 { + panic("err mclBnFr_serialize") + } + return buf[:n] +} + +// FrNeg -- +func FrNeg(out *Fr, x *Fr) { + C.mclBnFr_neg(out.getPointer(), x.getPointer()) +} + +// FrInv -- +func FrInv(out *Fr, x *Fr) { + C.mclBnFr_inv(out.getPointer(), x.getPointer()) +} + +// FrAdd -- +func FrAdd(out *Fr, x *Fr, y *Fr) { + C.mclBnFr_add(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// FrSub -- +func FrSub(out *Fr, x *Fr, y *Fr) { + C.mclBnFr_sub(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// FrMul -- +func FrMul(out *Fr, x *Fr, y *Fr) { + C.mclBnFr_mul(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// FrDiv -- +func FrDiv(out *Fr, x *Fr, y *Fr) { + C.mclBnFr_div(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G1 -- +type G1 struct { + v C.mclBnG1 +} + +// getPointer -- +func (x *G1) getPointer() (p *C.mclBnG1) { + // #nosec + return (*C.mclBnG1)(unsafe.Pointer(x)) +} + +// Clear -- +func (x *G1) Clear() { + // #nosec + C.mclBnG1_clear(x.getPointer()) +} + +// SetString -- +func (x *G1) SetString(s string, base int) error { + buf := []byte(s) + // #nosec + err := C.mclBnG1_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) + if err != 0 { + return fmt.Errorf("err mclBnG1_setStr %x", err) + } + return nil +} + +// Deserialize -- +func (x *G1) Deserialize(buf []byte) error { + // #nosec + err := C.mclBnG1_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err == 0 { + return fmt.Errorf("err mclBnG1_deserialize %x", buf) + } + return nil +} + +// IsEqual -- +func (x *G1) IsEqual(rhs *G1) bool { + return C.mclBnG1_isEqual(x.getPointer(), rhs.getPointer()) == 1 +} + +// IsZero -- +func (x *G1) IsZero() bool { + return C.mclBnG1_isZero(x.getPointer()) == 1 +} + +// HashAndMapTo -- +func (x *G1) HashAndMapTo(buf []byte) error { + // #nosec + err := C.mclBnG1_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err != 0 { + return fmt.Errorf("err mclBnG1_hashAndMapTo %x", err) + } + return nil +} + +// GetString -- +func (x *G1) GetString(base int) string { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnG1_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) + if n == 0 { + panic("err mclBnG1_getStr") + } + return string(buf[:n]) +} + +// Serialize -- +func (x *G1) Serialize() []byte { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnG1_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) + if n == 0 { + panic("err mclBnG1_serialize") + } + return buf[:n] +} + +// G1Neg -- +func G1Neg(out *G1, x *G1) { + C.mclBnG1_neg(out.getPointer(), x.getPointer()) +} + +// G1Dbl -- +func G1Dbl(out *G1, x *G1) { + C.mclBnG1_dbl(out.getPointer(), x.getPointer()) +} + +// G1Add -- +func G1Add(out *G1, x *G1, y *G1) { + C.mclBnG1_add(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G1Sub -- +func G1Sub(out *G1, x *G1, y *G1) { + C.mclBnG1_sub(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G1Mul -- +func G1Mul(out *G1, x *G1, y *Fr) { + C.mclBnG1_mul(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G1MulCT -- constant time (depending on bit lengh of y) +func G1MulCT(out *G1, x *G1, y *Fr) { + C.mclBnG1_mulCT(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G2 -- +type G2 struct { + v C.mclBnG2 +} + +// getPointer -- +func (x *G2) getPointer() (p *C.mclBnG2) { + // #nosec + return (*C.mclBnG2)(unsafe.Pointer(x)) +} + +// Clear -- +func (x *G2) Clear() { + // #nosec + C.mclBnG2_clear(x.getPointer()) +} + +// SetString -- +func (x *G2) SetString(s string, base int) error { + buf := []byte(s) + // #nosec + err := C.mclBnG2_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) + if err != 0 { + return fmt.Errorf("err mclBnG2_setStr %x", err) + } + return nil +} + +// Deserialize -- +func (x *G2) Deserialize(buf []byte) error { + // #nosec + err := C.mclBnG2_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err == 0 { + return fmt.Errorf("err mclBnG2_deserialize %x", buf) + } + return nil +} + +// IsEqual -- +func (x *G2) IsEqual(rhs *G2) bool { + return C.mclBnG2_isEqual(x.getPointer(), rhs.getPointer()) == 1 +} + +// IsZero -- +func (x *G2) IsZero() bool { + return C.mclBnG2_isZero(x.getPointer()) == 1 +} + +// HashAndMapTo -- +func (x *G2) HashAndMapTo(buf []byte) error { + // #nosec + err := C.mclBnG2_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err != 0 { + return fmt.Errorf("err mclBnG2_hashAndMapTo %x", err) + } + return nil +} + +// GetString -- +func (x *G2) GetString(base int) string { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnG2_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) + if n == 0 { + panic("err mclBnG2_getStr") + } + return string(buf[:n]) +} + +// Serialize -- +func (x *G2) Serialize() []byte { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnG2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) + if n == 0 { + panic("err mclBnG2_serialize") + } + return buf[:n] +} + +// G2Neg -- +func G2Neg(out *G2, x *G2) { + C.mclBnG2_neg(out.getPointer(), x.getPointer()) +} + +// G2Dbl -- +func G2Dbl(out *G2, x *G2) { + C.mclBnG2_dbl(out.getPointer(), x.getPointer()) +} + +// G2Add -- +func G2Add(out *G2, x *G2, y *G2) { + C.mclBnG2_add(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G2Sub -- +func G2Sub(out *G2, x *G2, y *G2) { + C.mclBnG2_sub(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G2Mul -- +func G2Mul(out *G2, x *G2, y *Fr) { + C.mclBnG2_mul(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GT -- +type GT struct { + v C.mclBnGT +} + +// getPointer -- +func (x *GT) getPointer() (p *C.mclBnGT) { + // #nosec + return (*C.mclBnGT)(unsafe.Pointer(x)) +} + +// Clear -- +func (x *GT) Clear() { + // #nosec + C.mclBnGT_clear(x.getPointer()) +} + +// SetInt64 -- +func (x *GT) SetInt64(v int64) { + // #nosec + C.mclBnGT_setInt(x.getPointer(), C.int64_t(v)) +} + +// SetString -- +func (x *GT) SetString(s string, base int) error { + buf := []byte(s) + // #nosec + err := C.mclBnGT_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) + if err != 0 { + return fmt.Errorf("err mclBnGT_setStr %x", err) + } + return nil +} + +// Deserialize -- +func (x *GT) Deserialize(buf []byte) error { + // #nosec + err := C.mclBnGT_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err == 0 { + return fmt.Errorf("err mclBnGT_deserialize %x", buf) + } + return nil +} + +// IsEqual -- +func (x *GT) IsEqual(rhs *GT) bool { + return C.mclBnGT_isEqual(x.getPointer(), rhs.getPointer()) == 1 +} + +// IsZero -- +func (x *GT) IsZero() bool { + return C.mclBnGT_isZero(x.getPointer()) == 1 +} + +// IsOne -- +func (x *GT) IsOne() bool { + return C.mclBnGT_isOne(x.getPointer()) == 1 +} + +// GetString -- +func (x *GT) GetString(base int) string { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnGT_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) + if n == 0 { + panic("err mclBnGT_getStr") + } + return string(buf[:n]) +} + +// Serialize -- +func (x *GT) Serialize() []byte { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnGT_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) + if n == 0 { + panic("err mclBnGT_serialize") + } + return buf[:n] +} + +// GTNeg -- +func GTNeg(out *GT, x *GT) { + C.mclBnGT_neg(out.getPointer(), x.getPointer()) +} + +// GTInv -- +func GTInv(out *GT, x *GT) { + C.mclBnGT_inv(out.getPointer(), x.getPointer()) +} + +// GTAdd -- +func GTAdd(out *GT, x *GT, y *GT) { + C.mclBnGT_add(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GTSub -- +func GTSub(out *GT, x *GT, y *GT) { + C.mclBnGT_sub(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GTMul -- +func GTMul(out *GT, x *GT, y *GT) { + C.mclBnGT_mul(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GTDiv -- +func GTDiv(out *GT, x *GT, y *GT) { + C.mclBnGT_div(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GTPow -- +func GTPow(out *GT, x *GT, y *Fr) { + C.mclBnGT_pow(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// Pairing -- +func Pairing(out *GT, x *G1, y *G2) { + C.mclBn_pairing(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// FinalExp -- +func FinalExp(out *GT, x *GT) { + C.mclBn_finalExp(out.getPointer(), x.getPointer()) +} + +// MillerLoop -- +func MillerLoop(out *GT, x *G1, y *G2) { + C.mclBn_millerLoop(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GetUint64NumToPrecompute -- +func GetUint64NumToPrecompute() int { + return int(C.mclBn_getUint64NumToPrecompute()) +} + +// PrecomputeG2 -- +func PrecomputeG2(Qbuf []uint64, Q *G2) { + // #nosec + C.mclBn_precomputeG2((*C.uint64_t)(unsafe.Pointer(&Qbuf[0])), Q.getPointer()) +} + +// PrecomputedMillerLoop -- +func PrecomputedMillerLoop(out *GT, P *G1, Qbuf []uint64) { + // #nosec + C.mclBn_precomputedMillerLoop(out.getPointer(), P.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Qbuf[0]))) +} + +// PrecomputedMillerLoop2 -- +func PrecomputedMillerLoop2(out *GT, P1 *G1, Q1buf []uint64, P2 *G1, Q2buf []uint64) { + // #nosec + C.mclBn_precomputedMillerLoop2(out.getPointer(), P1.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Q1buf[0])), P1.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Q1buf[0]))) +} + +// FrEvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... +func FrEvaluatePolynomial(y *Fr, c []Fr, x *Fr) error { + // #nosec + err := C.mclBn_FrEvaluatePolynomial(y.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer()) + if err != 0 { + return fmt.Errorf("err mclBn_FrEvaluatePolynomial") + } + return nil +} + +// G1EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... +func G1EvaluatePolynomial(y *G1, c []G1, x *Fr) error { + // #nosec + err := C.mclBn_G1EvaluatePolynomial(y.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer()) + if err != 0 { + return fmt.Errorf("err mclBn_G1EvaluatePolynomial") + } + return nil +} + +// G2EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... +func G2EvaluatePolynomial(y *G2, c []G2, x *Fr) error { + // #nosec + err := C.mclBn_G2EvaluatePolynomial(y.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer()) + if err != 0 { + return fmt.Errorf("err mclBn_G2EvaluatePolynomial") + } + return nil +} + +// FrLagrangeInterpolation -- +func FrLagrangeInterpolation(out *Fr, xVec []Fr, yVec []Fr) error { + if len(xVec) != len(yVec) { + return fmt.Errorf("err FrLagrangeInterpolation:bad size") + } + // #nosec + err := C.mclBn_FrLagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec))) + if err != 0 { + return fmt.Errorf("err FrLagrangeInterpolation") + } + return nil +} + +// G1LagrangeInterpolation -- +func G1LagrangeInterpolation(out *G1, xVec []Fr, yVec []G1) error { + if len(xVec) != len(yVec) { + return fmt.Errorf("err G1LagrangeInterpolation:bad size") + } + // #nosec + err := C.mclBn_G1LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG1)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec))) + if err != 0 { + return fmt.Errorf("err G1LagrangeInterpolation") + } + return nil +} + +// G2LagrangeInterpolation -- +func G2LagrangeInterpolation(out *G2, xVec []Fr, yVec []G2) error { + if len(xVec) != len(yVec) { + return fmt.Errorf("err G2LagrangeInterpolation:bad size") + } + // #nosec + err := C.mclBn_G2LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec))) + if err != 0 { + return fmt.Errorf("err G2LagrangeInterpolation") + } + return nil +} diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl_test.go b/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl_test.go new file mode 100644 index 000000000..16bb6910f --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/go/mcl/mcl_test.go @@ -0,0 +1,157 @@ +package mcl + +import "testing" +import "fmt" + +func testBadPointOfG2(t *testing.T) { + var Q G2 + // this value is not in G2 so should return an error + err := Q.SetString("1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50", 16) + if err == nil { + t.Error(err) + } +} + +func testGT(t *testing.T) { + var x GT + x.Clear() + if !x.IsZero() { + t.Errorf("not zero") + } + x.SetInt64(1) + if !x.IsOne() { + t.Errorf("not one") + } +} + +func testHash(t *testing.T) { + var x Fr + if !x.SetHashOf([]byte("abc")) { + t.Error("SetHashOf") + } + fmt.Printf("x=%s\n", x.GetString(16)) +} + +func testNegAdd(t *testing.T) { + var x Fr + var P1, P2, P3 G1 + var Q1, Q2, Q3 G2 + err := P1.HashAndMapTo([]byte("this")) + if err != nil { + t.Error(err) + } + err = Q1.HashAndMapTo([]byte("this")) + if err != nil { + t.Error(err) + } + fmt.Printf("P1=%s\n", P1.GetString(16)) + fmt.Printf("Q1=%s\n", Q1.GetString(16)) + G1Neg(&P2, &P1) + G2Neg(&Q2, &Q1) + fmt.Printf("P2=%s\n", P2.GetString(16)) + fmt.Printf("Q2=%s\n", Q2.GetString(16)) + + x.SetInt64(-1) + G1Mul(&P3, &P1, &x) + G2Mul(&Q3, &Q1, &x) + if !P2.IsEqual(&P3) { + t.Errorf("P2 != P3 %s\n", P3.GetString(16)) + } + if !Q2.IsEqual(&Q3) { + t.Errorf("Q2 != Q3 %s\n", Q3.GetString(16)) + } + + G1Add(&P2, &P2, &P1) + G2Add(&Q2, &Q2, &Q1) + if !P2.IsZero() { + t.Errorf("P2 is not zero %s\n", P2.GetString(16)) + } + if !Q2.IsZero() { + t.Errorf("Q2 is not zero %s\n", Q2.GetString(16)) + } +} + +func testPairing(t *testing.T) { + var a, b, ab Fr + err := a.SetString("123", 10) + if err != nil { + t.Error(err) + return + } + err = b.SetString("456", 10) + if err != nil { + t.Error(err) + return + } + FrMul(&ab, &a, &b) + var P, aP G1 + var Q, bQ G2 + err = P.HashAndMapTo([]byte("this")) + if err != nil { + t.Error(err) + return + } + fmt.Printf("P=%s\n", P.GetString(16)) + G1Mul(&aP, &P, &a) + fmt.Printf("aP=%s\n", aP.GetString(16)) + err = Q.HashAndMapTo([]byte("that")) + if err != nil { + t.Error(err) + return + } + fmt.Printf("Q=%s\n", Q.GetString(16)) + G2Mul(&bQ, &Q, &b) + fmt.Printf("bQ=%s\n", bQ.GetString(16)) + var e1, e2 GT + Pairing(&e1, &P, &Q) + fmt.Printf("e1=%s\n", e1.GetString(16)) + Pairing(&e2, &aP, &bQ) + fmt.Printf("e2=%s\n", e1.GetString(16)) + GTPow(&e1, &e1, &ab) + fmt.Printf("e1=%s\n", e1.GetString(16)) + if !e1.IsEqual(&e2) { + t.Errorf("not equal pairing\n%s\n%s", e1.GetString(16), e2.GetString(16)) + } + { + s := P.GetString(IoSerializeHexStr) + var P1 G1 + P1.SetString(s, IoSerializeHexStr) + if !P1.IsEqual(&P) { + t.Error("not equal to P") + return + } + s = Q.GetString(IoSerializeHexStr) + var Q1 G2 + Q1.SetString(s, IoSerializeHexStr) + if !Q1.IsEqual(&Q) { + t.Error("not equal to Q") + return + } + } +} + +func testMcl(t *testing.T, c int) { + err := Init(c) + if err != nil { + t.Fatal(err) + } + testHash(t) + testNegAdd(t) + testPairing(t) + testGT(t) + testBadPointOfG2(t) +} + +func TestMclMain(t *testing.T) { + t.Logf("GetMaxOpUnitSize() = %d\n", GetMaxOpUnitSize()) + t.Log("CurveFp254BNb") + testMcl(t, CurveFp254BNb) + if GetMaxOpUnitSize() == 6 { + if GetFrUnitSize() == 6 { + t.Log("CurveFp382_1") + testMcl(t, CurveFp382_1) + } + t.Log("BLS12_381") + testMcl(t, BLS12_381) + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/Bn256Test.java b/vendor/github.com/dexon-foundation/mcl/ffi/java/Bn256Test.java new file mode 100644 index 000000000..b1f9f6f34 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/Bn256Test.java @@ -0,0 +1,104 @@ +import java.io.*; +import com.herumi.mcl.*; + +/* + Bn256Test +*/ +public class Bn256Test { + static { + String lib = "mcl_bn256"; + String libName = System.mapLibraryName(lib); + System.out.println("libName : " + libName); + System.loadLibrary(lib); + } + public static void assertEquals(String msg, String x, String y) { + if (x.equals(y)) { + System.out.println("OK : " + msg); + } else { + System.out.println("NG : " + msg + ", x = " + x + ", y = " + y); + } + } + public static void assertBool(String msg, boolean b) { + if (b) { + System.out.println("OK : " + msg); + } else { + System.out.println("NG : " + msg); + } + } + public static void main(String argv[]) { + try { + Bn256.SystemInit(); + Fr x = new Fr(5); + Fr y = new Fr(-2); + Fr z = new Fr(5); + assertBool("x != y", !x.equals(y)); + assertBool("x == z", x.equals(z)); + assertEquals("x == 5", x.toString(), "5"); + Bn256.add(x, x, y); + assertEquals("x == 3", x.toString(), "3"); + Bn256.mul(x, x, x); + assertEquals("x == 9", x.toString(), "9"); + G1 P = new G1(); + System.out.println("P=" + P); + P.set("-1", "1"); + System.out.println("P=" + P); + Bn256.neg(P, P); + System.out.println("P=" + P); + + String xa = "12723517038133731887338407189719511622662176727675373276651903807414909099441"; + String xb = "4168783608814932154536427934509895782246573715297911553964171371032945126671"; + String ya = "13891744915211034074451795021214165905772212241412891944830863846330766296736"; + String yb = "7937318970632701341203597196594272556916396164729705624521405069090520231616"; + + G2 Q = new G2(xa, xb, ya, yb); + + P.hashAndMapToG1("This is a pen"); + { + String s = P.toString(); + G1 P1 = new G1(); + P1.setStr(s); + assertBool("P == P1", P1.equals(P)); + } + + GT e = new GT(); + Bn256.pairing(e, P, Q); + GT e1 = new GT(); + GT e2 = new GT(); + Fr c = new Fr("1234567890123234928348230428394234"); + G2 cQ = new G2(Q); + Bn256.mul(cQ, Q, c); // cQ = Q * c + Bn256.pairing(e1, P, cQ); + Bn256.pow(e2, e, c); // e2 = e^c + assertBool("e1 == e2", e1.equals(e2)); + + G1 cP = new G1(P); + Bn256.mul(cP, P, c); // cP = P * c + Bn256.pairing(e1, cP, Q); + assertBool("e1 == e2", e1.equals(e2)); + + BLSsignature(Q); + } catch (RuntimeException e) { + System.out.println("unknown exception :" + e); + } + } + public static void BLSsignature(G2 Q) + { + Fr s = new Fr(); + s.setRand(); // secret key + System.out.println("secret key " + s); + G2 pub = new G2(); + Bn256.mul(pub, Q, s); // public key = sQ + + String m = "signature test"; + G1 H = new G1(); + H.hashAndMapToG1(m); // H = Hash(m) + G1 sign = new G1(); + Bn256.mul(sign, H, s); // signature of m = s H + + GT e1 = new GT(); + GT e2 = new GT(); + Bn256.pairing(e1, H, pub); // e1 = e(H, s Q) + Bn256.pairing(e2, sign, Q); // e2 = e(s H, Q); + assertBool("verify signature", e1.equals(e2)); + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/ElgamalTest.java b/vendor/github.com/dexon-foundation/mcl/ffi/java/ElgamalTest.java new file mode 100644 index 000000000..0cf49e144 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/ElgamalTest.java @@ -0,0 +1,144 @@ +import java.io.*; +import com.herumi.mcl.*; + +/* + ElgamalTest [ecParam] + ecParam = secp192k1, NIST_P224, ... + hashParam = hash224, hash384, ... +*/ +public class ElgamalTest { + static { + String lib = "mcl_elgamal"; + String libName = System.mapLibraryName(lib); + System.out.println("libName : " + libName); + System.loadLibrary(lib); + } + public static void assertEquals(String msg, int x, int y) { + if (x == y) { + System.out.println("OK : " + msg); + } else { + System.out.println("NG : " + msg + ", x = " + x + ", y = " + y); + } + } + public static void assertBool(String msg, boolean b) { + if (b) { + System.out.println("OK : " + msg); + } else { + System.out.println("NG : " + msg); + } + } + public static void main(String argv[]) { + try { + String ecStr = "secp192k1"; + String hashStr = "sha224"; + for (int i = 0; i < argv.length; i++) { + if (argv[i].equals("-e") && i < argv.length - 1) { + ecStr = argv[i + 1]; + i++; + } else + if (argv[i].equals("-h") && i < argv.length - 1) { + hashStr = argv[i + 1]; + i++; + } + } + String param = ecStr + " " + hashStr; + System.out.println("param=" + param); + Elgamal.SystemInit(param); + + String prvStr = ""; + String pubStr = ""; + { + PrivateKey prv = new PrivateKey(); + prv.init(); + prvStr = prv.toStr(); + PublicKey pub = prv.getPublicKey(); + pubStr = pub.toStr(); + } + int m = 1234; + CipherText c = new CipherText(); + PublicKey pub = new PublicKey(); + + pub.fromStr(pubStr); + + pub.enc(c, m); + + PrivateKey prv = new PrivateKey(); + prv.fromStr(prvStr); + prv.setCache(0, 60000); + + int dec = prv.dec(c); + // verify dec(enc(m)) == m + assertEquals("dec(enc(m)) == m", m, dec); + + // verify toStr, fromStr + { + String cStr = c.toStr(); + CipherText c2 = new CipherText(); + c2.fromStr(cStr); + int dec2 = prv.dec(c2); + assertEquals("fromStr(toStr(CipherText) == CipherText", dec, dec2); + } + + // verify dec(enc(str)) == str + pub.enc(c, "1234"); + dec = prv.dec(c); + assertEquals("dec(enc(str)) == str", m, dec); + + // verify dec(mul(enc(m), 3)) == m * 3 + c.mul(3); + m *= 3; + dec = prv.dec(c); + assertEquals("mul(int)", m, dec); + + // verify dec(mul(enc(m), "10")) == m * 10 + c.mul("10"); + m *= 10; + dec = prv.dec(c); + assertEquals("mul(str)", m, dec); + + // convert str + { + String s = c.toStr(); + CipherText c2 = new CipherText(); + c2.fromStr(s); + dec = prv.dec(c); + assertEquals("fromStr", m, dec); + } + // rerandomize + pub.rerandomize(c); + dec = prv.dec(c); + assertEquals("rerandomize", m, dec); + int m2 = 12345; + // verify dec(add(enc(m), m2)) == m + m2 + pub.add(c, m2); + m += m2; + dec = prv.dec(c); + assertEquals("pub.add(int)", m, dec); + + pub.add(c, "993"); + m += 993; + dec = prv.dec(c); + assertEquals("pub.add(str)", m, dec); + + // string test + String m3 = "-2000000"; + String m4 = "2001234"; + CipherText c2 = new CipherText(); + SWIGTYPE_p_bool b = Elgamal.new_p_bool(); + pub.enc(c, m3); + dec = prv.dec(c, b); + assertBool("expect dec fail", !Elgamal.p_bool_value(b)); + pub.enc(c2, m4); + dec = prv.dec(c2, b); + assertBool("expect dec fail", !Elgamal.p_bool_value(b)); + c.add(c2); // m3 + m4 + + dec = prv.dec(c, b); + assertEquals("int add", 1234, dec); + assertBool("expect dec success", Elgamal.p_bool_value(b)); + Elgamal.delete_p_bool(b); + } catch (RuntimeException e) { + System.out.println("unknown exception :" + e); + } + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/Makefile b/vendor/github.com/dexon-foundation/mcl/ffi/java/Makefile new file mode 100644 index 000000000..d69c043fb --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/Makefile @@ -0,0 +1,64 @@ +TOP_DIR=../.. +include $(TOP_DIR)/common.mk +ifeq ($(UNAME_S),Darwin) + JAVA_INC=-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/ +else + JAVA_INC=-I/usr/lib/jvm/default-java/include +#JAVA_INC=-I/usr/lib/jvm/java-7-openjdk-amd64/include + CFLAGS+=-z noexecstack + LDFLAGS+=-lrt +endif +CFLAGS+=$(JAVA_INC) $(JAVA_INC)/linux -I $(TOP_DIR)/include -I $(TOP_DIR)/../xbyak -I $(TOP_DIR)/../cybozulib/include -Wno-strict-aliasing +MCL_LIB=$(TOP_DIR)/lib/libmcl.a + +PACKAGE_NAME=com.herumi.mcl +PACKAGE_DIR=$(subst .,/,$(PACKAGE_NAME)) + +ELGAMAL_LIB=$(TOP_DIR)/bin/libmcl_elgamal.$(LIB_SUF) +BN256_LIB=$(TOP_DIR)/bin/libmcl_bn256.$(LIB_SUF) +JAVA_EXE=cd $(TOP_DIR)/bin && LD_LIBRARY_PATH=./:$(LD_LIBRARY_PATH) java -classpath ../ffi/java +all: $(ELGAMAL_LIB) + +elgamal_wrap.cxx: elgamal.i elgamal_impl.hpp + $(MKDIR) $(PACKAGE_DIR) + swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall elgamal.i + +bn256_wrap.cxx: bn256.i bn256_impl.hpp + $(MKDIR) $(PACKAGE_DIR) + swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall bn256.i + +$(MCL_LIB): + make -C $(TOP_DIR) + +$(ELGAMAL_LIB): elgamal_wrap.cxx $(MCL_LIB) + $(PRE)$(CXX) $< -o $@ $(CFLAGS) $(LDFLAGS) $(MCL_LIB) -shared + +$(BN256_LIB): bn256_wrap.cxx $(MCL_LIB) + $(PRE)$(CXX) $< -o $@ $(CFLAGS) $(LDFLAGS) $(MCL_LIB) -shared + +%.class: %.java + javac $< + +ElgamalTest.class: ElgamalTest.java $(ELGAMAL_LIB) +Bn256Test.class: Bn256Test.java $(BN256_LIB) + +jar: + jar cvf mcl.jar com + +test_elgamal: ElgamalTest.class $(ELGAMAL_LIB) + $(JAVA_EXE) ElgamalTest + $(JAVA_EXE) ElgamalTest -e NIST_P192 + $(JAVA_EXE) ElgamalTest -e NIST_P256 -h sha256 + $(JAVA_EXE) ElgamalTest -e NIST_P384 -h sha384 + $(JAVA_EXE) ElgamalTest -e NIST_P521 -h sha512 + +test_bn256: Bn256Test.class $(BN256_LIB) + $(JAVA_EXE) Bn256Test + +test: + $(MAKE) test_elgamal + $(MAKE) test_bn256 + +clean: + rm -rf *.class $(ELGAMAL_LIB) $(PACKAGE_DIR)/*.class *_wrap.cxx + diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256.i b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256.i new file mode 100644 index 000000000..94a8edb7a --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256.i @@ -0,0 +1,31 @@ +%module Bn256 + +%include "std_string.i" +%include "std_except.i" + + +%{ +#include +#include +#include +struct Param { + cybozu::RandomGenerator rg; + static inline Param& getParam() + { + static Param p; + return p; + } +}; + +static void HashAndMapToG1(mcl::bn256::G1& P, const std::string& m) +{ + std::string digest = cybozu::crypto::Hash::digest(cybozu::crypto::Hash::N_SHA256, m); + mcl::bn256::Fp t; + t.setArrayMask(digest.c_str(), digest.size()); + mcl::bn256::BN::param.mapTo.calcG1(P, t); +} + +#include "bn256_impl.hpp" +%} + +%include "bn256_impl.hpp" diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_impl.hpp b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_impl.hpp new file mode 100644 index 000000000..c4caaf3ca --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_impl.hpp @@ -0,0 +1,249 @@ +#include +#include +#include + +void SystemInit() throw(std::exception) +{ + mcl::bn256::initPairing(); +} + +class G1; +class G2; +class GT; +/* + Fr = Z / rZ +*/ +class Fr { + mcl::bn256::Fr self_; + friend class G1; + friend class G2; + friend class GT; + friend void neg(Fr& y, const Fr& x); + friend void add(Fr& z, const Fr& x, const Fr& y); + friend void sub(Fr& z, const Fr& x, const Fr& y); + friend void mul(Fr& z, const Fr& x, const Fr& y); + friend void mul(G1& z, const G1& x, const Fr& y); + friend void mul(G2& z, const G2& x, const Fr& y); + friend void div(Fr& z, const Fr& x, const Fr& y); + friend void pow(GT& z, const GT& x, const Fr& y); +public: + Fr() {} + Fr(const Fr& rhs) : self_(rhs.self_) {} + Fr(int x) : self_(x) {} + Fr(const std::string& str) throw(std::exception) + : self_(str) {} + bool equals(const Fr& rhs) const { return self_ == rhs.self_; } + void setStr(const std::string& str) throw(std::exception) + { + self_.setStr(str); + } + void setInt(int x) + { + self_ = x; + } + void clear() + { + self_.clear(); + } + void setRand() + { + self_.setRand(Param::getParam().rg); + } + std::string toString() const throw(std::exception) + { + return self_.getStr(); + } +}; + +void neg(Fr& y, const Fr& x) +{ + mcl::bn256::Fr::neg(y.self_, x.self_); +} + +void add(Fr& z, const Fr& x, const Fr& y) +{ + mcl::bn256::Fr::add(z.self_, x.self_, y.self_); +} + +void sub(Fr& z, const Fr& x, const Fr& y) +{ + mcl::bn256::Fr::sub(z.self_, x.self_, y.self_); +} + +void mul(Fr& z, const Fr& x, const Fr& y) +{ + mcl::bn256::Fr::mul(z.self_, x.self_, y.self_); +} + +void div(Fr& z, const Fr& x, const Fr& y) +{ + mcl::bn256::Fr::div(z.self_, x.self_, y.self_); +} + +/* + #G1 = r +*/ +class G1 { + mcl::bn256::G1 self_; + friend void neg(G1& y, const G1& x); + friend void dbl(G1& y, const G1& x); + friend void add(G1& z, const G1& x, const G1& y); + friend void sub(G1& z, const G1& x, const G1& y); + friend void mul(G1& z, const G1& x, const Fr& y); + friend void pairing(GT& e, const G1& P, const G2& Q); +public: + G1() {} + G1(const G1& rhs) : self_(rhs.self_) {} + G1(const std::string& x, const std::string& y) throw(std::exception) + : self_(mcl::bn256::Fp(x), mcl::bn256::Fp(y)) + { + } + bool equals(const G1& rhs) const { return self_ == rhs.self_; } + void set(const std::string& x, const std::string& y) + { + self_.set(mcl::bn256::Fp(x), mcl::bn256::Fp(y)); + } + void hashAndMapToG1(const std::string& m) throw(std::exception) + { + HashAndMapToG1(self_, m); + } + void clear() + { + self_.clear(); + } + /* + compressed format + */ + void setStr(const std::string& str) throw(std::exception) + { + self_.setStr(str); + } + std::string toString() const throw(std::exception) + { + return self_.getStr(); + } +}; + +void neg(G1& y, const G1& x) +{ + mcl::bn256::G1::neg(y.self_, x.self_); +} +void dbl(G1& y, const G1& x) +{ + mcl::bn256::G1::dbl(y.self_, x.self_); +} +void add(G1& z, const G1& x, const G1& y) +{ + mcl::bn256::G1::add(z.self_, x.self_, y.self_); +} +void sub(G1& z, const G1& x, const G1& y) +{ + mcl::bn256::G1::sub(z.self_, x.self_, y.self_); +} +void mul(G1& z, const G1& x, const Fr& y) +{ + mcl::bn256::G1::mul(z.self_, x.self_, y.self_); +} + +/* + #G2 = r +*/ +class G2 { + mcl::bn256::G2 self_; + friend void neg(G2& y, const G2& x); + friend void dbl(G2& y, const G2& x); + friend void add(G2& z, const G2& x, const G2& y); + friend void sub(G2& z, const G2& x, const G2& y); + friend void mul(G2& z, const G2& x, const Fr& y); + friend void pairing(GT& e, const G1& P, const G2& Q); +public: + G2() {} + G2(const G2& rhs) : self_(rhs.self_) {} + G2(const std::string& xa, const std::string& xb, const std::string& ya, const std::string& yb) throw(std::exception) + : self_(mcl::bn256::Fp2(xa, xb), mcl::bn256::Fp2(ya, yb)) + { + } + bool equals(const G2& rhs) const { return self_ == rhs.self_; } + void set(const std::string& xa, const std::string& xb, const std::string& ya, const std::string& yb) + { + self_.set(mcl::bn256::Fp2(xa, xb), mcl::bn256::Fp2(ya, yb)); + } + void clear() + { + self_.clear(); + } + /* + compressed format + */ + void setStr(const std::string& str) throw(std::exception) + { + self_.setStr(str); + } + std::string toString() const throw(std::exception) + { + return self_.getStr(); + } +}; + +void neg(G2& y, const G2& x) +{ + mcl::bn256::G2::neg(y.self_, x.self_); +} +void dbl(G2& y, const G2& x) +{ + mcl::bn256::G2::dbl(y.self_, x.self_); +} +void add(G2& z, const G2& x, const G2& y) +{ + mcl::bn256::G2::add(z.self_, x.self_, y.self_); +} +void sub(G2& z, const G2& x, const G2& y) +{ + mcl::bn256::G2::sub(z.self_, x.self_, y.self_); +} +void mul(G2& z, const G2& x, const Fr& y) +{ + mcl::bn256::G2::mul(z.self_, x.self_, y.self_); +} + +/* + #GT = r +*/ +class GT { + mcl::bn256::Fp12 self_; + friend void mul(GT& z, const GT& x, const GT& y); + friend void pow(GT& z, const GT& x, const Fr& y); + friend void pairing(GT& e, const G1& P, const G2& Q); +public: + GT() {} + GT(const GT& rhs) : self_(rhs.self_) {} + bool equals(const GT& rhs) const { return self_ == rhs.self_; } + void clear() + { + self_.clear(); + } + void setStr(const std::string& str) throw(std::exception) + { + std::istringstream iss(str); + iss >> self_; + } + std::string toString() const throw(std::exception) + { + std::ostringstream oss; + oss << self_; + return oss.str(); + } +}; + +void mul(GT& z, const GT& x, const GT& y) +{ + mcl::bn256::Fp12::mul(z.self_, x.self_, y.self_); +} +void pow(GT& z, const GT& x, const Fr& y) +{ + mcl::bn256::Fp12::pow(z.self_, x.self_, y.self_); +} +void pairing(GT& e, const G1& P, const G2& Q) +{ + mcl::bn256::pairing(e.self_, P.self_, Q.self_); +} diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_wrap.cxx b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_wrap.cxx new file mode 100644 index 000000000..0c8257af5 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/bn256_wrap.cxx @@ -0,0 +1,1542 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 3.0.12 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + + +#ifndef SWIGJAVA +#define SWIGJAVA +#endif + + + +#ifdef __cplusplus +/* SwigValueWrapper is described in swig.swg */ +template class SwigValueWrapper { + struct SwigMovePointer { + T *ptr; + SwigMovePointer(T *p) : ptr(p) { } + ~SwigMovePointer() { delete ptr; } + SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } + } pointer; + SwigValueWrapper& operator=(const SwigValueWrapper& rhs); + SwigValueWrapper(const SwigValueWrapper& rhs); +public: + SwigValueWrapper() : pointer(0) { } + SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } + operator T&() const { return *pointer.ptr; } + T *operator&() { return pointer.ptr; } +}; + +template T SwigValueInit() { + return T(); +} +#endif + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if defined(__GNUC__) +# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + +/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ +#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) +# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +/* Intel's compiler complains if a variable which was never initialised is + * cast to void, which is a common idiom which we use to indicate that we + * are aware a variable isn't used. So we just silence that warning. + * See: https://github.com/swig/swig/issues/192 for more discussion. + */ +#ifdef __INTEL_COMPILER +# pragma warning disable 592 +#endif + + +/* Fix for jlong on some versions of gcc on Windows */ +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) + typedef long long __int64; +#endif + +/* Fix for jlong on 64-bit x86 Solaris */ +#if defined(__x86_64) +# ifdef _LP64 +# undef _LP64 +# endif +#endif + +#include +#include +#include + + +/* Support for throwing Java exceptions */ +typedef enum { + SWIG_JavaOutOfMemoryError = 1, + SWIG_JavaIOException, + SWIG_JavaRuntimeException, + SWIG_JavaIndexOutOfBoundsException, + SWIG_JavaArithmeticException, + SWIG_JavaIllegalArgumentException, + SWIG_JavaNullPointerException, + SWIG_JavaDirectorPureVirtual, + SWIG_JavaUnknownError +} SWIG_JavaExceptionCodes; + +typedef struct { + SWIG_JavaExceptionCodes code; + const char *java_exception; +} SWIG_JavaExceptions_t; + + +static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionCodes code, const char *msg) { + jclass excep; + static const SWIG_JavaExceptions_t java_exceptions[] = { + { SWIG_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" }, + { SWIG_JavaIOException, "java/io/IOException" }, + { SWIG_JavaRuntimeException, "java/lang/RuntimeException" }, + { SWIG_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" }, + { SWIG_JavaArithmeticException, "java/lang/ArithmeticException" }, + { SWIG_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" }, + { SWIG_JavaNullPointerException, "java/lang/NullPointerException" }, + { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" }, + { SWIG_JavaUnknownError, "java/lang/UnknownError" }, + { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" } + }; + const SWIG_JavaExceptions_t *except_ptr = java_exceptions; + + while (except_ptr->code != code && except_ptr->code) + except_ptr++; + + jenv->ExceptionClear(); + excep = jenv->FindClass(except_ptr->java_exception); + if (excep) + jenv->ThrowNew(excep, msg); +} + + +/* Contract support */ + +#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, msg); return nullreturn; } else + + +#include + + +#include +#include + + +#include +#include +#include +struct Param { + cybozu::RandomGenerator rg; + static inline Param& getParam() + { + static Param p; + return p; + } +}; + +static void HashAndMapToG1(mcl::bn256::G1& P, const std::string& m) +{ + std::string digest = cybozu::crypto::Hash::digest(cybozu::crypto::Hash::N_SHA256, m); + mcl::bn256::Fp t; + t.setArrayMask(digest.c_str(), digest.size()); + mcl::bn256::BN::param.mapTo.calcG1(P, t); +} + +#include "bn256_impl.hpp" + + +#ifdef __cplusplus +extern "C" { +#endif + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_SystemInit(JNIEnv *jenv, jclass jcls) { + (void)jenv; + (void)jcls; + try { + SystemInit(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_neg_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + Fr *arg1 = 0 ; + Fr *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(Fr **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null"); + return ; + } + arg2 = *(Fr **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + neg(*arg1,(Fr const &)*arg2); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_add_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + Fr *arg1 = 0 ; + Fr *arg2 = 0 ; + Fr *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(Fr **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null"); + return ; + } + arg2 = *(Fr **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + arg3 = *(Fr **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + add(*arg1,(Fr const &)*arg2,(Fr const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_sub_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + Fr *arg1 = 0 ; + Fr *arg2 = 0 ; + Fr *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(Fr **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null"); + return ; + } + arg2 = *(Fr **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + arg3 = *(Fr **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + sub(*arg1,(Fr const &)*arg2,(Fr const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_mul_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + Fr *arg1 = 0 ; + Fr *arg2 = 0 ; + Fr *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(Fr **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null"); + return ; + } + arg2 = *(Fr **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + arg3 = *(Fr **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + mul(*arg1,(Fr const &)*arg2,(Fr const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_mul_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + G1 *arg1 = 0 ; + G1 *arg2 = 0 ; + Fr *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(G1 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null"); + return ; + } + arg2 = *(G1 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return ; + } + arg3 = *(Fr **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + mul(*arg1,(G1 const &)*arg2,(Fr const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_mul_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + G2 *arg1 = 0 ; + G2 *arg2 = 0 ; + Fr *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(G2 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null"); + return ; + } + arg2 = *(G2 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return ; + } + arg3 = *(Fr **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + mul(*arg1,(G2 const &)*arg2,(Fr const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_div(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + Fr *arg1 = 0 ; + Fr *arg2 = 0 ; + Fr *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(Fr **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr & reference is null"); + return ; + } + arg2 = *(Fr **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + arg3 = *(Fr **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + div(*arg1,(Fr const &)*arg2,(Fr const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_pow(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + GT *arg1 = 0 ; + GT *arg2 = 0 ; + Fr *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(GT **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT & reference is null"); + return ; + } + arg2 = *(GT **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null"); + return ; + } + arg3 = *(Fr **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return ; + } + pow(*arg1,(GT const &)*arg2,(Fr const &)*arg3); +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1Fr_1_1SWIG_10(JNIEnv *jenv, jclass jcls) { + jlong jresult = 0 ; + Fr *result = 0 ; + + (void)jenv; + (void)jcls; + result = (Fr *)new Fr(); + *(Fr **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1Fr_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jlong jresult = 0 ; + Fr *arg1 = 0 ; + Fr *result = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(Fr **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return 0; + } + result = (Fr *)new Fr((Fr const &)*arg1); + *(Fr **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1Fr_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jint jarg1) { + jlong jresult = 0 ; + int arg1 ; + Fr *result = 0 ; + + (void)jenv; + (void)jcls; + arg1 = (int)jarg1; + result = (Fr *)new Fr(arg1); + *(Fr **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1Fr_1_1SWIG_13(JNIEnv *jenv, jclass jcls, jstring jarg1) { + jlong jresult = 0 ; + std::string *arg1 = 0 ; + Fr *result = 0 ; + + (void)jenv; + (void)jcls; + if(!jarg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return 0; + } + const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0); + if (!arg1_pstr) return 0; + std::string arg1_str(arg1_pstr); + arg1 = &arg1_str; + jenv->ReleaseStringUTFChars(jarg1, arg1_pstr); + try { + result = (Fr *)new Fr((std::string const &)*arg1); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + *(Fr **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1equals(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + jboolean jresult = 0 ; + Fr *arg1 = (Fr *) 0 ; + Fr *arg2 = 0 ; + bool result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(Fr **)&jarg1; + arg2 = *(Fr **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Fr const & reference is null"); + return 0; + } + result = (bool)((Fr const *)arg1)->equals((Fr const &)*arg2); + jresult = (jboolean)result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1setStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + Fr *arg1 = (Fr *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(Fr **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->setStr((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1setInt(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) { + Fr *arg1 = (Fr *) 0 ; + int arg2 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(Fr **)&jarg1; + arg2 = (int)jarg2; + (arg1)->setInt(arg2); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1clear(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + Fr *arg1 = (Fr *) 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(Fr **)&jarg1; + (arg1)->clear(); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1setRand(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + Fr *arg1 = (Fr *) 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(Fr **)&jarg1; + (arg1)->setRand(); +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_Bn256JNI_Fr_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + Fr *arg1 = (Fr *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(Fr **)&jarg1; + try { + result = ((Fr const *)arg1)->toString(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_delete_1Fr(JNIEnv *jenv, jclass jcls, jlong jarg1) { + Fr *arg1 = (Fr *) 0 ; + + (void)jenv; + (void)jcls; + arg1 = *(Fr **)&jarg1; + delete arg1; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_neg_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + G1 *arg1 = 0 ; + G1 *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(G1 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null"); + return ; + } + arg2 = *(G1 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return ; + } + neg(*arg1,(G1 const &)*arg2); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_dbl_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + G1 *arg1 = 0 ; + G1 *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(G1 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null"); + return ; + } + arg2 = *(G1 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return ; + } + dbl(*arg1,(G1 const &)*arg2); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_add_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + G1 *arg1 = 0 ; + G1 *arg2 = 0 ; + G1 *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(G1 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null"); + return ; + } + arg2 = *(G1 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return ; + } + arg3 = *(G1 **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return ; + } + add(*arg1,(G1 const &)*arg2,(G1 const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_sub_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + G1 *arg1 = 0 ; + G1 *arg2 = 0 ; + G1 *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(G1 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 & reference is null"); + return ; + } + arg2 = *(G1 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return ; + } + arg3 = *(G1 **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return ; + } + sub(*arg1,(G1 const &)*arg2,(G1 const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_pairing(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + GT *arg1 = 0 ; + G1 *arg2 = 0 ; + G2 *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(GT **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT & reference is null"); + return ; + } + arg2 = *(G1 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return ; + } + arg3 = *(G2 **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return ; + } + pairing(*arg1,(G1 const &)*arg2,(G2 const &)*arg3); +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G1_1_1SWIG_10(JNIEnv *jenv, jclass jcls) { + jlong jresult = 0 ; + G1 *result = 0 ; + + (void)jenv; + (void)jcls; + result = (G1 *)new G1(); + *(G1 **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G1_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jlong jresult = 0 ; + G1 *arg1 = 0 ; + G1 *result = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G1 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return 0; + } + result = (G1 *)new G1((G1 const &)*arg1); + *(G1 **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G1_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2) { + jlong jresult = 0 ; + std::string *arg1 = 0 ; + std::string *arg2 = 0 ; + G1 *result = 0 ; + + (void)jenv; + (void)jcls; + if(!jarg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return 0; + } + const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0); + if (!arg1_pstr) return 0; + std::string arg1_str(arg1_pstr); + arg1 = &arg1_str; + jenv->ReleaseStringUTFChars(jarg1, arg1_pstr); + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return 0; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return 0; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + result = (G1 *)new G1((std::string const &)*arg1,(std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + *(G1 **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1equals(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + jboolean jresult = 0 ; + G1 *arg1 = (G1 *) 0 ; + G1 *arg2 = 0 ; + bool result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(G1 **)&jarg1; + arg2 = *(G1 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G1 const & reference is null"); + return 0; + } + result = (bool)((G1 const *)arg1)->equals((G1 const &)*arg2); + jresult = (jboolean)result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1set(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3) { + G1 *arg1 = (G1 *) 0 ; + std::string *arg2 = 0 ; + std::string *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G1 **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + if(!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0); + if (!arg3_pstr) return ; + std::string arg3_str(arg3_pstr); + arg3 = &arg3_str; + jenv->ReleaseStringUTFChars(jarg3, arg3_pstr); + (arg1)->set((std::string const &)*arg2,(std::string const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1hashAndMapToG1(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + G1 *arg1 = (G1 *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G1 **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->hashAndMapToG1((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1clear(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + G1 *arg1 = (G1 *) 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G1 **)&jarg1; + (arg1)->clear(); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1setStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + G1 *arg1 = (G1 *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G1 **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->setStr((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_Bn256JNI_G1_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + G1 *arg1 = (G1 *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G1 **)&jarg1; + try { + result = ((G1 const *)arg1)->toString(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_delete_1G1(JNIEnv *jenv, jclass jcls, jlong jarg1) { + G1 *arg1 = (G1 *) 0 ; + + (void)jenv; + (void)jcls; + arg1 = *(G1 **)&jarg1; + delete arg1; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_neg_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + G2 *arg1 = 0 ; + G2 *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(G2 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null"); + return ; + } + arg2 = *(G2 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return ; + } + neg(*arg1,(G2 const &)*arg2); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_dbl_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + G2 *arg1 = 0 ; + G2 *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(G2 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null"); + return ; + } + arg2 = *(G2 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return ; + } + dbl(*arg1,(G2 const &)*arg2); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_add_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + G2 *arg1 = 0 ; + G2 *arg2 = 0 ; + G2 *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(G2 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null"); + return ; + } + arg2 = *(G2 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return ; + } + arg3 = *(G2 **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return ; + } + add(*arg1,(G2 const &)*arg2,(G2 const &)*arg3); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_sub_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + G2 *arg1 = 0 ; + G2 *arg2 = 0 ; + G2 *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(G2 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 & reference is null"); + return ; + } + arg2 = *(G2 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return ; + } + arg3 = *(G2 **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return ; + } + sub(*arg1,(G2 const &)*arg2,(G2 const &)*arg3); +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G2_1_1SWIG_10(JNIEnv *jenv, jclass jcls) { + jlong jresult = 0 ; + G2 *result = 0 ; + + (void)jenv; + (void)jcls; + result = (G2 *)new G2(); + *(G2 **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G2_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jlong jresult = 0 ; + G2 *arg1 = 0 ; + G2 *result = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G2 **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return 0; + } + result = (G2 *)new G2((G2 const &)*arg1); + *(G2 **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1G2_1_1SWIG_12(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2, jstring jarg3, jstring jarg4) { + jlong jresult = 0 ; + std::string *arg1 = 0 ; + std::string *arg2 = 0 ; + std::string *arg3 = 0 ; + std::string *arg4 = 0 ; + G2 *result = 0 ; + + (void)jenv; + (void)jcls; + if(!jarg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return 0; + } + const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0); + if (!arg1_pstr) return 0; + std::string arg1_str(arg1_pstr); + arg1 = &arg1_str; + jenv->ReleaseStringUTFChars(jarg1, arg1_pstr); + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return 0; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return 0; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + if(!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return 0; + } + const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0); + if (!arg3_pstr) return 0; + std::string arg3_str(arg3_pstr); + arg3 = &arg3_str; + jenv->ReleaseStringUTFChars(jarg3, arg3_pstr); + if(!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return 0; + } + const char *arg4_pstr = (const char *)jenv->GetStringUTFChars(jarg4, 0); + if (!arg4_pstr) return 0; + std::string arg4_str(arg4_pstr); + arg4 = &arg4_str; + jenv->ReleaseStringUTFChars(jarg4, arg4_pstr); + try { + result = (G2 *)new G2((std::string const &)*arg1,(std::string const &)*arg2,(std::string const &)*arg3,(std::string const &)*arg4); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + *(G2 **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1equals(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + jboolean jresult = 0 ; + G2 *arg1 = (G2 *) 0 ; + G2 *arg2 = 0 ; + bool result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(G2 **)&jarg1; + arg2 = *(G2 **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "G2 const & reference is null"); + return 0; + } + result = (bool)((G2 const *)arg1)->equals((G2 const &)*arg2); + jresult = (jboolean)result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1set(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3, jstring jarg4, jstring jarg5) { + G2 *arg1 = (G2 *) 0 ; + std::string *arg2 = 0 ; + std::string *arg3 = 0 ; + std::string *arg4 = 0 ; + std::string *arg5 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G2 **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + if(!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0); + if (!arg3_pstr) return ; + std::string arg3_str(arg3_pstr); + arg3 = &arg3_str; + jenv->ReleaseStringUTFChars(jarg3, arg3_pstr); + if(!jarg4) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg4_pstr = (const char *)jenv->GetStringUTFChars(jarg4, 0); + if (!arg4_pstr) return ; + std::string arg4_str(arg4_pstr); + arg4 = &arg4_str; + jenv->ReleaseStringUTFChars(jarg4, arg4_pstr); + if(!jarg5) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg5_pstr = (const char *)jenv->GetStringUTFChars(jarg5, 0); + if (!arg5_pstr) return ; + std::string arg5_str(arg5_pstr); + arg5 = &arg5_str; + jenv->ReleaseStringUTFChars(jarg5, arg5_pstr); + (arg1)->set((std::string const &)*arg2,(std::string const &)*arg3,(std::string const &)*arg4,(std::string const &)*arg5); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1clear(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + G2 *arg1 = (G2 *) 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G2 **)&jarg1; + (arg1)->clear(); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1setStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + G2 *arg1 = (G2 *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G2 **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->setStr((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_Bn256JNI_G2_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + G2 *arg1 = (G2 *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(G2 **)&jarg1; + try { + result = ((G2 const *)arg1)->toString(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_delete_1G2(JNIEnv *jenv, jclass jcls, jlong jarg1) { + G2 *arg1 = (G2 *) 0 ; + + (void)jenv; + (void)jcls; + arg1 = *(G2 **)&jarg1; + delete arg1; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_mul_1_1SWIG_13(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3, jobject jarg3_) { + GT *arg1 = 0 ; + GT *arg2 = 0 ; + GT *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + (void)jarg3_; + arg1 = *(GT **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT & reference is null"); + return ; + } + arg2 = *(GT **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null"); + return ; + } + arg3 = *(GT **)&jarg3; + if (!arg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null"); + return ; + } + mul(*arg1,(GT const &)*arg2,(GT const &)*arg3); +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1GT_1_1SWIG_10(JNIEnv *jenv, jclass jcls) { + jlong jresult = 0 ; + GT *result = 0 ; + + (void)jenv; + (void)jcls; + result = (GT *)new GT(); + *(GT **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_Bn256JNI_new_1GT_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jlong jresult = 0 ; + GT *arg1 = 0 ; + GT *result = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(GT **)&jarg1; + if (!arg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null"); + return 0; + } + result = (GT *)new GT((GT const &)*arg1); + *(GT **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_Bn256JNI_GT_1equals(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + jboolean jresult = 0 ; + GT *arg1 = (GT *) 0 ; + GT *arg2 = 0 ; + bool result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(GT **)&jarg1; + arg2 = *(GT **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "GT const & reference is null"); + return 0; + } + result = (bool)((GT const *)arg1)->equals((GT const &)*arg2); + jresult = (jboolean)result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_GT_1clear(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + GT *arg1 = (GT *) 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(GT **)&jarg1; + (arg1)->clear(); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_GT_1setStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + GT *arg1 = (GT *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(GT **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->setStr((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_Bn256JNI_GT_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + GT *arg1 = (GT *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(GT **)&jarg1; + try { + result = ((GT const *)arg1)->toString(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_Bn256JNI_delete_1GT(JNIEnv *jenv, jclass jcls, jlong jarg1) { + GT *arg1 = (GT *) 0 ; + + (void)jenv; + (void)jcls; + arg1 = *(GT **)&jarg1; + delete arg1; +} + + +#ifdef __cplusplus +} +#endif + diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal.i b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal.i new file mode 100644 index 000000000..410723174 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal.i @@ -0,0 +1,28 @@ +%module Elgamal + +%include "std_string.i" +%include "std_except.i" + + +%{ +#include +#include +#include +#include +struct Param { +const mcl::EcParam *ecParam; +cybozu::RandomGenerator rg; +cybozu::crypto::Hash::Name hashName; +static inline Param& getParam() +{ + static Param p; + return p; +} +}; + +#include "elgamal_impl.hpp" +%} +%include cpointer.i +%pointer_functions(bool, p_bool); + +%include "elgamal_impl.hpp" diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_impl.hpp b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_impl.hpp new file mode 100644 index 000000000..dbf2ba64e --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_impl.hpp @@ -0,0 +1,147 @@ +#pragma once +//#define MCL_MAX_BIT_SIZE 521 +#include +#include +#include +#include +#include +#include +#include + +typedef mcl::FpT Fp; +typedef mcl::FpT Zn; +typedef mcl::EcT Ec; +typedef mcl::ElgamalT Elgamal; + +/* + init system + @param param [in] string such as "ecParamName hashName" + @note NOT thread safe because setting global parameters of elliptic curve + ex1) "secp192k1 sha256" // 192bit security + sha256 + ex2) "secp160k1 sha1" // 160bit security + sha1 + hashName : sha1 sha224 sha256 sha384 sha512 +*/ +void SystemInit(const std::string& param) throw(std::exception) +{ + std::istringstream iss(param); + std::string ecParamStr; + std::string hashNameStr; + if (iss >> ecParamStr >> hashNameStr) { + Param& p = Param::getParam(); + p.ecParam = mcl::getEcParam(ecParamStr); + Zn::init(p.ecParam->n); + Fp::init(p.ecParam->p); + Ec::init(p.ecParam->a, p.ecParam->b); + p.hashName = cybozu::crypto::Hash::getName(hashNameStr); + return; + } + throw cybozu::Exception("SystemInit:bad param") << param; +} + +class CipherText { + Elgamal::CipherText self_; + friend class PublicKey; + friend class PrivateKey; +public: + std::string toStr() const throw(std::exception) { return self_.toStr(); } + std::string toString() const throw(std::exception) { return toStr(); } + void fromStr(const std::string& str) throw(std::exception) { self_.fromStr(str); } + + void add(const CipherText& c) throw(std::exception) { self_.add(c.self_); } + void mul(int m) throw(std::exception) + { + self_.mul(m); + } + void mul(const std::string& str) throw(std::exception) + { + Zn zn(str); + self_.mul(zn); + } +}; + +class PublicKey { + Elgamal::PublicKey self_; + friend class PrivateKey; +public: + std::string toStr() const throw(std::exception) { return self_.toStr(); } + std::string toString() const throw(std::exception) { return toStr(); } + void fromStr(const std::string& str) throw(std::exception) { self_.fromStr(str); } + + void save(const std::string& fileName) const throw(std::exception) + { + std::ofstream ofs(fileName.c_str(), std::ios::binary); + if (!(ofs << self_)) throw cybozu::Exception("PublicKey:save") << fileName; + } + void load(const std::string& fileName) throw(std::exception) + { + std::ifstream ifs(fileName.c_str(), std::ios::binary); + if (!(ifs >> self_)) throw cybozu::Exception("PublicKey:load") << fileName; + } + void enc(CipherText& c, int m) const throw(std::exception) + { + self_.enc(c.self_, m, Param::getParam().rg); + } + void enc(CipherText& c, const std::string& str) const throw(std::exception) + { + Zn zn(str); + self_.enc(c.self_, zn, Param::getParam().rg); + } + void rerandomize(CipherText& c) const throw(std::exception) + { + self_.rerandomize(c.self_, Param::getParam().rg); + } + void add(CipherText& c, int m) const throw(std::exception) + { + self_.add(c.self_, m); + } + void add(CipherText& c, const std::string& str) const throw(std::exception) + { + Zn zn(str); + self_.add(c.self_, zn); + } +}; + +class PrivateKey { + Elgamal::PrivateKey self_; +public: + std::string toStr() const throw(std::exception) { return self_.toStr(); } + std::string toString() const throw(std::exception) { return toStr(); } + void fromStr(const std::string& str) throw(std::exception) { self_.fromStr(str); } + + void save(const std::string& fileName) const throw(std::exception) + { + std::ofstream ofs(fileName.c_str(), std::ios::binary); + if (!(ofs << self_)) throw cybozu::Exception("PrivateKey:save") << fileName; + } + void load(const std::string& fileName) throw(std::exception) + { + std::ifstream ifs(fileName.c_str(), std::ios::binary); + if (!(ifs >> self_)) throw cybozu::Exception("PrivateKey:load") << fileName; + } + void init() throw(std::exception) + { + Param& p = Param::getParam(); + const Fp x0(p.ecParam->gx); + const Fp y0(p.ecParam->gy); + Ec P(x0, y0); + self_.init(P, Zn::getBitSize(), p.rg); + } + PublicKey getPublicKey() const throw(std::exception) + { + PublicKey ret; + ret.self_ = self_.getPublicKey(); + return ret; + } + int dec(const CipherText& c, bool *b = 0) const throw(std::exception) + { + return self_.dec(c.self_, b); + } + void setCache(int rangeMin, int rangeMax) throw(std::exception) + { + self_.setCache(rangeMin, rangeMax); + } + void clearCache() throw(std::exception) + { + self_.clearCache(); + } +}; diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_wrap.cxx b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_wrap.cxx new file mode 100644 index 000000000..38d05f489 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/elgamal_wrap.cxx @@ -0,0 +1,1129 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 3.0.12 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + + +#ifndef SWIGJAVA +#define SWIGJAVA +#endif + + + +#ifdef __cplusplus +/* SwigValueWrapper is described in swig.swg */ +template class SwigValueWrapper { + struct SwigMovePointer { + T *ptr; + SwigMovePointer(T *p) : ptr(p) { } + ~SwigMovePointer() { delete ptr; } + SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } + } pointer; + SwigValueWrapper& operator=(const SwigValueWrapper& rhs); + SwigValueWrapper(const SwigValueWrapper& rhs); +public: + SwigValueWrapper() : pointer(0) { } + SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } + operator T&() const { return *pointer.ptr; } + T *operator&() { return pointer.ptr; } +}; + +template T SwigValueInit() { + return T(); +} +#endif + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if defined(__GNUC__) +# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + +/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ +#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) +# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +/* Intel's compiler complains if a variable which was never initialised is + * cast to void, which is a common idiom which we use to indicate that we + * are aware a variable isn't used. So we just silence that warning. + * See: https://github.com/swig/swig/issues/192 for more discussion. + */ +#ifdef __INTEL_COMPILER +# pragma warning disable 592 +#endif + + +/* Fix for jlong on some versions of gcc on Windows */ +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) + typedef long long __int64; +#endif + +/* Fix for jlong on 64-bit x86 Solaris */ +#if defined(__x86_64) +# ifdef _LP64 +# undef _LP64 +# endif +#endif + +#include +#include +#include + + +/* Support for throwing Java exceptions */ +typedef enum { + SWIG_JavaOutOfMemoryError = 1, + SWIG_JavaIOException, + SWIG_JavaRuntimeException, + SWIG_JavaIndexOutOfBoundsException, + SWIG_JavaArithmeticException, + SWIG_JavaIllegalArgumentException, + SWIG_JavaNullPointerException, + SWIG_JavaDirectorPureVirtual, + SWIG_JavaUnknownError +} SWIG_JavaExceptionCodes; + +typedef struct { + SWIG_JavaExceptionCodes code; + const char *java_exception; +} SWIG_JavaExceptions_t; + + +static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionCodes code, const char *msg) { + jclass excep; + static const SWIG_JavaExceptions_t java_exceptions[] = { + { SWIG_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" }, + { SWIG_JavaIOException, "java/io/IOException" }, + { SWIG_JavaRuntimeException, "java/lang/RuntimeException" }, + { SWIG_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" }, + { SWIG_JavaArithmeticException, "java/lang/ArithmeticException" }, + { SWIG_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" }, + { SWIG_JavaNullPointerException, "java/lang/NullPointerException" }, + { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" }, + { SWIG_JavaUnknownError, "java/lang/UnknownError" }, + { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" } + }; + const SWIG_JavaExceptions_t *except_ptr = java_exceptions; + + while (except_ptr->code != code && except_ptr->code) + except_ptr++; + + jenv->ExceptionClear(); + excep = jenv->FindClass(except_ptr->java_exception); + if (excep) + jenv->ThrowNew(excep, msg); +} + + +/* Contract support */ + +#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, msg); return nullreturn; } else + + +#include + + +#include +#include + + +#include +#include +#include +#include +struct Param { +const mcl::EcParam *ecParam; +cybozu::RandomGenerator rg; +cybozu::crypto::Hash::Name hashName; +static inline Param& getParam() +{ + static Param p; + return p; +} +}; + +#include "elgamal_impl.hpp" + + +static bool *new_p_bool() { + return new bool(); +} + +static bool *copy_p_bool(bool value) { + return new bool(value); +} + +static void delete_p_bool(bool *obj) { + if (obj) delete obj; +} + +static void p_bool_assign(bool *obj, bool value) { + *obj = value; +} + +static bool p_bool_value(bool *obj) { + return *obj; +} + + +#ifdef __cplusplus +extern "C" { +#endif + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_new_1p_1bool(JNIEnv *jenv, jclass jcls) { + jlong jresult = 0 ; + bool *result = 0 ; + + (void)jenv; + (void)jcls; + result = (bool *)new_p_bool(); + *(bool **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_copy_1p_1bool(JNIEnv *jenv, jclass jcls, jboolean jarg1) { + jlong jresult = 0 ; + bool arg1 ; + bool *result = 0 ; + + (void)jenv; + (void)jcls; + arg1 = jarg1 ? true : false; + result = (bool *)copy_p_bool(arg1); + *(bool **)&jresult = result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_delete_1p_1bool(JNIEnv *jenv, jclass jcls, jlong jarg1) { + bool *arg1 = (bool *) 0 ; + + (void)jenv; + (void)jcls; + arg1 = *(bool **)&jarg1; + delete_p_bool(arg1); +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_p_1bool_1assign(JNIEnv *jenv, jclass jcls, jlong jarg1, jboolean jarg2) { + bool *arg1 = (bool *) 0 ; + bool arg2 ; + + (void)jenv; + (void)jcls; + arg1 = *(bool **)&jarg1; + arg2 = jarg2 ? true : false; + p_bool_assign(arg1,arg2); +} + + +SWIGEXPORT jboolean JNICALL Java_com_herumi_mcl_ElgamalJNI_p_1bool_1value(JNIEnv *jenv, jclass jcls, jlong jarg1) { + jboolean jresult = 0 ; + bool *arg1 = (bool *) 0 ; + bool result; + + (void)jenv; + (void)jcls; + arg1 = *(bool **)&jarg1; + result = (bool)p_bool_value(arg1); + jresult = (jboolean)result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_SystemInit(JNIEnv *jenv, jclass jcls, jstring jarg1) { + std::string *arg1 = 0 ; + + (void)jenv; + (void)jcls; + if(!jarg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0); + if (!arg1_pstr) return ; + std::string arg1_str(arg1_pstr); + arg1 = &arg1_str; + jenv->ReleaseStringUTFChars(jarg1, arg1_pstr); + try { + SystemInit((std::string const &)*arg1); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + CipherText *arg1 = (CipherText *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(CipherText **)&jarg1; + try { + result = ((CipherText const *)arg1)->toStr(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + CipherText *arg1 = (CipherText *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(CipherText **)&jarg1; + try { + result = ((CipherText const *)arg1)->toString(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1fromStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + CipherText *arg1 = (CipherText *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(CipherText **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->fromStr((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1add(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + CipherText *arg1 = (CipherText *) 0 ; + CipherText *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(CipherText **)&jarg1; + arg2 = *(CipherText **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText const & reference is null"); + return ; + } + try { + (arg1)->add((CipherText const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) { + CipherText *arg1 = (CipherText *) 0 ; + int arg2 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(CipherText **)&jarg1; + arg2 = (int)jarg2; + try { + (arg1)->mul(arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + CipherText *arg1 = (CipherText *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(CipherText **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->mul((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_new_1CipherText(JNIEnv *jenv, jclass jcls) { + jlong jresult = 0 ; + CipherText *result = 0 ; + + (void)jenv; + (void)jcls; + result = (CipherText *)new CipherText(); + *(CipherText **)&jresult = result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_delete_1CipherText(JNIEnv *jenv, jclass jcls, jlong jarg1) { + CipherText *arg1 = (CipherText *) 0 ; + + (void)jenv; + (void)jcls; + arg1 = *(CipherText **)&jarg1; + delete arg1; +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + PublicKey *arg1 = (PublicKey *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PublicKey **)&jarg1; + try { + result = ((PublicKey const *)arg1)->toStr(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + PublicKey *arg1 = (PublicKey *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PublicKey **)&jarg1; + try { + result = ((PublicKey const *)arg1)->toString(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1fromStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + PublicKey *arg1 = (PublicKey *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PublicKey **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->fromStr((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1save(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + PublicKey *arg1 = (PublicKey *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PublicKey **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + ((PublicKey const *)arg1)->save((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1load(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + PublicKey *arg1 = (PublicKey *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PublicKey **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->load((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jint jarg3) { + PublicKey *arg1 = (PublicKey *) 0 ; + CipherText *arg2 = 0 ; + int arg3 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(PublicKey **)&jarg1; + arg2 = *(CipherText **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null"); + return ; + } + arg3 = (int)jarg3; + try { + ((PublicKey const *)arg1)->enc(*arg2,arg3); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jstring jarg3) { + PublicKey *arg1 = (PublicKey *) 0 ; + CipherText *arg2 = 0 ; + std::string *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(PublicKey **)&jarg1; + arg2 = *(CipherText **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null"); + return ; + } + if(!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0); + if (!arg3_pstr) return ; + std::string arg3_str(arg3_pstr); + arg3 = &arg3_str; + jenv->ReleaseStringUTFChars(jarg3, arg3_pstr); + try { + ((PublicKey const *)arg1)->enc(*arg2,(std::string const &)*arg3); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1rerandomize(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + PublicKey *arg1 = (PublicKey *) 0 ; + CipherText *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(PublicKey **)&jarg1; + arg2 = *(CipherText **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null"); + return ; + } + try { + ((PublicKey const *)arg1)->rerandomize(*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jint jarg3) { + PublicKey *arg1 = (PublicKey *) 0 ; + CipherText *arg2 = 0 ; + int arg3 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(PublicKey **)&jarg1; + arg2 = *(CipherText **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null"); + return ; + } + arg3 = (int)jarg3; + try { + ((PublicKey const *)arg1)->add(*arg2,arg3); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jstring jarg3) { + PublicKey *arg1 = (PublicKey *) 0 ; + CipherText *arg2 = 0 ; + std::string *arg3 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(PublicKey **)&jarg1; + arg2 = *(CipherText **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText & reference is null"); + return ; + } + if(!jarg3) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg3_pstr = (const char *)jenv->GetStringUTFChars(jarg3, 0); + if (!arg3_pstr) return ; + std::string arg3_str(arg3_pstr); + arg3 = &arg3_str; + jenv->ReleaseStringUTFChars(jarg3, arg3_pstr); + try { + ((PublicKey const *)arg1)->add(*arg2,(std::string const &)*arg3); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_new_1PublicKey(JNIEnv *jenv, jclass jcls) { + jlong jresult = 0 ; + PublicKey *result = 0 ; + + (void)jenv; + (void)jcls; + result = (PublicKey *)new PublicKey(); + *(PublicKey **)&jresult = result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_delete_1PublicKey(JNIEnv *jenv, jclass jcls, jlong jarg1) { + PublicKey *arg1 = (PublicKey *) 0 ; + + (void)jenv; + (void)jcls; + arg1 = *(PublicKey **)&jarg1; + delete arg1; +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + PrivateKey *arg1 = (PrivateKey *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PrivateKey **)&jarg1; + try { + result = ((PrivateKey const *)arg1)->toStr(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toString(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + PrivateKey *arg1 = (PrivateKey *) 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PrivateKey **)&jarg1; + try { + result = ((PrivateKey const *)arg1)->toString(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1fromStr(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + PrivateKey *arg1 = (PrivateKey *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PrivateKey **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->fromStr((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1save(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + PrivateKey *arg1 = (PrivateKey *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PrivateKey **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + ((PrivateKey const *)arg1)->save((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1load(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + PrivateKey *arg1 = (PrivateKey *) 0 ; + std::string *arg2 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PrivateKey **)&jarg1; + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + try { + (arg1)->load((std::string const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1init(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + PrivateKey *arg1 = (PrivateKey *) 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PrivateKey **)&jarg1; + try { + (arg1)->init(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1getPublicKey(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jlong jresult = 0 ; + PrivateKey *arg1 = (PrivateKey *) 0 ; + PublicKey result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PrivateKey **)&jarg1; + try { + result = ((PrivateKey const *)arg1)->getPublicKey(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + *(PublicKey **)&jresult = new PublicKey((const PublicKey &)result); + return jresult; +} + + +SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_10(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jlong jarg3) { + jint jresult = 0 ; + PrivateKey *arg1 = (PrivateKey *) 0 ; + CipherText *arg2 = 0 ; + bool *arg3 = (bool *) 0 ; + int result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(PrivateKey **)&jarg1; + arg2 = *(CipherText **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText const & reference is null"); + return 0; + } + arg3 = *(bool **)&jarg3; + try { + result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2,arg3); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = (jint)result; + return jresult; +} + + +SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_11(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_) { + jint jresult = 0 ; + PrivateKey *arg1 = (PrivateKey *) 0 ; + CipherText *arg2 = 0 ; + int result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(PrivateKey **)&jarg1; + arg2 = *(CipherText **)&jarg2; + if (!arg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "CipherText const & reference is null"); + return 0; + } + try { + result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return 0; + } + + jresult = (jint)result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1setCache(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3) { + PrivateKey *arg1 = (PrivateKey *) 0 ; + int arg2 ; + int arg3 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PrivateKey **)&jarg1; + arg2 = (int)jarg2; + arg3 = (int)jarg3; + try { + (arg1)->setCache(arg2,arg3); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1clearCache(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + PrivateKey *arg1 = (PrivateKey *) 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(PrivateKey **)&jarg1; + try { + (arg1)->clearCache(); + } + catch(std::exception &_e) { + SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); + return ; + } + +} + + +SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_new_1PrivateKey(JNIEnv *jenv, jclass jcls) { + jlong jresult = 0 ; + PrivateKey *result = 0 ; + + (void)jenv; + (void)jcls; + result = (PrivateKey *)new PrivateKey(); + *(PrivateKey **)&jresult = result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_delete_1PrivateKey(JNIEnv *jenv, jclass jcls, jlong jarg1) { + PrivateKey *arg1 = (PrivateKey *) 0 ; + + (void)jenv; + (void)jcls; + arg1 = *(PrivateKey **)&jarg1; + delete arg1; +} + + +#ifdef __cplusplus +} +#endif + diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/java.md b/vendor/github.com/dexon-foundation/mcl/ffi/java/java.md new file mode 100644 index 000000000..3fe861351 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/java.md @@ -0,0 +1,95 @@ +# JNI for mcl (experimental) +This library provides functionality to compute the optimal ate pairing +over Barreto-Naehrig (BN) curves. + +# Initialization +Load the library `mcl_bn256`. +``` +import com.herumi.mcl.*; + +System.loadLibrary("mcl_bn256"); +``` + +# Classes +* `G1` ; The cyclic group instantiated as E(Fp)[r] where where r = p + 1 - t. +* `G2` ; The cyclic group instantiated as the inverse image of E'(Fp^2)[r]. +* `GT` ; The cyclic group in the image of the optimal ate pairing. + * `e : G1 x G2 -> GT` +* `Fr` ; The finite field with characteristic r. + +# Methods and Functions +## Fr +* `Fr::setInt(int x)` ; set by x +* `Fr::setStr(String str)` ; set by str such as "123", "0xfff", etc. +* `Fr::setRand()` ; randomly set +* `Bn256.neg(Fr y, Fr x)` ; `y = -x` +* `Bn256.add(Fr z, Fr x, Fr y)` ; `z = x + y` +* `Bn256.sub(Fr z, Fr x, Fr y)` ; `z = x - y` +* `Bn256.mul(Fr z, Fr x, Fr y)` ; `z = x * y` +* `Bn256.div(Fr z, Fr x, Fr y)` ; `z = x / y` + +## G1 + +* `G1::set(String x, String y)` ; set by (x, y) +* `G1::hashAndMapToG1(String m)` ; take SHA-256 of m and map it to an element of G1 +* `G1::setStr(String str)` ; set by the result of `toString()` method +* `Bn256.neg(G1 y, G1 x)` ; `y = -x` +* `Bn256.dbl(G1 y, G1 x)` ; `y = 2x` +* `Bn256.add(G1 z, G1 x, G1 y)` ; `z = x + y` +* `Bn256.sub(G1 z, G1 x, G1 y)` ; `z = x - y` +* `Bn256.mul(G1 z, G1 x, Fr y)` ; `z = x * y` + +## G2 + +* `G2::set(String xa, String xb, String ya, String yb)` ; set by ((xa, xb), (ya, yb)) +* `G2::setStr(String str)` ; set by the result of `toString()` method +* `Bn256.neg(G2 y, G2 x)` ; `y = -x` +* `Bn256.dbl(G2 y, G2 x)` ; `y = 2x` +* `Bn256.add(G2 z, G2 x, G2 y)` ; `z = x + y` +* `Bn256.sub(G2 z, G2 x, G2 y)` ; `z = x - y` +* `Bn256.mul(G2 z, G2 x, Fr y)` ; `z = x * y` + +## GT + +* `GT::setStr(String str)` ; set by the result of `toString()` method +* `Bn256.mul(GT z, GT x, GT y)` ; `z = x * y` +* `Bn256.pow(GT z, GT x, Fr y)` ; `z = x ^ y` + +## pairing +* `Bn256.pairing(GT e, G1 P, G2 Q)` ; e = e(P, Q) + +# BLS signature sample +``` +String xa = "12723517038133731887338407189719511622662176727675373276651903807414909099441"; +String xb = "4168783608814932154536427934509895782246573715297911553964171371032945126671"; +String ya = "13891744915211034074451795021214165905772212241412891944830863846330766296736"; +String yb = "7937318970632701341203597196594272556916396164729705624521405069090520231616"; + +G2 Q = new G2(xa, xb, ya, yb); // fixed point of G2 + +Fr s = new Fr(); +s.setRand(); // secret key +G2 pub = new G2(); +Bn256.mul(pub, Q, s); // public key = sQ + +String m = "signature test"; +G1 H = new G1(); +H.hashAndMapToG1(m); // H = Hash(m) +G1 sign = new G1(); +Bn256.mul(sign, H, s); // signature of m = s H + +GT e1 = new GT(); +GT e2 = new GT(); +Bn256.pairing(e1, H, pub); // e1 = e(H, s Q) +Bn256.pairing(e2, sign, Q); // e2 = e(s H, Q); +assertBool("verify signature", e1.equals(e2)); +``` + +# Make test +``` +cd java +make test_bn256 +``` + +# Sample code +[Bn256Test.java](https://github.com/herumi/mcl/blob/master/java/Bn256Test.java) diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/make_wrap.bat b/vendor/github.com/dexon-foundation/mcl/ffi/java/make_wrap.bat new file mode 100644 index 000000000..b7008bc02 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/make_wrap.bat @@ -0,0 +1,23 @@ +@echo off +call set-java-path.bat +set JAVA_INCLUDE=%JAVA_DIR%\include +set SWIG=..\..\..\..\p\swig\swig.exe +set PACKAGE_NAME=com.herumi.mcl +set PACKAGE_DIR=%PACKAGE_NAME:.=\% +if /i "%1"=="" ( + set NAME=elgamal +) else ( + set NAME=%1 +) + +echo [[run swig]] +mkdir %PACKAGE_DIR% +set TOP_DIR=../.. +%SWIG% -java -package %PACKAGE_NAME% -outdir %PACKAGE_DIR% -c++ -Wall %NAME%.i +echo [[make dll]] +cl /MT /DNOMINMAX /LD /Ox /DNDEBUG /EHsc %NAME%_wrap.cxx %TOP_DIR%/src/fp.cpp -DMCL_NO_AUTOLINK -I%JAVA_INCLUDE% -I%JAVA_INCLUDE%\win32 -I%TOP_DIR%/include -I%TOP_DIR%/../cybozulib/include -I%TOP_DIR%/../cybozulib_ext/include -I%TOP_DIR%/../xbyak /link /LIBPATH:%TOP_DIR%/../cybozulib_ext/lib /OUT:%TOP_DIR%/bin/mcl_%NAME%.dll + +call run-%NAME%.bat + +echo [[make jar]] +%JAVA_DIR%\bin\jar cvf mcl.jar com diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/run-bn256.bat b/vendor/github.com/dexon-foundation/mcl/ffi/java/run-bn256.bat new file mode 100644 index 000000000..903876ec6 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/run-bn256.bat @@ -0,0 +1,9 @@ +@echo off +echo [[compile Bn256Test.java]] +%JAVA_DIR%\bin\javac Bn256Test.java + +echo [[run Bn256Test]] +set TOP_DIR=..\.. +pushd %TOP_DIR%\bin +%JAVA_DIR%\bin\java -classpath ../ffi/java Bn256Test %1 %2 %3 %4 %5 %6 +popd diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/run-elgamal.bat b/vendor/github.com/dexon-foundation/mcl/ffi/java/run-elgamal.bat new file mode 100644 index 000000000..8b889a64c --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/run-elgamal.bat @@ -0,0 +1,9 @@ +@echo off +echo [[compile ElgamalTest.java]] +%JAVA_DIR%\bin\javac ElgamalTest.java + +echo [[run ElgamalTest]] +set TOP_DIR=..\.. +pushd %TOP_DIR%\bin +%JAVA_DIR%\bin\java -classpath ../ffi/java ElgamalTest %1 %2 %3 %4 %5 %6 +popd diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/java/set-java-path.bat b/vendor/github.com/dexon-foundation/mcl/ffi/java/set-java-path.bat new file mode 100644 index 000000000..c66f81830 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/java/set-java-path.bat @@ -0,0 +1,8 @@ +@echo off +if "%JAVA_HOME%"=="" ( + set JAVA_DIR=c:/p/Java/jdk +) else ( + set JAVA_DIR=%JAVA_HOME% +) +echo JAVA_DIR=%JAVA_DIR% +rem set PATH=%PATH%;%JAVA_DIR%\bin diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/js/export-functions.py b/vendor/github.com/dexon-foundation/mcl/ffi/js/export-functions.py new file mode 100644 index 000000000..2a929564b --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/js/export-functions.py @@ -0,0 +1,73 @@ +import sys, re, argparse + +#RE_PROTOTYPE = re.compile(r'MCLBN_DLL_API\s\w\s\w\([^)]*\);') +RE_PROTOTYPE = re.compile(r'\w*\s(\w*)\s(\w*)\(([^)]*)\);') +def export_functions(args, fileNames, reToAddUnderscore): + modName = args.js + json = args.json + if not reToAddUnderscore: + reToAddUnderscore = r'(mclBn_init|setStr|getStr|[sS]erialize|setLittleEndian|setHashOf|hashAndMapTo|DecStr|HexStr|HashTo|blsSign|blsVerify|GetCurveOrder|GetFieldOrder|KeyShare|KeyRecover|blsSignatureRecover|blsInit)' + reSpecialFunctionName = re.compile(reToAddUnderscore) + if json: + print '[' + elif modName: + print 'function define_exported_' + modName + '(mod) {' + comma = '' + for fileName in fileNames: + with open(fileName, 'rb') as f: + for line in f.readlines(): + p = RE_PROTOTYPE.search(line) + if p: + ret = p.group(1) + name = p.group(2) + arg = p.group(3) + if json or modName: + retType = 'null' if ret == 'void' else 'number' + if arg == '' or arg == 'void': + paramNum = 0 + else: + paramNum = len(arg.split(',')) + if reSpecialFunctionName.search(name): + exportName = '_' + name # to wrap function + else: + exportName = name + if json: + print comma + '{' + if comma == '': + comma = ',' + print ' "name":"{0}",'.format(name) + print ' "exportName":"{0}",'.format(exportName) + print ' "ret":"{0}",'.format(retType) + print ' "args":[', + if paramNum > 0: + print '"number"' + (', "number"' * (paramNum - 1)), + print ']' + print '}' + else: + paramType = '[' + ("'number', " * paramNum) + ']' + print "{0} = mod.cwrap('{1}', '{2}', {3})".format(exportName, name, retType, paramType) + else: + print comma + "'_" + name + "'", + if comma == '': + comma = ',' + if json: + print ']' + elif modName: + print '}' + +def main(): + p = argparse.ArgumentParser('export_functions') + p.add_argument('header', type=str, nargs='+', help='headers') + p.add_argument('-js', type=str, nargs='?', help='module name') + p.add_argument('-re', type=str, nargs='?', help='regular expression file to add underscore to function name') + p.add_argument('-json', action='store_true', help='output json') + args = p.parse_args() + + reToAddUnderscore = '' + if args.re: + reToAddUnderscore = open(args.re).read().strip() + export_functions(args, args.header, reToAddUnderscore) + +if __name__ == '__main__': + main() + diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/js/pre-mcl.js b/vendor/github.com/dexon-foundation/mcl/ffi/js/pre-mcl.js new file mode 100644 index 000000000..ebc93e581 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/js/pre-mcl.js @@ -0,0 +1,5 @@ +if (typeof __dirname === 'string') { + var Module = {} + Module.wasmBinaryFile = __dirname + '/mcl_c.wasm' +} + diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/python/pairing.py b/vendor/github.com/dexon-foundation/mcl/ffi/python/pairing.py new file mode 100644 index 000000000..88b729176 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/python/pairing.py @@ -0,0 +1,80 @@ +from ctypes import * +from ctypes.wintypes import LPWSTR, LPCSTR, LPVOID + +g_lib = None + +def BN256_init(): + global g_lib + g_lib = cdll.LoadLibrary("../../bin/bn256.dll") + ret = g_lib.BN256_init() + if ret: + print "ERR BN256_init" + +class Fr(Structure): + _fields_ = [("v", c_ulonglong * 4)] + def setInt(self, v): + g_lib.BN256_Fr_setInt(self.v, v) + def setStr(self, s): + ret = g_lib.BN256_Fr_setStr(self.v, c_char_p(s)) + if ret: + print("ERR Fr:setStr") + def __str__(self): + svLen = 1024 + sv = create_string_buffer('\0' * svLen) + ret = g_lib.BN256_Fr_getStr(sv, svLen, self.v) + if ret: + print("ERR Fr:getStr") + return sv.value + def isZero(self, rhs): + return g_lib.BN256_Fr_isZero(self.v) != 0 + def isOne(self, rhs): + return g_lib.BN256_Fr_isOne(self.v) != 0 + def __eq__(self, rhs): + return g_lib.BN256_Fr_isEqual(self.v, rhs.v) != 0 + def __ne__(self, rhs): + return not(P == Q) + def __add__(self, rhs): + ret = Fr() + g_lib.BN256_Fr_add(ret.v, self.v, rhs.v) + return ret + def __sub__(self, rhs): + ret = Fr() + g_lib.BN256_Fr_sub(ret.v, self.v, rhs.v) + return ret + def __mul__(self, rhs): + ret = Fr() + g_lib.BN256_Fr_mul(ret.v, self.v, rhs.v) + return ret + def __div__(self, rhs): + ret = Fr() + g_lib.BN256_Fr_div(ret.v, self.v, rhs.v) + return ret + def __neg__(self): + ret = Fr() + g_lib.BN256_Fr_neg(ret.v, self.v) + return ret + +def Fr_add(z, x, y): + g_lib.BN256_Fr_add(z.v, x.v, y.v) + +def Fr_sub(z, x, y): + g_lib.BN256_Fr_sub(z.v, x.v, y.v) + +def Fr_mul(z, x, y): + g_lib.BN256_Fr_mul(z.v, x.v, y.v) + +def Fr_div(z, x, y): + g_lib.BN256_Fr_div(z.v, x.v, y.v) + +BN256_init() + +P = Fr() +Q = Fr() +print P == Q +print P != Q +P.setInt(5) +Q.setStr("34982034824") +print Q +R = Fr() +Fr_add(R, P, Q) +print R diff --git a/vendor/github.com/dexon-foundation/mcl/ffi/python/she.py b/vendor/github.com/dexon-foundation/mcl/ffi/python/she.py new file mode 100644 index 000000000..ab8975274 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/ffi/python/she.py @@ -0,0 +1,298 @@ +import os +import platform +from ctypes import * + +MCL_BN254 = 0 +MCLBN_FR_UNIT_SIZE = 4 +MCLBN_FP_UNIT_SIZE = 4 + +FR_SIZE = MCLBN_FR_UNIT_SIZE +G1_SIZE = MCLBN_FP_UNIT_SIZE * 3 +G2_SIZE = MCLBN_FP_UNIT_SIZE * 6 +GT_SIZE = MCLBN_FP_UNIT_SIZE * 12 + +SEC_SIZE = FR_SIZE * 2 +PUB_SIZE = G1_SIZE + G2_SIZE +G1_CIPHER_SIZE = G1_SIZE * 2 +G2_CIPHER_SIZE = G2_SIZE * 2 +GT_CIPHER_SIZE = GT_SIZE * 4 + +MCLBN_COMPILED_TIME_VAR = (MCLBN_FR_UNIT_SIZE * 10) + MCLBN_FP_UNIT_SIZE + +Buffer = c_ubyte * 1536 +lib = None + +def init(curveType=MCL_BN254): + global lib + name = platform.system() + if name == 'Linux': + libName = 'libmclshe256.so' + elif name == 'Darwin': + libName = 'libmclshe256.dylib' + elif name == 'Windows': + libName = 'mclshe256.dll' + else: + raise RuntimeError("not support yet", name) + lib = cdll.LoadLibrary(libName) + ret = lib.sheInit(MCL_BN254, MCLBN_COMPILED_TIME_VAR) + if ret != 0: + raise RuntimeError("sheInit", ret) + # custom setup for a function which returns pointer + lib.shePrecomputedPublicKeyCreate.restype = c_void_p + +def setRangeForDLP(hashSize): + ret = lib.sheSetRangeForDLP(hashSize) + if ret != 0: + raise RuntimeError("setRangeForDLP", ret) + +def setTryNum(tryNum): + ret = lib.sheSetTryNum(tryNum) + if ret != 0: + raise RuntimeError("setTryNum", ret) + +def hexStr(v): + s = "" + for x in v: + s += format(x, '02x') + return s + +class CipherTextG1(Structure): + _fields_ = [("v", c_ulonglong * G1_CIPHER_SIZE)] + def serialize(self): + buf = Buffer() + ret = lib.sheCipherTextG1Serialize(byref(buf), len(buf), byref(self.v)) + if ret == 0: + raise RuntimeError("serialize") + return buf[0:ret] + def serializeToHexStr(self): + return hexStr(self.serialize()) + +class CipherTextG2(Structure): + _fields_ = [("v", c_ulonglong * G2_CIPHER_SIZE)] + def serialize(self): + buf = Buffer() + ret = lib.sheCipherTextG2Serialize(byref(buf), len(buf), byref(self.v)) + if ret == 0: + raise RuntimeError("serialize") + return buf[0:ret] + def serializeToHexStr(self): + return hexStr(self.serialize()) + +class CipherTextGT(Structure): + _fields_ = [("v", c_ulonglong * GT_CIPHER_SIZE)] + def serialize(self): + buf = Buffer() + ret = lib.sheCipherTextGTSerialize(byref(buf), len(buf), byref(self.v)) + if ret == 0: + raise RuntimeError("serialize") + return buf[0:ret] + def serializeToHexStr(self): + return hexStr(self.serialize()) + +class PrecomputedPublicKey(Structure): + def __init__(self): + self.p = 0 + def create(self): + if not self.p: + self.p = c_void_p(lib.shePrecomputedPublicKeyCreate()) + if self.p == 0: + raise RuntimeError("PrecomputedPublicKey::create") + def destroy(self): + lib.shePrecomputedPublicKeyDestroy(self.p) + def encG1(self, m): + c = CipherTextG1() + ret = lib.shePrecomputedPublicKeyEncG1(byref(c.v), self.p, m) + if ret != 0: + raise RuntimeError("encG1", m) + return c + def encG2(self, m): + c = CipherTextG2() + ret = lib.shePrecomputedPublicKeyEncG2(byref(c.v), self.p, m) + if ret != 0: + raise RuntimeError("encG2", m) + return c + def encGT(self, m): + c = CipherTextGT() + ret = lib.shePrecomputedPublicKeyEncGT(byref(c.v), self.p, m) + if ret != 0: + raise RuntimeError("encGT", m) + return c + +class PublicKey(Structure): + _fields_ = [("v", c_ulonglong * PUB_SIZE)] + def serialize(self): + buf = Buffer() + ret = lib.shePublicKeySerialize(byref(buf), len(buf), byref(self.v)) + if ret == 0: + raise RuntimeError("serialize") + return buf[0:ret] + def serializeToHexStr(self): + return hexStr(self.serialize()) + def encG1(self, m): + c = CipherTextG1() + ret = lib.sheEncG1(byref(c.v), byref(self.v), m) + if ret != 0: + raise RuntimeError("encG1", m) + return c + def encG2(self, m): + c = CipherTextG2() + ret = lib.sheEncG2(byref(c.v), byref(self.v), m) + if ret != 0: + raise RuntimeError("encG2", m) + return c + def encGT(self, m): + c = CipherTextGT() + ret = lib.sheEncGT(byref(c.v), byref(self.v), m) + if ret != 0: + raise RuntimeError("encGT", m) + return c + def createPrecomputedPublicKey(self): + ppub = PrecomputedPublicKey() + ppub.create() + ret = lib.shePrecomputedPublicKeyInit(ppub.p, byref(self.v)) + if ret != 0: + raise RuntimeError("createPrecomputedPublicKey") + return ppub + +class SecretKey(Structure): + _fields_ = [("v", c_ulonglong * SEC_SIZE)] + def setByCSPRNG(self): + ret = lib.sheSecretKeySetByCSPRNG(byref(self.v)) + if ret != 0: + raise RuntimeError("setByCSPRNG", ret) + def serialize(self): + buf = Buffer() + ret = lib.sheSecretKeySerialize(byref(buf), len(buf), byref(self.v)) + if ret == 0: + raise RuntimeError("serialize") + return buf[0:ret] + def serializeToHexStr(self): + return hexStr(self.serialize()) + def getPulicKey(self): + pub = PublicKey() + lib.sheGetPublicKey(byref(pub.v), byref(self.v)) + return pub + def dec(self, c): + m = c_longlong() + if isinstance(c, CipherTextG1): + ret = lib.sheDecG1(byref(m), byref(self.v), byref(c.v)) + elif isinstance(c, CipherTextG2): + ret = lib.sheDecG2(byref(m), byref(self.v), byref(c.v)) + elif isinstance(c, CipherTextGT): + ret = lib.sheDecGT(byref(m), byref(self.v), byref(c.v)) + if ret != 0: + raise RuntimeError("dec") + return m.value + +def neg(c): + ret = -1 + if isinstance(c, CipherTextG1): + out = CipherTextG1() + ret = lib.sheNegG1(byref(out.v), byref(c.v)) + elif isinstance(c, CipherTextG2): + out = CipherTextG2() + ret = lib.sheNegG2(byref(out.v), byref(c.v)) + elif isinstance(c, CipherTextGT): + out = CipherTextGT() + ret = lib.sheNegGT(byref(out.v), byref(c.v)) + if ret != 0: + raise RuntimeError("neg") + return out + +def add(cx, cy): + ret = -1 + if isinstance(cx, CipherTextG1) and isinstance(cy, CipherTextG1): + out = CipherTextG1() + ret = lib.sheAddG1(byref(out.v), byref(cx.v), byref(cy.v)) + elif isinstance(cx, CipherTextG2) and isinstance(cy, CipherTextG2): + out = CipherTextG2() + ret = lib.sheAddG2(byref(out.v), byref(cx.v), byref(cy.v)) + elif isinstance(cx, CipherTextGT) and isinstance(cy, CipherTextGT): + out = CipherTextGT() + ret = lib.sheAddGT(byref(out.v), byref(cx.v), byref(cy.v)) + if ret != 0: + raise RuntimeError("add") + return out + +def sub(cx, cy): + ret = -1 + if isinstance(cx, CipherTextG1) and isinstance(cy, CipherTextG1): + out = CipherTextG1() + ret = lib.sheSubG1(byref(out.v), byref(cx.v), byref(cy.v)) + elif isinstance(cx, CipherTextG2) and isinstance(cy, CipherTextG2): + out = CipherTextG2() + ret = lib.sheSubG2(byref(out.v), byref(cx.v), byref(cy.v)) + elif isinstance(cx, CipherTextGT) and isinstance(cy, CipherTextGT): + out = CipherTextGT() + ret = lib.sheSubGT(byref(out.v), byref(cx.v), byref(cy.v)) + if ret != 0: + raise RuntimeError("sub") + return out + +def mul(cx, cy): + ret = -1 + if isinstance(cx, CipherTextG1) and isinstance(cy, CipherTextG2): + out = CipherTextGT() + ret = lib.sheMul(byref(out.v), byref(cx.v), byref(cy.v)) + elif isinstance(cx, CipherTextG1) and isinstance(cy, int): + out = CipherTextG1() + ret = lib.sheMulG1(byref(out.v), byref(cx.v), cy) + elif isinstance(cx, CipherTextG2) and isinstance(cy, int): + out = CipherTextG2() + ret = lib.sheMulG2(byref(out.v), byref(cx.v), cy) + elif isinstance(cx, CipherTextGT) and isinstance(cy, int): + out = CipherTextGT() + ret = lib.sheMulGT(byref(out.v), byref(cx.v), cy) + if ret != 0: + raise RuntimeError("mul") + return out + +if __name__ == '__main__': + init() + sec = SecretKey() + sec.setByCSPRNG() + print("sec=", sec.serializeToHexStr()) + pub = sec.getPulicKey() + print("pub=", pub.serializeToHexStr()) + + m11 = 1 + m12 = 5 + m21 = 3 + m22 = -4 + c11 = pub.encG1(m11) + c12 = pub.encG1(m12) + # dec(enc) for G1 + if sec.dec(c11) != m11: print("err1") + + # add/sub for G1 + if sec.dec(add(c11, c12)) != m11 + m12: print("err2") + if sec.dec(sub(c11, c12)) != m11 - m12: print("err3") + + # add/sub for G2 + c21 = pub.encG2(m21) + c22 = pub.encG2(m22) + if sec.dec(c21) != m21: print("err4") + if sec.dec(add(c21, c22)) != m21 + m22: print("err5") + if sec.dec(sub(c21, c22)) != m21 - m22: print("err6") + + mt = -56 + ct = pub.encGT(mt) + if sec.dec(ct) != mt: print("err7") + + # mul G1 and G2 + if sec.dec(mul(c11, c21)) != m11 * m21: print("err8") + + # use precomputedPublicKey for performance + ppub = pub.createPrecomputedPublicKey() + c1 = ppub.encG1(m11) + if sec.dec(c1) != m11: print("err9") + + import sys + if sys.version_info.major >= 3: + import timeit + N = 100000 + print(str(timeit.timeit("pub.encG1(12)", number=N, globals=globals()) / float(N) * 1e3) + "msec") + print(str(timeit.timeit("ppub.encG1(12)", number=N, globals=globals()) / float(N) * 1e3) + "msec") + + ppub.destroy() # necessary to avoid memory leak + diff --git a/vendor/github.com/dexon-foundation/mcl/include/cybozu/random_generator.hpp b/vendor/github.com/dexon-foundation/mcl/include/cybozu/random_generator.hpp index 23096989d..ff4a78da5 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/cybozu/random_generator.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/cybozu/random_generator.hpp @@ -54,11 +54,9 @@ public: } throw cybozu::Exception("randomgenerator"); } - void read_inner(void *buf, size_t byteSize) + bool read_inner(void *buf, size_t byteSize) { - if (CryptGenRandom(prov_, static_cast(byteSize), static_cast(buf)) == 0) { - throw cybozu::Exception("randomgenerator:read") << byteSize; - } + return CryptGenRandom(prov_, static_cast(byteSize), static_cast(buf)) != 0; } ~RandomGenerator() { @@ -71,12 +69,15 @@ public: @note bufNum is not byte size */ template - void read(T *buf, size_t bufNum) + void read(bool *pb, T *buf, size_t bufNum) { cybozu::AutoLockCs al(cs_); const size_t byteSize = sizeof(T) * bufNum; if (byteSize > bufSize) { - read_inner(buf, byteSize); + if (!read_inner(buf, byteSize)) { + *pb = false; + return; + } } else { if (pos_ + byteSize > bufSize) { read_inner(buf_, bufSize); @@ -85,6 +86,14 @@ public: memcpy(buf, buf_ + pos_, byteSize); pos_ += byteSize; } + *pb = true; + } + template + void read(T *buf, size_t bufNum) + { + bool b; + read(&b, buf, bufNum); + if (!b) throw cybozu::Exception("RandomGenerator:read") << bufNum; } private: HCRYPTPROV prov_; @@ -107,12 +116,17 @@ private: @note bufNum is not byte size */ template - void read(T *buf, size_t bufNum) + void read(bool *pb, T *buf, size_t bufNum) { const size_t byteSize = sizeof(T) * bufNum; - if (::fread(buf, 1, (int)byteSize, fp_) != byteSize) { - throw cybozu::Exception("randomgenerator:read") << byteSize; - } + *pb = ::fread(buf, 1, (int)byteSize, fp_) == byteSize; + } + template + void read(T *buf, size_t bufNum) + { + bool b; + read(&b, buf, bufNum); + if (!b) throw cybozu::Exception("RandomGenerator:read") << bufNum; } #endif private: diff --git a/vendor/github.com/dexon-foundation/mcl/include/cybozu/sha2.hpp b/vendor/github.com/dexon-foundation/mcl/include/cybozu/sha2.hpp index 97193849b..1830936f0 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/cybozu/sha2.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/cybozu/sha2.hpp @@ -6,36 +6,124 @@ @license modified new BSD license http://opensource.org/licenses/BSD-3-Clause */ -#include +#if !defined(CYBOZU_DONT_USE_OPENSSL) && !defined(MCL_DONT_USE_OPENSSL) + #define CYBOZU_USE_OPENSSL_SHA +#endif + #ifndef CYBOZU_DONT_USE_STRING -#include #include #endif -#include -#include -namespace cybozu { +#ifdef CYBOZU_USE_OPENSSL_SHA +#ifdef __APPLE__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif +#include +#ifdef _MSC_VER + #include +#endif -namespace sha2_local { +#ifdef __APPLE__ + #pragma GCC diagnostic pop +#endif -template -T min_(T x, T y) { return x < y ? x : y;; } +namespace cybozu { +class Sha256 { + SHA256_CTX ctx_; +public: + Sha256() + { + clear(); + } + void clear() + { + SHA256_Init(&ctx_); + } + void update(const void *buf, size_t bufSize) + { + SHA256_Update(&ctx_, buf, bufSize); + } + size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize) + { + if (mdSize < SHA256_DIGEST_LENGTH) return 0; + update(buf, bufSize); + SHA256_Final(reinterpret_cast(md), &ctx_); + return SHA256_DIGEST_LENGTH; + } #ifndef CYBOZU_DONT_USE_STRING -inline void uint32toHexStr(char *buf, const uint32_t *x, size_t n) -{ - for (size_t i = 0; i < n; i++) { - cybozu::itohex(buf + i * 8, 8, x[i], false); + void update(const std::string& buf) + { + update(buf.c_str(), buf.size()); } -} + std::string digest(const std::string& buf) + { + return digest(buf.c_str(), buf.size()); + } + std::string digest(const void *buf, size_t bufSize) + { + std::string md(SHA256_DIGEST_LENGTH, 0); + digest(&md[0], md.size(), buf, bufSize); + return md; + } +#endif +}; -inline void uint64toHexStr(char *buf, const uint64_t *x, size_t n) -{ - for (size_t i = 0; i < n; i++) { - cybozu::itohex(buf + i * 16, 16, x[i], false); +class Sha512 { + SHA512_CTX ctx_; +public: + Sha512() + { + clear(); + } + void clear() + { + SHA512_Init(&ctx_); + } + void update(const void *buf, size_t bufSize) + { + SHA512_Update(&ctx_, buf, bufSize); + } + size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize) + { + if (mdSize < SHA512_DIGEST_LENGTH) return 0; + update(buf, bufSize); + SHA512_Final(reinterpret_cast(md), &ctx_); + return SHA512_DIGEST_LENGTH; + } +#ifndef CYBOZU_DONT_USE_STRING + void update(const std::string& buf) + { + update(buf.c_str(), buf.size()); + } + std::string digest(const std::string& buf) + { + return digest(buf.c_str(), buf.size()); + } + std::string digest(const void *buf, size_t bufSize) + { + std::string md(SHA512_DIGEST_LENGTH, 0); + digest(&md[0], md.size(), buf, bufSize); + return md; } -} #endif +}; + +} // cybozu + +#else + +#include +#include +#include + +namespace cybozu { + +namespace sha2_local { + +template +T min_(T x, T y) { return x < y ? x : y;; } inline uint32_t rot32(uint32_t x, int s) { @@ -55,12 +143,64 @@ inline uint64_t rot64(uint64_t x, int s) #endif } +template +struct Common { + void term(const char *buf, size_t bufSize) + { + assert(bufSize < T::blockSize_); + T& self = static_cast(*this); + const uint64_t totalSize = self.totalSize_ + bufSize; + + uint8_t last[T::blockSize_]; + memcpy(last, buf, bufSize); + last[bufSize] = uint8_t(0x80); /* top bit = 1 */ + memset(&last[bufSize + 1], 0, T::blockSize_ - bufSize - 1); + if (bufSize >= T::blockSize_ - T::msgLenByte_) { + self.round(reinterpret_cast(last)); + memset(last, 0, sizeof(last)); // clear stack + } + cybozu::Set64bitAsBE(&last[T::blockSize_ - 8], totalSize * 8); + self.round(reinterpret_cast(last)); + } + void inner_update(const char *buf, size_t bufSize) + { + T& self = static_cast(*this); + if (bufSize == 0) return; + if (self.roundBufSize_ > 0) { + size_t size = sha2_local::min_(T::blockSize_ - self.roundBufSize_, bufSize); + memcpy(self.roundBuf_ + self.roundBufSize_, buf, size); + self.roundBufSize_ += size; + buf += size; + bufSize -= size; + } + if (self.roundBufSize_ == T::blockSize_) { + self.round(self.roundBuf_); + self.roundBufSize_ = 0; + } + while (bufSize >= T::blockSize_) { + assert(self.roundBufSize_ == 0); + self.round(buf); + buf += T::blockSize_; + bufSize -= T::blockSize_; + } + if (bufSize > 0) { + assert(bufSize < T::blockSize_); + assert(self.roundBufSize_ == 0); + memcpy(self.roundBuf_, buf, bufSize); + self.roundBufSize_ = bufSize; + } + assert(self.roundBufSize_ < T::blockSize_); + } +}; + } // cybozu::sha2_local -class Sha256 { +class Sha256 : public sha2_local::Common { + friend struct sha2_local::Common; private: static const size_t blockSize_ = 64; static const size_t hSize_ = 8; + static const size_t msgLenByte_ = 8; uint64_t totalSize_; size_t roundBufSize_; char roundBuf_[blockSize_]; @@ -117,38 +257,13 @@ private: h_[5] += f; h_[6] += g; h_[7] += h; - totalSize_ += 64; - } - /* - final phase - */ - void term(const char *buf, size_t bufSize) - { - assert(bufSize < blockSize_); - const uint64_t totalSize = totalSize_ + bufSize; - - uint8_t last[blockSize_]; - memcpy(last, buf, bufSize); - memset(&last[bufSize], 0, blockSize_ - bufSize); - last[bufSize] = uint8_t(0x80); /* top bit = 1 */ - if (bufSize >= blockSize_ - 8) { - round(reinterpret_cast(last)); - memset(last, 0, sizeof(last)); // clear stack - } - cybozu::Set32bitAsBE(&last[56], uint32_t(totalSize >> 29)); - cybozu::Set32bitAsBE(&last[60], uint32_t(totalSize * 8)); - round(reinterpret_cast(last)); + totalSize_ += blockSize_; } public: Sha256() { clear(); } - Sha256(const void *buf, size_t bufSize) - { - clear(); - digest(buf, bufSize); - } void clear() { static const uint32_t kTbl[] = { @@ -173,43 +288,16 @@ public: h_[6] = 0x1f83d9ab; h_[7] = 0x5be0cd19; } - void update(const void *buf_, size_t bufSize) + void update(const void *buf, size_t bufSize) { - const char *buf = reinterpret_cast(buf_); - if (bufSize == 0) return; - if (roundBufSize_ > 0) { - size_t size = sha2_local::min_(blockSize_ - roundBufSize_, bufSize); - memcpy(roundBuf_ + roundBufSize_, buf, size); - roundBufSize_ += size; - buf += size; - bufSize -= size; - } - if (roundBufSize_ == blockSize_) { - round(roundBuf_); - roundBufSize_ = 0; - } - while (bufSize >= blockSize_) { - assert(roundBufSize_ == 0); - round(buf); - buf += blockSize_; - bufSize -= blockSize_; - } - if (bufSize > 0) { - assert(bufSize < blockSize_); - assert(roundBufSize_ == 0); - memcpy(roundBuf_, buf, bufSize); - roundBufSize_ = bufSize; - } - assert(roundBufSize_ < blockSize_); + inner_update(reinterpret_cast(buf), bufSize); } - void digest(const void *buf, size_t bufSize) + size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize) { + if (mdSize < outByteSize_) return 0; update(buf, bufSize); term(roundBuf_, roundBufSize_); - } - size_t get(void *out) const - { - char *p = reinterpret_cast(out); + char *p = reinterpret_cast(md); for (size_t i = 0; i < hSize_; i++) { cybozu::Set32bitAsBE(&p[i * sizeof(h_[0])], h_[i]); } @@ -220,29 +308,25 @@ public: { update(buf.c_str(), buf.size()); } - void digest(const std::string& str = "") + std::string digest(const std::string& buf) { - digest(str.c_str(), str.size()); + return digest(buf.c_str(), buf.size()); } - std::string get() const + std::string digest(const void *buf, size_t bufSize) { - char out[outByteSize_]; - get(out); - return std::string(out, sizeof(out)); - } - std::string toHexStr() const - { - char buf[outByteSize_ * 2]; - sha2_local::uint32toHexStr(buf, h_, hSize_); - return std::string(buf, sizeof(buf)); + std::string md(outByteSize_, 0); + digest(&md[0], md.size(), buf, bufSize); + return md; } #endif }; -class Sha512 { +class Sha512 : public sha2_local::Common { + friend struct sha2_local::Common; private: static const size_t blockSize_ = 128; static const size_t hSize_ = 8; + static const size_t msgLenByte_ = 16; uint64_t totalSize_; size_t roundBufSize_; char roundBuf_[blockSize_]; @@ -308,35 +392,11 @@ private: } totalSize_ += blockSize_; } - /* - final phase - */ - void term(const char *buf, size_t bufSize) - { - assert(bufSize < blockSize_); - const uint64_t totalSize = totalSize_ + bufSize; - - uint8_t last[blockSize_]; - memcpy(last, buf, bufSize); - memset(&last[bufSize], 0, blockSize_ - bufSize); - last[bufSize] = uint8_t(0x80); /* top bit = 1 */ - if (bufSize >= blockSize_ - 16) { - round(reinterpret_cast(last)); - memset(last, 0, sizeof(last)); // clear stack - } - cybozu::Set64bitAsBE(&last[blockSize_ - 8], totalSize * 8); - round(reinterpret_cast(last)); - } public: Sha512() { clear(); } - Sha512(const void *buf, size_t bufSize) - { - clear(); - digest(buf, bufSize); - } void clear() { static const uint64_t kTbl[] = { @@ -369,70 +429,39 @@ public: h_[6] = 0x1f83d9abfb41bd6bull; h_[7] = 0x5be0cd19137e2179ull; } - void update(const void *buf_, size_t bufSize) + void update(const void *buf, size_t bufSize) { - const char *buf = reinterpret_cast(buf_); - if (bufSize == 0) return; - if (roundBufSize_ > 0) { - size_t size = sha2_local::min_(blockSize_ - roundBufSize_, bufSize); - memcpy(roundBuf_ + roundBufSize_, buf, size); - roundBufSize_ += size; - buf += size; - bufSize -= size; - } - if (roundBufSize_ == blockSize_) { - round(roundBuf_); - roundBufSize_ = 0; - } - while (bufSize >= blockSize_) { - assert(roundBufSize_ == 0); - round(buf); - buf += blockSize_; - bufSize -= blockSize_; - } - if (bufSize > 0) { - assert(bufSize < blockSize_); - assert(roundBufSize_ == 0); - memcpy(roundBuf_, buf, bufSize); - roundBufSize_ = bufSize; - } - assert(roundBufSize_ < blockSize_); + inner_update(reinterpret_cast(buf), bufSize); } - void digest(const void *buf, size_t bufSize) + size_t digest(void *md, size_t mdSize, const void *buf, size_t bufSize) { + if (mdSize < outByteSize_) return 0; update(buf, bufSize); term(roundBuf_, roundBufSize_); - } - size_t get(void *out) const - { - char *p = reinterpret_cast(out); + char *p = reinterpret_cast(md); for (size_t i = 0; i < hSize_; i++) { cybozu::Set64bitAsBE(&p[i * sizeof(h_[0])], h_[i]); } return outByteSize_; } #ifndef CYBOZU_DONT_USE_STRING - void digest(const std::string& str = "") - { - digest(str.c_str(), str.size()); - } void update(const std::string& buf) { update(buf.c_str(), buf.size()); } - std::string get() const + std::string digest(const std::string& buf) { - char out[outByteSize_]; - get(out); - return std::string(out, sizeof(out)); + return digest(buf.c_str(), buf.size()); } - std::string toHexStr() const + std::string digest(const void *buf, size_t bufSize) { - char buf[outByteSize_ * 2]; - sha2_local::uint64toHexStr(buf, h_, hSize_); - return std::string(buf, sizeof(buf)); + std::string md(outByteSize_, 0); + digest(&md[0], md.size(), buf, bufSize); + return md; } #endif }; } // cybozu + +#endif diff --git a/vendor/github.com/dexon-foundation/mcl/include/cybozu/xorshift.hpp b/vendor/github.com/dexon-foundation/mcl/include/cybozu/xorshift.hpp index 69edaa939..08c6a04f9 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/cybozu/xorshift.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/cybozu/xorshift.hpp @@ -7,9 +7,47 @@ @author MITSUNARI Shigeo */ #include +#include namespace cybozu { +namespace xorshift_local { + +/* + U is uint32_t or uint64_t +*/ +template +void read_local(void *p, size_t n, Gen& gen, U (Gen::*f)()) +{ + uint8_t *dst = static_cast(p); + const size_t uSize = sizeof(U); + assert(uSize == 4 || uSize == 8); + union ua { + U u; + uint8_t a[uSize]; + }; + + while (n >= uSize) { + ua ua; + ua.u = (gen.*f)(); + for (size_t i = 0; i < uSize; i++) { + dst[i] = ua.a[i]; + } + dst += uSize; + n -= uSize; + } + assert(n < uSize); + if (n > 0) { + ua ua; + ua.u = (gen.*f)(); + for (size_t i = 0; i < n; i++) { + dst[i] = ua.a[i]; + } + } +} + +} // xorshift_local + class XorShift { uint32_t x_, y_, z_, w_; public: @@ -38,25 +76,18 @@ public: return (uint64_t(a) << 32) | b; } template - void read(T *x, size_t n) - { - const size_t size = sizeof(T) * n; - uint8_t *p8 = static_cast(x); - for (size_t i = 0; i < size; i++) { - p8[i] = static_cast(get32()); - } - } - void read(uint32_t *x, size_t n) + void read(bool *pb, T *p, size_t n) { - for (size_t i = 0; i < n; i++) { - x[i] = get32(); - } + xorshift_local::read_local(p, n * sizeof(T), *this, &XorShift::get32); + *pb = true; } - void read(uint64_t *x, size_t n) + template + size_t read(T *p, size_t n) { - for (size_t i = 0; i < n; i++) { - x[i] = get64(); - } + bool b; + read(&b, p, n); + (void)b; + return n; } }; @@ -90,25 +121,18 @@ public: return s_[1] + s0; } template - void read(T *x, size_t n) + void read(bool *pb, T *p, size_t n) { - const size_t size = sizeof(T) * n; - uint8_t *p8 = static_cast(x); - for (size_t i = 0; i < size; i++) { - p8[i] = static_cast(get32()); - } + xorshift_local::read_local(p, n * sizeof(T), *this, &XorShift128Plus::get64); + *pb = true; } - void read(uint32_t *x, size_t n) - { - for (size_t i = 0; i < n; i++) { - x[i] = get32(); - } - } - void read(uint64_t *x, size_t n) + template + size_t read(T *p, size_t n) { - for (size_t i = 0; i < n; i++) { - x[i] = get64(); - } + bool b; + read(&b, p, n); + (void)b; + return n; } }; @@ -147,25 +171,18 @@ public: return result; } template - void read(T *x, size_t n) + void read(bool *pb, T *p, size_t n) { - const size_t size = sizeof(T) * n; - uint8_t *p8 = static_cast(x); - for (size_t i = 0; i < size; i++) { - p8[i] = static_cast(get32()); - } - } - void read(uint32_t *x, size_t n) - { - for (size_t i = 0; i < n; i++) { - x[i] = get32(); - } + xorshift_local::read_local(p, n * sizeof(T), *this, &Xoroshiro128Plus::get64); + *pb = true; } - void read(uint64_t *x, size_t n) + template + size_t read(T *p, size_t n) { - for (size_t i = 0; i < n; i++) { - x[i] = get64(); - } + bool b; + read(&b, p, n); + (void)b; + return n; } }; diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/array.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/array.hpp index 84c5f3765..a6d2a8fa3 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/array.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/array.hpp @@ -8,6 +8,9 @@ */ #include #include +#ifndef CYBOZU_DONT_USE_EXCEPTION +#include +#endif namespace mcl { @@ -15,8 +18,6 @@ template class Array { T *p_; size_t n_; - Array(const Array&); - void operator=(const Array&); template void swap_(U& x, U& y) const { @@ -31,6 +32,26 @@ public: { free(p_); } +#ifndef CYBOZU_DONT_USE_EXCEPTION + Array(const Array& rhs) + : p_(0) + , n_(0) + { + if (rhs.n_ == 0) return; + p_ = (T*)malloc(sizeof(T) * rhs.n_); + if (p_ == 0) throw std::bad_alloc(); + n_ = rhs.n_; + for (size_t i = 0; i < n_; i++) { + p_[i] = rhs.p_[i]; + } + } + Array& operator=(const Array& rhs) + { + Array tmp(rhs); + tmp.swap(*this); + return *this; + } +#endif bool resize(size_t n) { if (n <= n_) { diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.h b/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.h index 9c78f92f1..0a31d5501 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.h +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.h @@ -68,6 +68,8 @@ typedef struct mclBnFr mclBnFr; typedef struct mclBnG1 mclBnG1; typedef struct mclBnG2 mclBnG2; typedef struct mclBnGT mclBnGT; +typedef struct mclBnFp mclBnFp; +typedef struct mclBnFp2 mclBnFp2; #else @@ -87,6 +89,14 @@ typedef struct { uint64_t d[MCLBN_FP_UNIT_SIZE * 12]; } mclBnGT; +typedef struct { + uint64_t d[MCLBN_FP_UNIT_SIZE]; +} mclBnFp; + +typedef struct { + mclBnFp d[2]; +} mclBnFp2; + #endif #include @@ -102,6 +112,8 @@ enum { mclBls12_CurveFp381 = 5 }; +// return 0xABC which means A.BC +MCLBN_DLL_API int mclBn_getVersion(); /* init library @param curve [in] type of bn curve @@ -146,6 +158,10 @@ MCLBN_DLL_API int mclBn_getG1ByteSize(void); return bytes for serialized Fr */ MCLBN_DLL_API int mclBn_getFrByteSize(void); +/* + return bytes for serialized Fp +*/ +MCLBN_DLL_API int mclBn_getFpByteSize(void); /* return decimal string of the order of the curve(=the characteristic of Fr) @@ -168,6 +184,8 @@ MCLBN_DLL_API mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize b MCLBN_DLL_API mclSize mclBnG1_deserialize(mclBnG1 *x, const void *buf, mclSize bufSize); MCLBN_DLL_API mclSize mclBnG2_deserialize(mclBnG2 *x, const void *buf, mclSize bufSize); MCLBN_DLL_API mclSize mclBnGT_deserialize(mclBnGT *x, const void *buf, mclSize bufSize); +MCLBN_DLL_API mclSize mclBnFp_deserialize(mclBnFp *x, const void *buf, mclSize bufSize); +MCLBN_DLL_API mclSize mclBnFp2_deserialize(mclBnFp2 *x, const void *buf, mclSize bufSize); /* serialize @@ -177,6 +195,8 @@ MCLBN_DLL_API mclSize mclBnFr_serialize(void *buf, mclSize maxBufSize, const mcl MCLBN_DLL_API mclSize mclBnG1_serialize(void *buf, mclSize maxBufSize, const mclBnG1 *x); MCLBN_DLL_API mclSize mclBnG2_serialize(void *buf, mclSize maxBufSize, const mclBnG2 *x); MCLBN_DLL_API mclSize mclBnGT_serialize(void *buf, mclSize maxBufSize, const mclBnGT *x); +MCLBN_DLL_API mclSize mclBnFp_serialize(void *buf, mclSize maxBufSize, const mclBnFp *x); +MCLBN_DLL_API mclSize mclBnFp2_serialize(void *buf, mclSize maxBufSize, const mclBnFp2 *x); /* set string @@ -190,6 +210,7 @@ MCLBN_DLL_API int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, i MCLBN_DLL_API int mclBnG1_setStr(mclBnG1 *x, const char *buf, mclSize bufSize, int ioMode); MCLBN_DLL_API int mclBnG2_setStr(mclBnG2 *x, const char *buf, mclSize bufSize, int ioMode); MCLBN_DLL_API int mclBnGT_setStr(mclBnGT *x, const char *buf, mclSize bufSize, int ioMode); +MCLBN_DLL_API int mclBnFp_setStr(mclBnFp *x, const char *buf, mclSize bufSize, int ioMode); /* buf is terminated by '\0' @@ -199,16 +220,29 @@ MCLBN_DLL_API mclSize mclBnFr_getStr(char *buf, mclSize maxBufSize, const mclBnF MCLBN_DLL_API mclSize mclBnG1_getStr(char *buf, mclSize maxBufSize, const mclBnG1 *x, int ioMode); MCLBN_DLL_API mclSize mclBnG2_getStr(char *buf, mclSize maxBufSize, const mclBnG2 *x, int ioMode); MCLBN_DLL_API mclSize mclBnGT_getStr(char *buf, mclSize maxBufSize, const mclBnGT *x, int ioMode); +MCLBN_DLL_API mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode); // set zero MCLBN_DLL_API void mclBnFr_clear(mclBnFr *x); +MCLBN_DLL_API void mclBnFp_clear(mclBnFp *x); +MCLBN_DLL_API void mclBnFp2_clear(mclBnFp2 *x); // set x to y MCLBN_DLL_API void mclBnFr_setInt(mclBnFr *y, mclInt x); MCLBN_DLL_API void mclBnFr_setInt32(mclBnFr *y, int x); -// mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r +// x = buf & (1 << bitLen(r)) - 1 +// if (x >= r) x &= (1 << (bitLen(r) - 1)) - 1 +// always return 0 MCLBN_DLL_API int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize); +MCLBN_DLL_API int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize); + +// set (buf mod r) to x +// return 0 if bufSize <= (byte size of Fr * 2) else -1 +MCLBN_DLL_API int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize); +// set (buf mod p) to x +// return 0 if bufSize <= (byte size of Fp * 2) else -1 +MCLBN_DLL_API int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize); // return 1 if true and 0 otherwise MCLBN_DLL_API int mclBnFr_isValid(const mclBnFr *x); @@ -216,15 +250,33 @@ MCLBN_DLL_API int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y); MCLBN_DLL_API int mclBnFr_isZero(const mclBnFr *x); MCLBN_DLL_API int mclBnFr_isOne(const mclBnFr *x); +MCLBN_DLL_API int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y); +MCLBN_DLL_API int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y); + #ifndef MCL_DONT_USE_CSRPNG // return 0 if success MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x); + +/* + set user-defined random function for setByCSPRNG + @param self [in] user-defined pointer + @param readFunc [in] user-defined function, + which writes random bufSize bytes to buf and returns bufSize if success else returns 0 + @note if self == 0 and readFunc == 0 then set default random function + @note not threadsafe +*/ +MCLBN_DLL_API void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)); #endif // hash(s) and set x // return 0 if success MCLBN_DLL_API int mclBnFr_setHashOf(mclBnFr *x, const void *buf, mclSize bufSize); +MCLBN_DLL_API int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize); +// map x to y +// return 0 if success else -1 +MCLBN_DLL_API int mclBnFp_mapToG1(mclBnG1 *y, const mclBnFp *x); +MCLBN_DLL_API int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x); MCLBN_DLL_API void mclBnFr_neg(mclBnFr *y, const mclBnFr *x); MCLBN_DLL_API void mclBnFr_inv(mclBnFr *y, const mclBnFr *x); @@ -340,6 +392,7 @@ MCLBN_DLL_API void mclBn_precomputedMillerLoop2mixed(mclBnGT *f, const mclBnG1 * Lagrange interpolation recover out = y(0) by { (xVec[i], yVec[i]) } return 0 if success else -1 + @note *out = yVec[0] if k = 1 @note k >= 2, xVec[i] != 0, xVec[i] != xVec[j] for i != j */ MCLBN_DLL_API int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, mclSize k); @@ -363,6 +416,13 @@ MCLBN_DLL_API int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, MCLBN_DLL_API void mclBn_verifyOrderG1(int doVerify); MCLBN_DLL_API void mclBn_verifyOrderG2(int doVerify); +/* + EXPERIMENTAL + only for curve = MCL_SECP* or MCL_NIST* + return standard base point of the current elliptic curve +*/ +MCLBN_DLL_API int mclBnG1_getBasePoint(mclBnG1 *x); + #ifdef __cplusplus } #endif diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.hpp index 8e9a9c652..5ebe5d956 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/bn.hpp @@ -315,11 +315,18 @@ public: }; struct MapTo { + enum { + BNtype, + BLS12type, + STD_ECtype + }; Fp c1_; // sqrt(-3) Fp c2_; // (-1 + sqrt(-3)) / 2 mpz_class z_; mpz_class cofactor_; - bool isBN_; + int type_; + bool useNaiveMapTo_; + int legendre(bool *pb, const Fp& x) const { mpz_class xx; @@ -488,27 +495,44 @@ struct MapTo { (void)b; c2_ = (c1_ - 1) / 2; } - void init(const mpz_class& cofactor, const mpz_class &z, bool isBN, int curveType = -1) + /* + if type == STD_ECtype, then cofactor, z are not used. + */ + void init(const mpz_class& cofactor, const mpz_class &z, int curveType) { - isBN_ = isBN; - if (isBN_) { - initBN(cofactor, z, curveType); + if (0 <= curveType && curveType < MCL_EC_BEGIN) { + type_ = curveType == MCL_BLS12_381 ? BLS12type : BNtype; + } else { + type_ = STD_ECtype; + } + if (type_ == STD_ECtype) { + useNaiveMapTo_ = true; } else { + useNaiveMapTo_ = false; + } +#ifdef MCL_USE_OLD_MAPTO_FOR_BLS12 + if (type == BLS12type) useNaiveMapTo_ = true; +#endif + if (type_ == BNtype) { + initBN(cofactor, z, curveType); + } else if (type_ == BLS12type) { initBLS12(z); } } bool calcG1(G1& P, const Fp& t) const { - if (isBN_) { - if (!calcBN(P, t)) return false; - // no subgroup - } else { -#ifdef MCL_USE_OLD_MAPTO_FOR_BLS12 + if (useNaiveMapTo_) { naiveMapTo(P, t); -#else + } else { if (!calcBN(P, t)) return false; -#endif + } + switch (type_) { + case BNtype: + // no subgroup + break; + case BLS12type: mulByCofactorBLS12(P, P); + break; } assert(P.isValid()); return true; @@ -518,16 +542,18 @@ struct MapTo { */ bool calcG2(G2& P, const Fp2& t) const { - if (isBN_) { - if (!calcBN(P, t)) return false; - mulByCofactorBN(P, P); + if (useNaiveMapTo_) { + naiveMapTo(P, t); } else { -#ifdef MCL_USE_OLD_MAPTO_FOR_BLS12 - naiveMapTo(P, t); -#else if (!calcBN(P, t)) return false; -#endif + } + switch(type_) { + case BNtype: + mulByCofactorBN(P, P); + break; + case BLS12type: mulByCofactorBLS12(P, P); + break; } assert(P.isValid()); return true; @@ -1018,6 +1044,9 @@ struct Param { bool useNAF; local::SignVec zReplTbl; + // for initG1only + G1 basePoint; + void init(bool *pb, const mcl::CurveParam& cp, fp::Mode mode) { this->cp = cp; @@ -1043,12 +1072,12 @@ struct Param { assert((p % 6) == 1); r = local::evalPoly(z, rCoff); } - Fp::init(pb, p, mode); - if (!*pb) return; Fr::init(pb, r, mode); if (!*pb) return; - Fp2::init(cp.xi_a); - Fp2 xi(cp.xi_a, 1); + Fp::init(pb, cp.xi_a, p, mode); + if (!*pb) return; + Fp2::init(); + const Fp2 xi(cp.xi_a, 1); g2 = Fp2::get_gTbl()[0]; g3 = Fp2::get_gTbl()[3]; if (cp.isMtype) { @@ -1099,14 +1128,31 @@ struct Param { } */ if (isBLS12) { - mapTo.init(0, z, false); + mapTo.init(0, z, cp.curveType); } else { - mapTo.init(2 * p - r, z, true, cp.curveType); + mapTo.init(2 * p - r, z, cp.curveType); } glv1.init(r, z, isBLS12, cp.curveType); glv2.init(r, z, isBLS12); + basePoint.clear(); *pb = true; } + void initG1only(bool *pb, const mcl::EcParam& para) + { + Fp::init(pb, para.p); + if (!*pb) return; + Fr::init(pb, para.n); + if (!*pb) return; + G1::init(pb, para.a, para.b); + if (!*pb) return; + G1::setOrder(Fr::getOp().mp); + mapTo.init(0, 0, para.curveType); + Fp x0, y0; + x0.setStr(pb, para.gx); + if (!*pb) return; + y0.setStr(pb, para.gy); + basePoint.set(pb, x0, y0); + } #ifndef CYBOZU_DONT_USE_EXCEPTION void init(const mcl::CurveParam& cp, fp::Mode mode) { @@ -1564,17 +1610,22 @@ inline void mulSparse(Fp12& z, const Fp6& x) } inline void convertFp6toFp12(Fp12& y, const Fp6& x) { - y.clear(); if (BN::param.cp.isMtype) { // (a, b, c) -> (a, c, 0, 0, b, 0) y.a.a = x.a; y.b.b = x.b; y.a.b = x.c; + y.a.c.clear(); + y.b.a.clear(); + y.b.c.clear(); } else { // (a, b, c) -> (b, 0, 0, c, a, 0) y.b.b = x.a; y.a.a = x.b; y.b.a = x.c; + y.a.b.clear(); + y.a.c.clear(); + y.b.c.clear(); } } inline void mulSparse2(Fp12& z, const Fp6& x, const Fp6& y) @@ -2190,5 +2241,21 @@ inline void initPairing(const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode = } #endif +inline void initG1only(bool *pb, const mcl::EcParam& para) +{ + local::StaticVar<>::param.initG1only(pb, para); + if (!*pb) return; + G1::setMulArrayGLV(0); + G2::setMulArrayGLV(0); + Fp12::setPowArrayGLV(0); + G1::setCompressedExpression(); + G2::setCompressedExpression(); +} + +inline const G1& getG1basePoint() +{ + return local::StaticVar<>::param.basePoint; +} + } } // mcl::bn diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/curve_type.h b/vendor/github.com/dexon-foundation/mcl/include/mcl/curve_type.h index 5957d1ae8..9e4a941a0 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/curve_type.h +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/curve_type.h @@ -14,5 +14,22 @@ enum { MCL_BN462 = 3, MCL_BN_SNARK1 = 4, MCL_BLS12_381 = 5, - MCL_BN160 = 6 + MCL_BN160 = 6, + + /* + for only G1 + the size of curve must be less or equal to MCLBN_FP_UNIT_SIZE + */ + MCL_EC_BEGIN = 100, + MCL_SECP192K1 = MCL_EC_BEGIN, + MCL_SECP224K1 = 101, + MCL_SECP256K1 = 102, + MCL_SECP384R1 = 103, + MCL_SECP521R1 = 104, + MCL_NIST_P192 = 105, + MCL_NIST_P224 = 106, + MCL_NIST_P256 = 107, + MCL_EC_END = MCL_NIST_P256 + 1, + MCL_NIST_P384 = MCL_SECP384R1, + MCL_NIST_P521 = MCL_SECP521R1 }; diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/ec.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/ec.hpp index 8ebf7e757..b8eb10be3 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/ec.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/ec.hpp @@ -23,11 +23,11 @@ namespace mcl { namespace ec { enum Mode { - Jacobi, - Proj + Jacobi = 0, + Proj = 1 }; -} // mcl::ecl +} // mcl::ec /* elliptic curve @@ -423,27 +423,41 @@ public: dblNoVerifyInf(R, P); } #ifndef MCL_EC_USE_AFFINE - static inline void addJacobi(EcT& R, const EcT& P, const EcT& Q) + static inline void addJacobi(EcT& R, const EcT& P, const EcT& Q, bool isPzOne, bool isQzOne) { - const bool isQzOne = Q.z.isOne(); Fp r, U1, S1, H, H3; - Fp::sqr(r, P.z); + if (isPzOne) { + // r = 1; + } else { + Fp::sqr(r, P.z); + } if (isQzOne) { U1 = P.x; - Fp::mul(H, Q.x, r); + if (isPzOne) { + H = Q.x; + } else { + Fp::mul(H, Q.x, r); + } H -= U1; - r *= P.z; S1 = P.y; } else { Fp::sqr(S1, Q.z); Fp::mul(U1, P.x, S1); - Fp::mul(H, Q.x, r); + if (isPzOne) { + H = Q.x; + } else { + Fp::mul(H, Q.x, r); + } H -= U1; - r *= P.z; S1 *= Q.z; S1 *= P.y; } - r *= Q.y; + if (isPzOne) { + r = Q.y; + } else { + r *= P.z; + r *= Q.y; + } r -= S1; if (H.isZero()) { if (r.isZero()) { @@ -453,11 +467,13 @@ public: } return; } - if (isQzOne) { - Fp::mul(R.z, P.z, H); + if (isPzOne) { + R.z = H; } else { - Fp::mul(R.z, P.z, Q.z); - R.z *= H; + Fp::mul(R.z, P.z, H); + } + if (!isQzOne) { + R.z *= Q.z; } Fp::sqr(H3, H); // H^2 Fp::sqr(R.y, r); // r^2 @@ -471,9 +487,8 @@ public: H3 *= S1; Fp::sub(R.y, U1, H3); } - static inline void addProj(EcT& R, const EcT& P, const EcT& Q) + static inline void addProj(EcT& R, const EcT& P, const EcT& Q, bool isPzOne, bool isQzOne) { - const bool isQzOne = Q.z.isOne(); Fp r, PyQz, v, A, vv; if (isQzOne) { r = P.x; @@ -482,8 +497,13 @@ public: Fp::mul(r, P.x, Q.z); Fp::mul(PyQz, P.y, Q.z); } - Fp::mul(A, Q.y, P.z); - Fp::mul(v, Q.x, P.z); + if (isPzOne) { + A = Q.y; + v = Q.x; + } else { + Fp::mul(A, Q.y, P.z); + Fp::mul(v, Q.x, P.z); + } v -= r; if (v.isZero()) { if (A == PyQz) { @@ -501,10 +521,19 @@ public: if (isQzOne) { R.z = P.z; } else { - Fp::mul(R.z, P.z, Q.z); + if (isPzOne) { + R.z = Q.z; + } else { + Fp::mul(R.z, P.z, Q.z); + } + } + // R.z = 1 if isPzOne && isQzOne + if (isPzOne && isQzOne) { + R.z = vv; + } else { + A *= R.z; + R.z *= vv; } - A *= R.z; - R.z *= vv; A -= vv; vv *= PyQz; A -= r; @@ -515,17 +544,14 @@ public: R.y -= vv; } #endif - static inline void add(EcT& R, const EcT& P0, const EcT& Q0) - { - if (P0.isZero()) { R = Q0; return; } - if (Q0.isZero()) { R = P0; return; } - if (&P0 == &Q0) { - dblNoVerifyInf(R, P0); + static inline void add(EcT& R, const EcT& P, const EcT& Q) { + if (P.isZero()) { R = Q; return; } + if (Q.isZero()) { R = P; return; } + if (&P == &Q) { + dblNoVerifyInf(R, P); return; } #ifdef MCL_EC_USE_AFFINE - const EcT& P(P0); - const EcT& Q(Q0); Fp t; Fp::neg(t, Q.y); if (P.y == t) { R.clear(); return; } @@ -547,19 +573,14 @@ public: Fp::sub(R.y, s, P.y); R.x = x3; #else - const EcT *pP = &P0; - const EcT *pQ = &Q0; - if (pP->z.isOne()) { - fp::swap_(pP, pQ); - } - const EcT& P(*pP); - const EcT& Q(*pQ); + bool isPzOne = P.z.isOne(); + bool isQzOne = Q.z.isOne(); switch (mode_) { case ec::Jacobi: - addJacobi(R, P, Q); + addJacobi(R, P, Q, isPzOne, isQzOne); break; case ec::Proj: - addProj(R, P, Q); + addProj(R, P, Q, isPzOne, isQzOne); break; } #endif @@ -889,6 +910,10 @@ public: bool operator<=(const EcT& rhs) const { return !operator>(rhs); } static inline void mulArray(EcT& z, const EcT& x, const fp::Unit *y, size_t yn, bool isNegative, bool constTime = false) { + if (!constTime && x.isZero()) { + z.clear(); + return; + } if (mulArrayGLV && (constTime || yn > 1)) { mulArrayGLV(z, x, y, yn, isNegative, constTime); return; @@ -983,6 +1008,7 @@ struct EcParam { const char *gy; const char *n; size_t bitSize; // bit length of p + int curveType; }; } // mcl diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/ecparam.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/ecparam.hpp index 19b76bf55..087bf8b6c 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/ecparam.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/ecparam.hpp @@ -7,6 +7,7 @@ http://opensource.org/licenses/BSD-3-Clause */ #include +#include namespace mcl { namespace ecparam { @@ -18,7 +19,8 @@ const struct mcl::EcParam secp160k1 = { "0x3b4c382ce37aa192a4019e763036f4f5dd4d7ebb", "0x938cf935318fdced6bc28286531733c3f03c4fee", "0x100000000000000000001b8fa16dfab9aca16b6b3", - 160 + 160, + -1 }; // p=2^160 + 7 const struct mcl::EcParam p160_1 = { @@ -29,7 +31,8 @@ const struct mcl::EcParam p160_1 = { "1", "1236612389951462151661156731535316138439983579284", "1461501637330902918203683518218126812711137002561", - 161 + 161, + -1 }; const struct mcl::EcParam secp192k1 = { "secp192k1", @@ -39,7 +42,8 @@ const struct mcl::EcParam secp192k1 = { "0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d", "0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d", "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d", - 192 + 192, + MCL_SECP192K1 }; const struct mcl::EcParam secp224k1 = { "secp224k1", @@ -49,7 +53,8 @@ const struct mcl::EcParam secp224k1 = { "0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c", "0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5", "0x10000000000000000000000000001dce8d2ec6184caf0a971769fb1f7", - 224 + 224, + MCL_SECP224K1 }; const struct mcl::EcParam secp256k1 = { "secp256k1", @@ -59,7 +64,8 @@ const struct mcl::EcParam secp256k1 = { "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - 256 + 256, + MCL_SECP256K1 }; const struct mcl::EcParam secp384r1 = { "secp384r1", @@ -69,7 +75,8 @@ const struct mcl::EcParam secp384r1 = { "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973", - 384 + 384, + MCL_SECP384R1 }; const struct mcl::EcParam secp521r1 = { "secp521r1", @@ -79,7 +86,8 @@ const struct mcl::EcParam secp521r1 = { "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", - 521 + 521, + MCL_SECP521R1 }; const struct mcl::EcParam NIST_P192 = { "NIST_P192", @@ -89,7 +97,8 @@ const struct mcl::EcParam NIST_P192 = { "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811", "0xffffffffffffffffffffffff99def836146bc9b1b4d22831", - 192 + 192, + MCL_NIST_P192 }; const struct mcl::EcParam NIST_P224 = { "NIST_P224", @@ -99,7 +108,8 @@ const struct mcl::EcParam NIST_P224 = { "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d", - 224 + 224, + MCL_NIST_P224 }; const struct mcl::EcParam NIST_P256 = { "NIST_P256", @@ -109,7 +119,8 @@ const struct mcl::EcParam NIST_P256 = { "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", - 256 + 256, + MCL_NIST_P256 }; // same secp384r1 const struct mcl::EcParam NIST_P384 = { @@ -120,7 +131,8 @@ const struct mcl::EcParam NIST_P384 = { "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973", - 384 + 384, + MCL_NIST_P384 }; // same secp521r1 const struct mcl::EcParam NIST_P521 = { @@ -131,7 +143,8 @@ const struct mcl::EcParam NIST_P521 = { "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", - 521 + 521, + MCL_NIST_P521 }; } // mcl::ecparam @@ -161,4 +174,18 @@ static inline const mcl::EcParam* getEcParam(const std::string& name) } #endif +inline const mcl::EcParam* getEcParam(int curve) +{ + switch (curve) { + case MCL_SECP192K1: return &ecparam::secp192k1; + case MCL_SECP224K1: return &ecparam::secp224k1; + case MCL_SECP256K1: return &ecparam::secp256k1; + case MCL_SECP384R1: return &ecparam::secp384r1; + case MCL_NIST_P192: return &ecparam::NIST_P192; + case MCL_NIST_P224: return &ecparam::NIST_P224; + case MCL_NIST_P256: return &ecparam::NIST_P256; + default: return 0; + } +} + } // mcl diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/elgamal.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/elgamal.hpp index 8bc3104b7..431148508 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/elgamal.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/elgamal.hpp @@ -244,8 +244,7 @@ struct ElgamalT { input : m = 0 or 1 output : c (c1, c2), zkp */ - template - void encWithZkp(CipherText& c, Zkp& zkp, int m, Hash& hash, fp::RandGen rg = fp::RandGen()) const + void encWithZkp(CipherText& c, Zkp& zkp, int m, fp::RandGen rg = fp::RandGen()) const { if (m != 0 && m != 1) { throw cybozu::Exception("elgamal:PublicKey:encWithZkp") << m; @@ -272,10 +271,8 @@ struct ElgamalT { mulH(R12, r1); std::ostringstream os; os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << f << g << h; - hash.update(os.str()); - const std::string digest = hash.digest(); Zn cc; - cc.setArrayMask(digest.c_str(), digest.size()); + cc.setHashOf(os.str()); zkp.c1 = cc - zkp.c0; zkp.s1 = r1 + zkp.c1 * u; } else { @@ -296,10 +293,8 @@ struct ElgamalT { Ec::sub(R12, t1, t2); std::ostringstream os; os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << f << g << h; - hash.update(os.str()); - const std::string digest = hash.digest(); Zn cc; - cc.setArrayMask(digest.c_str(), digest.size()); + cc.setHashOf(os.str()); zkp.c0 = cc - zkp.c1; zkp.s0 = r0 + zkp.c0 * u; } @@ -307,8 +302,7 @@ struct ElgamalT { /* verify cipher text with ZKP */ - template - bool verify(const CipherText& c, const Zkp& zkp, Hash& hash) const + bool verify(const CipherText& c, const Zkp& zkp) const { Ec R01, R02, R11, R12; Ec t1, t2; @@ -327,10 +321,8 @@ struct ElgamalT { Ec::sub(R12, t1, t2); std::ostringstream os; os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << f << g << h; - hash.update(os.str()); - const std::string digest = hash.digest(); Zn cc; - cc.setArrayMask(digest.c_str(), digest.size()); + cc.setHashOf(os.str()); return cc == zkp.c0 + zkp.c1; } /* diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/fp.hpp index 48500127e..2e69729dd 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/fp.hpp @@ -70,8 +70,6 @@ inline void dumpUnit(Unit x) bool isEnableJIT(); // 1st call is not threadsafe -void getRandVal(Unit *out, RandGen& rg, const Unit *in, size_t bitSize); - uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); uint32_t sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); @@ -112,10 +110,14 @@ public: } printf("\n"); } - static inline void init(bool *pb, const mpz_class& _p, fp::Mode mode = fp::FP_AUTO) + /* + xi_a is used for Fp2::mul_xi(), where xi = xi_a + i and i^2 = -1 + if xi_a = 0 then asm functions for Fp2 are not generated. + */ + static inline void init(bool *pb, int xi_a, const mpz_class& p, fp::Mode mode = fp::FP_AUTO) { assert(maxBitSize <= MCL_MAX_BIT_SIZE); - *pb = op_.init(_p, maxBitSize, mode); + *pb = op_.init(p, maxBitSize, xi_a, mode); if (!*pb) return; { // set oneRep FpT& one = *reinterpret_cast(op_.oneRep); @@ -130,19 +132,23 @@ public: } inv(inv2_, 2); #ifdef MCL_XBYAK_DIRECT_CALL - add = (void (*)(FpT& z, const FpT& x, const FpT& y))op_.fp_addA_; + add = fp::func_ptr_cast(op_.fp_addA_); if (add == 0) add = addC; - sub = (void (*)(FpT& z, const FpT& x, const FpT& y))op_.fp_subA_; + sub = fp::func_ptr_cast(op_.fp_subA_); if (sub == 0) sub = subC; - neg = (void (*)(FpT& y, const FpT& x))op_.fp_negA_; + neg = fp::func_ptr_cast(op_.fp_negA_); if (neg == 0) neg = negC; - mul = (void (*)(FpT& z, const FpT& x, const FpT& y))op_.fp_mulA_; + mul = fp::func_ptr_cast(op_.fp_mulA_); if (mul == 0) mul = mulC; - sqr = (void (*)(FpT& y, const FpT& x))op_.fp_sqrA_; + sqr = fp::func_ptr_cast(op_.fp_sqrA_); if (sqr == 0) sqr = sqrC; #endif *pb = true; } + static inline void init(bool *pb, const mpz_class& p, fp::Mode mode = fp::FP_AUTO) + { + init(pb, 0, p, mode); + } static inline void init(bool *pb, const char *mstr, fp::Mode mode = fp::FP_AUTO) { mpz_class p; @@ -296,10 +302,13 @@ public: } cybozu::write(pb, os, buf + sizeof(buf) - len, len); } + /* + mode = Mod : set x mod p if sizeof(S) * n <= 64 else error + */ template - void setArray(bool *pb, const S *x, size_t n) + void setArray(bool *pb, const S *x, size_t n, mcl::fp::MaskMode mode = fp::NoMask) { - *pb = fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::NoMask); + *pb = fp::copyAndMask(v_, x, sizeof(S) * n, op_, mode); toMont(); } /* @@ -331,12 +340,21 @@ public: b.p = &v_[0]; } } - void setByCSPRNG(fp::RandGen rg = fp::RandGen()) + void setByCSPRNG(bool *pb, fp::RandGen rg = fp::RandGen()) { if (rg.isZero()) rg = fp::RandGen::get(); - fp::getRandVal(v_, rg, op_.p, op_.bitSize); - toMont(); + rg.read(pb, v_, op_.N * sizeof(Unit)); // byte size + if (!pb) return; + setArrayMask(v_, op_.N); + } +#ifndef CYBOZU_DONT_USE_EXCEPTION + void setByCSPRNG(fp::RandGen rg = fp::RandGen()) + { + bool b; + setByCSPRNG(&b, rg); + if (!b) throw cybozu::Exception("setByCSPRNG"); } +#endif void setRand(fp::RandGen rg = fp::RandGen()) // old api { setByCSPRNG(rg); @@ -522,17 +540,25 @@ public: } #endif #ifndef CYBOZU_DONT_USE_EXCEPTION - static inline void init(const mpz_class& _p, fp::Mode mode = fp::FP_AUTO) + static inline void init(int xi_a, const mpz_class& p, fp::Mode mode = fp::FP_AUTO) { bool b; - init(&b, _p, mode); + init(&b, xi_a, p, mode); if (!b) throw cybozu::Exception("Fp:init"); } + static inline void init(int xi_a, const std::string& mstr, fp::Mode mode = fp::FP_AUTO) + { + mpz_class p; + gmp::setStr(p, mstr); + init(xi_a, p, mode); + } + static inline void init(const mpz_class& p, fp::Mode mode = fp::FP_AUTO) + { + init(0, p, mode); + } static inline void init(const std::string& mstr, fp::Mode mode = fp::FP_AUTO) { - bool b; - init(&b, mstr.c_str(), mode); - if (!b) throw cybozu::Exception("Fp:init"); + init(0, mstr, mode); } template void save(OutputStream& os, int ioMode = IoSerialize) const @@ -562,7 +588,7 @@ public: { bool b; setMpz(&b, x); - if (!b) throw cybozu::Exception("Fp:setMpz:neg"); + if (!b) throw cybozu::Exception("Fp:setMpz"); } uint64_t getUint64() const { diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp index 63738a3f5..95722e2d5 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/fp_tower.hpp @@ -121,20 +121,22 @@ public: static void (*add)(FpDblT& z, const FpDblT& x, const FpDblT& y); static void (*sub)(FpDblT& z, const FpDblT& x, const FpDblT& y); static void (*mod)(Fp& z, const FpDblT& xy); + static void (*addPre)(FpDblT& z, const FpDblT& x, const FpDblT& y); + static void (*subPre)(FpDblT& z, const FpDblT& x, const FpDblT& y); static void addC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); } static void subC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); } static void modC(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); } + static void addPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); } + static void subPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); } #else static void add(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); } static void sub(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); } static void mod(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); } + static void addPre(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); } + static void subPre(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); } #endif - static void addPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); } - static void subPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); } static void mulPreC(FpDblT& xy, const Fp& x, const Fp& y) { Fp::op_.fpDbl_mulPre(xy.v_, x.v_, y.v_); } static void sqrPreC(FpDblT& xx, const Fp& x) { Fp::op_.fpDbl_sqrPre(xx.v_, x.v_); } - static void (*addPre)(FpDblT& z, const FpDblT& x, const FpDblT& y); - static void (*subPre)(FpDblT& z, const FpDblT& x, const FpDblT& y); /* mul(z, x, y) = mulPre(xy, x, y) + mod(z, xy) */ @@ -149,30 +151,24 @@ public: { const mcl::fp::Op& op = Fp::getOp(); #ifdef MCL_XBYAK_DIRECT_CALL - add = (void (*)(FpDblT&, const FpDblT&, const FpDblT&))op.fpDbl_addA_; + add = fp::func_ptr_cast(op.fpDbl_addA_); if (add == 0) add = addC; - sub = (void (*)(FpDblT&, const FpDblT&, const FpDblT&))op.fpDbl_subA_; + sub = fp::func_ptr_cast(op.fpDbl_subA_); if (sub == 0) sub = subC; - mod = (void (*)(Fp&, const FpDblT&))op.fpDbl_modA_; + mod = fp::func_ptr_cast(op.fpDbl_modA_); if (mod == 0) mod = modC; + addPre = fp::func_ptr_cast(op.fpDbl_addPre); + if (addPre == 0) addPre = addPreC; + subPre = fp::func_ptr_cast(op.fpDbl_subPre); + if (subPre == 0) subPre = subPreC; #endif - if (op.fpDbl_addPreA_) { - addPre = (void (*)(FpDblT&, const FpDblT&, const FpDblT&))op.fpDbl_addPreA_; - } else { - addPre = addPreC; - } - if (op.fpDbl_subPreA_) { - subPre = (void (*)(FpDblT&, const FpDblT&, const FpDblT&))op.fpDbl_subPreA_; - } else { - subPre = subPreC; - } if (op.fpDbl_mulPreA_) { - mulPre = (void (*)(FpDblT&, const Fp&, const Fp&))op.fpDbl_mulPreA_; + mulPre = fp::func_ptr_cast(op.fpDbl_mulPreA_); } else { mulPre = mulPreC; } if (op.fpDbl_sqrPreA_) { - sqrPre = (void (*)(FpDblT&, const Fp&))op.fpDbl_sqrPreA_; + sqrPre = fp::func_ptr_cast(op.fpDbl_sqrPreA_); } else { sqrPre = sqrPreC; } @@ -185,9 +181,9 @@ public: template void (*FpDblT::add)(FpDblT&, const FpDblT&, const FpDblT&); template void (*FpDblT::sub)(FpDblT&, const FpDblT&, const FpDblT&); template void (*FpDblT::mod)(Fp&, const FpDblT&); -#endif template void (*FpDblT::addPre)(FpDblT&, const FpDblT&, const FpDblT&); template void (*FpDblT::subPre)(FpDblT&, const FpDblT&, const FpDblT&); +#endif template void (*FpDblT::mulPre)(FpDblT&, const Fp&, const Fp&); template void (*FpDblT::sqrPre)(FpDblT&, const Fp&); @@ -206,7 +202,6 @@ class Fp2T : public fp::Serializable, typedef fp::Unit Unit; typedef FpDblT FpDbl; typedef Fp2DblT Fp2Dbl; - static uint32_t xi_a_; static const size_t gN = 5; /* g = xi^((p - 1) / 6) @@ -245,11 +240,19 @@ public: a = a_; b = b_; } +#ifdef MCL_XBYAK_DIRECT_CALL static void (*add)(Fp2T& z, const Fp2T& x, const Fp2T& y); static void (*sub)(Fp2T& z, const Fp2T& x, const Fp2T& y); static void (*neg)(Fp2T& y, const Fp2T& x); static void (*mul)(Fp2T& z, const Fp2T& x, const Fp2T& y); static void (*sqr)(Fp2T& y, const Fp2T& x); +#else + static void add(Fp2T& z, const Fp2T& x, const Fp2T& y) { addC(z, x, y); } + static void sub(Fp2T& z, const Fp2T& x, const Fp2T& y) { subC(z, x, y); } + static void neg(Fp2T& y, const Fp2T& x) { negC(y, x); } + static void mul(Fp2T& z, const Fp2T& x, const Fp2T& y) { mulC(z, x, y); } + static void sqr(Fp2T& y, const Fp2T& x) { sqrC(y, x); } +#endif static void (*mul_xi)(Fp2T& y, const Fp2T& x); static void addPre(Fp2T& z, const Fp2T& x, const Fp2T& y) { Fp::addPre(z.a, x.a, y.a); Fp::addPre(z.b, x.b, y.b); } static void inv(Fp2T& y, const Fp2T& x) { Fp::op_.fp2_inv(y.a.v_, x.a.v_); } @@ -377,51 +380,38 @@ public: } } - static uint32_t get_xi_a() { return xi_a_; } - static void init(uint32_t xi_a) + static uint32_t get_xi_a() { return Fp::getOp().xi_a; } + static void init() { // assert(Fp::maxSize <= 256); - xi_a_ = xi_a; mcl::fp::Op& op = Fp::op_; - add = (void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y))op.fp2_addA_; - if (add == 0) add = fp2_addC; - sub = (void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y))op.fp2_subA_; - if (sub == 0) sub = fp2_subC; - neg = (void (*)(Fp2T& y, const Fp2T& x))op.fp2_negA_; - if (neg == 0) neg = fp2_negC; - mul = (void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y))op.fp2_mulA_; - if (mul == 0) { - if (op.isFastMod) { - mul = fp2_mulC; - } else if (!op.isFullBit) { - if (0 && sizeof(Fp) * 8 == op.N * fp::UnitBitSize && op.fp2_mulNF) { - mul = fp2_mulNFW; - } else { - mul = fp2_mulC; - } - } else { - mul = fp2_mulC; - } - } - sqr = (void (*)(Fp2T& y, const Fp2T& x))op.fp2_sqrA_; - if (sqr == 0) sqr = fp2_sqrC; + assert(op.xi_a); + mul_xi = 0; +#ifdef MCL_XBYAK_DIRECT_CALL + add = fp::func_ptr_cast(op.fp2_addA_); + if (add == 0) add = addC; + sub = fp::func_ptr_cast(op.fp2_subA_); + if (sub == 0) sub = subC; + neg = fp::func_ptr_cast(op.fp2_negA_); + if (neg == 0) neg = negC; + mul = fp::func_ptr_cast(op.fp2_mulA_); + if (mul == 0) mul = mulC; + sqr = fp::func_ptr_cast(op.fp2_sqrA_); + if (sqr == 0) sqr = sqrC; + mul_xi = fp::func_ptr_cast(op.fp2_mul_xiA_); +#endif op.fp2_inv = fp2_invW; - if (xi_a == 1) { - /* - current fp_generator.hpp generates mul_xi for xi_a = 1 - */ - if (op.fp2_mul_xiA_) { - mul_xi = (void (*)(Fp2T&, const Fp2T&))op.fp2_mul_xiA_; + if (mul_xi == 0) { + if (op.xi_a == 1) { + mul_xi = fp2_mul_xi_1_1iC; } else { - mul_xi = fp2_mul_xi_1_1i; + mul_xi = fp2_mul_xiC; } - } else { - mul_xi = fp2_mul_xiC; } FpDblT::init(); Fp2DblT::init(); // call init before Fp2::pow because FpDbl is used in Fp2T - const Fp2T xi(xi_a, 1); + const Fp2T xi(op.xi_a, 1); const mpz_class& p = Fp::getOp().mp; Fp2T::pow(g[0], xi, (p - 1) / 6); // g = xi^((p-1)/6) for (size_t i = 1; i < gN; i++) { @@ -490,17 +480,17 @@ private: default Fp2T operator Fp2T = Fp[i]/(i^2 + 1) */ - static void fp2_addC(Fp2T& z, const Fp2T& x, const Fp2T& y) + static void addC(Fp2T& z, const Fp2T& x, const Fp2T& y) { Fp::add(z.a, x.a, y.a); Fp::add(z.b, x.b, y.b); } - static void fp2_subC(Fp2T& z, const Fp2T& x, const Fp2T& y) + static void subC(Fp2T& z, const Fp2T& x, const Fp2T& y) { Fp::sub(z.a, x.a, y.a); Fp::sub(z.b, x.b, y.b); } - static void fp2_negC(Fp2T& y, const Fp2T& x) + static void negC(Fp2T& y, const Fp2T& x) { Fp::neg(y.a, x.a); Fp::neg(y.b, x.b); @@ -531,13 +521,13 @@ private: Fp::sub(pz[1], t1, ac); pz[1] -= bd; } -#endif static void fp2_mulNFW(Fp2T& z, const Fp2T& x, const Fp2T& y) { const fp::Op& op = Fp::op_; op.fp2_mulNF((Unit*)&z, (const Unit*)&x, (const Unit*)&y, op.p); } - static void fp2_mulC(Fp2T& z, const Fp2T& x, const Fp2T& y) +#endif + static void mulC(Fp2T& z, const Fp2T& x, const Fp2T& y) { Fp2Dbl d; Fp2Dbl::mulPre(d, x, y); @@ -548,7 +538,7 @@ private: x = a + bi, i^2 = -1 y = x^2 = (a + bi)^2 = (a + b)(a - b) + 2abi */ - static void fp2_sqrC(Fp2T& y, const Fp2T& x) + static void sqrC(Fp2T& y, const Fp2T& x) { const Fp& a = x.a; const Fp& b = x.b; @@ -583,9 +573,9 @@ private: const Fp& a = x.a; const Fp& b = x.b; Fp t; - Fp::mulUnit(t, a, xi_a_); + Fp::mulUnit(t, a, Fp::getOp().xi_a); t -= b; - Fp::mulUnit(y.b, b, xi_a_); + Fp::mulUnit(y.b, b, Fp::getOp().xi_a); y.b += a; y.a = t; } @@ -593,7 +583,7 @@ private: xi = 1 + i ; xi_a = 1 y = (a + bi)xi = (a - b) + (a + b)i */ - static void fp2_mul_xi_1_1i(Fp2T& y, const Fp2T& x) + static void fp2_mul_xi_1_1iC(Fp2T& y, const Fp2T& x) { const Fp& a = x.a; const Fp& b = x.b; @@ -623,11 +613,13 @@ private: } }; +#ifdef MCL_XBYAK_DIRECT_CALL template void (*Fp2T::add)(Fp2T& z, const Fp2T& x, const Fp2T& y); template void (*Fp2T::sub)(Fp2T& z, const Fp2T& x, const Fp2T& y); template void (*Fp2T::neg)(Fp2T& y, const Fp2T& x); template void (*Fp2T::mul)(Fp2T& z, const Fp2T& x, const Fp2T& y); template void (*Fp2T::sqr)(Fp2T& y, const Fp2T& x); +#endif template void (*Fp2T::mul_xi)(Fp2T& y, const Fp2T& x); template @@ -697,7 +689,7 @@ struct Fp2DblT { { const mcl::fp::Op& op = Fp::getOp(); if (op.fp2Dbl_mulPreA_) { - mulPre = (void (*)(Fp2DblT&, const Fp2&, const Fp2&))op.fp2Dbl_mulPreA_; + mulPre = fp::func_ptr_cast(op.fp2Dbl_mulPreA_); } else { if (op.isFullBit) { mulPre = fp2Dbl_mulPreW; @@ -706,7 +698,7 @@ struct Fp2DblT { } } if (op.fp2Dbl_sqrPreA_) { - sqrPre = (void (*)(Fp2DblT&, const Fp2&))op.fp2Dbl_sqrPreA_; + sqrPre = fp::func_ptr_cast(op.fp2Dbl_sqrPreA_); } else { if (op.isFullBit) { sqrPre = fp2Dbl_sqrPreW; @@ -769,11 +761,12 @@ struct Fp2DblT { template void (*Fp2DblT::mulPre)(Fp2DblT&, const Fp2T&, const Fp2T&); template void (*Fp2DblT::sqrPre)(Fp2DblT&, const Fp2T&); -template uint32_t Fp2T::xi_a_; template Fp2T Fp2T::g[Fp2T::gN]; template Fp2T Fp2T::g2[Fp2T::gN]; template Fp2T Fp2T::g3[Fp2T::gN]; +template +struct Fp6DblT; /* Fp6T = Fp2[v] / (v^3 - xi) x = a + b v + c v^2 @@ -784,6 +777,7 @@ struct Fp6T : public fp::Serializable, typedef _Fp Fp; typedef Fp2T Fp2; typedef Fp2DblT Fp2Dbl; + typedef Fp6DblT Fp6Dbl; typedef Fp BaseFp; Fp2 a, b, c; Fp6T() { } @@ -914,91 +908,7 @@ struct Fp6T : public fp::Serializable, y.b += t1; // c^2 xi + 2ab y.c -= t1; // b^2 + 2ac } - /* - x = a + bv + cv^2, y = d + ev + fv^2, v^3 = xi - xy = (ad + (bf + ce)xi) + ((ae + bd) + cf xi)v + ((af + cd) + be)v^2 - bf + ce = (b + c)(e + f) - be - cf - ae + bd = (a + b)(e + d) - ad - be - af + cd = (a + c)(d + f) - ad - cf - */ - static void mul(Fp6T& z, const Fp6T& x, const Fp6T& y) - { -//clk.begin(); - const Fp2& a = x.a; - const Fp2& b = x.b; - const Fp2& c = x.c; - const Fp2& d = y.a; - const Fp2& e = y.b; - const Fp2& f = y.c; -#if 1 - Fp2Dbl AD, BE, CF; - Fp2Dbl::mulPre(AD, a, d); - Fp2Dbl::mulPre(BE, b, e); - Fp2Dbl::mulPre(CF, c, f); - - Fp2 t1, t2, t3, t4; - Fp2::add(t1, b, c); - Fp2::add(t2, e, f); - Fp2Dbl T1; - Fp2Dbl::mulPre(T1, t1, t2); - Fp2Dbl::sub(T1, T1, BE); - Fp2Dbl::sub(T1, T1, CF); - Fp2Dbl::mul_xi(T1, T1); - - Fp2::add(t2, a, b); - Fp2::add(t3, e, d); - Fp2Dbl T2; - Fp2Dbl::mulPre(T2, t2, t3); - Fp2Dbl::sub(T2, T2, AD); - Fp2Dbl::sub(T2, T2, BE); - - Fp2::add(t3, a, c); - Fp2::add(t4, d, f); - Fp2Dbl T3; - Fp2Dbl::mulPre(T3, t3, t4); - Fp2Dbl::sub(T3, T3, AD); - Fp2Dbl::sub(T3, T3, CF); - - Fp2Dbl::add(AD, AD, T1); - Fp2Dbl::mod(z.a, AD); - Fp2Dbl::mul_xi(CF, CF); - Fp2Dbl::add(CF, CF, T2); - Fp2Dbl::mod(z.b, CF); - Fp2Dbl::add(T3, T3, BE); - Fp2Dbl::mod(z.c, T3); -#else - Fp2 ad, be, cf; - Fp2::mul(ad, a, d); - Fp2::mul(be, b, e); - Fp2::mul(cf, c, f); - - Fp2 t1, t2, t3, t4; - Fp2::add(t1, b, c); - Fp2::add(t2, e, f); - t1 *= t2; - t1 -= be; - t1 -= cf; - Fp2::mul_xi(t1, t1); - - Fp2::add(t2, a, b); - Fp2::add(t3, e, d); - t2 *= t3; - t2 -= ad; - t2 -= be; - - Fp2::add(t3, a, c); - Fp2::add(t4, d, f); - t3 *= t4; - t3 -= ad; - t3 -= cf; - - Fp2::add(z.a, ad, t1); - Fp2::mul_xi(z.b, cf); - z.b += t2; - Fp2::add(z.c, t3, be); -#endif -//clk.end(); - } + static inline void mul(Fp6T& z, const Fp6T& x, const Fp6T& y); /* x = a + bv + cv^2, v^3 = xi y = 1/x = p/q where @@ -1040,6 +950,94 @@ struct Fp6T : public fp::Serializable, } }; +template +struct Fp6DblT { + typedef Fp2T Fp2; + typedef Fp6T Fp6; + typedef Fp2DblT Fp2Dbl; + typedef Fp6DblT Fp6Dbl; + typedef fp::Unit Unit; + Fp2Dbl a, b, c; + static void add(Fp6Dbl& z, const Fp6Dbl& x, const Fp6Dbl& y) + { + Fp2Dbl::add(z.a, x.a, y.a); + Fp2Dbl::add(z.b, x.b, y.b); + Fp2Dbl::add(z.c, x.c, y.c); + } + static void sub(Fp6Dbl& z, const Fp6Dbl& x, const Fp6Dbl& y) + { + Fp2Dbl::sub(z.a, x.a, y.a); + Fp2Dbl::sub(z.b, x.b, y.b); + Fp2Dbl::sub(z.c, x.c, y.c); + } + /* + x = a + bv + cv^2, y = d + ev + fv^2, v^3 = xi + xy = (ad + (bf + ce)xi) + ((ae + bd) + cf xi)v + ((af + cd) + be)v^2 + bf + ce = (b + c)(e + f) - be - cf + ae + bd = (a + b)(e + d) - ad - be + af + cd = (a + c)(d + f) - ad - cf + */ + static void mulPre(Fp6DblT& z, const Fp6& x, const Fp6& y) + { +//clk.begin(); + const Fp2& a = x.a; + const Fp2& b = x.b; + const Fp2& c = x.c; + const Fp2& d = y.a; + const Fp2& e = y.b; + const Fp2& f = y.c; + Fp2Dbl& za = z.a; + Fp2Dbl& zb = z.b; + Fp2Dbl& zc = z.c; + Fp2Dbl BE; + Fp2Dbl::mulPre(za, a, d); + Fp2Dbl::mulPre(BE, b, e); + Fp2Dbl::mulPre(zb, c, f); + + Fp2 t1, t2, t3, t4; + Fp2::add(t1, b, c); + Fp2::add(t2, e, f); + Fp2Dbl T1; + Fp2Dbl::mulPre(T1, t1, t2); + Fp2Dbl::sub(T1, T1, BE); + Fp2Dbl::sub(T1, T1, zb); + Fp2Dbl::mul_xi(T1, T1); + + Fp2::add(t2, a, b); + Fp2::add(t3, e, d); + Fp2Dbl T2; + Fp2Dbl::mulPre(T2, t2, t3); + Fp2Dbl::sub(T2, T2, za); + Fp2Dbl::sub(T2, T2, BE); + + Fp2::add(t3, a, c); + Fp2::add(t4, d, f); + Fp2Dbl::mulPre(zc, t3, t4); + Fp2Dbl::sub(zc, zc, za); + Fp2Dbl::sub(zc, zc, zb); + + Fp2Dbl::add(za, za, T1); + Fp2Dbl::mul_xi(zb, zb); + Fp2Dbl::add(zb, zb, T2); + Fp2Dbl::add(zc, zc, BE); +//clk.end(); + } + static void mod(Fp6& y, const Fp6Dbl& x) + { + Fp2Dbl::mod(y.a, x.a); + Fp2Dbl::mod(y.b, x.b); + Fp2Dbl::mod(y.c, x.c); + } +}; + +template +inline void Fp6T::mul(Fp6T& z, const Fp6T& x, const Fp6T& y) +{ + Fp6DblT Z; + Fp6DblT::mulPre(Z, x, y); + Fp6DblT::mod(z, Z); +} + /* Fp12T = Fp6[w] / (w^2 - v) x = a + b w @@ -1049,6 +1047,8 @@ struct Fp12T : public fp::Serializable, fp::Operator > > { typedef Fp2T Fp2; typedef Fp6T Fp6; + typedef Fp2DblT Fp2Dbl; + typedef Fp6DblT Fp6Dbl; typedef Fp BaseFp; Fp6 a, b; Fp12T() {} @@ -1115,6 +1115,14 @@ struct Fp12T : public fp::Serializable, Fp2::add(z.b, x.a, y.b); Fp2::add(z.a, t, y.a); } + static void mulVadd(Fp6Dbl& z, const Fp6Dbl& x, const Fp6Dbl& y) + { + Fp2Dbl t; + Fp2Dbl::mul_xi(t, x.c); + Fp2Dbl::add(z.c, x.b, y.c); + Fp2Dbl::add(z.b, x.a, y.b); + Fp2Dbl::add(z.a, t, y.a); + } /* x = a + bw, y = c + dw, w^2 = v z = xy = (a + bw)(c + dw) = (ac + bdv) + (ad + bc)w @@ -1124,19 +1132,33 @@ struct Fp12T : public fp::Serializable, */ static void mul(Fp12T& z, const Fp12T& x, const Fp12T& y) { + // 4.7Kclk -> 4.55Kclk const Fp6& a = x.a; const Fp6& b = x.b; const Fp6& c = y.a; const Fp6& d = y.b; - Fp6 t1, t2, ac, bd; + Fp6 t1, t2; Fp6::add(t1, a, b); Fp6::add(t2, c, d); +#if 1 + Fp6Dbl T, AC, BD; + Fp6Dbl::mulPre(AC, a, c); + Fp6Dbl::mulPre(BD, b, d); + mulVadd(T, BD, AC); + Fp6Dbl::mod(z.a, T); + Fp6Dbl::mulPre(T, t1, t2); // (a + b)(c + d) + Fp6Dbl::sub(T, T, AC); + Fp6Dbl::sub(T, T, BD); + Fp6Dbl::mod(z.b, T); +#else + Fp6 ac, bd; t1 *= t2; // (a + b)(c + d) Fp6::mul(ac, a, c); Fp6::mul(bd, b, d); mulVadd(z.a, bd, ac); t1 -= ac; Fp6::sub(z.b, t1, bd); +#endif } /* x = a + bw, w^2 = v diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/gmp_util.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/gmp_util.hpp index 2dd71eb50..bcbd91a1e 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/gmp_util.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/gmp_util.hpp @@ -450,7 +450,8 @@ inline void getRand(bool *pb, mpz_class& z, size_t bitSize, fp::RandGen rg = fp: *pb = false; return; } - rg.read(buf, n * sizeof(buf[0])); + rg.read(pb, buf, n * sizeof(buf[0])); + if (!*pb) return; uint32_t v = buf[n - 1]; if (rem == 0) { v |= 1U << 31; @@ -858,4 +859,96 @@ public: #endif }; +/* + Barrett Reduction + for non GMP version + mod of GMP is faster than Modp +*/ +struct Modp { + static const size_t unitBitSize = sizeof(mcl::fp::Unit) * 8; + mpz_class p_; + mpz_class u_; + mpz_class a_; + size_t pBitSize_; + size_t N_; + bool initU_; // Is u_ initialized? + Modp() + : pBitSize_(0) + , N_(0) + , initU_(false) + { + } + // x &= 1 << (unitBitSize * unitSize) + void shrinkSize(mpz_class &x, size_t unitSize) const + { + size_t u = gmp::getUnitSize(x); + if (u < unitSize) return; + bool b; + gmp::setArray(&b, x, gmp::getUnit(x), unitSize); + (void)b; + assert(b); + } + // p_ is set by p and compute (u_, a_) if possible + void init(const mpz_class& p) + { + p_ = p; + pBitSize_ = gmp::getBitSize(p); + N_ = (pBitSize_ + unitBitSize - 1) / unitBitSize; + initU_ = false; +#if 0 + u_ = (mpz_class(1) << (unitBitSize * 2 * N_)) / p_; +#else + /* + 1 << (unitBitSize * 2 * N_) may be overflow, + so use (1 << (unitBitSize * 2 * N_)) - 1 because u_ is same. + */ + uint8_t buf[48 * 2]; + const size_t byteSize = unitBitSize / 8 * 2 * N_; + if (byteSize > sizeof(buf)) return; + memset(buf, 0xff, byteSize); + bool b; + gmp::setArray(&b, u_, buf, byteSize); + if (!b) return; +#endif + u_ /= p_; + a_ = mpz_class(1) << (unitBitSize * (N_ + 1)); + initU_ = true; + } + void modp(mpz_class& r, const mpz_class& t) const + { + assert(p_ > 0); + const size_t tBitSize = gmp::getBitSize(t); + // use gmp::mod if init() fails or t is too large + if (tBitSize > unitBitSize * 2 * N_ || !initU_) { + gmp::mod(r, t, p_); + return; + } + if (tBitSize < pBitSize_) { + r = t; + return; + } + // mod is faster than modp if t is small + if (tBitSize <= unitBitSize * N_) { + gmp::mod(r, t, p_); + return; + } + mpz_class q; + q = t; + q >>= unitBitSize * (N_ - 1); + q *= u_; + q >>= unitBitSize * (N_ + 1); + q *= p_; + shrinkSize(q, N_ + 1); + r = t; + shrinkSize(r, N_ + 1); + r -= q; + if (r < 0) { + r += a_; + } + if (r >= p_) { + r -= p_; + } + } +}; + } // mcl diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/impl/bn_c_impl.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/impl/bn_c_impl.hpp new file mode 100644 index 000000000..bec2466dd --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/impl/bn_c_impl.hpp @@ -0,0 +1,643 @@ +/* + This is an internal header + Do not include this +*/ +#define MCLBN_DLL_EXPORT +#include + +#if MCLBN_FP_UNIT_SIZE == 4 && MCLBN_FR_UNIT_SIZE == 4 +#include +#elif MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 6 +#include +#elif MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE == 4 +#include +#elif MCLBN_FP_UNIT_SIZE == 8 && MCLBN_FR_UNIT_SIZE == 8 +#include +#else + #error "not supported size" +#endif +#include +#include +using namespace mcl::bn; + +static Fr *cast(mclBnFr *p) { return reinterpret_cast(p); } +static const Fr *cast(const mclBnFr *p) { return reinterpret_cast(p); } + +static G1 *cast(mclBnG1 *p) { return reinterpret_cast(p); } +static const G1 *cast(const mclBnG1 *p) { return reinterpret_cast(p); } + +static G2 *cast(mclBnG2 *p) { return reinterpret_cast(p); } +static const G2 *cast(const mclBnG2 *p) { return reinterpret_cast(p); } + +static Fp12 *cast(mclBnGT *p) { return reinterpret_cast(p); } +static const Fp12 *cast(const mclBnGT *p) { return reinterpret_cast(p); } + +static Fp6 *cast(uint64_t *p) { return reinterpret_cast(p); } +static const Fp6 *cast(const uint64_t *p) { return reinterpret_cast(p); } + +static Fp2 *cast(mclBnFp2 *p) { return reinterpret_cast(p); } +static const Fp2 *cast(const mclBnFp2 *p) { return reinterpret_cast(p); } + +static Fp *cast(mclBnFp *p) { return reinterpret_cast(p); } +static const Fp *cast(const mclBnFp *p) { return reinterpret_cast(p); } + +template +int setStr(T *x, const char *buf, mclSize bufSize, int ioMode) +{ + size_t n = cast(x)->deserialize(buf, bufSize, ioMode); + return n > 0 ? 0 : -1; +} + +#ifdef __EMSCRIPTEN__ +// use these functions forcibly +extern "C" MCLBN_DLL_API void *mclBnMalloc(size_t n) +{ + return malloc(n); +} +extern "C" MCLBN_DLL_API void mclBnFree(void *p) +{ + free(p); +} +#endif + +int mclBn_getVersion() +{ + return mcl::version; +} + +int mclBn_init(int curve, int compiledTimeVar) +{ + if (compiledTimeVar != MCLBN_COMPILED_TIME_VAR) { + return -(compiledTimeVar | (MCLBN_COMPILED_TIME_VAR * 100)); + } + if (MCL_EC_BEGIN <= curve && curve < MCL_EC_END) { + const mcl::EcParam *para = mcl::getEcParam(curve); + if (para == 0) return -2; + bool b; + initG1only(&b, *para); + return b ? 0 : -1; + } + const mcl::CurveParam& cp = mcl::getCurveParam(curve); + bool b; + initPairing(&b, cp); + return b ? 0 : -1; +} + +int mclBn_getOpUnitSize() +{ + return (int)Fp::getUnitSize() * sizeof(mcl::fp::Unit) / sizeof(uint64_t); +} + +int mclBn_getG1ByteSize() +{ + return mclBn_getFpByteSize(); +} + +int mclBn_getFrByteSize() +{ + return (int)Fr::getByteSize(); +} + +int mclBn_getFpByteSize() +{ + return (int)Fp::getByteSize(); +} + +mclSize mclBn_getCurveOrder(char *buf, mclSize maxBufSize) +{ + return Fr::getModulo(buf, maxBufSize); +} + +mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize) +{ + return Fp::getModulo(buf, maxBufSize); +} + +//////////////////////////////////////////////// +// set zero +void mclBnFr_clear(mclBnFr *x) +{ + cast(x)->clear(); +} + +// set x to y +void mclBnFr_setInt(mclBnFr *y, mclInt x) +{ + *cast(y) = x; +} +void mclBnFr_setInt32(mclBnFr *y, int x) +{ + *cast(y) = x; +} + +int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, int ioMode) +{ + return setStr(x, buf, bufSize, ioMode); +} +int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize) +{ + cast(x)->setArrayMask((const char *)buf, bufSize); + return 0; +} +int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize) +{ + bool b; + cast(x)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod); + return b ? 0 : -1; +} +mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize bufSize) +{ + return (mclSize)cast(x)->deserialize(buf, bufSize); +} +// return 1 if true +int mclBnFr_isValid(const mclBnFr *x) +{ + return cast(x)->isValid(); +} +int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y) +{ + return *cast(x) == *cast(y); +} +int mclBnFr_isZero(const mclBnFr *x) +{ + return cast(x)->isZero(); +} +int mclBnFr_isOne(const mclBnFr *x) +{ + return cast(x)->isOne(); +} + +#ifndef MCL_DONT_USE_CSRPNG +int mclBnFr_setByCSPRNG(mclBnFr *x) +{ + bool b; + cast(x)->setByCSPRNG(&b); + return b ? 0 : -1; +} +void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)) +{ + mcl::fp::RandGen::setRandFunc(self, readFunc); +} +#endif + +// hash(buf) and set x +int mclBnFr_setHashOf(mclBnFr *x, const void *buf, mclSize bufSize) +{ + cast(x)->setHashOf(buf, bufSize); + return 0; +} + +mclSize mclBnFr_getStr(char *buf, mclSize maxBufSize, const mclBnFr *x, int ioMode) +{ + return cast(x)->getStr(buf, maxBufSize, ioMode); +} +mclSize mclBnFr_serialize(void *buf, mclSize maxBufSize, const mclBnFr *x) +{ + return (mclSize)cast(x)->serialize(buf, maxBufSize); +} + +void mclBnFr_neg(mclBnFr *y, const mclBnFr *x) +{ + Fr::neg(*cast(y), *cast(x)); +} +void mclBnFr_inv(mclBnFr *y, const mclBnFr *x) +{ + Fr::inv(*cast(y), *cast(x)); +} +void mclBnFr_sqr(mclBnFr *y, const mclBnFr *x) +{ + Fr::sqr(*cast(y), *cast(x)); +} +void mclBnFr_add(mclBnFr *z, const mclBnFr *x, const mclBnFr *y) +{ + Fr::add(*cast(z),*cast(x), *cast(y)); +} +void mclBnFr_sub(mclBnFr *z, const mclBnFr *x, const mclBnFr *y) +{ + Fr::sub(*cast(z),*cast(x), *cast(y)); +} +void mclBnFr_mul(mclBnFr *z, const mclBnFr *x, const mclBnFr *y) +{ + Fr::mul(*cast(z),*cast(x), *cast(y)); +} +void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y) +{ + Fr::div(*cast(z),*cast(x), *cast(y)); +} + +//////////////////////////////////////////////// +// set zero +void mclBnG1_clear(mclBnG1 *x) +{ + cast(x)->clear(); +} + +int mclBnG1_setStr(mclBnG1 *x, const char *buf, mclSize bufSize, int ioMode) +{ + return setStr(x, buf, bufSize, ioMode); +} +mclSize mclBnG1_deserialize(mclBnG1 *x, const void *buf, mclSize bufSize) +{ + return (mclSize)cast(x)->deserialize(buf, bufSize); +} + +// return 1 if true +int mclBnG1_isValid(const mclBnG1 *x) +{ + return cast(x)->isValid(); +} +int mclBnG1_isEqual(const mclBnG1 *x, const mclBnG1 *y) +{ + return *cast(x) == *cast(y); +} +int mclBnG1_isZero(const mclBnG1 *x) +{ + return cast(x)->isZero(); +} +int mclBnG1_isValidOrder(const mclBnG1 *x) +{ + return cast(x)->isValidOrder(); +} + +int mclBnG1_hashAndMapTo(mclBnG1 *x, const void *buf, mclSize bufSize) +{ + hashAndMapToG1(*cast(x), buf, bufSize); + return 0; +} + +mclSize mclBnG1_getStr(char *buf, mclSize maxBufSize, const mclBnG1 *x, int ioMode) +{ + return cast(x)->getStr(buf, maxBufSize, ioMode); +} + +mclSize mclBnG1_serialize(void *buf, mclSize maxBufSize, const mclBnG1 *x) +{ + return (mclSize)cast(x)->serialize(buf, maxBufSize); +} + +void mclBnG1_neg(mclBnG1 *y, const mclBnG1 *x) +{ + G1::neg(*cast(y), *cast(x)); +} +void mclBnG1_dbl(mclBnG1 *y, const mclBnG1 *x) +{ + G1::dbl(*cast(y), *cast(x)); +} +void mclBnG1_normalize(mclBnG1 *y, const mclBnG1 *x) +{ + G1::normalize(*cast(y), *cast(x)); +} +void mclBnG1_add(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y) +{ + G1::add(*cast(z),*cast(x), *cast(y)); +} +void mclBnG1_sub(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y) +{ + G1::sub(*cast(z),*cast(x), *cast(y)); +} +void mclBnG1_mul(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y) +{ + G1::mul(*cast(z),*cast(x), *cast(y)); +} +void mclBnG1_mulCT(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y) +{ + G1::mulCT(*cast(z),*cast(x), *cast(y)); +} + +//////////////////////////////////////////////// +// set zero +void mclBnG2_clear(mclBnG2 *x) +{ + cast(x)->clear(); +} + +int mclBnG2_setStr(mclBnG2 *x, const char *buf, mclSize bufSize, int ioMode) +{ + return setStr(x, buf, bufSize, ioMode); +} +mclSize mclBnG2_deserialize(mclBnG2 *x, const void *buf, mclSize bufSize) +{ + return (mclSize)cast(x)->deserialize(buf, bufSize); +} + +// return 1 if true +int mclBnG2_isValid(const mclBnG2 *x) +{ + return cast(x)->isValid(); +} +int mclBnG2_isEqual(const mclBnG2 *x, const mclBnG2 *y) +{ + return *cast(x) == *cast(y); +} +int mclBnG2_isZero(const mclBnG2 *x) +{ + return cast(x)->isZero(); +} +int mclBnG2_isValidOrder(const mclBnG2 *x) +{ + return cast(x)->isValidOrder(); +} + +int mclBnG2_hashAndMapTo(mclBnG2 *x, const void *buf, mclSize bufSize) +{ + hashAndMapToG2(*cast(x), buf, bufSize); + return 0; +} + +mclSize mclBnG2_getStr(char *buf, mclSize maxBufSize, const mclBnG2 *x, int ioMode) +{ + return cast(x)->getStr(buf, maxBufSize, ioMode); +} + +mclSize mclBnG2_serialize(void *buf, mclSize maxBufSize, const mclBnG2 *x) +{ + return (mclSize)cast(x)->serialize(buf, maxBufSize); +} + +void mclBnG2_neg(mclBnG2 *y, const mclBnG2 *x) +{ + G2::neg(*cast(y), *cast(x)); +} +void mclBnG2_dbl(mclBnG2 *y, const mclBnG2 *x) +{ + G2::dbl(*cast(y), *cast(x)); +} +void mclBnG2_normalize(mclBnG2 *y, const mclBnG2 *x) +{ + G2::normalize(*cast(y), *cast(x)); +} +void mclBnG2_add(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y) +{ + G2::add(*cast(z),*cast(x), *cast(y)); +} +void mclBnG2_sub(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y) +{ + G2::sub(*cast(z),*cast(x), *cast(y)); +} +void mclBnG2_mul(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y) +{ + G2::mul(*cast(z),*cast(x), *cast(y)); +} +void mclBnG2_mulCT(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y) +{ + G2::mulCT(*cast(z),*cast(x), *cast(y)); +} + +//////////////////////////////////////////////// +// set zero +void mclBnGT_clear(mclBnGT *x) +{ + cast(x)->clear(); +} +void mclBnGT_setInt(mclBnGT *y, mclInt x) +{ + cast(y)->clear(); + *(cast(y)->getFp0()) = x; +} +void mclBnGT_setInt32(mclBnGT *y, int x) +{ + cast(y)->clear(); + *(cast(y)->getFp0()) = x; +} + +int mclBnGT_setStr(mclBnGT *x, const char *buf, mclSize bufSize, int ioMode) +{ + return setStr(x, buf, bufSize, ioMode); +} +mclSize mclBnGT_deserialize(mclBnGT *x, const void *buf, mclSize bufSize) +{ + return (mclSize)cast(x)->deserialize(buf, bufSize); +} + +// return 1 if true +int mclBnGT_isEqual(const mclBnGT *x, const mclBnGT *y) +{ + return *cast(x) == *cast(y); +} +int mclBnGT_isZero(const mclBnGT *x) +{ + return cast(x)->isZero(); +} +int mclBnGT_isOne(const mclBnGT *x) +{ + return cast(x)->isOne(); +} + +mclSize mclBnGT_getStr(char *buf, mclSize maxBufSize, const mclBnGT *x, int ioMode) +{ + return cast(x)->getStr(buf, maxBufSize, ioMode); +} + +mclSize mclBnGT_serialize(void *buf, mclSize maxBufSize, const mclBnGT *x) +{ + return (mclSize)cast(x)->serialize(buf, maxBufSize); +} + +void mclBnGT_neg(mclBnGT *y, const mclBnGT *x) +{ + Fp12::neg(*cast(y), *cast(x)); +} +void mclBnGT_inv(mclBnGT *y, const mclBnGT *x) +{ + Fp12::inv(*cast(y), *cast(x)); +} +void mclBnGT_sqr(mclBnGT *y, const mclBnGT *x) +{ + Fp12::sqr(*cast(y), *cast(x)); +} +void mclBnGT_add(mclBnGT *z, const mclBnGT *x, const mclBnGT *y) +{ + Fp12::add(*cast(z),*cast(x), *cast(y)); +} +void mclBnGT_sub(mclBnGT *z, const mclBnGT *x, const mclBnGT *y) +{ + Fp12::sub(*cast(z),*cast(x), *cast(y)); +} +void mclBnGT_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y) +{ + Fp12::mul(*cast(z),*cast(x), *cast(y)); +} +void mclBnGT_div(mclBnGT *z, const mclBnGT *x, const mclBnGT *y) +{ + Fp12::div(*cast(z),*cast(x), *cast(y)); +} + +void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y) +{ + Fp12::pow(*cast(z), *cast(x), *cast(y)); +} +void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y) +{ + Fp12::powGeneric(*cast(z), *cast(x), *cast(y)); +} + +void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y) +{ + pairing(*cast(z), *cast(x), *cast(y)); +} +void mclBn_finalExp(mclBnGT *y, const mclBnGT *x) +{ + finalExp(*cast(y), *cast(x)); +} +void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y) +{ + millerLoop(*cast(z), *cast(x), *cast(y)); +} +int mclBn_getUint64NumToPrecompute(void) +{ + return int(BN::param.precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t)); +} + +void mclBn_precomputeG2(uint64_t *Qbuf, const mclBnG2 *Q) +{ + precomputeG2(cast(Qbuf), *cast(Q)); +} + +void mclBn_precomputedMillerLoop(mclBnGT *f, const mclBnG1 *P, const uint64_t *Qbuf) +{ + precomputedMillerLoop(*cast(f), *cast(P), cast(Qbuf)); +} + +void mclBn_precomputedMillerLoop2(mclBnGT *f, const mclBnG1 *P1, const uint64_t *Q1buf, const mclBnG1 *P2, const uint64_t *Q2buf) +{ + precomputedMillerLoop2(*cast(f), *cast(P1), cast(Q1buf), *cast(P2), cast(Q2buf)); +} + +void mclBn_precomputedMillerLoop2mixed(mclBnGT *f, const mclBnG1 *P1, const mclBnG2 *Q1, const mclBnG1 *P2, const uint64_t *Q2buf) +{ + precomputedMillerLoop2mixed(*cast(f), *cast(P1), *cast(Q1), *cast(P2), cast(Q2buf)); +} + +int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, mclSize k) +{ + bool b; + mcl::LagrangeInterpolation(&b, *cast(out), cast(xVec), cast(yVec), k); + return b ? 0 : -1; +} +int mclBn_G1LagrangeInterpolation(mclBnG1 *out, const mclBnFr *xVec, const mclBnG1 *yVec, mclSize k) +{ + bool b; + mcl::LagrangeInterpolation(&b, *cast(out), cast(xVec), cast(yVec), k); + return b ? 0 : -1; +} +int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVec, const mclBnG2 *yVec, mclSize k) +{ + bool b; + mcl::LagrangeInterpolation(&b, *cast(out), cast(xVec), cast(yVec), k); + return b ? 0 : -1; +} +int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, mclSize cSize, const mclBnFr *x) +{ + bool b; + mcl::evaluatePolynomial(&b, *cast(out), cast(cVec), cSize, *cast(x)); + return b ? 0 : -1; +} +int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, mclSize cSize, const mclBnFr *x) +{ + bool b; + mcl::evaluatePolynomial(&b, *cast(out), cast(cVec), cSize, *cast(x)); + return b ? 0 : -1; +} +int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, mclSize cSize, const mclBnFr *x) +{ + bool b; + mcl::evaluatePolynomial(&b, *cast(out), cast(cVec), cSize, *cast(x)); + return b ? 0 : -1; +} + +void mclBn_verifyOrderG1(int doVerify) +{ + verifyOrderG1(doVerify != 0); +} + +void mclBn_verifyOrderG2(int doVerify) +{ + verifyOrderG2(doVerify != 0); +} + +mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode) +{ + return cast(x)->getStr(buf, maxBufSize, ioMode); +} +int mclBnFp_setStr(mclBnFp *x, const char *buf, mclSize bufSize, int ioMode) +{ + return setStr(x, buf, bufSize, ioMode); +} +mclSize mclBnFp_deserialize(mclBnFp *x, const void *buf, mclSize bufSize) +{ + return (mclSize)cast(x)->deserialize(buf, bufSize); +} + +mclSize mclBnFp_serialize(void *buf, mclSize maxBufSize, const mclBnFp *x) +{ + return (mclSize)cast(x)->serialize(buf, maxBufSize); +} + +void mclBnFp_clear(mclBnFp *x) +{ + cast(x)->clear(); +} + +int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize) +{ + cast(x)->setArrayMask((const char *)buf, bufSize); + return 0; +} + +int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize) +{ + bool b; + cast(x)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod); + return b ? 0 : -1; +} +int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y) +{ + return *cast(x) == *cast(y); +} + +int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize) +{ + cast(x)->setHashOf(buf, bufSize); + return 0; +} + +int mclBnFp_mapToG1(mclBnG1 *y, const mclBnFp *x) +{ + bool b; + mapToG1(&b, *cast(y), *cast(x)); + return b ? 0 : -1; +} + +mclSize mclBnFp2_deserialize(mclBnFp2 *x, const void *buf, mclSize bufSize) +{ + return (mclSize)cast(x)->deserialize(buf, bufSize); +} + +mclSize mclBnFp2_serialize(void *buf, mclSize maxBufSize, const mclBnFp2 *x) +{ + return (mclSize)cast(x)->serialize(buf, maxBufSize); +} + +void mclBnFp2_clear(mclBnFp2 *x) +{ + cast(x)->clear(); +} + +int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y) +{ + return *cast(x) == *cast(y); +} + +int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x) +{ + bool b; + mapToG2(&b, *cast(y), *cast(x)); + return b ? 0 : -1; +} + +int mclBnG1_getBasePoint(mclBnG1 *x) +{ + *cast(x) = mcl::bn::getG1basePoint(); + return 0; +} + diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/lagrange.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/lagrange.hpp index 7c0218896..18e0597ec 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/lagrange.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/lagrange.hpp @@ -15,14 +15,19 @@ namespace mcl { template void LagrangeInterpolation(bool *pb, G& out, const F *S, const G *vec, size_t k) { + if (k == 0) { + *pb = false; + return; + } + if (k == 1) { + out = vec[0]; + *pb = true; + return; + } /* delta_{i,S}(0) = prod_{j != i} S[j] / (S[j] - S[i]) = a / b where a = prod S[j], b = S[i] * prod_{j != i} (S[j] - S[i]) */ - if (k < 2) { - *pb = false; - return; - } F a = S[0]; for (size_t i = 1; i < k; i++) { a *= S[i]; @@ -58,15 +63,20 @@ void LagrangeInterpolation(bool *pb, G& out, const F *S, const G *vec, size_t k) /* out = f(x) = c[0] + c[1] * x + c[2] * x^2 + ... + c[cSize - 1] * x^(cSize - 1) - @retval 0 if succeed else -1 + @retval 0 if succeed else -1 (if cSize == 0) */ template void evaluatePolynomial(bool *pb, G& out, const G *c, size_t cSize, const T& x) { - if (cSize < 2) { + if (cSize == 0) { *pb = false; return; } + if (cSize == 1) { + out = c[0]; + *pb = true; + return; + } G y = c[cSize - 1]; for (int i = (int)cSize - 2; i >= 0; i--) { G::mul(y, y, x); diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/op.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/op.hpp index d108d1a55..36d37035e 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/op.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/op.hpp @@ -26,6 +26,8 @@ namespace mcl { +static const int version = 0x092; /* 0xABC = A.BC */ + /* specifies available string format mode for X::setIoMode() // for Fp, Fp2, Fp6, Fp12 @@ -59,7 +61,7 @@ namespace mcl { IoArray array of Unit(fixed size = Fp::getByteSize()) IoArrayRaw - array of Unit(fixed size = Fp::getByteSize()) without Montgomery convresion + array of Unit(fixed size = Fp::getByteSize()) without Montgomery conversion // for Ec::setIoMode() IoEcAffine(default) @@ -127,6 +129,15 @@ typedef int (*int2u)(Unit*, const Unit*); typedef Unit (*u1uII)(Unit*, Unit, Unit); typedef Unit (*u3u)(Unit*, const Unit*, const Unit*); +/* + disable -Wcast-function-type + the number of arguments of some JIT functions is smaller than that of T +*/ +template +T func_ptr_cast(S func) +{ + return reinterpret_cast(reinterpret_cast(func)); +} struct Block { const Unit *p; // pointer to original FpT.v_ size_t n; @@ -152,7 +163,8 @@ enum PrimeMode { enum MaskMode { NoMask = 0, // throw if greater or equal SmallMask = 1, // 1-bit smaller mask if greater or equal - MaskAndMod = 2 // mask and substract if greater or equal + MaskAndMod = 2, // mask and substract if greater or equal + Mod = 3 // mod p }; struct Op { @@ -165,6 +177,7 @@ struct Op { mpz_class mp; uint32_t pmod4; mcl::SquareRoot sq; + mcl::Modp modp; Unit half[maxUnitSize]; // (p + 1) / 2 Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery) /* @@ -193,8 +206,6 @@ struct Op { void2u fp2_sqrA_; void3u fpDbl_addA_; void3u fpDbl_subA_; - void3u fpDbl_addPreA_; - void3u fpDbl_subPreA_; void3u fpDbl_mulPreA_; void2u fpDbl_sqrPreA_; void2u fpDbl_modA_; @@ -282,8 +293,6 @@ struct Op { fp2_sqrA_ = 0; fpDbl_addA_ = 0; fpDbl_subA_ = 0; - fpDbl_addPreA_ = 0; - fpDbl_subPreA_ = 0; fpDbl_mulPreA_ = 0; fpDbl_sqrPreA_ = 0; fpDbl_modA_ = 0; @@ -345,8 +354,7 @@ struct Op { */ fp_mul(y, x, R2, p); } - bool init(const mpz_class& p, size_t maxBitSize, Mode mode, size_t mclMaxBitSize = MCL_MAX_BIT_SIZE); - void initFp2(int xi_a); + bool init(const mpz_class& p, size_t maxBitSize, int xi_a, Mode mode, size_t mclMaxBitSize = MCL_MAX_BIT_SIZE); #ifdef MCL_USE_XBYAK static FpGenerator* createFpGenerator(); static void destroyFpGenerator(FpGenerator *fg); diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/randgen.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/randgen.hpp index 4bfb30b03..30502fc10 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/randgen.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/randgen.hpp @@ -15,10 +15,16 @@ namespace mcl { struct RandomGeneratorJS { - void read(void *buf, size_t bufSize) + void read(bool *pb, void *buf, uint32_t byteSize) { + // cf. https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues + if (byteSize > 65536) { + *pb = false; + return; + } // use crypto.getRandomValues - EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, bufSize); + EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, byteSize); + *pb = true; } }; } // mcl @@ -38,28 +44,33 @@ namespace mcl { namespace fp { namespace local { template -void readWrapper(void *self, void *buf, uint32_t bufSize) +uint32_t readWrapper(void *self, void *buf, uint32_t byteSize) { - reinterpret_cast(self)->read((uint8_t*)buf, bufSize); + bool b; + reinterpret_cast(self)->read(&b, (uint8_t*)buf, byteSize); + if (b) return byteSize; + return 0; } #if 0 // #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 template<> -inline void readWrapper(void *self, void *buf, uint32_t bufSize) +inline uint32_t readWrapper(void *self, void *buf, uint32_t byteSize) { + const uint32_t keep = byteSize; std::random_device& rg = *reinterpret_cast(self); uint8_t *p = reinterpret_cast(buf); uint32_t v; - while (bufSize >= 4) { + while (byteSize >= 4) { v = rg(); memcpy(p, &v, 4); p += 4; - bufSize -= 4; + byteSize -= 4; } - if (bufSize > 0) { + if (byteSize > 0) { v = rg(); - memcpy(p, &v, bufSize); + memcpy(p, &v, byteSize); } + return keep; } #endif } // local @@ -67,7 +78,7 @@ inline void readWrapper(void *self, void *buf, uint32_t bufS wrapper of cryptographically secure pseudo random number generator */ class RandGen { - typedef void (*readFuncType)(void *self, void *buf, uint32_t bufSize); + typedef uint32_t (*readFuncType)(void *self, void *buf, uint32_t byteSize); void *self_; readFuncType readFunc_; public: @@ -87,16 +98,17 @@ public: , readFunc_(local::readWrapper) { } - void read(void *out, size_t byteSize) + void read(bool *pb, void *out, size_t byteSize) { - readFunc_(self_, out, static_cast(byteSize)); + uint32_t size = readFunc_(self_, out, static_cast(byteSize)); + *pb = size == byteSize; } #ifdef MCL_DONT_USE_CSPRNG bool isZero() const { return false; } /* return false to avoid copying default rg */ #else bool isZero() const { return self_ == 0 && readFunc_ == 0; } #endif - static RandGen& get() + static RandGen& getDefaultRandGen() { #ifdef MCL_DONT_USE_CSPRNG static RandGen wrg; @@ -109,14 +121,32 @@ public: #endif return wrg; } + static RandGen& get() + { + static RandGen wrg(getDefaultRandGen()); + return wrg; + } /* rg must be thread safe - rg.read(void *buf, size_t bufSize); + rg.read(void *buf, size_t byteSize); */ static void setRandGen(const RandGen& rg) { get() = rg; } + /* + set rand function + if self and readFunc are NULL then set default rand function + */ + static void setRandFunc(void *self, readFuncType readFunc) + { + if (self == 0 && readFunc == 0) { + setRandGen(getDefaultRandGen()); + } else { + RandGen rg(self, readFunc); + setRandGen(rg); + } + } }; } } // mcl::fp diff --git a/vendor/github.com/dexon-foundation/mcl/include/mcl/vint.hpp b/vendor/github.com/dexon-foundation/mcl/include/mcl/vint.hpp index 32a51bb64..b087688c3 100644 --- a/vendor/github.com/dexon-foundation/mcl/include/mcl/vint.hpp +++ b/vendor/github.com/dexon-foundation/mcl/include/mcl/vint.hpp @@ -568,6 +568,7 @@ void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn) yn = getRealSize(y, yn); if (x == y) { assert(xn == yn); + x_is_y: clearN(r, rn); if (q) { q[0] = 1; @@ -579,6 +580,7 @@ void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn) /* if y > x then q = 0 and r = x */ + q_is_zero: copyN(r, x, xn); clearN(r + xn, rn - xn); if (q) clearN(q, qn); @@ -598,11 +600,61 @@ void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn) clearN(r + 1, rn - 1); return; } + const size_t yTopBit = cybozu::bsr(y[yn - 1]); assert(yn >= 2); + if (xn == yn) { + const size_t xTopBit = cybozu::bsr(x[xn - 1]); + if (xTopBit < yTopBit) goto q_is_zero; + if (yTopBit == xTopBit) { + int ret = compareNM(x, xn, y, yn); + if (ret == 0) goto x_is_y; + if (ret < 0) goto q_is_zero; + if (r) { + subN(r, x, y, yn); + } + if (q) { + q[0] = 1; + clearN(q + 1, qn - 1); + } + return; + } + assert(xTopBit > yTopBit); + // fast reduction for larger than fullbit-3 size p + if (yTopBit >= sizeof(T) * 8 - 4) { + T *xx = (T*)CYBOZU_ALLOCA(sizeof(T) * xn); + T qv = 0; + if (yTopBit == sizeof(T) * 8 - 2) { + copyN(xx, x, xn); + } else { + qv = x[xn - 1] >> (yTopBit + 1); + mulu1(xx, y, yn, qv); + subN(xx, x, xx, xn); + xn = getRealSize(xx, xn); + } + for (;;) { + T ret = subN(xx, xx, y, yn); + if (ret) { + addN(xx, xx, y, yn); + break; + } + qv++; + xn = getRealSize(xx, xn); + } + if (r) { + copyN(r, xx, xn); + clearN(r + xn, rn - xn); + } + if (q) { + q[0] = qv; + clearN(q + 1, qn - 1); + } + return; + } + } /* bitwise left shift x and y to adjust MSB of y[yn - 1] = 1 */ - const size_t shift = sizeof(T) * 8 - 1 - cybozu::bsr(y[yn - 1]); + const size_t shift = sizeof(T) * 8 - 1 - yTopBit; T *xx = (T*)CYBOZU_ALLOCA(sizeof(T) * (xn + 1)); const T *yy; if (shift) { @@ -1124,8 +1176,15 @@ public: size_t unitSize = (sizeof(S) * size + sizeof(Unit) - 1) / sizeof(Unit); buf_.alloc(pb, unitSize); if (!*pb) return; - buf_[unitSize - 1] = 0; - memcpy(&buf_[0], x, sizeof(S) * size); + char *dst = (char *)&buf_[0]; + const char *src = (const char *)x; + size_t i = 0; + for (; i < sizeof(S) * size; i++) { + dst[i] = src[i]; + } + for (; i < sizeof(Unit) * unitSize; i++) { + dst[i] = 0; + } trim(unitSize); } /* @@ -1138,7 +1197,8 @@ public: size_t n = max.size(); buf_.alloc(pb, n); if (!*pb) return; - rg.read(&buf_[0], n * sizeof(buf_[0])); + rg.read(pb, &buf_[0], n * sizeof(buf_[0])); + if (!*pb) return; trim(n); *this %= max; } @@ -1231,7 +1291,8 @@ public: */ void setStr(bool *pb, const char *str, int base = 0) { - const size_t maxN = MCL_MAX_BIT_SIZE / (sizeof(MCL_SIZEOF_UNIT) * 8); + // allow twice size of MCL_MAX_BIT_SIZE because of multiplication + const size_t maxN = (MCL_MAX_BIT_SIZE * 2 + unitBitSize - 1) / unitBitSize; buf_.alloc(pb, maxN); if (!*pb) return; *pb = false; diff --git a/vendor/github.com/dexon-foundation/mcl/misc/bench.txt b/vendor/github.com/dexon-foundation/mcl/misc/bench.txt new file mode 100644 index 000000000..3e18e6b44 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/bench.txt @@ -0,0 +1,21 @@ +Core i7-7700 @ 3.6GHz + BN254 BLS12_381 +G1::mul 185.863Kclk 360.723Kclk +G1::add 812.01 clk 1.540Kclk +G1::dbl 837.24 clk 1.977Kclk +G2::mul 340.125Kclk 642.457Kclk +G2::add 2.233Kclk 4.368Kclk +G2::dbl 2.134Kclk 4.088Kclk +GT::pow 615.052Kclk 1.055Mclk +G1::setStr chk 1.546Kclk 534.376Kclk +G1::setStr 1.592Kclk 4.000Kclk +G2::setStr chk 609.195Kclk 1.402Mclk +G2::setStr 5.444Kclk 8.282Kclk +hashAndMapToG1 26.997Kclk 336.207Kclk +hashAndMapToG2 212.800Kclk 775.072Kclk +pairing 909.076Kclk 2.367Mclk +millerLoop 549.957Kclk 983.935Kclk +finalExp 375.203Kclk 1.404Mclk +precomputeG2 126.000Kclk 236.912Kclk +precomputedML 427.272Kclk 729.234Kclk + diff --git a/vendor/github.com/dexon-foundation/mcl/misc/karatsuba.cpp b/vendor/github.com/dexon-foundation/mcl/misc/karatsuba.cpp new file mode 100644 index 000000000..7c150c6e3 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/karatsuba.cpp @@ -0,0 +1,75 @@ +/* + sudo cpufreq-set -c 0 -g performance + mycl karatsuba.cpp -DMCL_USE_LLVM=1 ../lib/libmcl.a && ./a.out +*/ +#include +#include +#include +#include "../src/proto.hpp" +#include "../src/low_func.hpp" +#ifdef MCL_USE_LLVM +#include "../src/low_func_llvm.hpp" +#endif +#include +#include + +typedef mcl::FpT<> Fp; + +using namespace mcl::fp; + +void dump(const Unit *x, size_t N) +{ + for (size_t i = 0; i < N; i++) { + printf("%016llx ", (long long)x[N - 1 - i]); + } + printf("\n"); +} + +void gggKara(uint64_t *z, const uint64_t *x, const uint64_t *) +{ + SqrPre<8, Gtag>::f(z, x); +} +void gggLLVM(uint64_t *z, const uint64_t *x, const uint64_t *y) +{ + MulPre<8, Ltag>::f(z, x, y); +} + +template +void benchKaratsuba() +{ + cybozu::XorShift rg; + printf("N=%d\n", (int)N); + Unit z[N * 2]; + rg.read(z, N); + CYBOZU_BENCH("g:mulPre ", (MulPreCore::f), z, z, z); +// CYBOZU_BENCH("g:mulKara", (MulPre::karatsuba), z, z, z); + CYBOZU_BENCH("g:sqrPre ", (SqrPreCore::f), z, z); +// CYBOZU_BENCH("g:sqrKara", (SqrPre::karatsuba), z, z); + +#ifdef MCL_USE_LLVM + CYBOZU_BENCH("l:mulPre ", (MulPreCore::f), z, z, z); + CYBOZU_BENCH("l:sqrPre ", (SqrPreCore::f), z, z); + CYBOZU_BENCH("l:mulKara", (MulPre::karatsuba), z, z, z); + CYBOZU_BENCH("l:sqrKara", (SqrPre::karatsuba), z, z); +#endif +} + +CYBOZU_TEST_AUTO(karatsuba) +{ + benchKaratsuba<4>(); + benchKaratsuba<6>(); + benchKaratsuba<8>(); +#if MCL_MAX_BIT_SIZE >= 640 + benchKaratsuba<10>(); +#endif +#if MCL_MAX_BIT_SIZE >= 768 + benchKaratsuba<12>(); +#endif +#if MCL_MAX_BIT_SIZE >= 896 + benchKaratsuba<14>(); +#endif +#if MCL_MAX_BIT_SIZE >= 1024 + benchKaratsuba<16>(); +#endif +} + diff --git a/vendor/github.com/dexon-foundation/mcl/misc/mul.cpp b/vendor/github.com/dexon-foundation/mcl/misc/mul.cpp new file mode 100644 index 000000000..146ac33a9 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/mul.cpp @@ -0,0 +1,58 @@ +/* + sudo cpufreq-set -c 0 -g performance + mycl mul.cpp -DMCL_USE_LLVM=1 ../lib/libmcl.a && ./a.out +*/ +#include +#include +#include +#include +#include + +typedef mcl::FpT<> Fp; + +using namespace mcl::fp; + +void dump(const Unit *x, size_t N) +{ + for (size_t i = 0; i < N; i++) { + printf("%016llx ", (long long)x[N - 1 - i]); + } + printf("\n"); +} + +CYBOZU_TEST_AUTO(mulPre) +{ + cybozu::XorShift rg; + const char *pTbl[] = { + "0x2523648240000001ba344d80000000086121000000000013a700000000000013", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff", + "6701817056313037086248947066310538444882082605308124576230408038843357549886356779857393369967010764802541005796711440355753503701056323603", // 462 bit + "4562440617622195218641171605700291324893228507248559930579192517899275167208677386505912811317371399778642309573594407310688704721375437998252661319722214188251994674360264950082874192246603471", // 640 bit + "1552518092300708935148979488462502555256886017116696611139052038026050952686376886330878408828646477950487730697131073206171580044114814391444287275041181139204454976020849905550265285631598444825262999193716468750892846853816057031", // 768 bit + }; + const size_t N = 16; + const Mode modeTbl[] = { + FP_GMP_MONT, +#ifdef MCL_USE_LLVM + FP_LLVM_MONT, +#endif + }; + for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(modeTbl); j++) { + Mode mode = modeTbl[j]; + printf("%s\n", ModeToStr(mode)); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(pTbl); i++) { + const char *p = pTbl[i]; + Fp::init(p, mode); + printf("bitSize=%d\n", (int)Fp::getBitSize()); + const Op& op = Fp::getOp(); + Unit x[N], y[N * 2]; + rg.read(x, N); + rg.read(y, N * 2); + CYBOZU_BENCH("mul ", op.fp_mul, y, y, x, op.p); + CYBOZU_BENCH("sqr ", op.fp_sqr, y, y, op.p); + CYBOZU_BENCH("mulPre", op.fpDbl_mulPre, y, y, y); + CYBOZU_BENCH("sqrPre", op.fpDbl_sqrPre, y, y); + CYBOZU_BENCH("mod ", op.fpDbl_mod, y, y, op.p); + } + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/misc/precompute.cpp b/vendor/github.com/dexon-foundation/mcl/misc/precompute.cpp new file mode 100644 index 000000000..63cdd663b --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/precompute.cpp @@ -0,0 +1,30 @@ +#include +#include + +using namespace mcl::bn; + +int main() +{ + initPairing(mcl::BN254); + G2 Q; + mapToG2(Q, 1); + std::vector Qcoeff; + precomputeG2(Qcoeff, Q); + puts("#if MCL_SIZEOF_UNIT == 8"); + puts("static const uint64_t QcoeffTblBN254[][6][4] = {"); + for (size_t i = 0; i < Qcoeff.size(); i++) { + const Fp6& x6 = Qcoeff[i]; + puts("\t{"); + for (size_t j = 0; j < 6; j++) { + printf("\t\t{"); + const Fp& x = x6.getFp0()[j]; + for (size_t k = 0; k < 4; k++) { + printf("0x%016llxull,", (unsigned long long)x.getUnit()[k]); + } + puts("},"); + } + puts("\t},"); + } + puts("};"); + puts("#endif"); +} diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/bench.sh b/vendor/github.com/dexon-foundation/mcl/misc/she/bench.sh new file mode 100644 index 000000000..ced87b4db --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/she/bench.sh @@ -0,0 +1,6 @@ +for i in 4 6 8 +do echo $i +touch test/she_test.cpp +make bin/she_test.exe CFLAGS_USER=-DMCLBN_FP_UNIT_SIZE=$i +bin/she_test.exe > misc/she/bench$i.txt +done diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/bench4.txt b/vendor/github.com/dexon-foundation/mcl/misc/she/bench4.txt new file mode 100644 index 000000000..99b2593c4 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/she/bench4.txt @@ -0,0 +1,99 @@ +ctest:module=log +CurveFp254BNb +ctest:module=HashTable +ctest:module=GTHashTable +ctest:module=enc_dec +ctest:module=add_sub_mul +ctest:module=add_mul_add_sub +ctest:module=innerProduct +ctest:module=io +ctest:module=bench +enc 673.772Kclk +add 8.021Kclk +mul 4.042Mclk +dec 2.194Mclk +add after mul 20.693Kclk +ctest:module=saveHash +ctest:module=hashBench +Kclk +m=000fffff decG1 1.83e+02 +m=001fffff decG1 1.83e+02 +m=003fffff decG1 1.83e+02 +m=007fffff decG1 1.90e+02 +m=00ffffff decG1 2.04e+02 +m=01ffffff decG1 2.66e+02 +m=03ffffff decG1 4.17e+02 +m=07ffffff decG1 7.15e+02 +m=0fffffff decG1 1.29e+03 +m=1fffffff decG1 2.43e+03 +m=3fffffff decG1 4.70e+03 +m=7fffffff decG1 9.28e+03 + +m=000fffff decG2 4.09e+02 +m=001fffff decG2 4.11e+02 +m=003fffff decG2 4.09e+02 +m=007fffff decG2 4.23e+02 +m=00ffffff decG2 4.48e+02 +m=01ffffff decG2 5.21e+02 +m=03ffffff decG2 7.25e+02 +m=07ffffff decG2 1.11e+03 +m=0fffffff decG2 1.87e+03 +m=1fffffff decG2 3.36e+03 +m=3fffffff decG2 6.38e+03 +m=7fffffff decG2 1.24e+04 + +m=000fffff decGT 2.20e+03 +m=001fffff decGT 2.21e+03 +m=003fffff decGT 2.20e+03 +m=007fffff decGT 2.21e+03 +m=00ffffff decGT 2.23e+03 +m=01ffffff decGT 2.28e+03 +m=03ffffff decGT 2.37e+03 +m=07ffffff decGT 2.56e+03 +m=0fffffff decGT 2.94e+03 +m=1fffffff decGT 3.78e+03 +m=3fffffff decGT 5.41e+03 +m=7fffffff decGT 8.69e+03 +large m +G1::add 7.36e-01 +G1::mul 1.92e+02 +G2::add 3.51e+00 +G2::mul 4.03e+02 +GT::mul 5.47e+00 +GT::pow 7.27e+02 +G1window 1.92e+01 +G2window 6.15e+01 +GTwindow 1.35e+02 +miller 6.69e+02 +finalExp 4.23e+02 +precomML 5.16e+02 +small m = 2097151 +G1::mul 4.52e+01 +G2::mul 1.01e+02 +GT::pow 1.33e+02 +G1window 1.55e+00 +G2window 5.02e+00 +GTwindow 1.55e+01 +encG1 2.10e+02 +encG2 4.82e+02 +encGT 2.47e+03 +encG1pre 5.31e+01 +encG2pre 1.47e+02 +encGTpre 6.01e+02 +decG1 1.84e+02 +decG2 3.96e+02 +degGT 2.20e+03 +mul 4.07e+03 +addG1 1.56e+00 +addG2 4.72e+00 +addGT 2.12e+01 +reRandG1 2.10e+02 +reRandG2 4.71e+02 +reRandGT 2.49e+03 +reRandG1pre 5.16e+01 +reRandG2pre 1.44e+02 +reRandGTpre 6.10e+02 +mulG1 9.03e+01 +mulG2 2.03e+02 +mulGT 5.34e+02 +ctest:name=she_test, module=11, total=2879, ok=2879, ng=0, exception=0 diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/bench6.txt b/vendor/github.com/dexon-foundation/mcl/misc/she/bench6.txt new file mode 100644 index 000000000..863f7129a --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/she/bench6.txt @@ -0,0 +1,99 @@ +ctest:module=log +CurveFp382_1 +ctest:module=HashTable +ctest:module=GTHashTable +ctest:module=enc_dec +ctest:module=add_sub_mul +ctest:module=add_mul_add_sub +ctest:module=innerProduct +ctest:module=io +ctest:module=bench +enc 2.077Mclk +add 17.694Kclk +mul 13.408Mclk +dec 5.854Mclk +add after mul 41.570Kclk +ctest:module=saveHash +ctest:module=hashBench +Kclk +m=000fffff decG1 5.34e+02 +m=001fffff decG1 5.36e+02 +m=003fffff decG1 5.34e+02 +m=007fffff decG1 5.48e+02 +m=00ffffff decG1 5.87e+02 +m=01ffffff decG1 7.11e+02 +m=03ffffff decG1 9.53e+02 +m=07ffffff decG1 1.41e+03 +m=0fffffff decG1 2.30e+03 +m=1fffffff decG1 4.11e+03 +m=3fffffff decG1 7.71e+03 +m=7fffffff decG1 1.50e+04 + +m=000fffff decG2 1.27e+03 +m=001fffff decG2 1.27e+03 +m=003fffff decG2 1.27e+03 +m=007fffff decG2 1.30e+03 +m=00ffffff decG2 1.35e+03 +m=01ffffff decG2 1.53e+03 +m=03ffffff decG2 1.88e+03 +m=07ffffff decG2 2.55e+03 +m=0fffffff decG2 3.87e+03 +m=1fffffff decG2 6.53e+03 +m=3fffffff decG2 1.18e+04 +m=7fffffff decG2 2.25e+04 + +m=000fffff decGT 6.01e+03 +m=001fffff decGT 6.03e+03 +m=003fffff decGT 6.01e+03 +m=007fffff decGT 6.04e+03 +m=00ffffff decGT 6.08e+03 +m=01ffffff decGT 6.17e+03 +m=03ffffff decGT 6.39e+03 +m=07ffffff decGT 6.71e+03 +m=0fffffff decGT 7.44e+03 +m=1fffffff decGT 8.95e+03 +m=3fffffff decGT 1.20e+04 +m=7fffffff decGT 1.80e+04 +large m +G1::add 1.48e+00 +G1::mul 5.44e+02 +G2::add 6.91e+00 +G2::mul 1.28e+03 +GT::mul 1.04e+01 +GT::pow 2.04e+03 +G1window 5.57e+01 +G2window 2.04e+02 +GTwindow 4.03e+02 +miller 2.09e+03 +finalExp 1.50e+03 +precomML 1.63e+03 +small m = 2097151 +G1::mul 8.29e+01 +G2::mul 2.05e+02 +GT::pow 2.66e+02 +G1window 3.18e+00 +G2window 1.14e+01 +GTwindow 3.19e+01 +encG1 6.01e+02 +encG2 1.49e+03 +encGT 7.66e+03 +encG1pre 1.41e+02 +encG2pre 4.71e+02 +encGTpre 1.76e+03 +decG1 5.37e+02 +decG2 1.27e+03 +degGT 6.02e+03 +mul 1.34e+04 +addG1 3.07e+00 +addG2 1.02e+01 +addGT 4.18e+01 +reRandG1 5.99e+02 +reRandG2 1.49e+03 +reRandGT 7.69e+03 +reRandG1pre 1.40e+02 +reRandG2pre 4.68e+02 +reRandGTpre 1.75e+03 +mulG1 1.65e+02 +mulG2 4.14e+02 +mulGT 1.06e+03 +ctest:name=she_test, module=11, total=2879, ok=2879, ng=0, exception=0 diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/bench8.txt b/vendor/github.com/dexon-foundation/mcl/misc/she/bench8.txt new file mode 100644 index 000000000..f8fe8fd75 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/she/bench8.txt @@ -0,0 +1,99 @@ +ctest:module=log +CurveFp462 +ctest:module=HashTable +ctest:module=GTHashTable +ctest:module=enc_dec +ctest:module=add_sub_mul +ctest:module=add_mul_add_sub +ctest:module=innerProduct +ctest:module=io +ctest:module=bench +enc 5.095Mclk +add 36.280Kclk +mul 30.163Mclk +dec 12.974Mclk +add after mul 76.646Kclk +ctest:module=saveHash +ctest:module=hashBench +Kclk +m=000fffff decG1 1.44e+03 +m=001fffff decG1 1.45e+03 +m=003fffff decG1 1.45e+03 +m=007fffff decG1 1.47e+03 +m=00ffffff decG1 1.54e+03 +m=01ffffff decG1 1.70e+03 +m=03ffffff decG1 2.03e+03 +m=07ffffff decG1 2.64e+03 +m=0fffffff decG1 3.88e+03 +m=1fffffff decG1 6.32e+03 +m=3fffffff decG1 1.12e+04 +m=7fffffff decG1 2.11e+04 + +m=000fffff decG2 2.99e+03 +m=001fffff decG2 3.01e+03 +m=003fffff decG2 2.99e+03 +m=007fffff decG2 3.05e+03 +m=00ffffff decG2 3.15e+03 +m=01ffffff decG2 3.41e+03 +m=03ffffff decG2 3.93e+03 +m=07ffffff decG2 4.95e+03 +m=0fffffff decG2 6.97e+03 +m=1fffffff decG2 1.10e+04 +m=3fffffff decG2 1.91e+04 +m=7fffffff decG2 3.54e+04 + +m=000fffff decGT 1.31e+04 +m=001fffff decGT 1.31e+04 +m=003fffff decGT 1.31e+04 +m=007fffff decGT 1.31e+04 +m=00ffffff decGT 1.32e+04 +m=01ffffff decGT 1.33e+04 +m=03ffffff decGT 1.36e+04 +m=07ffffff decGT 1.43e+04 +m=0fffffff decGT 1.56e+04 +m=1fffffff decGT 1.82e+04 +m=3fffffff decGT 2.34e+04 +m=7fffffff decGT 3.39e+04 +large m +G1::add 3.40e+00 +G1::mul 1.41e+03 +G2::add 1.38e+01 +G2::mul 2.93e+03 +GT::mul 1.94e+01 +GT::pow 4.30e+03 +G1window 1.59e+02 +G2window 4.89e+02 +GTwindow 8.96e+02 +miller 4.99e+03 +finalExp 3.26e+03 +precomML 3.71e+03 +small m = 2097151 +G1::mul 1.53e+02 +G2::mul 3.85e+02 +GT::pow 4.88e+02 +G1window 6.96e+00 +G2window 2.17e+01 +GTwindow 5.83e+01 +encG1 1.62e+03 +encG2 3.48e+03 +encGT 1.79e+04 +encG1pre 3.67e+02 +encG2pre 1.09e+03 +encGTpre 3.88e+03 +decG1 1.45e+03 +decG2 3.02e+03 +degGT 1.31e+04 +mul 3.02e+04 +addG1 7.08e+00 +addG2 2.03e+01 +addGT 7.68e+01 +reRandG1 1.63e+03 +reRandG2 3.48e+03 +reRandGT 1.79e+04 +reRandG1pre 3.65e+02 +reRandG2pre 1.08e+03 +reRandGTpre 3.79e+03 +mulG1 3.08e+02 +mulG2 7.65e+02 +mulGT 1.95e+03 +ctest:name=she_test, module=11, total=2879, ok=2879, ng=0, exception=0 diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/nizkp.pdf b/vendor/github.com/dexon-foundation/mcl/misc/she/nizkp.pdf new file mode 100644 index 000000000..7e61b5a64 Binary files /dev/null and b/vendor/github.com/dexon-foundation/mcl/misc/she/nizkp.pdf differ diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/she-api-ja.md b/vendor/github.com/dexon-foundation/mcl/misc/she/she-api-ja.md new file mode 100644 index 000000000..850f11ff3 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/she/she-api-ja.md @@ -0,0 +1,314 @@ +# L2準同型暗号ライブラリshe + +# 概要 +she(somewhat homomorphic encryption)はペアリングベースのL2準同型暗号と呼ばれる公開鍵暗号ライブラリである。 +L2準同型暗号とは暗号文同士の加算を複数回、乗算を一度だけできる性質を表す。 + +特に2個の整数値ベクトルx = (x_i), y = (y_i)の各要素が暗号化された状態で、その2個のベクトルの内積を暗号化したまま計算できる。 + +ΣEnc(x_i) Enc(y_i) = Enc(Σx_i y_i). + +# 特長 +* ペアリングベースの最新アルゴリズムを実装 + * [Efficient Two-level Homomorphic Encryption in Prime-order Bilinear Groups and A Fast Implementation in WebAssembly : ASIA CCS2018](http://asiaccs2018.org/?page_id=632) +* C++版はWindows(x64), Linux(x64, ARM64), OSX(x64)に対応 +* JavaScript(WebAssembly 以降JSと記す)版はChrome, Firefox, Edge, Safari(Android, iPhone含む), Node.jsに対応 + +# クラスと主な機能 + +## 主なクラス +* 秘密鍵クラス SecretKey +* 公開鍵クラス PublicKey +* 暗号文クラス CipherTextG1, CipherTextG2, CipherTextGT +* ゼロ知識証明クラス ZkpBin, ZkpEq, ZkpBinEq + +## 暗号化と復号方法 +* 秘密鍵から公開鍵を作成する +* 公開鍵を用いて整数から暗号文を作る +* 秘密鍵を用いて暗号文を復号する + +## 暗号文同士の計算 +* 同じ暗号文クラス同士は加算・減算できる +* CipherTextG1とCipherTextG2を乗算するとCipherTextGTになる + +## 復号の重要な注意点 +* このsheは復号時に小さな離散対数問題(DLP)を解く必要がある +* DLPのテーブルサイズをs、暗号文をEnc(m)とすると復号時間はm/sに比例する +* テーブルサイズの設定は`setRangeForDLP(s)`を使う + * `m/s`の最大値は`setTryNum(tryNum)`で行う + +## ゼロ知識証明クラス +* mを暗号するときに同時にゼロ知識証明を生成する +* 暗号文と生成されたゼロ知識証明と公開鍵でmに関する制約条件を検証できる + +# JS版 + +## Node.jsでの読み込み + +``` +>npm install she-wasm +>node +>const she = require('she-wasm') +``` + +## ブラウザでの読み込み +[she-wasm](https://github.com/herumi/she-wasm/)のshe.js, she\_c.js, she\_c.wasmファイルを同じディレクトリに置いてshe.jsを読み込む +``` +// HTML + +``` + +## JS版サンプル + +``` +// システムの初期化 +she.init().then(() => { + const sec = new she.SecretKey() + // 秘密鍵の初期化 + sec.setByCSPRNG() + + // 秘密鍵secから公開鍵pubを作成 + const pub = sec.getPublicKey() + + const m1 = 1 + const m2 = 2 + const m3 = 3 + const m4 = -1 + + // 平文m1とm2をCipherTextG1として暗号化 + const c11 = pub.encG1(m1) + const c12 = pub.encG1(m2) + + // 平文m3とm4をCipherTextG2として暗号化 + const c21 = pub.encG2(m3) + const c22 = pub.encG2(m4) + + // c11とc12, c21とc22をそれぞれ加算 + const c1 = she.add(c11, c12) + const c2 = she.add(c21, c22) + + // c1とc2を乗算するとCipherTextGT型になる + const ct = she.mul(c1, c2) + + // 暗号文ctを復号する + console.log(`(${m1} + ${m2}) * (${m3} + ${m4}) = ${sec.dec(ct)}`) +}) +``` + +# C++版サンプル +ライブラリのビルドは[mcl](https://github.com/herumi/mcl/#installation-requirements)を参照 +``` +#include +int main() + try +{ + using namespace mcl::she; + // システのム初期化 + init(); + + SecretKey sec; + + // 秘密鍵の初期化 + sec.setByCSPRNG(); + + // 秘密鍵secから公開鍵pubを作成 + PublicKey pub; + sec.getPublicKey(pub); + + int m1 = 1; + int m2 = 2; + int m3 = 3; + int m4 = -1; + + // 平文m1とm2をCipherTextG1として暗号化 + CipherTextG1 c11, c12; + pub.enc(c11, m1); + pub.enc(c12, m2); + + // 平文m3とm4をCipherTextG2として暗号化 + CipherTextG2 c21, c22; + pub.enc(c21, m3); + pub.enc(c22, m4); + + // c11とc12, c21とc22をそれぞれ加算 + CipherTextG1 c1; + CipherTextG2 c2; + CipherTextG1::add(c1, c11, c12); + CipherTextG2::add(c2, c21, c22); + + // c1とc2を乗算するとCipherTextGT型になる + CipherTextGT ct; + CipherTextGT::mul(ct, c1, c2); + + // 暗号文ctを復号する + printf("(%d + %d) * (%d + %d) = %d\n", m1, m2, m3, m4, (int)sec.dec(ct)); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} + +``` + +# クラス共通メソッド + +## シリアライズ(C++) + +* `setStr(const std::string& str, int ioMode = 0)` + * ioModeに従ってstrで設定する + +* `getStr(std::string& str, int ioMode = 0) const` +* `std::string getStr(int ioMode = 0) const` + * ioModeに従ってstrを取得する +* `size_t serialize(void *buf, size_t maxBufSize) const` + * maxBufSize確保されたbufにシリアライズする + * bufに書き込まれたbyte長が返る + * エラーの場合は0が返る +* `size_t deserialize(const void *buf, size_t bufSize)` + * bufから最大bufSizeまで値を読み込みデリシアライズする + * 読み込まれたbyte長が返る + * エラーの場合は0が返る + +## シリアライズ(JS) + +* `deserialize(s)` + * Uint8Array型sでデシリアライズ +* `serialize()` + * シリアライズしてUint8Arrayの値を返す +* `deserializeHexStr(s)` + * 16進数文字列sでデシリアライズ +* `serializeToHexStr()` + * 16進数文字列sでシリアライズ + +## ioMode + +* 2 ; 2進数 +* 10 ; 10進数 +* 16 ; 16進数 +* IoPrefix ; 2または16とorの値を設定すると0bまたは0xがつく +* IoEcAffine ; (G1, G2のみ)アフィン座標 +* IoEcProj ; (G1, G2のみ)射影座標 +* IoSerialize ; serialize()/deserialize()と同じ + +## 注意 +* C++の名前空間は`mcl::she` +* 以下CTはCipherTextG1, CipherTextG2, CipherTextGTのいずれかを表す +* JS版の平文は32ビット整数の範囲に制限される + +## SecretKeyクラス + +* `void setByCSPRNG()`(C++) +* `void setByCSPRNG()`(JS) + * 疑似乱数で秘密鍵を初期化する + +* `int64_t dec(const CT& c) const`(C++) +* `int dec(CT c)`(JS) + * 暗号文cを復号する +* `int64_t decViaGT(const CipherTextG1& c) const`(C++) +* `int64_t decViaGT(const CipherTextG2& c) const`(C++) +* `int decViaGT(CT c)`(JS) + * 暗号文をGT経由で復号する +* `bool isZero(const CT& c) const`(C++) +* `bool isZero(CT c)`(JS) + * cの復号結果が0ならばtrue + * decしてから0と比較するよりも高速 + +## PublicKey, PrecomputedPublicKeyクラス +PrecomputedPublicKeyはPublicKeyの高速版 + +* `void PrecomputedPublicKey::init(const PublicKey& pub)`(C++) +* `void PrecomputedPublicKey::init(pub)`(JS) + * 公開鍵pubでPrecomputedPublicKeyを初期化する + + +* `PrecomputedPublicKey::destroy()`(JS) + * JavaScriptではPrecomputedPublicKeyが不要になったらこのメソッドを呼ぶ必要がある + * そうしないとメモリリークする + +以下はPK = PublicKey or PrecomputedPublicKey + +* `void PK::enc(CT& c, int64_t m) const`(C++) +* `CipherTextG1 PK::encG1(m)`(JS) +* `CipherTextG2 PK::encG2(m)`(JS) +* `CipherTextGT PK::encGT(m)`(JS) + * mを暗号化してcにセットする(またはその値を返す) + +* `void PK::reRand(CT& c) const`(C++) +* `CT PK::reRand(CT c)`(JS) + * cを再ランダム化する + * 再ランダム化された暗号文と元の暗号文は同じ平文を暗号化したものかどうか判定できない + +* `void convert(CipherTextGT& cm, const CT& ca) const` +* `CipherTextGT convert(CT ca)` + * 暗号文ca(CipherTextG1かCipherTextG2)をCipherTextGTに変換する + +## CipherTextクラス + +* `void CT::add(CT& z, const CT& x const CT& y)`(C++) +* `CT she.add(CT x, CT y)`(JS) + * 暗号文xと暗号文yを足してzにセットする(またはその値を返す) +* `void CT::sub(CT& z, const CT& x const CT& y)`(C++) +* `CT she.sub(CT x, CT y)`(JS) + * 暗号文xから暗号文yを引いてzにセットする(またはその値を返す) +* `void CT::neg(CT& y, const CT& x)`(C++) +* `void she.neg(CT x)`(JS) + * 暗号文xの符号反転をyにセットする(またはその値を返す) +* `void CT::mul(CT& z, const CT& x, int y)`(C++) +* `CT she.mulInt(CT x, int y)`(JS) + * 暗号文xを整数倍yしてzにセットする(またはその値を返す) + +* `void CipherTextGT::mul(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++) +* `CipherTextGT she.mul(CipherTextG1 x, CipherTextG2 y)`(JS) + * 暗号文xと暗号文yを掛けてzにセットする(またはその値を返す) + +* `void CipherTextGT::mulML(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++) + * 暗号文xと暗号文yを掛けて(Millerループだけして)zにセットする(またはその値を返す) +* `CipherTextGT::finalExp(CipherText& , const CipherTextG1& x, const CipherTextG2& y)`(C++) + * mul(a, b) = finalExp(mulML(a, b)) + * add(mul(a, b), mul(c, d)) = finalExp(add(mulML(a, b), mulML(c, d))) + * すなわち積和演算はmulMLしたものを足してから最後に一度finalExpするのがよい + +## ゼロ知識証明クラス + +### 概要 +* ZkpBin 暗号文encGi(m)(i = 1, 2, T)についてm = 0または1であることを復号せずに検証できる +* ZkpEq 暗号文encG1(m1), encG2(m2)についてm1 = m2であることを検証できる +* ZkpBinEq 暗号文encG1(m1), encG2(m2)についてm1 = m2 = 0または1であることを検証できる + +### API +PK = PublicKey or PrecomputedPublicKey + +* `void PK::encWithZkpBin(CipherTextG1& c, Zkp& zkp, int m) const`(C++) +* `void PK::encWithZkpBin(CipherTextG2& c, Zkp& zkp, int m) const`(C++) +* `[CipherTextG1, ZkpBin] PK::encWithZkpBinG1(m)`(JS) +* `[CipherTextG2, ZkpBin] PK::encWithZkpBinG2(m)`(JS) + * m(=0 or 1)を暗号化して暗号文cとゼロ知識証明zkpをセットする(または[c, zkp]を返す) + * mが0でも1でもなければ例外 +* `void PK::encWithZkpEq(CipherTextG1& c1, CipherTextG2& c2, ZkpEq& zkp, const INT& m) const`(C++) +* `[CipherTextG1, CipherTextG2, ZkpEq] PK::encWithZkpEq(m)`(JS) + * mを暗号化して暗号文c1, c2とゼロ知識証明zkpをセットする(または[c1, c2, zkp]を返す) +* `void PK::encWithZkpBinEq(CipherTextG1& c1, CipherTextG2& c2, ZkpBinEq& zkp, int m) const`(C++) +* `[CipherTextG1, CipherTextG2, ZkpEqBin] PK::encWithZkpBinEq(m)`(JS) + * m(=0 or 1)を暗号化して暗号文c1, c2とゼロ知識証明zkpをセットする(または[c1, c2, zkp]を返す) + * mが0でも1でもなければ例外 + +## グローバル関数 + +* `void init(const CurveParam& cp, size_t hashSize = 1024, size_t tryNum = 2048)`(C++) +* `void init(curveType = she.BN254, hashSize = 1024, tryNum = 2048)`(JS) + * hashSizeの大きさの復号用テーブルとtryNumを元に初期化する + * 復号可能な平文mの範囲は|m| <= hashSize * tryNum +* `she.loadTableForGTDLP(Uint8Array a)`(JS) + * 復号用テーブルを読み込む + * 現在は`https://herumi.github.io/she-dlp-table/she-dlp-0-20-gt.bin`のみがある +* `void useDecG1ViaGT(bool use)`(C++/JS) +* `void useDecG2ViaGT(bool use)`(C++/JS) + * CipherTextG1, CipherTextG2の復号をCipherTextGT経由で行う + * 大きな値を復号するときはDLP用の巨大なテーブルをそれぞれに持つよりもGTに集約した方が効率がよい + +# ライセンス + +このライブラリは[修正BSDライセンス](https://github.com/herumi/mcl/blob/master/COPYRIGHT)で提供されます + +# 開発者 + +光成滋生 MITSUNARI Shigeo(herumi@nifty.com) diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/she-api.md b/vendor/github.com/dexon-foundation/mcl/misc/she/she-api.md new file mode 100644 index 000000000..af54311e9 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/misc/she/she-api.md @@ -0,0 +1,322 @@ +# she ; Two-level homomorphic encryption library for browser/Node.js by WebAssembly + +# Abstruct +she is a somewhat(two-level) homomorphic encryption library, +which is based on pairings. +This library supports polynomially many homomorphic additions and +one multiplication over encrypted data. + +Especially, the inner products of two encrypted integer vectors such as Enc(x) = (Enc(x_i)), Enc(y) = (Enc(y_i)) +can be computed. + +Sum_i Enc(x_i) Enc(y_i) = Enc(Sum_i x_i y_i). + +# Features +* supports the latest pairing based algorithm + * [Efficient Two-level Homomorphic Encryption in Prime-order Bilinear Groups and A Fast Implementation in WebAssembly : ASIA CCS2018](http://asiaccs2018.org/?page_id=632) +* supports Windows(x64), Linux(x64, ARM64), OSX(x64) +* supports JavaScript(WebAssembly), Chrome, Firefox, Safari(contains Android, iPhone), Node.js + +# Classes + +## Main classes +* secret key class ; SecretKey +* public key class ; PublicKey +* ciphertext class ; CipherTextG1, CipherTextG2, CipherTextGT +* zero-knowledge proof class ; ZkpBin, ZkpEq, ZkpBinEq + +## Encryption and decryption +* create the corresponding public key from a secret key +* encrypt an integer(plaintext) with a public key +* decrypt a ciphertext with a secret key + +## Homomorphic operations +* homomorphic addtion/substraction over ciphertexts of the same ciphertext class +* homomprphic multiplication over ciphertext of CipherTextG1 and CipherTextG2 + * The class of the result is CipherTextGT. + +## Important notation of decryption +* This library requires to solve a small DLP to decrypt a ciphertext. +* The decryption timing is O(m/s), where s is the size of table to solve DLP, and m is the size fo a plaintext. +* call `setRangeForDLP(s)` to set the table size. + * The maximun `m/s` is set by `setTryNum(tryNum)`. + +## Zero-knowledge proof class +* A zero-knowledge proof is simultaneously created when encrypting a plaintext `m`. +* The restriction according to `m` can be verified with a created zero-knowledge proof and a public key. + +# Setup for JavaScript(JS) + +## for Node.js + +``` +>npm install she-wasm +>node +>const she = require('she-wasm') +``` + +## for a browser + +Copy `she.js`, `she\_c.js`, `she\_c.wasm` to your directory from [she-wasm](https://github.com/herumi/she-wasm/), +and read `she.js`. +``` +// HTML + +``` + +## A sample for JS + +``` +// initialize a library +she.init().then(() => { + const sec = new she.SecretKey() + // initialize a secret key by CSPRNG(cryptographically secure pseudo random number generator) + sec.setByCSPRNG() + + // create a public key from a secret key + const pub = sec.getPublicKey() + + const m1 = 1 + const m2 = 2 + const m3 = 3 + const m4 = -1 + + // encrypt m1 and m2 as CipherTextG1 class + const c11 = pub.encG1(m1) + const c12 = pub.encG1(m2) + + // encrypt m3 and m4 as CipherTextG2 class + const c21 = pub.encG2(m3) + const c22 = pub.encG2(m4) + + // add c11 and c12, c21 and c22 respectively + const c1 = she.add(c11, c12) + const c2 = she.add(c21, c22) + + // get ct as a CipherTextGT class by multiplying c1 with c2 + const ct = she.mul(c1, c2) + + // decrypt ct + console.log(`(${m1} + ${m2}) * (${m3} + ${m4}) = ${sec.dec(ct)}`) +}) +``` + +# A sample for C++ +How to build the library, see [mcl](https://github.com/herumi/mcl/#installation-requirements). +``` +#include +int main() + try +{ + using namespace mcl::she; + // initialize a library + init(); + + SecretKey sec; + + // initialize a secret key by CSPRNG + sec.setByCSPRNG(); + + // create a public key from a secret key + PublicKey pub; + sec.getPublicKey(pub); + + int m1 = 1; + int m2 = 2; + int m3 = 3; + int m4 = -1; + + // encrypt m1 and m2 as CipherTextG1 class + CipherTextG1 c11, c12; + pub.enc(c11, m1); + pub.enc(c12, m2); + + // encrypt m3 and m4 as CipherTextG2 class + CipherTextG2 c21, c22; + pub.enc(c21, m3); + pub.enc(c22, m4); + + // add c11 and c12, c21 and c22 respectively + CipherTextG1 c1; + CipherTextG2 c2; + CipherTextG1::add(c1, c11, c12); + CipherTextG2::add(c2, c21, c22); + + // get ct as a CipherTextGT class by multiplying c1 with c2 + CipherTextGT ct; + CipherTextGT::mul(ct, c1, c2); + + // decrypt ct + printf("(%d + %d) * (%d + %d) = %d\n", m1, m2, m3, m4, (int)sec.dec(ct)); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} + +``` +# Class method + +## Serialization(C++) + +* `setStr(const std::string& str, int ioMode = 0)` + * set a value by `str` according to `ioMode` + +* `getStr(std::string& str, int ioMode = 0) const` +* `std::string getStr(int ioMode = 0) const` + * get a string `str` according to `ioMode` +* `size_t serialize(void *buf, size_t maxBufSize) const` + * serialize a value to buf which has maxBufSize byte size + * return the byte size to be written in `buf` + * return zero if error +* `size_t deserialize(const void *buf, size_t bufSize)` + * deserialize a value from buf which has bufSize byte size + * return the byte size to be read from `buf` + * return zero if error + +## Serialization(JS) + +* `deserialize(s)` + * deserialize from `s` as Uint8Array type +* `serialize()` + * serialize a value and return Uint8Array value +* `deserializeHexStr(s)` + * deserialize as a hexadecimal string +* `serializeToHexStr()` + * serialize as a hexadecimal string + +## ioMode + +* 2 ; binary number +* 10 ; decimal number +* 16 ; hexadecimal number +* IoPrefix ; append a prefix 0b(resp. 2) or 0x(resp. 16) +* IoEcAffine ; affine coordinate (for only G1, G2) +* IoEcProj ; projective coordinate (for only G1, G2) +* IoSerialize ; same as serialize()/deserialize() + +## Notation +* the namespace of C++ is `mcl::she` +* CT means one of CipherTextG1, CipherTextG2, CipherTextGT +* The range of plaintext is rectricted as a 32-bit integer for JS + +## SecretKey class + +* `void setByCSPRNG()`(C++) +* `void setByCSPRNG()`(JS) + * set a secret key by CSPRNG(cryptographically secure pseudo random number generator) + +* `int64_t dec(const CT& c) const`(C++) +* `int dec(CT c)`(JS) + * decrypt `c` +* `int64_t decViaGT(const CipherTextG1& c) const`(C++) +* `int64_t decViaGT(const CipherTextG2& c) const`(C++) +* `int decViaGT(CT c)`(JS) + * decrypt `c` through CipherTextGT +* `bool isZero(const CT& c) const`(C++) +* `bool isZero(CT c)`(JS) + * return true if decryption of `c` is zero + * it is faster than the timing of comparision with zero after decrypting `c` + +## PublicKey, PrecomputedPublicKey class +`PrecomputedPublicKey` is a faster version of `PublicKey` + +* `void PrecomputedPublicKey::init(const PublicKey& pub)`(C++) +* `void PrecomputedPublicKey::init(pub)`(JS) + * initialize `PrecomputedPublicKey` by a public key `pub` + +* `PrecomputedPublicKey::destroy()`(JS) + * It is necessary to call this method if this instance becomes unnecessary + * otherwise a memory leak will be caused + +PK means PublicKey or PrecomputedPublicKey + +* `void PK::enc(CT& c, int64_t m) const`(C++) +* `CipherTextG1 PK::encG1(m)`(JS) +* `CipherTextG2 PK::encG2(m)`(JS) +* `CipherTextGT PK::encGT(m)`(JS) + * encrypt `m` and set `c`(or return the value) + +* `void PK::reRand(CT& c) const`(C++) +* `CT PK::reRand(CT c)`(JS) + * rerandomize `c` + * For `c = Enc(m)`, the rerandomized ciphertext is hard to detect if it is generated by the rerandomization + or an encrypted `m` freshly again. + +* `void convert(CipherTextGT& cm, const CT& ca) const` +* `CipherTextGT convert(CT ca)` + * convert `ca`(CipherTextG1 or CipherTextG2) to `CipherTextGT` class + +## CipherText class + +* `void CT::add(CT& z, const CT& x const CT& y)`(C++) +* `CT she.add(CT x, CT y)`(JS) + * add `x` and `y` and set the value to `z`(or return the value) +* `void CT::sub(CT& z, const CT& x const CT& y)`(C++) +* `CT she.sub(CT x, CT y)`(JS) + * subtract `x` and `y` and set the value to `z`(or return the value) +* `void CT::neg(CT& y, const CT& x)`(C++) +* `void she.neg(CT x)`(JS) + * negate `x` and set the value to `y`(or return the value) +* `void CT::mul(CT& z, const CT& x, int y)`(C++) +* `CT she.mulInt(CT x, int y)`(JS) + * multiple `x` and `y` and set the value `y`(or return the value) + +* `void CipherTextGT::mul(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++) +* `CipherTextGT she.mul(CipherTextG1 x, CipherTextG2 y)`(JS) + * multiple `x` and `y` and set the value `y`(or return the value) + +* `void CipherTextGT::mulML(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++) + * multiple(only Miller Loop) `x` and `y` and set the value `y`(or return the value) + +* `CipherTextGT::finalExp(CipherText& , const CipherTextG1& x, const CipherTextG2& y)`(C++) + * mul(a, b) = finalExp(mulML(a, b)) + * add(mul(a, b), mul(c, d)) = finalExp(add(mulML(a, b), mulML(c, d))) + * i.e., innor product can be computed as once calling `finalExp` after computing `mulML` for each elements of two vectors and adding all + +## Zero knowledge proof class + +### Abstract +* ZkpBin ; verify whether `m = 0` or `1` for ciphertexts `encGi(m)(i = 1, 2, T)` +* ZkpEq ; verify whether `m1 = m2` for ciphertexts `encG1(m1)` and `encG2(m2)` +* ZkpBinEq ; verify whether `m1 = m2 = 0` or `1` for ciphertexts `encG1(m1)` and `encG2(m2)` + +### API +PK = PublicKey or PrecomputedPublicKey + +* `void PK::encWithZkpBin(CipherTextG1& c, Zkp& zkp, int m) const`(C++) +* `void PK::encWithZkpBin(CipherTextG2& c, Zkp& zkp, int m) const`(C++) +* `[CipherTextG1, ZkpBin] PK::encWithZkpBinG1(m)`(JS) +* `[CipherTextG2, ZkpBin] PK::encWithZkpBinG2(m)`(JS) + * encrypt `m`(=0 or 1) and set the ciphertext `c` and zero-knowledge proof `zkp`(or returns [c, zkp]) + * throw exception if m != 0 and m != 1 +* `void PK::encWithZkpEq(CipherTextG1& c1, CipherTextG2& c2, ZkpEq& zkp, const INT& m) const`(C++) +* `[CipherTextG1, CipherTextG2, ZkpEq] PK::encWithZkpEq(m)`(JS) + * encrypt `m` and set the ciphertext `c1`, `c2` and zero-knowledge proof `zk`(or returns [c1, c2, zkp]) +* `void PK::encWithZkpBinEq(CipherTextG1& c1, CipherTextG2& c2, ZkpBinEq& zkp, int m) const`(C++) +* `[CipherTextG1, CipherTextG2, ZkpEqBin] PK::encWithZkpBinEq(m)`(JS) + * encrypt `m`(=0 or 1) and set ciphertexts `c1`, `c2` and zero-knowledge proof `zkp`(or returns [c1, c2, zkp]) + * throw exception if m != 0 and m != 1 + +## Global functions + +* `void init(const CurveParam& cp, size_t hashSize = 1024, size_t tryNum = 2048)`(C++) +* `void init(curveType = she.BN254, hashSize = 1024, tryNum = 2048)`(JS) + * initialize a table to solve a DLP with `hashSize` size and set maximum trying count `tryNum`. + * the range `m` to be solvable is |m| <= hashSize * tryNum +* `getHashTableGT().load(InputStream& is)`(C++) +* `she.loadTableForGTDLP(Uint8Array a)`(JS) + * load a DLP table for CipherTextGT + * reset the value of `hashSize` used in `init()` + * `https://herumi.github.io/she-dlp-table/she-dlp-0-20-gt.bin` is a precomputed table +* `void useDecG1ViaGT(bool use)`(C++/JS) +* `void useDecG2ViaGT(bool use)`(C++/JS) + * decrypt a ciphertext of CipherTextG1 and CipherTextG2 through CipherTextGT + * it is better when decrypt a big value + +# License + +[modified new BSD License](https://github.com/herumi/mcl/blob/master/COPYRIGHT) + +# Author + +光成滋生 MITSUNARI Shigeo(herumi@nifty.com) diff --git a/vendor/github.com/dexon-foundation/mcl/misc/she/she.pdf b/vendor/github.com/dexon-foundation/mcl/misc/she/she.pdf new file mode 100644 index 000000000..355a308b3 Binary files /dev/null and b/vendor/github.com/dexon-foundation/mcl/misc/she/she.pdf differ diff --git a/vendor/github.com/dexon-foundation/mcl/mklib.bat b/vendor/github.com/dexon-foundation/mcl/mklib.bat index b601f15d2..389b69009 100644 --- a/vendor/github.com/dexon-foundation/mcl/mklib.bat +++ b/vendor/github.com/dexon-foundation/mcl/mklib.bat @@ -23,6 +23,11 @@ if "%1"=="dll" ( cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj /DMCLBN_NO_AUTOLINK echo link /nologo /DLL /OUT:bin\mclbn384.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.lib link /nologo /DLL /OUT:bin\mclbn384.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.lib + + echo cl /c %CFLAGS% src\she_c256.cpp /Foobj\she_c256.obj /DMCLBN_NO_AUTOLINK + cl /c %CFLAGS% src\she_c256.cpp /Foobj\she_c256.obj /DMCLBN_NO_AUTOLINK + echo link /nologo /DLL /OUT:bin\mclshe256.dll obj\she_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c256.lib + link /nologo /DLL /OUT:bin\mclshe256.dll obj\she_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c256.lib ) else ( echo cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj diff --git a/vendor/github.com/dexon-foundation/mcl/readme.md b/vendor/github.com/dexon-foundation/mcl/readme.md index 1a9f3acc0..39b3d4d42 100644 --- a/vendor/github.com/dexon-foundation/mcl/readme.md +++ b/vendor/github.com/dexon-foundation/mcl/readme.md @@ -10,6 +10,8 @@ mcl is a library for pairing-based cryptography. The current version supports the optimal Ate pairing over BN curves and BLS12-381 curves. # News +* (Break backward compatibility) libmcl_dy.a is renamed to libmcl.a + * The option SHARE_BASENAME_SUF is removed * 2nd argument of `mclBn_init` is changed from `maxUnitSize` to `compiledTimeVar`, which must be `MCLBN_COMPILED_TIME_VAR`. * break backward compatibility of mapToGi for BLS12. A map-to-function for BN is used. If `MCL_USE_OLD_MAPTO_FOR_BLS12` is defined, then the old function is used, but this will be removed in the future. @@ -35,33 +37,31 @@ p(z) = 36z^4 + 36z^3 + 24z^2 + 6z + 1. # Benchmark -A benchmark of a BN curve BN254(2016/12/25). +## The latest benchmark(2018/11/7) -* x64, x86 ; Inte Core i7-6700 3.4GHz(Skylake) upto 4GHz on Ubuntu 16.04. - * `sudo cpufreq-set -g performance` -* arm ; 900MHz quad-core ARM Cortex-A7 on Raspberry Pi2, Linux 4.4.11-v7+ -* arm64 ; 1.2GHz ARM Cortex-A53 [HiKey](http://www.96boards.org/product/hikey/) +### Intel Core i7-6700 3.4GHz(Skylake), Ubuntu 18.04.1 LTS -software | x64| x86| arm|arm64(msec) ----------------------------------------------------------|------|-----|----|----- -[ate-pairing](https://github.com/herumi/ate-pairing) | 0.21 | - | - | - -mcl | 0.31 | 1.6 |22.6| 3.9 -[TEPLA](http://www.cipher.risk.tsukuba.ac.jp/tepla/) | 1.76 | 3.7 | 37 | 17.9 -[RELIC](https://github.com/relic-toolkit/relic) PRIME=254| 0.30 | 3.5 | 36 | - -[MIRACL](https://github.com/miracl/MIRACL) ake12bnx | 4.2 | - | 78 | - -[NEONabe](http://sandia.cs.cinvestav.mx/Site/NEONabe) | - | - | 16 | - +curveType | binary|clang-6.0.0|gcc-7.3.0| +----------|--------------------|-----------|---------| +BN254 | bin/bn\_test.exe| 882Kclk| 933Kclk| +BLS12-381 | bin/bls12\_test.exe| 2290Kclk| 2630Kclk| -* compile option for RELIC -``` -cmake -DARITH=x64-asm-254 -DFP_PRIME=254 -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" -``` -## Higher-bit BN curve benchmark by mcl +### Intel Core i7-7700 3.6GHz(Kaby Lake), Ubuntu 18.04.1 LTS on Windows 10 Vmware + +curveType | binary|clang-6.0.0|gcc-7.3.0| +----------|--------------------|-----------|---------| +BN254 | bin/bn\_test.exe| 900Kclk| 954Kclk| +BLS12-381 | bin/bls12\_test.exe| 2340Kclk| 2680Kclk| + +* now investigating the reason why gcc is slower than clang. + +## Higher-bit BN curve benchmark For JavaScript(WebAssembly), see [ID based encryption demo](https://herumi.github.io/mcl-wasm/ibe-demo.html). paramter | x64| Firefox on x64|Safari on iPhone7| -----------|-----|---------------|-----------------| -BN254 | 0.29| 2.48| 4.78| +BN254 | 0.25| 2.48| 4.78| BN381\_1 | 0.95| 7.91| 11.74| BN462 | 2.16| 14.73| 22.77| @@ -74,6 +74,27 @@ BN462 | 2.16| 14.73| 22.77| The other benchmark results are [bench.txt](bench.txt). +## An old benchmark of a BN curve BN254(2016/12/25). + +* x64, x86 ; Inte Core i7-6700 3.4GHz(Skylake) upto 4GHz on Ubuntu 16.04. + * `sudo cpufreq-set -g performance` +* arm ; 900MHz quad-core ARM Cortex-A7 on Raspberry Pi2, Linux 4.4.11-v7+ +* arm64 ; 1.2GHz ARM Cortex-A53 [HiKey](http://www.96boards.org/product/hikey/) + +software | x64| x86| arm|arm64(msec) +---------------------------------------------------------|------|-----|----|----- +[ate-pairing](https://github.com/herumi/ate-pairing) | 0.21 | - | - | - +mcl | 0.31 | 1.6 |22.6| 3.9 +[TEPLA](http://www.cipher.risk.tsukuba.ac.jp/tepla/) | 1.76 | 3.7 | 37 | 17.9 +[RELIC](https://github.com/relic-toolkit/relic) PRIME=254| 0.30 | 3.5 | 36 | - +[MIRACL](https://github.com/miracl/MIRACL) ake12bnx | 4.2 | - | 78 | - +[NEONabe](http://sandia.cs.cinvestav.mx/Site/NEONabe) | - | - | 16 | - + +* compile option for RELIC +``` +cmake -DARITH=x64-asm-254 -DFP_PRIME=254 -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" +``` + # Installation Requirements * [GMP](https://gmplib.org/) and OpenSSL @@ -90,6 +111,18 @@ git clone git://github.com/herumi/cybozulib_ext ; for only Windows ``` * Cybozulib\_ext is a prerequisite for running OpenSSL and GMP on VC (Visual C++). +# (Option) Without GMP +``` +make MCL_USE_GMP=0 +``` +Define `MCL_USE_VINT` before including `bn.hpp` + +# (Option) Without Openssl +``` +make MCL_USE_OPENSSL=0 +``` +Define `MCL_DONT_USE_OPENSSL` before including `bn.hpp` + # Build and test on x86-64 Linux, macOS, ARM and ARM64 Linux To make lib/libmcl.a and test it: ``` @@ -198,7 +231,7 @@ finalExp 546.259Kclk ## C++ library * libmcl.a ; static C++ library of mcl -* libmcl\_dy.so ; shared C++ library of mcl +* libmcl.so ; shared C++ library of mcl * the default parameter of curveType is BN254 header |support curveType |sizeof Fr|sizeof Fp| @@ -212,16 +245,22 @@ bn384.hpp |BN381_1, BLS12_381, BN254| 48 | 48 | * Define `MCLBN_FR_UNIT_SIZE` and `MCLBN_FP_UNIT_SIZE` and include bn.h * set `MCLBN_FR_UNIT_SIZE = MCLBN_FP_UNIT_SIZE` unless `MCLBN_FR_UNIT_SIZE` is defined + library |MCLBN_FR_UNIT_SIZE|MCLBN_FP_UNIT_SIZE| ------------------|------------------|------------------| +sizeof | Fr | Fp | libmclbn256.a | 4 | 4 | libmclbn384_256.a | 4 | 6 | libmclbn384.a | 6 | 6 | + * libmclbn*.a ; static C library -* libmclbn*\_dy.so ; shared C library +* libmclbn*.so ; shared C library -If you want to remove `_dy` of so files, then `makeSHARE_BASENAME\_SUF=`. +### 2nd argument of `mclBn_init` +Specify `MCLBN_COMPILED_TIME_VAR` to 2nd argument of `mclBn_init`, which +is defined as `MCLBN_FR_UNIT_SIZE * 10 + MCLBN_FP_UNIT_SIZE`. +This parameter is used to make sure that the values are the same when the library is built and used. # How to initialize pairing library Call `mcl::bn256::initPairing` before calling any operations. @@ -293,10 +332,14 @@ Use `Fp12::mulGeneric` for x in Fp12 - GT. ## Map To points -* mapToG1(G1& P, const Fp& x); +Use these functions to make a point of G1 and G2. + +* mapToG1(G1& P, const Fp& x); // assume x != 0 * mapToG2(G2& P, const Fp2& x); +* hashAndMapToG1(G1& P, const void *buf, size_t bufSize); // set P by the hash value of [buf, bufSize) +* hashAndMapToG2(G2& P, const void *buf, size_t bufSize); -These functions maps x into Gi according to [_Faster hashing to G2_]. +These functions maps x into Gi according to [\[_Faster hashing to G2_\]]. ## String format of G1 and G2 G1 and G2 have three elements of Fp (x, y, z) for Jacobi coordinate. @@ -309,6 +352,44 @@ getStr() method gets * `2 ` ; compressed format for even y * `3 ` ; compressed format for odd y +## Generator of G1 and G2 + +If you want to use the same generators of BLS12-381 with [zkcrypto](https://github.com/zkcrypto/pairing/tree/master/src/bls12_381#g2) then, + +``` +// G1 P +P.setStr('1 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569') + +// G2 Q +Q.setStr('1 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582') +``` + +## Serialization format of G1 and G2 + +pseudo-code to serialize of p +``` +if bit-length(p) % 8 != 0: + size = Fp::getByteSize() + if p is zero: + return [0] * size + else: + s = x.serialize() + # x in Fp2 is odd <=> x.a is odd + if y is odd: + s[byte-length(s) - 1] |= 0x80 + return s +else: + size = Fp::getByteSize() + 1 + if p is zero: + return [0] * size + else: + s = x.serialize() + if y is odd: + return 2:s + else: + return 3:s +``` + ## Verify an element in G2 `G2::isValid()` checks that the element is in the curve of G2 and the order of it is r for subgroup attack. `G2::set()`, `G2::setStr` and `operator<<` also check the order. @@ -360,6 +441,17 @@ This library contains some part of the followings software licensed by BSD-3-Cla * [_Skew Frobenius Map and Efficient Scalar Multiplication for Pairing–Based Cryptography_](https://www.researchgate.net/publication/221282560_Skew_Frobenius_Map_and_Efficient_Scalar_Multiplication_for_Pairing-Based_Cryptography), Y. Sakemi, Y. Nogami, K. Okeya, Y. Morikawa, CANS 2008. +# History + +* 2019/Mar/22 v0.92 shortcut for Ec::mul(Px, P, x) if P = 0 +* 2019/Mar/21 python binding of she256 for Linux/Mac/Windows +* 2019/Mar/14 v0.91 modp supports mcl-wasm +* 2019/Mar/12 v0.90 fix Vint::setArray(x) for x == this +* 2019/Mar/07 add mclBnFr_setLittleEndianMod, mclBnFp_setLittleEndianMod +* 2019/Feb/20 LagrangeInterpolation sets out = yVec[0] if k = 1 +* 2019/Jan/31 add mclBnFp_mapToG1, mclBnFp2_mapToG2 +* 2019/Jan/31 fix crash on x64-CPU without AVX (thanks to mortdeus) + # Author 光成滋生 MITSUNARI Shigeo(herumi@nifty.com) diff --git a/vendor/github.com/dexon-foundation/mcl/sample/bench.cpp b/vendor/github.com/dexon-foundation/mcl/sample/bench.cpp new file mode 100644 index 000000000..0f865b189 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/bench.cpp @@ -0,0 +1,233 @@ +#include +#include +#include +#include +#include +#include + +typedef mcl::FpT<> Fp; +typedef mcl::FpT Zn; +typedef mcl::EcT Ec; + +void benchFpSub(const char *pStr, const char *xStr, const char *yStr, mcl::fp::Mode mode) +{ + const char *s = mcl::fp::ModeToStr(mode); + Fp::init(pStr, mode); + Fp x(xStr); + Fp y(yStr); + + double addT, subT, mulT, sqrT, invT; + CYBOZU_BENCH_T(addT, Fp::add, x, x, x); + CYBOZU_BENCH_T(subT, Fp::sub, x, x, y); + CYBOZU_BENCH_T(mulT, Fp::mul, x, x, x); + CYBOZU_BENCH_T(sqrT, Fp::sqr, x, x); + CYBOZU_BENCH_T(invT, x += y;Fp::inv, x, x); // avoid same jmp + printf("%10s bit % 3d add %8.2f sub %8.2f mul %8.2f sqr %8.2f inv %8.2f\n", s, (int)Fp::getBitSize(), addT, subT, mulT, sqrT, invT); +} + +void benchFp(size_t bitSize, int mode) +{ + const struct { + size_t bitSize; + const char *p; + const char *x; + const char *y; + } tbl[] = { + { + 192, + "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d", + "0x148094810948190412345678901234567900342423332197", + "0x7fffffffffffffffffffffe26f2fc170f69466a74defd8d", + }, + { + 256, + "0x2523648240000001ba344d80000000086121000000000013a700000000000013", + "0x1480948109481904123456789234234242423424201234567900342423332197", + "0x151342342342341517fffffffffffffffffffffe26f2fc170f69466a74defd8d", + }, + { + 384, + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff", + "0x19481084109481094820948209482094820984290482212345678901234567900342308472047204720422423332197", + "0x209348209481094820984209842094820948204204243123456789012345679003423084720472047204224233321972", + + }, + { + 521, + "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x2908209582095820941098410948109482094820984209840294829049240294242498540975555312345678901234567900342308472047204720422423332197", + "0x3948384209834029834092384204920349820948205872380573205782385729385729385723985837ffffffffffffffffffffffe26f2fc170f69466a74defd8d", + + }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + if (bitSize != 0 && tbl[i].bitSize != bitSize) continue; + if (mode & 1) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_GMP); + if (mode & 2) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_GMP_MONT); +#ifdef MCL_USE_LLVM + if (mode & 4) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_LLVM); + if (mode & 8) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_LLVM_MONT); +#endif +#ifdef MCL_USE_XBYAK + if (mode & 16) benchFpSub(tbl[i].p, tbl[i].x, tbl[i].y, mcl::fp::FP_XBYAK); +#endif + } +} + +void benchEcSub(const mcl::EcParam& para, mcl::fp::Mode mode, mcl::ec::Mode ecMode) +{ + Fp::init(para.p, mode); + Zn::init(para.n); + Ec::init(para.a, para.b, ecMode); + Fp x(para.gx); + Fp y(para.gy); + Ec P(x, y); + Ec P2; Ec::add(P2, P, P); + Ec Q = P + P + P; + double addT, add2T, subT, dblT, mulT, mulCTT, mulRandT, mulCTRandT, normT; + CYBOZU_BENCH_T(addT, P = P2; Ec::add, Q, P, Q); + P.normalize(); + CYBOZU_BENCH_T(add2T, Ec::add, Q, P, Q); + CYBOZU_BENCH_T(subT, Ec::sub, Q, P, Q); + CYBOZU_BENCH_T(dblT, Ec::dbl, P, P); + Zn z("3"); + CYBOZU_BENCH_T(mulT, Ec::mul, Q, P, z); + CYBOZU_BENCH_T(mulCTT, Ec::mulCT, Q, P, z); + cybozu::XorShift rg; + z.setRand(rg); + CYBOZU_BENCH_T(mulRandT, Ec::mul, Q, P, z); + CYBOZU_BENCH_T(mulCTRandT, Ec::mulCT, Q, P, z); + CYBOZU_BENCH_T(normT, Q = P; Q.normalize); + printf("%10s %10s add %8.2f add2 %8.2f sub %8.2f dbl %8.2f mul(3) %8.2f mulCT(3) %8.2f mul(rand) %8.2f mulCT(rand) %8.2f norm %8.2f\n", para.name, mcl::fp::ModeToStr(mode), addT, add2T, subT, dblT, mulT, mulCTT, mulRandT, mulCTRandT, normT); + +} +void benchEc(size_t bitSize, int mode, mcl::ec::Mode ecMode) +{ + const struct mcl::EcParam tbl[] = { + mcl::ecparam::p160_1, + mcl::ecparam::secp160k1, + mcl::ecparam::secp192k1, + mcl::ecparam::NIST_P192, + mcl::ecparam::secp224k1, + mcl::ecparam::secp256k1, + mcl::ecparam::NIST_P224, + mcl::ecparam::NIST_P256, +// mcl::ecparam::secp384r1, + mcl::ecparam::NIST_P384, +// mcl::ecparam::secp521r1, + mcl::ecparam::NIST_P521, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + if (bitSize != 0 && tbl[i].bitSize != bitSize) continue; + benchEcSub(tbl[i], mcl::fp::FP_AUTO, ecMode); + if (mode & 1) benchEcSub(tbl[i], mcl::fp::FP_GMP, ecMode); + if (mode & 2) benchEcSub(tbl[i], mcl::fp::FP_GMP_MONT, ecMode); +#ifdef MCL_USE_LLVM + if (mode & 4) benchEcSub(tbl[i], mcl::fp::FP_LLVM, ecMode); + if (mode & 8) benchEcSub(tbl[i], mcl::fp::FP_LLVM_MONT, ecMode); +#endif +#ifdef MCL_USE_XBYAK + if (mode & 16) benchEcSub(tbl[i], mcl::fp::FP_XBYAK, ecMode); +#endif + } +} + +void benchToStr16() +{ + puts("benchToStr16"); + const char *tbl[] = { + "0x0", + "0x5", + "0x123", + "0x123456789012345679adbc", + "0xffffffff26f2fc170f69466a74defd8d", + "0x100000000000000000000000000000033", + "0x11ee12312312940000000000000000000000000002342343" + }; + Fp::init("0xffffffffffffffffffffffffffffffffffffffffffffff13"); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + char buf[128]; + std::string str; + Fp x(tbl[i]); + CYBOZU_BENCH("fp::arrayToHex", mcl::fp::arrayToHex, buf, sizeof(buf), x.getUnit(), x.getUnitSize(), true); + mpz_class y(tbl[i]); + CYBOZU_BENCH("gmp:getStr ", mcl::gmp::getStr, str, y, 16); + } +} + +void benchFromStr16() +{ + puts("benchFromStr16"); + const char *tbl[] = { + "0", + "5", + "123", + "123456789012345679adbc", + "ffffffff26f2fc170f69466a74defd8d", + "100000000000000000000000000000033", + "11ee12312312940000000000000000000000000002342343" + }; + Fp::init("0xffffffffffffffffffffffffffffffffffffffffffffff13"); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + std::string str = tbl[i]; + Fp x; + const size_t N = 64; + mcl::fp::Unit buf[N]; + CYBOZU_BENCH("fp:hexToArray", mcl::fp::hexToArray, buf, N, str.c_str(), str.size()); + + mpz_class y; + CYBOZU_BENCH("gmp:setStr ", mcl::gmp::setStr, y, str, 16); + } +} + +int main(int argc, char *argv[]) + try +{ + size_t bitSize; + int mode; + bool ecOnly; + bool fpOnly; + bool misc; + mcl::ec::Mode ecMode; + std::string ecModeStr; + cybozu::Option opt; + opt.appendOpt(&bitSize, 0, "s", ": bitSize"); + opt.appendOpt(&mode, 0, "m", ": mode(0:all, sum of 1:gmp, 2:gmp+mont, 4:llvm, 8:llvm+mont, 16:xbyak"); + opt.appendBoolOpt(&ecOnly, "ec", ": ec only"); + opt.appendBoolOpt(&fpOnly, "fp", ": fp only"); + opt.appendBoolOpt(&misc, "misc", ": other benchmark"); + opt.appendOpt(&ecModeStr, "jacobi", "ecmode", ": jacobi or proj"); + opt.appendHelp("h", ": show this message"); + if (!opt.parse(argc, argv)) { + opt.usage(); + return 1; + } + if (ecModeStr == "jacobi") { + ecMode = mcl::ec::Jacobi; + } else if (ecModeStr == "proj") { + ecMode = mcl::ec::Proj; + } else { + printf("bad ecstr %s\n", ecModeStr.c_str()); + opt.usage(); + return 1; + } + if (mode < 0 || mode > 31) { + printf("bad mode %d\n", mode); + opt.usage(); + return 1; + } + if (mode == 0) mode = 31; + if (misc) { + benchToStr16(); + benchFromStr16(); + } else { + if (!ecOnly) benchFp(bitSize, mode); + if (!fpOnly) { + printf("ecMode=%s\n", ecModeStr.c_str()); + benchEc(bitSize, mode, ecMode); + } + } +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); +} + diff --git a/vendor/github.com/dexon-foundation/mcl/sample/bls_sig.cpp b/vendor/github.com/dexon-foundation/mcl/sample/bls_sig.cpp new file mode 100644 index 000000000..d75f7d427 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/bls_sig.cpp @@ -0,0 +1,70 @@ +/** + @file + @brief a sample of BLS signature + see https://github.com/herumi/bls + @author MITSUNARI Shigeo(@herumi) + @license modified new BSD license + http://opensource.org/licenses/BSD-3-Clause + +*/ +#include +#include + +using namespace mcl::bn256; + +void Hash(G1& P, const std::string& m) +{ + Fp t; + t.setHashOf(m); + mapToG1(P, t); +} + +void KeyGen(Fr& s, G2& pub, const G2& Q) +{ + s.setRand(); + G2::mul(pub, Q, s); // pub = sQ +} + +void Sign(G1& sign, const Fr& s, const std::string& m) +{ + G1 Hm; + Hash(Hm, m); + G1::mul(sign, Hm, s); // sign = s H(m) +} + +bool Verify(const G1& sign, const G2& Q, const G2& pub, const std::string& m) +{ + Fp12 e1, e2; + G1 Hm; + Hash(Hm, m); + pairing(e1, sign, Q); // e1 = e(sign, Q) + pairing(e2, Hm, pub); // e2 = e(Hm, sQ) + return e1 == e2; +} + +int main(int argc, char *argv[]) +{ + std::string m = argc == 1 ? "hello mcl" : argv[1]; + + // setup parameter + initPairing(); + G2 Q; + mapToG2(Q, 1); + + // generate secret key and public key + Fr s; + G2 pub; + KeyGen(s, pub, Q); + std::cout << "secret key " << s << std::endl; + std::cout << "public key " << pub << std::endl; + + // sign + G1 sign; + Sign(sign, s, m); + std::cout << "msg " << m << std::endl; + std::cout << "sign " << sign << std::endl; + + // verify + bool ok = Verify(sign, Q, pub, m); + std::cout << "verify " << (ok ? "ok" : "ng") << std::endl; +} diff --git a/vendor/github.com/dexon-foundation/mcl/sample/ecdh.cpp b/vendor/github.com/dexon-foundation/mcl/sample/ecdh.cpp new file mode 100644 index 000000000..d5c4a31b2 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/ecdh.cpp @@ -0,0 +1,64 @@ +/* + sample of Elliptic Curve Diffie-Hellman key sharing +*/ +#include +#include +#include +#include +#include + +typedef mcl::FpT<> Fp; +typedef mcl::FpT Zn; +typedef mcl::EcT Ec; + +int main() +{ + cybozu::RandomGenerator rg; + /* + system setup with a parameter secp192k1 recommended by SECG + Ec is an elliptic curve over Fp + the cyclic group of

is isomorphic to Zn + */ + const mcl::EcParam& para = mcl::ecparam::secp192k1; + Zn::init(para.n); + Fp::init(para.p); + Ec::init(para.a, para.b); + const Ec P(Fp(para.gx), Fp(para.gy)); + + /* + Alice setups a private key a and public key aP + */ + Zn a; + Ec aP; + + a.setRand(rg); + Ec::mul(aP, P, a); // aP = a * P; + + std::cout << "aP=" << aP << std::endl; + + /* + Bob setups a private key b and public key bP + */ + Zn b; + Ec bP; + + b.setRand(rg); + Ec::mul(bP, P, b); // bP = b * P; + + std::cout << "bP=" << bP << std::endl; + + Ec abP, baP; + + // Alice uses bP(B's public key) and a(A's priavte key) + Ec::mul(abP, bP, a); // abP = a * (bP) + + // Bob uses aP(A's public key) and b(B's private key) + Ec::mul(baP, aP, b); // baP = b * (aP) + + if (abP == baP) { + std::cout << "key sharing succeed:" << abP << std::endl; + } else { + std::cout << "ERR(not here)" << std::endl; + } +} + diff --git a/vendor/github.com/dexon-foundation/mcl/sample/large.cpp b/vendor/github.com/dexon-foundation/mcl/sample/large.cpp new file mode 100644 index 000000000..60b2ac900 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/large.cpp @@ -0,0 +1,125 @@ +/* + large prime sample for 64-bit arch + make MCL_USE_LLVM=1 MCL_MAX_BIT_SIZE=768 +*/ +#include +#include +#include +#include "../src/low_func.hpp" + +typedef mcl::FpT<> Fp; + +using namespace mcl::fp; +const size_t N = 12; + +void testMul() +{ + Unit ux[N], uy[N], a[N * 2], b[N * 2]; + for (size_t i = 0; i < N; i++) { + ux[i] = -i * i + 5; + uy[i] = -i * i + 9; + } + MulPreCore::f(a, ux, uy); + MulPreCore::f(b, ux, uy); + for (size_t i = 0; i < N * 2; i++) { + if (a[i] != b[i]) { + printf("ERR %016llx %016llx\n", (long long)a[i], (long long)b[i]); + } + } + puts("end testMul"); + CYBOZU_BENCH("gmp ", (MulPreCore::f), ux, ux, uy); + CYBOZU_BENCH("kara", (MulPre::karatsuba), ux, ux, uy); +} + +void mulGmp(mpz_class& z, const mpz_class& x, const mpz_class& y, const mpz_class& p) +{ + z = (x * y) % p; +} +void compareGmp(const std::string& pStr) +{ + Fp::init(pStr); + std::string xStr = "2104871209348712947120947102843728"; + std::string s1, s2; + { + Fp x(xStr); + CYBOZU_BENCH_C("mul by mcl", 1000, Fp::mul, x, x, x); + std::ostringstream os; + os << x; + s1 = os.str(); + } + { + const mpz_class p(pStr); + mpz_class x(xStr); + CYBOZU_BENCH_C("mul by GMP", 1000, mulGmp, x, x, x, p); + std::ostringstream os; + os << x; + s2 = os.str(); + } + if (s1 != s2) { + puts("ERR"); + } +} + +void test(const std::string& pStr, mcl::fp::Mode mode) +{ + printf("test %s\n", mcl::fp::ModeToStr(mode)); + Fp::init(pStr, mode); + const mcl::fp::Op& op = Fp::getOp(); + printf("bitSize=%d\n", (int)Fp::getBitSize()); + mpz_class p(pStr); + Fp x = 123456; + Fp y; + Fp::pow(y, x, p); + std::cout << y << std::endl; + if (x != y) { + std::cout << "err:pow:" << y << std::endl; + return; + } + const size_t N = 24; + mcl::fp::Unit ux[N], uy[N]; + for (size_t i = 0; i < N; i++) { + ux[i] = -i * i + 5; + uy[i] = -i * i + 9; + } + CYBOZU_BENCH("mulPre", op.fpDbl_mulPre, ux, ux, uy); + CYBOZU_BENCH("sqrPre", op.fpDbl_sqrPre, ux, ux); + CYBOZU_BENCH("add", op.fpDbl_add, ux, ux, ux, op.p); + CYBOZU_BENCH("sub", op.fpDbl_sub, ux, ux, ux, op.p); + if (op.fpDbl_addPre) { + CYBOZU_BENCH("addPre", op.fpDbl_addPre, ux, ux, ux); + CYBOZU_BENCH("subPre", op.fpDbl_subPre, ux, ux, ux); + } + CYBOZU_BENCH("mont", op.fpDbl_mod, ux, ux, op.p); + CYBOZU_BENCH("mul", Fp::mul, x, x, x); + compareGmp(pStr); +} + +void testAll(const std::string& pStr) +{ + test(pStr, mcl::fp::FP_GMP); + test(pStr, mcl::fp::FP_GMP_MONT); +#ifdef MCL_USE_LLVM + test(pStr, mcl::fp::FP_LLVM); + test(pStr, mcl::fp::FP_LLVM_MONT); +#endif + compareGmp(pStr); +} +int main() + try +{ + const char *pTbl[] = { + "40347654345107946713373737062547060536401653012956617387979052445947619094013143666088208645002153616185987062074179207", + "13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006083527", + "776259046150354467574489744231251277628443008558348305569526019013025476343188443165439204414323238975243865348565536603085790022057407195722143637520590569602227488010424952775132642815799222412631499596858234375446423426908029627", + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(pTbl); i++) { + testAll(pTbl[i]); + } + testMul(); +} catch (std::exception& e) { + printf("err %s\n", e.what()); + puts("make clean"); + puts("make -DMCL_MAX_BIT_SIZE=768"); + return 1; +} + diff --git a/vendor/github.com/dexon-foundation/mcl/sample/pairing.cpp b/vendor/github.com/dexon-foundation/mcl/sample/pairing.cpp new file mode 100644 index 000000000..230583b6e --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/pairing.cpp @@ -0,0 +1,56 @@ +#include + +using namespace mcl::bn256; + +void minimum_sample(const G1& P, const G2& Q) +{ + const mpz_class a = 123; + const mpz_class b = 456; + Fp12 e1, e2; + pairing(e1, P, Q); + G2 aQ; + G1 bP; + G2::mul(aQ, Q, a); + G1::mul(bP, P, b); + pairing(e2, bP, aQ); + Fp12::pow(e1, e1, a * b); + printf("%s\n", e1 == e2 ? "ok" : "ng"); +} + +void miller_and_finel_exp(const G1& P, const G2& Q) +{ + Fp12 e1, e2; + pairing(e1, P, Q); + + millerLoop(e2, P, Q); + finalExp(e2, e2); + printf("%s\n", e1 == e2 ? "ok" : "ng"); +} + +void precomputed(const G1& P, const G2& Q) +{ + Fp12 e1, e2; + pairing(e1, P, Q); + std::vector Qcoeff; + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e2, P, Qcoeff); + finalExp(e2, e2); + printf("%s\n", e1 == e2 ? "ok" : "ng"); +} + +int main() +{ + const char *aa = "12723517038133731887338407189719511622662176727675373276651903807414909099441"; + const char *ab = "4168783608814932154536427934509895782246573715297911553964171371032945126671"; + const char *ba = "13891744915211034074451795021214165905772212241412891944830863846330766296736"; + const char *bb = "7937318970632701341203597196594272556916396164729705624521405069090520231616"; + + initPairing(); + G2 Q(Fp2(aa, ab), Fp2(ba, bb)); + G1 P(-1, 1); + + minimum_sample(P, Q); + miller_and_finel_exp(P, Q); + precomputed(P, Q); +} + diff --git a/vendor/github.com/dexon-foundation/mcl/sample/pairing_c.c b/vendor/github.com/dexon-foundation/mcl/sample/pairing_c.c new file mode 100644 index 000000000..5c2cd222a --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/pairing_c.c @@ -0,0 +1,52 @@ +#include +#include +#define MCLBN_FP_UNIT_SIZE 4 +#include + +int g_err = 0; +#define ASSERT(x) { if (!(x)) { printf("err %s:%d\n", __FILE__, __LINE__); g_err++; } } + +int main() +{ + char buf[1024]; + const char *aStr = "123"; + const char *bStr = "456"; + mclBn_init(MCL_BN254, MCLBN_FP_UNIT_SIZE); + mclBnFr a, b, ab; + mclBnG1 P, aP; + mclBnG2 Q, bQ; + mclBnGT e, e1, e2; + mclBnFr_setStr(&a, aStr, strlen(aStr), 10); + mclBnFr_setStr(&b, bStr, strlen(bStr), 10); + mclBnFr_mul(&ab, &a, &b); + mclBnFr_getStr(buf, sizeof(buf), &ab, 10); + printf("%s x %s = %s\n", aStr, bStr, buf); + + ASSERT(!mclBnG1_hashAndMapTo(&P, "this", 4)); + ASSERT(!mclBnG2_hashAndMapTo(&Q, "that", 4)); + mclBnG1_getStr(buf, sizeof(buf), &P, 16); + printf("P = %s\n", buf); + mclBnG2_getStr(buf, sizeof(buf), &Q, 16); + printf("Q = %s\n", buf); + + mclBnG1_mul(&aP, &P, &a); + mclBnG2_mul(&bQ, &Q, &b); + + mclBn_pairing(&e, &P, &Q); + mclBnGT_getStr(buf, sizeof(buf), &e, 16); + printf("e = %s\n", buf); + mclBnGT_pow(&e1, &e, &a); + mclBn_pairing(&e2, &aP, &Q); + ASSERT(mclBnGT_isEqual(&e1, &e2)); + + mclBnGT_pow(&e1, &e, &b); + mclBn_pairing(&e2, &P, &bQ); + ASSERT(mclBnGT_isEqual(&e1, &e2)); + if (g_err) { + printf("err %d\n", g_err); + return 1; + } else { + printf("no err\n"); + return 0; + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/sample/random.cpp b/vendor/github.com/dexon-foundation/mcl/sample/random.cpp new file mode 100644 index 000000000..a2a3619ad --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/random.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include +typedef mcl::FpT<> Fp; + +typedef std::map Map; + +int main(int argc, char *argv[]) +{ + cybozu::RandomGenerator rg; + const char *p = mcl::ecparam::secp192k1.p; + if (argc == 2) { + p = argv[1]; + } + Fp::init(p); + Fp x; + printf("p=%s\n", p); + Map m; + for (int i = 0; i < 10000; i++) { + x.setRand(rg); + m[x.getStr(16)]++; + } + for (Map::const_iterator i = m.begin(), ie = m.end(); i != ie; ++i) { + printf("%s %d\n", i->first.c_str(), i->second); + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/sample/rawbench.cpp b/vendor/github.com/dexon-foundation/mcl/sample/rawbench.cpp new file mode 100644 index 000000000..4d7506ef5 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/rawbench.cpp @@ -0,0 +1,180 @@ +#define PUT(x) std::cout << #x "=" << (x) << std::endl +#include +#include +#include +#include +#include + +typedef mcl::FpT Fp; +typedef mcl::Fp2T Fp2; +typedef mcl::FpDblT FpDbl; +typedef mcl::Fp6T Fp6; +typedef mcl::Fp12T Fp12; + +typedef mcl::fp::Unit Unit; + +void mul9(const mcl::fp::Op& op, Unit *y, const Unit *x, const Unit *p) +{ + const size_t maxN = sizeof(Fp) / sizeof(Unit); + Unit tmp[maxN]; + op.fp_add(tmp, x, x, p); // 2x + op.fp_add(tmp, tmp, tmp, p); // 4x + op.fp_add(tmp, tmp, tmp, p); // 8x + op.fp_add(y, tmp, x, p); // 9x +} + +void benchRaw(const char *p, mcl::fp::Mode mode) +{ + Fp::init(1, p, mode); + Fp2::init(); + const size_t maxN = sizeof(Fp) / sizeof(Unit); + const mcl::fp::Op& op = Fp::getOp(); + cybozu::XorShift rg; + Fp fx, fy; + fx.setRand(rg); + fy.setRand(rg); + Unit ux[maxN * 2] = {}; + Unit uy[maxN * 2] = {}; + Unit uz[maxN * 2] = {}; + memcpy(ux, fx.getUnit(), sizeof(Unit) * op.N); + memcpy(ux + op.N, fx.getUnit(), sizeof(Unit) * op.N); + memcpy(uy, fy.getUnit(), sizeof(Unit) * op.N); + memcpy(ux + op.N, fx.getUnit(), sizeof(Unit) * op.N); + double fp_addT, fp_subT; + double fp_addPreT, fp_subPreT; + double fp_sqrT, fp_mulT; + double fp_mulUnitT; + double mul9T; + double fp_mulUnitPreT; + double fpN1_modT; + double fpDbl_addT, fpDbl_subT; + double fpDbl_sqrPreT, fpDbl_mulPreT, fpDbl_modT; + double fp2_sqrT, fp2_mulT; + CYBOZU_BENCH_T(fp_addT, op.fp_add, uz, ux, uy, op.p); + CYBOZU_BENCH_T(fp_subT, op.fp_sub, uz, uy, ux, op.p); + CYBOZU_BENCH_T(fp_addPreT, op.fp_addPre, uz, ux, uy); + CYBOZU_BENCH_T(fp_subPreT, op.fp_subPre, uz, uy, ux); + CYBOZU_BENCH_T(fp_sqrT, op.fp_sqr, uz, ux, op.p); + CYBOZU_BENCH_T(fp_mulT, op.fp_mul, uz, ux, uy, op.p); + CYBOZU_BENCH_T(fp_mulUnitT, op.fp_mulUnit, uz, ux, 9, op.p); + CYBOZU_BENCH_T(mul9T, mul9, op, uz, ux, op.p); + CYBOZU_BENCH_T(fp_mulUnitPreT, op.fp_mulUnitPre, ux, ux, 9); + CYBOZU_BENCH_T(fpN1_modT, op.fpN1_mod, ux, uy, op.p); + CYBOZU_BENCH_T(fpDbl_addT, op.fpDbl_add, uz, ux, uy, op.p); + CYBOZU_BENCH_T(fpDbl_subT, op.fpDbl_sub, uz, uy, ux, op.p); + CYBOZU_BENCH_T(fpDbl_sqrPreT, op.fpDbl_sqrPre, uz, ux); + CYBOZU_BENCH_T(fpDbl_mulPreT, op.fpDbl_mulPre, uz, ux, uy); + CYBOZU_BENCH_T(fpDbl_modT, op.fpDbl_mod, uz, ux, op.p); + Fp2 f2x, f2y; + f2x.a = fx; + f2x.b = fy; + f2y = f2x; + CYBOZU_BENCH_T(fp2_sqrT, Fp2::sqr, f2x, f2x); + CYBOZU_BENCH_T(fp2_mulT, Fp2::mul, f2x, f2x, f2y); + printf("%s\n", mcl::fp::ModeToStr(mode)); + const char *tStrTbl[] = { + "fp_add", "fp_sub", + "addPre", "subPre", + "fp_sqr", "fp_mul", + "mulUnit", + "mul9", + "mulUnitP", + "fpN1_mod", + "D_add", "D_sub", + "D_sqrPre", "D_mulPre", "D_mod", + "fp2_sqr", "fp2_mul", + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tStrTbl); i++) { + printf(" %8s", tStrTbl[i]); + } + printf("\n"); + const double tTbl[] = { + fp_addT, fp_subT, + fp_addPreT, fp_subPreT, + fp_sqrT, fp_mulT, + fp_mulUnitT, + mul9T, + fp_mulUnitPreT, + fpN1_modT, + fpDbl_addT, fpDbl_subT, + fpDbl_sqrPreT, fpDbl_mulPreT, fpDbl_modT, + fp2_sqrT, fp2_mulT, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tTbl); i++) { + printf(" %8.2f", tTbl[i]); + } + printf("\n"); +} + +int main(int argc, char *argv[]) + try +{ + cybozu::Option opt; + size_t bitSize; + opt.appendOpt(&bitSize, 0, "s", ": bitSize"); + opt.appendHelp("h", ": show this message"); + if (!opt.parse(argc, argv)) { + opt.usage(); + return 1; + } + const char *tbl[] = { + // N = 2 + "0x0000000000000001000000000000000d", + "0x7fffffffffffffffffffffffffffffff", + "0x8000000000000000000000000000001d", + "0xffffffffffffffffffffffffffffff61", + + // N = 3 + "0x000000000000000100000000000000000000000000000033", // min prime + "0x70000000000000000000000000000000000000000000001f", + "0x800000000000000000000000000000000000000000000005", + "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d", + "0xfffffffffffffffffffffffffffffffeffffffffffffffff", + "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime + + // N = 4 + "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime + "0x2523648240000001ba344d80000000086121000000000013a700000000000013", // BN254 + "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47", // Snark + "0x7523648240000001ba344d80000000086121000000000013a700000000000017", + "0x800000000000000000000000000000000000000000000000000000000000005f", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime + // N = 5 + "0x80000000000000000000000000000000000000000000000000000000000000000000000000000009", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3b", + // N = 6 + "0x800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000171", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec3", + // N = 7 + "0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff35", + // N = 8 + "0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc7", +#if MCL_MAX_BIT_SIZE == 1024 + "0xc70b1ddda9b96e3965e5855942aa5852d8f8e052c760ac32cdfec16a2ed3d56981e1a475e20a70144ed2f5061ba64900f69451492803f815d446ee133d0668f7a7f3276d6301c95ce231f0e4b0d0f3882f10014fca04454cff55d2e2d4cfc1aad33b8d38397e2fc8b623177e63d0b783269c40a85b8f105654783b8ed2e737df", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97", +#endif + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const char *p = tbl[i]; + if (bitSize > 0 && (strlen(p) - 2) * 4 != bitSize) { + continue; + } + printf("prime=%s\n", p); + benchRaw(tbl[i], mcl::fp::FP_GMP); + benchRaw(tbl[i], mcl::fp::FP_GMP_MONT); +#ifdef MCL_USE_LLVM + benchRaw(tbl[i], mcl::fp::FP_LLVM); + benchRaw(tbl[i], mcl::fp::FP_LLVM_MONT); +#endif +#ifdef MCL_USE_XBYAK + if (bitSize <= 384) { + benchRaw(tbl[i], mcl::fp::FP_XBYAK); + } +#endif + } +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/mcl/sample/she_make_dlp_table.cpp b/vendor/github.com/dexon-foundation/mcl/sample/she_make_dlp_table.cpp new file mode 100644 index 000000000..41f18e225 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/she_make_dlp_table.cpp @@ -0,0 +1,69 @@ +/* + make she DLP table +*/ +#include +#include +#include + +using namespace mcl::she; + +struct Param { + int curveType; + int hashBitSize; + int group; + std::string path; +}; + +template +void makeTable(const Param& param, const char *groupStr, HashTable& hashTbl, const G& P) +{ + char baseName[32]; + CYBOZU_SNPRINTF(baseName, sizeof(baseName), "she-dlp-%d-%d-%s.bin", param.curveType, param.hashBitSize, groupStr); + const std::string fileName = param.path + baseName; + printf("file=%s\n", fileName.c_str()); + std::ofstream ofs(fileName.c_str(), std::ios::binary); + + const size_t hashSize = 1u << param.hashBitSize; + hashTbl.init(P, hashSize); + hashTbl.save(ofs); +} + +void run(const Param& param) +{ + SHE::init(mcl::getCurveParam(param.curveType)); + + switch (param.group) { + case 1: + makeTable(param, "g1", getHashTableG1(), SHE::P_); + break; + case 2: + makeTable(param, "g2", getHashTableG2(), SHE::Q_); + break; + case 3: + makeTable(param, "gt", getHashTableGT(), SHE::ePQ_); + break; + default: + throw cybozu::Exception("bad group") << param.group; + } +} + +int main(int argc, char *argv[]) + try +{ + cybozu::Option opt; + Param param; + opt.appendOpt(¶m.curveType, 0, "ct", ": curveType(0:BN254, 1:BN381_1, 5:BLS12_381)"); + opt.appendOpt(¶m.hashBitSize, 20, "hb", ": hash bit size"); + opt.appendOpt(¶m.group, 3, "g", ": group(1:G1, 2:G2, 3:GT"); + opt.appendOpt(¶m.path, "./", "path", ": path to table"); + opt.appendHelp("h"); + if (opt.parse(argc, argv)) { + run(param); + } else { + opt.usage(); + return 1; + } +} catch (std::exception& e) { + printf("err %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/mcl/sample/she_smpl.cpp b/vendor/github.com/dexon-foundation/mcl/sample/she_smpl.cpp new file mode 100644 index 000000000..e01b9c130 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/she_smpl.cpp @@ -0,0 +1,125 @@ +/* + sample of somewhat homomorphic encryption(SHE) +*/ +#define PUT(x) std::cout << #x << "=" << (x) << std::endl; +#include +#include + +using namespace mcl::she; + +void miniSample() +{ + // init library + SHE::init(); + + SecretKey sec; + + // init secret key by random_device + sec.setByCSPRNG(); + + // set range to decode GT DLP + SHE::setRangeForDLP(1000); + + PublicKey pub; + // get public key + sec.getPublicKey(pub); + + const int N = 5; + int a[] = { 1, 5, -3, 4, 6 }; + int b[] = { 4, 2, 1, 9, -2 }; + // compute correct value + int sum = 0; + for (size_t i = 0; i < N; i++) { + sum += a[i] * b[i]; + } + + std::vector ca(N), cb(N); + + // encrypt each a[] and b[] + for (size_t i = 0; i < N; i++) { + pub.enc(ca[i], a[i]); + pub.enc(cb[i], b[i]); + } + CipherText c; + c.clearAsMultiplied(); // clear as multiplied before using c.add() + // inner product of encrypted vector + for (size_t i = 0; i < N; i++) { + CipherText t; + CipherText::mul(t, ca[i], cb[i]); // t = ca[i] * cb[i] + c.add(t); // c += t + } + // decode it + int m = (int)sec.dec(c); + // verify the value + if (m == sum) { + puts("ok"); + } else { + printf("err correct %d err %d\n", sum, m); + } +} + +void usePrimitiveCipherText() +{ + // init library + SHE::init(); + + SecretKey sec; + + // init secret key by random_device + sec.setByCSPRNG(); + + // set range to decode GT DLP + SHE::setRangeForGTDLP(100); + + PublicKey pub; + // get public key + sec.getPublicKey(pub); + + int a1 = 1, a2 = 2; + int b1 = 5, b2 = -4; + CipherTextG1 c1, c2; // size of CipherTextG1 = N * 2 ; N = 256-bit for CurveFp254BNb + CipherTextG2 d1, d2; // size of CipherTextG2 = N * 4 + pub.enc(c1, a1); + pub.enc(c2, a2); + pub.enc(d1, b1); + pub.enc(d2, b2); + c1.add(c2); // CipherTextG1 is additive HE + d1.add(d2); // CipherTextG2 is additive HE + CipherTextGT cm; // size of CipherTextGT = N * 12 * 4 + CipherTextGT::mul(cm, c1, d1); // cm = c1 * d1 + cm.add(cm); // 2cm + int m = (int)sec.dec(cm); + int ok = (a1 + a2) * (b1 + b2) * 2; + if (m == ok) { + puts("ok"); + } else { + printf("err m=%d ok=%d\n", m, ok); + } + std::string s; + s = c1.getStr(mcl::IoSerialize); // serialize + printf("c1 data size %d byte\n", (int)s.size()); + + c2.setStr(s, mcl::IoSerialize); + printf("deserialize %s\n", c1 == c2 ? "ok" : "ng"); + + s = d1.getStr(mcl::IoSerialize); // serialize + printf("d1 data size %d byte\n", (int)s.size()); + d2.setStr(s, mcl::IoSerialize); + printf("deserialize %s\n", d1 == d2 ? "ok" : "ng"); + + s = cm.getStr(mcl::IoSerialize); // serialize + printf("cm data size %d byte\n", (int)s.size()); + CipherTextGT cm2; + cm2.setStr(s, mcl::IoSerialize); + printf("deserialize %s\n", cm == cm2 ? "ok" : "ng"); +} + +int main() + try +{ + miniSample(); + usePrimitiveCipherText(); +} catch (std::exception& e) { + printf("err %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/mcl/sample/tri-dh.cpp b/vendor/github.com/dexon-foundation/mcl/sample/tri-dh.cpp new file mode 100644 index 000000000..8b720edbf --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/tri-dh.cpp @@ -0,0 +1,97 @@ +/* + tripartie Diffie-Hellman +*/ +#include +#include +#include +#include +#include + +static cybozu::RandomGenerator rg; + +const std::string skSuf = ".sk.txt"; +const std::string pkSuf = ".pk.txt"; + +using namespace mcl::bn256; + +void keygen(const std::string& user) +{ + if (user.empty()) { + throw cybozu::Exception("keygen:user is empty"); + } + const char *aa = "12723517038133731887338407189719511622662176727675373276651903807414909099441"; + const char *ab = "4168783608814932154536427934509895782246573715297911553964171371032945126671"; + const char *ba = "13891744915211034074451795021214165905772212241412891944830863846330766296736"; + const char *bb = "7937318970632701341203597196594272556916396164729705624521405069090520231616"; + + + initPairing(); + G2 Q(Fp2(aa, ab), Fp2(ba, bb)); + G1 P(-1, 1); + + Fr s; + s.setRand(rg); + G1::mul(P, P, s); + G2::mul(Q, Q, s); + { + std::string name = user + skSuf; + std::ofstream ofs(name.c_str(), std::ios::binary); + ofs << s << std::endl; + } + { + std::string name = user + pkSuf; + std::ofstream ofs(name.c_str(), std::ios::binary); + ofs << P << std::endl; + ofs << Q << std::endl; + } +} + +void load(G1& P, G2& Q, const std::string& fileName) +{ + std::ifstream ifs(fileName.c_str(), std::ios::binary); + ifs >> P >> Q; +} + +void share(const std::string& skFile, const std::string& pk1File, const std::string& pk2File) +{ + initPairing(); + Fr s; + G1 P1, P2; + G2 Q1, Q2; + { + std::ifstream ifs(skFile.c_str(), std::ios::binary); + ifs >> s; + } + load(P1, Q1, pk1File); + load(P2, Q2, pk2File); + Fp12 e; + pairing(e, P1, Q2); + { + // verify(not necessary) + Fp12 e2; + pairing(e2, P2, Q1); + if (e != e2) { + throw cybozu::Exception("share:bad public key file") << e << e2; + } + } + Fp12::pow(e, e, s); + std::cout << "share key:\n" << e << std::endl; +} + +int main(int argc, char *argv[]) + try +{ + if (argc == 3 && strcmp(argv[1], "keygen") == 0) { + keygen(argv[2]); + } else if (argc == 5 && strcmp(argv[1], "share") == 0) { + share(argv[2], argv[3], argv[4]); + } else { + fprintf(stderr, "tri-dh.exe keygen \n"); + fprintf(stderr, "tri-dh.exe share \n"); + return 1; + } +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} + diff --git a/vendor/github.com/dexon-foundation/mcl/sample/vote.cpp b/vendor/github.com/dexon-foundation/mcl/sample/vote.cpp new file mode 100644 index 000000000..88137187c --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/sample/vote.cpp @@ -0,0 +1,206 @@ +/* + vote sample tool + Copyright (c) 2014, National Institute of Advanced Industrial + Science and Technology All rights reserved. + This source file is subject to BSD 3-Clause license. + + modifyed for mcl by herumi +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef mcl::FpT<> Fp; +typedef mcl::FpT Zn; // use ZnTag because Zn is different class with Fp +typedef mcl::EcT Ec; +typedef mcl::ElgamalT Elgamal; + +cybozu::RandomGenerator rg; + +const std::string pubFile = "vote_pub.txt"; +const std::string prvFile = "vote_prv.txt"; +const std::string resultFile = "vote_ret.txt"; + +std::string GetSheetName(size_t n) +{ + return std::string("vote_") + cybozu::itoa(n) + ".txt"; +} + +struct Param { + std::string mode; + std::string voteList; + Param(int argc, const char *const argv[]) + { + cybozu::Option opt; + opt.appendOpt(&voteList, "11001100", "l", ": list of voters for vote mode(eg. 11001100)"); + opt.appendHelp("h", ": put this message"); + opt.appendParam(&mode, "mode", ": init/vote/count/open"); + if (!opt.parse(argc, argv)) { + opt.usage(); + exit(1); + } + printf("mode=%s\n", mode.c_str()); + if (mode == "vote") { + printf("voters=%s\n", voteList.c_str()); + size_t pos = voteList.find_first_not_of("01"); + if (pos != std::string::npos) { + printf("bad char %c\n", voteList[pos]); + exit(1); + } + } + } +}; + +void SysInit() +{ + const mcl::EcParam& para = mcl::ecparam::secp192k1; + Zn::init(para.n); + Fp::init(para.p); + Ec::init(para.a, para.b); +} + +template +bool Load(T& t, const std::string& name, bool doThrow = true) +{ + std::ifstream ifs(name.c_str(), std::ios::binary); + if (!ifs) { + if (doThrow) throw cybozu::Exception("Load:can't read") << name; + return false; + } + if (ifs >> t) return true; + if (doThrow) throw cybozu::Exception("Load:bad data") << name; + return false; +} + +template +void Save(const std::string& name, const T& t) +{ + std::ofstream ofs(name.c_str(), std::ios::binary); + ofs << t; +} + +void Init() +{ + const mcl::EcParam& para = mcl::ecparam::secp192k1; + const Fp x0(para.gx); + const Fp y0(para.gy); + const Ec P(x0, y0); + const size_t bitSize = para.bitSize; + + Elgamal::PrivateKey prv; + prv.init(P, bitSize, rg); + const Elgamal::PublicKey& pub = prv.getPublicKey(); + printf("make privateKey=%s, publicKey=%s\n", prvFile.c_str(), pubFile.c_str()); + Save(prvFile, prv); + Save(pubFile, pub); +} + +struct CipherWithZkp { + Elgamal::CipherText c; + Elgamal::Zkp zkp; + bool verify(const Elgamal::PublicKey& pub) const + { + return pub.verify(c, zkp); + } +}; + +inline std::ostream& operator<<(std::ostream& os, const CipherWithZkp& self) +{ + return os << self.c << std::endl << self.zkp; +} +inline std::istream& operator>>(std::istream& is, CipherWithZkp& self) +{ + return is >> self.c >> self.zkp; +} + +void Vote(const std::string& voteList) +{ + Elgamal::PublicKey pub; + Load(pub, pubFile); + puts("shuffle"); + std::vector idxTbl(voteList.size()); + for (size_t i = 0; i < idxTbl.size(); i++) { + idxTbl[i] = i; + } + cybozu::shuffle(idxTbl, rg); + puts("each voter votes"); + for (size_t i = 0; i < voteList.size(); i++) { + CipherWithZkp c; + pub.encWithZkp(c.c, c.zkp, voteList[i] - '0', rg); + const std::string sheetName = GetSheetName(idxTbl[i]); + printf("make %s\n", sheetName.c_str()); + Save(sheetName, c); + } +} + +void Count() +{ + Elgamal::PublicKey pub; + Load(pub, pubFile); + Elgamal::CipherText result; + puts("aggregate votes"); + for (size_t i = 0; ; i++) { + const std::string sheetName = GetSheetName(i); + CipherWithZkp c; + if (!Load(c, sheetName, false)) break; + if (!c.verify(pub)) throw cybozu::Exception("bad cipher text") << i; + printf("add %s\n", sheetName.c_str()); + result.add(c.c); + } + printf("create result file : %s\n", resultFile.c_str()); + Save(resultFile, result); +} + +void Open() +{ + Elgamal::PrivateKey prv; + Load(prv, prvFile); + Elgamal::CipherText c; + Load(c, resultFile); + Zn n; + prv.dec(n, c); + std::cout << "result of vote count " << n << std::endl; +#if 0 + puts("open real value"); + for (size_t i = 0; ; i++) { + Elgamal::CipherText c; + const std::string sheetName = GetSheetName(i); + if (!Load(c, sheetName, false)) break; + Zn n; + prv.dec(n, c); + std::cout << sheetName << " " << n << std::endl; + } +#endif +} + +int main(int argc, char *argv[]) + try +{ + const Param p(argc, argv); + SysInit(); + if (p.mode == "init") { + Init(); + } else + if (p.mode == "vote") { + Vote(p.voteList); + } else + if (p.mode == "count") { + Count(); + } else + if (p.mode == "open") { + Open(); + } else + { + printf("bad mode=%s\n", p.mode.c_str()); + return 1; + } +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); +} + diff --git a/vendor/github.com/dexon-foundation/mcl/src/bn_c256.cpp b/vendor/github.com/dexon-foundation/mcl/src/bn_c256.cpp index 5c3007410..2f975a287 100644 --- a/vendor/github.com/dexon-foundation/mcl/src/bn_c256.cpp +++ b/vendor/github.com/dexon-foundation/mcl/src/bn_c256.cpp @@ -2,5 +2,5 @@ implementation of mclBn_* apis */ #define MCLBN_FP_UNIT_SIZE 4 -#include "bn_c_impl.hpp" +#include "mcl/impl/bn_c_impl.hpp" diff --git a/vendor/github.com/dexon-foundation/mcl/src/bn_c384.cpp b/vendor/github.com/dexon-foundation/mcl/src/bn_c384.cpp index 067e728f1..934a078ae 100644 --- a/vendor/github.com/dexon-foundation/mcl/src/bn_c384.cpp +++ b/vendor/github.com/dexon-foundation/mcl/src/bn_c384.cpp @@ -3,5 +3,5 @@ */ #define MCLBN_FP_UNIT_SIZE 6 #define MCLBN_FR_UNIT_SIZE 6 -#include "bn_c_impl.hpp" +#include "mcl/impl/bn_c_impl.hpp" diff --git a/vendor/github.com/dexon-foundation/mcl/src/bn_c384_256.cpp b/vendor/github.com/dexon-foundation/mcl/src/bn_c384_256.cpp index 5630e831d..ecd968efd 100644 --- a/vendor/github.com/dexon-foundation/mcl/src/bn_c384_256.cpp +++ b/vendor/github.com/dexon-foundation/mcl/src/bn_c384_256.cpp @@ -3,5 +3,5 @@ */ #define MCLBN_FP_UNIT_SIZE 6 #define MCLBN_FR_UNIT_SIZE 4 -#include "bn_c_impl.hpp" +#include "mcl/impl/bn_c_impl.hpp" diff --git a/vendor/github.com/dexon-foundation/mcl/src/bn_c512.cpp b/vendor/github.com/dexon-foundation/mcl/src/bn_c512.cpp index 90be2d9bc..7c1029522 100644 --- a/vendor/github.com/dexon-foundation/mcl/src/bn_c512.cpp +++ b/vendor/github.com/dexon-foundation/mcl/src/bn_c512.cpp @@ -2,5 +2,5 @@ implementation of mclBn_* apis */ #define MCLBN_FP_UNIT_SIZE 8 -#include "bn_c_impl.hpp" +#include "mcl/impl/bn_c_impl.hpp" diff --git a/vendor/github.com/dexon-foundation/mcl/src/fp.cpp b/vendor/github.com/dexon-foundation/mcl/src/fp.cpp index bea1dff72..df72d6d07 100644 --- a/vendor/github.com/dexon-foundation/mcl/src/fp.cpp +++ b/vendor/github.com/dexon-foundation/mcl/src/fp.cpp @@ -1,10 +1,6 @@ #include #include -#ifdef MCL_DONT_USE_OPENSSL #include -#else -#include -#endif #include #include #ifdef MCL_USE_XBYAK @@ -120,44 +116,16 @@ bool isEnableJIT() #endif } -void getRandVal(Unit *out, RandGen& rg, const Unit *in, size_t bitSize) -{ - if (rg.isZero()) rg = RandGen::get(); - const size_t n = (bitSize + UnitBitSize - 1) / UnitBitSize; - const size_t rem = bitSize & (UnitBitSize - 1); - assert(n > 0); - for (;;) { - rg.read(out, n * sizeof(Unit)); - if (rem > 0) out[n - 1] &= (Unit(1) << rem) - 1; - if (isLessArray(out, in, n)) return; - } -} - uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize) { - const uint32_t hashSize = 256 / 8; - if (maxOutSize < hashSize) return 0; -#ifdef MCL_DONT_USE_OPENSSL - cybozu::Sha256(msg, msgSize).get(out); -#else - cybozu::crypto::Hash::digest(out, cybozu::crypto::Hash::N_SHA256, msg, msgSize); -#endif - return hashSize; + return (uint32_t)cybozu::Sha256().digest(out, maxOutSize, msg, msgSize); } uint32_t sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize) { - const uint32_t hashSize = 512 / 8; - if (maxOutSize < hashSize) return 0; -#ifdef MCL_DONT_USE_OPENSSL - cybozu::Sha512(msg, msgSize).get(out); -#else - cybozu::crypto::Hash::digest(out, cybozu::crypto::Hash::N_SHA512, msg, msgSize); -#endif - return hashSize; + return (uint32_t)cybozu::Sha512().digest(out, maxOutSize, msg, msgSize); } - #ifndef MCL_USE_VINT static inline void set_mpz_t(mpz_t& z, const Unit* p, int n) { @@ -350,9 +318,9 @@ static bool initForMont(Op& op, const Unit *p, Mode mode) if (mode != FP_XBYAK) return true; #ifdef MCL_USE_XBYAK if (op.fg == 0) op.fg = Op::createFpGenerator(); - op.fg->init(op); + bool useXbyak = op.fg->init(op); - if (op.isMont && N <= 4) { + if (useXbyak && op.isMont && N <= 4) { op.fp_invOp = &invOpForMontC; initInvTbl(op); } @@ -360,7 +328,7 @@ static bool initForMont(Op& op, const Unit *p, Mode mode) return true; } -bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBitSize) +bool Op::init(const mpz_class& _p, size_t maxBitSize, int _xi_a, Mode mode, size_t mclMaxBitSize) { if (mclMaxBitSize != MCL_MAX_BIT_SIZE) return false; #ifdef MCL_USE_VINT @@ -382,6 +350,7 @@ bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBi mp = _p; bitSize = gmp::getBitSize(mp); pmod4 = gmp::getUnit(mp, 0) % 4; + this->xi_a = _xi_a; /* priority : MCL_USE_XBYAK > MCL_USE_LLVM > none Xbyak > llvm_mont > llvm > gmp_mont > gmp @@ -497,18 +466,18 @@ bool Op::init(const mpz_class& _p, size_t maxBitSize, Mode mode, size_t mclMaxBi fpDbl_mod = &mcl::vint::mcl_fpDbl_mod_SECP256K1; } #endif - if (!fp::initForMont(*this, p, mode)) return false; - { - bool b; - sq.set(&b, mp); - if (!b) return false; - } if (N * UnitBitSize <= 256) { hash = sha256; } else { hash = sha512; } - return true; + { + bool b; + sq.set(&b, mp); + if (!b) return false; + } + modp.init(mp); + return fp::initForMont(*this, p, mode); } void copyUnitToByteAsLE(uint8_t *dst, const Unit *src, size_t byteSize) @@ -560,6 +529,27 @@ int detectIoMode(int ioMode, const std::ios_base& ios) bool copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, MaskMode maskMode) { const size_t fpByteSize = sizeof(Unit) * op.N; + if (maskMode == Mod) { + if (xByteSize > fpByteSize * 2) return false; + mpz_class mx; + bool b; + gmp::setArray(&b, mx, (const char*)x, xByteSize); + if (!b) return false; +#ifdef MCL_USE_VINT + op.modp.modp(mx, mx); +#else + mx %= op.mp; +#endif + const Unit *pmx = gmp::getUnit(mx); + size_t i = 0; + for (const size_t n = gmp::getUnitSize(mx); i < n; i++) { + y[i] = pmx[i]; + } + for (; i < op.N; i++) { + y[i] = 0; + } + return true; + } if (xByteSize > fpByteSize) { if (maskMode == NoMask) return false; xByteSize = fpByteSize; @@ -652,10 +642,5 @@ int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op) #pragma warning(pop) #endif -void Op::initFp2(int _xi_a) -{ - this->xi_a = _xi_a; -} - } } // mcl::fp diff --git a/vendor/github.com/dexon-foundation/mcl/src/fp_generator.hpp b/vendor/github.com/dexon-foundation/mcl/src/fp_generator.hpp index 581a0de87..b496bc4d4 100644 --- a/vendor/github.com/dexon-foundation/mcl/src/fp_generator.hpp +++ b/vendor/github.com/dexon-foundation/mcl/src/fp_generator.hpp @@ -8,6 +8,7 @@ */ #if CYBOZU_HOST == CYBOZU_HOST_INTEL #define XBYAK_NO_OP_NAMES +#define XBYAK_DISABLE_AVX512 #include "xbyak/xbyak_util.h" #if MCL_SIZEOF_UNIT == 8 @@ -126,6 +127,71 @@ if (rm.isReg()) { \ namespace fp { +struct Profiler { + FILE *fp_; + const char *suf_; + const uint8_t *prev_; + Profiler() + : fp_(0) + , suf_(0) + , prev_(0) + { + } + void init(const char *suf, const uint8_t *prev) + { +#ifdef __linux__ + close(); + const char *s = getenv("MCL_PERF"); + if (s == 0 || strcmp(s, "1") != 0) return; + fprintf(stderr, "use perf suf=%s\n", suf); + suf_ = suf; + const int pid = getpid(); + char name[128]; + snprintf(name, sizeof(name), "/tmp/perf-%d.map", pid); + fp_ = fopen(name, "wb"); + if (fp_ == 0) throw cybozu::Exception("PerMap") << name; + prev_ = prev; +#else + (void)suf; + (void)prev; +#endif + } + ~Profiler() + { + close(); + } + void close() + { +#ifdef __linux__ + if (fp_ == 0) return; + fclose(fp_); + fp_ = 0; + prev_ = 0; +#endif + } + void set(const uint8_t *p, size_t n, const char *name) const + { +#ifdef __linux__ + if (fp_ == 0) return; + fprintf(fp_, "%llx %zx %s%s\n", (long long)p, n, name, suf_); +#else + (void)p; + (void)n; + (void)name; +#endif + } + void set(const char *name, const uint8_t *cur) + { +#ifdef __linux__ + set(prev_, cur - prev_, name); + prev_ = cur; +#else + (void)name; + (void)cur; +#endif + } +}; + struct FpGenerator : Xbyak::CodeGenerator { typedef Xbyak::RegExp RegExp; typedef Xbyak::Reg64 Reg64; @@ -192,28 +258,17 @@ struct FpGenerator : Xbyak::CodeGenerator { const Reg64& gt8; const Reg64& gt9; const mcl::fp::Op *op_; - Label *pL_; // valid only in init_inner + Label pL_; // pointer to p + // the following labels assume sf(this, 3, 10 | UseRDX) + Label mulPreL; + Label fpDbl_modL; + Label fp_mulL; const uint64_t *p_; uint64_t rp_; int pn_; int FpByte_; bool isFullBit_; - // add/sub without carry. return true if overflow - typedef bool (*bool3op)(uint64_t*, const uint64_t*, const uint64_t*); - - // add/sub with mod -// typedef void (*void3op)(uint64_t*, const uint64_t*, const uint64_t*); - - // mul without carry. return top of z - typedef uint64_t (*uint3opI)(uint64_t*, const uint64_t*, uint64_t); - - // neg - typedef void (*void2op)(uint64_t*, const uint64_t*); - - // preInv - typedef int (*int2op)(uint64_t*, const uint64_t*); - void4u mul_; -// uint3opI mulUnit_; + Profiler prof_; /* @param op [in] ; use op.p, op.N, op.isFullBit @@ -248,34 +303,25 @@ struct FpGenerator : Xbyak::CodeGenerator { , rp_(0) , pn_(0) , FpByte_(0) - , mul_(0) -// , mulUnit_(0) { useMulx_ = cpu_.has(Xbyak::util::Cpu::tBMI2); useAdx_ = cpu_.has(Xbyak::util::Cpu::tADX); } - void init(Op& op) + bool init(Op& op) { + if (!cpu_.has(Xbyak::util::Cpu::tAVX)) return false; reset(); // reset jit code for reuse setProtectModeRW(); // read/write memory init_inner(op); +// printf("code size=%d\n", (int)getSize()); setProtectModeRE(); // set read/exec memory + return true; } private: void init_inner(Op& op) { - // the following labels assume sf(this, 3, 10 | UseRDX) - Label mulPreL; - Label fpDbl_modL; - Label fp_mulL; - Label pL; // label to p_ op_ = &op; - pL_ = &pL; - /* - first 4096-byte is data area - remain is code area - */ - L(pL); + L(pL_); p_ = reinterpret_cast(getCurr()); for (size_t i = 0; i < op.N; i++) { dq(op.p[i]); @@ -285,167 +331,101 @@ private: FpByte_ = int(op.maxN * sizeof(uint64_t)); isFullBit_ = op.isFullBit; // printf("p=%p, pn_=%d, isFullBit_=%d\n", p_, pn_, isFullBit_); - // code from here - setSize(4096); - assert((getCurr() & 4095) == 0); - op.fp_addPre = getCurr(); - gen_addSubPre(true, pn_); - align(16); - op.fp_subPre = getCurr(); - gen_addSubPre(false, pn_); - align(16); - op.fp_sub = getCurr(); - op.fp_subA_ = getCurr(); - gen_fp_sub(); - align(16); - op.fp_add = getCurr(); - op.fp_addA_ = getCurr(); - gen_fp_add(); + static char suf[] = "_0"; + prof_.init(suf, getCurr()); + suf[1]++; - align(16); - op.fp_shr1 = getCurr(); - gen_shr1(); + op.fp_addPre = gen_addSubPre(true, pn_); + prof_.set("Fp_addPre", getCurr()); - align(16); - op.fp_negA_ = getCurr(); - gen_fp_neg(); + op.fp_subPre = gen_addSubPre(false, pn_); + prof_.set("Fp_subPre", getCurr()); - // setup fp_tower - op.fp2_mulNF = 0; - if (pn_ <= 4 || (pn_ == 6 && !isFullBit_)) { - align(16); - op.fpDbl_addA_ = getCurr(); - gen_fpDbl_add(); - align(16); - op.fpDbl_subA_ = getCurr(); - gen_fpDbl_sub(); - } - if (op.isFullBit) { - op.fpDbl_addPre = 0; - op.fpDbl_subPre = 0; - } else { - align(16); - op.fpDbl_addPreA_ = getCurr(); - gen_addSubPre(true, pn_ * 2); - align(16); - op.fpDbl_subPreA_ = getCurr(); - gen_addSubPre(false, pn_ * 2); - } - if ((useMulx_ && op.N == 2) || op.N == 3 || op.N == 4 || (useAdx_ && op.N == 6)) { - align(16); - op.fpDbl_mulPreA_ = getCurr(); - if (op.N == 4) { - /* - fpDbl_mulPre is available as C function - this function calls mulPreL directly. - */ - StackFrame sf(this, 3, 10 | UseRDX, 0, false); - mulPre4(gp0, gp1, gp2, sf.t); - sf.close(); // make epilog - L(mulPreL); // called only from asm code - mulPre4(gp0, gp1, gp2, sf.t); - ret(); - } else if (op.N == 6 && useAdx_) { -#if 1 - StackFrame sf(this, 3, 7 | UseRDX, 0, false); - mulPre6(gp0, gp1, gp2, sf.t); - sf.close(); // make epilog - L(mulPreL); // called only from asm code - mulPre6(gp0, gp1, gp2, sf.t); - ret(); -#else - { - StackFrame sf(this, 3, 7 | UseRDX); - mulPre6(gp0, gp1, gp2, sf.t); - } - { - StackFrame sf(this, 3, 10 | UseRDX, 0, false); - L(mulPreL); // called only from asm code - mulPre6(gp0, gp1, gp2, sf.t); - ret(); - } -#endif - } else { - gen_fpDbl_mulPre(); - } - } - if (op.N == 2 || op.N == 3 || op.N == 4 || (op.N == 6 && !isFullBit_ && useAdx_)) { - align(16); - op.fpDbl_modA_ = getCurr(); - if (op.N == 4) { - StackFrame sf(this, 3, 10 | UseRDX, 0, false); - call(fpDbl_modL); - sf.close(); - L(fpDbl_modL); - gen_fpDbl_mod4(gp0, gp1, sf.t, gp2); - ret(); - } else if (op.N == 6 && !isFullBit_ && useAdx_) { - StackFrame sf(this, 3, 10 | UseRDX, 0, false); - call(fpDbl_modL); - sf.close(); - L(fpDbl_modL); - Pack t = sf.t; - t.append(gp2); - gen_fpDbl_mod6(gp0, gp1, t); - ret(); - } else { - gen_fpDbl_mod(op); - } - } - if (op.N > 4) return; - if ((useMulx_ && op.N == 2) || op.N == 3 || op.N == 4) { - align(16); - op.fpDbl_sqrPreA_ = getCurr(); - gen_fpDbl_sqrPre(op); + op.fp_addA_ = gen_fp_add(); + prof_.set("Fp_add", getCurr()); + + op.fp_subA_ = gen_fp_sub(); + prof_.set("Fp_sub", getCurr()); + + op.fp_shr1 = gen_shr1(); + prof_.set("Fp_shr1", getCurr()); + + op.fp_negA_ = gen_fp_neg(); + prof_.set("Fp_neg", getCurr()); + + op.fpDbl_addA_ = gen_fpDbl_add(); + prof_.set("FpDbl_add", getCurr()); + + op.fpDbl_subA_ = gen_fpDbl_sub(); + prof_.set("FpDbl_sub", getCurr()); + + op.fpDbl_addPre = gen_addSubPre(true, pn_ * 2); + prof_.set("FpDbl_addPre", getCurr()); + + op.fpDbl_subPre = gen_addSubPre(false, pn_ * 2); + prof_.set("FpDbl_subPre", getCurr()); + + op.fpDbl_mulPreA_ = gen_fpDbl_mulPre(); + prof_.set("FpDbl_mulPre", getCurr()); + + op.fpDbl_sqrPreA_ = gen_fpDbl_sqrPre(); + prof_.set("FpDbl_sqrPre", getCurr()); + + op.fpDbl_modA_ = gen_fpDbl_mod(op); + prof_.set("FpDbl_mod", getCurr()); + + op.fp_mulA_ = gen_mul(); + prof_.set("Fp_mul", getCurr()); + if (op.fp_mulA_) { + op.fp_mul = fp::func_ptr_cast(op.fp_mulA_); // used in toMont/fromMont } - align(16); - op.fp_mul = getCurr(); // used in toMont/fromMont - op.fp_mulA_ = getCurr(); - gen_mul(fp_mulL); -// if (op.N > 4) return; - align(16); - op.fp_sqrA_ = getCurr(); - gen_sqr(); + op.fp_sqrA_ = gen_sqr(); + prof_.set("Fp_sqr", getCurr()); + if (op.primeMode != PM_NIST_P192 && op.N <= 4) { // support general op.N but not fast for op.N > 4 align(16); op.fp_preInv = getCurr(); gen_preInv(); + prof_.set("preInv", getCurr()); } - if (op.N == 4 && !isFullBit_) { - align(16); - op.fp2_addA_ = getCurr(); - gen_fp2_add4(); - align(16); - op.fp2_subA_ = getCurr(); - gen_fp2_sub4(); - align(16); - op.fp2_negA_ = getCurr(); - gen_fp2_neg4(); - align(16); - op.fp2Dbl_mulPreA_ = getCurr(); - gen_fp2Dbl_mulPre(mulPreL); - align(16); - op.fp2Dbl_sqrPreA_ = getCurr(); - gen_fp2Dbl_sqrPre(mulPreL); - align(16); - op.fp2_mulA_ = getCurr(); - gen_fp2_mul4(fpDbl_modL); - align(16); - op.fp2_sqrA_ = getCurr(); - gen_fp2_sqr4(fp_mulL); - align(16); - op.fp2_mul_xiA_ = getCurr(); - gen_fp2_mul_xi4(); - } + if (op.xi_a == 0) return; // Fp2 is not used + op.fp2_addA_ = gen_fp2_add(); + prof_.set("Fp2_add", getCurr()); + + op.fp2_subA_ = gen_fp2_sub(); + prof_.set("Fp2_sub", getCurr()); + + op.fp2_negA_ = gen_fp2_neg(); + prof_.set("Fp2_neg", getCurr()); + + op.fp2_mulNF = 0; + op.fp2Dbl_mulPreA_ = gen_fp2Dbl_mulPre(); + prof_.set("Fp2Dbl_mulPre", getCurr()); + + op.fp2Dbl_sqrPreA_ = gen_fp2Dbl_sqrPre(); + prof_.set("Fp2Dbl_sqrPre", getCurr()); + + op.fp2_mulA_ = gen_fp2_mul(); + prof_.set("Fp2_mul", getCurr()); + + op.fp2_sqrA_ = gen_fp2_sqr(); + prof_.set("Fp2_sqr", getCurr()); + + op.fp2_mul_xiA_ = gen_fp2_mul_xi(); + prof_.set("Fp2_mul_xi", getCurr()); } - void gen_addSubPre(bool isAdd, int n) + u3u gen_addSubPre(bool isAdd, int n) { +// if (isFullBit_) return 0; + align(16); + u3u func = getCurr(); StackFrame sf(this, 3); if (isAdd) { gen_raw_add(sf.p[0], sf.p[1], sf.p[2], rax, n); } else { gen_raw_sub(sf.p[0], sf.p[1], sf.p[2], rax, n); } + return func; } /* pz[] = px[] + py[] @@ -498,7 +478,7 @@ private: } jmp(exit); L(nonZero); - mov(rax, (size_t)p_); + mov(rax, pL_); for (size_t i = 0; i < t.size(); i++) { mov(rdx, ptr [rax + i * 8]); if (i == 0) { @@ -626,7 +606,7 @@ private: mov(*fullReg, 0); adc(*fullReg, 0); } - mov(rax, (size_t)p_); + mov(rax, pL_); sub_rm(p1, rax); if (fullReg) { sbb(*fullReg, 0); @@ -646,7 +626,7 @@ private: const Pack& p1 = t.sub(pn_, pn_); load_rm(p0, px); sub_rm(p0, py, withCarry); - mov(rax, (size_t)p_); + mov(rax, pL_); load_rm(p1, rax); sbb(rax, rax); // rax = (x > y) ? 0 : -1 for (size_t i = 0; i < p1.size(); i++) { @@ -676,29 +656,29 @@ private: gen_raw_fp_sub(pz, px, py, sf.t, false); } /* - add(pz + offset, px + offset, py + offset); + add(pz, px, py); size of t1, t2 == 6 destroy t0, t1 */ - void gen_raw_fp_add6(const Reg64& pz, const Reg64& px, const Reg64& py, int offset, const Pack& t1, const Pack& t2, bool withCarry) + void gen_raw_fp_add6(const RegExp& pz, const RegExp& px, const RegExp& py, const Pack& t1, const Pack& t2, bool withCarry) { - load_rm(t1, px + offset); - add_rm(t1, py + offset, withCarry); + load_rm(t1, px); + add_rm(t1, py, withCarry); Label exit; if (isFullBit_) { jnc("@f"); - mov(t2[0], *pL_); // t2 is not used + mov(t2[0], pL_); // t2 is not used sub_rm(t1, t2[0]); jmp(exit); L("@@"); } mov_rr(t2, t1); - sub_rm(t2, rip + *pL_); + sub_rm(t2, rip + pL_); for (int i = 0; i < 6; i++) { cmovnc(t1[i], t2[i]); } L(exit); - store_mr(pz + offset, t1); + store_mr(pz, t1); } void gen_fp_add6() { @@ -713,17 +693,19 @@ private: Pack t2 = sf.t.sub(6); t2.append(rax); t2.append(px); // destory after used - gen_raw_fp_add6(pz, px, py, 0, t1, t2, false); + gen_raw_fp_add6(pz, px, py, t1, t2, false); } - void gen_fp_add() + void3u gen_fp_add() { + align(16); + void3u func = getCurr(); if (pn_ <= 4) { gen_fp_add_le4(); - return; + return func; } if (pn_ == 6) { gen_fp_add6(); - return; + return func; } StackFrame sf(this, 3, 0, pn_ * 8); const Reg64& pz = sf.p[0]; @@ -733,7 +715,7 @@ private: inLocalLabel(); gen_raw_add(pz, px, py, rax, pn_); - mov(px, (size_t)p_); // destroy px + mov(px, pL_); // destroy px if (isFullBit_) { jc(".over", jmpMode); } @@ -759,9 +741,12 @@ private: L(".exit"); #endif outLocalLabel(); + return func; } - void gen_fpDbl_add() + void3u gen_fpDbl_add() { + align(16); + void3u func = getCurr(); if (pn_ <= 4) { int tn = pn_ * 2 + (isFullBit_ ? 1 : 0); StackFrame sf(this, 3, tn); @@ -770,6 +755,7 @@ private: const Reg64& py = sf.p[2]; gen_raw_add(pz, px, py, rax, pn_); gen_raw_fp_add(pz + 8 * pn_, px + 8 * pn_, py + 8 * pn_, sf.t, true); + return func; } else if (pn_ == 6 && !isFullBit_) { StackFrame sf(this, 3, 10); const Reg64& pz = sf.p[0]; @@ -780,14 +766,15 @@ private: Pack t2 = sf.t.sub(6); t2.append(rax); t2.append(py); - gen_raw_fp_add6(pz, px, py, pn_ * 8, t1, t2, true); - } else { - assert(0); - exit(1); + gen_raw_fp_add6(pz + pn_ * 8, px + pn_ * 8, py + pn_ * 8, t1, t2, true); + return func; } + return 0; } - void gen_fpDbl_sub() + void3u gen_fpDbl_sub() { + align(16); + void3u func = getCurr(); if (pn_ <= 4) { int tn = pn_ * 2; StackFrame sf(this, 3, tn); @@ -796,6 +783,7 @@ private: const Reg64& py = sf.p[2]; gen_raw_sub(pz, px, py, rax, pn_); gen_raw_fp_sub(pz + 8 * pn_, px + 8 * pn_, py + 8 * pn_, sf.t, true); + return func; } else if (pn_ == 6) { StackFrame sf(this, 3, 4); const Reg64& pz = sf.p[0]; @@ -806,12 +794,11 @@ private: t.append(rax); t.append(px); gen_raw_fp_sub6(pz, px, py, pn_ * 8, t, true); - } else { - assert(0); - exit(1); + return func; } + return 0; } - void gen_raw_fp_sub6(const Reg64& pz, const Reg64& px, const Reg64& py, int offset, const Pack& t, bool withCarry) + void gen_raw_fp_sub6(const RegExp& pz, const RegExp& px, const RegExp& py, int offset, const Pack& t, bool withCarry) { load_rm(t, px + offset); sub_rm(t, py + offset, withCarry); @@ -819,7 +806,7 @@ private: jmp is faster than and-mask without jmp */ jnc("@f"); - add_rm(t, rip + *pL_); + add_rm(t, rip + pL_); L("@@"); store_mr(pz + offset, t); } @@ -834,15 +821,17 @@ private: t.append(px); // |t| = 6 gen_raw_fp_sub6(pz, px, py, 0, t, false); } - void gen_fp_sub() + void3u gen_fp_sub() { + align(16); + void3u func = getCurr(); if (pn_ <= 4) { gen_fp_sub_le4(); - return; + return func; } if (pn_ == 6) { gen_fp_sub6(); - return; + return func; } StackFrame sf(this, 3); const Reg64& pz = sf.p[0]; @@ -852,17 +841,23 @@ private: Label exit; gen_raw_sub(pz, px, py, rax, pn_); jnc(exit, jmpMode); - mov(px, (size_t)p_); + mov(px, pL_); gen_raw_add(pz, pz, px, rax, pn_); L(exit); + return func; } - void gen_fp_neg() + void2u gen_fp_neg() { + align(16); + void2u func = getCurr(); StackFrame sf(this, 2, UseRDX | pn_); gen_raw_neg(sf.p[0], sf.p[1], sf.t); + return func; } - void gen_shr1() + void2u gen_shr1() { + align(16); + void2u func = getCurr(); const int c = 1; StackFrame sf(this, 2, 1); const Reg64 *t0 = &rax; @@ -878,25 +873,54 @@ private: } shr(*t0, c); mov(ptr [pz + (pn_ - 1) * 8], *t0); + return func; } - void gen_mul(Label& fp_mulL) + void3u gen_mul() { + align(16); + void3u func = getCurr(); if (op_->primeMode == PM_NIST_P192) { StackFrame sf(this, 3, 10 | UseRDX, 8 * 6); mulPre3(rsp, sf.p[1], sf.p[2], sf.t); fpDbl_mod_NIST_P192(sf.p[0], rsp, sf.t); + return func; } if (pn_ == 3) { - gen_montMul3(p_, rp_); - } else if (pn_ == 4) { - gen_montMul4(fp_mulL, p_, rp_); -// } else if (pn_ == 6 && useAdx_) { -// gen_montMul6(fp_mulL, p_, rp_); - } else if (pn_ <= 9) { + gen_montMul3(); + return func; + } + if (pn_ == 4) { + gen_montMul4(); + return func; + } + if (pn_ == 6 && !isFullBit_ && useMulx_ && useAdx_) { +#if 1 + // a little faster + gen_montMul6(); +#else + if (mulPreL.getAddress() == 0 || fpDbl_modL.getAddress() == 0) return 0; + StackFrame sf(this, 3, 10 | UseRDX, 12 * 8); + /* + use xm3 + rsp + [0, ..12 * 8) ; mul(x, y) + */ + vmovq(xm3, gp0); + mov(gp0, rsp); + call(mulPreL); // gp0, x, y + vmovq(gp0, xm3); + mov(gp1, rsp); + call(fpDbl_modL); +#endif + return func; + } +#if 0 + if (pn_ <= 9) { gen_montMulN(p_, rp_, pn_); - } else { - throw cybozu::Exception("mcl:FpGenerator:gen_mul:not implemented for") << pn_; + return func; } +#endif + return 0; } /* @input (z, xy) @@ -926,7 +950,7 @@ private: mov(a, rp_); mul(t6); - mov(t0, (uint64_t)p_); + mov(t0, pL_); mov(t7, a); // q // [d:t7:t1] = p * q @@ -995,7 +1019,7 @@ private: mov(a, rp_); mul(t10); - mov(t0, (uint64_t)p_); + mov(t0, pL_); mov(t7, a); // q // [d:t7:t2:t1] = p * q @@ -1070,12 +1094,12 @@ private: const Reg64& a = rax; const Reg64& d = rdx; - movq(xm0, z); + vmovq(xm0, z); mov(z, ptr [xy + 8 * 0]); mov(a, rp_); mul(z); - mov(t0, (uint64_t)p_); + mov(t0, pL_); mov(t7, a); // q // [d:t7:t3:t2:t1] = p * q @@ -1097,7 +1121,7 @@ private: if (isFullBit_) { mov(t5, 0); adc(t5, 0); - movq(xm2, t5); + vmovq(xm2, t5); } // free z, t0, t1, t5, t6, xy @@ -1106,18 +1130,18 @@ private: mul(t2); mov(z, a); // q - movq(xm1, t10); + vmovq(xm1, t10); // [d:z:t5:t6:xy] = p * q mul4x1(t0, z, t1, t5, t6, xy, t10); - movq(t10, xm1); + vmovq(t10, xm1); add_rr(Pack(t8, t4, t7, t3, t2), Pack(d, z, t5, t6, xy)); adc(t9, 0); adc(t10, 0); // [t10:t9:t8:t4:t7:t3] if (isFullBit_) { - movq(t5, xm2); + vmovq(t5, xm2); adc(t5, 0); - movq(xm2, t5); + vmovq(xm2, t5); } // free z, t0, t1, t2, t5, t6, xy @@ -1132,7 +1156,7 @@ private: add_rr(Pack(t9, t8, t4, t7, t3), Pack(d, z, t5, xy, t6)); adc(t10, 0); // c' = [t10:t9:t8:t4:t7] if (isFullBit_) { - movq(t3, xm2); + vmovq(t3, xm2); adc(t3, 0); } @@ -1161,60 +1185,112 @@ private: cmovc(t9, t2); cmovc(t10, t6); - movq(z, xm0); + vmovq(z, xm0); store_mr(z, Pack(t10, t9, t8, t4)); } - void gen_fpDbl_mod(const mcl::fp::Op& op) + void2u gen_fpDbl_mod(const fp::Op& op) { + align(16); + void2u func = getCurr(); if (op.primeMode == PM_NIST_P192) { StackFrame sf(this, 2, 6 | UseRDX); fpDbl_mod_NIST_P192(sf.p[0], sf.p[1], sf.t); - return; + return func; } #if 0 if (op.primeMode == PM_NIST_P521) { StackFrame sf(this, 2, 8 | UseRDX); fpDbl_mod_NIST_P521(sf.p[0], sf.p[1], sf.t); - return; + return func; } #endif - switch (pn_) { - case 2: + if (pn_ == 2) { gen_fpDbl_mod2(); - break; - case 3: + return func; + } + if (pn_ == 3) { gen_fpDbl_mod3(); - break; -#if 0 - case 4: - { - StackFrame sf(this, 3, 10 | UseRDX); - gen_fpDbl_mod4(gp0, gp1, sf.t, gp2); - } - break; -#endif - default: - throw cybozu::Exception("gen_fpDbl_mod:not support") << pn_; + return func; + } + if (pn_ == 4) { + StackFrame sf(this, 3, 10 | UseRDX, 0, false); + call(fpDbl_modL); + sf.close(); + L(fpDbl_modL); + gen_fpDbl_mod4(gp0, gp1, sf.t, gp2); + ret(); + return func; + } + if (pn_ == 6 && !isFullBit_ && useMulx_ && useAdx_) { + StackFrame sf(this, 3, 10 | UseRDX, 0, false); + call(fpDbl_modL); + sf.close(); + L(fpDbl_modL); + Pack t = sf.t; + t.append(gp2); + gen_fpDbl_mod6(gp0, gp1, t); + ret(); + return func; } + return 0; } - void gen_sqr() + void2u gen_sqr() { + align(16); + void2u func = getCurr(); if (op_->primeMode == PM_NIST_P192) { - StackFrame sf(this, 2, 10 | UseRDX | UseRCX, 8 * 6); - sqrPre3(rsp, sf.p[1], sf.t); + StackFrame sf(this, 3, 10 | UseRDX, 6 * 8); + Pack t = sf.t; + t.append(sf.p[2]); + sqrPre3(rsp, sf.p[1], t); fpDbl_mod_NIST_P192(sf.p[0], rsp, sf.t); + return func; } if (pn_ == 3) { - gen_montSqr3(p_, rp_); - return; + gen_montSqr3(); + return func; } - // sqr(y, x) = mul(y, x, x) + if (pn_ == 4 && useMulx_) { +#if 1 + // sqr(y, x) = mul(y, x, x) #ifdef XBYAK64_WIN - mov(r8, rdx); + mov(r8, rdx); #else - mov(rdx, rsi); + mov(rdx, rsi); +#endif + jmp((const void*)op_->fp_mulA_); +#else // (sqrPre + mod) is slower than mul + StackFrame sf(this, 3, 10 | UseRDX, 8 * 8); + Pack t = sf.t; + t.append(sf.p[2]); + sqrPre4(rsp, sf.p[1], t); + mov(gp0, sf.p[0]); + mov(gp1, rsp); + call(fpDbl_modL); #endif - jmp((const void*)op_->fp_mulA_); + return func; + } + if (pn_ == 6 && !isFullBit_ && useMulx_ && useAdx_) { + if (fpDbl_modL.getAddress() == 0) return 0; + StackFrame sf(this, 3, 10 | UseRDX, (12 + 6) * 8); + /* + use xm3 + rsp + [6 * 8, (12 + 6) * 8) ; sqrPre(x, x) + [0..6 * 8) ; stack for sqrPre6 + */ + vmovq(xm3, gp0); + Pack t = sf.t; + t.append(sf.p[2]); + // sqrPre6 uses 6 * 8 bytes stack + sqrPre6(rsp + 6 * 8, sf.p[1], t); + mov(gp0, ptr[rsp + (12 + 6) * 8]); + vmovq(gp0, xm3); + lea(gp1, ptr[rsp + 6 * 8]); + call(fpDbl_modL); + return func; + } + return 0; } /* input (pz[], px[], py[]) @@ -1259,7 +1335,7 @@ private: z[0..3] <- montgomery(x[0..3], y[0..3]) destroy gt0, ..., gt9, xm0, xm1, p2 */ - void gen_montMul4(Label& fp_mulL, const uint64_t *p, uint64_t pp) + void gen_montMul4() { StackFrame sf(this, 3, 10 | UseRDX, 0, false); call(fp_mulL); @@ -1280,23 +1356,23 @@ private: const Reg64& t9 = sf.t[9]; L(fp_mulL); - movq(xm0, p0); // save p0 - mov(p0, (uint64_t)p); - movq(xm1, p2); + vmovq(xm0, p0); // save p0 + mov(p0, pL_); + vmovq(xm1, p2); mov(p2, ptr [p2]); - montgomery4_1(pp, t0, t7, t3, t2, t1, p1, p2, p0, t4, t5, t6, t8, t9, true, xm2); + montgomery4_1(rp_, t0, t7, t3, t2, t1, p1, p2, p0, t4, t5, t6, t8, t9, true, xm2); - movq(p2, xm1); + vmovq(p2, xm1); mov(p2, ptr [p2 + 8]); - montgomery4_1(pp, t1, t0, t7, t3, t2, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2); + montgomery4_1(rp_, t1, t0, t7, t3, t2, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2); - movq(p2, xm1); + vmovq(p2, xm1); mov(p2, ptr [p2 + 16]); - montgomery4_1(pp, t2, t1, t0, t7, t3, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2); + montgomery4_1(rp_, t2, t1, t0, t7, t3, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2); - movq(p2, xm1); + vmovq(p2, xm1); mov(p2, ptr [p2 + 24]); - montgomery4_1(pp, t3, t2, t1, t0, t7, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2); + montgomery4_1(rp_, t3, t2, t1, t0, t7, p1, p2, p0, t4, t5, t6, t8, t9, false, xm2); // [t7:t3:t2:t1:t0] mov(t4, t0); @@ -1310,16 +1386,131 @@ private: cmovc(t2, t6); cmovc(t3, rdx); - movq(p0, xm0); // load p0 + vmovq(p0, xm0); // load p0 store_mr(p0, Pack(t3, t2, t1, t0)); ret(); } + /* + c[n+2] = c[n+1] + px[n] * rdx + use rax + */ + void mulAdd(const Pack& c, int n, const RegExp& px) + { + const Reg64& a = rax; + xor_(a, a); + for (int i = 0; i < n; i++) { + mulx(c[n + 1], a, ptr [px + i * 8]); + adox(c[i], a); + adcx(c[i + 1], c[n + 1]); + } + mov(a, 0); + mov(c[n + 1], a); + adox(c[n], a); + adcx(c[n + 1], a); + adox(c[n + 1], a); + } + /* + input + c[6..0] + rdx = yi + use rax, rdx + output + c[7..1] + + if first: + c = x[5..0] * rdx + else: + c += x[5..0] * rdx + q = uint64_t(c0 * rp) + c += p * q + c >>= 64 + */ + void montgomery6_1(const Pack& c, const RegExp& px, const Reg64& t0, const Reg64& t1, bool isFirst) + { + const int n = 6; + const Reg64& a = rax; + const Reg64& d = rdx; + if (isFirst) { + const Reg64 *pt0 = &a; + const Reg64 *pt1 = &t0; + // c[6..0] = px[5..0] * rdx + mulx(*pt0, c[0], ptr [px + 0 * 8]); + for (int i = 1; i < n; i++) { + mulx(*pt1, c[i], ptr[px + i * 8]); + if (i == 1) { + add(c[i], *pt0); + } else { + adc(c[i], *pt0); + } + std::swap(pt0, pt1); + } + mov(c[n], 0); + adc(c[n], *pt0); + } else { + // c[7..0] = c[6..0] + px[5..0] * rdx + mulAdd(c, 6, px); + } + mov(a, rp_); + mul(c[0]); // q = a + mov(d, a); + mov(t1, pL_); + // c += p * q + mulAdd(c, 6, t1); + } + /* + input (z, x, y) = (p0, p1, p2) + z[0..5] <- montgomery(x[0..5], y[0..5]) + destroy t0, ..., t9, rax, rdx + */ + void gen_montMul6() + { + assert(!isFullBit_ && useMulx_ && useAdx_); + StackFrame sf(this, 3, 10 | UseRDX, 0, false); + call(fp_mulL); + sf.close(); + const Reg64& pz = sf.p[0]; + const Reg64& px = sf.p[1]; + const Reg64& py = sf.p[2]; + + const Reg64& t0 = sf.t[0]; + const Reg64& t1 = sf.t[1]; + const Reg64& t2 = sf.t[2]; + const Reg64& t3 = sf.t[3]; + const Reg64& t4 = sf.t[4]; + const Reg64& t5 = sf.t[5]; + const Reg64& t6 = sf.t[6]; + const Reg64& t7 = sf.t[7]; + const Reg64& t8 = sf.t[8]; + const Reg64& t9 = sf.t[9]; + L(fp_mulL); + mov(rdx, ptr [py + 0 * 8]); + montgomery6_1(Pack(t7, t6, t5, t4, t3, t2, t1, t0), px, t8, t9, true); + mov(rdx, ptr [py + 1 * 8]); + montgomery6_1(Pack(t0, t7, t6, t5, t4, t3, t2, t1), px, t8, t9, false); + mov(rdx, ptr [py + 2 * 8]); + montgomery6_1(Pack(t1, t0, t7, t6, t5, t4, t3, t2), px, t8, t9, false); + mov(rdx, ptr [py + 3 * 8]); + montgomery6_1(Pack(t2, t1, t0, t7, t6, t5, t4, t3), px, t8, t9, false); + mov(rdx, ptr [py + 4 * 8]); + montgomery6_1(Pack(t3, t2, t1, t0, t7, t6, t5, t4), px, t8, t9, false); + mov(rdx, ptr [py + 5 * 8]); + montgomery6_1(Pack(t4, t3, t2, t1, t0, t7, t6, t5), px, t8, t9, false); + // [t4:t3:t2:t1:t0:t7:t6] + const Pack z = Pack(t3, t2, t1, t0, t7, t6); + const Pack keep = Pack(rdx, rax, px, py, t8, t9); + mov_rr(keep, z); + mov(t5, pL_); + sub_rm(z, t5); + cmovc_rr(z, keep); + store_mr(pz, z); + ret(); + } /* input (z, x, y) = (p0, p1, p2) z[0..2] <- montgomery(x[0..2], y[0..2]) destroy gt0, ..., gt9, xm0, xm1, p2 */ - void gen_montMul3(const uint64_t *p, uint64_t pp) + void gen_montMul3() { StackFrame sf(this, 3, 10 | UseRDX); const Reg64& p0 = sf.p[0]; @@ -1337,16 +1528,16 @@ private: const Reg64& t8 = sf.t[8]; const Reg64& t9 = sf.t[9]; - movq(xm0, p0); // save p0 - mov(t7, (uint64_t)p); + vmovq(xm0, p0); // save p0 + mov(t7, pL_); mov(t9, ptr [p2]); // c3, c2, c1, c0, px, y, p, - montgomery3_1(pp, t0, t3, t2, t1, p1, t9, t7, t4, t5, t6, t8, p0, true); + montgomery3_1(rp_, t0, t3, t2, t1, p1, t9, t7, t4, t5, t6, t8, p0, true); mov(t9, ptr [p2 + 8]); - montgomery3_1(pp, t1, t0, t3, t2, p1, t9, t7, t4, t5, t6, t8, p0, false); + montgomery3_1(rp_, t1, t0, t3, t2, p1, t9, t7, t4, t5, t6, t8, p0, false); mov(t9, ptr [p2 + 16]); - montgomery3_1(pp, t2, t1, t0, t3, p1, t9, t7, t4, t5, t6, t8, p0, false); + montgomery3_1(rp_, t2, t1, t0, t3, p1, t9, t7, t4, t5, t6, t8, p0, false); // [(t3):t2:t1:t0] mov(t4, t0); @@ -1357,7 +1548,7 @@ private: cmovc(t0, t4); cmovc(t1, t5); cmovc(t2, t6); - movq(p0, xm0); + vmovq(p0, xm0); store_mr(p0, Pack(t2, t1, t0)); } /* @@ -1365,7 +1556,7 @@ private: z[0..2] <- montgomery(px[0..2], px[0..2]) destroy gt0, ..., gt9, xm0, xm1, p2 */ - void gen_montSqr3(const uint64_t *p, uint64_t pp) + void gen_montSqr3() { StackFrame sf(this, 3, 10 | UseRDX, 16 * 3); const Reg64& pz = sf.p[0]; @@ -1383,24 +1574,24 @@ private: const Reg64& t8 = sf.t[8]; const Reg64& t9 = sf.t[9]; - movq(xm0, pz); // save pz - mov(t7, (uint64_t)p); + vmovq(xm0, pz); // save pz + mov(t7, pL_); mov(t9, ptr [px]); mul3x1_sqr1(px, t9, t3, t2, t1, t0); mov(t0, rdx); - montgomery3_sub(pp, t0, t9, t2, t1, px, t3, t7, t4, t5, t6, t8, pz, true); + montgomery3_sub(rp_, t0, t9, t2, t1, px, t3, t7, t4, t5, t6, t8, pz, true); mov(t3, ptr [px + 8]); mul3x1_sqr2(px, t3, t6, t5, t4); add_rr(Pack(t1, t0, t9, t2), Pack(rdx, rax, t5, t4)); if (isFullBit_) setc(pz.cvt8()); - montgomery3_sub(pp, t1, t3, t9, t2, px, t0, t7, t4, t5, t6, t8, pz, false); + montgomery3_sub(rp_, t1, t3, t9, t2, px, t0, t7, t4, t5, t6, t8, pz, false); mov(t0, ptr [px + 16]); mul3x1_sqr3(t0, t5, t4); add_rr(Pack(t2, t1, t3, t9), Pack(rdx, rax, t5, t4)); if (isFullBit_) setc(pz.cvt8()); - montgomery3_sub(pp, t2, t0, t3, t9, px, t1, t7, t4, t5, t6, t8, pz, false); + montgomery3_sub(rp_, t2, t0, t3, t9, px, t1, t7, t4, t5, t6, t8, pz, false); // [t9:t2:t0:t3] mov(t4, t3); @@ -1411,18 +1602,17 @@ private: cmovc(t3, t4); cmovc(t0, t5); cmovc(t2, t6); - movq(pz, xm0); + vmovq(pz, xm0); store_mr(pz, Pack(t2, t0, t3)); } /* py[5..0] <- px[2..0]^2 - @note use rax, rdx, rcx! + @note use rax, rdx */ void sqrPre3(const RegExp& py, const RegExp& px, const Pack& t) { const Reg64& a = rax; const Reg64& d = rdx; - const Reg64& c = rcx; const Reg64& t0 = t[0]; const Reg64& t1 = t[1]; const Reg64& t2 = t[2]; @@ -1433,6 +1623,7 @@ private: const Reg64& t7 = t[7]; const Reg64& t8 = t[8]; const Reg64& t9 = t[9]; + const Reg64& t10 = t[10]; if (useMulx_) { mov(d, ptr [px + 8 * 0]); @@ -1453,7 +1644,7 @@ private: mov(d, t7); mulx(t8, t7, d); - mulx(c, t9, t9); + mulx(t10, t9, t9); } else { mov(t9, ptr [px + 8 * 0]); mov(a, t9); @@ -1484,11 +1675,11 @@ private: mov(a, ptr [px + 8 * 2]); mul(t9); mov(t9, a); - mov(c, d); + mov(t10, d); } add(t2, t7); adc(t8, t9); - mov(t7, c); + mov(t7, t10); adc(t7, 0); // [t7:t8:t2:t1] add(t0, t1); @@ -1500,7 +1691,7 @@ private: mov(a, ptr [px + 8 * 2]); mul(a); add(t4, t9); - adc(a, c); + adc(a, t10); adc(d, 0); // [d:a:t4:t3] add(t2, t3); @@ -1537,13 +1728,13 @@ private: const Reg64& a = rax; const Reg64& d = rdx; mov(d, ptr [px]); - mulx(hi, a, ptr [py + 8 * 0]); - adox(pd[0], a); - mov(ptr [pz], pd[0]); - for (size_t i = 1; i < pd.size(); i++) { - adcx(pd[i], hi); - mulx(hi, a, ptr [py + 8 * i]); + xor_(a, a); + for (size_t i = 0; i < pd.size(); i++) { + mulx(hi, a, ptr [py + i * 8]); adox(pd[i], a); + if (i == 0) mov(ptr[pz], pd[0]); + if (i == pd.size() - 1) break; + adcx(pd[i + 1], hi); } mov(d, 0); adcx(hi, d); @@ -1611,6 +1802,7 @@ private: if (useMulx_) { mulPack(pz, px, py, Pack(t2, t1, t0)); +#if 0 // a little slow if (useAdx_) { // [t2:t1:t0] mulPackAdd(pz + 8 * 1, px + 8 * 1, py, t3, Pack(t2, t1, t0)); @@ -1620,6 +1812,7 @@ private: store_mr(pz + 8 * 3, Pack(t4, t3, t2)); return; } +#endif } else { mov(t5, ptr [px]); mov(a, ptr [py + 8 * 0]); @@ -1749,6 +1942,7 @@ private: } /* py[7..0] = px[3..0] ^ 2 + use xmm0 */ void sqrPre4(const RegExp& py, const RegExp& px, const Pack& t) { @@ -1762,30 +1956,76 @@ private: const Reg64& t7 = t[7]; const Reg64& t8 = t[8]; const Reg64& t9 = t[9]; + const Reg64& t10 = t[10]; + const Reg64& a = rax; + const Reg64& d = rdx; - // (AN + B)^2 = A^2N^2 + 2AB + B^2 - - mul2x2(px + 8 * 0, px + 8 * 2, t4, t3, t2, t1, t0); - // [t3:t2:t1:t0] = AB - xor_(t4, t4); - add_rr(Pack(t4, t3, t2, t1, t0), Pack(t4, t3, t2, t1, t0)); - // [t4:t3:t2:t1:t0] = 2AB - store_mr(py + 8 * 2, Pack(t4, t3, t2, t1, t0)); - - mov(t8, ptr [px + 8 * 0]); - mov(t9, ptr [px + 8 * 1]); - sqr2(t1, t0, t7, t6, t9, t8, rax, rcx); - // B^2 = [t1:t0:t7:t6] - store_mr(py + 8 * 0, Pack(t7, t6)); - // [t1:t0] - - mov(t8, ptr [px + 8 * 2]); - mov(t9, ptr [px + 8 * 3]); - sqr2(t5, t4, t3, t2, t9, t8, rax, rcx); - // [t5:t4:t3:t2] - add_rm(Pack(t4, t3, t2, t1, t0), py + 8 * 2); - adc(t5, 0); - store_mr(py + 8 * 2, Pack(t5, t4, t3, t2, t1, t0)); + /* + (aN + b)^2 = a^2 N^2 + 2ab N + b^2 + */ + load_rm(Pack(t9, t8), px); + sqr2(t3, t2, t1, t0, t9, t8, t7, t6); + // [t3:t2:t1:t0] = b^2 + store_mr(py, Pack(t1, t0)); + vmovq(xm0, t2); + mul2x2(px, px + 2 * 8, t6, t5, t4, t1, t0); + // [t5:t4:t1:t0] = ab + xor_(t6, t6); + add_rr(Pack(t6, t5, t4, t1, t0), Pack(t6, t5, t4, t1, t0)); + // [t6:t5:t4:t1:t0] = 2ab + load_rm(Pack(t8, t7), px + 2 * 8); + // free t10, t9, rax, rdx + /* + [d:t8:t10:t9] = [t8:t7]^2 + */ + mov(d, t7); + mulx(t10, t9, t7); // [t10:t9] = t7^2 + mulx(t7, t2, t8); // [t7:t2] = t7 t8 + xor_(a, a); + add_rr(Pack(a, t7, t2), Pack(a, t7, t2)); + // [a:t7:t2] = 2 t7 t8 + mov(d, t8); + mulx(d, t8, t8); // [d:t8] = t8^2 + add_rr(Pack(d, t8, t10), Pack(a, t7, t2)); + // [d:t8:t10:t9] = [t8:t7]^2 + vmovq(t2, xm0); + add_rr(Pack(t8, t10, t9, t3, t2), Pack(t6, t5, t4, t1, t0)); + adc(d, 0); + store_mr(py + 2 * 8, Pack(d, t8, t10, t9, t3, t2)); + } + /* + py[11..0] = px[5..0] ^ 2 + use rax, rdx, stack[6 * 8] + */ + void sqrPre6(const RegExp& py, const RegExp& px, const Pack& t) + { + const Reg64& t0 = t[0]; + const Reg64& t1 = t[1]; + const Reg64& t2 = t[2]; + /* + (aN + b)^2 = a^2 N^2 + 2ab N + b^2 + */ + sqrPre3(py, px, t); // [py] <- b^2 + sqrPre3(py + 6 * 8, px + 3 * 8, t); // [py + 6 * 8] <- a^2 + mulPre3(rsp, px, px + 3 * 8, t); // ab + Pack ab = t.sub(0, 6); + load_rm(ab, rsp); + xor_(rax, rax); + for (int i = 0; i < 6; i++) { + if (i == 0) { + add(ab[i], ab[i]); + } else { + adc(ab[i], ab[i]); + } + } + adc(rax, rax); + add_rm(ab, py + 3 * 8); + store_mr(py + 3 * 8, ab); + load_rm(Pack(t2, t1, t0), py + 9 * 8); + adc(t0, rax); + adc(t1, 0); + adc(t2, 0); + store_mr(py + 9 * 8, Pack(t2, t1, t0)); } /* pz[7..0] <- px[3..0] * py[3..0] @@ -1805,6 +2045,16 @@ private: const Reg64& t8 = t[8]; const Reg64& t9 = t[9]; +#if 0 // a little slower + if (useMulx_ && useAdx_) { + mulPack(pz, px, py, Pack(t3, t2, t1, t0)); + mulPackAdd(pz + 8 * 1, px + 8 * 1, py, t4, Pack(t3, t2, t1, t0)); + mulPackAdd(pz + 8 * 2, px + 8 * 2, py, t0, Pack(t4, t3, t2, t1)); + mulPackAdd(pz + 8 * 3, px + 8 * 3, py, t1, Pack(t0, t4, t3, t2)); + store_mr(pz + 8 * 4, Pack(t1, t0, t4, t3)); + return; + } +#endif #if 0 // a little slower if (!useMulx_) { @@ -1818,28 +2068,17 @@ private: mul2x2(px + 8 * 0, py + 8 * 0, t9, t8, t7, t6, t5); store_mr(pz, Pack(t6, t5)); // [t8:t7] - movq(xm0, t7); - movq(xm1, t8); + vmovq(xm0, t7); + vmovq(xm1, t8); mul2x2(px + 8 * 2, py + 8 * 2, t8, t7, t9, t6, t5); - movq(a, xm0); - movq(d, xm1); + vmovq(a, xm0); + vmovq(d, xm1); add_rr(Pack(t4, t3, t2, t1, t0), Pack(t9, t6, t5, d, a)); adc(t7, 0); store_mr(pz + 8 * 2, Pack(t7, t4, t3, t2, t1, t0)); #else if (useMulx_) { mulPack(pz, px, py, Pack(t3, t2, t1, t0)); - if (0 && useAdx_) { // a little slower? - // [t3:t2:t1:t0] - mulPackAdd(pz + 8 * 1, px + 8 * 1, py, t4, Pack(t3, t2, t1, t0)); - // [t4:t3:t2:t1] - mulPackAdd(pz + 8 * 2, px + 8 * 2, py, t5, Pack(t4, t3, t2, t1)); - // [t5:t4:t3:t2] - mulPackAdd(pz + 8 * 3, px + 8 * 3, py, t0, Pack(t5, t4, t3, t2)); - // [t0:t5:t4:t3] - store_mr(pz + 8 * 4, Pack(t0, t5, t4, t3)); - return; - } } else { mov(t5, ptr [px]); mov(a, ptr [py + 8 * 0]); @@ -1894,12 +2133,111 @@ private: mov(ptr [pz + 8 * 7], d); #endif } - void mulPre6(const RegExp& pz, const RegExp& px, const RegExp& py, const Pack& t) + // [gp0] <- [gp1] * [gp2] + void mulPre6(const Pack& t) { + const Reg64& pz = gp0; + const Reg64& px = gp1; + const Reg64& py = gp2; const Reg64& t0 = t[0]; const Reg64& t1 = t[1]; const Reg64& t2 = t[2]; const Reg64& t3 = t[3]; +#if 0 // slower than basic multiplication(56clk -> 67clk) +// const Reg64& t7 = t[7]; +// const Reg64& t8 = t[8]; +// const Reg64& t9 = t[9]; + const Reg64& a = rax; + const Reg64& d = rdx; + const int stackSize = (3 + 3 + 6 + 1 + 1 + 1) * 8; // a+b, c+d, (a+b)(c+d), x, y, z + const int abPos = 0; + const int cdPos = abPos + 3 * 8; + const int abcdPos = cdPos + 3 * 8; + const int zPos = abcdPos + 6 * 8; + const int yPos = zPos + 8; + const int xPos = yPos + 8; + + sub(rsp, stackSize); + mov(ptr[rsp + zPos], pz); + mov(ptr[rsp + xPos], px); + mov(ptr[rsp + yPos], py); + /* + x = aN + b, y = cN + d + xy = abN^2 + ((a+b)(c+d) - ac - bd)N + bd + */ + xor_(a, a); + load_rm(Pack(t2, t1, t0), px); // b + add_rm(Pack(t2, t1, t0), px + 3 * 8); // a + b + adc(a, 0); + store_mr(pz, Pack(t2, t1, t0)); + vmovq(xm0, a); // carry1 + + xor_(a, a); + load_rm(Pack(t2, t1, t0), py); // d + add_rm(Pack(t2, t1, t0), py + 3 * 8); // c + d + adc(a, 0); + store_mr(pz + 3 * 8, Pack(t2, t1, t0)); + vmovq(xm1, a); // carry2 + + mulPre3(rsp + abcdPos, pz, pz + 3 * 8, t); // (a+b)(c+d) + + vmovq(a, xm0); + vmovq(d, xm1); + mov(t3, a); + and_(t3, d); // t3 = carry1 & carry2 + Label doNothing; + je(doNothing); + load_rm(Pack(t2, t1, t0), rsp + abcdPos + 3 * 8); + test(a, a); + je("@f"); + // add (c+d) + add_rm(Pack(t2, t1, t0), pz + 3 * 8); + adc(t3, 0); + L("@@"); + test(d, d); + je("@f"); + // add(a+b) + add_rm(Pack(t2, t1, t0), pz); + adc(t3, 0); + L("@@"); + store_mr(rsp + abcdPos + 3 * 8, Pack(t2, t1, t0)); + L(doNothing); + vmovq(xm0, t3); // save new carry + + + mov(gp0, ptr [rsp + zPos]); + mov(gp1, ptr [rsp + xPos]); + mov(gp2, ptr [rsp + yPos]); + mulPre3(gp0, gp1, gp2, t); // [rsp] <- bd + + mov(gp0, ptr [rsp + zPos]); + mov(gp1, ptr [rsp + xPos]); + mov(gp2, ptr [rsp + yPos]); + mulPre3(gp0 + 6 * 8, gp1 + 3 * 8, gp2 + 3 * 8, t); // [rsp + 6 * 8] <- ac + + mov(pz, ptr[rsp + zPos]); + vmovq(d, xm0); + for (int i = 0; i < 6; i++) { + mov(a, ptr[pz + (3 + i) * 8]); + if (i == 0) { + add(a, ptr[rsp + abcdPos + i * 8]); + } else { + adc(a, ptr[rsp + abcdPos + i * 8]); + } + mov(ptr[pz + (3 + i) * 8], a); + } + mov(a, ptr[pz + 9 * 8]); + adc(a, d); + mov(ptr[pz + 9 * 8], a); + jnc("@f"); + for (int i = 10; i < 12; i++) { + mov(a, ptr[pz + i * 8]); + adc(a, 0); + mov(ptr[pz + i * 8], a); + } + L("@@"); + add(rsp, stackSize); +#else const Reg64& t4 = t[4]; const Reg64& t5 = t[5]; const Reg64& t6 = t[6]; @@ -1911,6 +2249,7 @@ private: mulPackAdd(pz + 8 * 4, px + 8 * 4, py, t2, Pack(t1, t0, t6, t5, t4, t3)); // [t2:t1:t0:t6:t5:t4] mulPackAdd(pz + 8 * 5, px + 8 * 5, py, t3, Pack(t2, t1, t0, t6, t5, t4)); // [t3:t2:t1:t0:t6:t5] store_mr(pz + 8 * 6, Pack(t3, t2, t1, t0, t6, t5)); +#endif } /* @input (z, xy) @@ -1934,11 +2273,11 @@ private: const Reg64& a = rax; const Reg64& d = rdx; - movq(xm0, z); + vmovq(xm0, z); mov(z, ptr [xy + 0 * 8]); mov(a, rp_); mul(z); - lea(t0, ptr [rip + *pL_]); + lea(t0, ptr [rip + pL_]); load_rm(Pack(t7, t6, t5, t4, t3, t2, t1), xy); mov(d, a); // q mulPackAddShr(Pack(t7, t6, t5, t4, t3, t2, t1), t0, t10); @@ -1951,32 +2290,32 @@ private: // z = [t1:t0:t10:t9:t8:t7:t6:t5:t4:t3:t2] mov(a, rp_); mul(t2); - movq(xm1, t0); // save - lea(t0, ptr [rip + *pL_]); + vmovq(xm1, t0); // save + lea(t0, ptr [rip + pL_]); mov(d, a); - movq(xm2, t10); + vmovq(xm2, t10); mulPackAddShr(Pack(t8, t7, t6, t5, t4, t3, t2), t0, t10); - movq(t10, xm2); + vmovq(t10, xm2); adc(t9, rax); adc(t10, rax); - movq(t0, xm1); // load + vmovq(t0, xm1); // load adc(t0, rax); adc(t1, rax); // z = [t1:t0:t10:t9:t8:t7:t6:t5:t4:t3] mov(a, rp_); mul(t3); - lea(t2, ptr [rip + *pL_]); + lea(t2, ptr [rip + pL_]); mov(d, a); - movq(xm2, t10); + vmovq(xm2, t10); mulPackAddShr(Pack(t9, t8, t7, t6, t5, t4, t3), t2, t10); - movq(t10, xm2); + vmovq(t10, xm2); adc(t10, rax); adc(t0, rax); adc(t1, rax); // z = [t1:t0:t10:t9:t8:t7:t6:t5:t4] mov(a, rp_); mul(t4); - lea(t2, ptr [rip + *pL_]); + lea(t2, ptr [rip + pL_]); mov(d, a); mulPackAddShr(Pack(t10, t9, t8, t7, t6, t5, t4), t2, t3); adc(t0, rax); @@ -1984,14 +2323,14 @@ private: // z = [t1:t0:t10:t9:t8:t7:t6:t5] mov(a, rp_); mul(t5); - lea(t2, ptr [rip + *pL_]); + lea(t2, ptr [rip + pL_]); mov(d, a); mulPackAddShr(Pack(t0, t10, t9, t8, t7, t6, t5), t2, t3); adc(t1, a); // z = [t1:t0:t10:t9:t8:t7:t6] mov(a, rp_); mul(t6); - lea(t2, ptr [rip + *pL_]); + lea(t2, ptr [rip + pL_]); mov(d, a); mulPackAddShr(Pack(t1, t0, t10, t9, t8, t7, t6), t2, t3, true); // z = [t1:t0:t10:t9:t8:t7] @@ -2000,47 +2339,87 @@ private: mov_rr(keep, zp); sub_rm(zp, t2); // z -= p cmovc_rr(zp, keep); - movq(z, xm0); + vmovq(z, xm0); store_mr(z, zp); } - void gen_fpDbl_sqrPre(mcl::fp::Op& op) + void2u gen_fpDbl_sqrPre() { - if (useMulx_ && pn_ == 2) { + align(16); + void2u func = getCurr(); + if (pn_ == 2 && useMulx_) { StackFrame sf(this, 2, 7 | UseRDX); sqrPre2(sf.p[0], sf.p[1], sf.t); - return; + return func; } if (pn_ == 3) { - StackFrame sf(this, 2, 10 | UseRDX | UseRCX); - sqrPre3(sf.p[0], sf.p[1], sf.t); - return; + StackFrame sf(this, 3, 10 | UseRDX); + Pack t = sf.t; + t.append(sf.p[2]); + sqrPre3(sf.p[0], sf.p[1], t); + return func; } - if (useMulx_ && pn_ == 4) { - StackFrame sf(this, 2, 10 | UseRDX | UseRCX); - sqrPre4(sf.p[0], sf.p[1], sf.t); - return; + if (pn_ == 4 && useMulx_) { + StackFrame sf(this, 3, 10 | UseRDX); + Pack t = sf.t; + t.append(sf.p[2]); + sqrPre4(sf.p[0], sf.p[1], t); + return func; + } + if (pn_ == 6 && useMulx_ && useAdx_) { + StackFrame sf(this, 3, 10 | UseRDX, 6 * 8); + Pack t = sf.t; + t.append(sf.p[2]); + sqrPre6(sf.p[0], sf.p[1], t); + return func; } + return 0; +#if 0 #ifdef XBYAK64_WIN mov(r8, rdx); #else mov(rdx, rsi); #endif jmp((void*)op.fpDbl_mulPreA_); + return func; +#endif } - void gen_fpDbl_mulPre() + void3u gen_fpDbl_mulPre() { - if (useMulx_ && pn_ == 2) { + align(16); + void3u func = getCurr(); + if (pn_ == 2 && useMulx_) { StackFrame sf(this, 3, 5 | UseRDX); mulPre2(sf.p[0], sf.p[1], sf.p[2], sf.t); - return; + return func; } if (pn_ == 3) { StackFrame sf(this, 3, 10 | UseRDX); mulPre3(sf.p[0], sf.p[1], sf.p[2], sf.t); - return; + return func; } - assert(0); - exit(1); + if (pn_ == 4) { + /* + fpDbl_mulPre is available as C function + this function calls mulPreL directly. + */ + StackFrame sf(this, 3, 10 | UseRDX, 0, false); + mulPre4(gp0, gp1, gp2, sf.t); + sf.close(); // make epilog + L(mulPreL); // called only from asm code + mulPre4(gp0, gp1, gp2, sf.t); + ret(); + return func; + } + if (pn_ == 6 && useAdx_) { + StackFrame sf(this, 3, 10 | UseRDX, 0, false); + call(mulPreL); + sf.close(); // make epilog + L(mulPreL); // called only from asm code + mulPre6(sf.t); + ret(); + return func; + } + return 0; } static inline void debug_put_inner(const uint64_t *ptr, int n) { @@ -2250,10 +2629,10 @@ private: { if (n >= 10) exit(1); static uint64_t buf[10]; - movq(xm0, rax); + vmovq(xm0, rax); mov(rax, (size_t)buf); store_mp(rax, mp, t); - movq(rax, xm0); + vmovq(rax, xm0); push(rax); mov(rax, (size_t)buf); debug_put(rax, n); @@ -2270,11 +2649,8 @@ private: */ void gen_preInv() { - assert(pn_ >= 1); + assert(1 <= pn_ && pn_ <= 4); const int freeRegNum = 13; - if (pn_ > 9) { - throw cybozu::Exception("mcl:FpGenerator:gen_preInv:large pn_") << pn_; - } StackFrame sf(this, 2, 10 | UseRDX | UseRCX, (std::max(0, pn_ * 5 - freeRegNum) + 1 + (isFullBit_ ? 1 : 0)) * 8); const Reg64& pr = sf.p[0]; const Reg64& px = sf.p[1]; @@ -2307,7 +2683,7 @@ private: mov(rax, px); // px is free frome here load_mp(vv, rax, t); // v = x - mov(rax, (size_t)p_); + mov(rax, pL_); load_mp(uu, rax, t); // u = p_ // k = 0 xor_(rax, rax); @@ -2324,46 +2700,6 @@ private: } else { mov(qword [ss.getMem(0)], 1); } -#if 0 - L(".lp"); - or_mp(vv, t); - jz(".exit", T_NEAR); - - g_test(uu[0], 1); - jz(".u_even", T_NEAR); - g_test(vv[0], 1); - jz(".v_even", T_NEAR); - for (int i = pn_ - 1; i >= 0; i--) { - g_cmp(vv[i], uu[i], t); - jc(".v_lt_u", T_NEAR); - if (i > 0) jnz(".v_ge_u", T_NEAR); - } - - L(".v_ge_u"); - sub_mp(vv, uu, t); - add_mp(ss, rr, t); - L(".v_even"); - shr_mp(vv, 1, t); - twice_mp(rr, t); - if (isFullBit_) { - sbb(t, t); - mov(ptr [rTop], t); - } - inc(rax); - jmp(".lp", T_NEAR); - L(".v_lt_u"); - sub_mp(uu, vv, t); - add_mp(rr, ss, t); - if (isFullBit_) { - sbb(t, t); - mov(ptr [rTop], t); - } - L(".u_even"); - shr_mp(uu, 1, t); - twice_mp(ss, t); - inc(rax); - jmp(".lp", T_NEAR); -#else for (int cn = pn_; cn > 0; cn--) { const std::string _lp = mkLabel(".lp", cn); const std::string _u_v_odd = mkLabel(".u_v_odd", cn); @@ -2420,13 +2756,12 @@ private: uu.removeLast(); } } -#endif L(".exit"); assert(ss.isReg(0)); const Reg64& t2 = ss.getReg(0); const Reg64& t3 = rdx; - mov(t2, (size_t)p_); + mov(t2, pL_); if (isFullBit_) { mov(t, ptr [rTop]); test(t, t); @@ -3057,7 +3392,7 @@ private: mul4x1(px, y, t3, t2, t1, t0, t4); // [rdx:y:t2:t1:t0] = px[3..0] * y if (isFullBit_) { - movq(xt, px); + vmovq(xt, px); xor_(px, px); } add_rr(Pack(c4, y, c2, c1, c0), Pack(rdx, c3, t2, t1, t0)); @@ -3081,13 +3416,19 @@ private: adc(c0, 0); } else { adc(c0, px); - movq(px, xt); + vmovq(px, xt); } } } - void gen_fp2Dbl_mulPre(Label& mulPreL) + void3u gen_fp2Dbl_mulPre() { - assert(!isFullBit_); + if (isFullBit_) return 0; +// if (pn_ != 4 && !(pn_ == 6 && useMulx_ && useAdx_)) return 0; + // almost same for pn_ == 6 + if (pn_ != 4) return 0; + align(16); + void3u func = getCurr(); + const RegExp z = rsp + 0 * 8; const RegExp x = rsp + 1 * 8; const RegExp y = rsp + 2 * 8; @@ -3100,9 +3441,9 @@ private: mov(ptr [x], gp1); mov(ptr [y], gp2); // s = a + b - gen_raw_add(s, gp1, gp1 + FpByte_, rax, 4); + gen_raw_add(s, gp1, gp1 + FpByte_, rax, pn_); // t = c + d - gen_raw_add(t, gp2, gp2 + FpByte_, rax, 4); + gen_raw_add(t, gp2, gp2 + FpByte_, rax, pn_); // d1 = (a + b)(c + d) mov(gp0, ptr [z]); add(gp0, FpByte_ * 2); // d1 @@ -3127,20 +3468,33 @@ private: add(gp0, FpByte_ * 2); // d1 mov(gp1, gp0); mov(gp2, ptr [z]); - gen_raw_sub(gp0, gp1, gp2, rax, 8); + gen_raw_sub(gp0, gp1, gp2, rax, pn_ * 2); lea(gp2, ptr [d2]); - gen_raw_sub(gp0, gp1, gp2, rax, 8); + gen_raw_sub(gp0, gp1, gp2, rax, pn_ * 2); mov(gp0, ptr [z]); mov(gp1, gp0); lea(gp2, ptr [d2]); - gen_raw_sub(gp0, gp1, gp2, rax, 4); - gen_raw_fp_sub(gp0 + 8 * 4, gp1 + 8 * 4, gp2 + 8 * 4, Pack(gt0, gt1, gt2, gt3, gt4, gt5, gt6, gt7), true); + gen_raw_sub(gp0, gp1, gp2, rax, pn_); + if (pn_ == 4) { + gen_raw_fp_sub(gp0 + pn_ * 8, gp1 + pn_ * 8, gp2 + pn_ * 8, Pack(gt0, gt1, gt2, gt3, gt4, gt5, gt6, gt7), true); + } else { + assert(pn_ == 6); + gen_raw_fp_sub6(gp0, gp1, gp2, pn_ * 8, sf.t.sub(0, 6), true); + } + return func; } - void gen_fp2Dbl_sqrPre(Label& mulPreL) + void2u gen_fp2Dbl_sqrPre() { - assert(!isFullBit_); + if (isFullBit_) return 0; +// if (pn_ != 4 && !(pn_ == 6 && useMulx_ && useAdx_)) return 0; + // almost same for pn_ == 6 + if (pn_ != 4) return 0; + align(16); + void2u func = getCurr(); + // almost same for pn_ == 6 + if (pn_ != 4) return 0; const RegExp y = rsp + 0 * 8; const RegExp x = rsp + 1 * 8; const Ext1 t1(FpByte_, rsp, 2 * 8); @@ -3149,10 +3503,15 @@ private: StackFrame sf(this, 3 /* not 2 */, 10 | UseRDX, t2.next); mov(ptr [y], gp0); mov(ptr [x], gp1); - const Pack a = sf.t.sub(0, 4); - const Pack b = sf.t.sub(4, 4); + Pack t = sf.t; + if (pn_ == 6) { + t.append(rax); + t.append(rdx); + } + const Pack a = t.sub(0, pn_); + const Pack b = t.sub(pn_, pn_); load_rm(b, gp1 + FpByte_); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < pn_; i++) { mov(rax, b[i]); if (i == 0) { add(rax, rax); @@ -3170,11 +3529,17 @@ private: mov(gp2, ptr [x]); call(mulPreL); mov(gp0, ptr [x]); - gen_raw_fp_sub(t1, gp0, gp0 + FpByte_, sf.t, false); + if (pn_ == 4) { + gen_raw_fp_sub(t1, gp0, gp0 + FpByte_, sf.t, false); + } else { + assert(pn_ == 6); + gen_raw_fp_sub6(t1, gp0, gp0, FpByte_, a, false); + } mov(gp0, ptr [y]); lea(gp1, ptr [t1]); lea(gp2, ptr [t2]); call(mulPreL); + return func; } void gen_fp2_add4() { @@ -3183,6 +3548,61 @@ private: gen_raw_fp_add(sf.p[0], sf.p[1], sf.p[2], sf.t, false); gen_raw_fp_add(sf.p[0] + FpByte_, sf.p[1] + FpByte_, sf.p[2] + FpByte_, sf.t, false); } + void gen_fp2_add6() + { + assert(!isFullBit_); + StackFrame sf(this, 3, 10); + const Reg64& pz = sf.p[0]; + const Reg64& px = sf.p[1]; + const Reg64& py = sf.p[2]; + Pack t1 = sf.t.sub(0, 6); + Pack t2 = sf.t.sub(6); + t2.append(rax); + t2.append(px); // destory after used + vmovq(xm0, px); + gen_raw_fp_add6(pz, px, py, t1, t2, false); + vmovq(px, xm0); + gen_raw_fp_add6(pz + FpByte_, px + FpByte_, py + FpByte_, t1, t2, false); + } + void gen_fp2_sub6() + { + StackFrame sf(this, 3, 5); + const Reg64& pz = sf.p[0]; + const Reg64& px = sf.p[1]; + const Reg64& py = sf.p[2]; + Pack t = sf.t; + t.append(rax); + gen_raw_fp_sub6(pz, px, py, 0, t, false); + gen_raw_fp_sub6(pz, px, py, FpByte_, t, false); + } + void3u gen_fp2_add() + { + align(16); + void3u func = getCurr(); + if (pn_ == 4 && !isFullBit_) { + gen_fp2_add4(); + return func; + } + if (pn_ == 6 && !isFullBit_) { + gen_fp2_add6(); + return func; + } + return 0; + } + void3u gen_fp2_sub() + { + align(16); + void3u func = getCurr(); + if (pn_ == 4 && !isFullBit_) { + gen_fp2_sub4(); + return func; + } + if (pn_ == 6 && !isFullBit_) { + gen_fp2_sub6(); + return func; + } + return 0; + } void gen_fp2_sub4() { assert(!isFullBit_); @@ -3198,14 +3618,17 @@ private: void gen_fp2_mul_xi4() { assert(!isFullBit_); -#if 0 - StackFrame sf(this, 2, 10 | UseRDX | UseRCX); + StackFrame sf(this, 2, 11 | UseRDX); + const Reg64& py = sf.p[0]; + const Reg64& px = sf.p[1]; Pack a = sf.t.sub(0, 4); Pack b = sf.t.sub(4, 4); - Pack t(rdx, rcx, sf.t[8], sf.t[9]); - load_rm(a, sf.p[1]); - load_rm(b, sf.p[1] + FpByte_); - for (int i = 0; i < 4; i++) { + Pack t = sf.t.sub(8); + t.append(rdx); + assert(t.size() == 4); + load_rm(a, px); + load_rm(b, px + FpByte_); + for (int i = 0; i < pn_; i++) { mov(t[i], a[i]); if (i == 0) { add(t[i], b[i]); @@ -3214,41 +3637,78 @@ private: } } sub_rr(a, b); - mov(rax, (size_t)p_); + mov(rax, pL_); load_rm(b, rax); sbb(rax, rax); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < pn_; i++) { and_(b[i], rax); } add_rr(a, b); - store_mr(sf.p[0], a); - mov(rax, (size_t)p_); + store_mr(py, a); + mov(rax, pL_); mov_rr(a, t); sub_rm(t, rax); - for (int i = 0; i < 4; i++) { - cmovc(t[i], a[i]); + cmovc_rr(t, a); + store_mr(py + FpByte_, t); + } + void gen_fp2_mul_xi6() + { + assert(!isFullBit_); + StackFrame sf(this, 2, 12); + const Reg64& py = sf.p[0]; + const Reg64& px = sf.p[1]; + Pack a = sf.t.sub(0, 6); + Pack b = sf.t.sub(6); + load_rm(a, px); + mov_rr(b, a); + add_rm(b, px + FpByte_); + sub_rm(a, px + FpByte_); + mov(rax, pL_); + jnc("@f"); + add_rm(a, rax); + L("@@"); + store_mr(py, a); + mov_rr(a, b); + sub_rm(b, rax); + cmovc_rr(b, a); + store_mr(py + FpByte_, b); + } + void2u gen_fp2_mul_xi() + { + if (isFullBit_) return 0; + if (op_->xi_a != 1) return 0; + align(16); + void2u func = getCurr(); + if (pn_ == 4) { + gen_fp2_mul_xi4(); + return func; } - store_mr(sf.p[0] + FpByte_, t); -#else - StackFrame sf(this, 2, 8, 8 * 4); - gen_raw_fp_add(rsp, sf.p[1], sf.p[1] + FpByte_, sf.t, false); - gen_raw_fp_sub(sf.p[0], sf.p[1], sf.p[1] + FpByte_, sf.t, false); - for (int i = 0; i < 4; i++) { - mov(rax, ptr [rsp + i * 8]); - mov(ptr[sf.p[0] + FpByte_ + i * 8], rax); + if (pn_ == 6) { + gen_fp2_mul_xi6(); + return func; } -#endif + return 0; } - void gen_fp2_neg4() + void2u gen_fp2_neg() { - assert(!isFullBit_); - StackFrame sf(this, 2, UseRDX | pn_); - gen_raw_neg(sf.p[0], sf.p[1], sf.t); - gen_raw_neg(sf.p[0] + FpByte_, sf.p[1] + FpByte_, sf.t); + align(16); + void2u func = getCurr(); + if (pn_ <= 6) { + StackFrame sf(this, 2, UseRDX | pn_); + gen_raw_neg(sf.p[0], sf.p[1], sf.t); + gen_raw_neg(sf.p[0] + FpByte_, sf.p[1] + FpByte_, sf.t); + return func; + } + return 0; } - void gen_fp2_mul4(Label& fpDbl_modL) + void3u gen_fp2_mul() { - assert(!isFullBit_); + if (isFullBit_) return 0; + if (pn_ != 4 && !(pn_ == 6 && useMulx_ && useAdx_)) return 0; + align(16); + void3u func = getCurr(); + bool embedded = pn_ == 4; + const RegExp z = rsp + 0 * 8; const RegExp x = rsp + 1 * 8; const RegExp y = rsp + 2 * 8; @@ -3263,27 +3723,50 @@ private: mov(ptr[x], gp1); mov(ptr[y], gp2); // s = a + b - gen_raw_add(s, gp1, gp1 + FpByte_, rax, 4); + gen_raw_add(s, gp1, gp1 + FpByte_, rax, pn_); // t = c + d - gen_raw_add(t, gp2, gp2 + FpByte_, rax, 4); + gen_raw_add(t, gp2, gp2 + FpByte_, rax, pn_); // d1 = (a + b)(c + d) - mulPre4(d1, s, t, sf.t); + if (embedded) { + mulPre4(d1, s, t, sf.t); + } else { + lea(gp0, ptr [d1]); + lea(gp1, ptr [s]); + lea(gp2, ptr [t]); + call(mulPreL); + } // d0 = a c mov(gp1, ptr [x]); mov(gp2, ptr [y]); - mulPre4(d0, gp1, gp2, sf.t); + if (embedded) { + mulPre4(d0, gp1, gp2, sf.t); + } else { + lea(gp0, ptr [d0]); + call(mulPreL); + } // d2 = b d mov(gp1, ptr [x]); add(gp1, FpByte_); mov(gp2, ptr [y]); add(gp2, FpByte_); - mulPre4(d2, gp1, gp2, sf.t); + if (embedded) { + mulPre4(d2, gp1, gp2, sf.t); + } else { + lea(gp0, ptr [d2]); + call(mulPreL); + } - gen_raw_sub(d1, d1, d0, rax, 8); - gen_raw_sub(d1, d1, d2, rax, 8); + gen_raw_sub(d1, d1, d0, rax, pn_ * 2); + gen_raw_sub(d1, d1, d2, rax, pn_ * 2); - gen_raw_sub(d0, d0, d2, rax, 4); - gen_raw_fp_sub((RegExp)d0 + 8 * 4, (RegExp)d0 + 8 * 4, (RegExp)d2 + 8 * 4, Pack(gt0, gt1, gt2, gt3, gt4, gt5, gt6, gt7), true); + gen_raw_sub(d0, d0, d2, rax, pn_); + if (pn_ == 4) { + gen_raw_fp_sub((RegExp)d0 + pn_ * 8, (RegExp)d0 + pn_ * 8, (RegExp)d2 + pn_ * 8, Pack(gt0, gt1, gt2, gt3, gt4, gt5, gt6, gt7), true); + } else { + lea(gp0, ptr[d0]); + lea(gp2, ptr[d2]); + gen_raw_fp_sub6(gp0, gp0, gp2, pn_ * 8, sf.t.sub(0, 6), true); + } mov(gp0, ptr [z]); lea(gp1, ptr[d0]); @@ -3293,10 +3776,15 @@ private: add(gp0, FpByte_); lea(gp1, ptr[d1]); call(fpDbl_modL); + return func; } - void gen_fp2_sqr4(Label& fp_mulL) + void2u gen_fp2_sqr() { - assert(!isFullBit_); + if (isFullBit_) return 0; + if (pn_ != 4 && !(pn_ == 6 && useMulx_ && useAdx_)) return 0; + align(16); + void2u func = getCurr(); + const RegExp y = rsp + 0 * 8; const RegExp x = rsp + 1 * 8; const Ext1 t1(FpByte_, rsp, 2 * 8); @@ -3309,7 +3797,7 @@ private: // t1 = b + b lea(gp0, ptr [t1]); if (nocarry) { - for (int i = 0; i < 4; i++) { + for (int i = 0; i < pn_; i++) { mov(rax, ptr [gp1 + FpByte_ + i * 8]); if (i == 0) { add(rax, rax); @@ -3319,7 +3807,15 @@ private: mov(ptr [gp0 + i * 8], rax); } } else { - gen_raw_fp_add(gp0, gp1 + FpByte_, gp1 + FpByte_, sf.t, false); + if (pn_ == 4) { + gen_raw_fp_add(gp0, gp1 + FpByte_, gp1 + FpByte_, sf.t, false); + } else { + assert(pn_ == 6); + Pack t = sf.t.sub(6, 4); + t.append(rax); + t.append(rdx); + gen_raw_fp_add6(gp0, gp1 + FpByte_, gp1 + FpByte_, sf.t.sub(0, 6), t, false); + } } // t1 = 2ab mov(gp1, gp0); @@ -3327,13 +3823,16 @@ private: call(fp_mulL); if (nocarry) { - Pack a = sf.t.sub(0, 4); - Pack b = sf.t.sub(4, 4); + Pack t = sf.t; + t.append(rdx); + t.append(gp1); + Pack a = t.sub(0, pn_); + Pack b = t.sub(pn_, pn_); mov(gp0, ptr [x]); load_rm(a, gp0); load_rm(b, gp0 + FpByte_); // t2 = a + b - for (int i = 0; i < 4; i++) { + for (int i = 0; i < pn_; i++) { mov(rax, a[i]); if (i == 0) { add(rax, b[i]); @@ -3343,14 +3842,24 @@ private: mov(ptr [(RegExp)t2 + i * 8], rax); } // t3 = a + p - b - mov(gp1, (size_t)p_); - add_rm(a, gp1); + mov(rax, pL_); + add_rm(a, rax); sub_rr(a, b); store_mr(t3, a); } else { mov(gp0, ptr [x]); - gen_raw_fp_add(t2, gp0, gp0 + FpByte_, sf.t, false); - gen_raw_fp_sub(t3, gp0, gp0 + FpByte_, sf.t, false); + if (pn_ == 4) { + gen_raw_fp_add(t2, gp0, gp0 + FpByte_, sf.t, false); + gen_raw_fp_sub(t3, gp0, gp0 + FpByte_, sf.t, false); + } else { + assert(pn_ == 6); + Pack p1 = sf.t.sub(0, 6); + Pack p2 = sf.t.sub(6, 4); + p2.append(rax); + p2.append(rdx); + gen_raw_fp_add6(t2, gp0, gp0 + FpByte_, p1, p2, false); + gen_raw_fp_sub6(t3, gp0, gp0 + FpByte_, 0, p1, false); + } } mov(gp0, ptr [y]); @@ -3358,10 +3867,11 @@ private: lea(gp2, ptr [t3]); call(fp_mulL); mov(gp0, ptr [y]); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < pn_; i++) { mov(rax, ptr [(RegExp)t1 + i * 8]); mov(ptr [gp0 + FpByte_ + i * 8], rax); } + return func; } }; diff --git a/vendor/github.com/dexon-foundation/mcl/src/she_c_impl.hpp b/vendor/github.com/dexon-foundation/mcl/src/she_c_impl.hpp index 723765a3c..073bc2b34 100644 --- a/vendor/github.com/dexon-foundation/mcl/src/she_c_impl.hpp +++ b/vendor/github.com/dexon-foundation/mcl/src/she_c_impl.hpp @@ -5,7 +5,7 @@ #include #include #include -#include "../src/bn_c_impl.hpp" +#include "mcl/impl/bn_c_impl.hpp" #define MCLSHE_DLL_EXPORT #include diff --git a/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak.h b/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak.h index 47494ef09..bcfeb34bf 100644 --- a/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak.h +++ b/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak.h @@ -40,6 +40,8 @@ // This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft. #if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\ ((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__))) + #include + #define XBYAK_STD_UNORDERED_SET std::unordered_set #include #define XBYAK_STD_UNORDERED_MAP std::unordered_map #define XBYAK_STD_UNORDERED_MULTIMAP std::unordered_multimap @@ -49,16 +51,22 @@ libstdcxx 20070719 (from GCC 4.2.1, the last GPL 2 version). */ #elif XBYAK_GNUC_PREREQ(4, 5) || (XBYAK_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || defined(__llvm__) + #include + #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set #include #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap #elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER < 1600) + #include + #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set #include #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap #else + #include + #define XBYAK_STD_UNORDERED_SET std::set #include #define XBYAK_STD_UNORDERED_MAP std::map #define XBYAK_STD_UNORDERED_MULTIMAP std::multimap @@ -105,7 +113,7 @@ namespace Xbyak { enum { DEFAULT_MAX_CODE_SIZE = 4096, - VERSION = 0x5730 /* 0xABCD = A.BC(D) */ + VERSION = 0x5751 /* 0xABCD = A.BC(D) */ }; #ifndef MIE_INTEGER_TYPE_DEFINED @@ -925,10 +933,10 @@ public: void dq(uint64 code) { db(code, 8); } const uint8 *getCode() const { return top_; } template - const F getCode() const { return CastTo(top_); } + const F getCode() const { return reinterpret_cast(top_); } const uint8 *getCurr() const { return &top_[size_]; } template - const F getCurr() const { return CastTo(&top_[size_]); } + const F getCurr() const { return reinterpret_cast(&top_[size_]); } size_t getSize() const { return size_; } void setSize(size_t size) { @@ -1134,6 +1142,7 @@ public: Label(const Label& rhs); Label& operator=(const Label& rhs); ~Label(); + void clear() { mgr = 0; id = 0; } int getId() const { return id; } const uint8 *getAddress() const; @@ -1172,6 +1181,7 @@ class LabelManager { }; typedef XBYAK_STD_UNORDERED_MAP ClabelDefList; typedef XBYAK_STD_UNORDERED_MULTIMAP ClabelUndefList; + typedef XBYAK_STD_UNORDERED_SET LabelPtrList; CodeArray *base_; // global : stateList_.front(), local : stateList_.back() @@ -1179,6 +1189,7 @@ class LabelManager { mutable int labelId_; ClabelDefList clabelDefList_; ClabelUndefList clabelUndefList_; + LabelPtrList labelPtrList_; int getId(const Label& label) const { @@ -1227,9 +1238,14 @@ class LabelManager { return true; } friend class Label; - void incRefCount(int id) { clabelDefList_[id].refCount++; } - void decRefCount(int id) + void incRefCount(int id, Label *label) { + clabelDefList_[id].refCount++; + labelPtrList_.insert(label); + } + void decRefCount(int id, Label *label) + { + labelPtrList_.erase(label); ClabelDefList::iterator i = clabelDefList_.find(id); if (i == clabelDefList_.end()) return; if (i->second.refCount == 1) { @@ -1248,11 +1264,23 @@ class LabelManager { #endif return !list.empty(); } + // detach all labels linked to LabelManager + void resetLabelPtrList() + { + for (LabelPtrList::iterator i = labelPtrList_.begin(), ie = labelPtrList_.end(); i != ie; ++i) { + (*i)->clear(); + } + labelPtrList_.clear(); + } public: LabelManager() { reset(); } + ~LabelManager() + { + resetLabelPtrList(); + } void reset() { base_ = 0; @@ -1262,6 +1290,7 @@ public: stateList_.push_back(SlabelState()); clabelDefList_.clear(); clabelUndefList_.clear(); + resetLabelPtrList(); } void enterLocal() { @@ -1294,10 +1323,11 @@ public: SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front(); define_inner(st.defList, st.undefList, label, base_->getSize()); } - void defineClabel(const Label& label) + void defineClabel(Label& label) { define_inner(clabelDefList_, clabelUndefList_, getId(label), base_->getSize()); label.mgr = this; + labelPtrList_.insert(&label); } void assign(Label& dst, const Label& src) { @@ -1305,6 +1335,7 @@ public: if (i == clabelDefList_.end()) throw Error(ERR_LABEL_ISNOT_SET_BY_L); define_inner(clabelDefList_, clabelUndefList_, dst.id, i->second.offset); dst.mgr = this; + labelPtrList_.insert(&dst); } bool getOffset(size_t *offset, std::string& label) const { @@ -1352,19 +1383,19 @@ inline Label::Label(const Label& rhs) { id = rhs.id; mgr = rhs.mgr; - if (mgr) mgr->incRefCount(id); + if (mgr) mgr->incRefCount(id, this); } inline Label& Label::operator=(const Label& rhs) { if (id) throw Error(ERR_LABEL_IS_ALREADY_SET_BY_L); id = rhs.id; mgr = rhs.mgr; - if (mgr) mgr->incRefCount(id); + if (mgr) mgr->incRefCount(id, this); return *this; } inline Label::~Label() { - if (id && mgr) mgr->decRefCount(id); + if (id && mgr) mgr->decRefCount(id, this); } inline const uint8* Label::getAddress() const { @@ -2168,7 +2199,7 @@ public: const Segment es, cs, ss, ds, fs, gs; #endif void L(const std::string& label) { labelMgr_.defineSlabel(label); } - void L(const Label& label) { labelMgr_.defineClabel(label); } + void L(Label& label) { labelMgr_.defineClabel(label); } Label L() { Label label; L(label); return label; } void inLocalLabel() { labelMgr_.enterLocal(); } void outLocalLabel() { labelMgr_.leaveLocal(); } @@ -2200,7 +2231,7 @@ public: // call(function pointer) #ifdef XBYAK_VARIADIC_TEMPLATE template - void call(Ret(*func)(Params...)) { call(CastTo(func)); } + void call(Ret(*func)(Params...)) { call(reinterpret_cast(func)); } #endif void call(const void *addr) { opJmpAbs(addr, T_NEAR, 0, 0xE8); } diff --git a/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak_mnemonic.h b/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak_mnemonic.h index 92a31f9a1..766f2f6ec 100644 --- a/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak_mnemonic.h +++ b/vendor/github.com/dexon-foundation/mcl/src/xbyak/xbyak_mnemonic.h @@ -1,4 +1,4 @@ -const char *getVersionString() const { return "5.73"; } +const char *getVersionString() const { return "5.751"; } void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); } void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); } void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); } diff --git a/vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp new file mode 100644 index 000000000..c3a0e758d --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp @@ -0,0 +1,74 @@ +//#define MCLBN_FP_UNIT_SIZE 8 +#include +#include +#include +#include + +using namespace mcl::aggs; + +CYBOZU_TEST_AUTO(init) +{ + AGGS::init(); +// AGGS::init(mcl::BN381_1); +// AGGS::init(mcl::BLS12_381); + SecretKey sec; + sec.init(); + PublicKey pub; + sec.getPublicKey(pub); + const std::string m = "abc"; + Signature sig; + sec.sign(sig, m); + CYBOZU_TEST_ASSERT(pub.verify(sig, m)); +} + +void aggregateTest(const std::vector& msgVec) +{ + const size_t n = msgVec.size(); + std::vector secVec(n); + std::vector pubVec(n); + std::vector sigVec(n); + Signature aggSig; + for (size_t i = 0; i < n; i++) { + secVec[i].init(); + secVec[i].getPublicKey(pubVec[i]); + secVec[i].sign(sigVec[i], msgVec[i]); + CYBOZU_TEST_ASSERT(pubVec[i].verify(sigVec[i], msgVec[i])); + } + aggSig.aggregate(sigVec); + CYBOZU_TEST_ASSERT(aggSig.verify(msgVec, pubVec)); + CYBOZU_BENCH_C("aggSig.verify", 10, aggSig.verify, msgVec, pubVec); +} + +CYBOZU_TEST_AUTO(aggregate) +{ +#if 0 + /* + Core i7-7700 CPU @ 3.60GHz + BN254 Fp382 Fp462 + security bit 100 115? 128 + # of sig 100 69 200 476 + 1000 693 2037 4731 + 10000 6969 20448 47000(Mclk) + */ + const size_t n = 1000; + const size_t msgSize = 16; + std::vector msgVec(n); + cybozu::XorShift rg; + for (size_t i = 0; i < n; i++) { + std::string& msg = msgVec[i]; + msg.resize(msgSize); + for (size_t j = 0; j < msgSize; j++) { + msg[j] = (char)rg(); + } + } + aggregateTest(msgVec); +#else + const std::string msgArray[] = { "abc", "12345", "xyz", "pqr", "aggregate signature" }; + const size_t n = sizeof(msgArray) / sizeof(msgArray[0]); + std::vector msgVec(n); + for (size_t i = 0; i < n; i++) { + msgVec[i] = msgArray[i]; + } + aggregateTest(msgVec); +#endif +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/array_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/array_test.cpp new file mode 100644 index 000000000..2168a28fa --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/array_test.cpp @@ -0,0 +1,104 @@ +#include +#include + +template +void setArray(Array& a, const int (&tbl)[n]) +{ + CYBOZU_TEST_ASSERT(a.resize(n)); + for (size_t i = 0; i < n; i++) a[i] = tbl[i]; +} + +template +void swapTest(const int (&a)[an], const int (&b)[bn]) +{ + Array s, t; + setArray(s, a); + setArray(t, b); + s.swap(t); + CYBOZU_TEST_EQUAL(s.size(), bn); + CYBOZU_TEST_EQUAL(t.size(), an); + CYBOZU_TEST_EQUAL_ARRAY(s, b, s.size()); + CYBOZU_TEST_EQUAL_ARRAY(t, a, t.size()); +} + +CYBOZU_TEST_AUTO(resize) +{ + mcl::Array a, b; + CYBOZU_TEST_EQUAL(a.size(), 0); + CYBOZU_TEST_EQUAL(b.size(), 0); + + const size_t n = 5; + bool ok = a.resize(n); + CYBOZU_TEST_ASSERT(ok); + CYBOZU_TEST_EQUAL(n, a.size()); + for (size_t i = 0; i < n; i++) { + a[i] = i; + } + ok = b.copy(a); + CYBOZU_TEST_ASSERT(ok); + CYBOZU_TEST_EQUAL(b.size(), n); + CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), n); + + const size_t small = n - 1; + ok = b.resize(small); + CYBOZU_TEST_ASSERT(ok); + CYBOZU_TEST_EQUAL(b.size(), small); + CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), small); + const size_t large = n * 2; + ok = b.resize(large); + CYBOZU_TEST_ASSERT(ok); + CYBOZU_TEST_EQUAL(b.size(), large); + CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), small); + + const int aTbl[] = { 3, 4 }; + const int bTbl[] = { 7, 6, 5, 3 }; + swapTest >(aTbl, bTbl); + swapTest >(bTbl, aTbl); +} + +CYBOZU_TEST_AUTO(FixedArray) +{ + const size_t n = 5; + mcl::FixedArray a, b; + CYBOZU_TEST_EQUAL(a.size(), 0); + CYBOZU_TEST_EQUAL(b.size(), 0); + + bool ok = a.resize(n); + CYBOZU_TEST_ASSERT(ok); + CYBOZU_TEST_EQUAL(n, a.size()); + for (size_t i = 0; i < n; i++) { + a[i] = i; + } + ok = b.copy(a); + CYBOZU_TEST_ASSERT(ok); + CYBOZU_TEST_EQUAL(b.size(), n); + CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), n); + + const size_t small = n - 1; + ok = b.resize(small); + CYBOZU_TEST_ASSERT(ok); + CYBOZU_TEST_EQUAL(b.size(), small); + CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), small); + const size_t large = n + 1; + ok = b.resize(large); + CYBOZU_TEST_ASSERT(!ok); + + const int aTbl[] = { 3, 4 }; + const int bTbl[] = { 7, 6, 5, 3 }; + swapTest >(aTbl, bTbl); + swapTest >(bTbl, aTbl); +} + +#ifndef CYBOZU_DONT_USE_EXCEPTION +CYBOZU_TEST_AUTO(assign) +{ + const int aTbl[] = { 3, 4, 2 }; + const int bTbl[] = { 3, 4, 2, 1, 5 }; + mcl::Array a, b; + setArray(a, aTbl); + setArray(b, bTbl); + a = b; + CYBOZU_TEST_EQUAL(a.size(), b.size()); + CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), a.size()); +} +#endif diff --git a/vendor/github.com/dexon-foundation/mcl/test/base_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/base_test.cpp new file mode 100644 index 000000000..2733d17ca --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/base_test.cpp @@ -0,0 +1,392 @@ +// not compiled +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../src/fp_generator.hpp" +#if (CYBOZU_HOST == CYBOZU_HOST_INTEL) && (MCL_SIZEOF_UNIT == 8) + #define USE_XBYAK + static mcl::FpGenerator fg; +#endif +#define PUT(x) std::cout << #x "=" << (x) << std::endl + +const size_t MAX_N = 32; +typedef mcl::fp::Unit Unit; + +size_t getUnitSize(size_t bitSize) +{ + return (bitSize + sizeof(Unit) * 8 - 1) / (sizeof(Unit) * 8); +} + +void setMpz(mpz_class& mx, const Unit *x, size_t n) +{ + mcl::gmp::setArray(mx, x, n); +} +void getMpz(Unit *x, size_t n, const mpz_class& mx) +{ + mcl::fp::toArray(x, n, mx.get_mpz_t()); +} + +struct Montgomery { + mpz_class p_; + mpz_class R_; // (1 << (n_ * 64)) % p + mpz_class RR_; // (R * R) % p + Unit r_; // p * r = -1 mod M = 1 << 64 + size_t n_; + Montgomery() {} + explicit Montgomery(const mpz_class& p) + { + p_ = p; + r_ = mcl::montgomery::getCoff(mcl::gmp::getUnit(p, 0)); + n_ = mcl::gmp::getUnitSize(p); + R_ = 1; + R_ = (R_ << (n_ * 64)) % p_; + RR_ = (R_ * R_) % p_; + } + + void toMont(mpz_class& x) const { mul(x, x, RR_); } + void fromMont(mpz_class& x) const { mul(x, x, 1); } + + void mont(Unit *z, const Unit *x, const Unit *y) const + { + mpz_class mx, my; + setMpz(mx, x, n_); + setMpz(my, y, n_); + mul(mx, mx, my); + getMpz(z, n_, mx); + } + void mul(mpz_class& z, const mpz_class& x, const mpz_class& y) const + { +#if 1 + const size_t ySize = mcl::gmp::getUnitSize(y); + mpz_class c = y == 0 ? mpz_class(0) : x * mcl::gmp::getUnit(y, 0); + Unit q = c == 0 ? 0 : mcl::gmp::getUnit(c, 0) * r_; + c += p_ * q; + c >>= sizeof(Unit) * 8; + for (size_t i = 1; i < n_; i++) { + if (i < ySize) { + c += x * mcl::gmp::getUnit(y, i); + } + Unit q = c == 0 ? 0 : mcl::gmp::getUnit(c, 0) * r_; + c += p_ * q; + c >>= sizeof(Unit) * 8; + } + if (c >= p_) { + c -= p_; + } + z = c; +#else + z = x * y; + const size_t zSize = mcl::gmp::getUnitSize(z); + for (size_t i = 0; i < n_; i++) { + if (i < zSize) { + Unit q = mcl::gmp::getUnit(z, 0) * r_; + z += p_ * (mp_limb_t)q; + } + z >>= sizeof(Unit) * 8; + } + if (z >= p_) { + z -= p_; + } +#endif + } +}; + +void put(const char *msg, const Unit *x, size_t n) +{ + printf("%s ", msg); + for (size_t i = 0; i < n; i++) printf("%016llx ", (long long)x[n - 1 - i]); + printf("\n"); +} +void verifyEqual(const Unit *x, const Unit *y, size_t n, const char *file, int line) +{ + bool ok = mcl::fp::isEqualArray(x, y, n); + CYBOZU_TEST_ASSERT(ok); + if (ok) return; + printf("%s:%d\n", file, line); + put("L", x, n); + put("R", y, n); + exit(1); +} +#define VERIFY_EQUAL(x, y, n) verifyEqual(x, y, n, __FILE__, __LINE__) + +void addC(Unit *z, const Unit *x, const Unit *y, const Unit *p, size_t n) +{ + mpz_class mx, my, mp; + setMpz(mx, x, n); + setMpz(my, y, n); + setMpz(mp, p, n); + mx += my; + if (mx >= mp) mx -= mp; + getMpz(z, n, mx); +} +void subC(Unit *z, const Unit *x, const Unit *y, const Unit *p, size_t n) +{ + mpz_class mx, my, mp; + setMpz(mx, x, n); + setMpz(my, y, n); + setMpz(mp, p, n); + mx -= my; + if (mx < 0) mx += mp; + getMpz(z, n, mx); +} +static inline void set_zero(mpz_t& z, Unit *p, size_t n) +{ + z->_mp_alloc = (int)n; + z->_mp_size = 0; + z->_mp_d = (mp_limb_t*)p; +} +static inline void set_mpz_t(mpz_t& z, const Unit* p, int n) +{ + z->_mp_alloc = n; + int i = n; + while (i > 0 && p[i - 1] == 0) { + i--; + } + z->_mp_size = i; + z->_mp_d = (mp_limb_t*)p; +} + +// z[2n] <- x[n] * y[n] +void mulPreC(Unit *z, const Unit *x, const Unit *y, size_t n) +{ +#if 1 + mpz_t mx, my, mz; + set_zero(mz, z, n * 2); + set_mpz_t(mx, x, n); + set_mpz_t(my, y, n); + mpz_mul(mz, mx, my); + mcl::fp::toArray(z, n * 2, mz); +#else + mpz_class mx, my; + setMpz(mx, x, n); + setMpz(my, y, n); + mx *= my; + getMpz(z, n * 2, mx); +#endif +} + +void modC(Unit *y, const Unit *x, const Unit *p, size_t n) +{ + mpz_t mx, my, mp; + set_mpz_t(mx, x, n * 2); + set_mpz_t(my, y, n); + set_mpz_t(mp, p, n); + mpz_mod(my, mx, mp); + mcl::fp::clearArray(y, my->_mp_size, n); +} + +void mul(Unit *z, const Unit *x, const Unit *y, const Unit *p, size_t n) +{ + Unit ret[MAX_N * 2]; + mpz_t mx, my, mz, mp; + set_zero(mz, ret, MAX_N * 2); + set_mpz_t(mx, x, n); + set_mpz_t(my, y, n); + set_mpz_t(mp, p, n); + mpz_mul(mz, mx, my); + mpz_mod(mz, mz, mp); + mcl::fp::toArray(z, n, mz); +} + +typedef mcl::fp::void3op void3op; +typedef mcl::fp::void4op void4op; +typedef mcl::fp::void4Iop void4Iop; + +const struct FuncOp { + size_t bitSize; + void4op addS; + void4op addL; + void4op subS; + void4op subL; + void3op mulPre; + void4Iop mont; +} gFuncOpTbl[] = { + { 128, mcl_fp_add128S, mcl_fp_add128L, mcl_fp_sub128S, mcl_fp_sub128L, mcl_fp_mul128pre, mcl_fp_mont128 }, + { 192, mcl_fp_add192S, mcl_fp_add192L, mcl_fp_sub192S, mcl_fp_sub192L, mcl_fp_mul192pre, mcl_fp_mont192 }, + { 256, mcl_fp_add256S, mcl_fp_add256L, mcl_fp_sub256S, mcl_fp_sub256L, mcl_fp_mul256pre, mcl_fp_mont256 }, + { 320, mcl_fp_add320S, mcl_fp_add320L, mcl_fp_sub320S, mcl_fp_sub320L, mcl_fp_mul320pre, mcl_fp_mont320 }, + { 384, mcl_fp_add384S, mcl_fp_add384L, mcl_fp_sub384S, mcl_fp_sub384L, mcl_fp_mul384pre, mcl_fp_mont384 }, + { 448, mcl_fp_add448S, mcl_fp_add448L, mcl_fp_sub448S, mcl_fp_sub448L, mcl_fp_mul448pre, mcl_fp_mont448 }, + { 512, mcl_fp_add512S, mcl_fp_add512L, mcl_fp_sub512S, mcl_fp_sub512L, mcl_fp_mul512pre, mcl_fp_mont512 }, +#if MCL_SIZEOF_UNIT == 4 + { 160, mcl_fp_add160S, mcl_fp_add160L, mcl_fp_sub160S, mcl_fp_sub160L, mcl_fp_mul160pre, mcl_fp_mont160 }, + { 224, mcl_fp_add224S, mcl_fp_add224L, mcl_fp_sub224S, mcl_fp_sub224L, mcl_fp_mul224pre, mcl_fp_mont224 }, + { 288, mcl_fp_add288S, mcl_fp_add288L, mcl_fp_sub288S, mcl_fp_sub288L, mcl_fp_mul288pre, mcl_fp_mont288 }, + { 352, mcl_fp_add352S, mcl_fp_add352L, mcl_fp_sub352S, mcl_fp_sub352L, mcl_fp_mul352pre, mcl_fp_mont352 }, + { 416, mcl_fp_add416S, mcl_fp_add416L, mcl_fp_sub416S, mcl_fp_sub416L, mcl_fp_mul416pre, mcl_fp_mont416 }, + { 480, mcl_fp_add480S, mcl_fp_add480L, mcl_fp_sub480S, mcl_fp_sub480L, mcl_fp_mul480pre, mcl_fp_mont480 }, + { 544, mcl_fp_add544S, mcl_fp_add544L, mcl_fp_sub544S, mcl_fp_sub544L, mcl_fp_mul544pre, mcl_fp_mont544 }, +#else + { 576, mcl_fp_add576S, mcl_fp_add576L, mcl_fp_sub576S, mcl_fp_sub576L, mcl_fp_mul576pre, mcl_fp_mont576 }, +#endif +}; + +FuncOp getFuncOp(size_t bitSize) +{ + typedef std::map Map; + static Map map; + static bool init = false; + if (!init) { + init = true; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(gFuncOpTbl); i++) { + map[gFuncOpTbl[i].bitSize] = gFuncOpTbl[i]; + } + } + for (Map::const_iterator i = map.begin(), ie = map.end(); i != ie; ++i) { + if (bitSize <= i->second.bitSize) { + return i->second; + } + } + printf("ERR bitSize=%d\n", (int)bitSize); + exit(1); +} + +void test(const Unit *p, size_t bitSize) +{ + printf("bitSize %d\n", (int)bitSize); + const size_t n = getUnitSize(bitSize); +#ifdef NDEBUG + bool doBench = true; +#else + bool doBench = false; +#endif + const FuncOp funcOp = getFuncOp(bitSize); + const void4op addS = funcOp.addS; + const void4op addL = funcOp.addL; + const void4op subS = funcOp.subS; + const void4op subL = funcOp.subL; + const void3op mulPre = funcOp.mulPre; + const void4Iop mont = funcOp.mont; + + mcl::fp::Unit x[MAX_N], y[MAX_N]; + mcl::fp::Unit z[MAX_N], w[MAX_N]; + mcl::fp::Unit z2[MAX_N * 2]; + mcl::fp::Unit w2[MAX_N * 2]; + cybozu::XorShift rg; + mcl::fp::getRandVal(x, rg, p, bitSize); + mcl::fp::getRandVal(y, rg, p, bitSize); + const size_t C = 10; + + addC(z, x, y, p, n); + addS(w, x, y, p); + VERIFY_EQUAL(z, w, n); + for (size_t i = 0; i < C; i++) { + addC(z, y, z, p, n); + addS(w, y, w, p); + VERIFY_EQUAL(z, w, n); + addC(z, y, z, p, n); + addL(w, y, w, p); + VERIFY_EQUAL(z, w, n); + subC(z, x, z, p, n); + subS(w, x, w, p); + VERIFY_EQUAL(z, w, n); + subC(z, x, z, p, n); + subL(w, x, w, p); + VERIFY_EQUAL(z, w, n); + mulPreC(z2, x, z, n); + mulPre(w2, x, z); + VERIFY_EQUAL(z2, w2, n * 2); + } + { + mpz_class mp; + setMpz(mp, p, n); + Montgomery m(mp); +#ifdef USE_XBYAK + if (bitSize > 128) fg.init(p, n); +#endif + /* + real mont + 0 0 + 1 R^-1 + R 1 + -1 -R^-1 + -R -1 + */ + mpz_class t = 1; + const mpz_class R = (t << (n * 64)) % mp; + const mpz_class tbl[] = { + 0, 1, R, mp - 1, mp - R + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const mpz_class& mx = tbl[i]; + for (size_t j = i; j < CYBOZU_NUM_OF_ARRAY(tbl); j++) { + const mpz_class& my = tbl[j]; + getMpz(x, n, mx); + getMpz(y, n, my); + m.mont(z, x, y); + mont(w, x, y, p, m.r_); + VERIFY_EQUAL(z, w, n); +#ifdef USE_XBYAK + if (bitSize > 128) { + fg.mul_(w, x, y); + VERIFY_EQUAL(z, w, n); + } +#endif + } + } + if (doBench) { +// CYBOZU_BENCH("montC", m.mont, x, y, x); + CYBOZU_BENCH("montA ", mont, x, y, x, p, m.r_); + } + } + if (doBench) { +// CYBOZU_BENCH("addS", addS, x, y, x, p); // slow +// CYBOZU_BENCH("subS", subS, x, y, x, p); +// CYBOZU_BENCH("addL", addL, x, y, x, p); +// CYBOZU_BENCH("subL", subL, x, y, x, p); + CYBOZU_BENCH("mulPreA", mulPre, w2, y, x); + CYBOZU_BENCH("mulPreC", mulPreC, w2, y, x, n); + CYBOZU_BENCH("modC ", modC, x, w2, p, n); + } +#ifdef USE_XBYAK + if (bitSize <= 128) return; + if (doBench) { + fg.init(p, n); + CYBOZU_BENCH("addA ", fg.add_, x, y, x); + CYBOZU_BENCH("subA ", fg.sub_, x, y, x); +// CYBOZU_BENCH("mulA", fg.mul_, x, y, x); + } +#endif + printf("mont test %d\n", (int)bitSize); +} + +CYBOZU_TEST_AUTO(all) +{ + const struct { + size_t n; + const uint64_t p[9]; + } tbl[] = { +// { 2, { 0xf000000000000001, 1, } }, + { 2, { 0x000000000000001d, 0x8000000000000000, } }, + { 3, { 0x000000000000012b, 0x0000000000000000, 0x0000000080000000, } }, +// { 3, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0x07ffffffffffffff, } }, +// { 3, { 0x7900342423332197, 0x1234567890123456, 0x1480948109481904, } }, + { 3, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0xffffffffffffffff, } }, +// { 4, { 0x7900342423332197, 0x4242342420123456, 0x1234567892342342, 0x1480948109481904, } }, +// { 4, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0x17ffffffffffffff, 0x1513423423423415, } }, + { 4, { 0xa700000000000013, 0x6121000000000013, 0xba344d8000000008, 0x2523648240000001, } }, +// { 5, { 0x0000000000000009, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, } }, + { 5, { 0xfffffffffffffc97, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } }, +// { 6, { 0x4720422423332197, 0x0034230847204720, 0x3456789012345679, 0x4820984290482212, 0x9482094820948209, 0x0194810841094810, } }, +// { 6, { 0x7204224233321972, 0x0342308472047204, 0x4567890123456790, 0x0948204204243123, 0x2098420984209482, 0x2093482094810948, } }, + { 6, { 0x00000000ffffffff, 0xffffffff00000000, 0xfffffffffffffffe, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } }, +// { 7, { 0x0000000000000063, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, } }, + { 7, { 0x000000000fffcff1, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } }, + { 8, { 0xffffffffffffd0c9, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } }, + { 9, { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x00000000000001ff, } }, +// { 9, { 0x4720422423332197, 0x0034230847204720, 0x3456789012345679, 0x2498540975555312, 0x9482904924029424, 0x0948209842098402, 0x1098410948109482, 0x0820958209582094, 0x0000000000000029, } }, +// { 9, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0x7fffffffffffffff, 0x8572938572398583, 0x5732057823857293, 0x9820948205872380, 0x3409238420492034, 0x9483842098340298, 0x0000000000000003, } }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const size_t n = tbl[i].n; + const size_t bitSize = (n - 1) * 64 + cybozu::bsr(tbl[i].p[n - 1]) + 1; + test((const Unit*)tbl[i].p, bitSize); + } +} + diff --git a/vendor/github.com/dexon-foundation/mcl/test/bench.hpp b/vendor/github.com/dexon-foundation/mcl/test/bench.hpp new file mode 100644 index 000000000..cc1639e6e --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bench.hpp @@ -0,0 +1,192 @@ +#include + +void benchAddDblG1() +{ + puts("benchAddDblG1"); + const int C = 100000; + G1 P1, P2, P3; + hashAndMapToG1(P1, "a"); + hashAndMapToG1(P2, "b"); + P1 += P2; + P2 += P1; + printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne()); + CYBOZU_BENCH_C("G1::add(1)", C, G1::add, P3, P1, P2); + P1.normalize(); + printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne()); + CYBOZU_BENCH_C("G1::add(2)", C, G1::add, P3, P1, P2); + CYBOZU_BENCH_C("G1::add(3)", C, G1::add, P3, P2, P1); + P2.normalize(); + printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne()); + CYBOZU_BENCH_C("G1::add(4)", C, G1::add, P3, P1, P2); + P1 = P3; + printf("z.isOne()=%d\n", P1.z.isOne()); + CYBOZU_BENCH_C("G1::dbl(1)", C, G1::dbl, P3, P1); + P1.normalize(); + printf("z.isOne()=%d\n", P1.z.isOne()); + CYBOZU_BENCH_C("G1::dbl(2)", C, G1::dbl, P3, P1); +} + +void benchAddDblG2() +{ + puts("benchAddDblG2"); + const int C = 100000; + G2 P1, P2, P3; + hashAndMapToG2(P1, "a"); + hashAndMapToG2(P2, "b"); + P1 += P2; + P2 += P1; + printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne()); + CYBOZU_BENCH_C("G2::add(1)", C, G2::add, P3, P1, P2); + P1.normalize(); + printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne()); + CYBOZU_BENCH_C("G2::add(2)", C, G2::add, P3, P1, P2); + CYBOZU_BENCH_C("G2::add(3)", C, G2::add, P3, P2, P1); + P2.normalize(); + printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne()); + CYBOZU_BENCH_C("G2::add(4)", C, G2::add, P3, P1, P2); + P1 = P3; + printf("z.isOne()=%d\n", P1.z.isOne()); + CYBOZU_BENCH_C("G2::dbl(1)", C, G2::dbl, P3, P1); + P1.normalize(); + printf("z.isOne()=%d\n", P1.z.isOne()); + CYBOZU_BENCH_C("G2::dbl(2)", C, G2::dbl, P3, P1); +} + + +void testBench(const G1& P, const G2& Q) +{ + G1 Pa; + G2 Qa; + Fp12 e1, e2; + pairing(e1, P, Q); + Fp12::pow(e2, e1, 12345); + Fp x, y; + x.setHashOf("abc"); + y.setHashOf("xyz"); + const int C = 1000; + const int C3 = 100000; +#if 1 + const int C2 = 3000; + mpz_class a = x.getMpz(); + CYBOZU_BENCH_C("G1::mulCT ", C, G1::mulCT, Pa, P, a); + CYBOZU_BENCH_C("G1::mul ", C, G1::mul, Pa, Pa, a); + CYBOZU_BENCH_C("G1::add ", C, G1::add, Pa, Pa, P); + CYBOZU_BENCH_C("G1::dbl ", C, G1::dbl, Pa, Pa); + CYBOZU_BENCH_C("G2::mulCT ", C, G2::mulCT, Qa, Q, a); + CYBOZU_BENCH_C("G2::mul ", C, G2::mul, Qa, Qa, a); + CYBOZU_BENCH_C("G2::add ", C, G2::add, Qa, Qa, Q); + CYBOZU_BENCH_C("G2::dbl ", C, G2::dbl, Qa, Qa); + CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e1, e1, a); +// CYBOZU_BENCH_C("GT::powGLV ", C, BN::param.glv2.pow, e1, e1, a); + G1 PP; + G2 QQ; + std::string s; + s = P.getStr(); + CYBOZU_BENCH_C("G1::setStr chk", C, PP.setStr, s); + verifyOrderG1(false); + CYBOZU_BENCH_C("G1::setStr ", C, PP.setStr, s); + verifyOrderG1(true); + s = Q.getStr(); + CYBOZU_BENCH_C("G2::setStr chk", C, QQ.setStr, s); + verifyOrderG2(false); + CYBOZU_BENCH_C("G2::setStr ", C, QQ.setStr, s); + verifyOrderG2(true); + CYBOZU_BENCH_C("hashAndMapToG1", C, hashAndMapToG1, PP, "abc", 3); + CYBOZU_BENCH_C("hashAndMapToG2", C, hashAndMapToG2, QQ, "abc", 3); +#endif + CYBOZU_BENCH_C("Fp::add ", C3, Fp::add, x, x, y); + CYBOZU_BENCH_C("Fp::sub ", C3, Fp::sub, x, x, y); + CYBOZU_BENCH_C("Fp::neg ", C3, Fp::neg, x, x); + CYBOZU_BENCH_C("Fp::mul ", C3, Fp::mul, x, x, y); + CYBOZU_BENCH_C("Fp::sqr ", C3, Fp::sqr, x, x); + CYBOZU_BENCH_C("Fp::inv ", C3, Fp::inv, x, x); + Fp2 xx, yy; + xx.a = x; + xx.b = 3; + yy.a = y; + yy.b = -5; + FpDbl d0, d1; + x = 9; + y = 3; +#if 1 + CYBOZU_BENCH_C("Fp2::add ", C3, Fp2::add, xx, xx, yy); + CYBOZU_BENCH_C("Fp2::sub ", C3, Fp2::sub, xx, xx, yy); + CYBOZU_BENCH_C("Fp2::neg ", C3, Fp2::neg, xx, xx); + CYBOZU_BENCH_C("Fp2::mul ", C3, Fp2::mul, xx, xx, yy); + CYBOZU_BENCH_C("Fp2::mul_xi ", C3, Fp2::mul_xi, xx, xx); + CYBOZU_BENCH_C("Fp2::sqr ", C3, Fp2::sqr, xx, xx); + CYBOZU_BENCH_C("Fp2::inv ", C3, Fp2::inv, xx, xx); + CYBOZU_BENCH_C("FpDbl::addPre ", C3, FpDbl::addPre, d1, d1, d0); + CYBOZU_BENCH_C("FpDbl::subPre ", C3, FpDbl::subPre, d1, d1, d0); + CYBOZU_BENCH_C("FpDbl::add ", C3, FpDbl::add, d1, d1, d0); + CYBOZU_BENCH_C("FpDbl::sub ", C3, FpDbl::sub, d1, d1, d0); + CYBOZU_BENCH_C("FpDbl::mulPre ", C3, FpDbl::mulPre, d0, x, y); + CYBOZU_BENCH_C("FpDbl::sqrPre ", C3, FpDbl::sqrPre, d1, x); + CYBOZU_BENCH_C("FpDbl::mod ", C3, FpDbl::mod, x, d0); + Fp2Dbl D; + CYBOZU_BENCH_C("Fp2Dbl::mulPre ", C3, Fp2Dbl::mulPre, D, xx, yy); + CYBOZU_BENCH_C("Fp2Dbl::sqrPre ", C3, Fp2Dbl::sqrPre, D, xx); + + CYBOZU_BENCH_C("GT::add ", C2, GT::add, e1, e1, e2); + CYBOZU_BENCH_C("GT::mul ", C2, GT::mul, e1, e1, e2); + CYBOZU_BENCH_C("GT::sqr ", C2, GT::sqr, e1, e1); + CYBOZU_BENCH_C("GT::inv ", C2, GT::inv, e1, e1); +#endif + CYBOZU_BENCH_C("FpDbl::mulPre ", C3, FpDbl::mulPre, d0, x, y); + CYBOZU_BENCH_C("pairing ", 3000, pairing, e1, P, Q); + CYBOZU_BENCH_C("millerLoop ", 3000, millerLoop, e1, P, Q); + CYBOZU_BENCH_C("finalExp ", 3000, finalExp, e1, e1); +//exit(1); + std::vector Qcoeff; + CYBOZU_BENCH_C("precomputeG2 ", C, precomputeG2, Qcoeff, Q); + precomputeG2(Qcoeff, Q); + CYBOZU_BENCH_C("precomputedML ", C, precomputedMillerLoop, e2, P, Qcoeff); +} + +inline void SquareRootPrecomputeTest(const mpz_class& p) +{ + mcl::SquareRoot sq1, sq2; + bool b; + sq1.set(&b, p, true); + CYBOZU_TEST_ASSERT(b); + CYBOZU_TEST_ASSERT(sq1.isPrecomputed()); + sq2.set(&b, p, false); + CYBOZU_TEST_ASSERT(sq1 == sq2); + if (sq1 != sq2) { + puts("dump"); + puts("sq1"); + sq1.dump(); + puts("sq2"); + sq2.dump(); + puts("---"); + } +} + +void testSquareRoot() +{ + if (BN::param.cp == mcl::BN254 || BN::param.cp == mcl::BLS12_381) { + SquareRootPrecomputeTest(BN::param.p); + SquareRootPrecomputeTest(BN::param.r); + } +} + +void testLagrange() +{ + puts("testLagrange"); + const int k = 7; + Fr c[k], x[k], y[k]; + for (size_t i = 0; i < k; i++) { + c[i].setByCSPRNG(); + x[i].setByCSPRNG(); + } + for (size_t i = 0; i < k; i++) { + mcl::evaluatePolynomial(y[i], c, k, x[i]); + } + Fr s; + mcl::LagrangeInterpolation(s, x, y, k); + CYBOZU_TEST_EQUAL(s, c[0]); + mcl::LagrangeInterpolation(s, x, y, 1); + CYBOZU_TEST_EQUAL(s, y[0]); + mcl::evaluatePolynomial(y[0], c, 1, x[0]); + CYBOZU_TEST_EQUAL(y[0], c[0]); +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/bls12_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bls12_test.cpp new file mode 100644 index 000000000..7011516bd --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bls12_test.cpp @@ -0,0 +1,720 @@ +#define PUT(x) std::cout << #x "=" << x << std::endl; +#define CYBOZU_TEST_DISABLE_AUTO_RUN +#include +cybozu::CpuClock clk; +#include +#include +#include +#include + +#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST) + #define MCL_AVOID_EXCEPTION_TEST +#endif + +using namespace mcl::bls12; + +mcl::fp::Mode g_mode; + +const struct TestSet { + mcl::CurveParam cp; + const char *name; + const char *p; + const char *r; + struct G2 { + const char *aa; + const char *ab; + const char *ba; + const char *bb; + } g2; + struct G1 { + const char *a; + const char *b; + } g1; + const char *e; +} g_testSetTbl[] = { + { + mcl::BLS12_381, + "BLS12_381", + "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", + "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", + { + "0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8", + "0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e", + "0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801", + "0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", + }, + { + "0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb", + "0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", + }, + "0x1250EBD871FC0A92A7B2D83168D0D727272D441BEFA15C503DD8E90CE98DB3E7B6D194F60839C508A84305AACA1789B6 " + "0x089A1C5B46E5110B86750EC6A532348868A84045483C92B7AF5AF689452EAFABF1A8943E50439F1D59882A98EAA0170F " + "0x1368BB445C7C2D209703F239689CE34C0378A68E72A6B3B216DA0E22A5031B54DDFF57309396B38C881C4C849EC23E87 " + "0x193502B86EDB8857C273FA075A50512937E0794E1E65A7617C90D8BD66065B1FFFE51D7A579973B1315021EC3C19934F " + "0x01B2F522473D171391125BA84DC4007CFBF2F8DA752F7C74185203FCCA589AC719C34DFFBBAAD8431DAD1C1FB597AAA5 " + "0x018107154F25A764BD3C79937A45B84546DA634B8F6BE14A8061E55CCEBA478B23F7DACAA35C8CA78BEAE9624045B4B6 " + "0x19F26337D205FB469CD6BD15C3D5A04DC88784FBB3D0B2DBDEA54D43B2B73F2CBB12D58386A8703E0F948226E47EE89D " + "0x06FBA23EB7C5AF0D9F80940CA771B6FFD5857BAAF222EB95A7D2809D61BFE02E1BFD1B68FF02F0B8102AE1C2D5D5AB1A " + "0x11B8B424CD48BF38FCEF68083B0B0EC5C81A93B330EE1A677D0D15FF7B984E8978EF48881E32FAC91B93B47333E2BA57 " + "0x03350F55A7AEFCD3C31B4FCB6CE5771CC6A0E9786AB5973320C806AD360829107BA810C5A09FFDD9BE2291A0C25A99A2 " + "0x04C581234D086A9902249B64728FFD21A189E87935A954051C7CDBA7B3872629A4FAFC05066245CB9108F0242D0FE3EF " + "0x0F41E58663BF08CF068672CBD01A7EC73BACA4D72CA93544DEFF686BFD6DF543D48EAA24AFE47E1EFDE449383B676631 " + }, +}; + +CYBOZU_TEST_AUTO(size) +{ + CYBOZU_TEST_EQUAL(sizeof(Fp), 48u); + CYBOZU_TEST_EQUAL(sizeof(Fr), 32u); + CYBOZU_TEST_EQUAL(sizeof(Fp2), sizeof(Fp) * 2); + CYBOZU_TEST_EQUAL(sizeof(Fp6), sizeof(Fp) * 6); + CYBOZU_TEST_EQUAL(sizeof(Fp12), sizeof(Fp) * 12); + CYBOZU_TEST_EQUAL(sizeof(G1), sizeof(Fp) * 3); + CYBOZU_TEST_EQUAL(sizeof(G2), sizeof(Fp2) * 3); +} + +void testParam(const TestSet& ts) +{ + CYBOZU_TEST_EQUAL(BN::param.r, mpz_class(ts.r)); + CYBOZU_TEST_EQUAL(BN::param.p, mpz_class(ts.p)); +} + +void finalExpC(Fp12& y, const Fp12& x) +{ + const mpz_class& r = BN::param.r; + const mpz_class& p = BN::param.p; + mpz_class p2 = p * p; + mpz_class p4 = p2 * p2; +#if 1 + Fp12::pow(y, x, p2 + 1); + Fp12::pow(y, y, p4 * p2 - 1); + Fp12::pow(y, y, (p4 - p2 + 1) / r * 3); +#else + Fp12::pow(y, x, (p4 * p4 * p4 - 1) / r * 3); +#endif +} + +void pairingC(Fp12& e, const G1& P, const G2& Q) +{ + millerLoop(e, P, Q); + finalExp(e, e); +} +void testIoAll(const G1& P, const G2& Q) +{ + const int FpTbl[] = { 0, 2, 2|mcl::IoPrefix, 10, 16, 16|mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw }; + const int EcTbl[] = { mcl::IoEcAffine, mcl::IoEcProj, mcl::IoEcCompY, mcl::IoSerialize }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(FpTbl); i++) { + for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(EcTbl); j++) { + G1 P2 = P, P3; + G2 Q2 = Q, Q3; + int ioMode = FpTbl[i] | EcTbl[j]; + std::string s = P2.getStr(ioMode); + P3.setStr(s, ioMode); + CYBOZU_TEST_EQUAL(P2, P3); + s = Q2.getStr(ioMode); + Q3.setStr(s, ioMode); + CYBOZU_TEST_EQUAL(Q2, Q3); + s = P.x.getStr(ioMode); + Fp Px; + Px.setStr(s, ioMode); + CYBOZU_TEST_EQUAL(P.x, Px); + s = Q.x.getStr(ioMode); + Fp2 Qx; + Qx.setStr(s, ioMode); + CYBOZU_TEST_EQUAL(Q.x, Qx); + } + } +} + +void testIo(const G1& P, const G2& Q) +{ + testIoAll(P, Q); + G1 Z1; + G2 Z2; + Z1.clear(); + Z2.clear(); + testIoAll(Z1, Z2); +} + +void testSetStr(const G2& Q0) +{ + G2::setCompressedExpression(); + G2 Q; + Q.clear(); + for (int i = 0; i < 10; i++) { + G2 R; + R.setStr(Q.getStr()); + CYBOZU_TEST_EQUAL(Q, R); + G2::add(Q, Q, Q0); + } +} + +void testMapToG1() +{ + G1 g; + for (int i = 1; i < 10; i++) { + mapToG1(g, i); + CYBOZU_TEST_ASSERT(!g.isZero()); + G1 gr; + G1::mul(gr, g, BN::param.r); + CYBOZU_TEST_ASSERT(gr.isZero()); + } +} + +void testMapToG2() +{ + G2 g; + for (int i = 1; i < 10; i++) { + mapToG2(g, i); + CYBOZU_TEST_ASSERT(!g.isZero()); + G2 gr; + G2::mul(gr, g, BN::param.r); + CYBOZU_TEST_ASSERT(gr.isZero()); + } + Fp x; + x.setHashOf("abc"); + mapToG2(g, Fp2(x, 0)); + CYBOZU_TEST_ASSERT(g.isValid()); +} + +void testPrecomputed(const G1& P, const G2& Q) +{ + Fp12 e1, e2; + pairing(e1, P, Q); + std::vector Qcoeff; + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e2, P, Qcoeff); + finalExp(e2, e2); + CYBOZU_TEST_EQUAL(e1, e2); +} + +#if 0 +void testFp12pow(const G1& P, const G2& Q) +{ + Fp12 e, e1, e2; + pairing(e, P, Q); + cybozu::XorShift rg; + for (int i = -10; i < 10; i++) { + mpz_class xm = i; + Fp12::pow(e1, e, xm); + Fp12::powGeneric(e2, e, xm); + CYBOZU_TEST_EQUAL(e1, e2); + } + for (int i = 0; i < 10; i++) { + Fr x; + x.setRand(rg); + mpz_class xm = x.getMpz(); + Fp12::pow(e1, e, xm); + param.glv2.pow(e2, e, xm); + CYBOZU_TEST_EQUAL(e1, e2); + } +} +#endif + +void testMillerLoop2(const G1& P1, const G2& Q1) +{ + Fp12 e1, e2, e3; + mpz_class c1("12342342423442"); + mpz_class c2("329428049820348209482"); + G2 Q2; + G1 P2; + G2::mul(Q2, Q1, c1); + G1::mul(P2, P1, c2); + pairing(e1, P1, Q1); + pairing(e2, P2, Q2); + e1 *= e2; + + std::vector Q1coeff, Q2coeff; + precomputeG2(Q1coeff, Q1); + precomputeG2(Q2coeff, Q2); + precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff); + precomputedMillerLoop2mixed(e3, P1, Q1, P2, Q2coeff); + CYBOZU_TEST_EQUAL(e2, e3); + finalExp(e2, e2); + CYBOZU_TEST_EQUAL(e1, e2); + + // special value + G2 Z; + Z.clear(); + Q2 += Q2; + precomputeG2(Q1coeff, Z); + precomputeG2(Q2coeff, Q2); + precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff); + precomputedMillerLoop2mixed(e3, P1, Z, P2, Q2coeff); + finalExp(e2, e2); + finalExp(e3, e3); + CYBOZU_TEST_EQUAL(e2, e3); +} + +void testPairing(const G1& P, const G2& Q, const char *eStr) +{ + Fp12 e1; + pairing(e1, P, Q); + Fp12 e2; + { + std::stringstream ss(eStr); + ss >> e2; + } + CYBOZU_TEST_EQUAL(e1, e2); + Fp12 e = e1, ea; + G1 Pa; + G2 Qa; +#if defined(__EMSCRIPTEN__) || MCL_SIZEOF_UNIT == 4 + const int count = 100; +#else + const int count = 1000; +#endif + mpz_class a; + cybozu::XorShift rg; + for (int i = 0; i < count; i++) { + Fr r; + r.setRand(rg); + a = r.getMpz(); + Fp12::pow(ea, e, a); + G1::mul(Pa, P, a); + G2::mul(Qa, Q, a); + G1 T; + G1::mulCT(T, P, a); + CYBOZU_TEST_EQUAL(Pa, T); + pairing(e1, Pa, Q); + pairing(e2, P, Qa); + CYBOZU_TEST_EQUAL(ea, e1); + CYBOZU_TEST_EQUAL(ea, e2); + } +} + +void testTrivial(const G1& P, const G2& Q) +{ + G1 Z1; Z1.clear(); + G2 Z2; Z2.clear(); + Fp12 e; + pairing(e, Z1, Q); + CYBOZU_TEST_EQUAL(e, 1); + pairing(e, P, Z2); + CYBOZU_TEST_EQUAL(e, 1); + pairing(e, Z1, Z2); + CYBOZU_TEST_EQUAL(e, 1); + + std::vector Qcoeff; + precomputeG2(Qcoeff, Z2); + precomputedMillerLoop(e, P, Qcoeff); + finalExp(e, e); + CYBOZU_TEST_EQUAL(e, 1); + + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e, Z1, Qcoeff); + finalExp(e, e); + CYBOZU_TEST_EQUAL(e, 1); +} + +#include "bench.hpp" + +CYBOZU_TEST_AUTO(naive) +{ + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(g_testSetTbl); i++) { + const TestSet& ts = g_testSetTbl[i]; + printf("i=%d curve=%s\n", int(i), ts.name); + initPairing(ts.cp, g_mode); + const G1 P(Fp(ts.g1.a), Fp(ts.g1.b)); + const G2 Q(Fp2(ts.g2.aa, ts.g2.ab), Fp2(ts.g2.ba, ts.g2.bb)); +#ifdef ONLY_BENCH + { + Fp12 e; + for (int i = 0; i < 1000; i++) pairing(e, P, Q); + } + clk.put(); + return; +#endif + testParam(ts); + testIo(P, Q); +// testFp12pow(P, Q); + testTrivial(P, Q); + testSetStr(Q); + testMapToG1(); + testMapToG2(); + testPairing(P, Q, ts.e); + testPrecomputed(P, Q); + testMillerLoop2(P, Q); + testBench(P, Q); + } + int count = (int)clk.getCount(); + if (count) { + printf("count=%d ", count); + clk.put(); + } +} + +CYBOZU_TEST_AUTO(finalExp) +{ + const char *e0Str = +"012974491575E232199B73B30FE53FF643FEAE11023BCA7AF961C3600B45DFECFE4B30D52A62E73DA4C0409810304997\n" +"05CE2FB890FE65E20EC36347190ECB4884E401A64B666557B53E561F6D0979B7A96AD9E647ED78BD47187195C00F563C\n" +"02E85D1E559488603A70FEE99354DA8847215EC97282CA230DE96FED6DD5D4DD4EF4D901DB7F544A1A45EBEBA1450109\n" +"048FB1E44DDABF18D55C95704158A24678AA2A6ED0844108762E88306E5880E8C67BF44E24E40AB3F93D9E3713170341\n" +"07EF7BE685DC0DBA1B3E1D2E9090CD98EAD1325B60881772F17077386A3182B117F5FD839363F5891D08E82B88EC6F12\n" +"17803435700EF7A16C06404C6D17EB4FD84079FE9872207302A36C791B6E90447B33D703BBFE04ECB641C3A573E2CD50\n" +"19A494E6A872E46FC85D09FD6D30844B6FF05729BC253A9640F7BE64AAA8C2C8E0AE014A9DD816C53A3EDEBB2FA649EB\n" +"020949ABAA14F1DCE17FA9E091DDA963E9E492BA788E12B9B610E80A4D94DB9CC50341ED107C7D50E5738052595D4A27\n" +"09E217B513B3603723DAC3188A2F7CBDD84A56E7E5004446E7D4C63D6E378DA26E411C10898E48DB4B0C065E4699A9C5\n" +"12393BD23D0EC122082A1EC892A982F3C9AFD14240CE85258D8A3EF0A13CB545D6EF7848FD40DD4AEF1554341C5C5BBF\n" +"07EA8A0D6A57C78E5663F94E2B1ABC0D760ED18DBA64305EAD5EE350FB0342A7A81C0D5C8B3AD826D009276B0F32D2C8\n" +"16804D0D4A2633ED01568B0F8F06C4497E46E88D05FD191AAE530ACA791D0E114D74874FA88E33FAF48757153B09BB0E"; + +const char *e1Str = +"0E05D19E90D2C501E5502C7AC80D77201C47DF147DD1076440F0DF0179DF9802CA0775E0E73DD9174F1094D2280787B3\n" +"14D2F5C84279E7177A3543FBEAE261DE8F6C97EFD5F3FF3F959EC9FC0303F620A4B3AF00DF409496CECADDD0A7F0A164\n" +"1414E9B9DF8DF1EAC2E70D5538018377788C62016A54F28B037A68740705089AE431B86756F98CBE19690A5EAC0C2466\n" +"12D8B32157836A131CCA3CA313DAAAF909BC3AD6BDD15885BB429922B9CD7D1246D1163E5E6F88D68BF1B75E451EFABB\n" +"102C9A839A924E0D603D13F2E08A919E0B9EE2A269FC75727BA13D66027C157B9BB4077977FA94557DE4427BF11B234B\n" +"19DBEB7F2E3096AFFD44837655BD8249741B484B0EB0DBEE569DEA8D9E38AE09D210C8BC16AA6DFBC923095B2C9A8B2B\n" +"19B9A6DCCD01FA0D04D5CE94D8BDCE1DF64AFEB7FD493B955180A5C6B236E469F0E07CC9BB4203FCAC46AE6F8E5419D6\n" +"02BFA87AF7A3726A7ABACDCFDD53694AF651554F3A431AB4274F67D5DAD2D6C88AF794705FF456A936C83594731AD8DC\n" +"0F21E0173E3B50DD98EFA815B410631A57399B451FD6E1056FFD09C9FE50EFAD3D026F0C46C8BB1583A50B7853D990DA\n" +"02230237AE04B61F9269F6E7CD2FCF1231CEE4690AA658B0018EFC0D0770FD0A56B3B7294086E8D306B1465CDDD858CD\n" +"087EB8F6547015661E9CD48D6525C808636FCB8420B867CB2A87E006B2A93BBD5EF675E6CDDA9E6F94519C49EA8BB689\n" +"19F5C988B2DD6E33D7D3D34EFB1991F80DC28006AC75E0AB53FD98FC6F2476D05DD4ECA582F5FF72B8DDD9DDDE80FFC9"; + + Fp12 e0, e1, e2; + e0.setStr(e0Str, 16); + e1.setStr(e1Str, 16); + finalExp(e2, e0); +// finalExpC(e2, e0); + CYBOZU_TEST_EQUAL(e1, e2); + CYBOZU_BENCH_C("finalExp", 100, finalExp, e2, e0); +} + +CYBOZU_TEST_AUTO(addLine) +{ +const char *l0Str= +"0EF586FCDB69442CB41C0DA719AC5C92BD99A916C1F01BCFC7606AA7A23D680C04620FDFC2144E0EA6025F05241A791F\n" +"164CFDADE9B91150C6D2C7F7CDF29BC3105A7EA51217283CDF801EBEE9E86CE5078253E322C72129DAA42F6DBAD17D37"; +const char *l1Str = +"07A124F536BE83CCB3AF8D3DA2AE094942755040B9DA8E0796C462ACE3805D6916ACA7E9281261D8025571E2F31AAF0D\n" +"12D05751A9B255143541D0A4E57E120F937D51F9A07D31982390CA6EB5DF8CC0640FD291521069BF9964AE33EDD1323D"; +const char *l4Str = +"0D609DE41CF1260B332C1A53AA54703F62AB8224777E34FEEAB09AA06187CA71D8C7C2EB66F59D3622D431BE17D0FEE6\n" +"0A93C2984041171BE701560017D64D0640B6F61D7DCA8F527FA6B6A1A1033261C0761CAA56A00D4D16C9D3B7371E02D9"; + +const char *rStr = +"4 0A8DFA69FDD43EDCCC6375750373B443157EF4641E5B4CA82FBF23E3E8EA72351EA754168CEC77573D337E6227C0D0DD\n" +"12C8508CF1828C52A9A1A71779129D605327191EE459AED3C0B4B14657B08B2927173FADF8E4275188E8D49E57A75B33\n" +"12AD7EB96734F2C93B669FD54845CD2FF351AFDF0123E96772021DC3F4F3B456DB1B37CB1C380B1947616165FF0DDAEA\n" +"03D80F92C8A6005DEB291AF28406B7B4FCEDD81A244997DBB719B01D162BD7D71F0FD63BF76F8F1AC90618C3702294DF\n" +"199F7A719EA1CA2CD03CFFBB9A4BC2FE1BD8BCA7C772D223E6CB20C1313C3D3C52CFBB88445E56C833908C52A4EC68F1\n" +"0A3F6B27A6DDA00DB848574ECB06F179271D5844BDA66CD5AE1792A8FDD25E3A504A95839113BAA8B1FCB53EEE5F1FF0"; + +const char *qStr = +"4 0B5C339C23F8EAB3647E974BCDDF72C96F97A444346BE72CA73AB1323B83B8F6161257AB34C7E0CF34F6C45086CA5868\n" +"13C2235E9F9DFB33344BA2EE5A71435859022880732EDC9EC75AC79AE9DA972593CDC40A0AC334D6D2E8D7FAD1D98D0B\n" +"134B8EED8196A00D3B70ADBC26FF963B725A351CF0B73FE1A541788AFB0BB081AF82A438021B5E878B15D53B1D27C6A7\n" +"18CC69F847BEE826B939DCB4030D33020D03B046465C9EE103AA8009A175DB169070294E75771586687FE361DB884BCD\n" +"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\n" +"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + +const char *pStr = +"4 0FD3977C60EC322BC281C915955ED534B491E39C72E8E800271CEF3F0492D890829FA69C45FCE93D9847A0CAB325D871\n" +"17CC2C36C5D283C05BFCECCF48DBB2050332DA058DD67326A9EE520967DBCAEDFCB5F05A085D1A49DF08BB968CC782C5\n" +"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"; + +const char *m0Str = +"1010A4F9944514352AAD5D290AFB95C435EB64B5E74519807C9602DABCD6B6F5494E419758AE9A43F539F812252C65E5\n" +"1622F7A52BAAC10EBFF0977F61866544BF9B91315FA66ADB6AC200AFF7A3676C1AD3480340B23C66F7C6AE50A703F245"; +const char *m1Str = +"0905180B20FCE2AA545A73D6B9EA1F82479EF3FB5A3BA8DDB656D9B2A4DA7B63CCF75538D15093949B442E27804C8CE2\n" +"0FE834508BBAD2F22DCBF1C3C1BCCD69561827613EB63F4907832A7ABBBC6040CF2E517D0D5E22D3812EEE1EC55640DD"; +const char *m4Str = +"1197D94A8DAFE6F72B17A31964CA5D0C3B2A12BEFF959F7DF7A37938C64C01508D12C24479E5C3D314F862A9977D6C7D\n" +"0B0254A26810307964E2A05680C19DE7C63CCBD7CC3558AD366BA48D9F7049E245BF2C54EA0339301739851E6EB2158F"; + +const char *r1Str = +"4 16A33C4ED01E95833D39EECE223380FE860B6DC1F71B1DDBEE2BE39B5D682B090F18758495E202010D3B9B45A46FF80E\n" +"01CECF5CC255E32B833C16EF3F983CCA9996A33504615909AD5685D9F637BF2357442BEC89DAFC747B69EFEF57D5A213\n" +"061C33850E5E4A418F3B68D6097C3911A551D6DB3C7E21196410F69D510C1A888635B6B699F98C14912A8D97742D36A9\n" +"0457FB78282C2B8F8BA803E77D058EF3BF6B06C6241D6FA6E2B1607F3E9D7597D1A10B7AA4E06B89FBA01736901AD826\n" +"0B45E9B7D311B8C37F7E9262227A4D721F2D148DE6F12EC5D599B45E4790F35B37A1D6928709F438849324A807EC1913\n" +"0E771545F892C247A5365BA1F14934D8ED37483A6B7DD3EB4C3FBA0AC884D7EE9C080C3B39ADA64AE545E7339F83AFB0"; + + const int mode = mcl::IoEcProj | 16; + Fp6 l, m; + G2 R, Q, R1; + G1 P; + + R.setStr(rStr, mode); + Q.setStr(qStr, mode); + P.setStr(pStr, mode); + l.a.setStr(l0Str, mode); + l.b.setStr(l4Str, mode); + l.c.setStr(l1Str, mode); + local::addLine(l, R, Q, P); + m.a.setStr(m0Str, mode); + m.b.setStr(m4Str, mode); + m.c.setStr(m1Str, mode); + R1.setStr(r1Str, mode); + CYBOZU_TEST_EQUAL(l, m); + CYBOZU_TEST_EQUAL(R, R1); +} + +CYBOZU_TEST_AUTO(dblLine) +{ +const char *l0Str= +"0905F47F07FA2177E4B73559D93D9B41A2FD20E0440167E63A0F62321EB73C784405DE360477245F5E4AE8FA2EAEC6FF\n" +"02DA455C573517EE8BD4E40A60851E2EC85CF514351681B89B1B72664E384A3678A25DC5C4CF84C086C13968BC701F91"; +const char *l1Str = +"0F48059E31CEF9546D41DEF31FB3BFD13BBCC38248E4846AFD216350B4B661FA1382E74BCF904BE8E33C26FF0D29ABA0\n" +"0D7FAEE426E4A6F32E4DE1CCB76BBA870A183113589CF58A358DC9C284C82B54C65A754F9A71EAD87304744CFD105051"; + +const char *l4Str = +"162AE8B029F8420BEDE5A399BA19C09FED01DE2748F4458065DBE51044FBFE749B28EF1B7F79A5E4545EB550DD0CFE02\n" +"091042B589FD59FBF286D21475CCCF444D8DCC49389EA3B98AF864DDB9C08BDDEB320D6D88F0C07D7CD1733A41404C1F"; + +const char *qStr = +"4 047ACF79048EDCA97A19DB1779A44CE610CEA9FDCC62D1C4014B335834BC63414F55B670CCF15A86E58BC3737FB70919\n" +"11D8063B2FFA2E1F5224593FF74D0E9650CAB6AF702B74159F7F97E2CF0843FBCD561D41FEC779BEB48746CD2F30FF74\n" +"17684E8EA85C990DF5472B4EBAF51002CDBBECF79BA2988FC610A5CE09F4A584248DCC506E78C39C9BB4F6008115DE64\n" +"1334CA7263ED9395BBEDBB6C938C642200C239FB0CADF1F652332A037FFBC7E567CCE09540939F25316CBC4FC68CE4DB\n" +"0670DCF344F027CB92F7B1F569B281C8FF756D83CD7B65EB118FE95FBE16ED28649B8F739FE3A2BECA1979FC18484ECD\n" +"13E3E30759DCC1FA9F1A62D54BEF0EE1CC75E194A559F2D6BE3025BE4BEB9F7351A7608FE8D4CCAD30BA2A8748205487"; + +const char *pStr = +"4 1579B48AE944AFE8FC69B38A7CD0D2C6B93E5F506535A5410E25FB1C1707938D6932F3D620A2BBB90ED7E2601971DEA8\n" +"0234E5B373AD62D9EF1EBAE6FA6FFAD26144717F65AE9F98BD4280978ED52B3621F60FA4A8F6E5B5DAF64469733827E6\n" +"0B4D1755924541041F75FF399E3B5F535BC85D5A982AEEC5FC2404F06AC7F062C090C4545D1602C3D8B559801EE7B9A2"; + +const char *m0Str = +"198D1123A9817C40A914A3FF9E29BB16DD2F0DF98D0AB5C3A6014D60E31AE973051C35ADCEA0A41F32BB16E6688DC73F\n" +"10339DB2F26D1B867FD3E60A24F938210EABEFC51536845A490F28A088A4AC53575DBBAA218D70D34E28EBDE14DB3465\n"; +const char *m1Str = +"066852248D915F6378B3F4A8E6173AC748FBFAE236AAEEAECC3F34D2D22706A06B925A83DD8276B2B240F61D761587B0\n" +"17CC8195E6607FF19A26AA69CA50C32487E35D2D75301AC4B6988F1B77523BF472927EE5710DF49A563534D86C684BE0\n"; +const char *m4Str = +"10B67D1A0CE430B7AD74F64DD6C2E44C4788EADF8340909843C96B918BF54703CC14686B26E350EB1140ACC3337EEEB4\n" +"0F5D52E6F0B10A081EFF885CC858109241B379985ADD8982E6B8A202FD283897EFBA4CBE444C29751410A61FC8346545"; + +const char *q1Str = +"4 17B5E51EC931E724ABACE9C7F8AFDD51F3929478B47C222F99844D166936063D3BFCDF7AD7079EEF4BE8514E3D09EF0F\n" +"0F5794F38BAEC0FA3C30AC4C0B8E9024B2047F2F4576434F91768F2B51AD58C48E88414B1D4B7A9119A947D3CFEDEF0A\n" +"1320714A8B7E23C4C558D2B1C556CC8FB6B41F3669EFD70B6D204C2A7C6EF2E0CBCA945AA7BACB402E00ED338F7D12FC\n" +"0C2846E386161F123344704528D9944677806C3F784E3997857C91D2F3F37AB6AD92360CD97CABD5D631E9FC74708AD3\n" +"17F92FF3D71B473B802F2DE90C19A5F5DBFAA397293871AB58E5B813F7D686EA8E1814C69C50C02D062F3A13C1D045E1\n" +"05214392858DE04B3B468B2D0C703A485508C29157D81E9F799BAB2FEF0F514C99D5F8085D8062281418C6CCE5621D18\n"; + + const int mode = mcl::IoEcProj | 16; + Fp6 l, m; + G2 Q, Q1; + G1 P; + + G1::setOrder(0); + Q.setStr(qStr, mode); + P.setStr(pStr, mode); + l.a.setStr(l0Str, mode); + l.b.setStr(l4Str, mode); + l.c.setStr(l1Str, mode); + local::dblLine(l, Q, P); + m.a.setStr(m0Str, mode); + m.b.setStr(m4Str, mode); + m.c.setStr(m1Str, mode); + Q1.setStr(q1Str, mode); + CYBOZU_TEST_EQUAL(l, m); + CYBOZU_TEST_EQUAL(Q, Q1); + G1::setOrder(BN::param.r); +} + +CYBOZU_TEST_AUTO(mul_012) +{ + const char *fStr = +"087590AFBFEB8F85DD912EC297C2B5DD7BC0A9B0914348C5D99F0089C09CDBA0DCDAF1C704A7B092D8FB9A75B7C06D88\n" +"119DD8B08C40D4EB3D7AF19221E41639A98A10EF1A22F9AD8CB1350526B9335F47E76B2FFD6652E693A67440574D5A0C\n" +"134ADA7C4ABFBA4324900D25E5077A119F9E55A7F337C03FD539D8DAC392B458F11261BEA007393D43657E9656B984D6\n" +"01032DDB3CAEC38B7DA916CA111C46A013F1DC83AF13DFF5B71CC3789974F946CFC43FE7B8EE519E524627248369FCE7\n" +"19E9455C14A9640139224BB1337E4EC5EE92BFF757DB179CC98CF0F09682E44ED4B6004F31D4788DE28BB2D8F41DDAE4\n" +"0B9877DF6AC1015375AB421363A5B06D2DC1763B923FF674A06AE101306A4A39967A3F9EF12E870C124A26CE68E2D003\n" +"02AA5AC5901C9C91CD0B43CA62F21FA541896802A8AAF0FD5EDF8DAF4A98CEC19F457A67369E795594543677B4A16EA4\n" +"0604DB7CE2A0ABD8ADB5F4F06F20B01510BF9787C912B1036F570E7368D341D9B794F078DFD3265306841180865500D0\n" +"08145045CF5751502778739EFE6FEA6036C8F14800F4818C2FD8BA5AF98E89B0BBE6510D511C4E5A83A2813A92B655F0\n" +"0FDE93D3326321ECF6171FBC4665F1C171F19A6F1D521BFA1A1B80E0B08CEBB78B255AF0B5F7E45AA6C1D01005200FB1\n" +"0F2A9EA2891A683AE15A79EDB0C6DF45FFAD4D22F3293AE59D3CE8F6E0E59A097673D05D81ACAD8C59817FFDD3E89CF1\n" +"0724BD07BDDCA23775C1DECD80CE7722F98C10E75A0CD9A1FA81921A04EEFAC55BE0740C5F01ED83FDFC66380339D417\n"; + +const char *l0Str = +"198D1123A9817C40A914A3FF9E29BB16DD2F0DF98D0AB5C3A6014D60E31AE973051C35ADCEA0A41F32BB16E6688DC73F\n" +"10339DB2F26D1B867FD3E60A24F938210EABEFC51536845A490F28A088A4AC53575DBBAA218D70D34E28EBDE14DB3465"; +const char *l1Str = +"066852248D915F6378B3F4A8E6173AC748FBFAE236AAEEAECC3F34D2D22706A06B925A83DD8276B2B240F61D761587B0\n" +"17CC8195E6607FF19A26AA69CA50C32487E35D2D75301AC4B6988F1B77523BF472927EE5710DF49A563534D86C684BE0\n"; +const char *l4Str = +"10B67D1A0CE430B7AD74F64DD6C2E44C4788EADF8340909843C96B918BF54703CC14686B26E350EB1140ACC3337EEEB4\n" +"0F5D52E6F0B10A081EFF885CC858109241B379985ADD8982E6B8A202FD283897EFBA4CBE444C29751410A61FC8346545\n"; + +const char *f2Str = +"10128E1A9BD00FC81F6550921D0FED3944F63F980ABF91FDB73B1ED162337ED16075730ACD60A0FA7DFABAD9FC9657C5\n" +"055BE26091D8CDA32241F4991A1F184E403C3FFDD54858B23D5CE4B44402B65B26BCA6855DA7AC1C60F1D6651632DCD8\n" +"0D70827981F0D33185DE8767FDDFEC26CEB6A28F82C83BBABB0057E432FCF9072B666974123274751E35F371E931D6CC\n" +"02382B1A80E5BC95C75AE71BE2E097FD59365279CDD7EA358D87DEF132430744DABBF1B685D110CC731A9FDA40EEFC1B\n" +"0AAB560FB99D57A9B1B6C753DAF6B0619ED598C9B5FB0908F2DAE83C530E6365DBEDE29B9357D63803F46247A1F41C73\n" +"13C048F553BFC3C56516786DD26FF9D59ECFB9BE6B165F90E77CCED623BC66C6E93EFBF14576DB7E33C8C4F4E21F64DC\n" +"0987D7DEBB96A10D977F256432871BEBB4B3A620E4AE822E089E9DAA192CD278E9FA0CF598444F6758628BC38C33A5AD\n" +"0A4F1B75845B6C976BF49C35134AE73CA7A3C16D2E0BDA39C70367E3829E94EB7CAFBB0F8B57F4734B696D9CEF84FE73\n" +"0DFAB9C035F3DA51226F27998A494A32245800F0313446D6437D2F5B3F34A9E91428818B0C9AF63EB3AA618E80055FD5\n" +"06A58B9640FF8931616F6D08BA16ECE71F341C61F22E5EC5B556DF217179C3ECEC20E4BE425A3471F1D6648D14F89FBF\n" +"1614391845CDC212937BC1070010603FB4DF99A6B3FA7E7CD3316C56BA8B633B3DC7D864B36DA2F9A1E6B977DB150100\n" +"144A44415BCCB077EAA64C8DAC50631AF432C1420EBD8538818D65D6176BC1EB699579CED8340493306AF842B4B6822E"; + + Fp6 l; + Fp12 f, f2; + l.a.setStr(l0Str, 16); + l.b.setStr(l4Str, 16); + l.c.setStr(l1Str, 16); + f.setStr(fStr, 16); + f2.setStr(f2Str, 16); + local::mulSparse(f, l); + CYBOZU_TEST_EQUAL(f, f2); +} + +CYBOZU_TEST_AUTO(pairing) +{ + const int mode = mcl::IoEcProj | 16; + +const char *pStr = +"4 0FD3977C60EC322BC281C915955ED534B491E39C72E8E800271CEF3F0492D890829FA69C45FCE93D9847A0CAB325D871\n" +"17CC2C36C5D283C05BFCECCF48DBB2050332DA058DD67326A9EE520967DBCAEDFCB5F05A085D1A49DF08BB968CC782C5\n" +"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"; +const char *qStr = +"4 0B5C339C23F8EAB3647E974BCDDF72C96F97A444346BE72CA73AB1323B83B8F6161257AB34C7E0CF34F6C45086CA5868\n" +"13C2235E9F9DFB33344BA2EE5A71435859022880732EDC9EC75AC79AE9DA972593CDC40A0AC334D6D2E8D7FAD1D98D0B\n" +"134B8EED8196A00D3B70ADBC26FF963B725A351CF0B73FE1A541788AFB0BB081AF82A438021B5E878B15D53B1D27C6A7\n" +"18CC69F847BEE826B939DCB4030D33020D03B046465C9EE103AA8009A175DB169070294E75771586687FE361DB884BCD\n" +"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\n" +"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; +const char *eStr = +"0E05D19E90D2C501E5502C7AC80D77201C47DF147DD1076440F0DF0179DF9802CA0775E0E73DD9174F1094D2280787B3\n" +"14D2F5C84279E7177A3543FBEAE261DE8F6C97EFD5F3FF3F959EC9FC0303F620A4B3AF00DF409496CECADDD0A7F0A164\n" +"1414E9B9DF8DF1EAC2E70D5538018377788C62016A54F28B037A68740705089AE431B86756F98CBE19690A5EAC0C2466\n" +"12D8B32157836A131CCA3CA313DAAAF909BC3AD6BDD15885BB429922B9CD7D1246D1163E5E6F88D68BF1B75E451EFABB\n" +"102C9A839A924E0D603D13F2E08A919E0B9EE2A269FC75727BA13D66027C157B9BB4077977FA94557DE4427BF11B234B\n" +"19DBEB7F2E3096AFFD44837655BD8249741B484B0EB0DBEE569DEA8D9E38AE09D210C8BC16AA6DFBC923095B2C9A8B2B\n" +"19B9A6DCCD01FA0D04D5CE94D8BDCE1DF64AFEB7FD493B955180A5C6B236E469F0E07CC9BB4203FCAC46AE6F8E5419D6\n" +"02BFA87AF7A3726A7ABACDCFDD53694AF651554F3A431AB4274F67D5DAD2D6C88AF794705FF456A936C83594731AD8DC\n" +"0F21E0173E3B50DD98EFA815B410631A57399B451FD6E1056FFD09C9FE50EFAD3D026F0C46C8BB1583A50B7853D990DA\n" +"02230237AE04B61F9269F6E7CD2FCF1231CEE4690AA658B0018EFC0D0770FD0A56B3B7294086E8D306B1465CDDD858CD\n" +"087EB8F6547015661E9CD48D6525C808636FCB8420B867CB2A87E006B2A93BBD5EF675E6CDDA9E6F94519C49EA8BB689\n" +"19F5C988B2DD6E33D7D3D34EFB1991F80DC28006AC75E0AB53FD98FC6F2476D05DD4ECA582F5FF72B8DDD9DDDE80FFC9"; + G1 P; + G2 Q; + P.setStr(pStr, mode); + Q.setStr(qStr, mode); + Fp12 e1, e2; + e1.setStr(eStr, 16); + pairing(e2, P, Q); + CYBOZU_TEST_EQUAL(e1, e2); +} + +void testCurve(const mcl::CurveParam& cp) +{ + initPairing(cp, g_mode); + G1 P; + G2 Q; + mapToG1(P, 1); + mapToG2(Q, 1); + GT e1, e2; + pairing(e1, P, Q); + cybozu::XorShift rg; + mpz_class a, b; + Fr r; + r.setRand(rg); a = r.getMpz(); + r.setRand(rg); b = r.getMpz(); + G1 aP; + G2 bQ; + G1::mul(aP, P, a); + G2::mul(bQ, Q, b); + pairing(e2, aP, bQ); + GT::pow(e1, e1, a * b); + CYBOZU_TEST_EQUAL(e1, e2); +} +CYBOZU_TEST_AUTO(multi) +{ + G1 P; + G2 Q; + int i; + puts("BN254"); + testCurve(mcl::BN254); + i = 1; + CYBOZU_BENCH_C("calcBN1", 100, (BN::param.mapTo.calcBN), P, i++); + CYBOZU_BENCH_C("naiveG2", 100, (BN::param.mapTo.naiveMapTo), P, i++); + CYBOZU_BENCH_C("calcBN2", 100, (BN::param.mapTo.calcBN), Q, i++); + CYBOZU_BENCH_C("naiveG2", 100, (BN::param.mapTo.naiveMapTo), Q, i++); + puts("BLS12_381"); + testCurve(mcl::BLS12_381); + i = 1; + CYBOZU_BENCH_C("calcBN1", 100, (BN::param.mapTo.calcBN), P, i++); + CYBOZU_BENCH_C("naiveG1", 100, (BN::param.mapTo.naiveMapTo), P, i++); + CYBOZU_BENCH_C("calcBN2", 100, (BN::param.mapTo.calcBN), Q, i++); + CYBOZU_BENCH_C("naiveG2", 100, (BN::param.mapTo.naiveMapTo), Q, i++); +} + +CYBOZU_TEST_AUTO(BLS12_G1mulCofactor) +{ + if (BN::param.cp.curveType != MCL_BLS12_381) return; +} + +typedef std::vector FpVec; + +void f(FpVec& zv, const FpVec& xv, const FpVec& yv) +{ + for (size_t i = 0; i < zv.size(); i++) { + Fp::mul(zv[i], xv[i], yv[i]); + } +} +int main(int argc, char *argv[]) + try +{ + cybozu::Option opt; + std::string mode; + opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)"); + if (!opt.parse(argc, argv)) { + opt.usage(); + return 1; + } + g_mode = mcl::fp::StrToMode(mode); + printf("JIT %d\n", mcl::fp::isEnableJIT()); +#if 0 + initPairing(mcl::BLS12_381); + cybozu::XorShift rg; + const int n = 1; + std::vector xv(n), yv(n), zv(n); + for (int i = 0; i < n; i++) { + xv[i].setByCSPRNG(rg); + yv[i].setByCSPRNG(rg); + } + FpDbl dx; + FpDbl::mulPre(dx, xv[0], yv[0]); + Fp2 x2, y2; + x2.a.setByCSPRNG(rg); + x2.b.setByCSPRNG(rg); + y2.a.setByCSPRNG(rg); + y2.b.setByCSPRNG(rg); + Fp2Dbl x2d, y2d; + Fp2Dbl::mulPre(x2d, x2, x2); + Fp2Dbl::mulPre(y2d, x2, y2); +if(0){ + puts("----------"); + xv[0].dump(); + yv[0].dump(); + dx.dump(); + puts("----------"); +// exit(1); +} +// CYBOZU_BENCH_C("Fp2::neg", 10000000, Fp2::neg, x2, x2); + CYBOZU_BENCH_C("Fp2::sqr", 10000000, Fp2::sqr, x2, x2); +// CYBOZU_BENCH_C("Fp2::sqrPre", 100000000, Fp2Dbl::sqrPre, x2d, x2); +// CYBOZU_BENCH_C("Fp2::mulPre", 100000000, Fp2Dbl::mulPre, x2d, x2, y2); +// CYBOZU_BENCH_C("sqrPre", 100000000, FpDbl::sqrPre, dx, xv[0]); +// CYBOZU_BENCH_C("mod ", 100000000, FpDbl::mod, xv[0], dx); +// CYBOZU_BENCH_C("mul ", 100000000, Fp::mul, xv[0], yv[0], xv[0]); +// CYBOZU_BENCH_C("sqr ", 100000000, Fp::sqr, xv[0], xv[0]); + return 0; +#endif + return cybozu::test::autoRun.run(argc, argv); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn384_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn384_test.cpp new file mode 100644 index 000000000..b5674a918 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bn384_test.cpp @@ -0,0 +1,83 @@ +#define CYBOZU_TEST_DISABLE_AUTO_RUN +#include +#include +#include +#include +#include +#include + +using namespace mcl::bn384; + +mcl::fp::Mode g_mode; + +#include "bench.hpp" + +void testCurve(const mcl::CurveParam& cp) +{ + initPairing(cp, g_mode); + G1 P; + G2 Q; + mapToG1(P, 1); + mapToG2(Q, 1); + GT e1, e2; +#ifdef ONLY_BENCH + cybozu::CpuClock clk; + for (int i = 0; i < 10000; i++) { clk.begin(); pairing(e1, P, Q); clk.end(); } + clk.put(); + return; +#endif + pairing(e1, P, Q); + cybozu::XorShift rg; + mpz_class a, b; + Fr r; + r.setRand(rg); a = r.getMpz(); + r.setRand(rg); b = r.getMpz(); + G1 aP; + G2 bQ; + G1::mul(aP, P, a); + G2::mul(bQ, Q, b); + pairing(e2, aP, bQ); + GT::pow(e1, e1, a * b); + CYBOZU_TEST_EQUAL(e1, e2); + testBench(P, Q); + testSquareRoot(); + testLagrange(); +} + +CYBOZU_TEST_AUTO(pairing) +{ +// puts("BN160"); +// testCurve(mcl::BN160); + puts("BN254"); + // support 256-bit pairing + testCurve(mcl::BN254); + puts("BN381_1"); + testCurve(mcl::BN381_1); + puts("BN381_2"); + testCurve(mcl::BN381_2); + puts("BLS12_381"); + testCurve(mcl::BLS12_381); + // Q is not on EcT, but bad order + { + const char *s = "1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50"; + G2 Q; + CYBOZU_TEST_EXCEPTION(Q.setStr(s, 16), std::exception); + } +} + +int main(int argc, char *argv[]) + try +{ + cybozu::Option opt; + std::string mode; + opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)"); + if (!opt.parse(argc, argv)) { + opt.usage(); + return 1; + } + g_mode = mcl::fp::StrToMode(mode); + return cybozu::test::autoRun.run(argc, argv); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn512_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn512_test.cpp new file mode 100644 index 000000000..905bfd3db --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bn512_test.cpp @@ -0,0 +1,68 @@ +#define CYBOZU_TEST_DISABLE_AUTO_RUN +#include +#include +#include +#include +#include +#include + +using namespace mcl::bn512; + +mcl::fp::Mode g_mode; + +#include "bench.hpp" + +void testCurve(const mcl::CurveParam& cp) +{ + initPairing(cp, g_mode); + G1 P; + G2 Q; + mapToG1(P, 1); + mapToG2(Q, 1); + GT e1, e2; + pairing(e1, P, Q); + cybozu::XorShift rg; + mpz_class a, b; + Fr r; + r.setRand(rg); a = r.getMpz(); + r.setRand(rg); b = r.getMpz(); + G1 aP; + G2 bQ; + G1::mul(aP, P, a); + G2::mul(bQ, Q, b); + pairing(e2, aP, bQ); + GT::pow(e1, e1, a * b); + CYBOZU_TEST_EQUAL(e1, e2); + testBench(P, Q); + testSquareRoot(); + testLagrange(); +} + +CYBOZU_TEST_AUTO(pairing) +{ + puts("BN462"); + testCurve(mcl::BN462); + puts("BN381_1"); + testCurve(mcl::BN381_1); + puts("BLS12_381"); + testCurve(mcl::BLS12_381); + puts("BN254"); + testCurve(mcl::BN254); +} + +int main(int argc, char *argv[]) + try +{ + cybozu::Option opt; + std::string mode; + opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)"); + if (!opt.parse(argc, argv)) { + opt.usage(); + return 1; + } + g_mode = mcl::fp::StrToMode(mode); + return cybozu::test::autoRun.run(argc, argv); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c256_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c256_test.cpp new file mode 100644 index 000000000..2ce85162d --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c256_test.cpp @@ -0,0 +1,6 @@ +#include +using namespace mcl::bn256; +#define MCLBN_DEFINE_STRUCT +#define MCLBN_FP_UNIT_SIZE 4 +#include "bn_c_test.hpp" + diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c384_256_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_256_test.cpp new file mode 100644 index 000000000..e7bbefda9 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_256_test.cpp @@ -0,0 +1,7 @@ +#include +using namespace mcl::bls12; +#define MCLBN_DEFINE_STRUCT +#define MCLBN_FP_UNIT_SIZE 6 +#define MCLBN_FR_UNIT_SIZE 4 +#include "bn_c_test.hpp" + diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c384_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_test.cpp new file mode 100644 index 000000000..a9f20243a --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_test.cpp @@ -0,0 +1,6 @@ +#include +using namespace mcl::bn384; +#define MCLBN_DEFINE_STRUCT +#define MCLBN_FP_UNIT_SIZE 6 +#include "bn_c_test.hpp" + diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c512_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c512_test.cpp new file mode 100644 index 000000000..c6af3989f --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c512_test.cpp @@ -0,0 +1,6 @@ +#include +using namespace mcl::bn512; +#define MCLBN_DEFINE_STRUCT +#define MCLBN_FP_UNIT_SIZE 8 +#include "bn_c_test.hpp" + diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_c_test.hpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c_test.hpp new file mode 100644 index 000000000..e9dc59393 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bn_c_test.hpp @@ -0,0 +1,699 @@ +/* + include from bn_if256_test.cpp and bn_if384_test.cpp +*/ +#include +#include +#include +#include +#include + +template +std::ostream& dump(std::ostream& os, const uint64_t (&x)[N]) +{ + for (size_t i = 0; i < N; i++) { + char buf[64]; + CYBOZU_SNPRINTF(buf, sizeof(buf), "%016llx", (long long)x[i]); + os << buf; + } + return os; +} + +CYBOZU_TEST_AUTO(init) +{ + int ret; + CYBOZU_TEST_EQUAL(sizeof(mclBnFr), sizeof(Fr)); + CYBOZU_TEST_EQUAL(sizeof(mclBnG1), sizeof(G1)); + CYBOZU_TEST_EQUAL(sizeof(mclBnG2), sizeof(G2)); + CYBOZU_TEST_EQUAL(sizeof(mclBnGT), sizeof(Fp12)); + +#if MCLBN_FP_UNIT_SIZE >= 4 + printf("test BN254 %d\n", MCLBN_FP_UNIT_SIZE); + ret = mclBn_init(MCL_BN254, MCLBN_COMPILED_TIME_VAR); +#endif +#if MCLBN_FP_UNIT_SIZE >= 6 && MCLBN_FR_UNIT_SIZE >= 4 + printf("test BLS12_381 %d\n", MCLBN_FP_UNIT_SIZE); + ret = mclBn_init(MCL_BLS12_381, MCLBN_COMPILED_TIME_VAR); +#endif +#if MCLBN_FP_UNIT_SIZE >= 6 && MCLBN_FR_UNIT_SIZE >= 6 + printf("test BN381_1 %d\n", MCLBN_FP_UNIT_SIZE); + ret = mclBn_init(MCL_BN381_1, MCLBN_COMPILED_TIME_VAR); +#endif +#if MCLBN_FP_UNIT_SIZE == 8 + printf("test BN462 %d\n", MCLBN_FP_UNIT_SIZE); + ret = mclBn_init(MCL_BN462, MCLBN_COMPILED_TIME_VAR); +#endif + CYBOZU_TEST_EQUAL(ret, 0); + if (ret != 0) exit(1); +} + +CYBOZU_TEST_AUTO(Fr) +{ + mclBnFr x, y; + memset(&x, 0xff, sizeof(x)); + CYBOZU_TEST_ASSERT(!mclBnFr_isValid(&x)); + CYBOZU_TEST_ASSERT(!mclBnFr_isZero(&x)); + + mclBnFr_clear(&x); + CYBOZU_TEST_ASSERT(mclBnFr_isZero(&x)); + + mclBnFr_setInt(&x, 1); + CYBOZU_TEST_ASSERT(mclBnFr_isOne(&x)); + + mclBnFr_setInt(&y, -1); + CYBOZU_TEST_ASSERT(!mclBnFr_isEqual(&x, &y)); + + y = x; + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y)); + + mclBnFr_setHashOf(&x, "", 0); + mclBnFr_setHashOf(&y, "abc", 3); + CYBOZU_TEST_ASSERT(!mclBnFr_isEqual(&x, &y)); + mclBnFr_setHashOf(&x, "abc", 3); + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y)); + + char buf[1024]; + mclBnFr_setInt(&x, 12345678); + size_t size; + size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_EQUAL(size, 8); + CYBOZU_TEST_EQUAL(buf, "12345678"); + + mclBnFr_setInt(&x, -7654321); + mclBnFr_neg(&x, &x); + size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_EQUAL(size, 7); + CYBOZU_TEST_EQUAL(buf, "7654321"); + + mclBnFr_setInt(&y, 123 - 7654321); + mclBnFr_add(&x, &x, &y); + size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_EQUAL(size, 3); + CYBOZU_TEST_EQUAL(buf, "123"); + + mclBnFr_setInt(&y, 100); + mclBnFr_sub(&x, &x, &y); + size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_EQUAL(size, 2); + CYBOZU_TEST_EQUAL(buf, "23"); + + mclBnFr_mul(&x, &x, &y); + size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_EQUAL(size, 4); + CYBOZU_TEST_EQUAL(buf, "2300"); + + mclBnFr_div(&x, &x, &y); + size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_EQUAL(size, 2); + CYBOZU_TEST_EQUAL(buf, "23"); + + mclBnFr_mul(&x, &y, &y); + mclBnFr_sqr(&y, &y); + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y)); + + const char *s = "12345678901234567"; + CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&x, s, strlen(s), 10)); + s = "20000000000000000"; + CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&y, s, strlen(s), 10)); + mclBnFr_add(&x, &x, &y); + size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_EQUAL(size, 17); + CYBOZU_TEST_EQUAL(buf, "32345678901234567"); + + mclBnFr_setInt(&x, 1); + mclBnFr_neg(&x, &x); + size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_ASSERT(size > 0); + CYBOZU_TEST_EQUAL(size, strlen(buf)); + CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&y, buf, size, 10)); + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y)); + + for (int i = 0; i < 10; i++) { + mclBnFr_setByCSPRNG(&x); + mclBnFr_getStr(buf, sizeof(buf), &x, 16); + printf("%s\n", buf); + } +} + +void G1test() +{ + mclBnG1 x, y, z; + memset(&x, 0x1, sizeof(x)); + /* + assert() of carry operation fails if use 0xff, so use 0x1 + */ + CYBOZU_TEST_ASSERT(!mclBnG1_isValid(&x)); + mclBnG1_clear(&x); + CYBOZU_TEST_ASSERT(mclBnG1_isValid(&x)); + CYBOZU_TEST_ASSERT(mclBnG1_isZero(&x)); + + CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&y, "abc", 3)); + CYBOZU_TEST_ASSERT(mclBnG1_isValidOrder(&y)); + + char buf[1024]; + size_t size; + size = mclBnG1_getStr(buf, sizeof(buf), &y, 10); + CYBOZU_TEST_ASSERT(size > 0); + CYBOZU_TEST_EQUAL(size, strlen(buf)); + CYBOZU_TEST_ASSERT(!mclBnG1_setStr(&x, buf, strlen(buf), 10)); + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &y)); + + mclBnG1_neg(&x, &x); + mclBnG1_add(&x, &x, &y); + CYBOZU_TEST_ASSERT(mclBnG1_isZero(&x)); + + mclBnG1_dbl(&x, &y); // x = 2y + mclBnG1_add(&z, &y, &y); + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z)); + mclBnG1_add(&z, &z, &y); // z = 3y + mclBnFr n; + mclBnFr_setInt(&n, 3); + mclBnG1_mul(&x, &y, &n); // x = 3y + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z)); + mclBnG1_sub(&x, &x, &y); // x = 2y + + mclBnFr_setInt(&n, 2); + mclBnG1_mul(&z, &y, &n); // z = 2y + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z)); + mclBnG1_normalize(&y, &z); + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&y, &z)); +} + +CYBOZU_TEST_AUTO(G1) +{ + G1test(); +} + +CYBOZU_TEST_AUTO(G2) +{ + mclBnG2 x, y, z; + /* + assert() of carry operation fails if use 0xff, so use 0x1 + */ + memset(&x, 0x1, sizeof(x)); + CYBOZU_TEST_ASSERT(!mclBnG2_isValid(&x)); + mclBnG2_clear(&x); + CYBOZU_TEST_ASSERT(mclBnG2_isValid(&x)); + CYBOZU_TEST_ASSERT(mclBnG2_isZero(&x)); + + CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&x, "abc", 3)); + CYBOZU_TEST_ASSERT(mclBnG2_isValidOrder(&x)); + + char buf[1024]; + size_t size; + size = mclBnG2_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_ASSERT(size > 0); + CYBOZU_TEST_EQUAL(size, strlen(buf)); + CYBOZU_TEST_ASSERT(!mclBnG2_setStr(&y, buf, strlen(buf), 10)); + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &y)); + + mclBnG2_neg(&x, &x); + mclBnG2_add(&x, &x, &y); + CYBOZU_TEST_ASSERT(mclBnG2_isZero(&x)); + + mclBnG2_dbl(&x, &y); // x = 2y + mclBnG2_add(&z, &y, &y); + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z)); + mclBnG2_add(&z, &z, &y); // z = 3y + mclBnFr n; + mclBnFr_setInt(&n, 3); + mclBnG2_mul(&x, &y, &n); // x = 3y + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z)); + mclBnG2_sub(&x, &x, &y); // x = 2y + + mclBnFr_setInt(&n, 2); + mclBnG2_mul(&z, &y, &n); // z = 2y + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z)); + mclBnG2_normalize(&y, &z); + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&y, &z)); +} + +CYBOZU_TEST_AUTO(GT) +{ + mclBnGT x, y, z; + memset(&x, 1, sizeof(x)); + CYBOZU_TEST_ASSERT(!mclBnGT_isZero(&x)); + + mclBnGT_clear(&x); + CYBOZU_TEST_ASSERT(mclBnGT_isZero(&x)); + + mclBnGT_setInt(&x, 1); + CYBOZU_TEST_ASSERT(mclBnGT_isOne(&x)); + char buf[2048]; + size_t size; + size = mclBnGT_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_ASSERT(size > 0); + CYBOZU_TEST_EQUAL(size, strlen(buf)); + const char *s = "1 0 0 0 0 0 0 0 0 0 0 0"; + CYBOZU_TEST_EQUAL(buf, s); + + s = "1 2 3 4 5 6 7 8 9 10 11 12"; + CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&x,s , strlen(s), 10)); + size = mclBnGT_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_ASSERT(size > 0); + CYBOZU_TEST_EQUAL(size, strlen(buf)); + CYBOZU_TEST_EQUAL(buf, s); + + y = x; + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &y)); + + s = "-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12"; + CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&z, s, strlen(s), 10)); + size = mclBnGT_getStr(buf, sizeof(buf), &z, 10); + CYBOZU_TEST_ASSERT(size > 0); + CYBOZU_TEST_EQUAL(size, strlen(buf)); + CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&y, buf, size, 10)); + + mclBnGT_neg(&z, &y); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &z)); + + mclBnGT_add(&y, &x, &y); + CYBOZU_TEST_ASSERT(mclBnGT_isZero(&y)); + + s = "2 0 0 0 0 0 0 0 0 0 0 0"; + CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&y, s, strlen(s), 10)); + mclBnGT_mul(&z, &x, &y); + size = mclBnGT_getStr(buf, sizeof(buf), &z, 10); + CYBOZU_TEST_ASSERT(size > 0); + CYBOZU_TEST_EQUAL(size, strlen(buf)); + CYBOZU_TEST_EQUAL(buf, "2 4 6 8 10 12 14 16 18 20 22 24"); + + mclBnGT_div(&z, &z, &y); + size = mclBnGT_getStr(buf, sizeof(buf), &x, 10); + CYBOZU_TEST_ASSERT(size > 0); + CYBOZU_TEST_EQUAL(size, strlen(buf)); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &z)); + + /* + can't use mclBnGT_pow because x is not in GT + */ + mclBnFr n; + mclBnFr_setInt(&n, 3); + mclBnGT_powGeneric(&z, &x, &n); + mclBnGT_mul(&y, &x, &x); + mclBnGT_mul(&y, &y, &x); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&y, &z)); + + mclBnGT_mul(&x, &y, &y); + mclBnGT_sqr(&y, &y); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &y)); +} + +CYBOZU_TEST_AUTO(pairing) +{ + mclBnFr a, b, ab; + mclBnFr_setInt(&a, 123); + mclBnFr_setInt(&b, 456); + mclBnFr_mul(&ab, &a, &b); + mclBnG1 P, aP; + mclBnG2 Q, bQ; + mclBnGT e, e1, e2; + + CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P, "1", 1)); + CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q, "1", 1)); + + mclBnG1_mul(&aP, &P, &a); + mclBnG2_mul(&bQ, &Q, &b); + + mclBn_pairing(&e, &P, &Q); + mclBnGT_pow(&e1, &e, &a); + mclBn_pairing(&e2, &aP, &Q); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2)); + + mclBnGT_pow(&e1, &e, &b); + mclBn_pairing(&e2, &P, &bQ); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2)); + + mclBnFr n; + mclBnFr_setInt(&n, 3); + mclBnGT_pow(&e1, &e, &n); + mclBnGT_mul(&e2, &e, &e); + mclBnGT_mul(&e2, &e2, &e); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2)); +} + +CYBOZU_TEST_AUTO(precomputed) +{ + mclBnG1 P1, P2; + mclBnG2 Q1, Q2; + CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P1, "1", 1)); + CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P2, "123", 3)); + CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q1, "1", 1)); + CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q2, "2", 1)); + + const int size = mclBn_getUint64NumToPrecompute(); + std::vector Q1buf, Q2buf; + Q1buf.resize(size); + Q2buf.resize(size); + mclBn_precomputeG2(Q1buf.data(), &Q1); + mclBn_precomputeG2(Q2buf.data(), &Q2); + + mclBnGT e1, e2, f1, f2, f3, f4; + mclBn_pairing(&e1, &P1, &Q1); + mclBn_precomputedMillerLoop(&f1, &P1, Q1buf.data()); + mclBn_finalExp(&f1, &f1); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &f1)); + + mclBn_pairing(&e2, &P2, &Q2); + mclBn_precomputedMillerLoop(&f2, &P2, Q2buf.data()); + mclBn_finalExp(&f2, &f2); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e2, &f2)); + + mclBn_precomputedMillerLoop2(&f3, &P1, Q1buf.data(), &P2, Q2buf.data()); + mclBn_precomputedMillerLoop2mixed(&f4, &P1, &Q1, &P2, Q2buf.data()); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&f3, &f4)); + mclBn_finalExp(&f3, &f3); + + mclBnGT_mul(&e1, &e1, &e2); + CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &f3)); +} + +CYBOZU_TEST_AUTO(serialize) +{ + const size_t FrSize = mclBn_getFrByteSize(); + const size_t G1Size = mclBn_getG1ByteSize(); + mclBnFr x1, x2; + mclBnG1 P1, P2; + mclBnG2 Q1, Q2; + char buf[1024]; + size_t n; + size_t expectSize; + size_t ret; + // Fr + expectSize = FrSize; + mclBnFr_setInt(&x1, -1); + n = mclBnFr_serialize(buf, sizeof(buf), &x1); + CYBOZU_TEST_EQUAL(n, expectSize); + + ret = mclBnFr_deserialize(&x2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2)); + + ret = mclBnFr_deserialize(&x2, buf, n - 1); + CYBOZU_TEST_EQUAL(ret, 0); + + memset(&x2, 0, sizeof(x2)); + ret = mclBnFr_deserialize(&x2, buf, n + 1); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2)); + + n = mclBnFr_serialize(buf, expectSize, &x1); + CYBOZU_TEST_EQUAL(n, expectSize); + + // G1 + expectSize = G1Size; + mclBnG1_hashAndMapTo(&P1, "1", 1); + n = mclBnG1_serialize(buf, sizeof(buf), &P1); + CYBOZU_TEST_EQUAL(n, expectSize); + + ret = mclBnG1_deserialize(&P2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2)); + + ret = mclBnG1_deserialize(&P2, buf, n - 1); + CYBOZU_TEST_EQUAL(ret, 0); + + memset(&P2, 0, sizeof(P2)); + ret = mclBnG1_deserialize(&P2, buf, n + 1); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2)); + + n = mclBnG1_serialize(buf, expectSize, &P1); + CYBOZU_TEST_EQUAL(n, expectSize); + + // G2 + expectSize = G1Size * 2; + mclBnG2_hashAndMapTo(&Q1, "1", 1); + n = mclBnG2_serialize(buf, sizeof(buf), &Q1); + CYBOZU_TEST_EQUAL(n, expectSize); + + ret = mclBnG2_deserialize(&Q2, buf, n); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2)); + + ret = mclBnG2_deserialize(&Q2, buf, n - 1); + CYBOZU_TEST_EQUAL(ret, 0); + + memset(&Q2, 0, sizeof(Q2)); + ret = mclBnG2_deserialize(&Q2, buf, n + 1); + CYBOZU_TEST_EQUAL(ret, n); + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2)); + + n = mclBnG2_serialize(buf, expectSize, &Q1); + CYBOZU_TEST_EQUAL(n, expectSize); +} + +CYBOZU_TEST_AUTO(serializeToHexStr) +{ + const size_t FrSize = mclBn_getFrByteSize(); + const size_t G1Size = mclBn_getG1ByteSize(); + mclBnFr x1, x2; + mclBnG1 P1, P2; + mclBnG2 Q1, Q2; + char buf[1024]; + size_t n; + size_t expectSize; + size_t ret; + // Fr + expectSize = FrSize * 2; // hex string + mclBnFr_setInt(&x1, -1); + n = mclBnFr_getStr(buf, sizeof(buf), &x1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(n, expectSize); + + ret = mclBnFr_setStr(&x2, buf, n, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2)); + + ret = mclBnFr_setStr(&x2, buf, n - 1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_ASSERT(ret != 0); + + memset(&x2, 0, sizeof(x2)); + ret = mclBnFr_setStr(&x2, buf, n + 1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2)); + + n = mclBnFr_getStr(buf, expectSize, &x1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(n, expectSize); + + // G1 + expectSize = G1Size * 2; // hex string + mclBnG1_hashAndMapTo(&P1, "1", 1); + n = mclBnG1_getStr(buf, sizeof(buf), &P1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(n, expectSize); + + ret = mclBnG1_setStr(&P2, buf, n, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2)); + + ret = mclBnG1_setStr(&P2, buf, n - 1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_ASSERT(ret != 0); + + memset(&P2, 0, sizeof(P2)); + ret = mclBnG1_setStr(&P2, buf, n + 1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2)); + + n = mclBnG1_getStr(buf, expectSize, &P1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(n, expectSize); + + // G2 + expectSize = G1Size * 2 * 2; // hex string + mclBnG2_hashAndMapTo(&Q1, "1", 1); + n = mclBnG2_getStr(buf, sizeof(buf), &Q1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(n, expectSize); + + ret = mclBnG2_setStr(&Q2, buf, n, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2)); + + ret = mclBnG2_setStr(&Q2, buf, n - 1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_ASSERT(ret != 0); + + memset(&Q2, 0, sizeof(Q2)); + ret = mclBnG2_setStr(&Q2, buf, n + 1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(ret, 0); + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2)); + + n = mclBnG2_getStr(buf, expectSize, &Q1, MCLBN_IO_SERIALIZE_HEX_STR); + CYBOZU_TEST_EQUAL(n, expectSize); +} + +#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE >= 6 +CYBOZU_TEST_AUTO(badG2) +{ + int ret; + ret = mclBn_init(MCL_BN381_1, MCLBN_COMPILED_TIME_VAR); + CYBOZU_TEST_EQUAL(ret, 0); + const char *s = "1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50"; + mclBnG2 Q; + ret = mclBnG2_setStr(&Q, s, strlen(s), 16); + CYBOZU_TEST_ASSERT(ret != 0); +} +#endif + +struct Sequential { + uint32_t pos; + Sequential() : pos(0) {} + static uint32_t read(void *self, void *buf, uint32_t bufSize) + { + Sequential *seq = reinterpret_cast(self); + uint8_t *p = reinterpret_cast(buf); + for (uint32_t i = 0; i < bufSize; i++) { + p[i] = uint8_t(seq->pos + i) & 0x1f; // mask is to make valid Fp + } + seq->pos += bufSize; + return bufSize; + } +}; + +CYBOZU_TEST_AUTO(setRandFunc) +{ + Sequential seq; + for (int j = 0; j < 3; j++) { + puts(j == 1 ? "sequential rand" : "true rand"); + for (int i = 0; i < 5; i++) { + mclBnFr x; + int ret; + char buf[1024]; + ret = mclBnFr_setByCSPRNG(&x); + CYBOZU_TEST_EQUAL(ret, 0); + ret = mclBnFr_getStr(buf, sizeof(buf), &x, 16); + CYBOZU_TEST_ASSERT(ret > 0); + printf("%d %s\n", i, buf); + } + if (j == 0) { + mclBn_setRandFunc(&seq, Sequential::read); + } else { + mclBn_setRandFunc(0, 0); + } + } +} + +CYBOZU_TEST_AUTO(Fp) +{ + mclBnFp x1, x2; + char buf[1024]; + int ret = mclBnFp_setHashOf(&x1, "abc", 3); + CYBOZU_TEST_ASSERT(ret == 0); + mclSize n = mclBnFp_serialize(buf, sizeof(buf), &x1); + CYBOZU_TEST_ASSERT(n > 0); + n = mclBnFp_deserialize(&x2, buf, n); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_ASSERT(mclBnFp_isEqual(&x1, &x2)); + for (size_t i = 0; i < n; i++) { + buf[i] = char(i); + } + ret = mclBnFp_setLittleEndian(&x1, buf, n); + CYBOZU_TEST_ASSERT(ret == 0); + memset(buf, 0, sizeof(buf)); + n = mclBnFp_serialize(buf, sizeof(buf), &x1); + CYBOZU_TEST_ASSERT(n > 0); + for (size_t i = 0; i < n - 1; i++) { + CYBOZU_TEST_EQUAL(buf[i], char(i)); + } + mclBnFp_clear(&x1); + memset(&x2, 0, sizeof(x2)); + CYBOZU_TEST_ASSERT(mclBnFp_isEqual(&x1, &x2)); +} + +CYBOZU_TEST_AUTO(mod) +{ + { + // Fp + char buf[1024]; + mclBn_getFieldOrder(buf, sizeof(buf)); + mpz_class p(buf); + mpz_class x = mpz_class(1) << (mclBn_getFpByteSize() * 2); + mclBnFp y; + int ret = mclBnFp_setLittleEndianMod(&y, x.get_mpz_t()->_mp_d, x.get_mpz_t()->_mp_size * sizeof(void*)); + CYBOZU_TEST_EQUAL(ret, 0); + mclBnFp_getStr(buf, sizeof(buf), &y, 10); + CYBOZU_TEST_EQUAL(mpz_class(buf), x % p); + } + { + // Fr + char buf[1024]; + mclBn_getCurveOrder(buf, sizeof(buf)); + mpz_class p(buf); + mpz_class x = mpz_class(1) << (mclBn_getFrByteSize() * 2); + mclBnFr y; + int ret = mclBnFr_setLittleEndianMod(&y, x.get_mpz_t()->_mp_d, x.get_mpz_t()->_mp_size * sizeof(void*)); + CYBOZU_TEST_EQUAL(ret, 0); + mclBnFr_getStr(buf, sizeof(buf), &y, 10); + CYBOZU_TEST_EQUAL(mpz_class(buf), x % p); + } +} + +CYBOZU_TEST_AUTO(Fp2) +{ + mclBnFp2 x1, x2; + char buf[1024]; + int ret = mclBnFp_setHashOf(&x1.d[0], "abc", 3); + CYBOZU_TEST_ASSERT(ret == 0); + ret = mclBnFp_setHashOf(&x1.d[1], "xyz", 3); + CYBOZU_TEST_ASSERT(ret == 0); + mclSize n = mclBnFp2_serialize(buf, sizeof(buf), &x1); + CYBOZU_TEST_ASSERT(n > 0); + n = mclBnFp2_deserialize(&x2, buf, n); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_ASSERT(mclBnFp2_isEqual(&x1, &x2)); + mclBnFp2_clear(&x1); + memset(&x2, 0, sizeof(x2)); + CYBOZU_TEST_ASSERT(mclBnFp2_isEqual(&x1, &x2)); +} + +CYBOZU_TEST_AUTO(mapToG1) +{ + mclBnFp x; + mclBnG1 P1, P2; + mclBnFp_setHashOf(&x, "abc", 3); + int ret = mclBnFp_mapToG1(&P1, &x); + CYBOZU_TEST_ASSERT(ret == 0); + mclBnG1_hashAndMapTo(&P2, "abc", 3); + CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2)); +} + +CYBOZU_TEST_AUTO(mapToG2) +{ + mclBnFp2 x; + mclBnG2 P1, P2; + mclBnFp_setHashOf(&x.d[0], "abc", 3); + mclBnFp_clear(&x.d[1]); + int ret = mclBnFp2_mapToG2(&P1, &x); + CYBOZU_TEST_ASSERT(ret == 0); + mclBnG2_hashAndMapTo(&P2, "abc", 3); + CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&P1, &P2)); +} + +void G1onlyTest(int curve) +{ + printf("curve=%d\n", curve); + int ret; + ret = mclBn_init(curve, MCLBN_COMPILED_TIME_VAR); + CYBOZU_TEST_EQUAL(ret, 0); + mclBnG1 P0; + ret = mclBnG1_getBasePoint(&P0); + CYBOZU_TEST_EQUAL(ret, 0); + char buf[256]; + ret = mclBnG1_getStr(buf, sizeof(buf), &P0, 16); + CYBOZU_TEST_ASSERT(ret > 0); + printf("basePoint=%s\n", buf); + G1test(); +} + +CYBOZU_TEST_AUTO(G1only) +{ + const int tbl[] = { + MCL_SECP192K1, + MCL_NIST_P192, + MCL_SECP224K1, + MCL_NIST_P224, // hashAndMapTo is error + MCL_SECP256K1, + MCL_NIST_P256, +#if MCLBN_FP_UNIT_SIZE >= 6 && MCLBN_FR_UNIT_SIZE >= 6 + MCL_SECP384R1, +#endif + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + G1onlyTest(tbl[i]); + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/bn_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_test.cpp new file mode 100644 index 000000000..071ec706c --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/bn_test.cpp @@ -0,0 +1,408 @@ +#define PUT(x) std::cout << #x "=" << x << std::endl; +#define CYBOZU_TEST_DISABLE_AUTO_RUN +#include +cybozu::CpuClock clk; +#include +#include +#include +#include + +#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST) + #define MCL_AVOID_EXCEPTION_TEST +#endif + +typedef mcl::bn::local::Compress Compress; +using namespace mcl::bn; + +mcl::fp::Mode g_mode; + +const struct TestSet { + mcl::CurveParam cp; + const char *name; + struct G2 { + const char *aa; + const char *ab; + const char *ba; + const char *bb; + } g2; + struct G1 { + int a; + int b; + } g1; + const char *e; +} g_testSetTbl[] = { + { + mcl::BN254, + "BN254", + { + "12723517038133731887338407189719511622662176727675373276651903807414909099441", + "4168783608814932154536427934509895782246573715297911553964171371032945126671", + "13891744915211034074451795021214165905772212241412891944830863846330766296736", + "7937318970632701341203597196594272556916396164729705624521405069090520231616", + }, + { + -1, 1 + }, + "8118772341496577043438385328606447626730215814727396173233264007541007797690 " + "6742571767760762192519140673058087976840103832045324348366170860928670686713 " + "9727912590495366720378364920530546614235713408261568635512172059018197267630 " + "10180700148605185348549931182990442059136187839792856455707820203302941578832 " + "5054507763444412917986776641611331046146804026682679569910978464879371792565 " + "6917005519826733659554708445125877487590687705432214234949972860245110398023 " + "10448556317747236258066222816126375978842661908560317699736569642190930635294 " + "1516980358051268127904344653343215863076753141133525905743113718749531324025 " + "9794836735385959178744195210089532061310424844916928682580569566332541022353 " + "9375574834170998962484906689780052970915033987453510324648351251071086068423 " + "710778048594563655498360873129325895716179849942646859397874562033386335205 " + "10688745994254573144943003027511098295097561129365638275727908595677791826005" + }, + { + mcl::BN_SNARK1, + "BN_SNARK1", + { + "15267802884793550383558706039165621050290089775961208824303765753922461897946", + "9034493566019742339402378670461897774509967669562610788113215988055021632533", + "644888581738283025171396578091639672120333224302184904896215738366765861164", + "20532875081203448695448744255224543661959516361327385779878476709582931298750", + }, + { + 1, 2 + }, + "15163392945550945552839911839294582974434771053565812675833291179413834896953 " + "20389211011850518572149982239826345669421868561029856883955740401696801984953 " + "17766795911013516700216709333389761327222334145011922123798810516425387779347 " + "6064163297423711021549973931984064750876944939004405231004441199168710504090 " + "296093106139306574860102680862436174771023602986903675151017278048818344347 " + "1573596951222456889652521728261836933382094474023551133585236991207205981715 " + "3511871642997169996730611220058787939468653751355351269812083879279936651479 " + "17848534184080172844395614793152774197360421729995967636680357250333093768504 " + "3273860031361637906105800996652640969711942192883181518057117446820546419132 " + "7212721189663231589365009629980400132745687533815732336503876102977912682966 " + "18569236611881855981733896549089319395087993987737891870319625215675547032585 " + "10088832670068482545658647976676953228519838542958787800193793260459700064172 " + }, +}; + +CYBOZU_TEST_AUTO(size) +{ + CYBOZU_TEST_EQUAL(sizeof(Fp), 32u); + CYBOZU_TEST_EQUAL(sizeof(Fp2), sizeof(Fp) * 2); + CYBOZU_TEST_EQUAL(sizeof(Fp6), sizeof(Fp) * 6); + CYBOZU_TEST_EQUAL(sizeof(Fp12), sizeof(Fp) * 12); + CYBOZU_TEST_EQUAL(sizeof(G1), sizeof(Fp) * 3); + CYBOZU_TEST_EQUAL(sizeof(G2), sizeof(Fp2) * 3); +} + +void testSetStr(const G2& Q0) +{ + G2::setCompressedExpression(); + G2 Q; + Q.clear(); + for (int i = 0; i < 10; i++) { + G2 R; + R.setStr(Q.getStr()); + CYBOZU_TEST_EQUAL(Q, R); + G2::add(Q, Q, Q0); + } +} + +void testMapToG1() +{ + G1 g; + for (int i = 1; i < 10; i++) { + mapToG1(g, i); + CYBOZU_TEST_ASSERT(!g.isZero()); + G1 gr; + G1::mulGeneric(gr, g, BN::param.r); + CYBOZU_TEST_ASSERT(gr.isZero()); + } +#ifndef MCL_AVOID_EXCEPTION_TEST + if (BN::param.cp.b == 2) { + Fp c1; + bool b = Fp::squareRoot(c1, -3); + CYBOZU_TEST_ASSERT(b); + CYBOZU_TEST_EXCEPTION(mapToG1(g, 0), cybozu::Exception); + CYBOZU_TEST_EXCEPTION(mapToG1(g, c1), cybozu::Exception); + CYBOZU_TEST_EXCEPTION(mapToG1(g, -c1), cybozu::Exception); + } +#endif +} + +void testMapToG2() +{ + G2 g; + for (int i = 1; i < 10; i++) { + mapToG2(g, i); + CYBOZU_TEST_ASSERT(!g.isZero()); + G2 gr; + G2::mulGeneric(gr, g, BN::param.r); + CYBOZU_TEST_ASSERT(gr.isZero()); + } +#ifndef MCL_AVOID_EXCEPTION_TEST + if (BN::param.cp.b == 2) { + CYBOZU_TEST_EXCEPTION(mapToG2(g, 0), cybozu::Exception); + } +#endif + Fp x; + x.setHashOf("abc"); + mapToG2(g, Fp2(x, 0)); + CYBOZU_TEST_ASSERT(g.isValid()); +} + +void testCyclotomic() +{ + Fp12 a; + for (int i = 0; i < 12; ++i) { + a.getFp0()[i] = i * i; + } + local::mapToCyclotomic(a, a); + Fp12 d; + Compress b(d, a); + a *= a; + Fp12 d2; + Compress c(d2, b); + Compress::square_n(c, 1); + c.decompress(); + CYBOZU_TEST_EQUAL(a, d2); + Compress::square_n(b, 1); + b.decompress(); + CYBOZU_TEST_EQUAL(a, d); +} + +void testCompress(const G1& P, const G2& Q) +{ + if (BN::param.cp.curveType != MCL_BN254) return; + Fp12 a; + pairing(a, P, Q); + local::mapToCyclotomic(a, a); + Fp12 b; + Compress::fixed_power(b, a); + Fp12 c; + Fp12::pow(c, a, BN::param.abs_z); + CYBOZU_TEST_EQUAL(b, c); +} + +void testPrecomputed(const G1& P, const G2& Q) +{ + Fp12 e1, e2; + pairing(e1, P, Q); + std::vector Qcoeff; + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e2, P, Qcoeff); + finalExp(e2, e2); + CYBOZU_TEST_EQUAL(e1, e2); +} + +void testFp12pow(const G1& P, const G2& Q) +{ + Fp12 e, e1, e2; + pairing(e, P, Q); + cybozu::XorShift rg; + for (int i = -10; i < 10; i++) { + mpz_class xm = i; + Fp12::pow(e1, e, xm); + Fp12::powGeneric(e2, e, xm); + CYBOZU_TEST_EQUAL(e1, e2); + } + for (int i = 0; i < 10; i++) { + Fr x; + x.setRand(rg); + mpz_class xm = x.getMpz(); + Fp12::pow(e1, e, xm); + BN::param.glv2.pow(e2, e, xm); + CYBOZU_TEST_EQUAL(e1, e2); + } +} + +void testMillerLoop2(const G1& P1, const G2& Q1) +{ + Fp12 e1, e2, e3; + mpz_class c1("12342342423442"); + mpz_class c2("329428049820348209482"); + G2 Q2; + G1 P2; + G2::mul(Q2, Q1, c1); + G1::mul(P2, P1, c2); + pairing(e1, P1, Q1); + pairing(e2, P2, Q2); + e1 *= e2; + + std::vector Q1coeff, Q2coeff; + precomputeG2(Q1coeff, Q1); + precomputeG2(Q2coeff, Q2); + precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff); + precomputedMillerLoop2mixed(e3, P1, Q1, P2, Q2coeff); + CYBOZU_TEST_EQUAL(e2, e3); + finalExp(e2, e2); + CYBOZU_TEST_EQUAL(e1, e2); + + // special value + G2 Z; + Z.clear(); + Q2 += Q2; + precomputeG2(Q1coeff, Z); + precomputeG2(Q2coeff, Q2); + precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff); + precomputedMillerLoop2mixed(e3, P1, Z, P2, Q2coeff); + finalExp(e2, e2); + finalExp(e3, e3); + CYBOZU_TEST_EQUAL(e2, e3); +} + +void testPairing(const G1& P, const G2& Q, const char *eStr) +{ + Fp12 e1; + pairing(e1, P, Q); + Fp12 e2; + { + std::stringstream ss(eStr); + ss >> e2; + } + CYBOZU_TEST_EQUAL(e1, e2); + + Fp12 e = e1, ea; + G1 Pa; + G2 Qa; +#if defined(__EMSCRIPTEN__) || MCL_SIZEOF_UNIT == 4 + const int count = 100; +#else + const int count = 1000; +#endif + mpz_class a; + cybozu::XorShift rg; + for (int i = 0; i < count; i++) { + Fr r; + r.setRand(rg); + a = r.getMpz(); + Fp12::pow(ea, e, a); + G1::mul(Pa, P, a); + G2::mul(Qa, Q, a); + G1 T; + G1::mulCT(T, P, a); + CYBOZU_TEST_EQUAL(Pa, T); + pairing(e1, Pa, Q); + pairing(e2, P, Qa); + CYBOZU_TEST_EQUAL(ea, e1); + CYBOZU_TEST_EQUAL(ea, e2); + } +} + +void testTrivial(const G1& P, const G2& Q) +{ + G1 Z1; Z1.clear(); + G2 Z2; Z2.clear(); + Fp12 e; + pairing(e, Z1, Q); + CYBOZU_TEST_EQUAL(e, 1); + pairing(e, P, Z2); + CYBOZU_TEST_EQUAL(e, 1); + pairing(e, Z1, Z2); + CYBOZU_TEST_EQUAL(e, 1); + + std::vector Qcoeff; + precomputeG2(Qcoeff, Z2); + precomputedMillerLoop(e, P, Qcoeff); + finalExp(e, e); + CYBOZU_TEST_EQUAL(e, 1); + + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e, Z1, Qcoeff); + finalExp(e, e); + CYBOZU_TEST_EQUAL(e, 1); +} + +void testIoAll(const G1& P, const G2& Q) +{ + const int FpTbl[] = { 0, 2, 2|mcl::IoPrefix, 10, 16, 16|mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw }; + const int EcTbl[] = { mcl::IoEcAffine, mcl::IoEcProj, mcl::IoEcCompY, mcl::IoSerialize }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(FpTbl); i++) { + for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(EcTbl); j++) { + G1 P2 = P, P3; + G2 Q2 = Q, Q3; + int ioMode = FpTbl[i] | EcTbl[j]; + std::string s = P2.getStr(ioMode); + P3.setStr(s, ioMode); + CYBOZU_TEST_EQUAL(P2, P3); + s = Q2.getStr(ioMode); + Q3.setStr(s, ioMode); + CYBOZU_TEST_EQUAL(Q2, Q3); + s = P.x.getStr(ioMode); + Fp Px; + Px.setStr(s, ioMode); + CYBOZU_TEST_EQUAL(P.x, Px); + s = Q.x.getStr(ioMode); + Fp2 Qx; + Qx.setStr(s, ioMode); + CYBOZU_TEST_EQUAL(Q.x, Qx); + } + } +} + +void testIo(const G1& P, const G2& Q) +{ + testIoAll(P, Q); + G1 Z1; + G2 Z2; + Z1.clear(); + Z2.clear(); + testIoAll(Z1, Z2); +} + +#include "bench.hpp" + +CYBOZU_TEST_AUTO(naive) +{ + printf("mcl version=%03x\n", mcl::version); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(g_testSetTbl); i++) { + const TestSet& ts = g_testSetTbl[i]; + printf("i=%d curve=%s\n", int(i), ts.name); + initPairing(ts.cp, g_mode); + const G1 P(ts.g1.a, ts.g1.b); + const G2 Q(Fp2(ts.g2.aa, ts.g2.ab), Fp2(ts.g2.ba, ts.g2.bb)); +#ifdef ONLY_BENCH + { + Fp12 e; + for (int i = 0; i < 10000; i++) { clk.begin(); pairing(e, P, Q); clk.end(); } + } + clk.put(); + return; +#endif + testFp12pow(P, Q); + testIo(P, Q); + testTrivial(P, Q); + testSetStr(Q); + testMapToG1(); + testMapToG2(); + testCyclotomic(); + testCompress(P, Q); + testPairing(P, Q, ts.e); + testPrecomputed(P, Q); + testMillerLoop2(P, Q); + testBench(P, Q); + benchAddDblG1(); + benchAddDblG2(); + } + int count = (int)clk.getCount(); + if (count) { + printf("count=%d ", count); + clk.put(); + } +} + +int main(int argc, char *argv[]) + try +{ + cybozu::Option opt; + std::string mode; + opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)"); + if (!opt.parse(argc, argv)) { + opt.usage(); + return 1; + } + g_mode = mcl::fp::StrToMode(mode); + printf("JIT %d\n", mcl::fp::isEnableJIT()); + return cybozu::test::autoRun.run(argc, argv); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/conversion_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/conversion_test.cpp new file mode 100644 index 000000000..ec11fe900 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/conversion_test.cpp @@ -0,0 +1,96 @@ +#include +#include + +CYBOZU_TEST_AUTO(arrayToDec) +{ + const struct { + uint32_t x[5]; + size_t xn; + const char *s; + } tbl[] = { + { { 0, 0, 0, 0, 0 }, 1, "0" }, + { { 9, 0, 0, 0, 0 }, 1, "9" }, + { { 123456789, 0, 0, 0, 0 }, 1, "123456789" }, + { { 2147483647, 0, 0, 0, 0 }, 1, "2147483647" }, + { { 0xffffffff, 0, 0, 0, 0 }, 1, "4294967295" }, + { { 0x540be400, 0x2, 0, 0, 0 }, 2, "10000000000" }, + { { 0xffffffff, 0xffffffff, 0, 0, 0 }, 2, "18446744073709551615" }, + { { 0x89e80001, 0x8ac72304, 0, 0, 0 }, 2, "10000000000000000001" }, + { { 0xc582ca00, 0x8ac72304, 0, 0, 0 }, 2, "10000000001000000000" }, + { { 0, 0, 1, 0, 0 }, 3, "18446744073709551616" }, + { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0 }, 4, "340282366920938463463374607431768211455" }, + { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, 5, "1461501637330902918203684832716283019655932542975" }, + { { 0x3b9aca00, 0x5e3f3700, 0x1cbfa532, 0x04f6433a, 0xd83ff078 }, 5, "1234567901234560000000000000000000000001000000000" }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const size_t bufSize = 128; + char buf[bufSize] = {}; + const char *str = tbl[i].s; + const uint32_t *x = tbl[i].x; + const size_t strLen = strlen(str); + size_t n = mcl::fp::arrayToDec(buf, bufSize, x, tbl[i].xn); + CYBOZU_TEST_EQUAL(n, strLen); + CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n); + const size_t maxN = 32; + uint32_t xx[maxN] = {}; + size_t xn = mcl::fp::decToArray(xx, maxN, str, strLen); + CYBOZU_TEST_EQUAL(xn, tbl[i].xn); + CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn); + } + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const size_t bufSize = 128; + char buf[bufSize] = {}; + const char *str = tbl[i].s; + const size_t strLen = strlen(str); + uint64_t x[8] = {}; + size_t xn = (tbl[i].xn + 1) / 2; + memcpy(x, tbl[i].x, tbl[i].xn * sizeof(uint32_t)); + size_t n = mcl::fp::arrayToDec(buf, bufSize, x, xn); + CYBOZU_TEST_EQUAL(n, strLen); + CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n); + const size_t maxN = 32; + uint64_t xx[maxN] = {}; + size_t xxn = mcl::fp::decToArray(xx, maxN, str, strLen); + CYBOZU_TEST_EQUAL(xxn, xn); + CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn); + } +} + +CYBOZU_TEST_AUTO(writeHexStr) +{ + const char *hex1tbl = "0123456789abcdef"; + const char *hex2tbl = "0123456789ABCDEF"; + for (size_t i = 0; i < 16; i++) { + uint8_t v = 0xff; + CYBOZU_TEST_ASSERT(mcl::fp::local::hexCharToUint8(&v, hex1tbl[i])); + CYBOZU_TEST_EQUAL(v, i); + CYBOZU_TEST_ASSERT(mcl::fp::local::hexCharToUint8(&v, hex2tbl[i])); + CYBOZU_TEST_EQUAL(v, i); + } + const struct Tbl { + const char *bin; + size_t n; + const char *hex; + } tbl[] = { + { "", 0, "" }, + { "\x12\x34\xab", 3, "1234ab" }, + { "\xff\xfc\x00\x12", 4, "fffc0012" }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + char buf[32]; + cybozu::MemoryOutputStream os(buf, sizeof(buf)); + const char *bin = tbl[i].bin; + const char *hex = tbl[i].hex; + size_t n = tbl[i].n; + bool b; + mcl::fp::writeHexStr(&b, os, bin, n); + CYBOZU_TEST_ASSERT(b); + CYBOZU_TEST_EQUAL(os.getPos(), n * 2); + CYBOZU_TEST_EQUAL_ARRAY(buf, hex, n * 2); + + cybozu::MemoryInputStream is(hex, n * 2); + size_t w = mcl::fp::readHexStr(buf, n, is); + CYBOZU_TEST_EQUAL(w, n); + CYBOZU_TEST_EQUAL_ARRAY(buf, bin, n); + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/ec_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/ec_test.cpp new file mode 100644 index 000000000..ec49adbfe --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/ec_test.cpp @@ -0,0 +1,573 @@ +//#define MCL_EC_USE_AFFINE +#define PUT(x) std::cout << #x "=" << (x) << std::endl +#define CYBOZU_TEST_DISABLE_AUTO_RUN +#include +#include +#include + +#include +#include +#include +#include +#include + +typedef mcl::FpT<> Fp; +struct tagZn; +typedef mcl::FpT Zn; +typedef mcl::EcT Ec; + +CYBOZU_TEST_AUTO(sizeof) +{ + CYBOZU_TEST_EQUAL(sizeof(Fp), sizeof(mcl::fp::Unit) * Fp::maxSize); +#ifdef MCL_EC_USE_AFFINE + CYBOZU_TEST_EQUAL(sizeof(Ec), sizeof(Fp) * 2 + sizeof(mcl::fp::Unit)); +#else + CYBOZU_TEST_EQUAL(sizeof(Ec), sizeof(Fp) * 3); +#endif +} + +struct Test { + const mcl::EcParam& para; + Test(const mcl::EcParam& para, mcl::fp::Mode fpMode, mcl::ec::Mode ecMode) + : para(para) + { + printf("fpMode=%s\n", mcl::fp::ModeToStr(fpMode)); + Fp::init(para.p, fpMode); + Zn::init(para.n, fpMode); + Ec::init(para.a, para.b, ecMode); + } + void cstr() const + { + Ec O; + O.clear(); + CYBOZU_TEST_ASSERT(O.isZero()); + CYBOZU_TEST_ASSERT(O.isValid()); + Ec P; + P.clear(); + Ec::neg(P, O); + CYBOZU_TEST_EQUAL(P, O); + } + void pow2(Ec& Q, const Ec& P, int n) const + { + Q = P; + for (int i = 0; i < n; i++) { + Q += Q; + } + } + void pow2test(const Ec& P, int n) const + { + Ec Q, R; + pow2(Q, P, n); + Q -= P; // Q = (2^n - 1)P + Fp x = 1; + for (int i = 0; i < n; i++) { + x += x; + } + x -= 1; // x = 2^n - 1 + Ec::mul(R, P, x); + CYBOZU_TEST_EQUAL(Q, R); + Q = P; + Ec::mul(Q, Q, x); + CYBOZU_TEST_EQUAL(Q, R); + } + void ope() const + { + Fp x(para.gx); + Fp y(para.gy); + Zn n = 0; + CYBOZU_TEST_NO_EXCEPTION(Ec(x, y)); + CYBOZU_TEST_EXCEPTION(Ec(x, y + 1), cybozu::Exception); + Ec P(x, y), Q, R, O; + O.clear(); + CYBOZU_TEST_ASSERT(P.isNormalized()); + { + Ec::neg(Q, P); + CYBOZU_TEST_EQUAL(Q.x, P.x); + CYBOZU_TEST_EQUAL(Q.y, -P.y); + + R = P + Q; + CYBOZU_TEST_ASSERT(R.isZero()); + CYBOZU_TEST_ASSERT(R.isNormalized()); + CYBOZU_TEST_ASSERT(R.isValid()); + + R = P + O; + CYBOZU_TEST_EQUAL(R, P); + R = O + P; + CYBOZU_TEST_EQUAL(R, P); + } + + { + Ec::dbl(R, P); +#ifndef MCL_EC_USE_AFFINE + CYBOZU_TEST_ASSERT(!R.isNormalized()); +#endif + CYBOZU_TEST_ASSERT(R.isValid()); + Ec R2 = P + P; + CYBOZU_TEST_EQUAL(R, R2); + { + Ec P2 = P; + Ec::dbl(P2, P2); + CYBOZU_TEST_EQUAL(P2, R2); + } + Ec R3L = R2 + P; + Ec R3R = P + R2; + CYBOZU_TEST_EQUAL(R3L, R3R); + { + Ec RR = R2; + RR = RR + P; + CYBOZU_TEST_EQUAL(RR, R3L); + RR = R2; + RR = P + RR; + CYBOZU_TEST_EQUAL(RR, R3L); + RR = P; + RR = RR + RR; + CYBOZU_TEST_EQUAL(RR, R2); + } + Ec::mul(R, P, 2); + CYBOZU_TEST_EQUAL(R, R2); + Ec R4L = R3L + R2; + Ec R4R = R2 + R3L; + CYBOZU_TEST_EQUAL(R4L, R4R); + Ec::mul(R, P, 5); + CYBOZU_TEST_EQUAL(R, R4L); + } + { + R = P; + for (int i = 0; i < 10; i++) { + R += P; + } + Ec R2; + Ec::mul(R2, P, 11); + CYBOZU_TEST_EQUAL(R, R2); + } + Ec::mul(R, P, n - 1); + CYBOZU_TEST_EQUAL(R, -P); + R += P; // Ec::mul(R, P, n); + CYBOZU_TEST_ASSERT(R.isZero()); + { + const int tbl[] = { 1, 2, 63, 64, 65, 127, 128, 129 }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + pow2test(P, tbl[i]); + } + } + { + Ec::mul(Q, P, 0); + CYBOZU_TEST_ASSERT(Q.isZero()); + Q = P; + CYBOZU_TEST_ASSERT(!Q.isZero()); + Ec::mul(Q, Q, 0); + CYBOZU_TEST_ASSERT(Q.isZero()); + Ec::mul(Q, P, 1); + CYBOZU_TEST_EQUAL(P, Q); + } + { + Ec R2; + P += P; + Q += P; + CYBOZU_TEST_ASSERT(!P.z.isOne()); + CYBOZU_TEST_ASSERT(!Q.z.isOne()); + Ec::add(R2, P, Q); + + P.normalize(); + CYBOZU_TEST_ASSERT(P.z.isOne()); + CYBOZU_TEST_ASSERT(!Q.z.isOne()); + // affine + generic + Ec::add(R, P, Q); + CYBOZU_TEST_EQUAL(R, R2); + // generic + affine + Ec::add(R, Q, P); + CYBOZU_TEST_EQUAL(R, R2); + + Q.normalize(); + CYBOZU_TEST_ASSERT(P.z.isOne()); + CYBOZU_TEST_ASSERT(Q.z.isOne()); + // affine + affine + Ec::add(R, P, Q); + CYBOZU_TEST_EQUAL(R, R2); + + P += P; + CYBOZU_TEST_ASSERT(!P.z.isOne()); + // generic + Ec::dbl(R2, P); + + P.normalize(); + CYBOZU_TEST_ASSERT(P.z.isOne()); + // affine + Ec::dbl(R, P); + CYBOZU_TEST_EQUAL(R, R2); + } + } + + void mul() const + { + Fp x(para.gx); + Fp y(para.gy); + Ec P(x, y); + Ec Q; + Ec R; + R.clear(); + for (int i = 0; i < 100; i++) { + Ec::mul(Q, P, i); + CYBOZU_TEST_EQUAL(Q, R); + R += P; + } + } + + void neg_mul() const + { + Fp x(para.gx); + Fp y(para.gy); + Ec P(x, y); + Ec Q; + Ec R; + R.clear(); + for (int i = 0; i < 100; i++) { + Ec::mul(Q, P, -i); + CYBOZU_TEST_EQUAL(Q, R); + R -= P; + } + } + void squareRoot() const + { + Fp x(para.gx); + Fp y(para.gy); + bool odd = y.isOdd(); + Fp yy; + bool b = Ec::getYfromX(yy, x, odd); + CYBOZU_TEST_ASSERT(b); + CYBOZU_TEST_EQUAL(yy, y); + Fp::neg(y, y); + odd = y.isOdd(); + yy.clear(); + b = Ec::getYfromX(yy, x, odd); + CYBOZU_TEST_ASSERT(b); + CYBOZU_TEST_EQUAL(yy, y); + } + void mul_fp() const + { + Fp x(para.gx); + Fp y(para.gy); + Ec P(x, y); + Ec Q; + Ec R; + R.clear(); + for (int i = 0; i < 100; i++) { + Ec::mul(Q, P, Zn(i)); + CYBOZU_TEST_EQUAL(Q, R); + R += P; + } + } + void str() const + { + const Fp x(para.gx); + const Fp y(para.gy); + Ec P(x, y); + Ec Q; + // not compressed + Ec::setCompressedExpression(false); + { + std::stringstream ss; + ss << P; + ss >> Q; + CYBOZU_TEST_EQUAL(P, Q); + } + { + Q.clear(); + CYBOZU_TEST_EQUAL(Q.getStr(), "0"); + } + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + int base = i == 0 ? 10 : 16; + bool withPrefix = j == 0; + int ioMode = base | (withPrefix ? mcl::IoPrefix : 0); + std::string expected = "1 " + x.getStr(ioMode) + " " + y.getStr(ioMode); + CYBOZU_TEST_EQUAL(P.getStr(ioMode), expected); + std::ostringstream os; + if (base == 16) { + os << std::hex; + } + if (withPrefix) { + os << std::showbase; + } + os << P; + CYBOZU_TEST_EQUAL(os.str(), expected); + } + } + { + P = -P; + std::stringstream ss; + ss << P; + ss >> Q; + CYBOZU_TEST_EQUAL(P, Q); + } + P.clear(); + { + std::stringstream ss; + ss << P; + ss >> Q; + CYBOZU_TEST_EQUAL(P, Q); + } + CYBOZU_TEST_EXCEPTION(P.setStr("1 3 5"), cybozu::Exception); + // compressed + Ec::setCompressedExpression(true); + P.set(x, y); + { + std::stringstream ss; + ss << P; + ss >> Q; + CYBOZU_TEST_EQUAL(P, Q); + } + { + P = -P; + std::stringstream ss; + ss << P; + ss >> Q; + CYBOZU_TEST_EQUAL(P, Q); + } + P.clear(); + { + std::stringstream ss; + ss << P; + ss >> Q; + CYBOZU_TEST_EQUAL(P, Q); + } + // IoSerialize, IoSerializeHexStr + const size_t adj = Ec::isMSBserialize() ? 0 : 1; + P.set(x, y); + { + std::string s = P.getStr(mcl::IoSerialize); + CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize() + adj); + Q.setStr(s, mcl::IoSerialize); + CYBOZU_TEST_EQUAL(P, Q); + } + { + std::string s = P.getStr(mcl::IoSerializeHexStr); + CYBOZU_TEST_EQUAL(s.size(), (Fp::getByteSize() + adj) * 2); + Q.setStr(s, mcl::IoSerializeHexStr); + CYBOZU_TEST_EQUAL(P, Q); + } + P = -P; + { + std::string s = P.getStr(mcl::IoSerialize); + CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize() + adj); + Q.setStr(s, mcl::IoSerialize); + CYBOZU_TEST_EQUAL(P, Q); + } + { + std::string s = P.getStr(mcl::IoSerializeHexStr); + CYBOZU_TEST_EQUAL(s.size(), (Fp::getByteSize() + adj) * 2); + Q.setStr(s, mcl::IoSerializeHexStr); + CYBOZU_TEST_EQUAL(P, Q); + } + P.clear(); + { + std::string s = P.getStr(mcl::IoSerialize); + CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize() + adj); + CYBOZU_TEST_ASSERT(mcl::fp::isZeroArray(s.c_str(), s.size())); + Q.setStr(s, mcl::IoSerialize); + CYBOZU_TEST_EQUAL(P, Q); + } + { + std::string s = P.getStr(mcl::IoSerializeHexStr); + CYBOZU_TEST_EQUAL(s.size(), (Fp::getByteSize() + adj) * 2); + for (size_t i = 0; i < s.size(); i++) { + CYBOZU_TEST_EQUAL(s[i], '0'); + } + Q.setStr(s, mcl::IoSerializeHexStr); + CYBOZU_TEST_EQUAL(P, Q); + } + } + void ioMode() const + { + const Fp x(para.gx); + const Fp y(para.gy); + Ec P(x, y); + const mcl::IoMode tbl[] = { + mcl::IoBin, + mcl::IoDec, + mcl::IoHex, + mcl::IoArray, + mcl::IoArrayRaw, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Fp::setIoMode(tbl[i]); + { + std::stringstream ss; + ss << P; + Ec Q; + ss >> Q; + CYBOZU_TEST_EQUAL(P, Q); + } + { + std::stringstream ss; + Ec Q; + Q.clear(); + ss << Q; + Ec R; + ss >> R; + CYBOZU_TEST_EQUAL(Q, R); + } + } + Fp::setIoMode(mcl::IoAuto); + } + void mulCT() const + { + Fp x(para.gx); + Fp y(para.gy); + Ec P(x, y), Q1, Q2; + for (int i = 0; i < 100; i++) { + Zn r = i; + Ec::mul(Q1, P, r); + Ec::mulCT(Q2, P, r); + CYBOZU_TEST_EQUAL(Q1, Q2); + } + } + void compare() const + { + Fp x(para.gx); + Fp y(para.gy); + Ec P1(x, y); + Ec P2(x, -y); + int c = Ec::compare(P1, P2); + int cx = Fp::compare(y, -y); + CYBOZU_TEST_EQUAL(c, cx); + c = Ec::compare(P2, P1); + cx = Fp::compare(-y, y); + CYBOZU_TEST_EQUAL(c, cx); + CYBOZU_TEST_EQUAL(Ec::compare(P1, P1), 0); + bool b1, b2; + b1 = P1 <= P2; + b2 = y <= -y; + CYBOZU_TEST_EQUAL(b1, b2); + b1 = P1 < P2; + b2 = y < -y; + CYBOZU_TEST_EQUAL(b1, b2); + CYBOZU_TEST_ASSERT(!(P1 < P1)); + CYBOZU_TEST_ASSERT((P1 <= P1)); + } + + template + void test(F f, const char *msg) const + { + const int N = 300000; + Fp x(para.gx); + Fp y(para.gy); + Ec P(x, y); + Ec Q = P + P + P; + clock_t begin = clock(); + for (int i = 0; i < N; i++) { + f(Q, P, Q); + } + clock_t end = clock(); + printf("%s %.2fusec\n", msg, (end - begin) / double(CLOCKS_PER_SEC) / N * 1e6); + } +/* +Affine : sandy-bridge +add 3.17usec +sub 2.43usec +dbl 3.32usec +mul 905.00usec +Jacobi +add 2.34usec +sub 2.65usec +dbl 1.56usec +mul 499.00usec +*/ + void run() const + { + cstr(); + ope(); + mul(); + neg_mul(); + mul_fp(); + squareRoot(); + str(); + ioMode(); + mulCT(); + compare(); + } +private: + Test(const Test&); + void operator=(const Test&); +}; + +void test_sub_sub(const mcl::EcParam& para, mcl::fp::Mode fpMode) +{ + puts("Proj"); + Test(para, fpMode, mcl::ec::Proj).run(); + puts("Jacobi"); + Test(para, fpMode, mcl::ec::Jacobi).run(); +} + +void test_sub(const mcl::EcParam *para, size_t paraNum) +{ + for (size_t i = 0; i < paraNum; i++) { + puts(para[i].name); + test_sub_sub(para[i], mcl::fp::FP_GMP); +#ifdef MCL_USE_LLVM + test_sub_sub(para[i], mcl::fp::FP_LLVM); + test_sub_sub(para[i], mcl::fp::FP_LLVM_MONT); +#endif +#ifdef MCL_USE_XBYAK + test_sub_sub(para[i], mcl::fp::FP_XBYAK); +#endif + } +} + +int g_partial = -1; + +CYBOZU_TEST_AUTO(all) +{ + if (g_partial & (1 << 3)) { + const struct mcl::EcParam para3[] = { + // mcl::ecparam::p160_1, + mcl::ecparam::secp160k1, + mcl::ecparam::secp192k1, + mcl::ecparam::NIST_P192, + }; + test_sub(para3, CYBOZU_NUM_OF_ARRAY(para3)); + } + + if (g_partial & (1 << 4)) { + const struct mcl::EcParam para4[] = { + mcl::ecparam::secp224k1, + mcl::ecparam::secp256k1, + mcl::ecparam::NIST_P224, + mcl::ecparam::NIST_P256, + }; + test_sub(para4, CYBOZU_NUM_OF_ARRAY(para4)); + } + +#if MCL_MAX_BIT_SIZE >= 384 + if (g_partial & (1 << 6)) { + const struct mcl::EcParam para6[] = { + // mcl::ecparam::secp384r1, + mcl::ecparam::NIST_P384, + }; + test_sub(para6, CYBOZU_NUM_OF_ARRAY(para6)); + } +#endif + +#if MCL_MAX_BIT_SIZE >= 521 + if (g_partial & (1 << 9)) { + const struct mcl::EcParam para9[] = { + // mcl::ecparam::secp521r1, + mcl::ecparam::NIST_P521, + }; + test_sub(para9, CYBOZU_NUM_OF_ARRAY(para9)); + } +#endif +} + +int main(int argc, char *argv[]) +{ + if (argc == 1) { + g_partial = -1; + } else { + g_partial = 0; + for (int i = 1; i < argc; i++) { + g_partial |= 1 << atoi(argv[i]); + } + } + return cybozu::test::autoRun.run(argc, argv); +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/ecdsa_c_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_c_test.cpp new file mode 100644 index 000000000..e0af38182 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_c_test.cpp @@ -0,0 +1,51 @@ +#include +#include +#include + +template +void serializeTest(const T& x, const Serializer& serialize, const Deserializer& deserialize) +{ + char buf[128]; + size_t n = serialize(buf, sizeof(buf), &x); + CYBOZU_TEST_ASSERT(n > 0); + T y; + size_t m = deserialize(&y, buf, n); + CYBOZU_TEST_EQUAL(m, n); + CYBOZU_TEST_ASSERT(memcmp(&x, &y, n) == 0); +} + +CYBOZU_TEST_AUTO(ecdsa) +{ + int ret; + ret = ecdsaInit(); + CYBOZU_TEST_EQUAL(ret, 0); + ecdsaSecretKey sec; + ecdsaPublicKey pub; + ecdsaPrecomputedPublicKey *ppub; + ecdsaSignature sig; + const char *msg = "hello"; + mclSize msgSize = strlen(msg); + + ret = ecdsaSecretKeySetByCSPRNG(&sec); + CYBOZU_TEST_EQUAL(ret, 0); + serializeTest(sec, ecdsaSecretKeySerialize, ecdsaSecretKeyDeserialize); + + ecdsaGetPublicKey(&pub, &sec); + serializeTest(pub, ecdsaPublicKeySerialize, ecdsaPublicKeyDeserialize); + ecdsaSign(&sig, &sec, msg, msgSize); + serializeTest(sig, ecdsaSignatureSerialize, ecdsaSignatureDeserialize); + CYBOZU_TEST_ASSERT(ecdsaVerify(&sig, &pub, msg, msgSize)); + + ppub = ecdsaPrecomputedPublicKeyCreate(); + CYBOZU_TEST_ASSERT(ppub); + ret = ecdsaPrecomputedPublicKeyInit(ppub, &pub); + CYBOZU_TEST_EQUAL(ret, 0); + + CYBOZU_TEST_ASSERT(ecdsaVerifyPrecomputed(&sig, ppub, msg, msgSize)); + + sig.d[0]++; + CYBOZU_TEST_ASSERT(!ecdsaVerify(&sig, &pub, msg, msgSize)); + CYBOZU_TEST_ASSERT(!ecdsaVerifyPrecomputed(&sig, ppub, msg, msgSize)); + + ecdsaPrecomputedPublicKeyDestroy(ppub); +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/ecdsa_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_test.cpp new file mode 100644 index 000000000..332c9ee27 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_test.cpp @@ -0,0 +1,69 @@ +#define PUT(x) std::cout << #x "=" << x << std::endl; +#include +#include +void put(const void *buf, size_t bufSize) +{ + const unsigned char* p = (const unsigned char*)buf; + for (size_t i = 0; i < bufSize; i++) { + printf("%02x", p[i]); + } + printf("\n"); +} +#include +#include +#include + +using namespace mcl::ecdsa; + +CYBOZU_TEST_AUTO(ecdsa) +{ + init(); + SecretKey sec; + PublicKey pub; + sec.setByCSPRNG(); + getPublicKey(pub, sec); + Signature sig; + const std::string msg = "hello"; + sign(sig, sec, msg.c_str(), msg.size()); + CYBOZU_TEST_ASSERT(verify(sig, pub, msg.c_str(), msg.size())); + sig.s += 1; + CYBOZU_TEST_ASSERT(!verify(sig, pub, msg.c_str(), msg.size())); +} + +CYBOZU_TEST_AUTO(value) +{ + const std::string msg = "hello"; + const char *secStr = "83ecb3984a4f9ff03e84d5f9c0d7f888a81833643047acc58eb6431e01d9bac8"; + const char *pubxStr = "653bd02ba1367e5d4cd695b6f857d1cd90d4d8d42bc155d85377b7d2d0ed2e71"; + const char *pubyStr = "04e8f5da403ab78decec1f19e2396739ea544e2b14159beb5091b30b418b813a"; + const char *sigStr = "a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5de5d79a2ba44e311d04fdca263639283965780bce9169822be9cc81756e95a24"; + + SecretKey sec; + sec.setStr(secStr, 16); + CYBOZU_TEST_EQUAL(sec.getStr(16), secStr); + PublicKey pub; + getPublicKey(pub, sec); + pub.normalize(); + Ec t(Fp(pubxStr, 16), Fp(pubyStr, 16)); + CYBOZU_TEST_EQUAL(pub, t); + Signature sig; + sig.r.setStr(std::string(sigStr, 64), 16); + sig.s.setStr(std::string(sigStr + 64, 64), 16); + PUT(sig); + CYBOZU_TEST_ASSERT(verify(sig, pub, msg.c_str(), msg.size())); +} + +CYBOZU_TEST_AUTO(bench) +{ + const std::string msg = "hello"; + SecretKey sec; + PublicKey pub; + PrecomputedPublicKey ppub; + sec.setByCSPRNG(); + getPublicKey(pub, sec); + ppub.init(pub); + Signature sig; + CYBOZU_BENCH_C("sign", 1000, sign, sig, sec, msg.c_str(), msg.size()); + CYBOZU_BENCH_C("pub.verify ", 1000, verify, sig, pub, msg.c_str(), msg.size()); + CYBOZU_BENCH_C("ppub.verify", 1000, verify, sig, ppub, msg.c_str(), msg.size()); +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/elgamal_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/elgamal_test.cpp new file mode 100644 index 000000000..9532fc597 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/elgamal_test.cpp @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include + +struct TagZn; +typedef mcl::FpT<> Fp; +typedef mcl::FpT Zn; +typedef mcl::EcT Ec; +typedef mcl::ElgamalT ElgamalEc; + +const mcl::EcParam& para = mcl::ecparam::secp192k1; +cybozu::RandomGenerator rg; + +CYBOZU_TEST_AUTO(testEc) +{ + Fp::init(para.p); + Zn::init(para.n); + Ec::init(para.a, para.b); + const Fp x0(para.gx); + const Fp y0(para.gy); + const size_t bitSize = Zn::getBitSize(); + const Ec P(x0, y0); + /* + Zn =

+ */ + ElgamalEc::PrivateKey prv; + prv.init(P, bitSize, rg); + prv.setCache(0, 60000); + const ElgamalEc::PublicKey& pub = prv.getPublicKey(); + + const int m1 = 12345; + const int m2 = 17655; + ElgamalEc::CipherText c1, c2; + pub.enc(c1, m1, rg); + pub.enc(c2, m2, rg); + Zn dec1, dec2; + prv.dec(dec1, c1); + prv.dec(dec2, c2); + // dec(enc) = id + CYBOZU_TEST_EQUAL(dec1, m1); + CYBOZU_TEST_EQUAL(dec2, m2); + CYBOZU_TEST_EQUAL(prv.dec(c1), m1); + CYBOZU_TEST_EQUAL(prv.dec(c2), m2); + // iostream + { + ElgamalEc::PublicKey pub2; + ElgamalEc::PrivateKey prv2; + ElgamalEc::CipherText cc1, cc2; + { + std::stringstream ss; + ss << prv; + ss >> prv2; + } + Zn d; + prv2.dec(d, c1); + CYBOZU_TEST_EQUAL(d, m1); + { + std::stringstream ss; + ss << c1; + ss >> cc1; + } + d = 0; + prv2.dec(d, cc1); + CYBOZU_TEST_EQUAL(d, m1); + { + std::stringstream ss; + ss << pub; + ss >> pub2; + } + pub2.enc(cc2, m2, rg); + prv.dec(d, cc2); + CYBOZU_TEST_EQUAL(d, m2); + } + // enc(m1) enc(m2) = enc(m1 + m2) + c1.add(c2); + prv.dec(dec1, c1); + CYBOZU_TEST_EQUAL(dec1, m1 + m2); + // enc(m1) x = enc(m1 + x) + { + const int x = 555; + pub.add(c1, x); + prv.dec(dec1, c1); + CYBOZU_TEST_EQUAL(dec1, m1 + m2 + x); + } + // rerandomize + c1 = c2; + pub.rerandomize(c1, rg); + // verify c1 != c2 + CYBOZU_TEST_ASSERT(c1.c1 != c2.c1); + CYBOZU_TEST_ASSERT(c1.c2 != c2.c2); + prv.dec(dec1, c1); + // dec(c1) = dec(c2) + CYBOZU_TEST_EQUAL(dec1, m2); + + // check neg + { + ElgamalEc::CipherText c; + Zn m = 1234; + pub.enc(c, m, rg); + c.neg(); + Zn dec; + prv.dec(dec, c); + CYBOZU_TEST_EQUAL(dec, -m); + } + // check mul + { + ElgamalEc::CipherText c; + Zn m = 123; + int x = 111; + pub.enc(c, m, rg); + Zn dec; + prv.dec(dec, c); + c.mul(x); + prv.dec(dec, c); + m *= x; + CYBOZU_TEST_EQUAL(dec, m); + } + + // check negative value + for (int i = -10; i < 10; i++) { + ElgamalEc::CipherText c; + const Zn mm = i; + pub.enc(c, mm, rg); + Zn dec; + prv.dec(dec, c, 1000); + CYBOZU_TEST_EQUAL(dec, mm); + } + + // isZeroMessage + for (int m = 0; m < 10; m++) { + ElgamalEc::CipherText c0; + pub.enc(c0, m, rg); + if (m == 0) { + CYBOZU_TEST_ASSERT(prv.isZeroMessage(c0)); + } else { + CYBOZU_TEST_ASSERT(!prv.isZeroMessage(c0)); + } + } + // zkp + { + ElgamalEc::Zkp zkp; + ElgamalEc::CipherText c; + pub.encWithZkp(c, zkp, 0, rg); + CYBOZU_TEST_ASSERT(pub.verify(c, zkp)); + zkp.s0 += 1; + CYBOZU_TEST_ASSERT(!pub.verify(c, zkp)); + pub.encWithZkp(c, zkp, 1, rg); + CYBOZU_TEST_ASSERT(pub.verify(c, zkp)); + zkp.s0 += 1; + CYBOZU_TEST_ASSERT(!pub.verify(c, zkp)); + CYBOZU_TEST_EXCEPTION_MESSAGE(pub.encWithZkp(c, zkp, 2, rg), cybozu::Exception, "encWithZkp"); + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/fp_generator_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_generator_test.cpp new file mode 100644 index 000000000..60ec5cd41 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/fp_generator_test.cpp @@ -0,0 +1,207 @@ +#include +#if MCL_SIZEOF_UNIT == 4 +// not support +#else +#include +#include +#include +#include +#include +#include "../src/fp_generator.hpp" +#include +#include +#include + +typedef mcl::FpT<> Fp; + +const int MAX_N = 4; + +const char *primeTable[] = { + "0x7fffffffffffffffffffffffffffffff", // 127bit(not full) + "0xffffffffffffffffffffffffffffff61", // 128bit(full) + "0xfffffffffffffffffffffffffffffffffffffffeffffee37", // 192bit(full) + "0x2523648240000001ba344d80000000086121000000000013a700000000000013", // 254bit(not full) +}; + +void strToArray(uint64_t *p, size_t n, const char *pStr) +{ + mpz_class x; + mcl::gmp::setStr(x, pStr, 16); + mcl::gmp::getArray(p, n, x); +} + +struct Int { + int vn; + uint64_t v[MAX_N]; + Int() + : vn(0) + { + } + explicit Int(int vn) + { + if (vn > MAX_N) { + printf("vn(%d) is too large\n", vn); + exit(1); + } + this->vn = vn; + } + void set(const char *str) { setStr(str); } + void set(const Fp& rhs) + { + mcl::gmp::getArray(v, MAX_N, rhs.getMpz()); + } + void set(const uint64_t* x) + { + for (int i = 0; i < vn; i++) v[i] = x[i]; + } + void setStr(const char *str) + { + strToArray(v, MAX_N, str); + } + std::string getStr() const + { + std::string ret; + for (int i = 0; i < vn; i++) { + ret += cybozu::itohex(v[vn - 1 - i], false); + } + return ret; + } + void put(const char *msg = "") const + { + if (msg) printf("%s=", msg); + printf("%s\n", getStr().c_str()); + } + bool operator==(const Int& rhs) const + { + if (vn != rhs.vn) return false; + for (int i = 0; i < vn; i++) { + if (v[i] != rhs.v[i]) return false; + } + return true; + } + bool operator!=(const Int& rhs) const { return !operator==(rhs); } + bool operator==(const Fp& rhs) const + { + Int t(vn); + t.set(rhs); + return operator==(t); + } + bool operator!=(const Fp& rhs) const { return !operator==(rhs); } +}; +static inline std::ostream& operator<<(std::ostream& os, const Int& x) +{ + return os << x.getStr(); +} + +void testAddSub(const mcl::fp::Op& op) +{ + Fp x, y; + const uint64_t *p = op.p; + Int mx(op.N), my(op.N); + x.setStr("0x8811aabb23427cc"); + y.setStr("0x8811aabb23427cc11"); + mx.set(x); + my.set(y); + for (int i = 0; i < 30; i++) { + CYBOZU_TEST_EQUAL(mx, x); + x += x; + op.fp_add(mx.v, mx.v, mx.v, p); + } + for (int i = 0; i < 30; i++) { + CYBOZU_TEST_EQUAL(mx, x); + x += y; + op.fp_add(mx.v, mx.v, my.v, p); + } + for (int i = 0; i < 30; i++) { + CYBOZU_TEST_EQUAL(my, y); + y -= x; + op.fp_sub(my.v, my.v, mx.v, p); + } +} + +void testNeg(const mcl::fp::Op& op) +{ + Fp x; + Int mx(op.N), my(op.N); + const char *tbl[] = { + "0", + "0x12346", + "0x11223344556677881122334455667788", + "0x0abbccddeeffaabb0000000000000000", + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + x.setStr(tbl[i]); + mx.set(x); + x = -x; + op.fp_neg(mx.v, mx.v, op.p); + CYBOZU_TEST_EQUAL(mx, x); + } +} + +#if 0 +void testMulI(const mcl::fp::FpGenerator& fg, int pn) +{ + cybozu::XorShift rg; +//printf("pn=%d, %p\n", pn, fg.mulUnit_); + for (int i = 0; i < 100; i++) { + uint64_t x[MAX_N]; + uint64_t z[MAX_N + 1]; + rg.read(x, pn); + uint64_t y = rg.get64(); + mpz_class mx; + mcl::gmp::setArray(mx, x, pn); + mpz_class my; + mcl::gmp::set(my, y); + mx *= my; + uint64_t d = fg.mulUnit_(z, x, y); + z[pn] = d; + mcl::gmp::setArray(my, z, pn + 1); + CYBOZU_TEST_EQUAL(mx, my); + } + { + uint64_t x[MAX_N]; + uint64_t z[MAX_N + 1]; + rg.read(x, pn); + uint64_t y = rg.get64(); + CYBOZU_BENCH_C("mulUnit", 10000000, fg.mulUnit_, z, x, y); + } +} +#endif + +void testShr1(const mcl::fp::Op& op, int pn) +{ + cybozu::XorShift rg; + for (int i = 0; i < 100; i++) { + uint64_t x[MAX_N]; + uint64_t z[MAX_N]; + rg.read(x, pn); + mpz_class mx; + mcl::gmp::setArray(mx, x, pn); + mx >>= 1; + op.fp_shr1(z, x); + mpz_class my; + mcl::gmp::setArray(my, z, pn); + CYBOZU_TEST_EQUAL(mx, my); + } +} + +void test(const char *pStr) +{ + printf("test %s\n", pStr); + Fp::init(pStr, mcl::fp::FP_XBYAK); + const mcl::fp::Op& op = Fp::getOp(); + const int pn = (int)op.N; + testAddSub(op); + testNeg(op); +// testMulI(*op.fg, pn); + testShr1(op, pn); +} + +CYBOZU_TEST_AUTO(all) +{ + if (!mcl::fp::isEnableJIT()) return; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(primeTable); i++) { + test(primeTable[i]); + } +} +#endif diff --git a/vendor/github.com/dexon-foundation/mcl/test/fp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_test.cpp new file mode 100644 index 000000000..dc1b01ef4 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/fp_test.cpp @@ -0,0 +1,1046 @@ +#define PUT(x) std::cout << #x "=" << (x) << std::endl +#define CYBOZU_TEST_DISABLE_AUTO_RUN +#include +#include +#include "../src/low_func.hpp" +#include "../src/proto.hpp" +#include +#include +#include +#include + +#ifdef _MSC_VER + #pragma warning(disable: 4127) // const condition +#endif + +typedef mcl::FpT<> Fp; + +CYBOZU_TEST_AUTO(sizeof) +{ + CYBOZU_TEST_EQUAL(sizeof(Fp), sizeof(mcl::fp::Unit) * Fp::maxSize); +} + +void cstrTest() +{ + const struct { + const char *str; + int val; + } tbl[] = { + { "0", 0 }, + { "1", 1 }, + { "123", 123 }, + { "0x123", 0x123 }, + { "0b10101", 21 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + // string cstr + Fp x(tbl[i].str); + CYBOZU_TEST_EQUAL(x, tbl[i].val); + + // int cstr + Fp y(tbl[i].val); + CYBOZU_TEST_EQUAL(y, x); + + // copy cstr + Fp z(x); + CYBOZU_TEST_EQUAL(z, x); + + // assign int + Fp w; + w = tbl[i].val; + CYBOZU_TEST_EQUAL(w, x); + + // assign self + Fp u; + u = w; + CYBOZU_TEST_EQUAL(u, x); + + // conv + std::ostringstream os; + os << tbl[i].val; + + std::string str; + x.getStr(str); + CYBOZU_TEST_EQUAL(str, os.str()); + } + const struct { + const char *str; + int val; + } tbl2[] = { + { "-123", 123 }, + { "-0x123", 0x123 }, + { "-0b10101", 21 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl2); i++) { + Fp x(tbl2[i].str); + x = -x; + CYBOZU_TEST_EQUAL(x, tbl2[i].val); + } +} + +void setStrTest() +{ + const struct { + const char *in; + int out; + int base; + } tbl[] = { + { "100", 100, 0 }, // set base = 10 if base = 0 + { "100", 4, 2 }, + { "100", 256, 16 }, + { "0b100", 4, 0 }, + { "0b100", 4, 2 }, + { "0x100", 256, 0 }, + { "0x100", 256, 16 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Fp x; + x.setStr(tbl[i].in, tbl[i].base); + CYBOZU_TEST_EQUAL(x, tbl[i].out); + } + // use prefix if base conflicts with prefix + { + Fp x; + CYBOZU_TEST_EXCEPTION(x.setStr("0b100", 16), cybozu::Exception); + CYBOZU_TEST_EXCEPTION(x.setStr("0b100", 10), cybozu::Exception); + CYBOZU_TEST_EXCEPTION(x.setStr("0x100", 2), cybozu::Exception); + CYBOZU_TEST_EXCEPTION(x.setStr("0x100", 10), cybozu::Exception); + } +} + +void streamTest() +{ + const struct { + const char *in; + int out10; + int out16; + } tbl[] = { + { "100", 100, 256 }, // set base = 10 if base = 0 + { "0x100", 256, 256 }, + }; + Fp::setIoMode(0); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + { + std::istringstream is(tbl[i].in); + Fp x; + is >> x; + CYBOZU_TEST_EQUAL(x, tbl[i].out10); + } + { + std::istringstream is(tbl[i].in); + Fp x; + is >> std::hex >> x; + CYBOZU_TEST_EQUAL(x, tbl[i].out16); + } + } + // use prefix if base conflicts with prefix + std::istringstream is("0b100"); + Fp x; + CYBOZU_TEST_EXCEPTION(is >> std::hex >> x, cybozu::Exception); + { + std::ostringstream os; + os << Fp(123); + CYBOZU_TEST_EQUAL(os.str(), "123"); + } + { + std::ostringstream os; + os << std::hex << Fp(0x123); + CYBOZU_TEST_EQUAL(os.str(), "123"); + } + { + std::ostringstream os; + os << std::hex << std::showbase << Fp(0x123); + CYBOZU_TEST_EQUAL(os.str(), "0x123"); + } +} + +void ioModeTest() +{ + Fp x(123); + const struct { + mcl::IoMode ioMode; + std::string expected; + } tbl[] = { + { mcl::IoBin, "1111011" }, + { mcl::IoDec, "123" }, + { mcl::IoHex, "7b" }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Fp::setIoMode(tbl[i].ioMode); + for (int j = 0; j < 2; j++) { + std::stringstream ss; + if (j == 1) { + ss << std::hex; + } + ss << x; + CYBOZU_TEST_EQUAL(ss.str(), tbl[i].expected); + Fp y; + y.clear(); + ss >> y; + CYBOZU_TEST_EQUAL(x, y); + } + } + for (int i = 0; i < 2; i++) { + if (i == 0) { + Fp::setIoMode(mcl::IoArray); + } else { + Fp::setIoMode(mcl::IoArrayRaw); + } + std::stringstream ss; + ss << x; + CYBOZU_TEST_EQUAL(ss.str().size(), Fp::getByteSize()); + Fp y; + ss >> y; + CYBOZU_TEST_EQUAL(x, y); + } + Fp::setIoMode(mcl::IoAuto); +} + +void edgeTest() +{ + const mpz_class& m = Fp::getOp().mp; + /* + real mont + 0 0 + 1 R^-1 + R 1 + -1 -R^-1 + -R -1 + */ + mpz_class t = 1; + const size_t N = Fp::getUnitSize(); + const mpz_class R = (t << (N * mcl::fp::UnitBitSize)) % m; + const mpz_class tbl[] = { + 0, 1, R, m - 1, m - R + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const mpz_class& x = tbl[i]; + for (size_t j = i; j < CYBOZU_NUM_OF_ARRAY(tbl); j++) { + const mpz_class& y = tbl[j]; + mpz_class z = (x * y) % m; + Fp xx, yy; + xx.setMpz(x); + yy.setMpz(y); + Fp zz = xx * yy; + zz.getMpz(t); + CYBOZU_TEST_EQUAL(z, t); + } + } + t = m; + t /= 2; + Fp x; + x.setMpz(t); + CYBOZU_TEST_EQUAL(x * 2, -1); + t += 1; + x.setMpz(t); + CYBOZU_TEST_EQUAL(x * 2, 1); +} + +void convTest() +{ +#if 1 + const char *bin, *hex, *dec; + if (Fp::getBitSize() <= 117) { + bin = "0b1000000000000000000000000000000000000000000000000000000000001110"; + hex = "0x800000000000000e"; + dec = "9223372036854775822"; + } else { + bin = "0b100100011010001010110011110001001000000010010001101000101011001111000100100000001001000110100010101100111100010010000"; + hex = "0x123456789012345678901234567890"; + dec = "94522879687365475552814062743484560"; + } +#else + const char *bin = "0b1001000110100"; + const char *hex = "0x1234"; + const char *dec = "4660"; +#endif + Fp b(bin); + Fp h(hex); + Fp d(dec); + CYBOZU_TEST_EQUAL(b, h); + CYBOZU_TEST_EQUAL(b, d); + + std::string str; + b.getStr(str, mcl::IoBinPrefix); + CYBOZU_TEST_EQUAL(str, bin); + b.getStr(str); + CYBOZU_TEST_EQUAL(str, dec); + b.getStr(str, mcl::IoHexPrefix); + CYBOZU_TEST_EQUAL(str, hex); +} + +void compareTest() +{ + { + const struct { + int lhs; + int rhs; + int cmp; + } tbl[] = { + { 0, 0, 0 }, + { 1, 0, 1 }, + { 0, 1, -1 }, + { -1, 0, 1 }, // m-1, 0 + { 0, -1, -1 }, // 0, m-1 + { 123, 456, -1 }, + { 456, 123, 1 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const Fp x(tbl[i].lhs); + const Fp y(tbl[i].rhs); + const int cmp = tbl[i].cmp; + if (cmp == 0) { + CYBOZU_TEST_EQUAL(x, y); + CYBOZU_TEST_ASSERT(x >= y); + CYBOZU_TEST_ASSERT(x <= y); + } else if (cmp > 0) { + CYBOZU_TEST_ASSERT(x > y); + CYBOZU_TEST_ASSERT(x >= y); + } else { + CYBOZU_TEST_ASSERT(x < y); + CYBOZU_TEST_ASSERT(x <= y); + } + } + } + { + Fp x(5); + CYBOZU_TEST_ASSERT(x < 10); + CYBOZU_TEST_ASSERT(x == 5); + CYBOZU_TEST_ASSERT(x > 2); + } + { + Fp x(1); + CYBOZU_TEST_ASSERT(x.isOne()); + x = 2; + CYBOZU_TEST_ASSERT(!x.isOne()); + } + { + const struct { + int v; + bool expected; + } tbl[] = { + { 0, false }, + { 1, false }, + { -1, true }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Fp x = tbl[i].v; + CYBOZU_TEST_EQUAL(x.isNegative(), tbl[i].expected); + } + std::string str; + Fp::getModulo(str); + char buf[1024]; + size_t n = Fp::getModulo(buf, sizeof(buf)); + CYBOZU_TEST_EQUAL(n, str.size()); + CYBOZU_TEST_EQUAL(buf, str.c_str()); + mpz_class half(str); + half = (half - 1) / 2; + Fp x; + x.setMpz(half - 1); + CYBOZU_TEST_ASSERT(!x.isNegative()); + x.setMpz(half); + CYBOZU_TEST_ASSERT(!x.isNegative()); + x.setMpz(half + 1); + CYBOZU_TEST_ASSERT(x.isNegative()); + } +} + +void moduloTest(const char *pStr) +{ + std::string str; + Fp::getModulo(str); + CYBOZU_TEST_EQUAL(str, mcl::gmp::getStr(mpz_class(pStr))); +} + +void opeTest() +{ + const struct { + int x; + int y; + int add; // x + y + int sub; // x - y + int mul; // x * y + int sqr; // x^2 + } tbl[] = { + { 0, 1, 1, -1, 0, 0 }, + { 9, 5, 14, 4, 45, 81 }, + { 10, 13, 23, -3, 130, 100 }, + { 2000, 1000, 3000, 1000, 2000 * 1000, 2000 * 2000 }, + { 12345, 9999, 12345 + 9999, 12345 - 9999, 12345 * 9999, 12345 * 12345 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const Fp x(tbl[i].x); + const Fp y(tbl[i].y); + Fp z; + Fp::add(z, x, y); + CYBOZU_TEST_EQUAL(z, tbl[i].add); + Fp::sub(z, x, y); + CYBOZU_TEST_EQUAL(z, tbl[i].sub); + Fp::mul(z, x, y); + CYBOZU_TEST_EQUAL(z, tbl[i].mul); + + Fp r; + Fp::inv(r, y); + Fp::mul(z, z, r); + CYBOZU_TEST_EQUAL(z, tbl[i].x); + z = x + y; + CYBOZU_TEST_EQUAL(z, tbl[i].add); + z = x - y; + CYBOZU_TEST_EQUAL(z, tbl[i].sub); + z = x * y; + CYBOZU_TEST_EQUAL(z, tbl[i].mul); + + Fp::sqr(z, x); + CYBOZU_TEST_EQUAL(z, tbl[i].sqr); + + z = x / y; + z *= y; + CYBOZU_TEST_EQUAL(z, tbl[i].x); + } + if (!Fp::isFullBit()) { + Fp x(5), y(3), z; + Fp::addPre(z, x, y); + if (Fp::compareRaw(z, Fp::getP()) >= 0) { + Fp::subPre(z, z, Fp::getP()); + } + CYBOZU_TEST_EQUAL(z, Fp(8)); + if (Fp::compareRaw(x, y) < 0) { + Fp::addPre(x, x, Fp::getP()); + } + Fp::subPre(x, x, y); + CYBOZU_TEST_EQUAL(x, Fp(2)); + } +} + +struct tag2; + +void powTest() +{ + Fp x, y, z; + x = 12345; + z = 1; + for (int i = 0; i < 100; i++) { + Fp::pow(y, x, i); + CYBOZU_TEST_EQUAL(y, z); + z *= x; + } + x = z; + Fp::pow(z, x, Fp::getOp().mp - 1); + CYBOZU_TEST_EQUAL(z, 1); + Fp::pow(z, x, Fp::getOp().mp); + CYBOZU_TEST_EQUAL(z, x); + typedef mcl::FpT Fp_other; + Fp_other::init("1009"); + x = 5; + Fp_other n = 3; + z = 3; + Fp::pow(x, x, z); + CYBOZU_TEST_EQUAL(x, 125); + x = 5; + Fp::pow(x, x, n); + CYBOZU_TEST_EQUAL(x, 125); +} + +void mulUnitTest() +{ + Fp x(-1), y, z; + for (unsigned int u = 0; u < 20; u++) { + Fp::mul(y, x, u); + Fp::mulUnit(z, x, u); + CYBOZU_TEST_EQUAL(y, z); + } +} + +void powNegTest() +{ + Fp x, y, z; + x = 12345; + z = 1; + Fp rx = 1 / x; + for (int i = 0; i < 100; i++) { + Fp::pow(y, x, -i); + CYBOZU_TEST_EQUAL(y, z); + z *= rx; + } +} + +void powFpTest() +{ + Fp x, y, z; + x = 12345; + z = 1; + for (int i = 0; i < 100; i++) { + Fp::pow(y, x, Fp(i)); + CYBOZU_TEST_EQUAL(y, z); + z *= x; + } +} + +void powGmp() +{ + Fp x, y, z; + x = 12345; + z = 1; + for (int i = 0; i < 100; i++) { + Fp::pow(y, x, mpz_class(i)); + CYBOZU_TEST_EQUAL(y, z); + z *= x; + } +} + +struct TagAnother; + +void anotherFpTest(mcl::fp::Mode mode) +{ + typedef mcl::FpT G; + G::init("13", mode); + G a = 3; + G b = 9; + a *= b; + CYBOZU_TEST_EQUAL(a, 1); +} + +void setArrayTest1() +{ + char b1[] = { 0x56, 0x34, 0x12 }; + Fp x; + x.setArray(b1, 3); + CYBOZU_TEST_EQUAL(x, 0x123456); + int b2[] = { 0x12, 0x34 }; + x.setArray(b2, 2); + CYBOZU_TEST_EQUAL(x, Fp("0x3400000012")); +} + +void setArrayTest2(mcl::fp::Mode mode) +{ + Fp::init("0x10000000000001234567a5", mode); + const struct { + uint32_t buf[3]; + size_t bufN; + const char *expected; + } tbl[] = { + { { 0x234567a4, 0x00000001, 0x00100000}, 1, "0x234567a4" }, + { { 0x234567a4, 0x00000001, 0x00100000}, 2, "0x1234567a4" }, + { { 0x234567a4, 0x00000001, 0x00080000}, 3, "0x08000000000001234567a4" }, + { { 0x234567a4, 0x00000001, 0x00100000}, 3, "0x10000000000001234567a4" }, + }; + Fp x; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + x.setArray(tbl[i].buf, tbl[i].bufN); + CYBOZU_TEST_EQUAL(x, Fp(tbl[i].expected)); + } + uint32_t large[3] = { 0x234567a5, 0x00000001, 0x00100000}; + CYBOZU_TEST_EXCEPTION(x.setArray(large, 3), cybozu::Exception); +} + +void setArrayMaskTest1() +{ + char b1[] = { 0x56, 0x34, 0x12 }; + Fp x; + x.setArrayMask(b1, 3); + CYBOZU_TEST_EQUAL(x, 0x123456); + int b2[] = { 0x12, 0x34 }; + x.setArrayMask(b2, 2); + CYBOZU_TEST_EQUAL(x, Fp("0x3400000012")); +} + +void setArrayMaskTest2(mcl::fp::Mode mode) +{ + Fp::init("0x10000000000001234567a5", mode); + const struct { + uint32_t buf[3]; + size_t bufN; + const char *expected; + } tbl[] = { + { { 0x234567a4, 0x00000001, 0x00100000}, 1, "0x234567a4" }, + { { 0x234567a4, 0x00000001, 0x00100000}, 2, "0x1234567a4" }, + { { 0x234567a4, 0x00000001, 0x00100000}, 3, "0x10000000000001234567a4" }, + { { 0x234567a5, 0xfffffff1, 0xffffffff}, 3, "0x0ffffffffffff1234567a5" }, + }; + Fp x; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + x.setArrayMask(tbl[i].buf, tbl[i].bufN); + CYBOZU_TEST_EQUAL(x, Fp(tbl[i].expected)); + } +} + +void setArrayModTest() +{ + const mpz_class& p = Fp::getOp().mp; + const mpz_class tbl[] = { + 0, + 1, + p - 1, + p, + p + 1, + p * 2 - 1, + p * 2, + p * 2 + 1, + p * (p - 1) - 1, + p * (p - 1), + p * (p - 1) + 1, + p * p - 1, + p * p, + p * p + 1, + (mpz_class(1) << Fp::getOp().N * mcl::fp::UnitBitSize * 2) - 1, + }; + const size_t unitByteSize = sizeof(mcl::fp::Unit); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const mpz_class& x = tbl[i]; + const mcl::fp::Unit *px = mcl::gmp::getUnit(x); + const size_t xn = mcl::gmp::getUnitSize(x); + const size_t xByteSize = xn * unitByteSize; + const size_t fpByteSize = unitByteSize * Fp::getOp().N; + Fp y; + bool b; + y.setArray(&b, px, xn, mcl::fp::Mod); + bool expected = xByteSize <= fpByteSize * 2; + CYBOZU_TEST_EQUAL(b, expected); + if (!b) continue; + CYBOZU_TEST_EQUAL(y.getMpz(), x % p); + } +} + +CYBOZU_TEST_AUTO(set64bit) +{ + Fp::init("0x1000000000000000000f"); + const struct { + const char *p; + int64_t i; + } tbl[] = { + { "0x1234567812345678", int64_t(0x1234567812345678ull) }, + { "0xfffedcba987edcba997", -int64_t(0x1234567812345678ull) }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Fp x(tbl[i].p); + Fp y(tbl[i].i); + CYBOZU_TEST_EQUAL(x, y); + } +} + +void getUint64Test() +{ + const uint64_t tbl[] = { + 0, 1, 123, 0xffffffff, int64_t(0x7fffffffffffffffull) + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + uint64_t a = tbl[i]; + Fp x(a); + uint64_t b = x.getUint64(); + CYBOZU_TEST_ASSERT(!x.isNegative()); + CYBOZU_TEST_EQUAL(a, b); + } + { + Fp x("0xffffffffffffffff"); + CYBOZU_TEST_EQUAL(x.getUint64(), uint64_t(0xffffffffffffffffull)); + } + { + Fp x("0x10000000000000000"); + CYBOZU_TEST_EXCEPTION(x.getUint64(), cybozu::Exception); + x = -1; + CYBOZU_TEST_EXCEPTION(x.getUint64(), cybozu::Exception); + } + { + Fp x("0x10000000000000000"); + bool b = true; + CYBOZU_TEST_EQUAL(x.getUint64(&b), 0u); + CYBOZU_TEST_ASSERT(!b); + } +} + +void getInt64Test() +{ + const int64_t tbl[] = { + 0, 1, 123, 0xffffffff, int64_t(0x7fffffffffffffffull), + -1, -2, -12345678, int64_t(-9223372036854775808ull)/*-int64_t(1) << 63*/, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + int64_t a = tbl[i]; + Fp x(a); + CYBOZU_TEST_EQUAL(x.isNegative(), a < 0); + int64_t b = x.getInt64(); + CYBOZU_TEST_EQUAL(a, b); + } + { + Fp x("0x8000000000000000"); + CYBOZU_TEST_EXCEPTION(x.getInt64(), cybozu::Exception); + } + { + Fp x("0x8000000000000000"); + bool b = true; + CYBOZU_TEST_EQUAL(x.getInt64(&b), 0u); + CYBOZU_TEST_ASSERT(!b); + } +} + +void divBy2Test() +{ + const int tbl[] = { -4, -3, -2, -1, 0, 1, 2, 3 }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Fp x(tbl[i]), y; + Fp::divBy2(y, x); + y *= 2; + CYBOZU_TEST_EQUAL(y, x); + y = x; + Fp::divBy2(y, y); + y *= 2; + CYBOZU_TEST_EQUAL(y, x); + } +} + +void getStrTest() +{ + Fp x(0); + std::string str; + str = x.getStr(); + CYBOZU_TEST_EQUAL(str, "0"); + str = x.getStr(mcl::IoBinPrefix); + CYBOZU_TEST_EQUAL(str, "0b0"); + str = x.getStr(mcl::IoBin); + CYBOZU_TEST_EQUAL(str, "0"); + str = x.getStr(mcl::IoHexPrefix); + CYBOZU_TEST_EQUAL(str, "0x0"); + str = x.getStr(mcl::IoHex); + CYBOZU_TEST_EQUAL(str, "0"); + + x = 123; + str = x.getStr(); + CYBOZU_TEST_EQUAL(str, "123"); + str = x.getStr(mcl::IoBinPrefix); + CYBOZU_TEST_EQUAL(str, "0b1111011"); + str = x.getStr(mcl::IoBin); + CYBOZU_TEST_EQUAL(str, "1111011"); + str = x.getStr(mcl::IoHexPrefix); + CYBOZU_TEST_EQUAL(str, "0x7b"); + str = x.getStr(mcl::IoHex); + CYBOZU_TEST_EQUAL(str, "7b"); + + { + std::ostringstream os; + os << x; + CYBOZU_TEST_EQUAL(os.str(), "123"); + } + { + std::ostringstream os; + os << std::hex << std::showbase << x; + CYBOZU_TEST_EQUAL(os.str(), "0x7b"); + } + { + std::ostringstream os; + os << std::hex << x; + CYBOZU_TEST_EQUAL(os.str(), "7b"); + } + const char *tbl[] = { + "0x0", + "0x5", + "0x123", + "0x123456789012345679adbc", + "0xffffffff26f2fc170f69466a74defd8d", + "0x100000000000000000000000000000033", + "0x11ee12312312940000000000000000000000000002342343" + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const char *s = tbl[i]; + mpz_class mx(s); + if (mx >= Fp::getOp().mp) continue; + Fp y(s); + std::string xs, ys; + mcl::gmp::getStr(xs, mx, 16); + y.getStr(ys, 16); + CYBOZU_TEST_EQUAL(xs, ys); + } +} + +void setHashOfTest() +{ + const std::string msgTbl[] = { + "", "abc", "111111111111111111111111111111111111", + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(msgTbl); i++) { + size_t bitSize = Fp::getBitSize(); + std::string digest; + if (bitSize <= 256) { + digest = cybozu::Sha256().digest(msgTbl[i]); + } else { + digest = cybozu::Sha512().digest(msgTbl[i]); + } + Fp x, y; + x.setArrayMask(digest.c_str(), digest.size()); + y.setHashOf(msgTbl[i]); + CYBOZU_TEST_EQUAL(x, y); + } +} + +CYBOZU_TEST_AUTO(getArray) +{ + const struct { + const char *s; + uint32_t v[4]; + size_t vn; + } tbl[] = { + { "0", { 0, 0, 0, 0 }, 1 }, + { "1234", { 1234, 0, 0, 0 }, 1 }, + { "0xaabbccdd12345678", { 0x12345678, 0xaabbccdd, 0, 0 }, 2 }, + { "0x11112222333344445555666677778888", { 0x77778888, 0x55556666, 0x33334444, 0x11112222 }, 4 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + mpz_class x(tbl[i].s); + const size_t bufN = 8; + uint32_t buf[bufN]; + mcl::gmp::getArray(buf, bufN, x); + size_t n = mcl::fp::getNonZeroArraySize(buf, bufN); + CYBOZU_TEST_EQUAL(n, tbl[i].vn); + CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].v, n); + } +} + +void serializeTest() +{ + const char *tbl[] = { "0", "-1", "123" }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + char buf[1024]; + Fp x, y; + x.setStr(tbl[i]); + size_t n = x.serialize(buf, sizeof(buf)); + CYBOZU_TEST_EQUAL(n, Fp::getByteSize()); + y.deserialize(buf, n); + CYBOZU_TEST_EQUAL(x, y); + + n = x.serialize(buf, sizeof(buf), mcl::IoSerializeHexStr); + CYBOZU_TEST_EQUAL(n, Fp::getByteSize() * 2); + y.deserialize(buf, n, mcl::IoSerializeHexStr); + CYBOZU_TEST_EQUAL(x, y); + } +} + +void modpTest() +{ + const mpz_class& p = Fp::getOp().mp; + const mpz_class tbl[] = { + 0, + 1, + p - 1, + p, + p + 1, + p * 2 - 1, + p * 2, + p * 2 + 1, + p * (p - 1) - 1, + p * (p - 1), + p * (p - 1) + 1, + p * p - 1, + p * p, + p * p + 1, + (mpz_class(1) << Fp::getOp().N * mcl::fp::UnitBitSize * 2) - 1, + }; + mcl::Modp modp; + modp.init(p); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const mpz_class& x = tbl[i]; + mpz_class r1, r2; + r1 = x % p; + modp.modp(r2, x); + CYBOZU_TEST_EQUAL(r1, r2); + } +} + +#include +#if (defined(MCL_USE_LLVM) || defined(MCL_USE_XBYAK)) && (MCL_MAX_BIT_SIZE >= 521) +CYBOZU_TEST_AUTO(mod_NIST_P521) +{ + const size_t len = 521; + const size_t N = len / mcl::fp::UnitBitSize; + const char *tbl[] = { + "0", + "0xffffffff", + "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", + "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", + "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0x20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00111423424", + "0x11111111111111112222222222222222333333333333333344444444444444445555555555555555666666666666666677777777777777778888888888888888aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccddddddddddddddddeeeeeeeeeeeeeeeeffffffffffffffff1234712341234123412341234123412341234", + "0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + }; + const char *p = "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + Fp::init(p, mcl::fp::FP_XBYAK); + const mpz_class mp(p); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + mpz_class mx(tbl[i]); + mcl::fp::Unit in[N * 2 + 1] = {}; + mcl::fp::Unit ok[N + 1]; + mcl::fp::Unit ex[N + 1]; + mcl::gmp::getArray(in, N * 2 + 1, mx); + mpz_class my = mx % mp; + mcl::gmp::getArray(ok, N + 1, my); +#ifdef MCL_USE_LLVM + mcl_fpDbl_mod_NIST_P521L(ex, in, Fp::getOp().p); + CYBOZU_TEST_EQUAL_ARRAY(ex, ok, N + 1); +#endif +#ifdef MCL_USE_XBYAK + const mcl::fp::Op& op = Fp::getOp(); + if (!op.isMont) { + op.fpDbl_mod(ex, in, op.p); + CYBOZU_TEST_EQUAL_ARRAY(ex, ok, N + 1); + } +#endif + } +} +#endif + +void sub(mcl::fp::Mode mode) +{ + printf("mode=%s\n", mcl::fp::ModeToStr(mode)); + const char *tbl[] = { + // N = 2 + "0x0000000000000001000000000000000d", + "0x7fffffffffffffffffffffffffffffff", + "0x8000000000000000000000000000001d", + "0xffffffffffffffffffffffffffffff61", + + // N = 3 + "0x000000000000000100000000000000000000000000000033", // min prime + "0x00000000fffffffffffffffffffffffffffffffeffffac73", + "0x0000000100000000000000000001b8fa16dfab9aca16b6b3", + "0x000000010000000000000000000000000000000000000007", + "0x30000000000000000000000000000000000000000000002b", + "0x70000000000000000000000000000000000000000000001f", + "0x800000000000000000000000000000000000000000000005", + "0xfffffffffffffffffffffffffffffffffffffffeffffee37", + "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d", + "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime + + // N = 4 + "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime + "0x2523648240000001ba344d80000000086121000000000013a700000000000013", + "0x7523648240000001ba344d80000000086121000000000013a700000000000017", + "0x800000000000000000000000000000000000000000000000000000000000005f", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime +#if MCL_MAX_BIT_SIZE >= 384 + + // N = 6 + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff", +#endif + +#if MCL_MAX_BIT_SIZE >= 521 + // N = 9 + "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", +#endif + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const char *pStr = tbl[i]; + printf("prime=%s\n", pStr); + Fp::init(pStr, mode); + cstrTest(); + setStrTest(); + streamTest(); + ioModeTest(); + edgeTest(); + convTest(); + compareTest(); + moduloTest(pStr); + opeTest(); + mulUnitTest(); + powTest(); + powNegTest(); + powFpTest(); + powGmp(); + setArrayTest1(); + setArrayMaskTest1(); + setArrayModTest(); + getUint64Test(); + getInt64Test(); + divBy2Test(); + getStrTest(); + setHashOfTest(); + serializeTest(); + modpTest(); + } + anotherFpTest(mode); + setArrayTest2(mode); + setArrayMaskTest2(mode); +} + +std::string g_mode; + +CYBOZU_TEST_AUTO(main) +{ + if (g_mode.empty() || g_mode == "auto") { + sub(mcl::fp::FP_AUTO); + } + if (g_mode.empty() || g_mode == "gmp") { + sub(mcl::fp::FP_GMP); + } + if (g_mode.empty() || g_mode == "gmp_mont") { + sub(mcl::fp::FP_GMP_MONT); + } +#ifdef MCL_USE_LLVM + if (g_mode.empty() || g_mode == "llvm") { + sub(mcl::fp::FP_LLVM); + } + if (g_mode.empty() || g_mode == "llvm_mont") { + sub(mcl::fp::FP_LLVM_MONT); + } +#endif +#ifdef MCL_USE_XBYAK + if (g_mode.empty() || g_mode == "xbyak") { + sub(mcl::fp::FP_XBYAK); + } +#endif +} + +CYBOZU_TEST_AUTO(copyUnitToByteAsLE) +{ + using namespace mcl::fp; +#if MCL_SIZEOF_UNIT == 4 + const Unit src[] = { 0x12345678, 0xaabbccdd, 0xffeeddcc, 0x87654321 }; +#else + const Unit src[] = { uint64_t(0xaabbccdd12345678ull), uint64_t(0x87654321ffeeddcc) }; +#endif + const uint8_t ok[] = { 0x78, 0x56, 0x34, 0x12, 0xdd, 0xcc, 0xbb, 0xaa, 0xcc, 0xdd, 0xee, 0xff, 0x21, 0x43, 0x65, 0x87 }; + const size_t okN = CYBOZU_NUM_OF_ARRAY(ok); + for (size_t i = 0; i < okN; i++) { + uint8_t buf[okN] = {}; + copyUnitToByteAsLE(buf, src, i); + CYBOZU_TEST_EQUAL_ARRAY(ok, buf, i); + } + mcl::fp::Unit dst[2]; + for (size_t i = 1; i <= sizeof(dst); i++) { + memset(dst, 0xff, sizeof(dst)); + mcl::fp::copyByteToUnitAsLE(dst, ok, i); + if (i < sizeof(Unit)) { + CYBOZU_TEST_EQUAL(src[0] & ((uint64_t(1) << (i * 8)) - 1), dst[0]); + CYBOZU_TEST_EQUAL(dst[1], Unit(-1)); + continue; + } + CYBOZU_TEST_EQUAL(dst[0], src[0]); + if (i == sizeof(Unit)) { + CYBOZU_TEST_EQUAL(dst[1], Unit(-1)); + continue; + } + if (i < sizeof(dst)) { + CYBOZU_TEST_EQUAL(src[1] & ((uint64_t(1) << ((i - sizeof(Unit)) * 8)) - 1), dst[1]); + continue; + } + CYBOZU_TEST_EQUAL(src[1], dst[1]); + } + dst[0] = 1; + copyByteToUnitAsLE(dst, ok, 0); + CYBOZU_TEST_EQUAL(dst[0], 1u); +} + +int main(int argc, char *argv[]) + try +{ + cybozu::Option opt; + opt.appendOpt(&g_mode, "", "m", ": mode(auto/gmp/gmp_mont/llvm/llvm_mont/xbyak)"); + opt.appendHelp("h", ": show this message"); + if (!opt.parse(argc, argv)) { + opt.usage(); + return 1; + } + return cybozu::test::autoRun.run(argc, argv); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/fp_tower_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_tower_test.cpp new file mode 100644 index 000000000..a7123f7a5 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/fp_tower_test.cpp @@ -0,0 +1,477 @@ +#define PUT(x) std::cout << #x "=" << (x) << std::endl +#define CYBOZU_TEST_DISABLE_AUTO_RUN +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + #pragma warning(disable : 4456) +#endif + +#if MCL_MAX_BIT_SIZE >= 768 +typedef mcl::FpT Fp; +#else +typedef mcl::FpT Fp; +#endif +typedef mcl::Fp2T Fp2; +typedef mcl::FpDblT FpDbl; +typedef mcl::Fp6T Fp6; +typedef mcl::Fp12T Fp12; + +bool g_benchOnly = false; + +void testFp2() +{ + using namespace mcl; + puts(__FUNCTION__); +#if MCL_MAX_BIT_SIZE < 768 + const size_t FpSize = 48; + CYBOZU_TEST_EQUAL(sizeof(Fp), FpSize); + CYBOZU_TEST_EQUAL(sizeof(Fp2), FpSize * 2); + CYBOZU_TEST_EQUAL(sizeof(Fp6), FpSize * 6); + CYBOZU_TEST_EQUAL(sizeof(Fp12), FpSize * 12); +#endif + Fp2 x, y, z; + x.a = 1; + x.b = 2; + + { + std::stringstream os; + os << x; + os >> y; + CYBOZU_TEST_EQUAL(x, y); + } + y.a = 3; + y.b = 4; + /* + x = 1 + 2i + y = 3 + 4i + */ + Fp2::add(z, x, y); + CYBOZU_TEST_EQUAL(z, Fp2(4, 6)); + Fp2::sub(z, x, y); + CYBOZU_TEST_EQUAL(z, Fp2(-2, -2)); + Fp2::mul(z, x, y); + /* + (1 + 2i)(3 + 4i) = (3 - 8) + (4 + 6)i = -5 + 10i + */ + CYBOZU_TEST_EQUAL(z, Fp2(-5, 10)); + Fp2::neg(z, z); + CYBOZU_TEST_EQUAL(z, Fp2(5, -10)); + /* + xi = xi_a + i + (1 - 2i)(xi_a + i) = (xi_a + 2) + (1 - 2 xi_a)i + */ + z = Fp2(1, -2); + Fp2::mul_xi(z, z); + Fp a = Fp2::get_xi_a(); + CYBOZU_TEST_EQUAL(z, Fp2(a + 2, a * (-2) + 1)); + z = x * x; + Fp2::sqr(y, x); + CYBOZU_TEST_EQUAL(z, y); + x.a = -123456789; + x.b = 464652165165; + y = x * x; + Fp2::sqr(x, x); + CYBOZU_TEST_EQUAL(x, y); + { + std::ostringstream oss; + oss << x; + std::istringstream iss(oss.str()); + Fp2 w; + iss >> w; + CYBOZU_TEST_EQUAL(x, w); + } + y = 1; + for (int i = 0; i < 10; i++) { + Fp2::pow(z, x, i); + CYBOZU_TEST_EQUAL(z, y); + y *= x; + } + /* + (a + bi)^p = a + bi if p % 4 = 1 + (a + bi)^p = a - bi if p % 4 = 3 + */ + { + const mpz_class& mp = Fp::getOp().mp; + y = x; + Fp2::pow(z, y, mp); + if ((mp % 4) == 3) { + Fp::neg(z.b, z.b); + } + CYBOZU_TEST_EQUAL(z, y); + } + { + mpz_class t = Fp::getOp().mp; + t /= 2; + Fp x; + x.setMpz(t); + CYBOZU_TEST_EQUAL(x * 2, Fp(-1)); + t += 1; + x.setMpz(t); + CYBOZU_TEST_EQUAL(x * 2, 1); + } + { + Fp2 a(1, 1); + Fp2 b(1, -1); + Fp2 c(Fp2(2) / a); + CYBOZU_TEST_EQUAL(c, b); + CYBOZU_TEST_EQUAL(a * b, Fp2(2)); + CYBOZU_TEST_EQUAL(a * c, Fp2(2)); + } + y = x; + Fp2::inv(y, x); + y *= x; + CYBOZU_TEST_EQUAL(y, 1); + + // square root + for (int i = 0; i < 3; i++) { + x.a = i * i + i * 2; + x.b = i; + Fp2::sqr(y, x); + CYBOZU_TEST_ASSERT(Fp2::squareRoot(z, y)); + CYBOZU_TEST_EQUAL(z * z, y); + CYBOZU_TEST_ASSERT(Fp2::squareRoot(y, y)); + CYBOZU_TEST_EQUAL(z * z, y * y); + x.b = 0; + Fp2::sqr(y, x); + CYBOZU_TEST_ASSERT(Fp2::squareRoot(z, y)); + CYBOZU_TEST_EQUAL(z * z, y); + x.a = 0; + x.b = i * i + i * 3; + Fp2::sqr(y, x); + CYBOZU_TEST_ASSERT(Fp2::squareRoot(z, y)); + CYBOZU_TEST_EQUAL(z * z, y); + } +} + +void testFp6sqr(const Fp2& a, const Fp2& b, const Fp2& c, const Fp6& x) +{ + Fp2 t; + t = b * c * 2; + Fp2::mul_xi(t, t); + t += a * a; + CYBOZU_TEST_EQUAL(x.a, t); + t = c * c; + Fp2::mul_xi(t, t); + t += a * b * 2; + CYBOZU_TEST_EQUAL(x.b, t); + t = b * b + a * c * 2; + CYBOZU_TEST_EQUAL(x.c, t); +} + +void testFp6() +{ + using namespace mcl; + puts(__FUNCTION__); + Fp2 a(1, 2), b(3, 4), c(5, 6); + Fp6 x(a, b, c); + Fp6 y(Fp2(-1, 1), Fp2(4, -3), Fp2(-6, 2)); + Fp6 z, w; + { + std::stringstream ss; + ss << x; + ss >> z; + CYBOZU_TEST_EQUAL(x, z); + } + Fp6::add(z, x, y); + CYBOZU_TEST_EQUAL(z, Fp6(Fp2(0, 3), Fp2(7, 1), Fp2(-1, 8))); + Fp6::sub(z, x, y); + CYBOZU_TEST_EQUAL(z, Fp6(Fp2(2, 1), Fp2(-1, 7), Fp2(11, 4))); + Fp6::neg(z, x); + CYBOZU_TEST_EQUAL(z, Fp6(-a, -b, -c)); + Fp6::sqr(z, x); + Fp6::mul(w, x, x); + testFp6sqr(a, b, c, z); + testFp6sqr(a, b, c, w); + z = x; + Fp6::sqr(z, z); + Fp6::mul(w, x, x); + testFp6sqr(a, b, c, z); + testFp6sqr(a, b, c, w); + for (int i = 0; i < 10; i++) { + Fp6::inv(y, x); + Fp6::mul(z, y, x); + CYBOZU_TEST_EQUAL(z, 1); + x += y; + y = x; + Fp6::inv(y, y); + y *= x; + CYBOZU_TEST_EQUAL(y, 1); + } +} + +void testFp12() +{ + puts(__FUNCTION__); + Fp6 xa(Fp2(1, 2), Fp2(3, 4), Fp2(5, 6)); + Fp6 xb(Fp2(3, 1), Fp2(6, -1), Fp2(-2, 5)); + Fp12 x(xa, xb); + Fp6 ya(Fp2(2, 1), Fp2(5, 3), Fp2(4, 1)); + Fp6 yb(Fp2(1, -3), Fp2(2, -1), Fp2(-3, 1)); + Fp12 y(ya, yb); + Fp12 z; + Fp12::add(z, x, y); + CYBOZU_TEST_EQUAL(z, Fp12(Fp6(Fp2(3, 3), Fp2(8, 7), Fp2(9, 7)), Fp6(Fp2(4, -2), Fp2(8, -2), Fp2(-5, 6)))); + Fp12::sub(z, x, y); + CYBOZU_TEST_EQUAL(z, Fp12(Fp6(Fp2(-1, 1), Fp2(-2, 1), Fp2(1, 5)), Fp6(Fp2(2, 4), Fp2(4, 0), Fp2(1, 4)))); + Fp12::neg(z, x); + CYBOZU_TEST_EQUAL(z, Fp12(-xa, -xb)); + + y.b.clear(); + z = y; + Fp12::sqr(z, z); + CYBOZU_TEST_EQUAL(z.a, y.a * y.a); + z = y * y; + CYBOZU_TEST_EQUAL(z.a, y.a * y.a); + CYBOZU_TEST_ASSERT(z.b.isZero()); + Fp12 w; + y = x; + z = x * x; + w = x; + Fp12::sqr(w, w); + CYBOZU_TEST_EQUAL(z, w); + y = x; + y *= y; + Fp12::sqr(x, x); + CYBOZU_TEST_EQUAL(x, y); + for (int i = 0; i < 10; i++) { + w = x; + Fp12::inv(w, w); + Fp12::mul(y, w, x); + CYBOZU_TEST_EQUAL(y, 1); + x += y; + } +} + +void testFpDbl() +{ + puts(__FUNCTION__); + { + std::string pstr; + Fp::getModulo(pstr); + mpz_class mp(pstr); + mp <<= Fp::getUnitSize() * mcl::fp::UnitBitSize; + mpz_class mp1 = mp - 1; + mcl::gmp::getStr(pstr, mp1); + const char *tbl[] = { + "0", "1", "123456", "123456789012345668909", pstr.c_str(), + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + mpz_class mx(tbl[i]); + FpDbl x; + x.setMpz(mx); + for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(tbl); j++) { + FpDbl y, z; + mpz_class mz, mo; + mpz_class my(tbl[j]); + y.setMpz(my); + FpDbl::add(z, x, y); + mcl::gmp::addMod(mo, mx, my, mp); + z.getMpz(mz); + CYBOZU_TEST_EQUAL(mz, mo); + mcl::gmp::subMod(mo, mx, my, mp); + FpDbl::sub(z, x, y); + z.getMpz(mz); + CYBOZU_TEST_EQUAL(mz, mo); + if (!Fp::isFullBit()) { + FpDbl::addPre(z, x, y); + mo = mx + my; + z.getMpz(mz); + CYBOZU_TEST_EQUAL(mz, mo); + if (mx >= my) { + FpDbl::subPre(z, x, y); + mo = mx - my; + z.getMpz(mz); + CYBOZU_TEST_EQUAL(mz, mo); + } + } + } + } + } + { + std::string pstr; + Fp::getModulo(pstr); + const mpz_class mp(pstr); + cybozu::XorShift rg; + for (int i = 0; i < 3; i++) { + Fp x, y, z; + mpz_class mx, my, mz, mo; + x.setRand(rg); + y.setRand(rg); + x.getMpz(mx); + y.getMpz(my); + FpDbl d; + FpDbl::mulPre(d, x, y); + d.getMpz(mz); + { + Fp tx, ty; + tx = x; + ty = y; + tx.toMont(); + ty.toMont(); + mpz_class mtx, mty; + tx.getMpz(mtx); + ty.getMpz(mty); + mo = mtx * mty; + } + CYBOZU_TEST_EQUAL(mz, mo); + + FpDbl::mod(z, d); + z.getMpz(mz); + mo = (mx * my) % mp; + CYBOZU_TEST_EQUAL(mz, mo); + CYBOZU_TEST_EQUAL(z, x * y); + + FpDbl::sqrPre(d, x); + d.getMpz(mz); + { + Fp tx; + tx = x; + tx.toMont(); + mpz_class mtx; + tx.getMpz(mtx); + mo = mtx * mtx; + } + CYBOZU_TEST_EQUAL(mz, mo); + + FpDbl::mod(z, d); + z.getMpz(mz); + mo = (mx * mx) % mp; + CYBOZU_TEST_EQUAL(mz, mo); + CYBOZU_TEST_EQUAL(z, x * x); + } + } +} + +void testIo() +{ + int modeTbl[] = { 0, 2, 2 | mcl::IoPrefix, 10, 16, 16 | mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(modeTbl); i++) { + int ioMode = modeTbl[i]; + Fp12 x; + for (int j = 0; j < 12; j++) { + x.getFp0()[j] = j * j; + } + std::string s = x.getStr(ioMode); + Fp12 y; + y.setStr(s, ioMode); + CYBOZU_TEST_EQUAL(x, y); + } +} + +void benchFp2() +{ + puts(__FUNCTION__); + Fp2 x, y; + x.a.setStr("4"); + x.b.setStr("464652165165"); + y = x * x; + double addT, subT, mulT, sqrT, invT, mul_xiT; + CYBOZU_BENCH_T(addT, Fp2::add, x, x, y); + CYBOZU_BENCH_T(subT, Fp2::sub, x, x, y); + CYBOZU_BENCH_T(mulT, Fp2::mul, x, x, y); + CYBOZU_BENCH_T(sqrT, Fp2::sqr, x, x); + CYBOZU_BENCH_T(invT, Fp2::inv, x, x); + CYBOZU_BENCH_T(mul_xiT, Fp2::mul_xi, x, x); +// CYBOZU_BENCH("Fp2::mul_Fp_0", Fp2::mul_Fp_0, x, x, Param::half); +// CYBOZU_BENCH("Fp2::mul_Fp_1", Fp2::mul_Fp_1, x, Param::half); +// CYBOZU_BENCH("Fp2::divBy2 ", Fp2::divBy2, x, x); +// CYBOZU_BENCH("Fp2::divBy4 ", Fp2::divBy4, x, x); + printf("add %8.2f|sub %8.2f|mul %8.2f|sqr %8.2f|inv %8.2f|mul_xi %8.2f\n", addT, subT, mulT, sqrT, invT, mul_xiT); +} + +void test(const char *p, mcl::fp::Mode mode) +{ + const int xi_a = 1; + Fp::init(xi_a, p, mode); + printf("mode=%s\n", mcl::fp::ModeToStr(mode)); + Fp2::init(); +#if 0 + if (Fp::getBitSize() > 256) { + printf("not support p=%s\n", p); + return; + } +#endif + if (g_benchOnly) { + benchFp2(); + return; + } + testFp2(); + testFpDbl(); + testFp6(); + testFp12(); + testIo(); +} + +void testAll() +{ + const char *tbl[] = { + // N = 2 + "0x0000000000000001000000000000000d", + "0x7fffffffffffffffffffffffffffffff", + "0x8000000000000000000000000000001d", + "0xffffffffffffffffffffffffffffff61", + + // N = 3 + "0x000000000000000100000000000000000000000000000033", // min prime + "0x00000000fffffffffffffffffffffffffffffffeffffac73", + "0x0000000100000000000000000001b8fa16dfab9aca16b6b3", + "0x000000010000000000000000000000000000000000000007", + "0x30000000000000000000000000000000000000000000002b", + "0x70000000000000000000000000000000000000000000001f", + "0x800000000000000000000000000000000000000000000005", + "0xfffffffffffffffffffffffffffffffeffffffffffffffff", + "0xfffffffffffffffffffffffffffffffffffffffeffffee37", + "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d", + "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime + + // N = 4 + "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime + "0x2523648240000001ba344d80000000086121000000000013a700000000000013", + "0x7523648240000001ba344d80000000086121000000000013a700000000000017", + "0x800000000000000000000000000000000000000000000000000000000000005f", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime +#if MCL_MAX_BIT_SIZE >= 384 + // N = 6 + "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff", +#endif +#if MCL_MAX_BIT_SIZE >= 768 + "776259046150354467574489744231251277628443008558348305569526019013025476343188443165439204414323238975243865348565536603085790022057407195722143637520590569602227488010424952775132642815799222412631499596858234375446423426908029627", +#endif + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const char *p = tbl[i]; + printf("prime=%s %d\n", p, (int)(strlen(p) - 2) * 4); + test(p, mcl::fp::FP_GMP); +#ifdef MCL_USE_LLVM + test(p, mcl::fp::FP_LLVM); + test(p, mcl::fp::FP_LLVM_MONT); +#endif +#ifdef MCL_USE_XBYAK + test(p, mcl::fp::FP_XBYAK); +#endif + } +} + +CYBOZU_TEST_AUTO(testAll) +{ + testAll(); +} + +int main(int argc, char *argv[]) +{ + if (argc > 1 && strcmp(argv[1], "-bench") == 0) { + g_benchOnly = true; + } + if (g_benchOnly) { + testAll(); + return 0; + } else { + return cybozu::test::autoRun.run(argc, argv); + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/fp_util_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_util_test.cpp new file mode 100644 index 000000000..e8a9f9aa5 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/fp_util_test.cpp @@ -0,0 +1,270 @@ +#define PUT(x) std::cout << #x "=" << (x) << std::endl +#include +#include +#include +#include +#include + +CYBOZU_TEST_AUTO(arrayToHex) +{ + const struct { + uint32_t x[4]; + size_t n; + const char *str; + } tbl[] = { + { { 0, 0, 0, 0 }, 0, "0" }, + { { 0x123, 0, 0, 0 }, 1, "123" }, + { { 0x12345678, 0xaabbcc, 0, 0 }, 2, "aabbcc12345678" }, + { { 0, 0x12, 0x234a, 0 }, 3, "234a0000001200000000" }, + { { 1, 2, 0xffffffff, 0x123abc }, 4, "123abcffffffff0000000200000001" }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + char buf[64]; + size_t n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, false); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n); + n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, true); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0x") + tbl[i].str).c_str(), n); + } +} + +CYBOZU_TEST_AUTO(arrayToBin) +{ + const struct { + uint32_t x[4]; + size_t n; + const char *str; + } tbl[] = { + { { 0, 0, 0, 0 }, 0, "0" }, + { { 0x123, 0, 0, 0 }, 1, "100100011" }, + { { 0x12345678, 0xaabbcc, 0, 0 }, 2, "10101010101110111100110000010010001101000101011001111000" }, + { { 0, 0x12, 0x234a, 0 }, 3, "100011010010100000000000000000000000000001001000000000000000000000000000000000" }, + { { 1, 2, 0xffffffff, 0x123abc }, 4, "100100011101010111100111111111111111111111111111111110000000000000000000000000000001000000000000000000000000000000001" }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + char buf[512]; + size_t n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, false); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n); + n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, true); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0b") + tbl[i].str).c_str(), n); + } +} +// CYBOZU_TEST_AUTO(verifyStr) // QQQ + +CYBOZU_TEST_AUTO(hexToArray) +{ + const struct { + const char *str; + uint64_t x[4]; + } tbl[] = { + { "0", { 0, 0, 0, 0 } }, + { "5", { 5, 0, 0, 0 } }, + { "123", { 0x123, 0, 0, 0 } }, + { "123456789012345679adbc", { uint64_t(0x789012345679adbcull), 0x123456, 0, 0 } }, + { "ffffffff26f2fc170f69466a74defd8d", { uint64_t(0x0f69466a74defd8dull), uint64_t(0xffffffff26f2fc17ull), 0, 0 } }, + { "100000000000000000000000000000033", { uint64_t(0x0000000000000033ull), 0, 1, 0 } }, + { "11ee12312312940000000000000000000000000002342343", { uint64_t(0x0000000002342343ull), uint64_t(0x0000000000000000ull), uint64_t(0x11ee123123129400ull), 0 } }, + { "1234567890abcdefABCDEF123456789aba32134723424242424", { uint64_t(0x2134723424242424ull), uint64_t(0xDEF123456789aba3ull), uint64_t(0x4567890abcdefABCull), 0x123 } }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const size_t xN = 4; + uint64_t x[xN]; + size_t n = mcl::fp::hexToArray(x, xN, tbl[i].str, strlen(tbl[i].str)); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL_ARRAY(x, tbl[i].x, n); + } +} + +CYBOZU_TEST_AUTO(compareArray) +{ + const struct { + uint32_t a[4]; + uint32_t b[4]; + size_t n; + int expect; + } tbl[] = { + { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0 }, + { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, 1, 1 }, + { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, -1 }, + { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, 0 }, + { { 3, 1, 1, 0 }, { 2, 1, 1, 0 }, 4, 1 }, + { { 9, 2, 1, 1 }, { 1, 3, 1, 1 }, 4, -1 }, + { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 3, 0 }, + { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 4, -1 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + int e = mcl::fp::compareArray(tbl[i].a, tbl[i].b, tbl[i].n); + CYBOZU_TEST_EQUAL(e, tbl[i].expect); + } +} + +CYBOZU_TEST_AUTO(isLessArray) +{ + const struct { + uint32_t a[4]; + uint32_t b[4]; + size_t n; + bool expect; + } tbl[] = { + { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, false }, + { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, 1, false }, + { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, true }, + { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, false }, + { { 3, 1, 1, 0 }, { 2, 1, 1, 0 }, 4, false }, + { { 3, 1, 2, 0 }, { 2, 2, 2, 0 }, 4, true }, + { { 9, 2, 1, 1 }, { 1, 3, 1, 1 }, 4, true }, + { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 3, false }, + { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 4, true }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + bool e = mcl::fp::isLessArray(tbl[i].a, tbl[i].b, tbl[i].n); + CYBOZU_TEST_EQUAL(e, tbl[i].expect); + e = mcl::fp::isGreaterArray(tbl[i].b, tbl[i].a, tbl[i].n); + CYBOZU_TEST_EQUAL(e, tbl[i].expect); + } +} + +CYBOZU_TEST_AUTO(isLessOrEqualArray) +{ + const struct { + uint32_t a[4]; + uint32_t b[4]; + size_t n; + bool expect; + } tbl[] = { + { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, true }, + { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, 1, false }, + { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, true }, + { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, true }, + { { 3, 1, 1, 0 }, { 2, 1, 1, 0 }, 4, false }, + { { 3, 1, 2, 0 }, { 2, 2, 2, 0 }, 4, true }, + { { 9, 2, 1, 1 }, { 1, 3, 1, 1 }, 4, true }, + { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 3, true }, + { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 4, true }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + bool e = mcl::fp::isLessOrEqualArray(tbl[i].a, tbl[i].b, tbl[i].n); + CYBOZU_TEST_EQUAL(e, tbl[i].expect); + e = mcl::fp::isGreaterOrEqualArray(tbl[i].b, tbl[i].a, tbl[i].n); + CYBOZU_TEST_EQUAL(e, tbl[i].expect); + } +} + +struct Rand { + std::vector v; + const uint8_t *p; + size_t pos; + size_t endPos; + void read(bool *pb, void *x, size_t n) + { + if (pos + n > endPos) { + *pb = false; + return; + } + uint8_t *dst = (uint8_t*)x; + memcpy(dst, p + pos, n); + pos += n; + *pb = true; + } + void read(void *x, size_t n) + { + bool b; + read(&b, x, n); + if (!b) throw cybozu::Exception("Rand") << n; + } + uint32_t operator()() + { + char buf[4]; + read(buf, 4); + uint32_t v; + memcpy(&v, buf, 4); + return v; + } + Rand(const uint32_t *x, size_t n) + : p(0) + , pos(0) + { + for (size_t i = 0; i < n; i++) { + v.push_back(x[i]); + } + p = (uint8_t*)&v[0]; + endPos = v.size() * 4; + } +}; + +CYBOZU_TEST_AUTO(maskArray) +{ +#if 1 + const size_t n = 2; + uint32_t org[n] = { 0xabce1234, 0xffffef32 }; + for (size_t i = 0; i <= sizeof(org) * 8; i++) { + uint32_t x[n]; + memcpy(x, org, sizeof(org)); + mcl::fp::maskArray(x, n, i); + mpz_class t; + mcl::gmp::setArray(t, org, n); + t &= (mpz_class(1) << i) - 1; + uint32_t y[n]; + mcl::gmp::getArray(y, n, t); + CYBOZU_TEST_EQUAL_ARRAY(x, y, n); + } +#else + const size_t n = 4; + uint16_t org[n] = { 0x1234, 0xabce, 0xef32, 0xffff }; + for (size_t i = 0; i <= sizeof(org) * 8; i++) { + uint16_t x[n]; + memcpy(x, org, sizeof(org)); + mcl::fp::maskArray(x, n, i); + mpz_class t; + mcl::gmp::setArray(t, org, n); + t &= (mpz_class(1) << i) - 1; + uint16_t y[n]; + mcl::gmp::getArray(y, n, t); + CYBOZU_TEST_EQUAL_ARRAY(x, y, n); + } +#endif +} + +CYBOZU_TEST_AUTO(stream) +{ + const char *nulTbl[] = { "", " ", " \t\t\n\n " }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(nulTbl); i++) { + const char *p = nulTbl[i]; + cybozu::MemoryInputStream is(p, strlen(p)); + std::string w = "abc"; + mcl::fp::local::loadWord(w, is); + CYBOZU_TEST_ASSERT(w.empty()); + } + const struct { + const char *buf; + const char *expect[2]; + size_t n; + } tbl[] = { + { "\t\t \n\rabc\r\r\n def", { "abc", "def" }, 2 }, + { "123", { "123" }, 1 }, + { "123\n", { "123" }, 1 }, + { "123 456", { "123", "456" }, 2 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const char *buf = tbl[i].buf; + { + cybozu::MemoryInputStream is(buf, strlen(buf)); + for (size_t j = 0; j < tbl[i].n; j++) { + std::string w; + mcl::fp::local::loadWord(w, is); + CYBOZU_TEST_EQUAL(w, tbl[i].expect[j]); + } + } + { + std::istringstream is(buf); + for (size_t j = 0; j < tbl[i].n; j++) { + std::string w; + mcl::fp::local::loadWord(w, is); + CYBOZU_TEST_EQUAL(w, tbl[i].expect[j]); + } + } + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/glv_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/glv_test.cpp new file mode 100644 index 000000000..a917f51f4 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/glv_test.cpp @@ -0,0 +1,209 @@ +#define PUT(x) std::cout << #x "=" << (x) << std::endl; +#include +#include +#include + +#if 1 +#include +using namespace mcl::bn384; +#else +#include +using namespace mcl::bn256; +#endif + +#define PUT(x) std::cout << #x "=" << (x) << std::endl; + +/* + Skew Frobenius Map and Efficient Scalar Multiplication for Pairing-Based Cryptography + Y. Sakemi, Y. Nogami, K. Okeya, H. Kato, Y. Morikawa +*/ +struct oldGLV { + Fp w; // (-1 + sqrt(-3)) / 2 + mpz_class r; + mpz_class v; // 6z^2 + 4z + 1 > 0 + mpz_class c; // 2z + 1 + void init(const mpz_class& r, const mpz_class& z) + { + if (!Fp::squareRoot(w, -3)) throw cybozu::Exception("oldGLV:init"); + w = (w - 1) / 2; + this->r = r; + v = 1 + z * (4 + z * 6); + c = 2 * z + 1; + } + /* + (p^2 mod r) (x, y) = (wx, -y) + */ + void mulP2(G1& Q, const G1& P) const + { + Fp::mul(Q.x, P.x, w); + Fp::neg(Q.y, P.y); + Q.z = P.z; + } + /* + x = ap^2 + b mod r + assume(x < r); + */ + void split(mpz_class& a, mpz_class& b, const mpz_class& x) const + { + assert(0 < x && x < r); + /* + x = s1 * v + s2 // s1 = x / v, s2 = x % v + = s1 * c * p^2 + s2 // vP = cp^2 P + = (s3 * v + s4) * p^2 + s2 // s3 = (s1 * c) / v, s4 = (s1 * c) % v + = (s3 * c * p^2 + s4) * p^2 + s2 + = (s3 * c) * p^4 + s4 * p^2 + s2 // s5 = s3 * c, p^4 = p^2 - 1 + = s5 * (p^2 - 1) + s4 * p^2 + s2 + = (s4 + s5) * p^2 + (s2 - s5) + */ + mpz_class t; + mcl::gmp::divmod(a, t, x, v); // a = t / v, t = t % v + a *= c; + mcl::gmp::divmod(b, a, a, v); // b = a / v, a = a % v + b *= c; + a += b; + b = t - b; + } + template + void mul(G1& Q, const G1& P, const mpz_class& x) const + { + G1 A, B; + mpz_class a, b; + split(a, b, x); + mulP2(A, P); + G1::mul(A, A, a); + G1::mul(B, P, b); + G1::add(Q, A, B); + } +}; + +template +void compareLength(const GLV1& rhs, const GLV2& lhs) +{ + cybozu::XorShift rg; + int lt = 0; + int eq = 0; + int gt = 0; + mpz_class R0, R1, L0, L1, x; + Fr r; + for (int i = 1; i < 1000; i++) { + r.setRand(rg); + x = r.getMpz(); + rhs.split(R0, R1, x); + lhs.split(L0, L1, x); + + size_t R0n = mcl::gmp::getBitSize(R0); + size_t R1n = mcl::gmp::getBitSize(R1); + size_t L0n = mcl::gmp::getBitSize(L0); + size_t L1n = mcl::gmp::getBitSize(L1); + size_t Rn = std::max(R0n, R1n); + size_t Ln = std::max(L0n, L1n); + if (Rn == Ln) { + eq++; + } + if (Rn > Ln) { + gt++; + } + if (Rn < Ln) { + lt++; + } + } + printf("#of{<} = %d, #of{=} = %d #of{>} = %d\n", lt, eq, gt); +} + +void testGLV1() +{ + G1 P0, P1, P2; + mapToG1(P0, 1); + cybozu::XorShift rg; + + oldGLV oldGlv; + if (!BN::param.isBLS12) { + oldGlv.init(BN::param.r, BN::param.z); + } + + mcl::bn::local::GLV1 glv; + glv.init(BN::param.r, BN::param.z, BN::param.isBLS12); + if (!BN::param.isBLS12) { + compareLength(glv, oldGlv); + } + + for (int i = 1; i < 100; i++) { + mapToG1(P0, i); + Fr s; + s.setRand(rg); + mpz_class ss = s.getMpz(); + G1::mulGeneric(P1, P0, ss); + glv.mul(P2, P0, ss); + CYBOZU_TEST_EQUAL(P1, P2); + glv.mul(P2, P0, ss, true); + CYBOZU_TEST_EQUAL(P1, P2); + if (!BN::param.isBLS12) { + oldGlv.mul(P2, P0, ss); + CYBOZU_TEST_EQUAL(P1, P2); + } + } + for (int i = -100; i < 100; i++) { + mpz_class ss = i; + G1::mulGeneric(P1, P0, ss); + glv.mul(P2, P0, ss); + CYBOZU_TEST_EQUAL(P1, P2); + glv.mul(P2, P0, ss, true); + CYBOZU_TEST_EQUAL(P1, P2); + } + Fr s; + mapToG1(P0, 123); + CYBOZU_BENCH_C("Ec::mul", 100, P1 = P0; s.setRand(rg); G1::mulGeneric, P2, P1, s.getMpz()); + CYBOZU_BENCH_C("Ec::glv", 100, P1 = P0; s.setRand(rg); glv.mul, P2, P1, s.getMpz()); +} + +/* + lambda = 6 * z * z + mul (lambda * 2) = FrobeniusOnTwist * 2 +*/ +void testGLV2() +{ + G2 Q0, Q1, Q2; + mpz_class z = BN::param.z; + mpz_class r = BN::param.r; + mpz_class lambda = 6 * z * z; + mcl::bn::local::GLV2 glv2; + glv2.init(r, z, BN::param.isBLS12); + mpz_class n; + cybozu::XorShift rg; + mapToG2(Q0, 1); + for (int i = -10; i < 10; i++) { + n = i; + G2::mulGeneric(Q1, Q0, n); + glv2.mul(Q2, Q0, n); + CYBOZU_TEST_EQUAL(Q1, Q2); + } + for (int i = 1; i < 100; i++) { + mcl::gmp::getRand(n, glv2.rBitSize, rg); + n %= r; + n -= r/2; + mapToG2(Q0, i); + G2::mulGeneric(Q1, Q0, n); + glv2.mul(Q2, Q0, n); + CYBOZU_TEST_EQUAL(Q1, Q2); + } + Fr s; + mapToG2(Q0, 123); + CYBOZU_BENCH_C("G2::mul", 1000, Q2 = Q0; s.setRand(rg); G2::mulGeneric, Q2, Q1, s.getMpz()); + CYBOZU_BENCH_C("G2::glv", 1000, Q1 = Q0; s.setRand(rg); glv2.mul, Q2, Q1, s.getMpz()); +} + +CYBOZU_TEST_AUTO(glv) +{ + const mcl::CurveParam tbl[] = { + mcl::BN254, + mcl::BN381_1, + mcl::BN381_2, + mcl::BLS12_381, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const mcl::CurveParam& cp = tbl[i]; + initPairing(cp); + testGLV1(); + testGLV2(); + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/gmp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/gmp_test.cpp new file mode 100644 index 000000000..1fe9d4eb6 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/gmp_test.cpp @@ -0,0 +1,70 @@ +#include +#include +#include + +CYBOZU_TEST_AUTO(testBit) +{ + const size_t maxBit = 100; + const size_t tbl[] = { + 3, 9, 5, 10, 50, maxBit + }; + mpz_class a; + std::vector b(maxBit + 1); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + a |= mpz_class(1) << tbl[i]; + b[tbl[i]] = 1; + } + for (size_t i = 0; i <= maxBit; i++) { + bool c1 = mcl::gmp::testBit(a, i); + bool c2 = b[i] != 0; + CYBOZU_TEST_EQUAL(c1, c2); + } +} + +CYBOZU_TEST_AUTO(getStr) +{ + const struct { + int x; + const char *dec; + const char *hex; + } tbl[] = { + { 0, "0", "0" }, + { 1, "1", "1" }, + { 10, "10", "a" }, + { 16, "16", "10" }, + { 123456789, "123456789", "75bcd15" }, + { -1, "-1", "-1" }, + { -10, "-10", "-a" }, + { -16, "-16", "-10" }, + { -100000000, "-100000000", "-5f5e100" }, + { -987654321, "-987654321", "-3ade68b1" }, + { -2147483647, "-2147483647", "-7fffffff" }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + mpz_class x = tbl[i].x; + char buf[32]; + size_t n, len; + len = strlen(tbl[i].dec); + n = mcl::gmp::getStr(buf, len, x, 10); + CYBOZU_TEST_EQUAL(n, 0); + n = mcl::gmp::getStr(buf, len + 1, x, 10); + CYBOZU_TEST_EQUAL(n, len); + CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].dec, n); + + len = strlen(tbl[i].hex); + n = mcl::gmp::getStr(buf, len, x, 16); + CYBOZU_TEST_EQUAL(n, 0); + n = mcl::gmp::getStr(buf, len + 1, x, 16); + CYBOZU_TEST_EQUAL(n, len); + CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].hex, n); + } +} + +CYBOZU_TEST_AUTO(getRandPrime) +{ + for (int i = 0; i < 10; i++) { + mpz_class z; + mcl::gmp::getRandPrime(z, i * 10 + 3); + CYBOZU_TEST_ASSERT(mcl::gmp::isPrime(z)); + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/low_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/low_test.cpp new file mode 100644 index 000000000..f5e72a0b3 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/low_test.cpp @@ -0,0 +1,73 @@ +#ifndef MCL_USE_LLVM + #define MCL_USE_LLVM +#endif +#include +#include +#include +#include "../src/low_func.hpp" +#include + +cybozu::XorShift rg; + +extern "C" void add_test(mcl::fp::Unit *z, const mcl::fp::Unit *x, const mcl::fp::Unit *y); + +template +void bench() +{ + using namespace mcl::fp; + const size_t N = bit / UnitBitSize; + Unit x[N], y[N]; + for (int i = 0; i < 10; i++) { + Unit z[N]; + Unit w[N]; + rg.read(x, N); + rg.read(y, N); + AddPre::f(z, x, y); + AddPre::f(w, x, y); + CYBOZU_TEST_EQUAL_ARRAY(z, w, N); + + SubPre::f(z, x, y); + SubPre::f(w, x, y); + CYBOZU_TEST_EQUAL_ARRAY(z, w, N); + } + const std::string bitS = cybozu::itoa(bit); + std::string name; + name = "add" + bitS; CYBOZU_BENCH(name.c_str(), (AddPre::f), x, x, y); + name = "sub" + bitS; CYBOZU_BENCH(name.c_str(), (SubPre::f), x, x, y); +} + +CYBOZU_TEST_AUTO(addPre64) { bench<64>(); } +CYBOZU_TEST_AUTO(addPre128) { bench<128>(); } +CYBOZU_TEST_AUTO(addPre192) { bench<192>(); } +CYBOZU_TEST_AUTO(addPre256) { bench<256>(); } +CYBOZU_TEST_AUTO(addPre320) { bench<320>(); } +CYBOZU_TEST_AUTO(addPre384) { bench<384>(); } +CYBOZU_TEST_AUTO(addPre448) { bench<448>(); } +CYBOZU_TEST_AUTO(addPre512) { bench<512>(); } +//CYBOZU_TEST_AUTO(addPre96) { bench<96>(); } +//CYBOZU_TEST_AUTO(addPre160) { bench<160>(); } +//CYBOZU_TEST_AUTO(addPre224) { bench<224>(); } +#if 0 +CYBOZU_TEST_AUTO(addPre) +{ + using namespace mcl::fp; + const size_t bit = 128; + const size_t N = bit / UnitBitSize; + Unit x[N], y[N]; + for (int i = 0; i < 10; i++) { + Unit z[N]; + Unit w[N]; + rg.read(x, N); + rg.read(y, N); + low_addPre_G(z, x, y); + addPre(w, x, y); + CYBOZU_TEST_EQUAL_ARRAY(z, w, N); + add_test(w, x, y); + CYBOZU_TEST_EQUAL_ARRAY(z, w, N); + } + std::string name = "add" + cybozu::itoa(bit); + CYBOZU_BENCH(name.c_str(), addPre, x, x, y); + CYBOZU_BENCH("add", add_test, x, x, y); +} +#endif + diff --git a/vendor/github.com/dexon-foundation/mcl/test/mk32.sh b/vendor/github.com/dexon-foundation/mcl/test/mk32.sh new file mode 100644 index 000000000..4d5f60711 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/mk32.sh @@ -0,0 +1 @@ +g++ -O3 -march=native base_test.cpp ../src/x86.s -m32 -I ~/32/include/ -I ../include/ -I ../../xbyak/ -I ../../cybozulib/include ~/32/lib/libgmp.a ~/32/lib/libgmpxx.a -I ~/32/lib -DNDEBUG diff --git a/vendor/github.com/dexon-foundation/mcl/test/modp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/modp_test.cpp new file mode 100644 index 000000000..bf9da38bf --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/modp_test.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + +#define PUT(x) std::cout << #x << "=" << x << std::endl; + +CYBOZU_TEST_AUTO(modp) +{ + const int C = 1000000; + const char *pTbl[] = { + "0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d", + "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", + "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", + }; + const char *xTbl[] = { + "0x12345678892082039482094823", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x10000000000000000000000000000000000000000000000000000000000000000", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + }; + mcl::Modp modp; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(pTbl); i++) { + const mpz_class p(pTbl[i]); + std::cout << std::hex << "p=" << p << std::endl; + modp.init(p); + for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(xTbl); j++) { + const mpz_class x(xTbl[j]); + std::cout << std::hex << "x=" << x << std::endl; + mpz_class r1, r2; + r1 = x % p; + modp.modp(r2, x); + CYBOZU_TEST_EQUAL(r1, r2); + CYBOZU_BENCH_C("x % p", C, mcl::gmp::mod, r1, x, p); + CYBOZU_BENCH_C("modp ", C, modp.modp, r2, x); + } + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/mont_fp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/mont_fp_test.cpp new file mode 100644 index 000000000..e41e77a53 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/mont_fp_test.cpp @@ -0,0 +1,332 @@ +#define PUT(x) std::cout << #x "=" << (x) << std::endl +#include +#include +#include +#include + +#if 0 +#include +using namespace mcl::bls12; +typedef Fr Zn; +#else +#include +struct ZnTag; +typedef mcl::FpT Zn; +typedef mcl::FpT<> Fp; +#endif + +struct Montgomery { + typedef mcl::fp::Unit Unit; + mpz_class p_; + mpz_class R_; // (1 << (pn_ * 64)) % p + mpz_class RR_; // (R * R) % p + Unit rp_; // rp * p = -1 mod M = 1 << 64 + size_t pn_; + Montgomery() {} + explicit Montgomery(const mpz_class& p) + { + p_ = p; + rp_ = mcl::fp::getMontgomeryCoeff(mcl::gmp::getUnit(p, 0)); + pn_ = mcl::gmp::getUnitSize(p); + R_ = 1; + R_ = (R_ << (pn_ * 64)) % p_; + RR_ = (R_ * R_) % p_; + } + + void toMont(mpz_class& x) const { mul(x, x, RR_); } + void fromMont(mpz_class& x) const { mul(x, x, 1); } + + void mul(mpz_class& z, const mpz_class& x, const mpz_class& y) const + { +#if 0 + const size_t ySize = mcl::gmp::getUnitSize(y); + mpz_class c = x * mcl::gmp::getUnit(y, 0); + Unit q = mcl::gmp::getUnit(c, 0) * rp_; + c += p_ * q; + c >>= sizeof(Unit) * 8; + for (size_t i = 1; i < pn_; i++) { + if (i < ySize) { + c += x * mcl::gmp::getUnit(y, i); + } + Unit q = mcl::gmp::getUnit(c, 0) * rp_; + c += p_ * q; + c >>= sizeof(Unit) * 8; + } + if (c >= p_) { + c -= p_; + } + z = c; +#else + z = x * y; + for (size_t i = 0; i < pn_; i++) { + Unit q = mcl::gmp::getUnit(z, 0) * rp_; +#ifdef MCL_USE_VINT + z += p_ * q; +#else + mpz_class t; + mcl::gmp::set(t, q); + z += p_ * t; +#endif + z >>= sizeof(Unit) * 8; + } + if (z >= p_) { + z -= p_; + } +#endif + } + void mod(mpz_class& z, const mpz_class& xy) const + { + z = xy; + for (size_t i = 0; i < pn_; i++) { +//printf("i=%zd\n", i); +//std::cout << "z=" << std::hex << z << std::endl; + Unit q = mcl::gmp::getUnit(z, 0) * rp_; +//std::cout << "q=" << q << std::endl; + mpz_class t; + mcl::gmp::set(t, q); + z += p_ * t; + z >>= sizeof(Unit) * 8; +//std::cout << "z=" << std::hex << z << std::endl; + } + if (z >= p_) { + z -= p_; + } +//std::cout << "z=" << std::hex << z << std::endl; + } +}; + +template +mpz_class getMpz(const T& x) +{ + std::string str = x.getStr(); + mpz_class t; + mcl::gmp::setStr(t, str); + return t; +} + +template +std::string getStr(const T& x) +{ + std::ostringstream os; + os << x; + return os.str(); +} + +template +T castTo(const U& x) +{ + T t; + t.setStr(getStr(x)); + return t; +} + +template +void putRaw(const T& x) +{ + const uint64_t *p = x.getInnerValue(); + for (size_t i = 0, n = T::BlockSize; i < n; i++) { + printf("%016llx", p[n - 1 - i]); + } + printf("\n"); +} + +template +void put(const uint64_t (&x)[N]) +{ + for (size_t i = 0; i < N; i++) { + printf("%016llx", x[N - 1 - i]); + } + printf("\n"); +} + +struct Test { + typedef mcl::FpT<> Fp; + void run(const char *p) + { + Fp::init(p); + Fp x("-123456789"); + Fp y("-0x7ffffffff"); + CYBOZU_BENCH("add", operator+, x, x); + CYBOZU_BENCH("sub", operator-, x, y); + CYBOZU_BENCH("mul", operator*, x, x); + CYBOZU_BENCH("sqr", Fp::sqr, x, x); + CYBOZU_BENCH("div", y += x; operator/, x, y); + } +}; + +void customTest(const char *pStr, const char *xStr, const char *yStr) +{ +#if 0 + { + pStr = "0xfffffffffffffffffffffffffffffffffffffffeffffee37", + Fp::init(pStr); + static uint64_t x[3] = { 1, 0, 0 }; + uint64_t z[3]; +std::cout<= 521 +CYBOZU_TEST_AUTO(customTest) +{ + const struct { + const char *p; + const char *x; + const char *y; + } tbl[] = { + { + "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", +// "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff", +// "0xfffffffffffffffffffffffffffffffffffffffeffffee37", + "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", + "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" + }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + customTest(tbl[i].p, tbl[i].x, tbl[i].y); + } +} +#endif + +CYBOZU_TEST_AUTO(test) +{ + Test test; + const char *tbl[] = { +#if 1 + // N = 2 + "0x0000000000000001000000000000000d", + "0x7fffffffffffffffffffffffffffffff", + "0x8000000000000000000000000000001d", + "0xffffffffffffffffffffffffffffff61", + + // N = 3 + "0x000000000000000100000000000000000000000000000033", // min prime + "0x00000000fffffffffffffffffffffffffffffffeffffac73", + "0x0000000100000000000000000001b8fa16dfab9aca16b6b3", + "0x000000010000000000000000000000000000000000000007", + "0x30000000000000000000000000000000000000000000002b", + "0x70000000000000000000000000000000000000000000001f", + "0x800000000000000000000000000000000000000000000005", + "0xfffffffffffffffffffffffffffffffffffffffeffffee37", + "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d", + "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime + + // N = 4 + "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime + "0x2523648240000001ba344d80000000086121000000000013a700000000000013", + "0x7523648240000001ba344d80000000086121000000000013a700000000000017", + "0x800000000000000000000000000000000000000000000000000000000000005f", + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime +#endif + +#if MCL_MAX_BIT_SIZE >= 384 + // N = 6 + "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff", +#endif + +#if MCL_MAX_BIT_SIZE >= 521 + // N = 9 + "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", +#endif + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + printf("prime=%s\n", tbl[i]); +#if 0 + mpz_class p(tbl[i]); + initPairing(mcl::BLS12_381); +#if 1 + cybozu::XorShift rg; + for (int i = 0; i < 1000; i++) { + Fp x, y, z; + FpDbl xy; + x.setByCSPRNG(rg); + y.setByCSPRNG(rg); + FpDbl::mulPre(xy, x, y); + FpDbl::mod(z, xy); + if (z != x * y) { + puts("ERR"); + std::cout << std::hex; + PUT(x); + PUT(y); + PUT(z); + PUT(x * y); + exit(1); + } + } +#else + Montgomery mont(p); + mpz_class x("19517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc", 16); + mpz_class y("139517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ff", 16); + std::cout << std::hex; + PUT(x); + PUT(y); + mpz_class z; + mont.mul(z, x, y); + PUT(z); + Fp x1, y1, z1; + puts("aaa"); + memcpy(&x1, mcl::gmp::getUnit(x), sizeof(x1)); + memcpy(&y1, mcl::gmp::getUnit(y), sizeof(y1)); + z1.clear(); + x1.dump(); + y1.dump(); + Fp::mul(z1, x1, y1); + z1.dump(); +#endif + exit(1); +#endif + test.run(tbl[i]); + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/paillier_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/paillier_test.cpp new file mode 100644 index 000000000..31d2b26fc --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/paillier_test.cpp @@ -0,0 +1,24 @@ +#include +#include + +CYBOZU_TEST_AUTO(paillier) +{ + using namespace mcl::paillier; + SecretKey sec; + sec.init(2048); + PublicKey pub; + sec.getPublicKey(pub); + mpz_class m1("12342340928409"), m2("23049820498204"); + mpz_class c1, c2, c3; + pub.enc(c1, m1); + pub.enc(c2, m2); + std::cout << std::hex << "c1=" << c1 << "\nc2=" << c2 << std::endl; + pub.add(c3, c1, c2); + mpz_class d1, d2, d3; + sec.dec(d1, c1); + sec.dec(d2, c2); + sec.dec(d3, c3); + CYBOZU_TEST_EQUAL(m1, d1); + CYBOZU_TEST_EQUAL(m2, d2); + CYBOZU_TEST_EQUAL(m1 + m2, d3); +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj new file mode 100644 index 000000000..936e075aa --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {9F935350-2F4C-45FA-A1C2-1D5AA0EADC96} + Win32Proj + bn_test + + + + Application + true + v120 + MultiByte + + + Application + false + v120 + true + MultiByte + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj new file mode 100644 index 000000000..4bdfda2cb --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {46B6E88E-739A-406B-9F68-BC46C5950FA3} + Win32Proj + ec_test + + + + Application + true + v120 + MultiByte + + + Application + false + v120 + true + MultiByte + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + diff --git a/vendor/github.com/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj new file mode 100644 index 000000000..f705982bf --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {51266DE6-B57B-4AE3-B85C-282F170E1728} + Win32Proj + fp_test + + + + Application + true + v120 + MultiByte + + + Application + false + v120 + true + MultiByte + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj new file mode 100644 index 000000000..d5720678f --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {733B6250-D249-4A99-B2A6-C8FAF6A90E97} + Win32Proj + fp_tower_test + + + + Application + true + v120 + MultiByte + + + Application + false + v120 + true + MultiByte + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/dexon-foundation/mcl/test/she_c256_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/she_c256_test.cpp new file mode 100644 index 000000000..3e458b623 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/she_c256_test.cpp @@ -0,0 +1,2 @@ +#define MCLBN_FP_UNIT_SIZE 4 +#include "she_c_test.hpp" diff --git a/vendor/github.com/dexon-foundation/mcl/test/she_c384_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/she_c384_test.cpp new file mode 100644 index 000000000..5c7bd9882 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/she_c384_test.cpp @@ -0,0 +1,2 @@ +#define MCLBN_FP_UNIT_SIZE 6 +#include "she_c_test.hpp" diff --git a/vendor/github.com/dexon-foundation/mcl/test/she_c_test.hpp b/vendor/github.com/dexon-foundation/mcl/test/she_c_test.hpp new file mode 100644 index 000000000..8287c0e0a --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/she_c_test.hpp @@ -0,0 +1,535 @@ +#include +#define CYBOZU_TEST_DISABLE_AUTO_RUN +#include +#include +#include + +const size_t hashSize = 1 << 10; +const size_t tryNum = 1024; + +CYBOZU_TEST_AUTO(init) +{ + int curve; +#if MCLBN_FP_UNIT_SIZE == 4 + curve = MCL_BN254; +#elif MCLBN_FP_UNIT_SIZE == 6 +// curve = MCL_BN381_1; + curve = MCL_BLS12_381; +#elif MCLBN_FP_UNIT_SIZE == 8 + curve = MCL_BN462; +#endif + int ret; + ret = sheInit(curve, MCLBN_COMPILED_TIME_VAR); + CYBOZU_TEST_EQUAL(ret, 0); + ret = sheSetRangeForDLP(hashSize); + CYBOZU_TEST_EQUAL(ret, 0); +} + +CYBOZU_TEST_AUTO(encDec) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + + int64_t m = 123; + sheCipherTextG1 c1; + sheCipherTextG2 c2; + sheCipherTextGT ct; + sheEncG1(&c1, &pub, m); + sheEncG2(&c2, &pub, m); + sheEncGT(&ct, &pub, m); + + int64_t dec; + CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c1), 0); + CYBOZU_TEST_EQUAL(dec, m); + dec = 0; + CYBOZU_TEST_EQUAL(sheDecG1ViaGT(&dec, &sec, &c1), 0); + CYBOZU_TEST_EQUAL(dec, m); + dec = 0; + CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c2), 0); + CYBOZU_TEST_EQUAL(dec, m); + dec = 0; + CYBOZU_TEST_EQUAL(sheDecG2ViaGT(&dec, &sec, &c2), 0); + CYBOZU_TEST_EQUAL(dec, m); + dec = 0; + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); + CYBOZU_TEST_EQUAL(dec, m); + + for (int m = -3; m < 3; m++) { + sheEncG1(&c1, &pub, m); + CYBOZU_TEST_EQUAL(sheIsZeroG1(&sec, &c1), m == 0); + sheEncG2(&c2, &pub, m); + CYBOZU_TEST_EQUAL(sheIsZeroG2(&sec, &c2), m == 0); + sheEncGT(&ct, &pub, m); + CYBOZU_TEST_EQUAL(sheIsZeroGT(&sec, &ct), m == 0); + } +} + +CYBOZU_TEST_AUTO(addMul) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + + int64_t m1 = 12; + int64_t m2 = -9; + sheCipherTextG1 c1; + sheCipherTextG2 c2; + sheCipherTextGT ct; + sheEncG1(&c1, &pub, m1); + sheEncG2(&c2, &pub, m2); + sheMul(&ct, &c1, &c2); + + int64_t dec; + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); + CYBOZU_TEST_EQUAL(dec, m1 * m2); +} + +CYBOZU_TEST_AUTO(allOp) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + + int64_t m1 = 12; + int64_t m2 = -9; + int64_t m3 = 12; + int64_t m4 = -9; + int64_t dec; + sheCipherTextG1 c11, c12; + sheCipherTextG2 c21, c22; + sheCipherTextGT ct; + + sheEncG1(&c11, &pub, m1); + sheNegG1(&c12, &c11); + CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c12), 0); + CYBOZU_TEST_EQUAL(dec, -m1); + + sheEncG1(&c12, &pub, m2); + sheSubG1(&c11, &c11, &c12); // m1 - m2 + sheMulG1(&c11, &c11, 4); // 4 * (m1 - m2) + + sheEncG2(&c21, &pub, m3); + sheNegG2(&c22, &c21); + CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c22), 0); + CYBOZU_TEST_EQUAL(dec, -m3); + sheEncG2(&c22, &pub, m4); + sheSubG2(&c21, &c21, &c22); // m3 - m4 + sheMulG2(&c21, &c21, -5); // -5 * (m3 - m4) + sheMul(&ct, &c11, &c21); // -20 * (m1 - m2) * (m3 - m4) + sheAddGT(&ct, &ct, &ct); // -40 * (m1 - m2) * (m3 - m4) + sheMulGT(&ct, &ct, -4); // 160 * (m1 - m2) * (m3 - m4) + + int64_t t = 160 * (m1 - m2) * (m3 - m4); + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); + CYBOZU_TEST_EQUAL(dec, t); + + sheCipherTextGT ct2; + sheNegGT(&ct2, &ct); + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct2), 0); + CYBOZU_TEST_EQUAL(dec, -t); +} + +CYBOZU_TEST_AUTO(rerand) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + + int64_t m1 = 12; + int64_t m2 = -9; + int64_t m3 = 12; + sheCipherTextG1 c1; + sheCipherTextG2 c2; + sheCipherTextGT ct1, ct2; + sheEncG1(&c1, &pub, m1); + sheReRandG1(&c1, &pub); + + sheEncG2(&c2, &pub, m2); + sheReRandG2(&c2, &pub); + + sheEncGT(&ct1, &pub, m3); + sheReRandGT(&ct1, &pub); + + sheMul(&ct2, &c1, &c2); + sheReRandGT(&ct2, &pub); + sheAddGT(&ct1, &ct1, &ct2); + + int64_t dec; + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct1), 0); + CYBOZU_TEST_EQUAL(dec, m1 * m2 + m3); +} + +CYBOZU_TEST_AUTO(serialize) +{ + sheSecretKey sec1, sec2; + sheSecretKeySetByCSPRNG(&sec1); + shePublicKey pub1, pub2; + sheGetPublicKey(&pub1, &sec1); + + char buf1[4096], buf2[4096]; + size_t n1, n2; + size_t r, size; + const size_t sizeofFr = mclBn_getFrByteSize(); + const size_t sizeofFp = mclBn_getG1ByteSize(); + + size = sizeofFr * 2; + n1 = sheSecretKeySerialize(buf1, sizeof(buf1), &sec1); + CYBOZU_TEST_EQUAL(n1, size); + r = sheSecretKeyDeserialize(&sec2, buf1, n1); + CYBOZU_TEST_EQUAL(r, n1); + n2 = sheSecretKeySerialize(buf2, sizeof(buf2), &sec2); + CYBOZU_TEST_EQUAL(n2, size); + CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2); + + size = sizeofFp * 3; + n1 = shePublicKeySerialize(buf1, sizeof(buf1), &pub1); + CYBOZU_TEST_EQUAL(n1, size); + r = shePublicKeyDeserialize(&pub2, buf1, n1); + CYBOZU_TEST_EQUAL(r, n1); + n2 = shePublicKeySerialize(buf2, sizeof(buf2), &pub2); + CYBOZU_TEST_EQUAL(n2, size); + CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2); + + int m = 123; + sheCipherTextG1 c11, c12; + sheCipherTextG2 c21, c22; + sheCipherTextGT ct1, ct2; + sheEncG1(&c11, &pub2, m); + sheEncG2(&c21, &pub2, m); + sheEncGT(&ct1, &pub2, m); + + size = sizeofFp * 2; + n1 = sheCipherTextG1Serialize(buf1, sizeof(buf1), &c11); + CYBOZU_TEST_EQUAL(n1, size); + r = sheCipherTextG1Deserialize(&c12, buf1, n1); + CYBOZU_TEST_EQUAL(r, n1); + n2 = sheCipherTextG1Serialize(buf2, sizeof(buf2), &c12); + CYBOZU_TEST_EQUAL(n2, size); + CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2); + + size = sizeofFp * 4; + n1 = sheCipherTextG2Serialize(buf1, sizeof(buf1), &c21); + CYBOZU_TEST_EQUAL(n1, size); + r = sheCipherTextG2Deserialize(&c22, buf1, n1); + CYBOZU_TEST_EQUAL(r, n1); + n2 = sheCipherTextG2Serialize(buf2, sizeof(buf2), &c22); + CYBOZU_TEST_EQUAL(n2, size); + CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2); + + size = sizeofFp * 12 * 4; + n1 = sheCipherTextGTSerialize(buf1, sizeof(buf1), &ct1); + CYBOZU_TEST_EQUAL(n1, size); + r = sheCipherTextGTDeserialize(&ct2, buf1, n1); + CYBOZU_TEST_EQUAL(r, n1); + n2 = sheCipherTextGTSerialize(buf2, sizeof(buf2), &ct2); + CYBOZU_TEST_EQUAL(n2, size); + CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2); +} + +CYBOZU_TEST_AUTO(convert) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + sheCipherTextGT ct; + const int64_t m = 123; + int64_t dec; + sheCipherTextG1 c1; + sheEncG1(&c1, &pub, m); + CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c1), 0); + CYBOZU_TEST_EQUAL(dec, 123); + sheConvertG1(&ct, &pub, &c1); + dec = 0; + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); + CYBOZU_TEST_EQUAL(dec, 123); + + sheCipherTextG2 c2; + sheEncG2(&c2, &pub, m); + CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c2), 0); + CYBOZU_TEST_EQUAL(dec, 123); + sheConvertG2(&ct, &pub, &c2); + dec = 0; + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); + CYBOZU_TEST_EQUAL(dec, 123); +} + +CYBOZU_TEST_AUTO(precomputed) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate(); + CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0); + const int64_t m = 152; + sheCipherTextG1 c1; + sheCipherTextG2 c2; + sheCipherTextGT ct; + int64_t dec = 0; + CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyEncG1(&c1, ppub, m), 0); + CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c1), 0); + CYBOZU_TEST_EQUAL(dec, m); + dec = 0; + CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyEncG2(&c2, ppub, m), 0); + CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c2), 0); + CYBOZU_TEST_EQUAL(dec, m); + dec = 0; + CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyEncGT(&ct, ppub, m), 0); + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); + CYBOZU_TEST_EQUAL(dec, m); + + shePrecomputedPublicKeyDestroy(ppub); +} + +template +void ZkpBinTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, decFunc dec, verifyFunc verify) +{ + CT c; + sheZkpBin zkp; + for (int m = 0; m < 2; m++) { + CYBOZU_TEST_EQUAL(encWithZkp(&c, &zkp, pub, m), 0); + mclInt mDec; + CYBOZU_TEST_EQUAL(dec(&mDec, sec, &c), 0); + CYBOZU_TEST_EQUAL(mDec, m); + CYBOZU_TEST_EQUAL(verify(pub, &c, &zkp), 1); + { + char buf[4096]; + size_t n = sheZkpBinSerialize(buf, sizeof(buf), &zkp); + CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * CYBOZU_NUM_OF_ARRAY(zkp.d)); + sheZkpBin zkp2; + size_t r = sheZkpBinDeserialize(&zkp2, buf, n); + CYBOZU_TEST_EQUAL(r, n); + CYBOZU_TEST_EQUAL(r, n); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(zkp.d); i++) { + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&zkp.d[i], &zkp2.d[i])); + } + } + zkp.d[0].d[0]++; + CYBOZU_TEST_EQUAL(verify(pub, &c, &zkp), 0); + } + CYBOZU_TEST_ASSERT(encWithZkp(&c, &zkp, pub, 2) != 0); +} + +CYBOZU_TEST_AUTO(ZkpBin) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + + ZkpBinTest(&sec, &pub, sheEncWithZkpBinG1, sheDecG1, sheVerifyZkpBinG1); + ZkpBinTest(&sec, &pub, sheEncWithZkpBinG2, sheDecG2, sheVerifyZkpBinG2); + + shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate(); + CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0); + + ZkpBinTest(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinG1, sheDecG1, shePrecomputedPublicKeyVerifyZkpBinG1); + ZkpBinTest(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinG2, sheDecG2, shePrecomputedPublicKeyVerifyZkpBinG2); + + shePrecomputedPublicKeyDestroy(ppub); +} + +template +void ZkpBinEqTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, verifyFunc verify) +{ + sheCipherTextG1 c1; + sheCipherTextG2 c2; + sheZkpBinEq zkp; + for (int m = 0; m < 2; m++) { + CYBOZU_TEST_EQUAL(encWithZkp(&c1, &c2, &zkp, pub, m), 0); + mclInt mDec = -1; + CYBOZU_TEST_EQUAL(sheDecG1(&mDec, sec, &c1), 0); + CYBOZU_TEST_EQUAL(mDec, m); + mDec = -1; + CYBOZU_TEST_EQUAL(sheDecG2(&mDec, sec, &c2), 0); + CYBOZU_TEST_EQUAL(mDec, m); + CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 1); + { + char buf[2048]; + size_t n = sheZkpBinEqSerialize(buf, sizeof(buf), &zkp); + CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * CYBOZU_NUM_OF_ARRAY(zkp.d)); + sheZkpBinEq zkp2; + size_t r = sheZkpBinEqDeserialize(&zkp2, buf, n); + CYBOZU_TEST_EQUAL(r, n); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(zkp.d); i++) { + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&zkp.d[i], &zkp2.d[i])); + } + } + zkp.d[0].d[0]++; + CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 0); + } + CYBOZU_TEST_ASSERT(encWithZkp(&c1, &c2, &zkp, pub, 2) != 0); +} + +CYBOZU_TEST_AUTO(ZkpBinEq) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + + ZkpBinEqTest(&sec, &pub, sheEncWithZkpBinEq, sheVerifyZkpBinEq); + + shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate(); + CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0); + + ZkpBinEqTest(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinEq, shePrecomputedPublicKeyVerifyZkpBinEq); + + shePrecomputedPublicKeyDestroy(ppub); +} + +template +void ZkpEqTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, verifyFunc verify) +{ + sheCipherTextG1 c1; + sheCipherTextG2 c2; + sheZkpEq zkp; + for (int m = -5; m < 5; m++) { + CYBOZU_TEST_EQUAL(encWithZkp(&c1, &c2, &zkp, pub, m), 0); + mclInt mDec = -1; + CYBOZU_TEST_EQUAL(sheDecG1(&mDec, sec, &c1), 0); + CYBOZU_TEST_EQUAL(mDec, m); + mDec = -1; + CYBOZU_TEST_EQUAL(sheDecG2(&mDec, sec, &c2), 0); + CYBOZU_TEST_EQUAL(mDec, m); + CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 1); + { + char buf[2048]; + size_t n = sheZkpEqSerialize(buf, sizeof(buf), &zkp); + CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * CYBOZU_NUM_OF_ARRAY(zkp.d)); + sheZkpEq zkp2; + size_t r = sheZkpEqDeserialize(&zkp2, buf, n); + CYBOZU_TEST_EQUAL(r, n); + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(zkp.d); i++) { + CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&zkp.d[i], &zkp2.d[i])); + } + } + zkp.d[0].d[0]++; + CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 0); + } +} + +CYBOZU_TEST_AUTO(ZkpEq) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + + ZkpEqTest(&sec, &pub, sheEncWithZkpEq, sheVerifyZkpEq); + + shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate(); + CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0); + + ZkpEqTest(&sec, ppub, shePrecomputedPublicKeyEncWithZkpEq, shePrecomputedPublicKeyVerifyZkpEq); + + shePrecomputedPublicKeyDestroy(ppub); +} + +CYBOZU_TEST_AUTO(finalExp) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + const int64_t m11 = 5; + const int64_t m12 = 7; + const int64_t m21 = -3; + const int64_t m22 = 9; + sheCipherTextG1 c11, c12; + sheCipherTextG2 c21, c22; + sheCipherTextGT ct1, ct2; + sheCipherTextGT ct; + sheEncG1(&c11, &pub, m11); + sheEncG1(&c12, &pub, m12); + sheEncG2(&c21, &pub, m21); + sheEncG2(&c22, &pub, m22); + + int64_t dec; + // sheMul = sheMulML + sheFinalExpGT + sheMul(&ct1, &c11, &c21); + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct1), 0); + CYBOZU_TEST_EQUAL(dec, m11 * m21); + + sheMulML(&ct1, &c11, &c21); + sheFinalExpGT(&ct, &ct1); + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); + CYBOZU_TEST_EQUAL(dec, m11 * m21); + + sheMulML(&ct2, &c12, &c22); + sheFinalExpGT(&ct, &ct2); + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); + CYBOZU_TEST_EQUAL(dec, m12 * m22); + + /* + Mul(c11, c21) + Mul(c21, c22) + = finalExp(ML(c11, c21) + ML(c21, c22)) + */ + sheAddGT(&ct, &ct1, &ct2); + sheFinalExpGT(&ct, &ct); + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); + CYBOZU_TEST_EQUAL(dec, (m11 * m21) + (m12 * m22)); +} + +int g_hashBitSize = 8; +std::string g_tableName; + +CYBOZU_TEST_AUTO(saveLoad) +{ + sheSecretKey sec; + sheSecretKeySetByCSPRNG(&sec); + shePublicKey pub; + sheGetPublicKey(&pub, &sec); + const size_t hashSize = 1 << g_hashBitSize; + const size_t byteSizePerEntry = 8; + sheSetRangeForGTDLP(hashSize); + std::string buf; + buf.resize(hashSize * byteSizePerEntry + 1024); + const size_t n1 = sheSaveTableForGTDLP(&buf[0], buf.size()); + CYBOZU_TEST_ASSERT(n1 > 0); + if (!g_tableName.empty()) { + printf("use table=%s\n", g_tableName.c_str()); + std::ofstream ofs(g_tableName.c_str(), std::ios::binary); + ofs.write(buf.c_str(), n1); + } + const int64_t m = hashSize - 1; + sheCipherTextGT ct; + CYBOZU_TEST_ASSERT(sheEncGT(&ct, &pub, m) == 0); + sheSetRangeForGTDLP(1); + sheSetTryNum(1); + int64_t dec = 0; + CYBOZU_TEST_ASSERT(sheDecGT(&dec, &sec, &ct) != 0); + if (!g_tableName.empty()) { + std::ifstream ifs(g_tableName.c_str(), std::ios::binary); + buf.clear(); + buf.resize(n1); + ifs.read(&buf[0], n1); + } + const size_t n2 = sheLoadTableForGTDLP(&buf[0], n1); + CYBOZU_TEST_ASSERT(n2 > 0); + CYBOZU_TEST_ASSERT(sheDecGT(&dec, &sec, &ct) == 0); + CYBOZU_TEST_EQUAL(dec, m); +} + +int main(int argc, char *argv[]) + try +{ + cybozu::Option opt; + opt.appendOpt(&g_hashBitSize, 8, "bit", ": hashBitSize"); + opt.appendOpt(&g_tableName, "", "f", ": table name"); + opt.appendHelp("h", ": show this message"); + if (!opt.parse(argc, argv)) { + opt.usage(); + return 1; + } + return cybozu::test::autoRun.run(argc, argv); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/she_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/she_test.cpp new file mode 100644 index 000000000..9292c35f4 --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/she_test.cpp @@ -0,0 +1,756 @@ +#define PUT(x) std::cout << #x << "=" << (x) << std::endl; +#include +#include +#include +#include +#include +#include +#include // for secp192k1 + +using namespace mcl::she; + +SecretKey g_sec; + +CYBOZU_TEST_AUTO(log) +{ +#if MCLBN_FP_UNIT_SIZE == 4 + const mcl::CurveParam& cp = mcl::BN254; + puts("BN254"); +#elif MCLBN_FP_UNIT_SIZE == 6 + const mcl::CurveParam& cp = mcl::BN381_1; + puts("BN381_1"); +#elif MCLBN_FP_UNIT_SIZE == 8 + const mcl::CurveParam& cp = mcl::BN462; + puts("BN462"); +#endif + init(cp); + G1 P; + hashAndMapToG1(P, "abc"); + for (int i = -5; i < 5; i++) { + G1 iP; + G1::mul(iP, P, i); + CYBOZU_TEST_EQUAL(mcl::she::local::log(P, iP), i); + } +} + +//#define PAPER +#ifdef PAPER +double clk2msec(const cybozu::CpuClock& clk, int n) +{ + const double rate = (1 / 3.4e9) * 1.e3; // 3.4GHz + return clk.getClock() / (double)clk.getCount() / n * rate; +} + +CYBOZU_TEST_AUTO(bench2) +{ + puts("msec"); + setTryNum(1 << 16); + useDecG1ViaGT(true); + useDecG2ViaGT(true); +#if 0 + setRangeForDLP(1 << 21); +#else + { + const char *tblName = "../she-dlp-table/she-dlp-0-20-gt.bin"; + std::ifstream ifs(tblName, std::ios::binary); + getHashTableGT().load(ifs); + } +#endif + SecretKey sec; + sec.setByCSPRNG(); + PublicKey pub; + sec.getPublicKey(pub); + PrecomputedPublicKey ppub; + ppub.init(pub); + const int C = 500; + double t1, t2; + int64_t m = (1ll << 31) - 12345; + CipherTextG1 c1, d1; + CipherTextG2 c2, d2; + CipherTextGT ct, dt; + CYBOZU_BENCH_C("", C, ppub.enc, c1, m); + t1 = clk2msec(cybozu::bench::g_clk, C); + CYBOZU_TEST_EQUAL(sec.dec(c1), m); + + CYBOZU_BENCH_C("", C, ppub.enc, c2, m); + t2 = clk2msec(cybozu::bench::g_clk, C); + CYBOZU_TEST_EQUAL(sec.dec(c2), m); + printf("Enc G1 %.2e\n", t1); + printf("Enc G2 %.2e\n", t2); + printf("Enc L1(G1+G2) %.2e\n", t1 + t2); + + CYBOZU_BENCH_C("", C, ppub.enc, ct, m); + t1 = clk2msec(cybozu::bench::g_clk, C); + CYBOZU_TEST_EQUAL(sec.dec(ct), m); + printf("Enc L2 %.2e\n", t1); + + CYBOZU_BENCH_C("", C, sec.dec, c1); + t1 = clk2msec(cybozu::bench::g_clk, C); + printf("Dec L1 %.2e\n", t1); + + CYBOZU_BENCH_C("", C, sec.dec, ct); + t1 = clk2msec(cybozu::bench::g_clk, C); + printf("Dec L2 %.2e\n", t1); + + pub.enc(ct, 1234); + CYBOZU_BENCH_C("", C, sec.dec, ct); + t1 = clk2msec(cybozu::bench::g_clk, C); + printf("Dec L2(small) %.2e\n", t1); + + CYBOZU_BENCH_C("", C, add, d1, d1, c1); + t1 = clk2msec(cybozu::bench::g_clk, C); + + CYBOZU_BENCH_C("", C, add, d2, d2, c2); + t2 = clk2msec(cybozu::bench::g_clk, C); + printf("Add G1 %.2e\n", t1); + printf("Add G2 %.2e\n", t2); + printf("Add L1(G1+G2) %.2e\n", t1 + t2); + + CYBOZU_BENCH_C("", C, add, dt, dt, ct); + t1 = clk2msec(cybozu::bench::g_clk, C); + printf("Add L2 %.2e\n", t1); + + CYBOZU_BENCH_C("", C, mul, ct, c1, c2); + t1 = clk2msec(cybozu::bench::g_clk, C); + printf("Mul %.2e\n", t1); + + CYBOZU_BENCH_C("", C, ppub.reRand, c1); + t1 = clk2msec(cybozu::bench::g_clk, C); + CYBOZU_BENCH_C("", C, ppub.reRand, c2); + t2 = clk2msec(cybozu::bench::g_clk, C); + printf("ReRand G1 %.2e\n", t1); + printf("ReRand G2 %.2e\n", t2); + printf("ReRand L1(G1+G2) %.2e\n", t1 + t2); + + CYBOZU_BENCH_C("", C, ppub.reRand, ct); + t1 = clk2msec(cybozu::bench::g_clk, C); + printf("ReRand L2 %.2e\n", t1); +} +#endif + +template +void GAHashTableTest(int maxSize, int tryNum, const G& P, const HashTbl& hashTbl) +{ + for (int i = -maxSize; i <= maxSize; i++) { + G xP; + G::mul(xP, P, i); + CYBOZU_TEST_EQUAL(hashTbl.basicLog(xP), i); + } + for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) { + G xP; + G::mul(xP, P, i); + CYBOZU_TEST_EQUAL(hashTbl.log(xP), i); + } +} + +template +void HashTableTest(const G& P) +{ + mcl::she::local::HashTable hashTbl, hashTbl2; + const int maxSize = 100; + const int tryNum = 3; + hashTbl.init(P, maxSize, tryNum); + GAHashTableTest(maxSize, tryNum, P, hashTbl); + std::stringstream ss; + hashTbl.save(ss); + hashTbl2.load(ss); + GAHashTableTest(maxSize, tryNum, P, hashTbl2); +} + +CYBOZU_TEST_AUTO(HashTable) +{ + G1 P; + hashAndMapToG1(P, "abc"); + G2 Q; + hashAndMapToG2(Q, "abc"); + HashTableTest(P); + HashTableTest(Q); +} + +template +void GTHashTableTest(int maxSize, int tryNum, const GT& g, const HashTbl& hashTbl) +{ + for (int i = -maxSize; i <= maxSize; i++) { + GT gx; + GT::pow(gx, g, i); + CYBOZU_TEST_EQUAL(hashTbl.basicLog(gx), i); + } + for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) { + GT gx; + GT::pow(gx, g, i); + CYBOZU_TEST_EQUAL(hashTbl.log(gx), i); + } +} + +CYBOZU_TEST_AUTO(GTHashTable) +{ + mcl::she::local::HashTable hashTbl, hashTbl2; + GT g; + { + G1 P; + hashAndMapToG1(P, "abc"); + G2 Q; + hashAndMapToG2(Q, "abc"); + pairing(g, P, Q); + } + const int maxSize = 100; + const int tryNum = 3; + hashTbl.init(g, maxSize, tryNum); + GTHashTableTest(maxSize, tryNum, g, hashTbl); + std::stringstream ss; + hashTbl.save(ss); + hashTbl2.load(ss); + GTHashTableTest(maxSize, tryNum, g, hashTbl2); +} + +CYBOZU_TEST_AUTO(enc_dec) +{ + SecretKey& sec = g_sec; + sec.setByCSPRNG(); + setRangeForDLP(1024); + PublicKey pub; + sec.getPublicKey(pub); + CipherText c; + for (int i = -5; i < 5; i++) { + pub.enc(c, i); + CYBOZU_TEST_EQUAL(sec.dec(c), i); + pub.reRand(c); + CYBOZU_TEST_EQUAL(sec.dec(c), i); + } + PrecomputedPublicKey ppub; + ppub.init(pub); + CipherTextG1 c1; + CipherTextG2 c2; + CipherTextGT ct1, ct2; + for (int i = -5; i < 5; i++) { + pub.enc(ct1, i); + CYBOZU_TEST_EQUAL(sec.dec(ct1), i); + CYBOZU_TEST_EQUAL(sec.isZero(ct1), i == 0); + ppub.enc(ct2, i); + CYBOZU_TEST_EQUAL(sec.dec(ct2), i); + ppub.enc(c1, i); + CYBOZU_TEST_EQUAL(sec.dec(c1), i); + CYBOZU_TEST_EQUAL(sec.decViaGT(c1), i); + CYBOZU_TEST_EQUAL(sec.isZero(c1), i == 0); + ct1.clear(); + pub.convert(ct1, c1); + CYBOZU_TEST_EQUAL(sec.dec(ct1), i); + ppub.enc(c2, i); + CYBOZU_TEST_EQUAL(sec.dec(c2), i); + CYBOZU_TEST_EQUAL(sec.decViaGT(c2), i); + CYBOZU_TEST_EQUAL(sec.isZero(c2), i == 0); + ct1.clear(); + pub.convert(ct1, c2); + CYBOZU_TEST_EQUAL(sec.dec(ct1), i); + pub.enc(c, i); + CYBOZU_TEST_EQUAL(sec.isZero(c), i == 0); + } +} + +template +void ZkpBinTest(const SecretKey& sec, const PK& pub) +{ + CT c; + ZkpBin zkp; + for (int m = 0; m < 2; m++) { + pub.encWithZkpBin(c, zkp, m); + CYBOZU_TEST_EQUAL(sec.dec(c), m); + CYBOZU_TEST_ASSERT(pub.verify(c, zkp)); + zkp.d_[0] += 1; + CYBOZU_TEST_ASSERT(!pub.verify(c, zkp)); + } + CYBOZU_TEST_EXCEPTION(pub.encWithZkpBin(c, zkp, 2), cybozu::Exception); +} +CYBOZU_TEST_AUTO(ZkpBin) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + ZkpBinTest(sec, pub); + ZkpBinTest(sec, pub); + + PrecomputedPublicKey ppub; + ppub.init(pub); + ZkpBinTest(sec, ppub); + ZkpBinTest(sec, ppub); +} + +template +void ZkpEqTest(const SecretKey& sec, const PubT& pub) +{ + CipherTextG1 c1; + CipherTextG2 c2; + ZkpEq zkp; + for (int m = -4; m < 4; m++) { + pub.encWithZkpEq(c1, c2, zkp, m); + CYBOZU_TEST_EQUAL(sec.dec(c1), m); + CYBOZU_TEST_EQUAL(sec.dec(c2), m); + CYBOZU_TEST_ASSERT(pub.verify(c1, c2, zkp)); + zkp.d_[0] += 1; + CYBOZU_TEST_ASSERT(!pub.verify(c1, c2, zkp)); + } +} + +CYBOZU_TEST_AUTO(ZkpEq) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + PrecomputedPublicKey ppub; + ppub.init(pub); + ZkpEqTest(sec, pub); + ZkpEqTest(sec, ppub); +} + +template +void ZkpBinEqTest(const SecretKey& sec, const PK& pub) +{ + CipherTextG1 c1; + CipherTextG2 c2; + ZkpBinEq zkp; + for (int m = 0; m < 2; m++) { + pub.encWithZkpBinEq(c1, c2, zkp, m); + CYBOZU_TEST_EQUAL(sec.dec(c1), m); + CYBOZU_TEST_EQUAL(sec.dec(c2), m); + CYBOZU_TEST_ASSERT(pub.verify(c1, c2, zkp)); + zkp.d_[0] += 1; + CYBOZU_TEST_ASSERT(!pub.verify(c1, c2, zkp)); + } + CYBOZU_TEST_EXCEPTION(pub.encWithZkpBinEq(c1, c2, zkp, 2), cybozu::Exception); +} + +CYBOZU_TEST_AUTO(ZkpBinEq) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + ZkpBinEqTest(sec, pub); + + PrecomputedPublicKey ppub; + ppub.init(pub); + ZkpBinEqTest(sec, ppub); +} + +CYBOZU_TEST_AUTO(add_sub_mul) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + for (int m1 = -5; m1 < 5; m1++) { + for (int m2 = -5; m2 < 5; m2++) { + CipherText c1, c2, c3; + pub.enc(c1, m1); + pub.enc(c2, m2); + add(c3, c1, c2); + CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3)); + + pub.reRand(c3); + CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3)); + + sub(c3, c1, c2); + CYBOZU_TEST_EQUAL(m1 - m2, sec.dec(c3)); + + mul(c3, c1, 5); + CYBOZU_TEST_EQUAL(m1 * 5, sec.dec(c3)); + mul(c3, c1, -123); + CYBOZU_TEST_EQUAL(m1 * -123, sec.dec(c3)); + + mul(c3, c1, c2); + CYBOZU_TEST_EQUAL(m1 * m2, sec.dec(c3)); + + pub.reRand(c3); + CYBOZU_TEST_EQUAL(m1 * m2, sec.dec(c3)); + + CipherText::mul(c3, c3, -25); + CYBOZU_TEST_EQUAL(m1 * m2 * -25, sec.dec(c3)); + + pub.enc(c1, m1, true); + CYBOZU_TEST_EQUAL(m1, sec.dec(c1)); + pub.enc(c2, m2, true); + add(c3, c1, c2); + CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3)); + } + } +} + +CYBOZU_TEST_AUTO(largeEnc) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + + Fr x; + x.setRand(); + CipherTextG1 c1, c2; + pub.enc(c1, x); + const int64_t m = 123; + pub.enc(c2, x + m); + sub(c1, c1, c2); + CYBOZU_TEST_EQUAL(sec.dec(c1), -m); + + pub.enc(c1, 0); + mul(c1, c1, x); + CYBOZU_TEST_ASSERT(sec.isZero(c1)); + pub.enc(c1, 1); + mul(c1, c1, x); + CYBOZU_TEST_ASSERT(!sec.isZero(c1)); +} + +CYBOZU_TEST_AUTO(add_mul_add_sub) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + int m[8] = { 1, -2, 3, 4, -5, 6, -7, 8 }; + CipherText c[8]; + for (int i = 0; i < 8; i++) { + pub.enc(c[i], m[i]); + CYBOZU_TEST_EQUAL(sec.dec(c[i]), m[i]); + CYBOZU_TEST_ASSERT(!c[i].isMultiplied()); + CipherText mc; + pub.convert(mc, c[i]); + CYBOZU_TEST_ASSERT(mc.isMultiplied()); + CYBOZU_TEST_EQUAL(sec.dec(mc), m[i]); + } + int ok1 = (m[0] + m[1]) * (m[2] + m[3]); + int ok2 = (m[4] + m[5]) * (m[6] + m[7]); + int ok = ok1 + ok2; + for (int i = 0; i < 4; i++) { + c[i * 2].add(c[i * 2 + 1]); + CYBOZU_TEST_EQUAL(sec.dec(c[i * 2]), m[i * 2] + m[i * 2 + 1]); + } + c[0].mul(c[2]); + CYBOZU_TEST_EQUAL(sec.dec(c[0]), ok1); + c[4].mul(c[6]); + CYBOZU_TEST_EQUAL(sec.dec(c[4]), ok2); + c[0].add(c[4]); + CYBOZU_TEST_EQUAL(sec.dec(c[0]), ok); + c[0].sub(c[4]); + CYBOZU_TEST_EQUAL(sec.dec(c[0]), ok1); +} + +CYBOZU_TEST_AUTO(finalExp) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + const int64_t m11 = 5; + const int64_t m12 = 3; + const int64_t m21 = -2; + const int64_t m22 = 9; + CipherTextG1 c11, c12; + CipherTextG2 c21, c22; + CipherTextGT ct1, ct2, ct; + pub.enc(c11, m11); + pub.enc(c12, m12); + pub.enc(c21, m21); + pub.enc(c22, m22); + CipherTextGT::mulML(ct1, c11, c21); + CipherTextGT::finalExp(ct, ct1); + CYBOZU_TEST_EQUAL(sec.dec(ct), m11 * m21); + CipherTextGT::mulML(ct2, c12, c22); + CipherTextGT::finalExp(ct, ct2); + CYBOZU_TEST_EQUAL(sec.dec(ct), m12 * m22); + CipherTextGT::add(ct1, ct1, ct2); + CipherTextGT::finalExp(ct1, ct1); + CYBOZU_TEST_EQUAL(sec.dec(ct1), (m11 * m21) + (m12 * m22)); +} + +CYBOZU_TEST_AUTO(innerProduct) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + + cybozu::XorShift rg; + const size_t n = 1000; + std::vector v1, v2; + std::vector c1, c2; + v1.resize(n); + v2.resize(n); + c1.resize(n); + c2.resize(n); + int innerProduct = 0; + for (size_t i = 0; i < n; i++) { + v1[i] = rg() % 2; + v2[i] = rg() % 2; + innerProduct += v1[i] * v2[i]; + pub.enc(c1[i], v1[i]); + pub.enc(c2[i], v2[i]); + } + CipherText c, t; + CipherText::mul(c, c1[0], c2[0]); + for (size_t i = 1; i < n; i++) { + CipherText::mul(t, c1[i], c2[i]); + c.add(t); + } + CYBOZU_TEST_EQUAL(innerProduct, sec.dec(c)); +} + +template +T testIo(const T& x) +{ + std::stringstream ss; + ss << x; + T y; + ss >> y; + CYBOZU_TEST_EQUAL(x, y); + return y; +} + +CYBOZU_TEST_AUTO(io) +{ + setRangeForDLP(100); + int64_t m; + for (int i = 0; i < 2; i++) { + if (i == 1) { + Fp::setIoMode(mcl::IoSerialize); + G1::setIoMode(mcl::IoSerialize); + } + SecretKey sec; + sec.setByCSPRNG(); + testIo(sec); + PublicKey pub; + sec.getPublicKey(pub); + testIo(pub); + CipherTextG1 g1; + pub.enc(g1, 3); + m = sec.dec(testIo(g1)); + CYBOZU_TEST_EQUAL(m, 3); + CipherTextG2 g2; + pub.enc(g2, 5); + testIo(g2); + CipherTextA ca; + pub.enc(ca, -4); + m = sec.dec(testIo(ca)); + CYBOZU_TEST_EQUAL(m, -4); + CipherTextGT ct; + CipherTextGT::mul(ct, g1, g2); + m = sec.dec(testIo(ct)); + CYBOZU_TEST_EQUAL(m, 15); + } +} + +#ifndef PAPER +CYBOZU_TEST_AUTO(bench) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + CipherText c1, c2, c3; + CYBOZU_BENCH("enc", pub.enc, c1, 5); + pub.enc(c2, 4); + CYBOZU_BENCH("add", c1.add, c2); + CYBOZU_BENCH("mul", CipherText::mul, c3, c1, c2); + pub.enc(c1, 5); + pub.enc(c2, 4); + c1.mul(c2); + CYBOZU_BENCH("dec", sec.dec, c1); + c2 = c1; + CYBOZU_BENCH("add after mul", c1.add, c2); +} +#endif + +CYBOZU_TEST_AUTO(saveHash) +{ + mcl::she::local::HashTable hashTbl1, hashTbl2; + hashTbl1.init(SHE::P_, 1234, 123); + std::stringstream ss; + hashTbl1.save(ss); + hashTbl2.load(ss); + CYBOZU_TEST_ASSERT(hashTbl1 == hashTbl2); +} + +static inline void putK(double t) { printf("%.2e\n", t * 1e-3); } + +template +void decBench(const char *msg, int C, const SecretKey& sec, const PublicKey& pub, int64_t (SecretKey::*dec)(const CT& c) const = &SecretKey::dec) +{ + int64_t begin = 1 << 20; + int64_t end = 1LL << 32; + while (begin < end) { + CT c; + int64_t x = begin - 1; + pub.enc(c, x); + printf("m=%08x ", (uint32_t)x); + CYBOZU_BENCH_C(msg, C, (sec.*dec), c); + CYBOZU_TEST_EQUAL((sec.*dec)(c), x); + begin *= 2; + } + int64_t mTbl[] = { -0x80000003ll, 0x80000000ll, 0x80000005ll }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(mTbl); i++) { + int64_t m = mTbl[i]; + CT c; + pub.enc(c, m); + CYBOZU_TEST_EQUAL((sec.*dec)(c), m); + } +} + +#ifndef PAPER +CYBOZU_TEST_AUTO(hashBench) +{ + SecretKey& sec = g_sec; + sec.setByCSPRNG(); + const int C = 500; + const size_t hashSize = 1u << 21; + + clock_t begin = clock(), end; + setRangeForG1DLP(hashSize); + end = clock(); + printf("init G1 DLP %f\n", double(end - begin) / CLOCKS_PER_SEC); + begin = end; + setRangeForG2DLP(hashSize); + end = clock(); + printf("init G2 DLP %f\n", double(end - begin) / CLOCKS_PER_SEC); + begin = end; + setRangeForGTDLP(hashSize); + end = clock(); + printf("init GT DLP %f\n", double(end - begin) / CLOCKS_PER_SEC); + + PublicKey pub; + sec.getPublicKey(pub); + PrecomputedPublicKey ppub; + ppub.init(pub); + puts("Kclk"); + cybozu::bench::setPutCallback(putK); + decBench("decG1", C, sec, pub); + puts(""); + decBench("decG2", C, sec, pub); + puts(""); + decBench("decGT", C, sec, pub); + puts(""); + decBench("decG1ViaGT", C, sec, pub, &SecretKey::decViaGT); + puts(""); + decBench("decG2ViaGT", C, sec, pub, &SecretKey::decViaGT); + + G1 P, P2; + G2 Q, Q2; + GT e, e2; + mpz_class mr; + { + Fr r; + r.setRand(); + mr = r.getMpz(); + } + hashAndMapToG1(P, "abc"); + hashAndMapToG2(Q, "abc"); + pairing(e, P, Q); + P2.clear(); + Q2.clear(); + e2 = 1; + + printf("large m\n"); + CYBOZU_BENCH_C("G1::add ", C, G1::add, P2, P2, P); + CYBOZU_BENCH_C("G1::mul ", C, G1::mul, P, P, mr); + CYBOZU_BENCH_C("G2::add ", C, G2::add, Q2, Q2, Q); + CYBOZU_BENCH_C("G2::mul ", C, G2::mul, Q, Q, mr); + CYBOZU_BENCH_C("GT::mul ", C, GT::mul, e2, e2, e); + CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e, e, mr); + CYBOZU_BENCH_C("G1window", C, SHE::PhashTbl_.mulByWindowMethod, P2, mr); + CYBOZU_BENCH_C("G2window", C, SHE::QhashTbl_.mulByWindowMethod, Q2, mr); + CYBOZU_BENCH_C("GTwindow", C, SHE::ePQhashTbl_.mulByWindowMethod, e, mr); +#if 1 + typedef mcl::GroupMtoA AG; + mcl::fp::WindowMethod wm; + wm.init(static_cast(e), Fr::getBitSize(), 10); + for (int i = 0; i < 100; i++) { + GT t1, t2; + GT::pow(t1, e, i); + wm.mul(static_cast(t2), i); + CYBOZU_TEST_EQUAL(t1, t2); + } +// CYBOZU_BENCH_C("GTwindow", C, wm.mul, static_cast(e), mr); +#endif + + CYBOZU_BENCH_C("miller ", C, millerLoop, e, P, Q); + CYBOZU_BENCH_C("finalExp", C, finalExp, e, e); + CYBOZU_BENCH_C("precomML", C, precomputedMillerLoop, e, P, SHE::Qcoeff_); + + CipherTextG1 c1; + CipherTextG2 c2; + CipherTextGT ct; + + int m = int(hashSize - 1); + printf("small m = %d\n", m); + CYBOZU_BENCH_C("G1::mul ", C, G1::mul, P, P, m); + CYBOZU_BENCH_C("G2::mul ", C, G2::mul, Q, Q, m); + CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e, e, m); + CYBOZU_BENCH_C("G1window", C, SHE::PhashTbl_.mulByWindowMethod, P2, m); + CYBOZU_BENCH_C("G2window", C, SHE::QhashTbl_.mulByWindowMethod, Q2, m); + CYBOZU_BENCH_C("GTwindow", C, SHE::ePQhashTbl_.mulByWindowMethod, e, m); +// CYBOZU_BENCH_C("GTwindow", C, wm.mul, static_cast(e), m); + + CYBOZU_BENCH_C("encG1 ", C, pub.enc, c1, m); + CYBOZU_BENCH_C("encG2 ", C, pub.enc, c2, m); + CYBOZU_BENCH_C("encGT ", C, pub.enc, ct, m); + CYBOZU_BENCH_C("encG1pre", C, ppub.enc, c1, m); + CYBOZU_BENCH_C("encG2pre", C, ppub.enc, c2, m); + CYBOZU_BENCH_C("encGTpre", C, ppub.enc, ct, m); + + CYBOZU_BENCH_C("decG1 ", C, sec.dec, c1); + CYBOZU_BENCH_C("decG2 ", C, sec.dec, c2); + CYBOZU_BENCH_C("degGT ", C, sec.dec, ct); + + CYBOZU_BENCH_C("CT:mul ", C, CipherTextGT::mul, ct, c1, c2); + CYBOZU_BENCH_C("CT:mulML", C, CipherTextGT::mulML, ct, c1, c2); + CYBOZU_BENCH_C("CT:finalExp", C, CipherTextGT::finalExp, ct, ct); + + CYBOZU_BENCH_C("addG1 ", C, CipherTextG1::add, c1, c1, c1); + CYBOZU_BENCH_C("addG2 ", C, CipherTextG2::add, c2, c2, c2); + CYBOZU_BENCH_C("addGT ", C, CipherTextGT::add, ct, ct, ct); + CYBOZU_BENCH_C("reRandG1", C, pub.reRand, c1); + CYBOZU_BENCH_C("reRandG2", C, pub.reRand, c2); + CYBOZU_BENCH_C("reRandGT", C, pub.reRand, ct); + CYBOZU_BENCH_C("reRandG1pre", C, ppub.reRand, c1); + CYBOZU_BENCH_C("reRandG2pre", C, ppub.reRand, c2); + CYBOZU_BENCH_C("reRandGTpre", C, ppub.reRand, ct); + CYBOZU_BENCH_C("mulG1 ", C, CipherTextG1::mul, c1, c1, m); + CYBOZU_BENCH_C("mulG2 ", C, CipherTextG2::mul, c2, c2, m); + CYBOZU_BENCH_C("mulGT ", C, CipherTextGT::mul, ct, ct, m); + + CYBOZU_BENCH_C("convG1toGT", C, pub.convert, ct, c1); + CYBOZU_BENCH_C("convG2toGT", C, pub.convert, ct, c2); +} +#endif + +CYBOZU_TEST_AUTO(liftedElGamal) +{ + const size_t hashSize = 1024; + initG1only(mcl::ecparam::secp192k1, hashSize); + const size_t byteSize = 192 / 8; + SecretKey sec; + sec.setByCSPRNG(); + PublicKey pub; + sec.getPublicKey(pub); + CipherTextG1 c1, c2, c3; + int m1 = 12, m2 = 34; + pub.enc(c1, m1); + pub.enc(c2, m2); + CYBOZU_TEST_EQUAL(sec.dec(c1), m1); + CYBOZU_TEST_EQUAL(sec.dec(c2), m2); + add(c3, c1, c2); + CYBOZU_TEST_EQUAL(sec.dec(c3), m1 + m2); + neg(c1, c2); + CYBOZU_TEST_EQUAL(sec.dec(c1), -m2); + mul(c1, c2, m1); + CYBOZU_TEST_EQUAL(sec.dec(c1), m2 * m1); + + char buf[1024]; + size_t n = sec.serialize(buf, sizeof(buf)); + CYBOZU_TEST_EQUAL(n, byteSize); + SecretKey sec2; + n = sec2.deserialize(buf, n); + CYBOZU_TEST_EQUAL(n, byteSize); + CYBOZU_TEST_EQUAL(sec, sec2); + + n = pub.serialize(buf, sizeof(buf)); + CYBOZU_TEST_EQUAL(n, byteSize + 1); // +1 is for sign of y + PublicKey pub2; + n = pub2.deserialize(buf, n); + CYBOZU_TEST_EQUAL(n, byteSize + 1); + CYBOZU_TEST_EQUAL(pub, pub2); + + PublicKey pub3; + sec2.getPublicKey(pub3); + CYBOZU_TEST_EQUAL(pub, pub3); +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/sq_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/sq_test.cpp new file mode 100644 index 000000000..4c386d23b --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/sq_test.cpp @@ -0,0 +1,21 @@ +#include +#include +#include + +CYBOZU_TEST_AUTO(sqrt) +{ + const int tbl[] = { 3, 5, 7, 11, 13, 17, 19, 257, 997, 1031 }; + mcl::SquareRoot sq; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const mpz_class p = tbl[i]; + sq.set(p); + for (mpz_class a = 0; a < p; a++) { + mpz_class x; + if (sq.get(x, a)) { + mpz_class y; + y = (x * x) % p; + CYBOZU_TEST_EQUAL(a, y); + } + } + } +} diff --git a/vendor/github.com/dexon-foundation/mcl/test/vint_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/vint_test.cpp new file mode 100644 index 000000000..15e14266a --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/vint_test.cpp @@ -0,0 +1,1353 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef DONT_USE_GMP_IN_TEST +#include +#endif + +#define PUT(x) std::cout << #x "=" << x << std::endl; + +#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST) + #define MCL_AVOID_EXCEPTION_TEST +#endif + +using namespace mcl; + +struct V { + int n; + unsigned int p[16]; +}; + +CYBOZU_TEST_AUTO(addSub) +{ + static const struct { + V a; + V b; + V c; + } tbl[] = { + { + { 1, { 123, } }, + { 1, { 456, } }, + { 1, { 579, } }, + }, + { + { 1, { 0xffffffff, } }, + { 1, { 3, } }, + { 2, { 2, 1 } }, + }, + { + { 3, { 0xffffffff, 1, 0xffffffff } }, + { 2, { 1, 0xfffffffe, } }, + { 4, { 0, 0, 0, 1 } }, + }, + { + { 3, { 0xffffffff, 5, 0xffffffff } }, + { 2, { 1, 0xfffffffe, } }, + { 4, { 0, 4, 0, 1 } }, + }, + { + { 3, { 0xffffffff, 5, 0xffffffff } }, + { 1, { 1, } }, + { 3, { 0, 6, 0xffffffff } }, + }, + { + { 3, { 1, 0xffffffff, 1 } }, + { 3, { 0xffffffff, 0, 1 } }, + { 3, { 0, 0, 3 } }, + }, + { + { 1, { 1 } }, + { 3, { 0xffffffff, 0xffffffff, 0xffffffff } }, + { 4, { 0, 0, 0, 1 } }, + }, + { + { 1, { 0xffffffff } }, + { 1, { 0xffffffff } }, + { 2, { 0xfffffffe, 1 } }, + }, + { + { 2, { 0xffffffff, 0xffffffff } }, + { 2, { 0xffffffff, 0xffffffff } }, + { 3, { 0xfffffffe, 0xffffffff, 1 } }, + }, + { + { 3, { 0xffffffff, 0xffffffff, 0xffffffff } }, + { 3, { 0xffffffff, 0xffffffff, 0xffffffff } }, + { 4, { 0xfffffffe, 0xffffffff, 0xffffffff, 1 } }, + }, + { + { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } }, + { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } }, + { 5, { 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 1 } }, + }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Vint x, y, z, t; + x.setArray(tbl[i].a.p, tbl[i].a.n); + y.setArray(tbl[i].b.p, tbl[i].b.n); + z.setArray(tbl[i].c.p, tbl[i].c.n); + Vint::add(t, x, y); + CYBOZU_TEST_EQUAL(t, z); + + Vint::add(t, y, x); + CYBOZU_TEST_EQUAL(t, z); + + Vint::sub(t, z, x); + CYBOZU_TEST_EQUAL(t, y); + } + { + const uint32_t in[] = { 0xffffffff, 0xffffffff }; + const uint32_t out[] = { 0xfffffffe, 0xffffffff, 1 }; + Vint x, y; + x.setArray(in, 2); + y.setArray(out, 3); + Vint::add(x, x, x); + CYBOZU_TEST_EQUAL(x, y); + Vint::sub(x, x, x); + y.clear(); + CYBOZU_TEST_EQUAL(x, y); + } + { + const uint32_t t0[] = {1, 2}; + const uint32_t t1[] = {3, 4, 5}; + const uint32_t t2[] = {4, 6, 5}; + Vint x, y, z; + z.setArray(t2, 3); + + x.setArray(t0, 2); + y.setArray(t1, 3); + Vint::add(x, x, y); + CYBOZU_TEST_EQUAL(x, z); + + x.setArray(t0, 2); + y.setArray(t1, 3); + Vint::add(x, y, x); + CYBOZU_TEST_EQUAL(x, z); + + x.setArray(t0, 2); + y.setArray(t1, 3); + Vint::add(y, x, y); + CYBOZU_TEST_EQUAL(y, z); + + x.setArray(t0, 2); + y.setArray(t1, 3); + Vint::add(y, y, x); + CYBOZU_TEST_EQUAL(y, z); + } +} + +CYBOZU_TEST_AUTO(mul1) +{ + static const struct { + V a; + int b; + V c; + } tbl[] = { + { + { 1, { 12, } }, + 5, + { 1, { 60, } }, + }, + { + { 1, { 1234567, } }, + 1, + { 1, { 1234567, } }, + }, + { + { 1, { 1234567, } }, + 89012345, + { 2, { 0x27F6EDCF, 0x63F2, } }, + }, + { + { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } }, + 0x7fffffff, + { 4, { 0x80000001, 0xffffffff, 0xffffffff, 0x7ffffffe } }, + }, + { + { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } }, + 1, + { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } }, + }, + { + { 2, { 0xffffffff, 1 } }, + 0x7fffffff, + { 2, { 0x80000001, 0xfffffffd } }, + }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Vint x, z, t; + int y; + x.setArray(tbl[i].a.p, tbl[i].a.n); + y = tbl[i].b; + z.setArray(tbl[i].c.p, tbl[i].c.n); + Vint::mul(t, x, y); + CYBOZU_TEST_EQUAL(t, z); + + Vint::mul(x, x, y); + CYBOZU_TEST_EQUAL(x, z); + } +} + +CYBOZU_TEST_AUTO(mul2) +{ + static const struct { + V a; + V b; + V c; + } tbl[] = { + { + { 1, { 12, } }, + { 1, { 5, } }, + { 1, { 60, } }, + }, + { + { 1, { 1234567, } }, + { 1, { 89012345, } }, + { 2, { 0x27F6EDCF, 0x63F2, } }, + }, + { + { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } }, + { 1, { 0xffffffff, } }, + { 4, { 0x00000001, 0xffffffff, 0xffffffff, 0xfffffffe } }, + }, + { + { 2, { 0xffffffff, 1 } }, + { 1, { 0xffffffff, } }, + { 3, { 0x00000001, 0xfffffffd, 1 } }, + }, + { + { 2, { 0xffffffff, 1 } }, + { 1, { 0xffffffff, } }, + { 3, { 0x00000001, 0xfffffffd, 1 } }, + }, + { + { 2, { 1, 1 } }, + { 2, { 1, 1 } }, + { 3, { 1, 2, 1 } }, + }, + { + { 3, { 0xffffffff, 0xffffffff, 1 } }, + { 2, { 0xffffffff, 0xffffffff } }, + { 5, { 1, 0, 0xfffffffd, 0xffffffff, 1 } }, + }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Vint x, y, z, t; + x.setArray(tbl[i].a.p, tbl[i].a.n); + y.setArray(tbl[i].b.p, tbl[i].b.n); + z.setArray(tbl[i].c.p, tbl[i].c.n); + Vint::mul(t, x, y); + CYBOZU_TEST_EQUAL(t, z); + + Vint::mul(t, y, x); + CYBOZU_TEST_EQUAL(t, z); + } + { + const uint32_t in[] = { 0xffffffff, 1 }; + const uint32_t out[] = { 1, 0xfffffffc, 3 }; + Vint x, y, z; + y.setArray(out, 3); + x.setArray(in, 2); + z = x; + Vint::mul(x, x, x); + CYBOZU_TEST_EQUAL(x, y); + + x.setArray(in, 2); + Vint::mul(x, x, z); + CYBOZU_TEST_EQUAL(x, y); + + x.setArray(in, 2); + Vint::mul(x, z, x); + CYBOZU_TEST_EQUAL(x, y); + + x.setArray(in, 2); + Vint::mul(x, z, z); + CYBOZU_TEST_EQUAL(x, y); + } + { + Vint a("285434247217355341057"); + a *= a; + CYBOZU_TEST_EQUAL(a, Vint("81472709484538325259309302444004789877249")); + } +} + +CYBOZU_TEST_AUTO(div1) +{ + static const struct { + V a; + unsigned int b; + unsigned int r; + V c; + } tbl[] = { + { + { 1, { 100, } }, + 1, 0, + { 1, { 100, } }, + }, + { + { 1, { 100, } }, + 100, 0, + { 1, { 1, } }, + }, + { + { 1, { 100, } }, + 101, 100, + { 1, { 0, } }, + }, + { + { 1, { 100, } }, + 2, 0, + { 1, { 50, } }, + }, + { + { 1, { 100, } }, + 3, 1, + { 1, { 33, } }, + }, + { + { 2, { 0xffffffff, 0xffffffff } }, + 1, 0, + { 2, { 0xffffffff, 0xffffffff, } }, + }, + { + { 2, { 0xffffffff, 0xffffffff } }, + 123, 15, + { 2, { 0x4d0214d0, 0x214d021 } }, + }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Vint x, z, t; + unsigned int b, r, u; + x.setArray(tbl[i].a.p, tbl[i].a.n); + b = tbl[i].b; + r = tbl[i].r; + z.setArray(tbl[i].c.p, tbl[i].c.n); + + u = (unsigned int)Vint::divMods1(&t, x, b); + CYBOZU_TEST_EQUAL(t, z); + CYBOZU_TEST_EQUAL(u, r); + + u = (unsigned int)Vint::divMods1(&x, x, b); + CYBOZU_TEST_EQUAL(x, z); + CYBOZU_TEST_EQUAL(u, r); + } +} + +CYBOZU_TEST_AUTO(div2) +{ + static const struct { + V x; + V y; + V q; + V r; + } tbl[] = { + { + { 1, { 100 } }, + { 1, { 3 } }, + { 1, { 33 } }, + { 1, { 1 } }, + }, + { + { 2, { 1, 1 } }, + { 2, { 0, 1 } }, + { 1, { 1 } }, + { 1, { 1 } }, + }, + { + { 2, { 0xffffffff, 0xffffffff } }, + { 2, { 0, 1 } }, + { 1, { 0xffffffff } }, + { 1, { 0xffffffff } }, + }, + { + { 2, { 0xffffffff, 0xffffffff } }, + { 2, { 0xffffffff, 1 } }, + { 1, { 0x80000000 } }, + { 1, { 0x7fffffff } }, + }, + { + { 3, { 0xffffffff, 0xffffffff, 0xffffffff } }, + { 2, { 0xffffffff, 1 } }, + { 2, { 0x40000000, 0x80000000 } }, + { 1, { 0x3fffffff } }, + }, + { + { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } }, + { 3, { 1, 0, 1 } }, + { 2, { 0xffffffff, 0xffffffff } }, + { 1, { 0 } }, + }, + { + { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } }, + { 3, { 1, 0xffffffff, 0xffffffff } }, + { 2, { 0, 1 } }, + { 2, { 0xffffffff, 0xfffffffe } }, + }, + { + { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } }, + { 3, { 1, 0, 0xffffffff } }, + { 2, { 1, 1 } }, + { 2, { 0xfffffffe, 0xfffffffe } }, + }, + { + { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 1 } }, + { 3, { 1, 0, 0xffffffff } }, + { 1, { 2 } }, + { 3, { 0xfffffffd, 0xffffffff, 1 } }, + }, + { + { 4, { 0, 0, 1, 1 } }, + { 2, { 1, 1 } }, + { 3, { 0, 0, 1 } }, + { 1, { 0 } }, + }, + { + { 3, { 5, 5, 1} }, + { 2, { 1, 2 } }, + { 1, { 0x80000002 } }, + { 1, { 0x80000003, } }, + }, + { + { 2, { 5, 5} }, + { 2, { 1, 1 } }, + { 1, { 5 } }, + { 1, { 0, } }, + }, + { + { 2, { 5, 5} }, + { 2, { 2, 1 } }, + { 1, { 4 } }, + { 1, { 0xfffffffd, } }, + }, + { + { 3, { 5, 0, 5} }, + { 3, { 2, 0, 1 } }, + { 1, { 4 } }, + { 2, { 0xfffffffd, 0xffffffff } }, + }, + { + { 2, { 4, 5 } }, + { 2, { 5, 5 } }, + { 1, { 0 } }, + { 2, { 4, 5 } }, + }, + { + { 1, { 123 } }, + { 2, { 1, 1 } }, + { 1, { 0 } }, + { 1, { 123 } }, + }, + { + { 1, { 123 } }, + { 3, { 1, 1, 1 } }, + { 1, { 0 } }, + { 1, { 123 } }, + }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Vint x, y, q, r; + x.setArray(tbl[i].x.p, tbl[i].x.n); + y.setArray(tbl[i].y.p, tbl[i].y.n); + q.setArray(tbl[i].q.p, tbl[i].q.n); + r.setArray(tbl[i].r.p, tbl[i].r.n); + + Vint qt, rt; + Vint::quotRem(&qt, rt, x, y); + CYBOZU_TEST_EQUAL(qt, q); + CYBOZU_TEST_EQUAL(rt, r); + + Vint::mul(y, y, qt); + Vint::add(y, y, rt); + CYBOZU_TEST_EQUAL(x, y); + + x.setArray(tbl[i].x.p, tbl[i].x.n); + y.setArray(tbl[i].y.p, tbl[i].y.n); + Vint::quotRem(&x, rt, x, y); + CYBOZU_TEST_EQUAL(x, q); + CYBOZU_TEST_EQUAL(rt, r); + + x.setArray(tbl[i].x.p, tbl[i].x.n); + y.setArray(tbl[i].y.p, tbl[i].y.n); + Vint::quotRem(&y, rt, x, y); + CYBOZU_TEST_EQUAL(y, q); + CYBOZU_TEST_EQUAL(rt, r); + + x.setArray(tbl[i].x.p, tbl[i].x.n); + y.setArray(tbl[i].y.p, tbl[i].y.n); + Vint::quotRem(&x, y, x, y); + CYBOZU_TEST_EQUAL(x, q); + CYBOZU_TEST_EQUAL(y, r); + + x.setArray(tbl[i].x.p, tbl[i].x.n); + y.setArray(tbl[i].y.p, tbl[i].y.n); + Vint::quotRem(&y, x, x, y); + CYBOZU_TEST_EQUAL(y, q); + CYBOZU_TEST_EQUAL(x, r); + } + { + const uint32_t in[] = { 1, 1 }; + Vint x, y, z; + x.setArray(in, 2); + Vint::quotRem(&x, y, x, x); + z = 1; + CYBOZU_TEST_EQUAL(x, z); + z.clear(); + CYBOZU_TEST_EQUAL(y, z); + + Vint::quotRem(&y, x, x, x); + z = 1; + CYBOZU_TEST_EQUAL(y, z); + z.clear(); + CYBOZU_TEST_EQUAL(x, z); + } +} + +CYBOZU_TEST_AUTO(quotRem) +{ + const struct { + const char *x; + const char *y; + const char *r; + } tbl[] = { + { + "1448106640508192452750709206294683535529268965445799785581837640324321797831381715960812126274894517677713278300997728292641936248881345120394299128611830", + "82434016654300679721217353503190038836571781811386228921167322412819029493183", + "72416512377294697540770834088766459385112079195086911762075702918882982361282" + }, + { + "97086308670107713719105336221824613370040805954034005192338040686500414395543303807941158656814978071549225072789349941064484974666540443679601226744652", + "82434016654300679721217353503190038836571781811386228921167322412819029493183", + "41854959563040430269871677548536437787164514279279911478858426970427834388586", + }, + { + "726838724295606887174238120788791626017347752989142414466410919788841485181240131619880050064495352797213258935807786970844241989010252", + "82434016654300679721217353503190038836571781811386228921167322412819029493183", + "81378967132566843036693176764684783485107373533583677681931133755003929106966", + }, + { + "85319207237201203511459960875801690195851794174784746933408178697267695525099750", + "82434016654300679721217353503190038836571781811386228921167322412819029493183", + "82434016654300679721217353503190038836571781811386228921167322412819029148528", + }, + { + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x100000000000000000000000000000000000000000000000001", + "1606938044258990275541962092341162602522202993782724115824640", + }, + { + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x1000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "34175792574734561318320347298712833833643272357332299899995954578095372295314880347335474659983360", + }, + { + "0xfffffffffffff000000000000000000000000000000000000000000000000000000000000000000", + "0x100000000000000000000000000000000000000000000000000000000000000000001", + "7558907585412001237250713901367146624661464598973016020495791084036551510708977665", + }, + { + "0xfffffffffffff000000000000000000000000000000000000000000000000000000000000000000", + "0xfffffffffffff0000000000000000000000000000000000000000000000000000000000000001", + "521481209941628322292632858916605385658190900090571826892867289394157573281830188869820088065", + }, + { + "0x1230000000000000456", + "0x1230000000000000457", + "0x1230000000000000456", + }, + { + "0x1230000000000000456", + "0x1230000000000000456", + "0", + }, + { + "0x1230000000000000456", + "0x1230000000000000455", + "1", + }, + { + "0x1230000000000000456", + "0x2000000000000000000", + "0x1230000000000000456", + }, + { + "0xffffffffffffffffffffffffffffffff", + "0x80000000000000000000000000000000", + "0x7fffffffffffffffffffffffffffffff", + }, + { + "0xffffffffffffffffffffffffffffffff", + "0x7fffffffffffffffffffffffffffffff", + "1", + }, + { + "0xffffffffffffffffffffffffffffffff", + "0x70000000000000000000000000000000", + "0x1fffffffffffffffffffffffffffffff", + }, + { + "0xffffffffffffffffffffffffffffffff", + "0x30000000000000000000000000000000", + "0x0fffffffffffffffffffffffffffffff", + }, + { + "0xffffffffffffffffffffffffffffffff", + "0x10000000000000000000000000000000", + "0x0fffffffffffffffffffffffffffffff", + }, + { + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x2523648240000001ba344d80000000086121000000000013a700000000000013", + "0x212ba4f27ffffff5a2c62effffffffcdb939ffffffffff8a15ffffffffffff8d", + }, + { + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d", + "0x212ba4f27ffffff5a2c62effffffffd00242ffffffffff9c39ffffffffffffb1", + }, + }; + mcl::Vint x, y, q, r1, r2; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + x.setStr(tbl[i].x); + y.setStr(tbl[i].y); + r1.setStr(tbl[i].r); + mcl::Vint::divMod(&q, r2, x, y); + CYBOZU_TEST_EQUAL(r1, r2); + CYBOZU_TEST_EQUAL(x, q * y + r2); + } +} + +CYBOZU_TEST_AUTO(string) +{ + const struct { + uint32_t v[5]; + size_t vn; + const char *str; + const char *hex; + const char *bin; + } tbl[] = { + { { 0 }, 0, "0", "0x0", "0b0" }, + { { 12345 }, 1, "12345", "0x3039", "0b11000000111001" }, + { { 0xffffffff }, 1, "4294967295", "0xffffffff", "0b11111111111111111111111111111111" }, + { { 0, 1 }, 2, "4294967296", "0x100000000", "0b100000000000000000000000000000000" }, + { { 0, 0, 0, 0, 1 }, 5, "340282366920938463463374607431768211456", "0x100000000000000000000000000000000", "0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }, + { { 0, 0x0b22a000, 0xe2f768a0, 0xe086b93c, 0x2cd76f }, 5, "1000000000000000000000000000000000000000000000", "0x2cd76fe086b93ce2f768a00b22a00000000000", "0b101100110101110110111111100000100001101011100100111100111000101111011101101000101000000000101100100010101000000000000000000000000000000000000000000000" }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Vint x, y; + x.setArray(tbl[i].v,tbl[i].vn); + CYBOZU_TEST_EQUAL(x.getStr(10), tbl[i].str); + char buf[1024]; + size_t n = x.getStr(buf, sizeof(buf), 10); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL(tbl[i].str, buf); + y.setStr(tbl[i].str); + CYBOZU_TEST_EQUAL(x.getStr(16), tbl[i].hex + 2); + n = x.getStr(buf, sizeof(buf), 16); + CYBOZU_TEST_ASSERT(n > 0); + CYBOZU_TEST_EQUAL(tbl[i].hex + 2, buf); + CYBOZU_TEST_EQUAL(x, y); + x = 1; + x.setStr(tbl[i].hex); + CYBOZU_TEST_EQUAL(x, y); + } +} + +CYBOZU_TEST_AUTO(shift) +{ + Vint x("123423424918471928374192874198274981274918274918274918243"); + Vint y, z; + + const size_t unitBitSize = Vint::unitBitSize; + Vint s; + // shl + for (size_t i = 1; i < 31; i++) { + Vint::shl(y, x, i); + z = x * (Vint::Unit(1) << i); + CYBOZU_TEST_EQUAL(y, z); + y = x << i; + CYBOZU_TEST_EQUAL(y, z); + y = x; + y <<= i; + CYBOZU_TEST_EQUAL(y, z); + } + for (int i = 0; i < 4; i++) { + Vint::shl(y, x, i * unitBitSize); + Vint::pow(s, Vint(2), i * unitBitSize); + z = x * s; + CYBOZU_TEST_EQUAL(y, z); + y = x << (i * unitBitSize); + CYBOZU_TEST_EQUAL(y, z); + y = x; + y <<= (i * unitBitSize); + CYBOZU_TEST_EQUAL(y, z); + } + for (int i = 0; i < 100; i++) { + y = x << i; + Vint::pow(s, Vint(2), i); + z = x * s; + CYBOZU_TEST_EQUAL(y, z); + y = x; + y <<= i; + CYBOZU_TEST_EQUAL(y, z); + } + + // shr + for (size_t i = 1; i < 31; i++) { + Vint::shr(y, x, i); + z = x / (Vint::Unit(1) << i); + CYBOZU_TEST_EQUAL(y, z); + y = x >> i; + CYBOZU_TEST_EQUAL(y, z); + y = x; + y >>= i; + CYBOZU_TEST_EQUAL(y, z); + } + for (int i = 0; i < 3; i++) { + Vint::shr(y, x, i * unitBitSize); + Vint::pow(s, Vint(2), i * unitBitSize); + z = x / s; + CYBOZU_TEST_EQUAL(y, z); + y = x >> (i * unitBitSize); + CYBOZU_TEST_EQUAL(y, z); + y = x; + y >>= (i * unitBitSize); + CYBOZU_TEST_EQUAL(y, z); + } + for (int i = 0; i < 100; i++) { + y = x >> i; + Vint::pow(s, Vint(2), i); + z = x / s; + CYBOZU_TEST_EQUAL(y, z); + y = x; + y >>= i; + CYBOZU_TEST_EQUAL(y, z); + } + { + Vint a = 0, zero = 0; + a <<= Vint::unitBitSize; + CYBOZU_TEST_EQUAL(a, zero); + } +} + +CYBOZU_TEST_AUTO(getBitSize) +{ + { + Vint zero = 0; + CYBOZU_TEST_EQUAL(zero.getBitSize(), 1); + zero <<= (Vint::unitBitSize - 1); + CYBOZU_TEST_EQUAL(zero.getBitSize(), 1); + zero <<= Vint::unitBitSize; + CYBOZU_TEST_EQUAL(zero.getBitSize(), 1); + } + + { + Vint a = 1; + CYBOZU_TEST_EQUAL(a.getBitSize(), 1); + a = 2; + CYBOZU_TEST_EQUAL(a.getBitSize(), 2); + a = 3; + CYBOZU_TEST_EQUAL(a.getBitSize(), 2); + a = 4; + CYBOZU_TEST_EQUAL(a.getBitSize(), 3); + } + + { + Vint a = 5; + const size_t msbindex = a.getBitSize(); + const size_t width = 100; + const size_t time = 3; + for (size_t i = 0; i < time; ++i) { + a <<= width; + CYBOZU_TEST_EQUAL(a.getBitSize(), msbindex + width*(i + 1)); + } + + for (size_t i = 0; i < time*2; ++i) { + a >>= width/2; + CYBOZU_TEST_EQUAL(a.getBitSize(), msbindex + width*time - (width/2)*(i + 1)); + } + a >>= width; + CYBOZU_TEST_ASSERT(a.isZero()); + CYBOZU_TEST_EQUAL(a.getBitSize(), 1); + } + + { + Vint b("12"), c("345"), d("67890"); + size_t bl = b.getBitSize(), cl = c.getBitSize(), dl = d.getBitSize(); + CYBOZU_TEST_ASSERT((b*c).getBitSize() <= bl + cl); + CYBOZU_TEST_ASSERT((c*d).getBitSize() <= cl + dl); + CYBOZU_TEST_ASSERT((b*c*d).getBitSize() <= bl + cl + dl); + } +} + +CYBOZU_TEST_AUTO(bit) +{ + Vint a; + a.setStr("0x1234567890abcdef"); + bool tvec[] = { + 1,1,1,1,0 ,1,1,1,1,0 + ,1,1,0,0,1 ,1,1,1,0,1 + ,0,1,0,1,0 ,0,0,0,1,0 + ,0,1,0,0,0 ,1,1,1,1,0 + ,0,1,1,0,1 ,0,1,0,0,0 + ,1,0,1,1,0 ,0,0,1,0,0 + ,1 + }; + CYBOZU_TEST_EQUAL(a.getBitSize(), sizeof(tvec)/sizeof(*tvec)); + for (int i = (int)a.getBitSize() - 1; i >= 0; --i) { + CYBOZU_TEST_EQUAL(a.testBit(i), tvec[i]); + } +} + +CYBOZU_TEST_AUTO(sample) +{ + using namespace mcl; + Vint x(1); + Vint y("123456789"); + Vint z; + + x = 1; // set by int + y.setStr("123456789"); // set by decimal + z.setStr("0xffffffff"); // set by hex + x += z; + + x = 2; + y = 250; + Vint::pow(x, x, y); + Vint r, q; + r = x % y; + q = x / y; + CYBOZU_TEST_EQUAL(q * y + r, x); + + Vint::quotRem(&q, r, x, y); // get both r and q + CYBOZU_TEST_EQUAL(q * y + r, x); +} + +CYBOZU_TEST_AUTO(Vint) +{ + const struct { + int a; + int b; + /* + q, r ; like C + q2, r2 ; like Python + */ + int add, sub, mul, q, r, q2, r2; + } tbl[] = { + { 13, 5, 18, 8, 65, 2, 3, 2, 3 }, + { 13, -5, 8, 18, -65, -2, 3, -3, -2 }, + { -13, 5, -8, -18, -65, -2, -3, -3, 2 }, + { -13, -5, -18, -8, 65, 2, -3, 2, -3 }, + { 5, 13, 18, -8, 65, 0, 5 , 0, 5}, + { 5, -13, -8, 18, -65, 0, 5 , -1, -8}, + { -5, 13, 8, -18, -65, 0, -5 , -1, 8}, + { -5, -13, -18, 8, 65, 0, -5 , 0, -5}, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Vint a = tbl[i].a; + Vint b = tbl[i].b; + Vint add = a + b; + Vint sub = a - b; + Vint mul = a * b; + Vint q = a / b; + Vint r = a % b; + Vint q2, r2; + Vint::quotRem(&q2, r2, a, b); + CYBOZU_TEST_EQUAL(add, tbl[i].add); + CYBOZU_TEST_EQUAL(sub, tbl[i].sub); + CYBOZU_TEST_EQUAL(mul, tbl[i].mul); + CYBOZU_TEST_EQUAL(q, tbl[i].q); + CYBOZU_TEST_EQUAL(r, tbl[i].r); + CYBOZU_TEST_EQUAL(q * b + r, a); + CYBOZU_TEST_EQUAL(q2, tbl[i].q2); + CYBOZU_TEST_EQUAL(r2, tbl[i].r2); + CYBOZU_TEST_EQUAL(q2 * b + r2, a); + } + CYBOZU_TEST_EQUAL(Vint("15") / Vint("3"), Vint("5")); + CYBOZU_TEST_EQUAL(Vint("15") / Vint("-3"), Vint("-5")); + CYBOZU_TEST_EQUAL(Vint("-15") / Vint("3"), Vint("-5")); + CYBOZU_TEST_EQUAL(Vint("-15") / Vint("-3"), Vint("5")); + + CYBOZU_TEST_EQUAL(Vint("15") % Vint("3"), Vint("0")); + CYBOZU_TEST_EQUAL(Vint("15") % Vint("-3"), Vint("0")); + CYBOZU_TEST_EQUAL(Vint("-15") % Vint("3"), Vint("0")); + CYBOZU_TEST_EQUAL(Vint("-15") % Vint("-3"), Vint("0")); + + CYBOZU_TEST_EQUAL(Vint("-0") + Vint("-3"), Vint("-3")); + CYBOZU_TEST_EQUAL(Vint("-0") - Vint("-3"), Vint("3")); + CYBOZU_TEST_EQUAL(Vint("-3") + Vint("-0"), Vint("-3")); + CYBOZU_TEST_EQUAL(Vint("-3") - Vint("-0"), Vint("-3")); + + CYBOZU_TEST_EQUAL(Vint("-0") + Vint("3"), Vint("3")); + CYBOZU_TEST_EQUAL(Vint("-0") - Vint("3"), Vint("-3")); + CYBOZU_TEST_EQUAL(Vint("3") + Vint("-0"), Vint("3")); + CYBOZU_TEST_EQUAL(Vint("3") - Vint("-0"), Vint("3")); + + CYBOZU_TEST_EQUAL(Vint("0"), Vint("0")); + CYBOZU_TEST_EQUAL(Vint("0"), Vint("-0")); + CYBOZU_TEST_EQUAL(Vint("-0"), Vint("0")); + CYBOZU_TEST_EQUAL(Vint("-0"), Vint("-0")); + + CYBOZU_TEST_ASSERT(Vint("2") < Vint("3")); + CYBOZU_TEST_ASSERT(Vint("-2") < Vint("3")); + CYBOZU_TEST_ASSERT(Vint("-5") < Vint("-3")); + CYBOZU_TEST_ASSERT(Vint("-0") < Vint("1")); + CYBOZU_TEST_ASSERT(Vint("-1") < Vint("-0")); + + CYBOZU_TEST_ASSERT(Vint("5") > Vint("3")); + CYBOZU_TEST_ASSERT(Vint("5") > Vint("-3")); + CYBOZU_TEST_ASSERT(Vint("-2") > Vint("-3")); + CYBOZU_TEST_ASSERT(Vint("3") > Vint("-0")); + CYBOZU_TEST_ASSERT(Vint("-0") > Vint("-1")); + + { + const struct { + const char *str; + int s; + int shl; + int shr; + } tbl2[] = { + { "0", 1, 0, 0 }, + { "-0", 1, 0, 0 }, + { "1", 1, 2, 0 }, + { "-1", 1, -2, 0 }, + { "12345", 3, 98760, 1543 }, + { "-12345", 3, -98760, 0 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl2); i++) { + Vint a = Vint(tbl2[i].str); + Vint shl = a << tbl2[i].s; + CYBOZU_TEST_EQUAL(shl, tbl2[i].shl); + if (!a.isNegative()) { + Vint shr = a >> tbl2[i].s; + CYBOZU_TEST_EQUAL(shr, tbl2[i].shr); + } + } + } +} + +CYBOZU_TEST_AUTO(add2) +{ + Vint x, y, z, w; + x.setStr("2416089439321382744001761632872637936198961520379024187947524965775137204955564426500438089001375107581766516460437532995850581062940399321788596606850"); + y.setStr("2416089439321382743300544243711595219403446085161565705825288050160594425031420687263897209379984490503106207071010949258995096347962762372787916800000"); + z.setStr("701217389161042716795515435217458482122236915614542779924143739236540879621390617078660309389426583736855484714977636949000679806850"); + Vint::sub(w, x, y); + CYBOZU_TEST_EQUAL(w, z); + + Vint a, c, d; + + a.setStr("-2416089439321382744001761632872637936198961520379024187947524965775137204955564426500438089001375107581766516460437532995850581062940399321788596606850"); + c.setStr("2416089439321382743300544243711595219403446085161565705825288050160594425031420687263897209379984490503106207071010949258995096347962762372787916800000"); + a = a + c; + + d.setStr("-701217389161042716795515435217458482122236915614542779924143739236540879621390617078660309389426583736855484714977636949000679806850"); + CYBOZU_TEST_EQUAL(a, d); +} + +CYBOZU_TEST_AUTO(stream) +{ + { + Vint x, y, z, w; + x.setStr("12345678901232342424242423423429922"); + y.setStr("23423423452424242343"); + std::ostringstream oss; + oss << x << ' ' << y; + std::istringstream iss(oss.str()); + iss >> z >> w; + CYBOZU_TEST_EQUAL(x, z); + CYBOZU_TEST_EQUAL(y, w); + } + { + Vint x, y, z, w; + x.setStr("0x100"); + y.setStr("123"); + std::ostringstream oss; + oss << x << ' ' << y; + std::istringstream iss(oss.str()); + iss >> z >> w; + CYBOZU_TEST_EQUAL(x, z); + CYBOZU_TEST_EQUAL(y, w); + } + { + Vint x, y, z, w; + x.setStr("12345678901232342424242423423429922"); + y.setStr("-23423423452424242343"); + std::ostringstream oss; + oss << x << ' ' << y; + std::istringstream iss(oss.str()); + iss >> z >> w; + CYBOZU_TEST_EQUAL(x, z); + CYBOZU_TEST_EQUAL(y, w); + } +} + +CYBOZU_TEST_AUTO(inc_dec) +{ + Vint x = 3; + CYBOZU_TEST_EQUAL(x++, 3); + CYBOZU_TEST_EQUAL(x, 4); + CYBOZU_TEST_EQUAL(++x, 5); + CYBOZU_TEST_EQUAL(x, 5); + + CYBOZU_TEST_EQUAL(x--, 5); + CYBOZU_TEST_EQUAL(x, 4); + CYBOZU_TEST_EQUAL(--x, 3); + CYBOZU_TEST_EQUAL(x, 3); +} + +CYBOZU_TEST_AUTO(withInt) +{ + Vint x = 15; + x += 3; + CYBOZU_TEST_EQUAL(x, 18); + x -= 2; + CYBOZU_TEST_EQUAL(x, 16); + x *= 2; + CYBOZU_TEST_EQUAL(x, 32); + x /= 3; + CYBOZU_TEST_EQUAL(x, 10); + x = -x; + CYBOZU_TEST_EQUAL(x, -10); + x += 1; + CYBOZU_TEST_EQUAL(x, -9); + x -= 2; + CYBOZU_TEST_EQUAL(x, -11); + x *= 2; + CYBOZU_TEST_EQUAL(x, -22); + x /= 5; + CYBOZU_TEST_EQUAL(x, -4); + x = -22; + x %= 5; + CYBOZU_TEST_EQUAL(x, -2); + + x = 3; + x += -2; + CYBOZU_TEST_EQUAL(x, 1); + x += -5; + CYBOZU_TEST_EQUAL(x, -4); + x -= -7; + CYBOZU_TEST_EQUAL(x, 3); + x *= -1; + CYBOZU_TEST_EQUAL(x, -3); + x /= -1; + CYBOZU_TEST_EQUAL(x, 3); + + x++; + CYBOZU_TEST_EQUAL(x, 4); + x--; + CYBOZU_TEST_EQUAL(x, 3); + x = -3; + x++; + CYBOZU_TEST_EQUAL(x, -2); + x--; + CYBOZU_TEST_EQUAL(x, -3); + + ++x; + CYBOZU_TEST_EQUAL(x, -2); + --x; + CYBOZU_TEST_EQUAL(x, -3); + x = 3; + ++x; + CYBOZU_TEST_EQUAL(x, 4); + --x; + CYBOZU_TEST_EQUAL(x, 3); +} + +CYBOZU_TEST_AUTO(addu1) +{ + Vint x = 4; + Vint::addu1(x, x, 2); + CYBOZU_TEST_EQUAL(x, 6); + Vint::subu1(x, x, 2); + CYBOZU_TEST_EQUAL(x, 4); + Vint::subu1(x, x, 10); + CYBOZU_TEST_EQUAL(x, -6); + x = -4; + Vint::addu1(x, x, 2); + CYBOZU_TEST_EQUAL(x, -2); + Vint::subu1(x, x, 2); + CYBOZU_TEST_EQUAL(x, -4); + Vint::addu1(x, x, 10); + CYBOZU_TEST_EQUAL(x, 6); + + x.setStr("0x10000000000000000000000002"); + Vint::subu1(x, x, 3); + CYBOZU_TEST_EQUAL(x, Vint("0xfffffffffffffffffffffffff")); + x.setStr("-0x10000000000000000000000000"); + Vint::addu1(x, x, 5); + CYBOZU_TEST_EQUAL(x, Vint("-0xffffffffffffffffffffffffb")); +} + +CYBOZU_TEST_AUTO(pow) +{ + Vint x = 2; + Vint y; + Vint::pow(y, x, 3); + CYBOZU_TEST_EQUAL(y, 8); + x = -2; + Vint::pow(y, x, 3); + CYBOZU_TEST_EQUAL(y, -8); +#ifndef MCL_AVOID_EXCEPTION_TEST +// CYBOZU_TEST_EXCEPTION(Vint::pow(y, x, -2), cybozu::Exception); +#endif +} + +CYBOZU_TEST_AUTO(powMod) +{ + Vint x = 7; + Vint m = 65537; + Vint y; + Vint::powMod(y, x, 20, m); + CYBOZU_TEST_EQUAL(y, 55277); + Vint::powMod(y, x, m - 1, m); + CYBOZU_TEST_EQUAL(y, 1); +} + +CYBOZU_TEST_AUTO(andOr) +{ + Vint x("1223480928420984209849242"); + Vint y("29348220482094820948208420984209482048204289482"); + Vint z; + z = x & y; + CYBOZU_TEST_EQUAL(z, Vint("1209221003550923564822922")); + z = x | y; + CYBOZU_TEST_EQUAL(z, Vint("29348220482094820948208435244134352108849315802")); +#ifndef MCL_AVOID_EXCEPTION_TEST +// CYBOZU_TEST_EXCEPTION(Vint("-2") | Vint("5"), cybozu::Exception); +// CYBOZU_TEST_EXCEPTION(Vint("-2") & Vint("5"), cybozu::Exception); +#endif + x = 8; + x |= 7; + CYBOZU_TEST_EQUAL(x, 15); + x = 65536; + y = 8; + y &= x; + CYBOZU_TEST_EQUAL(y, 0); +} + +CYBOZU_TEST_AUTO(invMod) +{ + Vint m("100000000000000000039"); + for (int i = 1; i < 100; i++) { + Vint x = i; + Vint y; + Vint::invMod(y, x, m); + CYBOZU_TEST_EQUAL((y * x) % m, 1); + } +} + +CYBOZU_TEST_AUTO(isPrime) +{ + int primeTbl[] = { + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, + 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,197, 199, 211, + 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, + 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, + 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, + 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, + 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, + 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, + 941, 947, 953, 967, 971, 977, 983, 991, 997 + }; + typedef std::set IntSet; + IntSet primes; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(primeTbl); i++) { + primes.insert(primeTbl[i]); + } + for (int i = 0; i < 1000; i++) { + bool ok = primes.find(i) != primes.end(); + bool my = Vint(i).isPrime(); + CYBOZU_TEST_EQUAL(ok, my); + } + const struct { + const char *n; + bool isPrime; + } tbl[] = { + { "65537", true }, + { "449065", false }, + { "488881", false }, + { "512461", false }, + { "18446744073709551629", true }, + { "18446744073709551631", false }, + { "0x10000000000000000000000000000000000000007", true }, + { "0x10000000000000000000000000000000000000009", false }, + { "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", true }, + { "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", false }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Vint x(tbl[i].n); + CYBOZU_TEST_EQUAL(x.isPrime(), tbl[i].isPrime); + } +} + +CYBOZU_TEST_AUTO(gcd) +{ + Vint x = 12; + Vint y = 18; + Vint z; + Vint::gcd(z, x, y); + CYBOZU_TEST_EQUAL(z, 6); + Vint::lcm(z, x, y); + CYBOZU_TEST_EQUAL(z, 36); + Vint::lcm(x, x, y); + CYBOZU_TEST_EQUAL(x, 36); + Vint::lcm(x, x, x); + CYBOZU_TEST_EQUAL(x, 36); +} + +CYBOZU_TEST_AUTO(jacobi) +{ + const struct { + const char *m; + const char *n; + int ok; + } tbl[] = { + { "0", "1", 1 }, + { "1", "1", 1 }, + { "123", "1", 1 }, + { "45", "77", -1 }, + { "60", "121", 1 }, + { "12345672342342342342428", "923423423424753211", 1 }, + { "12345672342342342342428","34592342234235424753211", -1 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + int my = Vint::jacobi(Vint(tbl[i].m), Vint(tbl[i].n)); + CYBOZU_TEST_EQUAL(my, tbl[i].ok); + } +} + +CYBOZU_TEST_AUTO(bench) +{ + Vint x, y, z; + x.setStr("0x2523648240000001ba344d80000000086121000000000013a700000000000013"); + y.setStr("0x1802938109810498104982094820498203942804928049284092424902424243"); + + int N = 100000; + CYBOZU_BENCH_C("add", N, Vint::add, z, x, y); + CYBOZU_BENCH_C("sub", N, Vint::sub, z, x, y); + CYBOZU_BENCH_C("mul", N, Vint::mul, z, x, y); + CYBOZU_BENCH_C("div", N, Vint::div, y, z, x); + + const struct { + const char *x; + const char *y; + } tbl[] = { + { + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d" + }, + { + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", + }, + { + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", + }, + + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + x.setStr(tbl[i].x); + y.setStr(tbl[i].y); + CYBOZU_BENCH_C("fast div", N, Vint::div, z, x, y); +#ifndef DONT_USE_GMP_IN_TEST + { + mpz_class mx(tbl[i].x), my(tbl[i].y), mz; + CYBOZU_BENCH_C("gmp", N, mpz_div, mz.get_mpz_t(), mx.get_mpz_t(), my.get_mpz_t()); + } +#endif + } +} + +struct Seq { + const uint32_t *tbl; + size_t n; + size_t i, j; + Seq(const uint32_t *tbl, size_t n) : tbl(tbl), n(n), i(0), j(0) {} + bool next(uint64_t *v) + { + if (i == n) { + if (j == n - 1) return false; + i = 0; + j++; + } + *v = (uint64_t(tbl[j]) << 32) | tbl[i]; + i++; + return true; + } +}; + +#if MCL_SIZEOF_UNIT == 8 +CYBOZU_TEST_AUTO(divUnit) +{ + const uint32_t tbl[] = { + 0, 1, 3, + 0x7fffffff, + 0x80000000, + 0x80000001, + 0xffffffff, + }; + const size_t n = sizeof(tbl) / sizeof(tbl[0]); + Seq seq3(tbl, n); + uint64_t y; + while (seq3.next(&y)) { + if (y == 0) continue; + Seq seq2(tbl, n); + uint64_t r; + while (seq2.next(&r)) { + if (r >= y) break; + Seq seq1(tbl, n); + uint64_t q; + while (seq1.next(&q)) { + uint64_t x[2]; + x[0] = mcl::vint::mulUnit(&x[1], q, y); + mcl::vint::addu1(x, x, 2, r); + uint64_t Q, R; +//printf("q=0x%016llxull, r=0x%016llxull, y=0x%016llxull\n", (long long)q, (long long)r, (long long)y); + Q = mcl::vint::divUnit(&R, x[1], x[0], y); + CYBOZU_TEST_EQUAL(q, Q); + CYBOZU_TEST_EQUAL(r, R); + } + } + } +} + +void compareMod(const uint64_t *x, const uint64_t *p) +{ + uint64_t y1[4] = {}; + uint64_t y2[4] = {}; + mcl::vint::divNM((uint64_t*)0, 0, y1, x, 8, p, 4); + mcl::vint::mcl_fpDbl_mod_SECP256K1(y2, x, p); + CYBOZU_TEST_EQUAL_ARRAY(y1, y2, 4); +} +CYBOZU_TEST_AUTO(SECP256k1) +{ + const uint64_t F = uint64_t(-1); + const uint64_t p[4] = { uint64_t(0xfffffffefffffc2full), F, F, F }; + const uint64_t tbl[][8] = { + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { F, F, F, F, F, F, F, F }, + { F, F, F, F, 1, 0, 0, 0 }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + const uint64_t *x = tbl[i]; + compareMod(x, p); + } + cybozu::XorShift rg; + for (size_t i = 0; i < 100; i++) { + uint64_t x[8]; + for (int j = 0; j < 8; j++) { + x[j] = rg(); + } + compareMod(x, p); + } +} +#endif diff --git a/vendor/github.com/dexon-foundation/mcl/test/window_method_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/window_method_test.cpp new file mode 100644 index 000000000..1b0f702af --- /dev/null +++ b/vendor/github.com/dexon-foundation/mcl/test/window_method_test.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include + +CYBOZU_TEST_AUTO(ArrayIterator) +{ + const uint32_t in[2] = { 0x12345678, 0xabcdef89 }; + const size_t bitSize = 64; + for (size_t w = 1; w <= 32; w++) { + const uint32_t mask = uint32_t((uint64_t(1) << w) - 1); + mpz_class x; + mcl::gmp::setArray(x, in, 2); + mcl::fp::ArrayIterator ai(in, bitSize, w); + size_t n = (bitSize + w - 1) / w; + for (size_t j = 0; j < n; j++) { + CYBOZU_TEST_ASSERT(ai.hasNext()); + uint32_t v = ai.getNext(); + CYBOZU_TEST_EQUAL(x & mask, v); + x >>= w; + } + CYBOZU_TEST_ASSERT(!ai.hasNext()); + } +} + +CYBOZU_TEST_AUTO(int) +{ + typedef mcl::FpT<> Fp; + typedef mcl::EcT Ec; + const struct mcl::EcParam& para = mcl::ecparam::secp192k1; + Fp::init(para.p); + Ec::init(para.a, para.b); + const Fp x(para.gx); + const Fp y(para.gy); + const Ec P(x, y); + + typedef mcl::fp::WindowMethod PW; + const size_t bitSize = 13; + Ec Q, R; + + for (size_t winSize = 10; winSize <= bitSize; winSize++) { + PW pw(P, bitSize, winSize); + for (int i = 0; i < (1 << bitSize); i++) { + pw.mul(Q, i); + Ec::mul(R, P, i); + CYBOZU_TEST_EQUAL(Q, R); + } + } + PW pw(P, para.bitSize, 10); + pw.mul(Q, -12345); + Ec::mul(R, P, -12345); + CYBOZU_TEST_EQUAL(Q, R); + mpz_class t(para.gx); + pw.mul(Q, t); + Ec::mul(R, P, t); + CYBOZU_TEST_EQUAL(Q, R); + t = -t; + pw.mul(Q, t); + Ec::mul(R, P, t); + CYBOZU_TEST_EQUAL(Q, R); + + pw.mul(Q, x); + Ec::mul(R, P, x); + CYBOZU_TEST_EQUAL(Q, R); + + pw.mul(Q, y); + Ec::mul(R, P, y); + CYBOZU_TEST_EQUAL(Q, R); +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 7cccb564a..f94f0e307 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -141,16 +141,16 @@ { "checksumSHA1": "In6vBHYUsX7DUIGiFN2hQggBgvI=", "path": "github.com/dexon-foundation/dexon-consensus/common", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "9uNk7orRE3xuTv2m/y6vO/4uDAg=", "path": "github.com/dexon-foundation/dexon-consensus/core", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, @@ -165,64 +165,64 @@ { "checksumSHA1": "tQSbYCu5P00lUhKsx3IbBZCuSLY=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, { - "checksumSHA1": "m5lUT04qSHKtFukvxjnFX5Jo2hI=", + "checksumSHA1": "4besQaa0rm8jRUAJjpEaLZ/ZOYs=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "BhLKK8RveoLaeXc9UyUKMwQqchU=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "3Ludp/1V4dMBZH/c1oIVjHj0CqY=", "path": "github.com/dexon-foundation/dexon-consensus/core/db", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "/OcEQKdtWDyRZibazIsAxJWHUyg=", "path": "github.com/dexon-foundation/dexon-consensus/core/syncer", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "zIgCdN4FJiAuPGMhB+/9YGK/Wgk=", "path": "github.com/dexon-foundation/dexon-consensus/core/types", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "lbG7yqVgzo2CV/CQPYjG78xp5jg=", "path": "github.com/dexon-foundation/dexon-consensus/core/types/dkg", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, { "checksumSHA1": "1VsJIshz0loXnGwCtrMM8SuIo6Y=", "path": "github.com/dexon-foundation/dexon-consensus/core/utils", - "revision": "1d64520274d4e33b3038550083b78c5ebe1ea45d", - "revisionTime": "2019-04-10T14:52:57Z", + "revision": "269fed574986331e07bf931b2c9b1a495c40f8ac", + "revisionTime": "2019-04-11T06:42:07Z", "version": "single-chain", "versionExact": "single-chain" }, -- cgit v1.2.3