Compare commits

...

597 Commits

Author SHA1 Message Date
Leo Chen 5ce237032b [build] fix build error on Mac OS X 4 years ago
MITSUNARI Shigeo d32e456fc8 add sample of g1only she 4 years ago
MITSUNARI Shigeo c4a356038a remove non-mulx-code in jit 4 years ago
MITSUNARI Shigeo 3f9cce8741 don't use exception in xbyak 4 years ago
MITSUNARI Shigeo 5304c1f5b3 remove unused header 4 years ago
MITSUNARI Shigeo e15ab2a649 [doc][skip cs] about C# 4 years ago
MITSUNARI Shigeo 3fc2ca7109 Merge branch 'cs_tmp' 4 years ago
MITSUNARI Shigeo 5a24245d0e [cs][skip cs] add G1, G2::Recover/Share 4 years ago
MITSUNARI Shigeo b389732ba8 [cs][skip cs] pass test of Fr::Recover 4 years ago
MITSUNARI Shigeo 65c8d5f86f add test for Lagrange 4 years ago
MITSUNARI Shigeo de148824a4 [skip ci][java] add Fr::inv and Fp::inv 4 years ago
MITSUNARI Shigeo e9399112b7 v1.40 4 years ago
MITSUNARI Shigeo daea66e216 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 05213a0fbb remove dmesg in main.yml 4 years ago
MITSUNARI Shigeo ea8c103aa3 test by valgrind 4 years ago
MITSUNARI Shigeo c41e9e459d disable JIT unless both mulx and adox are supported 4 years ago
MITSUNARI Shigeo c76f208703 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 1456a13f4c [cs] rename variables 4 years ago
MITSUNARI Shigeo 19aad60e2a [cs] remove unnecessary set 4 years ago
MITSUNARI Shigeo aa3e88e54e [cs] check that default value is zero 4 years ago
MITSUNARI Shigeo 2895287e46 Merge branch 'feature/cs-additions' of https://github.com/UndeadRat22/mcl 4 years ago
MITSUNARI Shigeo d91c0fc266 [wasm] reduce cast operation 4 years ago
Valdas Rakutis 2a82e2531a [cs] add some arithmetic operator overloads for g2, static factory, fix serialization issue 4 years ago
MITSUNARI Shigeo 5221e860f6 simplify generic add 4 years ago
MITSUNARI Shigeo 6b2d38e2b6 v1.39 4 years ago
MITSUNARI Shigeo 1564151d1b use MCL_SIZEOF_UNIT intead of CYBOZU_OS_BIT 4 years ago
MITSUNARI Shigeo 24e72ab3e3 Merge commit '67cea40' 4 years ago
MITSUNARI Shigeo 67cea40560 [cs] add MulVec for G2 4 years ago
MITSUNARI Shigeo 9ee82069bf [cs] add MulVec for G1 4 years ago
MITSUNARI Shigeo c2d843e6e0 [cs] fix correct value of test for mapToG1 4 years ago
MITSUNARI Shigeo 43df0c3c16 Merge branch 'UndeadRat22-feature/cs-additions' into dev 4 years ago
MITSUNARI Shigeo d9ef1cf1bb Merge branch 'feature/cs-additions' of https://github.com/UndeadRat22/mcl into UndeadRat22-feature/cs-additions 4 years ago
MITSUNARI Shigeo c4451d9c00 [skip ci] disable ffi/java test 4 years ago
MITSUNARI Shigeo b8b5c37e9e v1.38 4 years ago
MITSUNARI Shigeo 301051db53 update doc 4 years ago
MITSUNARI Shigeo fad6e7b3e3 set CFLAGS/LDFLAGS only if necessary 4 years ago
MITSUNARI Shigeo 2fc942b06e Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 014ecddf18 use montRed for sqrMont 4 years ago
MITSUNARI Shigeo f01790ba5d x86 asm generated by llvm-11 4 years ago
MITSUNARI Shigeo 8047bfe6aa arm.s generated by clang-11 4 years ago
MITSUNARI Shigeo 266d20173d llvm_test supports 32bit 4 years ago
MITSUNARI Shigeo 36e08dc5b4 asm/aarch64 generated by clang-4.0.0 4 years ago
MITSUNARI Shigeo 6d8a7d9830 enable montRedNF 4 years ago
MITSUNARI Shigeo f50e57c3b0 update x86-64mac asm 4 years ago
MITSUNARI Shigeo 89a0e3515c update x86-64 asm 4 years ago
MITSUNARI Shigeo b965c2c143 reduced base.ll 4 years ago
MITSUNARI Shigeo 414204f508 reduce supporting bitSize 4 years ago
MITSUNARI Shigeo 2e39b86af5 remove tests for small p 4 years ago
MITSUNARI Shigeo 33643b9a6d [llvm] add pack and split 4 years ago
Valdas Rakutis 9325c34783 [cs] add missing functions, some arithmetic operator overloads, static factory 4 years ago
MITSUNARI Shigeo 570396efd8 use textbook mul for N = 8 4 years ago
MITSUNARI Shigeo a9eef7fe49 _ 4 years ago
MITSUNARI Shigeo 1335112ef3 bench of llvm 4 years ago
MITSUNARI Shigeo 78392e25a1 [java] add make clean before test 4 years ago
MITSUNARI Shigeo 63d2707745 note for MCL_MAX_BIT_SIZE 4 years ago
MITSUNARI Shigeo ec661dcd66 set MCL_MAX_BIT_SIZE=512 and so disable test of NIST_P521 4 years ago
MITSUNARI Shigeo 6bdaec0567 [java] disable NIST_P521 test 4 years ago
MITSUNARI Shigeo ac580a19ab [java] specify libmcl.a to build 4 years ago
MITSUNARI Shigeo 9b5da4023e disable test_go in main.yml 4 years ago
MITSUNARI Shigeo 6d38eeea08 disable montRedNF after updating asm 4 years ago
MITSUNARI Shigeo f5fbc3e343 split montRed to w/wo NF 4 years ago
MITSUNARI Shigeo a06bfd3b8f [java] add JAVA_INC_DIR 4 years ago
MITSUNARI Shigeo f4afd32e2f v1.37 4 years ago
MITSUNARI Shigeo 94c59af7f7 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo e6cc4025e1 [python] LD_LIBRARY_PATH is necessary for linux 4 years ago
MITSUNARI Shigeo 317934bdfb fix test 4 years ago
MITSUNARI Shigeo 4eb4b2bd36 [python] add makefile 4 years ago
MITSUNARI Shigeo f3c39617ee
Merge pull request #107 from 0xflotus/patch-1 4 years ago
0xflotus 48349a18bc
fix: small errors 4 years ago
MITSUNARI Shigeo b91dbed2e0 disable ci test by sde 4 years ago
MITSUNARI Shigeo e974e3e2da Merge branch 'dev' 4 years ago
MITSUNARI Shigeo b28f608811 ci test of bn_test with DEBUG=1 4 years ago
MITSUNARI Shigeo 7d0087df69 fix main.yml 4 years ago
MITSUNARI Shigeo 01c81c60ca ci test on haswell 4 years ago
MITSUNARI Shigeo f52f4668ac remove warnings 4 years ago
MITSUNARI Shigeo 922a935e26 fix crash on haswell 4 years ago
MITSUNARI Shigeo fd4b408e52 [ci] show dmesg if error 4 years ago
MITSUNARI Shigeo 1317ddc6a7 [java] add test to main.yml 4 years ago
MITSUNARI Shigeo 7bfe60c537 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 98fc193f5f use -O3 instead of -Ofast 4 years ago
MITSUNARI Shigeo 8752e278ed remove warning of gmp_util 4 years ago
MITSUNARI Shigeo dbd58cc757 add test_go 4 years ago
MITSUNARI Shigeo ef3643f5bc use github action 4 years ago
MITSUNARI Shigeo f52743fdbb add Fp::mul9 4 years ago
MITSUNARI Shigeo 2d55524eb4 init smallModp 4 years ago
MITSUNARI Shigeo 62b67cf838 add mulSmall 4 years ago
MITSUNARI Shigeo 050a577095 look prime behavior 4 years ago
MITSUNARI Shigeo 952638edc3 use Fp::mul2 for ec 4 years ago
MITSUNARI Shigeo 4fb3fec3db v1.36 4 years ago
MITSUNARI Shigeo 9c7b1ad8b9 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 00ee0e8151 skip bench2 in debug 4 years ago
MITSUNARI Shigeo 70e9032ac0 define fp_sqrPreL 4 years ago
MITSUNARI Shigeo e1fc81a551 fast Fp::sqrPre 4 years ago
MITSUNARI Shigeo b7a47dc519 try mulPre + mod but it is slower 4 years ago
MITSUNARI Shigeo 5cad43bb10 make mulPre, sqrPre for mul/sqr 4 years ago
MITSUNARI Shigeo 95f2d4afff check undefined label 4 years ago
MITSUNARI Shigeo a314e6a54b remove unused code 4 years ago
MITSUNARI Shigeo 35db3f90b3 use fqrPre + mod for N = 4 4 years ago
MITSUNARI Shigeo 66c2852761 fast 256-bit Fp::mod 4 years ago
MITSUNARI Shigeo 6f5801b104 clean 4 years ago
MITSUNARI Shigeo bc4ed309e3 fast Fp4::sqrPre 4 years ago
MITSUNARI Shigeo 285b44546a move Fp6::mul 4 years ago
MITSUNARI Shigeo 5d703a98a8 update Fp12::inv 4 years ago
MITSUNARI Shigeo 0d01560a14 a little optimize Fp6::inv 4 years ago
MITSUNARI Shigeo 35a39d27e2 v1.35 4 years ago
MITSUNARI Shigeo 5f4559c249 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo e261605998 check it later 4 years ago
MITSUNARI Shigeo 847e97664c remove unused code 4 years ago
MITSUNARI Shigeo f248a91691 tweat Fp2Dbl::subSpecial 4 years ago
MITSUNARI Shigeo 7813e6a608 remove old fp_sub 4 years ago
MITSUNARI Shigeo 5dc683fea3 enable Fp2Dbl::sqrPre 4 years ago
MITSUNARI Shigeo fcc57b16fa unify fp2_mul and fp2Dbl_mupPre 4 years ago
MITSUNARI Shigeo bf703d617a enable Fp2Dbl_mulPre 4 years ago
MITSUNARI Shigeo 0785143e9a
Merge pull request #101 from herumi/dev 4 years ago
MITSUNARI Shigeo 194057fd02 use mov_mm 4 years ago
MITSUNARI Shigeo fd26ac6644 reduce memory access in Fp2::mul 4 years ago
MITSUNARI Shigeo b566c3a6e7 refactor FpDbl2::mul_xi 4 years ago
MITSUNARI Shigeo 022d37f762 factor Fp2Dbl::sub 4 years ago
MITSUNARI Shigeo 6ff8b16727 refactor Fp2::sub 4 years ago
MITSUNARI Shigeo 1fbb857884 fp_sub without jmp 4 years ago
MITSUNARI Shigeo aa6b6d0e15 refactor fp_add 4 years ago
MITSUNARI Shigeo d59dd09a34 remove unused code 4 years ago
MITSUNARI Shigeo acd4ef5aad under refactoring fp_add 4 years ago
MITSUNARI Shigeo 765ca7b89e under refactoring fp_add 4 years ago
MITSUNARI Shigeo d3d1504063 change build status to travis-ci.com 4 years ago
MITSUNARI Shigeo 7c042156d9 add -fPIC to cmake 4 years ago
MITSUNARI Shigeo ed8dc12e85 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo b226409e4a prepare for fp2Dbl_{mul,sqr}Pre 4 years ago
MITSUNARI Shigeo b19156bf5f disable bench in debug mode 4 years ago
MITSUNARI Shigeo d2b2ad8144 use llvm-add instead of C for Mul2 4 years ago
MITSUNARI Shigeo a7f2f656f8 fix generic fp2Dbl_mul_xi 4 years ago
MITSUNARI Shigeo 8bd785dab5 fix test of Fp2Dbl::mul_xi 4 years ago
MITSUNARI Shigeo 371399aa14 optimize Fp2Dbl::mul_xi 4 years ago
MITSUNARI Shigeo b46aa28d8e a little optimize Fp6::sqr 4 years ago
MITSUNARI Shigeo 988b1c6b41 v1.34 4 years ago
MITSUNARI Shigeo 2852262369 Merge branch 'staticlib' 4 years ago
MITSUNARI Shigeo 8ffb9f43c2 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 0c2babc0c4 remove unused code 4 years ago
MITSUNARI Shigeo 9f1df6d61c use mul2 4 years ago
MITSUNARI Shigeo ed74c3bfdd use mul2 in Fp6::mul 4 years ago
MITSUNARI Shigeo ae5b3a7330 _ 4 years ago
MITSUNARI Shigeo 6b5a64c3ec a little optimize Fp6::mul 4 years ago
MITSUNARI Shigeo 3423988fa0 use no-throw-version 4 years ago
MITSUNARI Shigeo f9d7d40059 fp_tower assumes p < W/4 4 years ago
MITSUNARI Shigeo 10183458d3 add cmake option MCL_STATIC_LIB 4 years ago
MITSUNARI Shigeo 91a2ecf358 add testABCD 4 years ago
MITSUNARI Shigeo 4b5869ffad refactor Fp6::mul 4 years ago
MITSUNARI Shigeo 3f65ce22ac move ecdsa code to ecdsa-wasm 4 years ago
MITSUNARI Shigeo 49b27ddbd7 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo b06f7f6956 [go] add testMapToG1 4 years ago
MITSUNARI Shigeo d33f8c6856 [go] add SetBigEndianMode 4 years ago
MITSUNARI Shigeo 6612374e3b [go] define const for SetMapToMode 4 years ago
MITSUNARI Shigeo d960faad6f [go] strict check of the length in Deserialize 4 years ago
MITSUNARI Shigeo 27cc37cc9c Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 46fc61dc75 enable mul2Test for isFullBit 4 years ago
MITSUNARI Shigeo 4c56c8e592 remove unnecessary comments 4 years ago
MITSUNARI Shigeo 744176ab8e use mul2 4 years ago
MITSUNARI Shigeo 630abea0c1 add Fp2::mul2 4 years ago
MITSUNARI Shigeo 40343a4a69 add mul2 4 years ago
MITSUNARI Shigeo bcf5961f70 add mul2 4 years ago
MITSUNARI Shigeo 28c8a0b489 field extension supposes non-fullbit 4 years ago
MITSUNARI Shigeo 9a3add8fe6 use adcx instead of adc 4 years ago
MITSUNARI Shigeo c08437c973 v1.33 4 years ago
MITSUNARI Shigeo b4abccd9a5 fix : disable bmi2 for old cpus 4 years ago
MITSUNARI Shigeo 3be1f32788 v1.32 4 years ago
MITSUNARI Shigeo 19616e15f7 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 6afa976ad2 rename local template function 4 years ago
MITSUNARI Shigeo 52a9f4d213 remove mulPreC 4 years ago
MITSUNARI Shigeo ebbb5cf6cc remove fpDbl_sqrPreA_ 4 years ago
MITSUNARI Shigeo 64be787592 reduce one wrapper of mulPre for wasm 4 years ago
MITSUNARI Shigeo b730448fa0 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 2378fd2743 a little optimization of portable mulUnit 4 years ago
MITSUNARI Shigeo c0d65655ea remove unused code 4 years ago
MITSUNARI Shigeo 54155986b4 replace bool to uint32_t 4 years ago
MITSUNARI Shigeo c0be1e91ce rename low_funct.hpp to low_func_wasm.hpp 4 years ago
MITSUNARI Shigeo 769ca108f9 disable log 4 years ago
MITSUNARI Shigeo 908fa76fca Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 215106e9e6 replace bool to unit32_t 4 years ago
MITSUNARI Shigeo dc8964db5a add sqrMont 4 years ago
MITSUNARI Shigeo c346f747d7 add modT 4 years ago
MITSUNARI Shigeo a3293c2c85 add sqrT 4 years ago
MITSUNARI Shigeo a7728b2286 add sqrT 4 years ago
MITSUNARI Shigeo f2f39faf99 fix comment 4 years ago
MITSUNARI Shigeo e61e56abdf add test of mont12 4 years ago
MITSUNARI Shigeo 7dae2ec939 add montT 4 years ago
MITSUNARI Shigeo 32b1f2f7e7 test N = 8, 12 4 years ago
MITSUNARI Shigeo a3dd0f8a55 add karatsuba 4 years ago
MITSUNARI Shigeo a31bde314f add mulT 4 years ago
MITSUNARI Shigeo 8d64a0cfed test of wasm 4 years ago
MITSUNARI Shigeo c1bcf317a1 v1.31 4 years ago
MITSUNARI Shigeo 8b1bd275b7 fix : call setOrder in init for isValidOrder 4 years ago
MITSUNARI Shigeo 6fcddcf944 v1.30 4 years ago
MITSUNARI Shigeo 802d04ab47
Merge pull request #97 from herumi/dev 4 years ago
MITSUNARI Shigeo f71698f60f optimize FpDbl::mod 4 years ago
MITSUNARI Shigeo 70e8b3f992 refactor montgomery6_1 4 years ago
MITSUNARI Shigeo 4e0e7c9089
Merge pull request #96 from herumi/dev 4 years ago
MITSUNARI Shigeo 184cada5d0 tweat montgomery6_1 4 years ago
MITSUNARI Shigeo 340389abfd keep rip+pL_ 4 years ago
MITSUNARI Shigeo 6030ded9e7 reorder registers 4 years ago
MITSUNARI Shigeo addd488d3d tweat mulAdd 4 years ago
MITSUNARI Shigeo 0731c980b9 remove unnecessary add 4 years ago
MITSUNARI Shigeo 106082b9ac clear top bit 4 years ago
MITSUNARI Shigeo 758b1df7c4 tweet a loop 4 years ago
MITSUNARI Shigeo c50b06141a adcx -> adc 4 years ago
MITSUNARI Shigeo ee1eef38c8 remove one adox in Fp::mul 4 years ago
MITSUNARI Shigeo 8befb75daa sample/pairing.exe uses Fr::setHashOf 4 years ago
MITSUNARI Shigeo 19128897a8 sample/pairing.exe shows values 4 years ago
MITSUNARI Shigeo df853a52c2 add sample of Fr::sub 4 years ago
MITSUNARI Shigeo 69f1435fe4 Merge branch 'gallmann-ubique-feature/jni-extensions' 4 years ago
Johannes Gallmann 7fb2ee5bb7 Add Fr.setHash() to JNI 4 years ago
MITSUNARI Shigeo 1b8b3fcf92 Merge branch 'gallmann-ubique-feature/jni-extensions' 4 years ago
Johannes Gallmann 1b08a14e8e Add G1.isValidOrder() to JNI 4 years ago
Johannes Gallmann 5ea94c2f51 Add Fr.setLittleEndianMod to JNI 4 years ago
MITSUNARI Shigeo 081db6d229 mov she-wasm entry in Makefile to she-wasm 4 years ago
MITSUNARI Shigeo 51292308d7 remove entry mcl-wasm in Makefile 4 years ago
MITSUNARI Shigeo 5fd72f06cf [she] add desc of decWithZkpDec 4 years ago
MITSUNARI Shigeo 700751ed0d v1.29 4 years ago
MITSUNARI Shigeo 8ecd8cf99f avoid computing in MCL_DUMP_JIT 4 years ago
MITSUNARI Shigeo 5cd31b666d [she] add test of ZkpDecGT 4 years ago
MITSUNARI Shigeo 0d123843df [she] move PublicKey::verify to Aux::verify 4 years ago
MITSUNARI Shigeo 3374bec58b [she] fix size of sheZkpDec 4 years ago
MITSUNARI Shigeo 58836c5ddc [she] add decWithZkpDec for CipherGT 4 years ago
MITSUNARI Shigeo 27f51cb987 update zkp for dec(c) = 0 4 years ago
MITSUNARI Shigeo 4407af6e33 update doc 4 years ago
MITSUNARI Shigeo 54cf1ca2bc reduce benchmark time 4 years ago
MITSUNARI Shigeo b9e6a9c166 Merge remote-tracking branch 'origin/m1-mac' 4 years ago
MITSUNARI Shigeo 250f7bddbc v1.28 4 years ago
MITSUNARI Shigeo b0abe614ae support m1 mac 4 years ago
MITSUNARI Shigeo d0da379eb2 [she] refactor makeHash 4 years ago
MITSUNARI Shigeo 48253e792f [she] add ZKP of dec(c)=0 for CipherTextGT 4 years ago
MITSUNARI Shigeo 5fd1dc64ef [java] mk files for android 4 years ago
MITSUNARI Shigeo 28af4a6b25 add llvm-IR for easy build 4 years ago
MITSUNARI Shigeo 467fa05e64 [she] makeHash supports C++03 4 years ago
MITSUNARI Shigeo edc48bc1ab [she] add makeHash for ZKP 4 years ago
MITSUNARI Shigeo 702b390ccb mcl.js contains mcl.wasm 4 years ago
MITSUNARI Shigeo cb16b0af72 v1.27 4 years ago
MITSUNARI Shigeo 17f3e80c58 fix macro condition 4 years ago
MITSUNARI Shigeo 2420cee2c3 [she] algo of decWithZkpDec 4 years ago
MITSUNARI Shigeo 0704eb875b [she] add decWithZkpDec C api 4 years ago
MITSUNARI Shigeo 3af5eaa48f [she] add decWithZkpDec 4 years ago
MITSUNARI Shigeo b32aecd583 v1.26 4 years ago
MITSUNARI Shigeo 95b32ec6e9 modify condition for DUMP_JIT 4 years ago
MITSUNARI Shigeo 9f97f25500 Revert "default build without GMP" 4 years ago
MITSUNARI Shigeo 04a5034fa0 Merge remote-tracking branch 'origin/dev' into master 4 years ago
MITSUNARI Shigeo 8e986394ae default build without GMP 4 years ago
MITSUNARI Shigeo 2497535f8c check FreeBSD in commom.mk 4 years ago
MITSUNARI Shigeo ad59c9eff7 test addCTProj for Zero 4 years ago
MITSUNARI Shigeo 34fdf9a67e add addCTProj 4 years ago
MITSUNARI Shigeo 776fab5ca6 mulSmallUnit supports 12 4 years ago
MITSUNARI Shigeo 5e1c3fc210 [doc] modify how to build GMP 4 years ago
MITSUNARI Shigeo bd5a368692 [java] add isZero, isOne 4 years ago
MITSUNARI Shigeo 44f3595a6d [java] use unitaryInv instead of inv 4 years ago
MITSUNARI Shigeo 0d436b2378 [java] remove space 4 years ago
MITSUNARI Shigeo 09e954e637 Merge branch 'master' of https://github.com/upbcuk/mcl into upbcuk-master 4 years ago
raphael e3bbe3fd75 Add Mcl.inv for GT to java ffi docs 4 years ago
raphael 016fd377dd Regenerate java ffi to fix missing package declarations 4 years ago
raphael dacfdaefea Regenerate java ffi to try out different inv location 4 years ago
MITSUNARI Shigeo 74eae4c83b update to v1.25 4 years ago
MITSUNARI Shigeo 99757f9f0f fix assert of expand_message_xmd 4 years ago
MITSUNARI Shigeo 2758b01440 refine tests 4 years ago
MITSUNARI Shigeo 20f1fc9c41 Merge branch 'lgremy-hash-to-curve-09-H.10.1-I.1' into dev 4 years ago
MITSUNARI Shigeo 0d9af2d203 dst for maptToG1 has changed 4 years ago
raphael e1efcbe55f Add GT inv to java ffi 4 years ago
MITSUNARI Shigeo a3cb8ff421 remove warning by -Wundef 4 years ago
MITSUNARI Shigeo 0114a3029f version 1.23 4 years ago
MITSUNARI Shigeo 6427215b98 remove warning for mcl-wasm 4 years ago
Laurent Grémy 81f6248645 Add test vectors in section I.1. of draft-irtf-cfrg-hash-to-curve-09. 4 years ago
Laurent Grémy 7f86eafef4 Add test vectors in section H.10.1 of draft-irtf-cfrg-hash-to-curve-09. 4 years ago
MITSUNARI Shigeo 0e64636878 move MCL_STATIC_CODE flag to common.mk 4 years ago
MITSUNARI Shigeo 512a0abd44 Fp::inv uses generated code 4 years ago
MITSUNARI Shigeo 02cce0ed47 add initF to millerLoopVec 4 years ago
MITSUNARI Shigeo fce9599a59 change internal millerLoopVecN api 4 years ago
MITSUNARI Shigeo c456490f73 bench of inv 4 years ago
MITSUNARI Shigeo c07c4a6b9f test of binary method of inv 4 years ago
MITSUNARI Shigeo 71e4f39fda Merge remote-tracking branch 'origin/dev' 4 years ago
MITSUNARI Shigeo eb1f0002d0 gen.cpp does not require GMP 4 years ago
MITSUNARI Shigeo af1950d8fb STATIC_CODE supports mac 4 years ago
MITSUNARI Shigeo 251bf1de3b return true if DUMP_JIT 4 years ago
MITSUNARI Shigeo 5af07a5522 update xbyak 4 years ago
MITSUNARI Shigeo 5a2f20f650 fix typo 4 years ago
MITSUNARI Shigeo d0e2d6ce15 update cybozulib 4 years ago
MITSUNARI Shigeo eca0e51959 DUMP_JIT always dump_code regardless of cpu 4 years ago
MITSUNARI Shigeo b390d6d4ff Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 4fd5fef8ed static_code does not need llvm-bmi2 4 years ago
MITSUNARI Shigeo 4ee23f5fd3 add -Wundef 4 years ago
MITSUNARI Shigeo ad7b7891fa fix bls12_test for static code 4 years ago
MITSUNARI Shigeo 938e15432a fix typo 4 years ago
MITSUNARI Shigeo 32453e25a2 add MCL_STATIC_CODE 4 years ago
MITSUNARI Shigeo eaabb2337b fix pic code 4 years ago
MITSUNARI Shigeo a522fd532d test of G1 and G2 4 years ago
MITSUNARI Shigeo 11a752cb6c Fr, Fp, Fp2 test ok 4 years ago
MITSUNARI Shigeo df3e118538 remove suf 4 years ago
MITSUNARI Shigeo 3768ebfedf test mclx_Fp_mul 4 years ago
MITSUNARI Shigeo 0c6b2c59b8 use rip instead of abs addr 4 years ago
MITSUNARI Shigeo f11b3be1ab refactor DumpCode 4 years ago
MITSUNARI Shigeo c29157cc9a test static_code 4 years ago
MITSUNARI Shigeo 7146cfd0f4 add dump_code 4 years ago
MITSUNARI Shigeo 10621c6299 refactor profiler 4 years ago
MITSUNARI Shigeo 9bfc47ca8d remove unused var 4 years ago
MITSUNARI Shigeo dc65ed2ccc update version 4 years ago
MITSUNARI Shigeo c278054238 finalExp by 2020/875.pdf 4 years ago
MITSUNARI Shigeo 5acf84b9c4 remove old unused code 4 years ago
MITSUNARI Shigeo 485c5c709d update xbyak 4 years ago
MITSUNARI Shigeo 1c402095e2 update doc for cmake 4 years ago
MITSUNARI Shigeo c060dea39d add default value to cmake 4 years ago
MITSUNARI Shigeo 384b600009 remove mclshe and ecdsa test from cmake 4 years ago
MITSUNARI Shigeo c0b7fb89f7 remove mclshe and mclecdsa 4 years ago
MITSUNARI Shigeo 6ffc879fce Merge branch 'master' of https://github.com/bitFlyer-Blockchain/mcl into bitFlyer-Blockchain-master 4 years ago
MITSUNARI Shigeo 8414aace7d Merge commit '0f6f5a1' into dev 4 years ago
MITSUNARI Shigeo ce6bfe4a45 Merge commit '50170e0' into dev 4 years ago
MITSUNARI Shigeo 793ef212c9 if CXX is defined then use it on OpenSBD 4 years ago
Mohamed Amin JABRI 4797e01714 Add project/soname version. 4 years ago
Mohamed Amin JABRI 45cde91626 Update readme: mention build.sh convenience script to build mcl on 4 years ago
Mohamed Amin JABRI 852b2a53e1 Improve cmake build. 4 years ago
Mohamed Amin JABRI 0f6f5a148b Make DllImport for mclBn256 cross-plateform (remove .dll extension) 4 years ago
Mohamed Amin JABRI 50170e0d57 Fix BOM at begining of file. 4 years ago
Alexander van der Meij b575c9c188 allow building on openbsd using clang 4 years ago
MITSUNARI Shigeo 90b4dc254e init is not necessary 4 years ago
MITSUNARI Shigeo c6c6e49eb8 remove unused old functions 4 years ago
MITSUNARI Shigeo a145a2144a nothrow version(TBD) 4 years ago
MITSUNARI Shigeo 9b86774989 update xbyak v5.941 4 years ago
MITSUNARI Shigeo 49e6633eaa add test of isValidOrder 4 years ago
MITSUNARI Shigeo 9eb8c7d1f5 update cybozulib 4 years ago
MITSUNARI Shigeo b3c2480266 [C#] add test of mapToG1 4 years ago
MITSUNARI Shigeo 2e989e6d7c [C#] how to init for ETH 4 years ago
MITSUNARI Shigeo 68ec65aec1 [C#] update doc 4 years ago
MITSUNARI Shigeo b4d8a29e5d [C#] add static member 4 years ago
MITSUNARI Shigeo 42fc50a240 Merge branch 'netstandard' into dev 4 years ago
MITSUNARI Shigeo 4a23b96b30 link to pull/82 4 years ago
jonny rhea 5b221f05eb fixes a CALL16 reloc error when compiling with mip toolchain. 4 years ago
MITSUNARI Shigeo d4d9091e54 change the return type of getCurveParam 4 years ago
MITSUNARI Shigeo aa9ace2f82 [C#] add readme.md 4 years ago
MITSUNARI Shigeo 58898ff5c7 [C#] add Normalize 4 years ago
MITSUNARI Shigeo ae670c82f7 [C#] add Serialize/Deserialize 4 years ago
MITSUNARI Shigeo 0901e76cc2 mklib makes dll without OpenSSL/GMP 4 years ago
MITSUNARI Shigeo 6ddebac588 remove warning of vc 4 years ago
MITSUNARI Shigeo d309a4a28a add C# bindings 4 years ago
MITSUNARI Shigeo 526d39af3d [she] disable exception catching 4 years ago
MITSUNARI Shigeo d79c5acb48 rename inner functions of MapTo 4 years ago
MITSUNARI Shigeo c193bb4cfe mclBn_eth* functions are removed 4 years ago
MITSUNARI Shigeo 730c50d4ea remove old eth hash-functions 4 years ago
MITSUNARI Shigeo 7909bd297b mcl::bn::mapToG1 is compatible to MAP_TO_G1 in eip-2537 4 years ago
MITSUNARI Shigeo 322b90c160 remove unnecessary param 4 years ago
MITSUNARI Shigeo e9e5f9fcf1 v1.20 4 years ago
MITSUNARI Shigeo 258b63c487 change mode of hashAndMapToG1 4 years ago
MITSUNARI Shigeo c7120c8963 reduce Fp::div in iso11 4 years ago
MITSUNARI Shigeo 718de1493c add hash-to-curve g1 test 4 years ago
MITSUNARI Shigeo 61e2971611 add g1cofactor 4 years ago
MITSUNARI Shigeo 65bb0890ca add iso11 4 years ago
MITSUNARI Shigeo 732c6b0993 add sswuG1 for E1 4 years ago
MITSUNARI Shigeo 7333742229 rename vars in mapto 4 years ago
MITSUNARI Shigeo 2488fa3f6d add init_iso11 4 years ago
MITSUNARI Shigeo 6a71548dde sswuG1 4 years ago
MITSUNARI Shigeo 066d3accf5 add 11 to mulSmallUnit 4 years ago
MITSUNARI Shigeo e1237ab19b remove unused code 4 years ago
MITSUNARI Shigeo eb4cdddf02 expand_message_xmd for G1 4 years ago
MITSUNARI Shigeo 9e0148698d add test of draft07 4 years ago
MITSUNARI Shigeo 7c3f6c3c63 fix link of url in readme.md 4 years ago
MITSUNARI Shigeo 5e561369e6
Merge pull request #81 from ineffectualproperty/patch-1 4 years ago
Kelly Olson 574cabc15f
Update readme.md to fix URLs 4 years ago
MITSUNARI Shigeo ef4a9de257 fix ec comparison with zero 4 years ago
MITSUNARI Shigeo e48973af50 add mclBnFr_setBigEndianMod 4 years ago
MITSUNARI Shigeo 2f3ccdde99 modify emcc option for mcl-wasm 4 years ago
MITSUNARI Shigeo 34afe9cdda mcl-wasm generates mcl_c384_256.{js,wasm} 4 years ago
MITSUNARI Shigeo 0928a17647 cmake install bn_c*.h headers 4 years ago
MITSUNARI Shigeo 0741627756 add CRYPT_VERIFYCONTEXT to CryptoAcquireContext 4 years ago
MITSUNARI Shigeo 69f890ae17 v1.11 4 years ago
MITSUNARI Shigeo f3f27d5b0d maxMulVecNGLV can be redefined 4 years ago
MITSUNARI Shigeo f6c46616ed update xbyak 4 years ago
MITSUNARI Shigeo 74f1b42f72 some old eth* functions will be duplicated 4 years ago
MITSUNARI Shigeo 3acf697650 reduce stack size for Gi::mul 4 years ago
MITSUNARI Shigeo 7fe3e07cdb [doc] fix link 4 years ago
MITSUNARI Shigeo 66716376b1 Azure App Service requires CRYPT_MACHINE_KEYSET 5 years ago
MITSUNARI Shigeo 42b0fb05ad remove vc warnings 5 years ago
MITSUNARI Shigeo 2095a80e17 aggs supports serialize 5 years ago
MITSUNARI Shigeo b27ecb2fc4 add test of hash-to-curve-08 5 years ago
MITSUNARI Shigeo fd8352e1a5 v1.10 5 years ago
MITSUNARI Shigeo 4527c4aa08 unify mulVecNGLV 5 years ago
MITSUNARI Shigeo 67672f4050 refactor mul 5 years ago
MITSUNARI Shigeo 2ede71f70c refactor mulCT 5 years ago
MITSUNARI Shigeo d51fd79c86 setBigEndianMod 5 years ago
MITSUNARI Shigeo 7b4eb83d5b hashAndMapToG2 support draft-07 5 years ago
MITSUNARI Shigeo 21dbb7ab8b v1.08 5 years ago
MITSUNARI Shigeo cb4fea5d66 update link to test 5 years ago
MITSUNARI Shigeo 19ece2524b add test of draft-07 5 years ago
MITSUNARI Shigeo d5f287bcc7 test of msgToG2 for draft-07 5 years ago
MITSUNARI Shigeo eb5f51a9af hashToFp2 supports draft-07 5 years ago
MITSUNARI Shigeo 711ae42072 rename old hashTo function 5 years ago
MITSUNARI Shigeo 63cb8d0d24 add sgn0 of draft-07 5 years ago
MITSUNARI Shigeo f1313a6831 add test of draft-07 5 years ago
MITSUNARI Shigeo 336c69d799 expand_message_xmd for draft-07 5 years ago
MITSUNARI Shigeo 2c24950b03 Z_pad is static constant 5 years ago
MITSUNARI Shigeo 95e80e3c7b remove warning of vc 5 years ago
MITSUNARI Shigeo 03a9c3f486 add link to GitHub Sponsor 5 years ago
MITSUNARI Shigeo bff17bffc7 how to profile by perf/vtune 5 years ago
MITSUNARI Shigeo 3b8caf72bc support llvm-9 or 10 but the generated code is slow 5 years ago
MITSUNARI Shigeo 74342272a3 4% speedup by removing unnecessary cstr 5 years ago
MITSUNARI Shigeo bd66a8b07b remove stack-protector option 5 years ago
MITSUNARI Shigeo 59418d6621 use mulByCofactorBLS12fast 5 years ago
MITSUNARI Shigeo 753e322c80 remove unnecessary test 5 years ago
MITSUNARI Shigeo 90a594a802 use Fp::isNegative() 5 years ago
MITSUNARI Shigeo d3f19c82cc add mapto benchmark 5 years ago
MITSUNARI Shigeo b23b7e1088 [wasm] add __multi3 5 years ago
MITSUNARI Shigeo 21f666d80c [wasm] remove warning of function signature mismatch 5 years ago
MITSUNARI Shigeo 3bfc2d3457 [she] fix compile error on clang 5 years ago
MITSUNARI Shigeo 2dd76c7b67 unify ec operations 5 years ago
MITSUNARI Shigeo 41c11a0f75 move unused functions to test.cpp 5 years ago
MITSUNARI Shigeo a0dcc763f8 refactor mapto 5 years ago
MITSUNARI Shigeo 7e6ab212fb refactor ec::dbl 5 years ago
MITSUNARI Shigeo 9c62b3d964 refactor ec 5 years ago
MITSUNARI Shigeo 75b1a8adc7 rename tag name of special a 5 years ago
MITSUNARI Shigeo a03605c57f mov ec operation to global 5 years ago
MITSUNARI Shigeo 88688c210c change name of test var 5 years ago
MITSUNARI Shigeo 14f9e64a54 add affine test 5 years ago
MITSUNARI Shigeo 8234909744 move some methods to global 5 years ago
MITSUNARI Shigeo 16fe1740de remove unused code 5 years ago
MITSUNARI Shigeo b96acf6e86 DST for hash-to-curve is changed 5 years ago
MITSUNARI Shigeo 6544951800 add one test from draft-irtf-cfrg-hash-to-curve 5 years ago
MITSUNARI Shigeo 9f01ea3ec9 add test of hashToFp2v6 5 years ago
MITSUNARI Shigeo 9c3f370c88 support hash-to-curve-06 5 years ago
MITSUNARI Shigeo 00c9cb00a1 remove clang warning 5 years ago
MITSUNARI Shigeo 1b043ade54 dirty hack of multi curve instance 5 years ago
MITSUNARI Shigeo a53b6b7f4c use _udiv128 for divUint on msvc 2019 5 years ago
MITSUNARI Shigeo a004a00952 remove warning of vc in fp_test 5 years ago
MITSUNARI Shigeo 554eeb5ff7 Merge branch 'earonesty-windows-dynamic' 5 years ago
erik aronesty c155ee3960 allow windows users to choose dynamic runtime dll build 5 years ago
MITSUNARI Shigeo e0f7f5d073 add test of window_method 5 years ago
MITSUNARI Shigeo 04157779d6 add CipherTestGi::isValid() 5 years ago
MITSUNARI Shigeo 959a0548d5 add IoEcAffineSerialize for serialize 5 years ago
MITSUNARI Shigeo 5d2379b226 v1.05 5 years ago
MITSUNARI Shigeo 1a7610fc84 [change] ethMsgToFp2 addes zero byte at the end of msg 5 years ago
MITSUNARI Shigeo 6f8d014f2c add some functions of py_ecc 5 years ago
MITSUNARI Shigeo e4f3027737 add optimized_swu_G2 5 years ago
MITSUNARI Shigeo f483ec41d7 refactor mapto test 5 years ago
MITSUNARI Shigeo fee5144d0f use eth* functions for c api 5 years ago
MITSUNARI Shigeo 0870bc8251 add eth hash functions for c++ 5 years ago
MITSUNARI Shigeo 8e71598093 add serializeToHexStr/deserializeHexStr 5 years ago
MITSUNARI Shigeo 124dd293a8 update version 5 years ago
MITSUNARI Shigeo 8f022a3de3 update readme.md 5 years ago
MITSUNARI Shigeo ede75f1645 add test of mclBn_ethMsgToG2 5 years ago
MITSUNARI Shigeo 83d3517b10 add mclBn_eth* 5 years ago
MITSUNARI Shigeo 50dde8fda1 add test of opt_swu2_map 5 years ago
MITSUNARI Shigeo f0df4f202b add a test of status-im/nim-blscurve 5 years ago
MITSUNARI Shigeo 601abdb208 test of mapToG2_WB19 5 years ago
MITSUNARI Shigeo b5c2edee03 init mapToG2_WBP19 in initBLS12 5 years ago
MITSUNARI Shigeo 7e827b9951
Merge pull request #71 from prprhyt/fix-she-api.md 5 years ago
prprhyt 1249f8600c Fix she-api documents 5 years ago
MITSUNARI Shigeo fc1b24d5e1 add msgToG2 5 years ago
MITSUNARI Shigeo 18b0a3bfa4 add hkdf_extract without adding zero byte 5 years ago
MITSUNARI Shigeo 2f9f142043 fix indent 5 years ago
MITSUNARI Shigeo b8fcf48e3b update comments for MAP_TO_MODE 5 years ago
MITSUNARI Shigeo 0737cbfa65 add getMapToMode 5 years ago
MITSUNARI Shigeo 77e4c0a9d1 compact h2_chain 5 years ago
MITSUNARI Shigeo 63fb03524b move hkdf_* to src/fp.cpp 5 years ago
MITSUNARI Shigeo c4472e1747 add map2curve_osswu2 5 years ago
MITSUNARI Shigeo e6bb40a838 add Fp::setArrayMod 5 years ago
MITSUNARI Shigeo 8877933592 add cybozu/file.hpp 5 years ago
MITSUNARI Shigeo 5f884f86ae add hmac256addZeroByte 5 years ago
MITSUNARI Shigeo 5200c33d44 update cybozulib 5 years ago
MITSUNARI Shigeo 8ec855f162 add maptg2_wb19 5 years ago
MITSUNARI Shigeo ecbc4e403c fix Makefile of pairing_c_min.exe 5 years ago
MITSUNARI Shigeo 844d9bb439 update xbyak 5.85 5 years ago
MITSUNARI Shigeo 6ff5cfa9fc v1.03 5 years ago
MITSUNARI Shigeo 0eb04f7e8a default disable to verifyOrder 5 years ago
MITSUNARI Shigeo fbe7d2e38d enable llvm-bmi2 without xbyak 5 years ago
MITSUNARI Shigeo d26bee4e33 fix typo 5 years ago
MITSUNARI Shigeo b399592446 refactor according to issues/69 5 years ago
MITSUNARI Shigeo 0dfad75069 v1.02 5 years ago
MITSUNARI Shigeo e27af0393c disable OpenSSL(default) 5 years ago
MITSUNARI Shigeo 54ed316fe1 rename TRY_AND_INC 5 years ago
MITSUNARI Shigeo bfd0459d2f disable GMP on macOS Catalina 5 years ago
MITSUNARI Shigeo 0fe07b047c fix vint_test with MCL_USE_GMP=0 5 years ago
MITSUNARI Shigeo d3aaf45e0f add option to select algorithm for G2::mulByCofactor 5 years ago
MITSUNARI Shigeo df7a1b5ff2 get g2 cofactor adj function 5 years ago
MITSUNARI Shigeo 9a1c70a59e faster multiplication of original G2 cofactor 5 years ago
MITSUNARI Shigeo 120ac2b1a9 fix typo 5 years ago
MITSUNARI Shigeo f796b73629 [doc] add comments for mulByCofactorBLS12 5 years ago
MITSUNARI Shigeo a549f8dbdc v1.01 5 years ago
MITSUNARI Shigeo 19b3493db2 [eth2] add benchmark of mapToG2 5 years ago
MITSUNARI Shigeo 506a8c954a [go] add some configration functions 5 years ago
MITSUNARI Shigeo f6aaf49fea [go] add MapToGi 5 years ago
MITSUNARI Shigeo 2113045aa6 add setOriginalG2cofactor 5 years ago
MITSUNARI Shigeo c0abe65cdf enable setETHserialization for Fr 5 years ago
MITSUNARI Shigeo 1b4f4335b0 change the format of zero 5 years ago
MITSUNARI Shigeo 8c56aed56c [go] add DeserializeUncompressed 5 years ago
MITSUNARI Shigeo 0aface885b ETH2.0 spec 5 years ago
MITSUNARI Shigeo 432b5457d4 split calcGi insto mapToEc and mulByCofactor 5 years ago
MITSUNARI Shigeo 3013b7d90b add dependency of bn_c384_256.cpp 5 years ago
MITSUNARI Shigeo 26c565176d [go] public member of G1/G2 5 years ago
MITSUNARI Shigeo 92681e984e [go] add some operations in bn.h 5 years ago
MITSUNARI Shigeo 402b825fc0 go fmt 5 years ago
MITSUNARI Shigeo b108b31c17 disable hash if DONT_USE_EXCEPTION 5 years ago
MITSUNARI Shigeo 5e02eafe9e fix for 32-bit env 5 years ago
MITSUNARI Shigeo 92539b0cd7 cybozu::Stream supports -fno-exceptions 5 years ago
MITSUNARI Shigeo cf437ac839 fix typo 5 years ago
MITSUNARI Shigeo 4d3f4009cc fix typo 5 years ago
MITSUNARI Shigeo 675e87005d [go] add G1MulVec, G2MulVec, MillerLoopVec 5 years ago
MITSUNARI Shigeo 910993eba8 v1.00 5 years ago
MITSUNARI Shigeo e41ef6d6c9 add api.md 5 years ago
MITSUNARI Shigeo c68217b9a7 add mclBnF{p,r}_isOdd 5 years ago
MITSUNARI Shigeo b21c80153a add macro for ioMode of getStr 5 years ago
MITSUNARI Shigeo 5259465695 add mclBnF{r,p}_isNegative 5 years ago
MITSUNARI Shigeo 4bb5bb702d add mclBnGT_invGeneric 5 years ago
MITSUNARI Shigeo 045de218ff fix comments of EvaluatePolynomial 5 years ago
MITSUNARI Shigeo 0ddc477823 sample/pairing.cpp uses BLS12-381 5 years ago
MITSUNARI Shigeo 1257ac7e36 pairing_c.c uses BLS12-381 5 years ago
MITSUNARI Shigeo 33bfcf4ac5 update doc 5 years ago
MITSUNARI Shigeo 26d9039b6c enable profile if MCL_PROF=2 5 years ago
MITSUNARI Shigeo 8c617ba67b remove warning 5 years ago
MITSUNARI Shigeo 5d6d1c51cc build bn_c384_256.dll 5 years ago
MITSUNARI Shigeo 3d619e0055 v0.99 5 years ago
MITSUNARI Shigeo e669a7a462 add mclBnG{1,2,T}_mulVec 5 years ago
MITSUNARI Shigeo 3039bdb86f change mulVec interface 5 years ago
MITSUNARI Shigeo afb1c812f1 support mulVec 5 years ago
MITSUNARI Shigeo 72c8c830e2 Merge branch 'dev' 5 years ago
MITSUNARI Shigeo 9f09970f70 fix for c++03 5 years ago
MITSUNARI Shigeo 2f1b4c9a56 new mulVec 5 years ago
MITSUNARI Shigeo 0cec8d45ef add test of mulVec 5 years ago
MITSUNARI Shigeo 58265a1e09 remove warning of vc 5 years ago
MITSUNARI Shigeo b46e0071ce use new mulArray 5 years ago
MITSUNARI Shigeo 3667c260fd [doc] fix support curveType 5 years ago
MITSUNARI Shigeo 51a3a60726 v0.98 5 years ago
MITSUNARI Shigeo 018bbe8e88 [she] add test sheMul 5 years ago
MITSUNARI Shigeo f4a2d2e3be add test for Ec::add, dbl 5 years ago
MITSUNARI Shigeo 6f82259d9e [bug] fix Ec::add(A, B, A) for no-normalized A, B 5 years ago
MITSUNARI Shigeo 13d9500f3f Ec::mulSmallInt errors if negative 5 years ago
MITSUNARI Shigeo 846b4ff8f6 add Ec::mulSmallInt 5 years ago
MITSUNARI Shigeo aebcdf1a83 mulVec 5 years ago
MITSUNARI Shigeo 2c2db22773 start to develop Ec::mulVec 5 years ago
MITSUNARI Shigeo 43a1e4983d add test of squareRootFp2 5 years ago
MITSUNARI Shigeo daaabddf1d add mclBnFp2_{add,sub,mul,div,neg,sqr,inv} 5 years ago
MITSUNARI Shigeo 1d6b4302ad add comments to mcl{Fr,Fp,Fp2,G1,G2} 5 years ago
MITSUNARI Shigeo e8dd8a68a0 add squareRoot into bn.h 5 years ago
MITSUNARI Shigeo 68f332d0ae change members of mclBn{Fp,G1,G2} 5 years ago
MITSUNARI Shigeo 1d7c99e8a7 add millerLoopVec 5 years ago
MITSUNARI Shigeo 7df73796d5 remove assert 5 years ago
MITSUNARI Shigeo 1d2f4cb29b optimize millerLoopVec 5 years ago
MITSUNARI Shigeo b74ec0cf1b refactor millerLoop 5 years ago
MITSUNARI Shigeo 3ec6ea8a0e remove unnecessary set 5 years ago
MITSUNARI Shigeo 6761619ba6 use secp256k1 in sample/ecdh.cpp 5 years ago
MITSUNARI Shigeo e769bd6cea Merge branch 'dev' 5 years ago
MITSUNARI Shigeo 40a2ec8fd8 fix include dependency of ec.hpp 5 years ago
MITSUNARI Shigeo b26ee426eb support jit profiler for VTune 5 years ago
MITSUNARI Shigeo 5298f0d260 [xbyak] update 5 years ago
MITSUNARI Shigeo 2c8d7947b7 add cybozu/*.hpp 5 years ago
MITSUNARI Shigeo c93811dde1 disable warning of cybozu::Option 5 years ago
MITSUNARI Shigeo cbc1f48da2 [cybozu] disable warning 5 years ago
MITSUNARI Shigeo 73ee7d5bd3 add cybozu/time.hpp 5 years ago
MITSUNARI Shigeo 572fa8d816 add millerLoopVec 5 years ago
MITSUNARI Shigeo c0efee00e1 [she] add getNonConstRef() for test 5 years ago
MITSUNARI Shigeo d493249b39 v0.97 5 years ago
MITSUNARI Shigeo 21dedae745 add mclBnFp_* like as mclBnFp_* 5 years ago
MITSUNARI Shigeo 55a1de171b [doc] update getStr(mode) 5 years ago
MITSUNARI Shigeo 0a638c7ad2 add mclBn{Fr,Fp}_getLittleEndian 5 years ago
MITSUNARI Shigeo bb287f8f11 add Fp::getLittleEndian 5 years ago
MITSUNARI Shigeo b84d0c7fe0 dump() accepts const void* 5 years ago
MITSUNARI Shigeo a6cab0b385 common.mk detects armv6l 5 years ago
MITSUNARI Shigeo 0f3aae4feb add openmp option to setvar.bat 5 years ago
MITSUNARI Shigeo 6e9f21d1af [she] use initCurve 5 years ago
MITSUNARI Shigeo b57e25f0cf old codes use initCurve 5 years ago
MITSUNARI Shigeo 85163ee003 add initCurve 5 years ago
MITSUNARI Shigeo 4c376d551e test of GT::pow 5 years ago
MITSUNARI Shigeo 96e6d628ec v0.96 improved scalar multiplication 5 years ago
MITSUNARI Shigeo 5b453fda2b v0.96 5 years ago
MITSUNARI Shigeo 3c98ac00c8 enable GLV for secp256k1 5 years ago
MITSUNARI Shigeo 2053b495a7 simplify GLV1T class 5 years ago
MITSUNARI Shigeo 626663b8db secp256k1 supports GLV method 5 years ago
MITSUNARI Shigeo 14465da205 move GLV1 to ec.hpp 5 years ago
MITSUNARI Shigeo 53028c4a98 GLV1 is template class 5 years ago
MITSUNARI Shigeo 2762669e4c test of GLV for secp256k1 5 years ago
MITSUNARI Shigeo 8118e08dc2 add FixedVec::value_type 5 years ago
MITSUNARI Shigeo 72a3ee5dc9 add FixedVec::value_type 5 years ago
MITSUNARI Shigeo cc1396f753 GLV2 supports GT::pow 5 years ago
MITSUNARI Shigeo de44c1336d rewrite GLV2::mul 5 years ago
MITSUNARI Shigeo 38d97e0802 disable many warnings of LSAN 5 years ago
MITSUNARI Shigeo cbf3c2ccc2 remove old comments 5 years ago
MITSUNARI Shigeo b1ef09c6c4 fix GLV1::mul(0) 5 years ago
MITSUNARI Shigeo 0931176c76 use wider naf for G1::mul 5 years ago
MITSUNARI Shigeo 3354927f26 add getNAFwidth 5 years ago
MITSUNARI Shigeo c4087c70f7 remove unused code 5 years ago
MITSUNARI Shigeo 38d82215f6 [doc] fix link to reference 5 years ago
MITSUNARI Shigeo 9d7d6f5041 [java] use Swig 4.0.0 5 years ago
MITSUNARI Shigeo d893c71d87 [java] change C++ version 5 years ago
MITSUNARI Shigeo a139f3291e [java] ignore -Wdeprecated 5 years ago
MITSUNARI Shigeo 7b21820c8a define hash for g++ of Mac 5 years ago
MITSUNARI Shigeo 4a5202567c [java] update documents 5 years ago
MITSUNARI Shigeo 4797680018 [she] fix compile error of she-wasm 5 years ago
MITSUNARI Shigeo dd19f1c350 [java] fix indent 5 years ago
MITSUNARI Shigeo d403ab84c6 [java] support windows 5 years ago
MITSUNARI Shigeo db79a61ed0 [java] fix path for mac 5 years ago
MITSUNARI Shigeo e50de173a3 [java] add serialize/deserialize 5 years ago
MITSUNARI Shigeo 562337b152 v0.95 fix a parser of 0b10 with base = 16 5 years ago
MITSUNARI Shigeo 24be4c8de1 [java] change Bn256 to Mcl 5 years ago
MITSUNARI Shigeo 17d2b0c18d [java] jni for BN254(old) 5 years ago
MITSUNARI Shigeo 977053396a disable addLine/dblLine test for Proj 6 years ago
MITSUNARI Shigeo 0363aee113 use Jacobi instead of Proj 6 years ago
MITSUNARI Shigeo a344ac8035 fix install for Darwin 6 years ago
  1. 25
      .github/workflows/main.yml
  2. 3
      .gitignore
  3. 17
      .travis.yml
  4. 420
      CMakeLists.txt
  5. 104
      Makefile
  6. 548
      api.md
  7. 67
      build.sh
  8. 88
      cmake/FindGMP.cmake
  9. 64
      common.mk
  10. 115
      ffi/cs/bn256.cs
  11. 31
      ffi/cs/mcl.sln
  12. 1007
      ffi/cs/mcl/mcl.cs
  13. 13
      ffi/cs/mcl/mcl.csproj
  14. 24
      ffi/cs/readme.md
  15. 408
      ffi/cs/test/test.cs
  16. 28
      ffi/cs/test/test.csproj
  17. 3
      ffi/go/mcl/init.go
  18. 597
      ffi/go/mcl/mcl.go
  19. 145
      ffi/go/mcl/mcl_test.go
  20. 104
      ffi/java/Bn256Test.java
  21. 2
      ffi/java/ElgamalTest.java
  22. 41
      ffi/java/Makefile
  23. 160
      ffi/java/MclTest.java
  24. 39
      ffi/java/android/jni/Android.mk
  25. 4
      ffi/java/android/jni/Application.mk
  26. 31
      ffi/java/bn256.i
  27. 249
      ffi/java/bn256_impl.hpp
  28. 1542
      ffi/java/bn256_wrap.cxx
  29. 67
      ffi/java/com/herumi/mcl/CipherText.java
  30. 38
      ffi/java/com/herumi/mcl/Elgamal.java
  31. 51
      ffi/java/com/herumi/mcl/ElgamalJNI.java
  32. 105
      ffi/java/com/herumi/mcl/Fp.java
  33. 113
      ffi/java/com/herumi/mcl/Fr.java
  34. 93
      ffi/java/com/herumi/mcl/G1.java
  35. 89
      ffi/java/com/herumi/mcl/G2.java
  36. 81
      ffi/java/com/herumi/mcl/GT.java
  37. 128
      ffi/java/com/herumi/mcl/Mcl.java
  38. 14
      ffi/java/com/herumi/mcl/MclConstants.java
  39. 120
      ffi/java/com/herumi/mcl/MclJNI.java
  40. 87
      ffi/java/com/herumi/mcl/PrivateKey.java
  41. 83
      ffi/java/com/herumi/mcl/PublicKey.java
  42. 26
      ffi/java/com/herumi/mcl/SWIGTYPE_p_bool.java
  43. 15
      ffi/java/elgamal_impl.hpp
  44. 118
      ffi/java/elgamal_wrap.cxx
  45. 77
      ffi/java/java.md
  46. 6
      ffi/java/make_wrap.bat
  47. 29
      ffi/java/mcl.i
  48. 436
      ffi/java/mcl_impl.hpp
  49. 2681
      ffi/java/mcl_wrap.cxx
  50. 9
      ffi/java/run-bn256.bat
  51. 9
      ffi/java/run-mcl.bat
  52. 9
      ffi/python/Makefile
  53. 7
      ffi/python/readme.md
  54. 2
      ffi/python/she.py
  55. 5
      include/cybozu/atoi.hpp
  56. 146
      include/cybozu/atomic.hpp
  57. 5
      include/cybozu/exception.hpp
  58. 626
      include/cybozu/file.hpp
  59. 2
      include/cybozu/hash.hpp
  60. 9
      include/cybozu/inttype.hpp
  61. 3
      include/cybozu/itoa.hpp
  62. 3
      include/cybozu/mutex.hpp
  63. 26
      include/cybozu/option.hpp
  64. 30
      include/cybozu/random_generator.hpp
  65. 59
      include/cybozu/sha2.hpp
  66. 785
      include/cybozu/socket.hpp
  67. 2
      include/cybozu/stream.hpp
  68. 281
      include/cybozu/time.hpp
  69. 60
      include/mcl/aggregate_sig.hpp
  70. 76
      include/mcl/ahe.hpp
  71. 10
      include/mcl/array.hpp
  72. 117
      include/mcl/bn.h
  73. 905
      include/mcl/bn.hpp
  74. 2
      include/mcl/conversion.hpp
  75. 87
      include/mcl/curve_type.h
  76. 1688
      include/mcl/ec.hpp
  77. 105
      include/mcl/ecdsa.h
  78. 257
      include/mcl/ecdsa.hpp
  79. 28
      include/mcl/ecparam.hpp
  80. 2
      include/mcl/elgamal.hpp
  81. 109
      include/mcl/fp.hpp
  82. 373
      include/mcl/fp_tower.hpp
  83. 161
      include/mcl/gmp_util.hpp
  84. 194
      include/mcl/impl/bn_c_impl.hpp
  85. 572
      include/mcl/mapto_wb19.hpp
  86. 48
      include/mcl/op.hpp
  87. 46
      include/mcl/operator.hpp
  88. 27
      include/mcl/she.h
  89. 317
      include/mcl/she.hpp
  90. 61
      include/mcl/util.hpp
  91. 119
      include/mcl/vint.hpp
  92. 30
      include/mcl/window_method.hpp
  93. 6
      misc/Makefile
  94. 234
      misc/low_test.cpp
  95. 119
      misc/she/memo.txt
  96. 14
      misc/she/she-api-ja.md
  97. 24
      misc/she/she-api.md
  98. 18
      misc/snark-p.py
  99. 29
      mklib.bat
  100. 540
      readme.md
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,25 @@
name: test
on: [push]
jobs:
build:
name: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: lscpu
- run: sudo apt install valgrind
- run: make bin/pairing.exe -j4
- run: valgrind bin/pairing.exe
- run: make clean
# - run: wget https://software.intel.com/content/dam/develop/external/us/en/documents/downloads/sde-external-8.63.0-2021-01-18-lin.tar.bz2
# - run: bzip2 -dc sde-external-8.63.0-2021-01-18-lin.tar.bz2 | tar xvf -
# - run: make bin/bn_test.exe DEBUG=1 -j4
# - run: sde-external-8.63.0-2021-01-18-lin/sde64 -hsw -- bin/bn_test.exe
- run: make test_ci DEBUG=1 -j4
- run: make clean
- run: make test_ci DEBUG=1 -j4 CXX=clang++
- run: make clean
# - run: make test_go
# - run: sudo apt install openjdk-8-jdk
# - run: make -C ffi/java test JAVA_INC=-I/usr/lib/jvm/java-8-openjdk-amd64/include

3
.gitignore vendored

@ -11,3 +11,6 @@ GTAGS
*.exe
*.swp
.cvsignore
build/
external/
Testing/

@ -1,17 +0,0 @@
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

@ -1,209 +1,395 @@
cmake_minimum_required (VERSION 3.0)
project(mcl CXX ASM)
set(SRCS src/fp.cpp)
cmake_minimum_required (VERSION 3.8)
project(mcl
VERSION 1.22
LANGUAGES CXX C ASM)
set(CMAKE_BUILD_TYPE "Release")
option(
MCL_MAX_BIT_SIZE
"max bit size for Fp"
0
384
)
option(
DOWNLOAD_SOURCE
"download cybozulib_ext"
MCL_STATIC_LIB
"build static library"
OFF
)
if(MSVC)
option(
MCL_DOWNLOAD_SOURCE
"download cybozulib_ext"
OFF
)
endif()
option(
USE_OPENSSL
MCL_USE_OPENSSL
"use openssl"
ON
OFF
)
option(
USE_GMP
MCL_USE_GMP
"use gmp"
ON
)
option(
USE_ASM
MCL_USE_ASM
"use asm"
ON
)
option(
USE_XBYAK
MCL_USE_XBYAK
"use xbyak"
ON
)
option(
USE_LLVM
MCL_USE_LLVM
"use base64.ll with -DCMAKE_CXX_COMPILER=clang++"
OFF
)
option(
ONLY_LIB
"only lib"
MCL_BUILD_SAMPLE
"Build mcl samples"
OFF
)
option(
MCL_BUILD_TESTING
"Build mcl tests"
OFF
)
if(MSVC)
option(
MCL_MSVC_RUNTIME_DLL
"use dynamic runtime /MD in msvc builds"
OFF
)
endif()
if(MSVC)
set(MCL_CYBOZULIB_EXT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../cybozulib_ext"
CACHE PATH "external cybozulib_ext directory")
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
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)
if(USE_LLVM)
if(MCL_USE_LLVM AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
message(WARNING "MCL_USE_LLVM will not be used: requiring clang/clang++.")
endif()
add_library(mcl SHARED src/fp.cpp)
add_library(mcl::mcl ALIAS mcl)
target_compile_definitions(mcl PUBLIC MCL_NO_AUTOLINK MCLBN_NO_AUTOLINK)
target_include_directories(mcl PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:$CMAKE_INSTALL_DIR/include>)
set_target_properties(mcl PROPERTIES
POSITION_INDEPENDENT_CODE ON)
set_target_properties(mcl PROPERTIES
OUTPUT_NAME mcl
VERSION ${mcl_VERSION}
SOVERSION ${mcl_VERSION_MAJOR})
# 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
add_library(mcl_st STATIC src/fp.cpp)
add_library(mcl::mcl_st ALIAS mcl_st)
target_compile_definitions(mcl_st PUBLIC MCL_NO_AUTOLINK MCLBN_NO_AUTOLINK)
target_include_directories(mcl_st PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:$CMAKE_INSTALL_DIR/include>)
set_target_properties(mcl_st PROPERTIES
OUTPUT_NAME mcl
POSITION_INDEPENDENT_CODE ON)
#set_target_properties(mcl_st PROPERTIES PREFIX "lib")
if(MCL_USE_LLVM AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_executable(gen src/gen.cpp)
add_custom_target(base64.ll
DEPENDS gen
SOURCES base64.ll
)
target_include_directories(gen PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include)
if(MCL_USE_GMP)
find_package(GMP REQUIRED)
target_link_libraries(gen PRIVATE GMP::GMPXX GMP::GMP)
endif()
add_custom_command(OUTPUT base64.ll
COMMAND gen > base64.ll
)
add_custom_target(base64.o
DEPENDS base64.ll
SOURCES base64.o
)
DEPENDS gen
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_custom_target(gen_base64.ll
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/base64.ll)
add_custom_command(OUTPUT base64.o
COMMAND ${CMAKE_CXX_COMPILER} -c -o base64.o base64.ll -O3 -fPIC
)
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/base64.ll
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_custom_target(gen_base64.o
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/base64.o)
target_link_libraries(mcl PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/base64.o)
add_dependencies(mcl gen_base64.o)
target_link_libraries(mcl_st PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/base64.o)
add_dependencies(mcl_st gen_base64.o)
endif()
if(MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MT /W4 /Oy /Ox /EHsc /GS- /Zi /DNDEBUG /DNOMINMAX")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /MTd /W4 /DNOMINMAX")
link_directories(${CMAKE_SOURCE_DIR}/../cybozulib_ext/lib)
link_directories(${CMAKE_SOURCE_DIR}/lib)
else()
if("${CFLAGS_OPT_USER}" STREQUAL "")
set(CFLAGS_OPT_USER "-O3 -DNDEBUG -march=native")
if(MCL_MSVC_RUNTIME_DLL)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MD /Oy /Ox /EHsc /GS- /Zi /DNDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /MDd")
else()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MT /Oy /Ox /EHsc /GS- /Zi /DNDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /MTd")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith ${CFLAGS_OPT_USER}")
target_compile_definitions(mcl PUBLIC NOMINMAX)
target_compile_definitions(mcl_st PUBLIC NOMINMAX)
# set compiler flags for warnings level
set(MCL_COMPILE_OPTIONS /W4)
target_compile_options(mcl PRIVATE ${MCL_COMPILE_OPTIONS})
target_compile_options(mcl_st PRIVATE ${MCL_COMPILE_OPTIONS})
else()
# Set compiler flags for warnings
set(MCL_COMPILE_OPTIONS -Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align
-Wwrite-strings -Wfloat-equal -Wpointer-arith -DNDEBUG -O3 -fPIC)
target_compile_options(mcl PRIVATE ${MCL_COMPILE_OPTIONS})
target_compile_options(mcl_st PRIVATE ${MCL_COMPILE_OPTIONS})
set_target_properties(mcl PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO)
set_target_properties(mcl_st PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO)
target_compile_features(mcl PUBLIC cxx_std_11)
target_compile_features(mcl_st PUBLIC cxx_std_11)
if(${MCL_MAX_BIT_SIZE} GREATER 0)
add_definitions(-DMCL_MAX_BIT_SIZE=${MCL_MAX_BIT_SIZE})
target_compile_definitions(mcl PUBLIC MCL_MAX_BIT_SIZE=${MCL_MAX_BIT_SIZE})
target_compile_definitions(mcl_st PUBLIC MCL_MAX_BIT_SIZE=${MCL_MAX_BIT_SIZE})
endif()
if(USE_LLVM)
add_definitions(-DMCL_USE_LLVM=1 -DMCL_LLVM_BMI2=0)
elseif(USE_ASM)
if(MCL_USE_LLVM AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1 MCL_LLVM_BMI2=0)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1 MCL_LLVM_BMI2=0)
elseif(MCL_USE_ASM)
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
add_definitions(-DMCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/aarch64.s)
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1)
target_sources(mcl PRIVATE src/asm/aarch64.s)
target_sources(mcl_st PRIVATE 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)
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1)
target_sources(mcl PRIVATE src/asm/arm.s)
target_sources(mcl_st PRIVATE 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)
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1)
target_sources(mcl PRIVATE src/asm/x86-64mac.s src/asm/x86-64mac.bmi2.s)
target_sources(mcl_st PRIVATE src/asm/x86-64mac.s src/asm/x86-64mac.bmi2.s)
set(CPU x86-64)
elseif(UNIX)
add_definitions(-DMCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/x86-64.s src/asm/x86-64.bmi2.s)
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1)
target_sources(mcl PRIVATE src/asm/x86-64.s src/asm/x86-64.bmi2.s)
target_sources(mcl_st PRIVATE src/asm/x86-64.s src/asm/x86-64.bmi2.s)
set(CPU x86-64)
endif()
endif()
if(USE_GMP)
set(EXT_LIBS ${EXT_LIBS} gmp gmpxx)
if(MCL_USE_GMP)
find_package(GMP REQUIRED)
target_link_libraries(mcl PUBLIC GMP::GMPXX GMP::GMP)
target_link_libraries(mcl_st PUBLIC GMP::GMPXX GMP::GMP)
endif()
if(USE_OPENSSL)
set(EXT_LIBS ${EXT_LIBS} crypto)
if(MCL_USE_OPENSSL)
find_package(OpenSSL REQUIRED)
target_link_libraries(mcl PUBLIC OpenSSL::Crypto)
target_link_libraries(mcl_st PUBLIC OpenSSL::Crypto)
endif()
endif()
if(NOT USE_GMP)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER")
if(NOT MCL_USE_GMP)
target_compile_definitions(mcl PUBLIC MCL_USE_VINT MCL_VINT_FIXED_BUFFER)
target_compile_definitions(mcl_st PUBLIC MCL_USE_VINT MCL_VINT_FIXED_BUFFER)
endif()
if(NOT USE_OPENSSL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_DONT_USE_OPENSSL")
if(NOT MCL_USE_OPENSSL)
target_compile_definitions(mcl PUBLIC MCL_DONT_USE_OPENSSL)
target_compile_definitions(mcl_st PUBLIC MCL_DONT_USE_OPENSSL)
endif()
if(NOT USE_XBYAK)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_DONT_USE_XBYAK")
if(NOT MCL_USE_XBYAK)
target_compile_definitions(mcl PUBLIC MCL_DONT_USE_XBYAK)
target_compile_definitions(mcl_st PUBLIC MCL_DONT_USE_XBYAK)
endif()
if(DOWNLOAD_SOURCE)
if(MCL_DOWNLOAD_SOURCE)
if(MSVC)
set(CYBOZULIB_EXT_DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/cybozulib_ext)
set(CYBOZULIB_EXT_TAG release20170521)
set(FILES config.h gmp-impl.h gmp-mparam.h gmp.h gmpxx.h longlong.h mpir.h mpirxx.h)
foreach(file IN ITEMS ${FILES})
file(DOWNLOAD https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/include/${file} ${mcl_SOURCE_DIR}/include/cybozulib_ext/${file})
file(DOWNLOAD https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/include/${file} ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include/${file})
message("download cybozulib_ext/" ${file})
endforeach()
set(FILES aes.h applink.c asn1.h asn1_mac.h asn1t.h bio.h blowfish.h bn.h buffer.h camellia.h cast.h cmac.h cms.h comp.h conf.h conf_api.h crypto.h des.h des_old.h dh.h dsa.h dso.h dtls1.h e_os2.h ebcdic.h ec.h ecdh.h ecdsa.h engine.h err.h evp.h hmac.h idea.h krb5_asn.h kssl.h lhash.h md4.h md5.h mdc2.h modes.h obj_mac.h objects.h ocsp.h opensslconf.h opensslv.h ossl_typ.h pem.h pem2.h pkcs12.h pkcs7.h pqueue.h rand.h rc2.h rc4.h ripemd.h rsa.h safestack.h seed.h sha.h srp.h srtp.h ssl.h ssl2.h ssl23.h ssl3.h stack.h symhacks.h tls1.h ts.h txt_db.h ui.h ui_compat.h whrlpool.h x509.h x509_vfy.h x509v3.h)
foreach(file IN ITEMS ${FILES})
file(DOWNLOAD https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/include/openssl/${file} ${mcl_SOURCE_DIR}/include/cybozulib_ext/openssl/${file})
file(DOWNLOAD
https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/include/openssl/${file} ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include/openssl/${file})
message("download cybozulib_ext/openssl/" ${file})
endforeach()
set(FILES mpir.lib mpirxx.lib mpirxx.pdb ssleay32.lib libeay32.lib mpir.pdb)
foreach(file IN ITEMS ${FILES})
file(DOWNLOAD https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/lib/mt/14/${file} ${mcl_SOURCE_DIR}/lib/mt/14/${file})
file(DOWNLOAD
https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/lib/mt/14/${file} ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/${file})
message("download lib/mt/14/" ${file})
endforeach()
if(MSVC)
include_directories(
${mcl_SOURCE_DIR}/include/cybozulib_ext
)
endif()
# mpir
add_library(cybozulib_ext::mpir STATIC IMPORTED)
set_target_properties(cybozulib_ext::mpir PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include
IMPORTED_LOCATION ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/mpir.lib)
# mpirxx
add_library(cybozulib_ext::mpirxx STATIC IMPORTED)
set_target_properties(cybozulib_ext::mpirxx PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include
IMPORTED_LOCATION ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/mpirxx.lib)
# libeay32
add_library(cybozulib_ext::libeay32 STATIC IMPORTED)
set_target_properties(cybozulib_ext::libeay32 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include
IMPORTED_LOCATION ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/libeay32.lib)
# ssleay32
add_library(cybozulib_ext::ssleay32 STATIC IMPORTED)
set_target_properties(cybozulib_ext::ssleay32 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include
IMPORTED_LOCATION ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/ssleay32.lib)
# abstracted cybozulib_ext libraries
add_library(windows_specific INTERFACE)
add_library(mcl::windows_specific ALIAS windows_specific)
target_link_libraries(windows_specific INTERFACE
-LIBPATH:${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib
-LIBPATH:${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14
cybozulib_ext::mpir
cybozulib_ext::mpirxx
cybozulib_ext::libeay32
cybozulib_ext::ssleay32)
target_link_libraries(mcl PUBLIC mcl::windows_specific)
target_link_libraries(mcl_st PUBLIC mcl::windows_specific)
endif()
else()
if(MSVC)
include_directories(
${mcl_SOURCE_DIR}/../cybozulib_ext/include
)
# mpir
add_library(cybozulib_ext::mpir STATIC IMPORTED)
set_target_properties(cybozulib_ext::mpir PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MCL_CYBOZULIB_EXT_DIR}/include
IMPORTED_LOCATION ${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14/mpir.lib)
# mpirxx
add_library(cybozulib_ext::mpirxx STATIC IMPORTED)
set_target_properties(cybozulib_ext::mpirxx PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MCL_CYBOZULIB_EXT_DIR}/include
IMPORTED_LOCATION ${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14/mpirxx.lib)
# libeay32
add_library(cybozulib_ext::libeay32 STATIC IMPORTED)
set_target_properties(cybozulib_ext::libeay32 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MCL_CYBOZULIB_EXT_DIR}/include
IMPORTED_LOCATION ${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14/libeay32.lib)
# ssleay32
add_library(cybozulib_ext::ssleay32 STATIC IMPORTED)
set_target_properties(cybozulib_ext::ssleay32 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MCL_CYBOZULIB_EXT_DIR}/include
IMPORTED_LOCATION ${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14/ssleay32.lib)
# abstracted cybozulib_ext libraries
add_library(windows_specific INTERFACE)
add_library(mcl::windows_specific ALIAS windows_specific)
target_link_libraries(windows_specific INTERFACE
-LIBPATH:${MCL_CYBOZULIB_EXT_DIR}/lib
-LIBPATH:${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14
cybozulib_ext::mpir
cybozulib_ext::mpirxx
cybozulib_ext::libeay32
cybozulib_ext::ssleay32)
target_link_libraries(mcl PUBLIC mcl::windows_specific)
target_link_libraries(mcl_st PUBLIC mcl::windows_specific)
endif()
endif()
include_directories(
${mcl_SOURCE_DIR}/include
)
# mclbnXXX
foreach(bit IN ITEMS 256 384 384_256)
if (MCL_STATIC_LIB)
add_library(mclbn${bit} STATIC src/bn_c${bit}.cpp)
else()
add_library(mclbn${bit} SHARED src/bn_c${bit}.cpp)
endif()
add_library(mcl::mclbn${bit} ALIAS mclbn${bit})
set_target_properties(mclbn${bit} PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO)
target_compile_options(mclbn${bit} PRIVATE ${MCL_COMPILE_OPTIONS})
target_compile_definitions(mclbn${bit}
PUBLIC MCL_NO_AUTOLINK MCLBN_NO_AUTOLINK)
target_link_libraries(mclbn${bit} PUBLIC mcl::mcl)
set_target_properties(mclbn${bit} PROPERTIES
VERSION ${mcl_VERSION}
SOVERSION ${mcl_VERSION_MAJOR})
endforeach()
if(USE_LLVM)
add_library(mcl SHARED ${SRCS} base64.o)
add_library(mcl_st STATIC ${SRCS} base64.o)
add_dependencies(mcl base64.o)
add_dependencies(mcl_st base64.o)
if(MSVC)
install(TARGETS mcl mcl_st mclbn256 mclbn384 mclbn384_256 windows_specific
EXPORT mclTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib)
else()
add_library(mcl SHARED ${SRCS})
add_library(mcl_st STATIC ${SRCS})
install(TARGETS mcl mcl_st mclbn256 mclbn384 mclbn384_256
EXPORT mclTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib)
endif()
target_link_libraries(mcl ${EXT_LIBS})
target_link_libraries(mcl_st ${EXT_LIBS})
set_target_properties(mcl_st PROPERTIES OUTPUT_NAME mcl)
#set_target_properties(mcl_st PROPERTIES PREFIX "lib")
#set_target_properties(mcl 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
install(DIRECTORY include/mcl
DESTINATION include
FILES_MATCHING PATTERN "*.hpp"
PATTERN "curve_type.h"
PATTERN "bn.h"
PATTERN "bn_c256.h"
PATTERN "bn_c384_256.h"
PATTERN "bn_c384.h")
install(DIRECTORY include/cybozu
DESTINATION include
FILES_MATCHING PATTERN "*.hpp")
set(LIBS mcl ${EXT_LIBS})
foreach(bit IN ITEMS 256 384 384_256 512)
add_library(mclbn${bit} SHARED src/bn_c${bit}.cpp)
target_link_libraries(mclbn${bit} ${LIBS})
add_executable(bn_c${bit}_test test/bn_c${bit}_test.cpp)
target_link_libraries(bn_c${bit}_test mclbn${bit})
endforeach()
install(EXPORT mclTargets
FILE mclTargets.cmake
NAMESPACE mcl::
DESTINATION lib/cmake/mcl)
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)
install(TARGETS mcl_st DESTINATION lib)
install(TARGETS mclbn256 DESTINATION lib)
install(TARGETS mclbn384 DESTINATION lib)
install(TARGETS mclbn384_256 DESTINATION lib)
install(TARGETS mclbn512 DESTINATION lib)
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)
if(NOT ONLY_LIB)
set(TEST_BASE fp_test ec_test fp_util_test window_method_test elgamal_test fp_tower_test gmp_test bn_test glv_test)
#set(TEST_BASE bn_test)
foreach(base IN ITEMS ${TEST_BASE})
add_executable(
${base}
test/${base}.cpp
)
target_link_libraries(
${base}
${LIBS}
)
endforeach()
# support local build-tree export to allow import from external projects
export(EXPORT mclTargets
FILE mclTargets.cmake
NAMESPACE mcl::)
set(CMAKE_EXPORT_PACKAGE_REGISTRY ON)
export(PACKAGE mcl)
# Tests
if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MCL_BUILD_TESTING)
AND BUILD_TESTING)
enable_testing()
add_subdirectory(test)
endif()
if(MCL_BUILD_SAMPLE)
# sample code
add_subdirectory(sample)
endif()

@ -2,14 +2,19 @@ include common.mk
LIB_DIR=lib
OBJ_DIR=obj
EXE_DIR=bin
SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c512.cpp she_c256.cpp
TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp ecdsa_test.cpp conversion_test.cpp
SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c384_256.cpp bn_c512.cpp she_c256.cpp
TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp conversion_test.cpp
TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c384_256_test.cpp bn_c512_test.cpp
TEST_SRC+=she_c256_test.cpp she_c384_test.cpp she_c384_256_test.cpp
TEST_SRC+=aggregate_sig_test.cpp array_test.cpp
TEST_SRC+=bls12_test.cpp
TEST_SRC+=ecdsa_c_test.cpp
TEST_SRC+=mapto_wb19_test.cpp
TEST_SRC+=modp_test.cpp
LIB_OBJ=$(OBJ_DIR)/fp.o
ifeq ($(MCL_STATIC_CODE),1)
LIB_OBJ+=obj/static_code.o
TEST_SRC=bls12_test.cpp
endif
ifeq ($(CPU),x86-64)
MCL_USE_XBYAK?=1
TEST_SRC+=mont_fp_test.cpp sq_test.cpp
@ -28,6 +33,13 @@ endif
ifeq ($(MCL_USE_XBYAK),0)
CFLAGS+=-DMCL_DONT_USE_XBYAK
endif
ifeq ($(MCL_USE_PROF),1)
CFLAGS+=-DMCL_USE_PROF
endif
ifeq ($(MCL_USE_PROF),2)
CFLAGS+=-DMCL_USE_PROF -DXBYAK_USE_VTUNE -I /opt/intel/vtune_amplifier/include/
LDFLAGS+=-L /opt/intel/vtune_amplifier/lib64 -ljitprofiling -ldl
endif
##################################################################
MCL_LIB=$(LIB_DIR)/libmcl.a
MCL_SNAME=mcl
@ -53,20 +65,19 @@ SHE384_LIB=$(LIB_DIR)/libmclshe384.a
SHE384_SLIB=$(LIB_DIR)/lib$(SHE384_SNAME).$(LIB_SUF)
SHE384_256_LIB=$(LIB_DIR)/libmclshe384_256.a
SHE384_256_SLIB=$(LIB_DIR)/lib$(SHE384_256_SNAME).$(LIB_SUF)
ECDSA_LIB=$(LIB_DIR)/libmclecdsa.a
SHE_LIB_ALL=$(SHE256_LIB) $(SHE256_SLIB) $(SHE384_LIB) $(SHE384_SLIB) $(SHE384_256_LIB) $(SHE384_256_SLIB)
all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN384_256_LIB) $(BN384_256_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE_LIB_ALL) $(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) $(SHE_LIB_ALL)
#LLVM_VER=-3.8
LLVM_LLC=llc$(LLVM_VER)
LLVM_OPT=opt$(LLVM_VER)
LLVM_OPT_VERSION=$(shell $(LLVM_OPT) --version 2>/dev/null | awk '/version/ {print $$3}')
LLVM_OPT_VERSION=$(shell $(LLVM_OPT) --version 2>/dev/null | awk '/version/ { split($$3,a,"."); print a[1]}')
GEN_EXE=src/gen
GEN_EXE_OPT=-u $(BIT)
# incompatibility between llvm 3.4 and the later version
ifneq ($(LLVM_OPT_VERSION),)
ifeq ($(shell expr $(LLVM_OPT_VERSION) \< 3.5.0),1)
GEN_EXE_OPT+=-old
ifeq ($(shell expr $(LLVM_OPT_VERSION) \>= 9),1)
GEN_EXE_OPT+=-ver 0x90
endif
endif
ifeq ($(OS),mac)
@ -78,7 +89,10 @@ ifneq ($(CPU),)
ASM_SRC=$(ASM_SRC_PATH_NAME).s
endif
ASM_OBJ=$(OBJ_DIR)/$(CPU).o
LIB_OBJ=$(OBJ_DIR)/fp.o
ifeq ($(OS),mac-m1)
ASM_SRC=src/base64.ll
ASM_OBJ=$(OBJ_DIR)/base64.o
endif
BN256_OBJ=$(OBJ_DIR)/bn_c256.o
BN384_OBJ=$(OBJ_DIR)/bn_c384.o
BN384_256_OBJ=$(OBJ_DIR)/bn_c384_256.o
@ -86,7 +100,6 @@ BN512_OBJ=$(OBJ_DIR)/bn_c512.o
SHE256_OBJ=$(OBJ_DIR)/she_c256.o
SHE384_OBJ=$(OBJ_DIR)/she_c384.o
SHE384_256_OBJ=$(OBJ_DIR)/she_c384_256.o
ECDSA_OBJ=$(OBJ_DIR)/ecdsa_c.o
FUNC_LIST=src/func.list
ifeq ($(findstring $(OS),mingw64/cygwin),)
MCL_USE_LLVM?=1
@ -98,8 +111,10 @@ ifeq ($(MCL_USE_LLVM),1)
LIB_OBJ+=$(ASM_OBJ)
# special case for intel with bmi2
ifeq ($(INTEL),1)
ifneq ($(MCL_STATIC_CODE),1)
LIB_OBJ+=$(OBJ_DIR)/$(CPU).bmi2.o
endif
endif
endif
LLVM_SRC=src/base$(BIT).ll
@ -173,9 +188,6 @@ $(SHE384_SLIB): $(SHE384_OBJ) $(MCL_LIB)
$(SHE384_256_SLIB): $(SHE384_256_OBJ) $(MCL_LIB)
$(PRE)$(CXX) -o $@ $(SHE384_256_OBJ) $(MCL_LIB) -shared $(LDFLAGS) $(SHE384_256_SLIB_LDFLAGS)
$(ECDSA_LIB): $(ECDSA_OBJ)
$(AR) $@ $(ECDSA_OBJ)
$(BN256_SLIB): $(BN256_OBJ) $(MCL_SLIB)
$(PRE)$(CXX) -o $@ $(BN256_OBJ) -shared $(LDFLAGS) $(BN256_SLIB_LDFLAGS)
@ -227,7 +239,19 @@ else
endif
$(GEN_EXE): src/gen.cpp src/llvm_gen.hpp
$(CXX) -o $@ $< $(CFLAGS)
$(CXX) -o $@ $< $(CFLAGS) -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER
src/dump_code: src/dump_code.cpp src/fp.cpp src/fp_generator.hpp
$(CXX) -o $@ src/dump_code.cpp src/fp.cpp -g -I include -DMCL_DUMP_JIT -DMCL_MAX_BIT_SIZE=384 -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER
src/static_code.asm: src/dump_code
$< > $@
obj/static_code.o: src/static_code.asm
nasm $(NASM_ELF_OPT) -o $@ $<
bin/static_code_test.exe: test/static_code_test.cpp src/fp.cpp obj/static_code.o
$(CXX) -o $@ -O3 $^ -g -DMCL_DONT_USE_XBYAK -DMCL_STATIC_CODE -DMCL_MAX_BIT_SIZE=384 -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -I include -Wall -Wextra
asm: $(LLVM_SRC)
$(LLVM_OPT) -O3 -o - $(LLVM_SRC) | $(LLVM_LLC) -O3 $(LLVM_FLAGS) -x86-asm-syntax=intel
@ -287,8 +311,8 @@ $(EXE_DIR)/bn_c384_256_test.exe: $(OBJ_DIR)/bn_c384_256_test.o $(BN384_256_LIB)
$(EXE_DIR)/bn_c512_test.exe: $(OBJ_DIR)/bn_c512_test.o $(BN512_LIB) $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(BN512_LIB) $(MCL_LIB) $(LDFLAGS)
$(EXE_DIR)/pairing_c.exe: $(OBJ_DIR)/pairing_c.o $(BN256_LIB) $(MCL_LIB)
$(PRE)$(CC) $< -o $@ $(BN256_LIB) $(MCL_LIB) $(LDFLAGS) -lstdc++
$(EXE_DIR)/pairing_c.exe: $(OBJ_DIR)/pairing_c.o $(BN384_256_LIB) $(MCL_LIB)
$(PRE)$(CC) $< -o $@ $(BN384_256_LIB) $(MCL_LIB) $(LDFLAGS) -lstdc++
$(EXE_DIR)/she_c256_test.exe: $(OBJ_DIR)/she_c256_test.o $(SHE256_LIB) $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(SHE256_LIB) $(MCL_LIB) $(LDFLAGS)
@ -299,9 +323,6 @@ $(EXE_DIR)/she_c384_test.exe: $(OBJ_DIR)/she_c384_test.o $(SHE384_LIB) $(MCL_LIB
$(EXE_DIR)/she_c384_256_test.exe: $(OBJ_DIR)/she_c384_256_test.o $(SHE384_256_LIB) $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(SHE384_256_LIB) $(MCL_LIB) $(LDFLAGS)
$(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)
@ -313,7 +334,7 @@ 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'
@sh -ec 'for i in $(TEST_EXE); do echo $$i; env LSAN_OPTIONS=verbosity=0: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
@ -321,7 +342,7 @@ test: $(TEST_EXE)
EMCC_OPT=-I./include -I./src -Wall -Wextra
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+=-s WASM=1 -s NO_EXIT_RUNTIME=1 -s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 -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/fp.hpp include/mcl/op.hpp include/mcl/she.h Makefile
@ -330,37 +351,18 @@ ifeq ($(MCL_USE_LLVM),2)
EMCC_OPT+=src/base64m.ll -DMCL_USE_LLVM
SHE_C_DEP+=src/base64m.ll
endif
../she-wasm/she_c.js: src/she_c256.cpp $(SHE_C_DEP)
emcc -o $@ src/fp.cpp src/she_c256.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=256 -s TOTAL_MEMORY=67108864 -s DISABLE_EXCEPTION_CATCHING=0
../she-wasm/she_c384.js: src/she_c384.cpp $(SHE_C_DEP)
emcc -o $@ src/fp.cpp src/she_c384.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=384 -s TOTAL_MEMORY=67108864 -s DISABLE_EXCEPTION_CATCHING=0
../mcl-wasm/mcl_c.js: src/bn_c256.cpp $(MCL_C_DEP)
emcc -o $@ src/fp.cpp src/bn_c256.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=256 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1 -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -fno-exceptions -MD -MP -MF obj/mcl_c.d
../mcl-wasm/mcl_c512.js: src/bn_c512.cpp $(MCL_C_DEP)
emcc -o $@ src/fp.cpp src/bn_c512.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=512 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1 -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -fno-exceptions
../ecdsa-wasm/ecdsa_c.js: src/ecdsa_c.cpp src/fp.cpp include/mcl/ecdsa.hpp include/mcl/ecdsa.h Makefile
emcc -o $@ src/fp.cpp src/ecdsa_c.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=256 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1 -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -fno-exceptions
mcl-wasm:
$(MAKE) ../mcl-wasm/mcl_c.js
$(MAKE) ../mcl-wasm/mcl_c512.js
she-wasm:
$(MAKE) ../she-wasm/she_c.js
$(MAKE) ../she-wasm/she_c384.js
ecdsa-wasm:
$(MAKE) ../ecdsa-wasm/ecdsa_c.js
# test
bin/emu:
$(CXX) -g -o $@ src/fp.cpp src/bn_c256.cpp test/bn_c256_test.cpp -DMCL_DONT_USE_XBYAK -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_64BIT_PORTABLE -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=256 -I./include
bin/pairing_c_min.exe: sample/pairing_c.c include/mcl/vint.hpp src/fp.cpp include/mcl/bn.hpp
$(CXX) -o $@ sample/pairing_c.c src/fp.cpp src/bn_c256.cpp -O3 -g -I./include -fno-threadsafe-statics -DMCL_DONT_USE_XBYAK -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=256 -DMCL_VINT_64BIT_PORTABLE -DCYBOZU_DONT_USE_STRING -DCYBOZU_DONT_USE_EXCEPTION -DNDEBUG # -DMCL_DONT_USE_CSPRNG
$(CXX) -std=c++03 -O3 -g -fno-threadsafe-statics -fno-exceptions -fno-rtti -o $@ sample/pairing_c.c src/fp.cpp src/bn_c384_256.cpp -I./include -DXBYAK_NO_EXCEPTION -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=384 -DMCL_VINT_64BIT_PORTABLE -DCYBOZU_DONT_USE_STRING -DCYBOZU_DONT_USE_EXCEPTION -DNDEBUG # -DMCL_DONT_USE_CSPRNG
bin/llvm_test64.exe: test/llvm_test.cpp src/base64.ll
clang++$(LLVM_VER) -o $@ -Ofast -DNDEBUG -Wall -Wextra -I ./include test/llvm_test.cpp src/base64.ll
bin/llvm_test32.exe: test/llvm_test.cpp src/base32.ll
clang++$(LLVM_VER) -o $@ -Ofast -DNDEBUG -Wall -Wextra -I ./include test/llvm_test.cpp src/base32.ll -m32
make_tbl:
$(MAKE) ../bls/src/qcoeff-bn254.hpp
@ -376,7 +378,7 @@ update_cybozulib:
cp -a $(addprefix ../cybozulib/,$(wildcard include/cybozu/*.hpp)) include/cybozu/
clean:
$(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) $(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) $(FUNC_LIST) lib/*.a src/static_code.asm src/dump_code
ALL_SRC=$(SRC_SRC) $(TEST_SRC) $(SAMPLE_SRC)
DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC))))
@ -385,12 +387,12 @@ DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC))))
PREFIX?=/usr/local
install: lib/libmcl.a lib/libmcl.$(LIB_SUF)
$(MKDIR) $(PREFIX)/include/mcl
cp -a include/mcl/ $(PREFIX)/include/
cp -a include/cybozu/ $(PREFIX)/include/
cp -a include/mcl $(PREFIX)/include/
cp -a include/cybozu $(PREFIX)/include/
$(MKDIR) $(PREFIX)/lib
cp -a lib/libmcl.a lib/libmcl.$(LIB_SUF) $(PREFIX)/lib/
.PHONY: test mcl-wasm she-wasm bin/emu
.PHONY: test she-wasm bin/emu
# don't remove these files automatically
.SECONDARY: $(addprefix $(OBJ_DIR)/, $(ALL_SRC:.cpp=.o))

548
api.md

@ -0,0 +1,548 @@
# C API
## News
APIs for old ethreum hash functions are removed.
`mclBn_setMapToMode` supports only `MCL_MAP_TO_MODE_ETH2`.
## Minimum sample
[sample/pairing_c.c](sample/pairing_c.c) is a sample of how to use BLS12-381 pairing.
```
cd mcl
make -j4
make bin/pairing_c.exe && bin/pairing_c.exe
```
## Header and libraries
To use BLS12-381, include `mcl/bn_c384_256.h` and link
- libmclbn384_256.{a,so}
- libmcl.{a,so} ; core library
`384_256` means the max bit size of `Fp` is 384 and that size of `Fr` is 256.
## Notation
The elliptic equation of a curve E is `E: y^2 = x^3 + b`.
- `Fp` ; a finite field of a prime order `p`, where curves is defined over.
- `Fr` ; a finite field of a prime order `r`.
- `Fp2` ; the field extension over Fp with degree 2. Fp[i] / (i^2 + 1).
- `Fp6` ; the field extension over Fp2 with degree 3. Fp2[v] / (v^3 - Xi) where Xi = i + 1.
- `Fp12` ; the field extension over Fp6 with degree 2. Fp6[w] / (w^2 - v).
- `G1` ; the cyclic subgroup of E(Fp).
- `G2` ; the cyclic subgroup of the inverse image of E'(Fp^2) under a twisting isomorphism from E' to E.
- `GT` ; the cyclie subgroup of Fp12.
- `G1`, `G2` and `GT` have the order `r`.
The pairing e: G1 x G2 -> GT is the optimal ate pairing.
mcl treats `G1` and `G2` as an additive group and `GT` as a multiplicative group.
- `mclSize` ; `unsigned int` if WebAssembly else `size_t`
### Curve Parameter
r = |G1| = |G2| = |GT|
curveType | b| r and p |
------------|--|------------------|
BN254 | 2|r = 0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d <br> p = 0x2523648240000001ba344d80000000086121000000000013a700000000000013 |
BLS12-381 | 4|r = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 <br> p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab |
BN381 | 2|r = 0x240026400f3d82b2e42de125b00158405b710818ac000007e0042f008e3e00000000001080046200000000000000000d <br> p = 0x240026400f3d82b2e42de125b00158405b710818ac00000840046200950400000000001380052e000000000000000013 |
## Structures
### `mclBnFp`
This is a struct of `Fp`. The value is stored as Montgomery representation.
### `mclBnFr`
This is a struct of `Fr`. The value is stored as Montgomery representation.
### `mclBnFp2`
This is a struct of `Fp2` which has a member `mclBnFp d[2]`.
An element `x` of `Fp2` is represented as `x = d[0] + d[1] i` where `i^2 = -1`.
### `mclBnG1`
This is a struct of `G1` which has three members `x`, `y`, `z` of type `mclBnFp`.
An element `P` of `G1` is represented as `P = [x:y:z]` of a Jacobi coordinate.
### `mclBnG2`
This is a struct of `G2` which has three members `x`, `y`, `z` of type `mclBnFp2`.
An element `Q` of `G2` is represented as `Q = [x:y:z]` of a Jacobi coordinate.
### `mclBnGT`
This is a struct of `GT` which has a member `mclBnFp d[12]`.
### sizeof
library |MCLBN_FR_UNIT_SIZE|MCLBN_FP_UNIT_SIZE|sizeof Fr|sizeof Fp|
------------------|------------------|------------------|---------|---------|
libmclbn256.a | 4 | 4 | 32 | 32 |
libmclbn384_256.a | 4 | 6 | 32 | 48 |
libmclbn384.a | 6 | 6 | 48 | 48 |
## Thread safety
All functions except for initialization and changing global setting are thread-safe.
## Initialization
Initialize mcl library. Call this function at first before calling the other functions.
```
int mclBn_init(int curve, int compiledTimeVar);
```
- `curve` ; specify the curve type
- MCL_BN254 ; BN254 (a little faster if including `mcl/bn_c256.h` and linking `libmclbn256.{a,so}`)
- MCL_BN_SNARK1 ; the same parameter used in libsnark
- MCL_BLS12_381 ; BLS12-381
- MCL_BN381_1 ; BN381 (include `mcl/bn_c384.h` and link `libmclbn384.{a,so}`)
- `compiledTimeVar` ; set `MCLBN_COMPILED_TIME_VAR`, which macro is used to make sure that
the values are the same when the library is built and used.
- return 0 if success.
- This is not thread safe.
## Global setting
```
int mclBn_setMapToMode(int mode);
```
The map-to-G2 function if `mode = MCL_MAP_TO_MODE_HASH_TO_CURVE`.
### Control to verify that a point of the elliptic curve has the order `r`.
This function affects `setStr()` and `deserialize()` for G1/G2.
```
void mclBn_verifyOrderG1(int doVerify);
void mclBn_verifyOrderG2(int doVerify);
```
- verify if `doVerify` is 1 or does not. The default parameter is 0 because the cost of verification is not small.
- Set `doVerify = 1` if considering subgroup attack is necessary.
- This is not thread safe.
## Setter / Getter
### Clear
Set `x` is zero.
```
void mclBnFr_clear(mclBnFr *x);
void mclBnFp_clear(mclBnFp *x);
void mclBnFp2_clear(mclBnFp2 *x);
void mclBnG1_clear(mclBnG1 *x);
void mclBnG2_clear(mclBnG2 *x);
void mclBnGT_clear(mclBnGT *x);
```
### Set `x` to `y`.
```
void mclBnFp_setInt(mclBnFp *y, mclInt x);
void mclBnFr_setInt(mclBnFr *y, mclInt x);
void mclBnGT_setInt(mclBnGT *y, mclInt x);
```
### Set `buf[0..bufSize-1]` to `x` with masking according to the following way.
```
int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize);
int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize);
```
1. set x = buf[0..bufSize-1] as little endian
2. x &= (1 << bitLen(r)) - 1
3. if (x >= r) x &= (1 << (bitLen(r) - 1)) - 1
- always return 0
### Set (`buf[0..bufSize-1]` mod `p` or `r`) to `x`.
```
int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize);
int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize);
```
- return 0 if bufSize <= (sizeof(*x) * 8 * 2) else -1
### Get little endian byte sequence `buf` corresponding to `x`
```
mclSize mclBnFr_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFr *x);
mclSize mclBnFp_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFp *x);
```
- write `x` to `buf` as little endian
- return the written size if sucess else 0
- NOTE: `buf[0] = 0` and return 1 if `x` is zero.
### Serialization
### Serialize
```
mclSize mclBnFr_serialize(void *buf, mclSize maxBufSize, const mclBnFr *x);
mclSize mclBnG1_serialize(void *buf, mclSize maxBufSize, const mclBnG1 *x);
mclSize mclBnG2_serialize(void *buf, mclSize maxBufSize, const mclBnG2 *x);
mclSize mclBnGT_serialize(void *buf, mclSize maxBufSize, const mclBnGT *x);
mclSize mclBnFp_serialize(void *buf, mclSize maxBufSize, const mclBnFp *x);
mclSize mclBnFp2_serialize(void *buf, mclSize maxBufSize, const mclBnFp2 *x);
```
- serialize `x` into `buf[0..maxBufSize-1]`
- return written byte size if success else 0
### Serialization format
- `Fp`(resp. `Fr`) ; a little endian byte sequence with a fixed size
- the size is the return value of `mclBn_getFpByteSize()` (resp. `mclBn_getFpByteSize()`).
- `G1` ; a compressed fixed size
- the size is equal to `mclBn_getG1ByteSize()` (=`mclBn_getFpByteSize()`).
- `G2` ; a compressed fixed size
- the size is equal to `mclBn_getG1ByteSize() * 2`.
pseudo-code to serialize of `P` of `G1` (resp. `G2`)
```
size = mclBn_getG1ByteSize() # resp. mclBn_getG1ByteSize() * 2
if P is zero:
return [0] * size
else:
P = P.normalize()
s = P.x.serialize()
# x in Fp2 is odd <=> x.a is odd
if P.y is odd: # resp. P.y.d[0] is odd
s[byte-length(s) - 1] |= 0x80
return s
```
### Ethereum serialization mode for BLS12-381
```
void mclBn_setETHserialization(int ETHserialization);
```
- serialize according to [serialization of BLS12-381](https://github.com/zkcrypto/pairing/blob/master/src/bls12_381/README.md#serialization) if BLS12-381 is used and `ETHserialization = 1` (default 0).
### Deserialize
```
mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize bufSize);
mclSize mclBnG1_deserialize(mclBnG1 *x, const void *buf, mclSize bufSize);
mclSize mclBnG2_deserialize(mclBnG2 *x, const void *buf, mclSize bufSize);
mclSize mclBnGT_deserialize(mclBnGT *x, const void *buf, mclSize bufSize);
mclSize mclBnFp_deserialize(mclBnFp *x, const void *buf, mclSize bufSize);
mclSize mclBnFp2_deserialize(mclBnFp2 *x, const void *buf, mclSize bufSize);
```
- deserialize `x` from `buf[0..bufSize-1]`
- return read size if success else 0
## String conversion
### Get string
```
mclSize mclBnFr_getStr(char *buf, mclSize maxBufSize, const mclBnFr *x, int ioMode);
mclSize mclBnG1_getStr(char *buf, mclSize maxBufSize, const mclBnG1 *x, int ioMode);
mclSize mclBnG2_getStr(char *buf, mclSize maxBufSize, const mclBnG2 *x, int ioMode);
mclSize mclBnGT_getStr(char *buf, mclSize maxBufSize, const mclBnGT *x, int ioMode);
mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode);
```
- write `x` to `buf` according to `ioMode`
- `ioMode`
- 10 ; decimal number
- 16 ; hexadecimal number
- `MCLBN_IO_EC_PROJ` ; output as Jacobi coordinate
- return `strlen(buf)` if success else 0.
The meaning of the output of `G1`.
- `0` ; infinity
- `1 <x> <y>` ; affine coordinate
- `4 <x> <y> <z>` ; Jacobi coordinate
- the element `<x>` of `G2` outputs `d[0] d[1]`.
### Set string
```
int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnG1_setStr(mclBnG1 *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnG2_setStr(mclBnG2 *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnGT_setStr(mclBnGT *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnFp_setStr(mclBnFp *x, const char *buf, mclSize bufSize, int ioMode);
```
- set `buf[0..bufSize-1]` to `x` accoring to `ioMode`
- return 0 if success else -1
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,
```
mclBnG1 P;
mclBnG1_setStr(&P, "1 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569", 10);
mclBnG2 Q;
mclBnG2_setStr(&Q, "1 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582");
```
## Set random value
Set `x` by cryptographically secure pseudo random number generator.
```
int mclBnFr_setByCSPRNG(mclBnFr *x);
int mclBnFp_setByCSPRNG(mclBnFp *x);
```
### Change random generator function
```
void mclBn_setRandFunc(
void *self,
unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)
);
```
- `self` ; user-defined pointer
- `readFunc` ; user-defined function, which writes random `bufSize` bytes to `buf` and returns `bufSize` if success else returns 0.
- `readFunc` must be thread-safe.
- Set the default random function if `self == 0` and `readFunc == 0`.
- This is not thread safe.
## Arithmetic operations
### neg / inv / sqr / add / sub / mul / div of `Fr`, `Fp`, `Fp2`, `GT`.
```
void mclBnFr_neg(mclBnFr *y, const mclBnFr *x);
void mclBnFr_inv(mclBnFr *y, const mclBnFr *x);
void mclBnFr_sqr(mclBnFr *y, const mclBnFr *x);
void mclBnFr_add(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFr_sub(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFr_mul(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFp_neg(mclBnFp *y, const mclBnFp *x);
void mclBnFp_inv(mclBnFp *y, const mclBnFp *x);
void mclBnFp_sqr(mclBnFp *y, const mclBnFp *x);
void mclBnFp_add(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp_sub(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp_mul(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp_div(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp2_neg(mclBnFp2 *y, const mclBnFp2 *x);
void mclBnFp2_inv(mclBnFp2 *y, const mclBnFp2 *x);
void mclBnFp2_sqr(mclBnFp2 *y, const mclBnFp2 *x);
void mclBnFp2_add(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnFp2_sub(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnFp2_mul(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnFp2_div(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnGT_inv(mclBnGT *y, const mclBnGT *x); // y = a - bw for x = a + bw where Fp12 = Fp6[w]
void mclBnGT_sqr(mclBnGT *y, const mclBnGT *x);
void mclBnGT_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
void mclBnGT_div(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
```
- use `mclBnGT_invGeneric` for an element in Fp12 - GT.
- NOTE: The following functions do NOT return a GT element because GT is multiplicative group.
```
void mclBnGT_neg(mclBnGT *y, const mclBnGT *x);
void mclBnGT_add(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
void mclBnGT_sub(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
```
### Square root of `x`.
```
int mclBnFr_squareRoot(mclBnFr *y, const mclBnFr *x);
int mclBnFp_squareRoot(mclBnFp *y, const mclBnFp *x);
int mclBnFp2_squareRoot(mclBnFp2 *y, const mclBnFp2 *x);
```
- `y` is one of square root of `x` if `y` exists.
- return 0 if success else -1
### add / sub / dbl / neg for `G1` and `G2`.
```
void mclBnG1_neg(mclBnG1 *y, const mclBnG1 *x);
void mclBnG1_dbl(mclBnG1 *y, const mclBnG1 *x);
void mclBnG1_add(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y);
void mclBnG1_sub(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y);
void mclBnG2_neg(mclBnG2 *y, const mclBnG2 *x);
void mclBnG2_dbl(mclBnG2 *y, const mclBnG2 *x);
void mclBnG2_add(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y);
void mclBnG2_sub(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y);
```
### Convert a point from Jacobi coordinate to affine.
```
void mclBnG1_normalize(mclBnG1 *y, const mclBnG1 *x);
void mclBnG2_normalize(mclBnG2 *y, const mclBnG2 *x);
```
- convert `[x:y:z]` to `[x:y:1]` if `z != 0` else `[*:*:0]`
### scalar multiplication
```
void mclBnG1_mul(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y);
void mclBnG2_mul(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y);
void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y);
```
- z = x * y for G1 / G2
- z = pow(x, y) for GT
- use `mclBnGT_powGeneric` for an element in Fp12 - GT.
### multi scalar multiplication
```
void mclBnG1_mulVec(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y, mclSize n);
void mclBnG2_mulVec(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y, mclSize n);
void mclBnGT_powVec(mclBnGT *z, const mclBnGT *x, const mclBnFr *y, mclSize n);
```
- z = sum_{i=0}^{n-1} mul(x[i], y[i]) for G1 / G2.
- z = prod_{i=0}^{n-1} pow(x[i], y[i]) for GT.
## hash and mapTo functions
### Set hash of `buf[0..bufSize-1]` to `x`
```
int mclBnFr_setHashOf(mclBnFr *x, const void *buf, mclSize bufSize);
int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize);
```
- always return 0
- use SHA-256 if sizeof(*x) <= 256 else SHA-512
- set accoring to the same way as `setLittleEndian`
- support the other wasy if you want in the future
### map `x` to G1 / G2.
```
int mclBnFp_mapToG1(mclBnG1 *y, const mclBnFp *x);
int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x);
```
- See `struct MapTo` in `mcl/bn.hpp` for the detail of the algorithm.
- return 0 if success else -1
### hash and map to G1 / G2.
```
int mclBnG1_hashAndMapTo(mclBnG1 *x, const void *buf, mclSize bufSize);
int mclBnG2_hashAndMapTo(mclBnG2 *x, const void *buf, mclSize bufSize);
```
- Combine `setHashOf` and `mapTo` functions
## Pairing operations
The pairing function `e(P, Q)` is consist of two parts:
- `MillerLoop(P, Q)`
- `finalExp(x)`
`finalExp` satisfies the following properties:
- `e(P, Q) = finalExp(MillerLoop(P, Q))`
- `e(P1, Q1) e(P2, Q2) = finalExp(MillerLoop(P1, Q1) MillerLoop(P2, Q2))`
### pairing
```
void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
```
### millerLoop
```
void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
```
### finalExp
```
void mclBn_finalExp(mclBnGT *y, const mclBnGT *x);
```
## Variants of MillerLoop
### multi pairing
```
void mclBn_millerLoopVec(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y, mclSize n);
```
- This function is for multi-pairing
- computes prod_{i=0}^{n-1} MillerLoop(x[i], y[i])
- prod_{i=0}^{n-1} e(x[i], y[i]) = finalExp(prod_{i=0}^{n-1} MillerLoop(x[i], y[i]))
### pairing for a fixed point of G2
```
int mclBn_getUint64NumToPrecompute(void);
void mclBn_precomputeG2(uint64_t *Qbuf, const mclBnG2 *Q);
void mclBn_precomputedMillerLoop(mclBnGT *f, const mclBnG1 *P, const uint64_t *Qbuf);
```
These functions is the same computation of `pairing(P, Q);` as the followings:
```
uint64_t *Qbuf = (uint64_t*)malloc(mclBn_getUint64NumToPrecompute() * sizeof(uint64_t));
mclBn_precomputeG2(Qbuf, Q); // precomputing of Q
mclBn_precomputedMillerLoop(f, P, Qbuf); // pairing of any P of G1 and the fixed Q
free(p);
```
```
void mclBn_precomputedMillerLoop2(
mclBnGT *f,
const mclBnG1 *P1, const uint64_t *Q1buf,
const mclBnG1 *P2, const uint64_t *Q2buf
);
```
- compute `MillerLoop(P1, Q1buf) * MillerLoop(P2, Q2buf)`
```
void mclBn_precomputedMillerLoop2mixed(
mclBnGT *f,
const mclBnG1 *P1, const mclBnG2 *Q1,
const mclBnG1 *P2, const uint64_t *Q2buf
);
```
- compute `MillerLoop(P1, Q2) * MillerLoop(P2, Q2buf)`
## Check value
### Check validness
```
int mclBnFr_isValid(const mclBnFr *x);
int mclBnFp_isValid(const mclBnFp *x);
int mclBnG1_isValid(const mclBnG1 *x);
int mclBnG2_isValid(const mclBnG2 *x);
```
- return 1 if true else 0
### Check the order of a point
```
int mclBnG1_isValidOrder(const mclBnG1 *x);
int mclBnG2_isValidOrder(const mclBnG2 *x);
```
- Check whether the order of `x` is valid or not
- return 1 if true else 0
- This function always cheks according to `mclBn_verifyOrderG1` and `mclBn_verifyOrderG2`.
### Is equal / zero / one / isOdd
```
int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y);
int mclBnFr_isZero(const mclBnFr *x);
int mclBnFr_isOne(const mclBnFr *x);
int mclBnFr_isOdd(const mclBnFr *x);
int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y);
int mclBnFp_isZero(const mclBnFp *x);
int mclBnFp_isOne(const mclBnFp *x);
int mclBnFp_isOdd(const mclBnFp *x);
int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y);
int mclBnFp2_isZero(const mclBnFp2 *x);
int mclBnFp2_isOne(const mclBnFp2 *x);
int mclBnG1_isEqual(const mclBnG1 *x, const mclBnG1 *y);
int mclBnG1_isZero(const mclBnG1 *x);
int mclBnG2_isEqual(const mclBnG2 *x, const mclBnG2 *y);
int mclBnG2_isZero(const mclBnG2 *x);
int mclBnGT_isEqual(const mclBnGT *x, const mclBnGT *y);
int mclBnGT_isZero(const mclBnGT *x);
int mclBnGT_isOne(const mclBnGT *x);
```
- return 1 if true else 0
### isNegative
```
int mclBnFr_isNegative(const mclBnFr *x);
int mclBnFp_isNegative(const mclBnFr *x);
```
return 1 if x >= half where half = (r + 1) / 2 (resp. (p + 1) / 2).
## Lagrange interpolation
```
int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, mclSize k);
int mclBn_G1LagrangeInterpolation(mclBnG1 *out, const mclBnFr *xVec, const mclBnG1 *yVec, mclSize k);
int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVec, const mclBnG2 *yVec, mclSize k);
```
- Lagrange interpolation
- recover out = y(0) from {(xVec[i], yVec[i])} for {i=0..k-1}
- return 0 if success else -1
- satisfy that xVec[i] != 0, xVec[i] != xVec[j] for i != j
```
int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, mclSize cSize, const mclBnFr *x);
int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, mclSize cSize, const mclBnFr *x);
int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, mclSize cSize, const mclBnFr *x);
```
- Evaluate polynomial
- out = f(x) = c[0] + c[1] * x + ... + c[cSize - 1] * x^{cSize - 1}
- return 0 if success else -1
- satisfy cSize >= 1

@ -0,0 +1,67 @@
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
BUILD_DIR=${1:-build}
windows_build()
{
if [ -d "${SCRIPT_DIR}/../cybozulib_ext" ]; then
DOWNLOAD_CYBOZULIB_EXT="OFF"
CYBOZULIB_EXT_OPTION="-DMCL_CYBOZULIB_EXT_DIR:PATH=${SCRIPT_DIR}/../cybozulib_ext"
else
DOWNLOAD_CYBOZULIB_EXT="ON"
CYBOZULIB_EXT_OPTION=""
fi
cmake -E remove_directory ${BUILD_DIR}
cmake -E make_directory ${BUILD_DIR}
cmake -H${SCRIPT_DIR} -B${BUILD_DIR} -A x64 \
-DBUILD_TESTING=ON \
-DMCL_BUILD_SAMPLE=ON \
-DCMAKE_INSTALL_PREFIX=${BUILD_DIR}/install \
-DMCL_DOWNLOAD_SOURCE=${DOWNLOAD_CYBOZULIB_EXT} ${CYBOZULIB_EXT_OPTION}
cmake --build ${BUILD_DIR} --clean-first --config Release --parallel
}
linux_build()
{
cmake -E remove_directory ${BUILD_DIR}
cmake -E make_directory ${BUILD_DIR}
cmake -H${SCRIPT_DIR} -B${BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=ON \
-DMCL_BUILD_SAMPLE=ON \
-DMCL_USE_LLVM=ON \
-DMCL_USE_OPENSSL=ON \
-DCMAKE_INSTALL_PREFIX=${BUILD_DIR}/install
cmake --build ${BUILD_DIR} --clean-first -- -j
}
osx_build()
{
OPENSSL_ROOT_DIR="/usr/local/opt/openssl"
cmake -E remove_directory ${BUILD_DIR}
cmake -E make_directory ${BUILD_DIR}
cmake -H${SCRIPT_DIR} -B${BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=ON \
-DMCL_BUILD_SAMPLE=ON \
-DMCL_USE_LLVM=ON \
-DMCL_USE_OPENSSL=ON \
-DOPENSSL_ROOT_DIR="${OPENSSL_ROOT_DIR}" \
-DCMAKE_INSTALL_PREFIX=${BUILD_DIR}/install
cmake --build ${BUILD_DIR} --clean-first -- -j
}
os=`uname -s`
case "${os}" in
CYGWIN*|MINGW32*|MSYS*|MINGW*)
windows_build
;;
Darwin*)
osx_build
;;
*)
linux_build
;;
esac

@ -0,0 +1,88 @@
# FindGMP.cmake
#
# Finds the GNU Multiple Precision Arithmetic Library (GMP)
# See http://gmplib.org/
#
# This will define the following variables::
#
# GMP_FOUND
# GMP_VERSION
# GMP_DEFINITIONS
# GMP_INCLUDE_DIR
# GMP_LIBRARY
# GMP_GMPXX_DEFINITIONS
# GMP_GMPXX_INCLUDE_DIR
# GMP_GMPXX_LIBRARY
#
# and the following imported targets::
#
# GMP::GMP
# GMP::GMPXX
find_package(PkgConfig QUIET)
pkg_check_modules(PC_GMP QUIET gmp gmpxx)
set(GMP_VERSION ${PC_GMP_gmp_VERSION})
find_library(GMP_LIBRARY
NAMES gmp libgmp
HINTS
${PC_GMP_gmp_LIBDIR}
${PC_GMP_gmp_LIBRARY_DIRS})
find_path(GMP_INCLUDE_DIR
NAMES gmp.h
HINTS
${PC_GMP_gmp_INCLUDEDIR}
${PC_GMP_gmp_INCLUDE_DIRS})
find_library(GMP_GMPXX_LIBRARY
NAMES gmpxx libgmpxx
HINTS
${PC_GMP_gmpxx_LIBDIR}
${PC_GMP_gmpxx_LIBRARY_DIRS})
find_path(GMP_GMPXX_INCLUDE_DIR
NAMES gmpxx.h
HINTS
${PC_GMP_gmpxx_INCLUDEDIR}
${PC_GMP_gmpxx_INCLUDE_DIRS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GMP
REQUIRED_VARS
GMP_INCLUDE_DIR
GMP_LIBRARY
GMP_GMPXX_INCLUDE_DIR
GMP_GMPXX_LIBRARY
VERSION_VAR GMP_VERSION)
if(GMP_FOUND)
set(GMP_LIBRARIES ${GMP_LIBRARY})
set(GMP_INCLUDE_DIRS ${GMP_INCLUDE_DIR})
set(GMP_DEFINITIONS ${PC_GMP_gmp_CFLAGS_OTHER})
set(GMP_GMPXX_LIBRARIES ${GMP_GMPXX_LIBRARY})
set(GMP_GMPXX_INCLUDE_DIRS ${GMP_GMPXX_INCLUDE_DIR})
set(GMP_GMPXX_DEFINITIONS ${PC_GMP_gmpxx_CFLAGS_OTHER})
if(NOT TARGET GMP::GMP)
add_library(GMP::GMP UNKNOWN IMPORTED)
set_target_properties(GMP::GMP PROPERTIES
INTERFACE_COMPILE_OPTIONS "${PC_GMP_gmp_CFLAGS_OTHER}"
INTERFACE_INCLUDE_DIRECTORIES "${GMP_INCLUDE_DIR}"
IMPORTED_LOCATION "${GMP_LIBRARY}")
endif()
if(NOT TARGET GMP::GMPXX)
add_library(GMP::GMPXX UNKNOWN IMPORTED)
set_target_properties(GMP::GMPXX PROPERTIES
INTERFACE_COMPILE_OPTIONS "${PC_GMP_gmpxx_CFLAGS_OTHER}"
INTERFACE_INCLUDE_DIRECTORIES "${GMP_GMPXX_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES GMP::GMP
IMPORTED_LOCATION "${GMP_GMPXX_LIBRARY}")
endif()
endif()
mark_as_advanced(GMP_FOUND GMP_INCLUDE_DIR GMP_LIBRARY)
mark_as_advanced(GMP_GMPXX_INCLUDE_DIR GMP_GMPXX_LIBRARY)

@ -1,29 +1,42 @@
GCC_VER=$(shell $(PRE)$(CC) -dumpversion)
UNAME_S=$(shell uname -s)
ARCH?=$(shell uname -m)
NASM_ELF_OPT=-felf64
ifeq ($(UNAME_S),Linux)
OS=Linux
endif
ifeq ($(findstring MINGW64,$(UNAME_S)),MINGW64)
OS=mingw64
CFLAGS+=-D__USE_MINGW_ANSI_STDIO=1
NASM_ELF_OPT=-fwin64
endif
ifeq ($(findstring CYGWIN,$(UNAME_S)),CYGWIN)
OS=cygwin
endif
ifeq ($(UNAME_S),Darwin)
ifeq ($(ARCH),x86_64)
OS=mac
ARCH=x86_64
else
OS=mac-m1
endif
LIB_SUF=dylib
OPENSSL_DIR?=/usr/local/opt/openssl
CFLAGS+=-I$(OPENSSL_DIR)/include
LDFLAGS+=-L$(OPENSSL_DIR)/lib
GMP_DIR?=/usr/local/opt/gmp
CFLAGS+=-I$(GMP_DIR)/include
LDFLAGS+=-L$(GMP_DIR)/lib
NASM_ELF_OPT=-fmacho64
else
LIB_SUF=so
endif
ARCH?=$(shell uname -m)
ifeq ($(UNAME_S),OpenBSD)
OS=openbsd
CXX?=clang++
CFLAGS+=-I/usr/local/include
LDFLAGS+=-L/usr/local/lib
endif
ifeq ($(UNAME_S),FreeBSD)
OS=freebsd
CXX?=clang++
CFLAGS+=-I/usr/local/include
LDFLAGS+=-L/usr/local/lib
endif
ifneq ($(findstring $(ARCH),x86_64/amd64),)
CPU=x86-64
INTEL=1
@ -42,16 +55,17 @@ ifeq ($(ARCH),x86)
BIT_OPT=-m32
#LOW_ASM_SRC=src/asm/low_x86.asm
endif
ifeq ($(ARCH),armv7l)
ifneq ($(findstring $(ARCH),armv7l/armv6l),)
CPU=arm
BIT=32
#LOW_ASM_SRC=src/asm/low_arm.s
endif
ifeq ($(ARCH),aarch64)
#ifeq ($(ARCH),aarch64)
ifneq ($(findstring $(ARCH),aarch64/arm64),)
CPU=aarch64
BIT=64
endif
ifeq ($(findstring $(OS),mac/mingw64),)
ifeq ($(findstring $(OS),mac/mac-m1/mingw64/openbsd),)
LDFLAGS+=-lrt
endif
@ -66,12 +80,12 @@ ifeq ($(DEBUG),1)
LDFLAGS+=-fsanitize=address
endif
else
CFLAGS_OPT+=-fomit-frame-pointer -DNDEBUG
CFLAGS_OPT+=-fomit-frame-pointer -DNDEBUG -fno-stack-protector
ifeq ($(CXX),clang++)
CFLAGS_OPT+=-O3
else
ifeq ($(shell expr $(GCC_VER) \> 4.6.0),1)
CFLAGS_OPT+=-Ofast
CFLAGS_OPT+=-O3
else
CFLAGS_OPT+=-O3
endif
@ -84,7 +98,7 @@ else
CFLAGS_OPT+=$(MARCH)
endif
endif
CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith
CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith -Wundef
CFLAGS+=-g3
INC_OPT=-I include -I test
CFLAGS+=$(CFLAGS_WARN) $(BIT_OPT) $(INC_OPT)
@ -95,7 +109,10 @@ CFLAGS+=$(CFLAGS_OPT_USER)
endif
CFLAGS+=$(CFLAGS_USER)
MCL_USE_GMP?=1
MCL_USE_OPENSSL?=1
ifneq ($(OS),mac/mac-m1,)
MCL_USE_GMP=0
endif
MCL_USE_OPENSSL?=0
ifeq ($(MCL_USE_GMP),0)
CFLAGS+=-DMCL_USE_VINT
endif
@ -107,9 +124,24 @@ ifeq ($(MCL_USE_OPENSSL),0)
endif
ifeq ($(MCL_USE_GMP),1)
GMP_LIB=-lgmp -lgmpxx
ifeq ($(UNAME_S),Darwin)
GMP_DIR?=/usr/local/opt/gmp
CFLAGS+=-I$(GMP_DIR)/include
LDFLAGS+=-L$(GMP_DIR)/lib
endif
endif
ifeq ($(MCL_USE_OPENSSL),1)
OPENSSL_LIB=-lcrypto
OPENSSL_LIB=-L${OPENSSL_DIR}/lib -lcrypto
ifeq ($(UNAME_S),Darwin)
OPENSSL_DIR?=/usr/local/opt/openssl
CFLAGS+=-I$(OPENSSL_DIR)/include
LDFLAGS+=-L$(OPENSSL_DIR)/lib
endif
endif
ifeq ($(MCL_STATIC_CODE),1)
MCL_USE_XBYAK=0
MCL_MAX_BIT_SIZE=384
CFLAGS+=-DMCL_STATIC_CODE
endif
LDFLAGS+=$(GMP_LIB) $(OPENSSL_LIB) $(BIT_OPT) $(LDFLAGS_USER)

@ -4,125 +4,126 @@ using System.Runtime.InteropServices;
namespace mcl {
public class BN256 {
[DllImport("mclBn256.dll")]
public const string dllName = "mclBn256";
[DllImport(dllName)]
public static extern int mclBn_init(int curve, int compiledTimeVar);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_clear(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_setInt(ref Fr y, int x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_setStr(ref Fr x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_isValid(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_isEqual(ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_isZero(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_isOne(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_setByCSPRNG(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_setHashOf(ref Fr x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_getStr([Out]StringBuilder buf, long maxBufSize, ref Fr x, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_neg(ref Fr y, ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_inv(ref Fr y, ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_add(ref Fr z, ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_sub(ref Fr z, ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_mul(ref Fr z, ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_div(ref Fr z, ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_clear(ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_setStr(ref G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_isValid(ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_isEqual(ref G1 x, ref G1 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_isZero(ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_hashAndMapTo(ref G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern long mclBnG1_getStr([Out]StringBuilder buf, long maxBufSize, ref G1 x, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_neg(ref G1 y, ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_dbl(ref G1 y, ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_add(ref G1 z, ref G1 x, ref G1 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_sub(ref G1 z, ref G1 x, ref G1 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_mul(ref G1 z, ref G1 x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_clear(ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_setStr(ref G2 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_isValid(ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_isEqual(ref G2 x, ref G2 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_isZero(ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_hashAndMapTo(ref G2 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern long mclBnG2_getStr([Out]StringBuilder buf, long maxBufSize, ref G2 x, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_neg(ref G2 y, ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_dbl(ref G2 y, ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_add(ref G2 z, ref G2 x, ref G2 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_sub(ref G2 z, ref G2 x, ref G2 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_mul(ref G2 z, ref G2 x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_clear(ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnGT_setStr(ref GT x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnGT_isEqual(ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnGT_isZero(ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnGT_isOne(ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern long mclBnGT_getStr([Out]StringBuilder buf, long maxBufSize, ref GT x, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_neg(ref GT y, ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_inv(ref GT y, ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_add(ref GT z, ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_sub(ref GT z, ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_mul(ref GT z, ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_div(ref GT z, ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_pow(ref GT z, ref GT x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBn_pairing(ref GT z, ref G1 x, ref G2 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBn_finalExp(ref GT y, ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBn_millerLoop(ref GT z, ref G1 x, ref G2 y);
public static void init()

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30309.148
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "test", "test\test.csproj", "{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mcl", "mcl\mcl.csproj", "{73288FB5-7173-4AE9-86C6-F76DF219C37B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}.Debug|x64.ActiveCfg = Debug|Any CPU
{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}.Debug|x64.Build.0 = Debug|Any CPU
{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}.Release|x64.ActiveCfg = Release|Any CPU
{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}.Release|x64.Build.0 = Release|Any CPU
{73288FB5-7173-4AE9-86C6-F76DF219C37B}.Debug|x64.ActiveCfg = Debug|Any CPU
{73288FB5-7173-4AE9-86C6-F76DF219C37B}.Debug|x64.Build.0 = Debug|Any CPU
{73288FB5-7173-4AE9-86C6-F76DF219C37B}.Release|x64.ActiveCfg = Release|Any CPU
{73288FB5-7173-4AE9-86C6-F76DF219C37B}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {ACBC75BC-5FB9-48DF-A78D-7C6BAD21E647}
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load Diff

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="CVS\**" />
<EmbeddedResource Remove="CVS\**" />
<None Remove="CVS\**" />
</ItemGroup>
</Project>

@ -0,0 +1,24 @@
# C# binding of mcl library
# How to build `bin/mclbn384_256.dll`.
```
git clone https://github.com/herumi/mcl
cd mcl
mklib dll
```
Open `mcl/ffi/cs/mcl.sln` and Set the directory of `mcl/bin` to `workingDirectory` at `Debug` of test project.
# Remark
- `bn256.cs` is an old code. It will be removed in the future.
- `mcl/mcl.cs` is a new version. It support `BN254`, `BN_SNARK` and `BLS12_381` curve, which requires `mclbn384_256.dll`.
# `ETHmode` with `BLS12_381`
If you need the map-to-G1/G2 function defined in [Hashing to Elliptic Curves](https://www.ietf.org/id/draft-irtf-cfrg-hash-to-curve-09.html),
then initialize this library as the followings:
```
MCL.Init(BLS12_381);
MCL.ETHmode();
```

@ -0,0 +1,408 @@
using System;
namespace mcl {
using static MCL;
class MCLTest {
static int err = 0;
static void assert(string msg, bool b)
{
if (b) return;
Console.WriteLine("ERR {0}", msg);
err++;
}
static void Main()
{
err = 0;
try {
Console.WriteLine("BN254");
TestCurve(BN254);
Console.WriteLine("BN_SNARK");
TestCurve(BN_SNARK);
Console.WriteLine("BLS12_381");
TestCurve(BLS12_381);
Console.WriteLine("BLS12_381 eth");
ETHmode();
TestETH();
if (err == 0) {
Console.WriteLine("all tests succeed");
} else {
Console.WriteLine("err={0}", err);
}
} catch (Exception e) {
Console.WriteLine("ERR={0}", e);
}
}
static void TestCurve(int curveType)
{
Init(curveType);
TestFr();
TestFp();
TestG1();
TestG2();
TestPairing();
TestSS();
}
static void TestFr()
{
Console.WriteLine("TestFr");
Fr x = new Fr();
assert("x.isZero", x.IsZero());
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));
Console.WriteLine("exception test");
try {
x.SetStr("1234567891234x", 10);
Console.WriteLine("x = {0}", x);
} catch (Exception e) {
Console.WriteLine("OK ; expected exception: {0}", e);
}
x.SetStr("1234567891234", 10);
assert("1234567891234", x.GetStr(10) == "1234567891234");
{
byte[] buf = x.Serialize();
y.Deserialize(buf);
assert("x == y", x.Equals(y));
}
}
static void TestFp()
{
Console.WriteLine("TestFp");
Fp x = new Fp();
assert("x.isZero", x.IsZero());
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");
Fp 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));
Console.WriteLine("exception test");
try {
x.SetStr("1234567891234x", 10);
Console.WriteLine("x = {0}", x);
} catch (Exception e) {
Console.WriteLine("OK ; expected exception: {0}", e);
}
x.SetStr("1234567891234", 10);
assert("1234567891234", x.GetStr(10) == "1234567891234");
{
byte[] buf = x.Serialize();
y.Deserialize(buf);
assert("x == y", x.Equals(y));
}
}
static void TestG1()
{
Console.WriteLine("TestG1");
G1 P = new G1();
assert("P.isZero", P.IsZero());
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));
{
byte[] buf = P.Serialize();
Q.Clear();
Q.Deserialize(buf);
assert("P == Q", P.Equals(Q));
}
{
const int n = 5;
G1[] xVec = new G1[n];
Fr[] yVec = new Fr[n];
P.Clear();
for (int i = 0; i < n; i++) {
xVec[i].HashAndMapTo(i.ToString());
yVec[i].SetByCSPRNG();
Q.Mul(xVec[i], yVec[i]);
P.Add(P, Q);
}
MulVec(ref Q, xVec, yVec);
assert("mulVecG1", P.Equals(Q));
}
G1 W = G1.Zero();
assert("W.IsZero", W.IsZero());
}
static void TestG2()
{
Console.WriteLine("TestG2");
G2 P = new G2();
assert("P.isZero", P.IsZero());
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));
{
byte[] buf = P.Serialize();
Q.Clear();
Q.Deserialize(buf);
assert("P == Q", P.Equals(Q));
}
{
const int n = 5;
G2[] xVec = new G2[n];
Fr[] yVec = new Fr[n];
P.Clear();
for (int i = 0; i < n; i++) {
xVec[i].HashAndMapTo(i.ToString());
yVec[i].SetByCSPRNG();
Q.Mul(xVec[i], yVec[i]);
P.Add(P, Q);
}
MulVec(ref Q, xVec, yVec);
assert("mulVecG2", P.Equals(Q));
}
G2 W = G2.Zero();
assert("W.IsZero", W.IsZero());
}
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));
}
static void TestETH_mapToG1()
{
var tbl = new[] {
new {
msg = "asdf",
x = "a72df17570d0eb81260042edbea415ad49bdb94a1bc1ce9d1bf147d0d48268170764bb513a3b994d662e1faba137106",
y = "122b77eca1ed58795b7cd456576362f4f7bd7a572a29334b4817898a42414d31e9c0267f2dc481a4daf8bcf4a460322",
},
};
G1 P = new G1();
Fp x = new Fp();
Fp y = new Fp();
foreach (var v in tbl) {
P.HashAndMapTo(v.msg);
x.SetStr(v.x, 16);
y.SetStr(v.y, 16);
Normalize(ref P, P);
Console.WriteLine("x={0}", P.x.GetStr(16));
Console.WriteLine("y={0}", P.y.GetStr(16));
assert("P.x", P.x.Equals(x));
assert("P.y", P.y.Equals(y));
}
}
static void TestETH()
{
TestETH_mapToG1();
}
static void TestSS_Fr()
{
const int n = 5;
const int k = 3; // can't change because the following loop
Fr[] cVec = new Fr[k];
// init polynomial coefficient
for (int i = 0; i < k; i++) {
cVec[i].SetByCSPRNG();
}
Fr[] xVec = new Fr[n];
Fr[] yVec = new Fr[n];
// share cVec[0] with yVec[0], ..., yVec[n-1]
for (int i = 0; i < n; i++) {
xVec[i].SetHashOf(i.ToString());
MCL.Share(ref yVec[i], cVec, xVec[i]);
}
// recover cVec[0] from xVecSubset and yVecSubset
Fr[] xVecSubset = new Fr[k];
Fr[] yVecSubset = new Fr[k];
for (int i0 = 0; i0 < n; i0++) {
xVecSubset[0] = xVec[i0];
yVecSubset[0] = yVec[i0];
for (int i1 = i0 + 1; i1 < n; i1++) {
xVecSubset[1] = xVec[i1];
yVecSubset[1] = yVec[i1];
for (int i2 = i1 + 1; i2 < n; i2++) {
xVecSubset[2] = xVec[i2];
yVecSubset[2] = yVec[i2];
Fr s = new Fr();
MCL.Recover(ref s, xVecSubset, yVecSubset);
assert("Recover", s.Equals(cVec[0]));
}
}
}
}
static void TestSS_G1()
{
const int n = 5;
const int k = 3; // can't change because the following loop
G1[] cVec = new G1[k];
// init polynomial coefficient
for (int i = 0; i < k; i++) {
Fr x = new Fr();
x.SetByCSPRNG();
cVec[i].SetHashOf(x.GetStr(16));
}
Fr[] xVec = new Fr[n];
G1[] yVec = new G1[n];
// share cVec[0] with yVec[0], ..., yVec[n-1]
for (int i = 0; i < n; i++) {
xVec[i].SetHashOf(i.ToString());
MCL.Share(ref yVec[i], cVec, xVec[i]);
}
// recover cVec[0] from xVecSubset and yVecSubset
Fr[] xVecSubset = new Fr[k];
G1[] yVecSubset = new G1[k];
for (int i0 = 0; i0 < n; i0++) {
xVecSubset[0] = xVec[i0];
yVecSubset[0] = yVec[i0];
for (int i1 = i0 + 1; i1 < n; i1++) {
xVecSubset[1] = xVec[i1];
yVecSubset[1] = yVec[i1];
for (int i2 = i1 + 1; i2 < n; i2++) {
xVecSubset[2] = xVec[i2];
yVecSubset[2] = yVec[i2];
G1 s = new G1();
MCL.Recover(ref s, xVecSubset, yVecSubset);
assert("Recover", s.Equals(cVec[0]));
}
}
}
}
static void TestSS_G2()
{
const int n = 5;
const int k = 3; // can't change because the following loop
G2[] cVec = new G2[k];
// init polynomial coefficient
for (int i = 0; i < k; i++) {
Fr x = new Fr();
x.SetByCSPRNG();
cVec[i].SetHashOf(x.GetStr(16));
}
Fr[] xVec = new Fr[n];
G2[] yVec = new G2[n];
// share cVec[0] with yVec[0], ..., yVec[n-1]
for (int i = 0; i < n; i++) {
xVec[i].SetHashOf(i.ToString());
MCL.Share(ref yVec[i], cVec, xVec[i]);
}
// recover cVec[0] from xVecSubset and yVecSubset
Fr[] xVecSubset = new Fr[k];
G2[] yVecSubset = new G2[k];
for (int i0 = 0; i0 < n; i0++) {
xVecSubset[0] = xVec[i0];
yVecSubset[0] = yVec[i0];
for (int i1 = i0 + 1; i1 < n; i1++) {
xVecSubset[1] = xVec[i1];
yVecSubset[1] = yVec[i1];
for (int i2 = i1 + 1; i2 < n; i2++) {
xVecSubset[2] = xVec[i2];
yVecSubset[2] = yVec[i2];
G2 s = new G2();
MCL.Recover(ref s, xVecSubset, yVecSubset);
assert("Recover", s.Equals(cVec[0]));
}
}
}
}
static void TestSS()
{
TestSS_Fr();
TestSS_G1();
TestSS_G2();
}
}
}

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<Compile Remove="CVS\**" />
<EmbeddedResource Remove="CVS\**" />
<None Remove="CVS\**" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mcl\mcl.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath></OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath></OutputPath>
</PropertyGroup>
</Project>

@ -11,6 +11,7 @@ package mcl
*/
import "C"
import "fmt"
// Init --
// call this function before calling all the other operations
// this function is not thread safe
@ -21,5 +22,3 @@ func Init(curve int) error {
}
return nil
}

@ -19,18 +19,27 @@ const CurveFp382_1 = C.mclBn_CurveFp382_1
// CurveFp382_2 -- 382 bit curve 2
const CurveFp382_2 = C.mclBn_CurveFp382_2
// BLS12_381
// BLS12_381 --
const BLS12_381 = C.MCL_BLS12_381
// IoSerializeHexStr
// IoSerializeHexStr --
const IoSerializeHexStr = C.MCLBN_IO_SERIALIZE_HEX_STR
// GetFrUnitSize() --
// IO_EC_AFFINE --
const IO_EC_AFFINE = C.MCLBN_IO_EC_AFFINE
// IO_EC_PROJ --
const IO_EC_PROJ = C.MCLBN_IO_EC_PROJ
// IRTF -- for SetMapToMode
const IRTF = 5 /* MCL_MAP_TO_MODE_HASH_TO_CURVE_07 */
// GetFrUnitSize --
func GetFrUnitSize() int {
return int(C.MCLBN_FR_UNIT_SIZE)
}
// GetFpUnitSize() --
// GetFpUnitSize --
// same as GetMaxOpUnitSize()
func GetFpUnitSize() int {
return int(C.MCLBN_FP_UNIT_SIZE)
@ -47,6 +56,26 @@ func GetOpUnitSize() int {
return int(C.mclBn_getOpUnitSize())
}
// GetFrByteSize -- the serialized size of Fr
func GetFrByteSize() int {
return int(C.mclBn_getFrByteSize())
}
// GetFpByteSize -- the serialized size of Fp
func GetFpByteSize() int {
return int(C.mclBn_getFpByteSize())
}
// GetG1ByteSize -- the serialized size of G1
func GetG1ByteSize() int {
return GetFpByteSize()
}
// GetG2ByteSize -- the serialized size of G2
func GetG2ByteSize() int {
return GetFpByteSize() * 2
}
// GetCurveOrder --
// return the order of G1
func GetCurveOrder() string {
@ -71,6 +100,42 @@ func GetFieldOrder() string {
return string(buf[:n])
}
func bool2Cint(b bool) C.int {
if b {
return 1
} else {
return 0
}
}
// VerifyOrderG1 -- verify order if SetString/Deserialize are called
func VerifyOrderG1(doVerify bool) {
// #nosec
C.mclBn_verifyOrderG1(bool2Cint(doVerify))
}
// VerifyOrderG2 -- verify order if SetString/Deserialize are called
func VerifyOrderG2(doVerify bool) {
// #nosec
C.mclBn_verifyOrderG2(bool2Cint(doVerify))
}
// SetETHserialization --
func SetETHserialization(enable bool) {
// #nosec
C.mclBn_setETHserialization(bool2Cint(enable))
}
// SetMapToMode --
func SetMapToMode(mode int) error {
// #nosec
err := C.mclBn_setMapToMode((C.int)(mode))
if err != 0 {
return fmt.Errorf("SetMapToMode mode=%d\n", mode)
}
return nil
}
// Fr --
type Fr struct {
v C.mclBnFr
@ -108,8 +173,8 @@ func (x *Fr) SetString(s string, base int) error {
// 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 {
n := C.mclBnFr_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnFr_deserialize %x", buf)
}
return nil
@ -125,6 +190,26 @@ func (x *Fr) SetLittleEndian(buf []byte) error {
return nil
}
// SetLittleEndianMod --
func (x *Fr) SetLittleEndianMod(buf []byte) error {
// #nosec
err := C.mclBnFr_setLittleEndianMod(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFr_setLittleEndianMod %x", err)
}
return nil
}
// SetBigEndianMod --
func (x *Fr) SetBigEndianMod(buf []byte) error {
// #nosec
err := C.mclBnFr_setBigEndianMod(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFr_setBigEndianMod %x", err)
}
return nil
}
// IsEqual --
func (x *Fr) IsEqual(rhs *Fr) bool {
return C.mclBnFr_isEqual(x.getPointer(), rhs.getPointer()) == 1
@ -135,11 +220,26 @@ func (x *Fr) IsZero() bool {
return C.mclBnFr_isZero(x.getPointer()) == 1
}
// IsValid --
func (x *Fr) IsValid() bool {
return C.mclBnFr_isValid(x.getPointer()) == 1
}
// IsOne --
func (x *Fr) IsOne() bool {
return C.mclBnFr_isOne(x.getPointer()) == 1
}
// IsOdd --
func (x *Fr) IsOdd() bool {
return C.mclBnFr_isOdd(x.getPointer()) == 1
}
// IsNegative -- true if x >= (r + 1) / 2
func (x *Fr) IsNegative() bool {
return C.mclBnFr_isNegative(x.getPointer()) == 1
}
// SetByCSPRNG --
func (x *Fr) SetByCSPRNG() {
err := C.mclBnFr_setByCSPRNG(x.getPointer())
@ -186,6 +286,11 @@ func FrInv(out *Fr, x *Fr) {
C.mclBnFr_inv(out.getPointer(), x.getPointer())
}
// FrSqr --
func FrSqr(out *Fr, x *Fr) {
C.mclBnFr_sqr(out.getPointer(), x.getPointer())
}
// FrAdd --
func FrAdd(out *Fr, x *Fr, y *Fr) {
C.mclBnFr_add(out.getPointer(), x.getPointer(), y.getPointer())
@ -206,9 +311,289 @@ func FrDiv(out *Fr, x *Fr, y *Fr) {
C.mclBnFr_div(out.getPointer(), x.getPointer(), y.getPointer())
}
// FrSquareRoot --
func FrSquareRoot(out *Fr, x *Fr) bool {
return C.mclBnFr_squareRoot(out.getPointer(), x.getPointer()) == 0
}
// Fp --
type Fp struct {
v C.mclBnFp
}
// getPointer --
func (x *Fp) getPointer() (p *C.mclBnFp) {
// #nosec
return (*C.mclBnFp)(unsafe.Pointer(x))
}
// Clear --
func (x *Fp) Clear() {
// #nosec
C.mclBnFp_clear(x.getPointer())
}
// SetInt64 --
func (x *Fp) SetInt64(v int64) {
// #nosec
C.mclBnFp_setInt(x.getPointer(), C.int64_t(v))
}
// SetString --
func (x *Fp) SetString(s string, base int) error {
buf := []byte(s)
// #nosec
err := C.mclBnFp_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base))
if err != 0 {
return fmt.Errorf("err mclBnFp_setStr %x", err)
}
return nil
}
// Deserialize --
func (x *Fp) Deserialize(buf []byte) error {
// #nosec
n := C.mclBnFp_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnFp_deserialize %x", buf)
}
return nil
}
// SetLittleEndian --
func (x *Fp) SetLittleEndian(buf []byte) error {
// #nosec
err := C.mclBnFp_setLittleEndian(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFp_setLittleEndian %x", err)
}
return nil
}
// SetLittleEndianMod --
func (x *Fp) SetLittleEndianMod(buf []byte) error {
// #nosec
err := C.mclBnFp_setLittleEndianMod(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFp_setLittleEndianMod %x", err)
}
return nil
}
// SetBigEndianMod --
func (x *Fp) SetBigEndianMod(buf []byte) error {
// #nosec
err := C.mclBnFp_setBigEndianMod(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFp_setBigEndianMod %x", err)
}
return nil
}
// IsEqual --
func (x *Fp) IsEqual(rhs *Fp) bool {
return C.mclBnFp_isEqual(x.getPointer(), rhs.getPointer()) == 1
}
// IsZero --
func (x *Fp) IsZero() bool {
return C.mclBnFp_isZero(x.getPointer()) == 1
}
// IsValid --
func (x *Fp) IsValid() bool {
return C.mclBnFp_isValid(x.getPointer()) == 1
}
// IsOne --
func (x *Fp) IsOne() bool {
return C.mclBnFp_isOne(x.getPointer()) == 1
}
// IsOdd --
func (x *Fp) IsOdd() bool {
return C.mclBnFp_isOdd(x.getPointer()) == 1
}
// IsNegative -- true if x >= (p + 1) / 2
func (x *Fp) IsNegative() bool {
return C.mclBnFp_isNegative(x.getPointer()) == 1
}
// SetByCSPRNG --
func (x *Fp) SetByCSPRNG() {
err := C.mclBnFp_setByCSPRNG(x.getPointer())
if err != 0 {
panic("err mclBnFp_setByCSPRNG")
}
}
// SetHashOf --
func (x *Fp) SetHashOf(buf []byte) bool {
// #nosec
return C.mclBnFp_setHashOf(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) == 0
}
// GetString --
func (x *Fp) GetString(base int) string {
buf := make([]byte, 2048)
// #nosec
n := C.mclBnFp_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base))
if n == 0 {
panic("err mclBnFp_getStr")
}
return string(buf[:n])
}
// Serialize --
func (x *Fp) Serialize() []byte {
buf := make([]byte, 2048)
// #nosec
n := C.mclBnFp_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
if n == 0 {
panic("err mclBnFp_serialize")
}
return buf[:n]
}
// FpNeg --
func FpNeg(out *Fp, x *Fp) {
C.mclBnFp_neg(out.getPointer(), x.getPointer())
}
// FpInv --
func FpInv(out *Fp, x *Fp) {
C.mclBnFp_inv(out.getPointer(), x.getPointer())
}
// FpSqr --
func FpSqr(out *Fp, x *Fp) {
C.mclBnFp_sqr(out.getPointer(), x.getPointer())
}
// FpAdd --
func FpAdd(out *Fp, x *Fp, y *Fp) {
C.mclBnFp_add(out.getPointer(), x.getPointer(), y.getPointer())
}
// FpSub --
func FpSub(out *Fp, x *Fp, y *Fp) {
C.mclBnFp_sub(out.getPointer(), x.getPointer(), y.getPointer())
}
// FpMul --
func FpMul(out *Fp, x *Fp, y *Fp) {
C.mclBnFp_mul(out.getPointer(), x.getPointer(), y.getPointer())
}
// FpDiv --
func FpDiv(out *Fp, x *Fp, y *Fp) {
C.mclBnFp_div(out.getPointer(), x.getPointer(), y.getPointer())
}
// FpSquareRoot --
func FpSquareRoot(out *Fp, x *Fp) bool {
return C.mclBnFp_squareRoot(out.getPointer(), x.getPointer()) == 0
}
// Fp2 -- x = D[0] + D[1] i where i^2 = -1
type Fp2 struct {
D [2]Fp
}
// getPointer --
func (x *Fp2) getPointer() (p *C.mclBnFp2) {
// #nosec
return (*C.mclBnFp2)(unsafe.Pointer(x))
}
// Clear --
func (x *Fp2) Clear() {
// #nosec
C.mclBnFp2_clear(x.getPointer())
}
// Deserialize --
func (x *Fp2) Deserialize(buf []byte) error {
// #nosec
n := C.mclBnFp2_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnFp2_deserialize %x", buf)
}
return nil
}
// IsEqual --
func (x *Fp2) IsEqual(rhs *Fp2) bool {
return C.mclBnFp2_isEqual(x.getPointer(), rhs.getPointer()) == 1
}
// IsZero --
func (x *Fp2) IsZero() bool {
return C.mclBnFp2_isZero(x.getPointer()) == 1
}
// IsOne --
func (x *Fp2) IsOne() bool {
return C.mclBnFp2_isOne(x.getPointer()) == 1
}
// Serialize --
func (x *Fp2) Serialize() []byte {
buf := make([]byte, 2048)
// #nosec
n := C.mclBnFp2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
if n == 0 {
panic("err mclBnFp2_serialize")
}
return buf[:n]
}
// Fp2Neg --
func Fp2Neg(out *Fp2, x *Fp2) {
C.mclBnFp2_neg(out.getPointer(), x.getPointer())
}
// Fp2Inv --
func Fp2Inv(out *Fp2, x *Fp2) {
C.mclBnFp2_inv(out.getPointer(), x.getPointer())
}
// Fp2Sqr --
func Fp2Sqr(out *Fp2, x *Fp2) {
C.mclBnFp2_sqr(out.getPointer(), x.getPointer())
}
// Fp2Add --
func Fp2Add(out *Fp2, x *Fp2, y *Fp2) {
C.mclBnFp2_add(out.getPointer(), x.getPointer(), y.getPointer())
}
// Fp2Sub --
func Fp2Sub(out *Fp2, x *Fp2, y *Fp2) {
C.mclBnFp2_sub(out.getPointer(), x.getPointer(), y.getPointer())
}
// Fp2Mul --
func Fp2Mul(out *Fp2, x *Fp2, y *Fp2) {
C.mclBnFp2_mul(out.getPointer(), x.getPointer(), y.getPointer())
}
// Fp2Div --
func Fp2Div(out *Fp2, x *Fp2, y *Fp2) {
C.mclBnFp2_div(out.getPointer(), x.getPointer(), y.getPointer())
}
// Fp2SquareRoot --
func Fp2SquareRoot(out *Fp2, x *Fp2) bool {
return C.mclBnFp2_squareRoot(out.getPointer(), x.getPointer()) == 0
}
// G1 --
type G1 struct {
v C.mclBnG1
X Fp
Y Fp
Z Fp
}
// getPointer --
@ -237,13 +622,54 @@ func (x *G1) SetString(s string, base int) error {
// 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 {
n := C.mclBnG1_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnG1_deserialize %x", buf)
}
return nil
}
const ZERO_HEADER = 1 << 6
func isZeroFormat(buf []byte, n int) bool {
if len(buf) < n {
return false
}
if buf[0] != ZERO_HEADER {
return false
}
for i := 1; i < n; i++ {
if buf[i] != 0 {
return false
}
}
return true
}
// DeserializeUncompressed -- x.Deserialize() + y.Deserialize()
func (x *G1) DeserializeUncompressed(buf []byte) error {
if isZeroFormat(buf, GetG1ByteSize()*2) {
x.Clear()
return nil
}
// #nosec
var n = C.mclBnFp_deserialize(x.X.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 {
return fmt.Errorf("err UncompressedDeserialize X %x", buf)
}
buf = buf[n:]
// #nosec
n = C.mclBnFp_deserialize(x.Y.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 {
return fmt.Errorf("err UncompressedDeserialize Y %x", buf)
}
x.Z.SetInt64(1)
if !x.IsValid() {
return fmt.Errorf("err invalid point")
}
return nil
}
// IsEqual --
func (x *G1) IsEqual(rhs *G1) bool {
return C.mclBnG1_isEqual(x.getPointer(), rhs.getPointer()) == 1
@ -254,6 +680,16 @@ func (x *G1) IsZero() bool {
return C.mclBnG1_isZero(x.getPointer()) == 1
}
// IsValid --
func (x *G1) IsValid() bool {
return C.mclBnG1_isValid(x.getPointer()) == 1
}
// IsValidOrder --
func (x *G1) IsValidOrder() bool {
return C.mclBnG1_isValidOrder(x.getPointer()) == 1
}
// HashAndMapTo --
func (x *G1) HashAndMapTo(buf []byte) error {
// #nosec
@ -277,13 +713,39 @@ func (x *G1) GetString(base int) string {
// Serialize --
func (x *G1) Serialize() []byte {
buf := make([]byte, 2048)
buf := make([]byte, GetG1ByteSize())
// #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]
return buf
}
// SerializeUncompressed -- all zero array if x.IsZero()
func (x *G1) SerializeUncompressed() []byte {
buf := make([]byte, GetG1ByteSize()*2)
if x.IsZero() {
buf[0] = ZERO_HEADER
return buf
}
var nx G1
G1Normalize(&nx, x)
// #nosec
var n = C.mclBnFp_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), nx.X.getPointer())
if n == 0 {
panic("err mclBnFp_serialize X")
}
n = C.mclBnFp_serialize(unsafe.Pointer(&buf[n]), C.size_t(len(buf))-n, nx.Y.getPointer())
if n == 0 {
panic("err mclBnFp_serialize Y")
}
return buf
}
// G1Normalize --
func G1Normalize(out *G1, x *G1) {
C.mclBnG1_normalize(out.getPointer(), x.getPointer())
}
// G1Neg --
@ -311,6 +773,14 @@ func G1Mul(out *G1, x *G1, y *Fr) {
C.mclBnG1_mul(out.getPointer(), x.getPointer(), y.getPointer())
}
// G1MulVec -- multi scalar multiplication out = sum mul(xVec[i], yVec[i])
func G1MulVec(out *G1, xVec []G1, yVec []Fr) {
if len(xVec) != len(yVec) {
panic("xVec and yVec have the same size")
}
C.mclBnG1_mulVec(out.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec)))
}
// 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())
@ -318,7 +788,9 @@ func G1MulCT(out *G1, x *G1, y *Fr) {
// G2 --
type G2 struct {
v C.mclBnG2
X Fp2
Y Fp2
Z Fp2
}
// getPointer --
@ -347,13 +819,38 @@ func (x *G2) SetString(s string, base int) error {
// 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 {
n := C.mclBnG2_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnG2_deserialize %x", buf)
}
return nil
}
// DeserializeUncompressed -- x.Deserialize() + y.Deserialize()
func (x *G2) DeserializeUncompressed(buf []byte) error {
if isZeroFormat(buf, GetG2ByteSize()*2) {
x.Clear()
return nil
}
// #nosec
var n = C.mclBnFp2_deserialize(x.X.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 {
return fmt.Errorf("err UncompressedDeserialize X %x", buf)
}
buf = buf[n:]
// #nosec
n = C.mclBnFp2_deserialize(x.Y.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 {
return fmt.Errorf("err UncompressedDeserialize Y %x", buf)
}
x.Z.D[0].SetInt64(1)
x.Z.D[1].Clear()
if !x.IsValid() {
return fmt.Errorf("err invalid point")
}
return nil
}
// IsEqual --
func (x *G2) IsEqual(rhs *G2) bool {
return C.mclBnG2_isEqual(x.getPointer(), rhs.getPointer()) == 1
@ -364,6 +861,16 @@ func (x *G2) IsZero() bool {
return C.mclBnG2_isZero(x.getPointer()) == 1
}
// IsValid --
func (x *G2) IsValid() bool {
return C.mclBnG2_isValid(x.getPointer()) == 1
}
// IsValidOrder --
func (x *G2) IsValidOrder() bool {
return C.mclBnG2_isValidOrder(x.getPointer()) == 1
}
// HashAndMapTo --
func (x *G2) HashAndMapTo(buf []byte) error {
// #nosec
@ -396,6 +903,32 @@ func (x *G2) Serialize() []byte {
return buf[:n]
}
// SerializeUncompressed -- all zero array if x.IsZero()
func (x *G2) SerializeUncompressed() []byte {
buf := make([]byte, GetG2ByteSize()*2)
if x.IsZero() {
buf[0] = ZERO_HEADER
return buf
}
var nx G2
G2Normalize(&nx, x)
// #nosec
var n = C.mclBnFp2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), nx.X.getPointer())
if n == 0 {
panic("err mclBnFp2_serialize X")
}
n = C.mclBnFp2_serialize(unsafe.Pointer(&buf[n]), C.size_t(len(buf))-n, nx.Y.getPointer())
if n == 0 {
panic("err mclBnFp2_serialize Y")
}
return buf
}
// G2Normalize --
func G2Normalize(out *G2, x *G2) {
C.mclBnG2_normalize(out.getPointer(), x.getPointer())
}
// G2Neg --
func G2Neg(out *G2, x *G2) {
C.mclBnG2_neg(out.getPointer(), x.getPointer())
@ -421,6 +954,14 @@ func G2Mul(out *G2, x *G2, y *Fr) {
C.mclBnG2_mul(out.getPointer(), x.getPointer(), y.getPointer())
}
// G2MulVec -- multi scalar multiplication out = sum mul(xVec[i], yVec[i])
func G2MulVec(out *G2, xVec []G2, yVec []Fr) {
if len(xVec) != len(yVec) {
panic("xVec and yVec have the same size")
}
C.mclBnG2_mulVec(out.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec)))
}
// GT --
type GT struct {
v C.mclBnGT
@ -458,8 +999,8 @@ func (x *GT) SetString(s string, base int) error {
// 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 {
n := C.mclBnGT_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnGT_deserialize %x", buf)
}
return nil
@ -537,6 +1078,22 @@ func GTPow(out *GT, x *GT, y *Fr) {
C.mclBnGT_pow(out.getPointer(), x.getPointer(), y.getPointer())
}
// MapToG1 --
func MapToG1(out *G1, x *Fp) error {
if C.mclBnFp_mapToG1(out.getPointer(), x.getPointer()) != 0 {
return fmt.Errorf("err mclBnFp_mapToG1")
}
return nil
}
// MapToG2 --
func MapToG2(out *G2, x *Fp2) error {
if C.mclBnFp2_mapToG2(out.getPointer(), x.getPointer()) != 0 {
return fmt.Errorf("err mclBnFp2_mapToG2")
}
return nil
}
// Pairing --
func Pairing(out *GT, x *G1, y *G2) {
C.mclBn_pairing(out.getPointer(), x.getPointer(), y.getPointer())
@ -552,6 +1109,14 @@ func MillerLoop(out *GT, x *G1, y *G2) {
C.mclBn_millerLoop(out.getPointer(), x.getPointer(), y.getPointer())
}
// MillerLoopVec -- multi pairings ; out = prod_i e(xVec[i], yVec[i])
func MillerLoopVec(out *GT, xVec []G1, yVec []G2) {
if len(xVec) != len(yVec) {
panic("xVec and yVec have the same size")
}
C.mclBn_millerLoopVec(out.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec)))
}
// GetUint64NumToPrecompute --
func GetUint64NumToPrecompute() int {
return int(C.mclBn_getUint64NumToPrecompute())

@ -2,6 +2,7 @@ package mcl
import "testing"
import "fmt"
import "encoding/hex"
func testBadPointOfG2(t *testing.T) {
var Q G2
@ -71,6 +72,71 @@ func testNegAdd(t *testing.T) {
}
}
func testVecG1(t *testing.T) {
N := 50
xVec := make([]G1, N)
yVec := make([]Fr, N)
xVec[0].HashAndMapTo([]byte("aa"))
var R1, R2 G1
for i := 0; i < N; i++ {
if i > 0 {
G1Dbl(&xVec[i], &xVec[i-1])
}
yVec[i].SetByCSPRNG()
G1Mul(&R1, &xVec[i], &yVec[i])
G1Add(&R2, &R2, &R1)
}
G1MulVec(&R1, xVec, yVec)
if !R1.IsEqual(&R2) {
t.Errorf("wrong G1MulVec")
}
}
func testVecG2(t *testing.T) {
N := 50
xVec := make([]G2, N)
yVec := make([]Fr, N)
xVec[0].HashAndMapTo([]byte("aa"))
var R1, R2 G2
for i := 0; i < N; i++ {
if i > 0 {
G2Dbl(&xVec[i], &xVec[i-1])
}
yVec[i].SetByCSPRNG()
G2Mul(&R1, &xVec[i], &yVec[i])
G2Add(&R2, &R2, &R1)
}
G2MulVec(&R1, xVec, yVec)
if !R1.IsEqual(&R2) {
t.Errorf("wrong G2MulVec")
}
}
func testVecPairing(t *testing.T) {
N := 50
xVec := make([]G1, N)
yVec := make([]G2, N)
var e1, e2 GT
e1.SetInt64(1)
for i := 0; i < N; i++ {
xVec[0].HashAndMapTo([]byte("aa"))
yVec[0].HashAndMapTo([]byte("aa"))
Pairing(&e2, &xVec[i], &yVec[i])
GTMul(&e1, &e1, &e2)
}
MillerLoopVec(&e2, xVec, yVec)
FinalExp(&e2, &e2)
if !e1.IsEqual(&e2) {
t.Errorf("wrong MillerLoopVec")
}
}
func testVec(t *testing.T) {
testVecG1(t)
testVecG2(t)
testVecPairing(t)
}
func testPairing(t *testing.T) {
var a, b, ab Fr
err := a.SetString("123", 10)
@ -130,6 +196,44 @@ func testPairing(t *testing.T) {
}
}
func testSerialize(t *testing.T) {
var x, xx Fr
var y, yy Fp
var P, PP G1
var Q, QQ G2
var e, ee GT
x.SetByCSPRNG()
y.SetByCSPRNG()
P.HashAndMapTo([]byte("abc"))
G1Dbl(&P, &P)
Q.HashAndMapTo([]byte("abc"))
G2Dbl(&Q, &Q)
Pairing(&e, &P, &Q)
if xx.Deserialize(x.Serialize()) != nil || !x.IsEqual(&xx) {
t.Error("Serialize Fr")
}
if yy.Deserialize(y.Serialize()) != nil || !y.IsEqual(&yy) {
t.Error("Serialize Fp")
}
if PP.Deserialize(P.Serialize()) != nil || !P.IsEqual(&PP) {
t.Error("Serialize G1")
}
if QQ.Deserialize(Q.Serialize()) != nil || !Q.IsEqual(&QQ) {
t.Error("Serialize G2")
}
if ee.Deserialize(e.Serialize()) != nil || !e.IsEqual(&ee) {
t.Error("Serialize GT")
}
G1Dbl(&PP, &PP)
if PP.DeserializeUncompressed(P.SerializeUncompressed()) != nil || !P.IsEqual(&PP) {
t.Error("SerializeUncompressed G1")
}
G2Dbl(&QQ, &QQ)
if QQ.DeserializeUncompressed(Q.SerializeUncompressed()) != nil || !Q.IsEqual(&QQ) {
t.Error("SerializeUncompressed G2")
}
}
func testMcl(t *testing.T, c int) {
err := Init(c)
if err != nil {
@ -138,8 +242,47 @@ func testMcl(t *testing.T, c int) {
testHash(t)
testNegAdd(t)
testPairing(t)
testVec(t)
testGT(t)
testBadPointOfG2(t)
testSerialize(t)
}
func testETHserialize(t *testing.T) {
b := make([]byte, 32)
b[0] = 0x12
b[1] = 0x34
var x Fr
SetETHserialization(false)
x.Deserialize(b)
fmt.Printf("AAA x=%s\n", x.GetString(16))
SetETHserialization(true)
x.Deserialize(b)
fmt.Printf("AAA x=%s\n", x.GetString(16))
}
func testMapToG1(t *testing.T) {
SetMapToMode(IRTF)
fpHex := "0000000000000000000000000000000014406e5bfb9209256a3820879a29ac2f62d6aca82324bf3ae2aa7d3c54792043bd8c791fccdb080c1a52dc68b8b69350"
g1Hex := "ad7721bcdb7ce1047557776eb2659a444166dc6dd55c7ca6e240e21ae9aa18f529f04ac31d861b54faf3307692545db7"
fpBin, _ := hex.DecodeString(fpHex)
var x Fp
x.SetBigEndianMod(fpBin)
var P1 G1
err := MapToG1(&P1, &x)
if err != nil {
t.Fatal("MapToG1")
}
g1Str, _ := hex.DecodeString(g1Hex)
var P2 G1
err = P2.Deserialize(g1Str)
if err != nil {
t.Fatal("G1.Deserialize")
}
if !P1.IsEqual(&P2) {
t.Fatal("bad MapToG1")
}
}
func TestMclMain(t *testing.T) {
@ -153,5 +296,7 @@ func TestMclMain(t *testing.T) {
}
t.Log("BLS12_381")
testMcl(t, BLS12_381)
testETHserialize(t)
testMapToG1(t)
}
}

@ -1,104 +0,0 @@
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));
}
}

@ -8,7 +8,7 @@ import com.herumi.mcl.*;
*/
public class ElgamalTest {
static {
String lib = "mcl_elgamal";
String lib = "mclelgamaljava";
String libName = System.mapLibraryName(lib);
System.out.println("libName : " + libName);
System.loadLibrary(lib);

@ -1,46 +1,50 @@
TOP_DIR=../..
include $(TOP_DIR)/common.mk
ifeq ($(UNAME_S),Darwin)
JAVA_INC=-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/
JAVA_INC_DIR?=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/JavaVM.framework/Headers/
JAVA_INC?=-I$(JAVA_INC_DIR)
CFLAGS+=$(JAVA_INC)/darwin
else
JAVA_INC=-I/usr/lib/jvm/default-java/include
JAVA_INC_DIR?=/usr/lib/jvm/default-java/include
JAVA_INC?=-I$(JAVA_INC_DIR)
#JAVA_INC=-I/usr/lib/jvm/java-7-openjdk-amd64/include
CFLAGS+=$(JAVA_INC)/linux
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
CFLAGS+=$(JAVA_INC) -I $(TOP_DIR)/include -I -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
ELGAMAL_LIB=$(TOP_DIR)/lib/libmclelgamaljava.$(LIB_SUF)
MCLJAVA_LIB=$(TOP_DIR)/lib/libmcljava.$(LIB_SUF)
JAVA_EXE=cd $(TOP_DIR)/lib && LD_LIBRARY_PATH=../lib:$(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
mcl_wrap.cxx: mcl.i mcl_impl.hpp
$(MKDIR) $(PACKAGE_DIR)
swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall bn256.i
swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall mcl.i
$(MCL_LIB):
make -C $(TOP_DIR)
make -C $(TOP_DIR) lib/libmcl.a
$(ELGAMAL_LIB): elgamal_wrap.cxx $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(CFLAGS) $(LDFLAGS) $(MCL_LIB) -shared
$(PRE)$(CXX) $< -o $@ $(CFLAGS) $(MCL_LIB) $(LDFLAGS) -shared
$(BN256_LIB): bn256_wrap.cxx $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(CFLAGS) $(LDFLAGS) $(MCL_LIB) -shared
$(MCLJAVA_LIB): mcl_wrap.cxx $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(CFLAGS) $(MCL_LIB) $(LDFLAGS) -shared
%.class: %.java
javac $<
ElgamalTest.class: ElgamalTest.java $(ELGAMAL_LIB)
Bn256Test.class: Bn256Test.java $(BN256_LIB)
MclTest.class: MclTest.java $(MCLJAVA_LIB)
jar:
jar cvf mcl.jar com
@ -49,16 +53,17 @@ 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 secp256k1 -h sha256
$(JAVA_EXE) ElgamalTest -e NIST_P384 -h sha384
$(JAVA_EXE) ElgamalTest -e NIST_P521 -h sha512
# $(JAVA_EXE) ElgamalTest -e NIST_P521 -h sha512
test_bn256: Bn256Test.class $(BN256_LIB)
$(JAVA_EXE) Bn256Test
test_mcl: MclTest.class $(MCLJAVA_LIB)
$(JAVA_EXE) MclTest
test:
$(MAKE) test_elgamal
$(MAKE) test_bn256
$(MAKE) test_mcl
clean:
rm -rf *.class $(ELGAMAL_LIB) $(PACKAGE_DIR)/*.class *_wrap.cxx
rm -rf *.class $(ELGAMAL_LIB) $(MCLJAVA_LIB) $(PACKAGE_DIR)/*.class *_wrap.cxx

@ -0,0 +1,160 @@
import java.io.*;
import com.herumi.mcl.*;
/*
MclTest
*/
public class MclTest {
static {
String lib = "mcljava";
String libName = System.mapLibraryName(lib);
System.out.println("libName : " + libName);
System.loadLibrary(lib);
}
public static int errN = 0;
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);
errN++;
}
}
public static void assertBool(String msg, boolean b) {
if (b) {
System.out.println("OK : " + msg);
} else {
System.out.println("NG : " + msg);
errN++;
}
}
public static void testCurve(int curveType, String name) {
try {
System.out.println("curve=" + name);
Mcl.SystemInit(curveType);
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");
Mcl.add(x, x, y);
assertEquals("x == 3", x.toString(), "3");
Mcl.mul(x, x, x);
assertEquals("x == 9", x.toString(), "9");
assertEquals("x == 12", (new Fr("12")).toString(), "12");
assertEquals("x == 18", (new Fr("12", 16)).toString(), "18");
assertEquals("x == ff", (new Fr("255")).toString(16), "ff");
Mcl.inv(y, x);
Mcl.mul(x, y, x);
assertBool("x == 1", x.isOne());
{
byte[] b = x.serialize();
Fr t = new Fr();
t.deserialize(b);
assertBool("serialize", x.equals(t));
t.setLittleEndianMod(b);
assertBool("setLittleEndianMod", x.equals(t));
t.setHashOf(b);
assertBool("setHashOf", !x.equals(t));
Fr u = new Fr();
u.setHashOf(new byte[]{1,2,3});
assertBool("setHashOf - different", !u.equals(t));
}
G1 P = new G1();
System.out.println("P=" + P);
Mcl.hashAndMapToG1(P, "test".getBytes());
System.out.println("P=" + P);
byte[] buf = { 1, 2, 3, 4 };
Mcl.hashAndMapToG1(P, buf);
System.out.println("P=" + P);
Mcl.neg(P, P);
System.out.println("P=" + P);
{
byte[] b = P.serialize();
G1 t = new G1();
t.deserialize(b);
assertBool("serialize", P.equals(t));
}
G2 Q = new G2();
Mcl.hashAndMapToG2(Q, "abc".getBytes());
System.out.println("Q=" + Q);
Mcl.hashAndMapToG1(P, "This is a pen".getBytes());
{
String s = P.toString();
G1 P1 = new G1();
P1.setStr(s);
assertBool("P == P1", P1.equals(P));
}
{
byte[] b = Q.serialize();
G2 t = new G2();
t.deserialize(b);
assertBool("serialize", Q.equals(t));
}
GT e = new GT();
Mcl.pairing(e, P, Q);
GT e1 = new GT();
GT e2 = new GT();
Fr c = new Fr("1234567890123234928348230428394234");
System.out.println("c=" + c);
G2 cQ = new G2(Q);
Mcl.mul(cQ, Q, c); // cQ = Q * c
Mcl.pairing(e1, P, cQ);
Mcl.pow(e2, e, c); // e2 = e^c
assertBool("e1 == e2", e1.equals(e2));
{
byte[] b = e1.serialize();
GT t = new GT();
t.deserialize(b);
assertBool("serialize", e1.equals(t));
}
G1 cP = new G1(P);
Mcl.mul(cP, P, c); // cP = P * c
Mcl.pairing(e1, cP, Q);
assertBool("e1 == e2", e1.equals(e2));
Mcl.inv(e1, e1);
Mcl.mul(e1, e1, e2);
e2.setStr("1 0 0 0 0 0 0 0 0 0 0 0");
assertBool("e1 == 1", e1.equals(e2));
assertBool("e1 == 1", e1.isOne());
BLSsignature(Q);
if (errN == 0) {
System.out.println("all test passed");
} else {
System.out.println("ERR=" + errN);
}
} catch (RuntimeException e) {
System.out.println("unknown exception :" + e);
}
}
public static void BLSsignature(G2 Q)
{
Fr s = new Fr();
s.setByCSPRNG(); // secret key
System.out.println("secret key " + s);
G2 pub = new G2();
Mcl.mul(pub, Q, s); // public key = sQ
byte[] m = "signature test".getBytes();
G1 H = new G1();
Mcl.hashAndMapToG1(H, m); // H = Hash(m)
G1 sign = new G1();
Mcl.mul(sign, H, s); // signature of m = s H
GT e1 = new GT();
GT e2 = new GT();
Mcl.pairing(e1, H, pub); // e1 = e(H, s Q)
Mcl.pairing(e2, sign, Q); // e2 = e(s H, Q);
assertBool("verify signature", e1.equals(e2));
}
public static void main(String argv[]) {
testCurve(Mcl.BN254, "BN254");
testCurve(Mcl.BLS12_381, "BLS12_381");
}
}

@ -0,0 +1,39 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cpp .ll .cxx
LOCAL_MODULE := mcljava
LOCAL_MCL_DIR := $(LOCAL_PATH)/../../../../
ifeq ($(TARGET_ARCH_ABI),x86_64)
MY_BIT := 64
endif
ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
MY_BIT := 64
endif
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
MY_BIT := 32
endif
ifeq ($(TARGET_ARCH_ABI),x86)
MY_BIT := 32
endif
ifeq ($(MY_BIT),64)
MY_BASE_LL := $(LOCAL_MCL_DIR)/src/base64.ll
LOCAL_CPPFLAGS += -DMCL_SIZEOF_UNIT=8
endif
ifeq ($(MY_BIT),32)
MY_BASE_LL := $(LOCAL_MCL_DIR)/src/base32.ll
LOCAL_CPPFLAGS += -DMCL_SIZEOF_UNIT=4
endif
LOCAL_SRC_FILES := $(LOCAL_MCL_DIR)/ffi/java/mcl_wrap.cxx $(LOCAL_MCL_DIR)/src/bn_c384_256.cpp $(LOCAL_MCL_DIR)/src/fp.cpp $(MY_BASE_LL)
LOCAL_C_INCLUDES := $(LOCAL_MCL_DIR)/include $(LOCAL_MCL_DIR)/src $(LOCAL_MCL_DIR)/ffi/java
LOCAL_CPPFLAGS += -DMCL_DONT_USE_XBYAK
LOCAL_CPPFLAGS += -O3 -DNDEBUG -fPIC -DMCL_DONT_USE_OPENSSL -DMCL_LLVM_BMI2=0 -DMCL_USE_LLVM=1 -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=384
LOCAL_CPPFLAGS += -fno-threadsafe-statics
#LOCAL_CPPFLAGS+=-fno-exceptions -fno-rtti -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -std=c++03
#LOCAL_CPPFLAGS += -DBLS_ETH
#LOCAL_LDLIBS := -llog #-Wl,--no-warn-shared-textrel
#include $(BUILD_STATIC_LIBRARY)
include $(BUILD_SHARED_LIBRARY)

@ -0,0 +1,4 @@
APP_ABI := arm64-v8a armeabi-v7a x86_64
APP_PLATFORM := android-19
APP_STL := c++_static
APP_CPPFLAGS := -fexceptions

@ -1,31 +0,0 @@
%module Bn256
%include "std_string.i"
%include "std_except.i"
%{
#include <cybozu/random_generator.hpp>
#include <cybozu/crypto.hpp>
#include <mcl/bn256.hpp>
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"

@ -1,249 +0,0 @@
#include <mcl/bn256.hpp>
#include <stdint.h>
#include <sstream>
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_);
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,67 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class CipherText {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected CipherText(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(CipherText obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
ElgamalJNI.delete_CipherText(swigCPtr);
}
swigCPtr = 0;
}
}
public String toStr() {
return ElgamalJNI.CipherText_toStr(swigCPtr, this);
}
public String toString() {
return ElgamalJNI.CipherText_toString(swigCPtr, this);
}
public void fromStr(String str) {
ElgamalJNI.CipherText_fromStr(swigCPtr, this, str);
}
public void add(CipherText c) {
ElgamalJNI.CipherText_add(swigCPtr, this, CipherText.getCPtr(c), c);
}
public void mul(int m) {
ElgamalJNI.CipherText_mul__SWIG_0(swigCPtr, this, m);
}
public void mul(String str) {
ElgamalJNI.CipherText_mul__SWIG_1(swigCPtr, this, str);
}
public CipherText() {
this(ElgamalJNI.new_CipherText(), true);
}
}

@ -0,0 +1,38 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class Elgamal {
public static SWIGTYPE_p_bool new_p_bool() {
long cPtr = ElgamalJNI.new_p_bool();
return (cPtr == 0) ? null : new SWIGTYPE_p_bool(cPtr, false);
}
public static SWIGTYPE_p_bool copy_p_bool(boolean value) {
long cPtr = ElgamalJNI.copy_p_bool(value);
return (cPtr == 0) ? null : new SWIGTYPE_p_bool(cPtr, false);
}
public static void delete_p_bool(SWIGTYPE_p_bool obj) {
ElgamalJNI.delete_p_bool(SWIGTYPE_p_bool.getCPtr(obj));
}
public static void p_bool_assign(SWIGTYPE_p_bool obj, boolean value) {
ElgamalJNI.p_bool_assign(SWIGTYPE_p_bool.getCPtr(obj), value);
}
public static boolean p_bool_value(SWIGTYPE_p_bool obj) {
return ElgamalJNI.p_bool_value(SWIGTYPE_p_bool.getCPtr(obj));
}
public static void SystemInit(String param) {
ElgamalJNI.SystemInit(param);
}
}

@ -0,0 +1,51 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class ElgamalJNI {
public final static native long new_p_bool();
public final static native long copy_p_bool(boolean jarg1);
public final static native void delete_p_bool(long jarg1);
public final static native void p_bool_assign(long jarg1, boolean jarg2);
public final static native boolean p_bool_value(long jarg1);
public final static native void SystemInit(String jarg1);
public final static native String CipherText_toStr(long jarg1, CipherText jarg1_);
public final static native String CipherText_toString(long jarg1, CipherText jarg1_);
public final static native void CipherText_fromStr(long jarg1, CipherText jarg1_, String jarg2);
public final static native void CipherText_add(long jarg1, CipherText jarg1_, long jarg2, CipherText jarg2_);
public final static native void CipherText_mul__SWIG_0(long jarg1, CipherText jarg1_, int jarg2);
public final static native void CipherText_mul__SWIG_1(long jarg1, CipherText jarg1_, String jarg2);
public final static native long new_CipherText();
public final static native void delete_CipherText(long jarg1);
public final static native String PublicKey_toStr(long jarg1, PublicKey jarg1_);
public final static native String PublicKey_toString(long jarg1, PublicKey jarg1_);
public final static native void PublicKey_fromStr(long jarg1, PublicKey jarg1_, String jarg2);
public final static native void PublicKey_save(long jarg1, PublicKey jarg1_, String jarg2);
public final static native void PublicKey_load(long jarg1, PublicKey jarg1_, String jarg2);
public final static native void PublicKey_enc__SWIG_0(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, int jarg3);
public final static native void PublicKey_enc__SWIG_1(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, String jarg3);
public final static native void PublicKey_rerandomize(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_);
public final static native void PublicKey_add__SWIG_0(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, int jarg3);
public final static native void PublicKey_add__SWIG_1(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, String jarg3);
public final static native long new_PublicKey();
public final static native void delete_PublicKey(long jarg1);
public final static native String PrivateKey_toStr(long jarg1, PrivateKey jarg1_);
public final static native String PrivateKey_toString(long jarg1, PrivateKey jarg1_);
public final static native void PrivateKey_fromStr(long jarg1, PrivateKey jarg1_, String jarg2);
public final static native void PrivateKey_save(long jarg1, PrivateKey jarg1_, String jarg2);
public final static native void PrivateKey_load(long jarg1, PrivateKey jarg1_, String jarg2);
public final static native void PrivateKey_init(long jarg1, PrivateKey jarg1_);
public final static native long PrivateKey_getPublicKey(long jarg1, PrivateKey jarg1_);
public final static native int PrivateKey_dec__SWIG_0(long jarg1, PrivateKey jarg1_, long jarg2, CipherText jarg2_, long jarg3);
public final static native int PrivateKey_dec__SWIG_1(long jarg1, PrivateKey jarg1_, long jarg2, CipherText jarg2_);
public final static native void PrivateKey_setCache(long jarg1, PrivateKey jarg1_, int jarg2, int jarg3);
public final static native void PrivateKey_clearCache(long jarg1, PrivateKey jarg1_);
public final static native long new_PrivateKey();
public final static native void delete_PrivateKey(long jarg1);
}

@ -0,0 +1,105 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class Fp {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected Fp(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(Fp obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_Fp(swigCPtr);
}
swigCPtr = 0;
}
}
public Fp() {
this(MclJNI.new_Fp__SWIG_0(), true);
}
public Fp(Fp rhs) {
this(MclJNI.new_Fp__SWIG_1(Fp.getCPtr(rhs), rhs), true);
}
public Fp(int x) {
this(MclJNI.new_Fp__SWIG_2(x), true);
}
public Fp(String str, int base) {
this(MclJNI.new_Fp__SWIG_3(str, base), true);
}
public Fp(String str) {
this(MclJNI.new_Fp__SWIG_4(str), true);
}
public boolean equals(Fp rhs) {
return MclJNI.Fp_equals(swigCPtr, this, Fp.getCPtr(rhs), rhs);
}
public boolean isZero() {
return MclJNI.Fp_isZero(swigCPtr, this);
}
public boolean isOne() {
return MclJNI.Fp_isOne(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.Fp_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.Fp_setStr__SWIG_1(swigCPtr, this, str);
}
public void setInt(int x) {
MclJNI.Fp_setInt(swigCPtr, this, x);
}
public void clear() {
MclJNI.Fp_clear(swigCPtr, this);
}
public void setByCSPRNG() {
MclJNI.Fp_setByCSPRNG(swigCPtr, this);
}
public String toString(int base) {
return MclJNI.Fp_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.Fp_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.Fp_deserialize(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.Fp_serialize(swigCPtr, this); }
}

@ -0,0 +1,113 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class Fr {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected Fr(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(Fr obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_Fr(swigCPtr);
}
swigCPtr = 0;
}
}
public Fr() {
this(MclJNI.new_Fr__SWIG_0(), true);
}
public Fr(Fr rhs) {
this(MclJNI.new_Fr__SWIG_1(Fr.getCPtr(rhs), rhs), true);
}
public Fr(int x) {
this(MclJNI.new_Fr__SWIG_2(x), true);
}
public Fr(String str, int base) {
this(MclJNI.new_Fr__SWIG_3(str, base), true);
}
public Fr(String str) {
this(MclJNI.new_Fr__SWIG_4(str), true);
}
public boolean equals(Fr rhs) {
return MclJNI.Fr_equals(swigCPtr, this, Fr.getCPtr(rhs), rhs);
}
public boolean isZero() {
return MclJNI.Fr_isZero(swigCPtr, this);
}
public boolean isOne() {
return MclJNI.Fr_isOne(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.Fr_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.Fr_setStr__SWIG_1(swigCPtr, this, str);
}
public void setInt(int x) {
MclJNI.Fr_setInt(swigCPtr, this, x);
}
public void clear() {
MclJNI.Fr_clear(swigCPtr, this);
}
public void setByCSPRNG() {
MclJNI.Fr_setByCSPRNG(swigCPtr, this);
}
public String toString(int base) {
return MclJNI.Fr_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.Fr_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.Fr_deserialize(swigCPtr, this, cbuf);
}
public void setLittleEndianMod(byte[] cbuf) {
MclJNI.Fr_setLittleEndianMod(swigCPtr, this, cbuf);
}
public void setHashOf(byte[] cbuf) {
MclJNI.Fr_setHashOf(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.Fr_serialize(swigCPtr, this); }
}

@ -0,0 +1,93 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class G1 {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected G1(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(G1 obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_G1(swigCPtr);
}
swigCPtr = 0;
}
}
public G1() {
this(MclJNI.new_G1__SWIG_0(), true);
}
public G1(G1 rhs) {
this(MclJNI.new_G1__SWIG_1(G1.getCPtr(rhs), rhs), true);
}
public G1(Fp x, Fp y) {
this(MclJNI.new_G1__SWIG_2(Fp.getCPtr(x), x, Fp.getCPtr(y), y), true);
}
public boolean equals(G1 rhs) {
return MclJNI.G1_equals(swigCPtr, this, G1.getCPtr(rhs), rhs);
}
public boolean isZero() {
return MclJNI.G1_isZero(swigCPtr, this);
}
public boolean isValidOrder() {
return MclJNI.G1_isValidOrder(swigCPtr, this);
}
public void set(Fp x, Fp y) {
MclJNI.G1_set(swigCPtr, this, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public void clear() {
MclJNI.G1_clear(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.G1_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.G1_setStr__SWIG_1(swigCPtr, this, str);
}
public String toString(int base) {
return MclJNI.G1_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.G1_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.G1_deserialize(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.G1_serialize(swigCPtr, this); }
}

@ -0,0 +1,89 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class G2 {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected G2(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(G2 obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_G2(swigCPtr);
}
swigCPtr = 0;
}
}
public G2() {
this(MclJNI.new_G2__SWIG_0(), true);
}
public G2(G2 rhs) {
this(MclJNI.new_G2__SWIG_1(G2.getCPtr(rhs), rhs), true);
}
public G2(Fp ax, Fp ay, Fp bx, Fp by) {
this(MclJNI.new_G2__SWIG_2(Fp.getCPtr(ax), ax, Fp.getCPtr(ay), ay, Fp.getCPtr(bx), bx, Fp.getCPtr(by), by), true);
}
public boolean equals(G2 rhs) {
return MclJNI.G2_equals(swigCPtr, this, G2.getCPtr(rhs), rhs);
}
public boolean isZero() {
return MclJNI.G2_isZero(swigCPtr, this);
}
public void set(Fp ax, Fp ay, Fp bx, Fp by) {
MclJNI.G2_set(swigCPtr, this, Fp.getCPtr(ax), ax, Fp.getCPtr(ay), ay, Fp.getCPtr(bx), bx, Fp.getCPtr(by), by);
}
public void clear() {
MclJNI.G2_clear(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.G2_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.G2_setStr__SWIG_1(swigCPtr, this, str);
}
public String toString(int base) {
return MclJNI.G2_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.G2_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.G2_deserialize(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.G2_serialize(swigCPtr, this); }
}

@ -0,0 +1,81 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class GT {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected GT(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(GT obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_GT(swigCPtr);
}
swigCPtr = 0;
}
}
public GT() {
this(MclJNI.new_GT__SWIG_0(), true);
}
public GT(GT rhs) {
this(MclJNI.new_GT__SWIG_1(GT.getCPtr(rhs), rhs), true);
}
public boolean equals(GT rhs) {
return MclJNI.GT_equals(swigCPtr, this, GT.getCPtr(rhs), rhs);
}
public boolean isOne() {
return MclJNI.GT_isOne(swigCPtr, this);
}
public void clear() {
MclJNI.GT_clear(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.GT_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.GT_setStr__SWIG_1(swigCPtr, this, str);
}
public String toString(int base) {
return MclJNI.GT_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.GT_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.GT_deserialize(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.GT_serialize(swigCPtr, this); }
}

@ -0,0 +1,128 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class Mcl implements MclConstants {
public static void SystemInit(int curveType) {
MclJNI.SystemInit(curveType);
}
public static void neg(Fr y, Fr x) {
MclJNI.neg__SWIG_0(Fr.getCPtr(y), y, Fr.getCPtr(x), x);
}
public static void inv(Fr y, Fr x) {
MclJNI.inv__SWIG_0(Fr.getCPtr(y), y, Fr.getCPtr(x), x);
}
public static void add(Fr z, Fr x, Fr y) {
MclJNI.add__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void sub(Fr z, Fr x, Fr y) {
MclJNI.sub__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void mul(Fr z, Fr x, Fr y) {
MclJNI.mul__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void mul(G1 z, G1 x, Fr y) {
MclJNI.mul__SWIG_1(G1.getCPtr(z), z, G1.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void mul(G2 z, G2 x, Fr y) {
MclJNI.mul__SWIG_2(G2.getCPtr(z), z, G2.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void div(Fr z, Fr x, Fr y) {
MclJNI.div__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void pow(GT z, GT x, Fr y) {
MclJNI.pow(GT.getCPtr(z), z, GT.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void neg(Fp y, Fp x) {
MclJNI.neg__SWIG_1(Fp.getCPtr(y), y, Fp.getCPtr(x), x);
}
public static void inv(Fp y, Fp x) {
MclJNI.inv__SWIG_1(Fp.getCPtr(y), y, Fp.getCPtr(x), x);
}
public static void add(Fp z, Fp x, Fp y) {
MclJNI.add__SWIG_1(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public static void sub(Fp z, Fp x, Fp y) {
MclJNI.sub__SWIG_1(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public static void mul(Fp z, Fp x, Fp y) {
MclJNI.mul__SWIG_3(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public static void div(Fp z, Fp x, Fp y) {
MclJNI.div__SWIG_1(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public static void neg(G1 y, G1 x) {
MclJNI.neg__SWIG_2(G1.getCPtr(y), y, G1.getCPtr(x), x);
}
public static void dbl(G1 y, G1 x) {
MclJNI.dbl__SWIG_0(G1.getCPtr(y), y, G1.getCPtr(x), x);
}
public static void add(G1 z, G1 x, G1 y) {
MclJNI.add__SWIG_2(G1.getCPtr(z), z, G1.getCPtr(x), x, G1.getCPtr(y), y);
}
public static void sub(G1 z, G1 x, G1 y) {
MclJNI.sub__SWIG_2(G1.getCPtr(z), z, G1.getCPtr(x), x, G1.getCPtr(y), y);
}
public static void pairing(GT e, G1 P, G2 Q) {
MclJNI.pairing(GT.getCPtr(e), e, G1.getCPtr(P), P, G2.getCPtr(Q), Q);
}
public static void hashAndMapToG1(G1 P, byte[] cbuf) {
MclJNI.hashAndMapToG1(G1.getCPtr(P), P, cbuf);
}
public static void neg(G2 y, G2 x) {
MclJNI.neg__SWIG_3(G2.getCPtr(y), y, G2.getCPtr(x), x);
}
public static void dbl(G2 y, G2 x) {
MclJNI.dbl__SWIG_1(G2.getCPtr(y), y, G2.getCPtr(x), x);
}
public static void add(G2 z, G2 x, G2 y) {
MclJNI.add__SWIG_3(G2.getCPtr(z), z, G2.getCPtr(x), x, G2.getCPtr(y), y);
}
public static void sub(G2 z, G2 x, G2 y) {
MclJNI.sub__SWIG_3(G2.getCPtr(z), z, G2.getCPtr(x), x, G2.getCPtr(y), y);
}
public static void hashAndMapToG2(G2 P, byte[] cbuf) {
MclJNI.hashAndMapToG2(G2.getCPtr(P), P, cbuf);
}
public static void mul(GT z, GT x, GT y) {
MclJNI.mul__SWIG_4(GT.getCPtr(z), z, GT.getCPtr(x), x, GT.getCPtr(y), y);
}
public static void inv(GT y, GT x) {
MclJNI.inv__SWIG_2(GT.getCPtr(y), y, GT.getCPtr(x), x);
}
}

@ -0,0 +1,14 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public interface MclConstants {
public final static int BN254 = 0;
public final static int BLS12_381 = 5;
}

@ -0,0 +1,120 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class MclJNI {
public final static native void SystemInit(int jarg1);
public final static native void neg__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_);
public final static native void inv__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_);
public final static native void add__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_);
public final static native void sub__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_);
public final static native void mul__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_);
public final static native void mul__SWIG_1(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_, long jarg3, Fr jarg3_);
public final static native void mul__SWIG_2(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_, long jarg3, Fr jarg3_);
public final static native void div__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_);
public final static native void pow(long jarg1, GT jarg1_, long jarg2, GT jarg2_, long jarg3, Fr jarg3_);
public final static native long new_Fr__SWIG_0();
public final static native long new_Fr__SWIG_1(long jarg1, Fr jarg1_);
public final static native long new_Fr__SWIG_2(int jarg1);
public final static native long new_Fr__SWIG_3(String jarg1, int jarg2);
public final static native long new_Fr__SWIG_4(String jarg1);
public final static native boolean Fr_equals(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_);
public final static native boolean Fr_isZero(long jarg1, Fr jarg1_);
public final static native boolean Fr_isOne(long jarg1, Fr jarg1_);
public final static native void Fr_setStr__SWIG_0(long jarg1, Fr jarg1_, String jarg2, int jarg3);
public final static native void Fr_setStr__SWIG_1(long jarg1, Fr jarg1_, String jarg2);
public final static native void Fr_setInt(long jarg1, Fr jarg1_, int jarg2);
public final static native void Fr_clear(long jarg1, Fr jarg1_);
public final static native void Fr_setByCSPRNG(long jarg1, Fr jarg1_);
public final static native String Fr_toString__SWIG_0(long jarg1, Fr jarg1_, int jarg2);
public final static native String Fr_toString__SWIG_1(long jarg1, Fr jarg1_);
public final static native void Fr_deserialize(long jarg1, Fr jarg1_, byte[] jarg2);
public final static native void Fr_setLittleEndianMod(long jarg1, Fr jarg1_, byte[] jarg2);
public final static native void Fr_setHashOf(long jarg1, Fr jarg1_, byte[] jarg2);
public final static native byte[] Fr_serialize(long jarg1, Fr jarg1_);
public final static native void delete_Fr(long jarg1);
public final static native void neg__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_);
public final static native void inv__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_);
public final static native void add__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native void sub__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native void mul__SWIG_3(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native void div__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native long new_Fp__SWIG_0();
public final static native long new_Fp__SWIG_1(long jarg1, Fp jarg1_);
public final static native long new_Fp__SWIG_2(int jarg1);
public final static native long new_Fp__SWIG_3(String jarg1, int jarg2);
public final static native long new_Fp__SWIG_4(String jarg1);
public final static native boolean Fp_equals(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_);
public final static native boolean Fp_isZero(long jarg1, Fp jarg1_);
public final static native boolean Fp_isOne(long jarg1, Fp jarg1_);
public final static native void Fp_setStr__SWIG_0(long jarg1, Fp jarg1_, String jarg2, int jarg3);
public final static native void Fp_setStr__SWIG_1(long jarg1, Fp jarg1_, String jarg2);
public final static native void Fp_setInt(long jarg1, Fp jarg1_, int jarg2);
public final static native void Fp_clear(long jarg1, Fp jarg1_);
public final static native void Fp_setByCSPRNG(long jarg1, Fp jarg1_);
public final static native String Fp_toString__SWIG_0(long jarg1, Fp jarg1_, int jarg2);
public final static native String Fp_toString__SWIG_1(long jarg1, Fp jarg1_);
public final static native void Fp_deserialize(long jarg1, Fp jarg1_, byte[] jarg2);
public final static native byte[] Fp_serialize(long jarg1, Fp jarg1_);
public final static native void delete_Fp(long jarg1);
public final static native void neg__SWIG_2(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_);
public final static native void dbl__SWIG_0(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_);
public final static native void add__SWIG_2(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_, long jarg3, G1 jarg3_);
public final static native void sub__SWIG_2(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_, long jarg3, G1 jarg3_);
public final static native void pairing(long jarg1, GT jarg1_, long jarg2, G1 jarg2_, long jarg3, G2 jarg3_);
public final static native void hashAndMapToG1(long jarg1, G1 jarg1_, byte[] jarg2);
public final static native long new_G1__SWIG_0();
public final static native long new_G1__SWIG_1(long jarg1, G1 jarg1_);
public final static native long new_G1__SWIG_2(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_);
public final static native boolean G1_equals(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_);
public final static native boolean G1_isZero(long jarg1, G1 jarg1_);
public final static native boolean G1_isValidOrder(long jarg1, G1 jarg1_);
public final static native void G1_set(long jarg1, G1 jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native void G1_clear(long jarg1, G1 jarg1_);
public final static native void G1_setStr__SWIG_0(long jarg1, G1 jarg1_, String jarg2, int jarg3);
public final static native void G1_setStr__SWIG_1(long jarg1, G1 jarg1_, String jarg2);
public final static native String G1_toString__SWIG_0(long jarg1, G1 jarg1_, int jarg2);
public final static native String G1_toString__SWIG_1(long jarg1, G1 jarg1_);
public final static native void G1_deserialize(long jarg1, G1 jarg1_, byte[] jarg2);
public final static native byte[] G1_serialize(long jarg1, G1 jarg1_);
public final static native void delete_G1(long jarg1);
public final static native void neg__SWIG_3(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_);
public final static native void dbl__SWIG_1(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_);
public final static native void add__SWIG_3(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_, long jarg3, G2 jarg3_);
public final static native void sub__SWIG_3(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_, long jarg3, G2 jarg3_);
public final static native void hashAndMapToG2(long jarg1, G2 jarg1_, byte[] jarg2);
public final static native long new_G2__SWIG_0();
public final static native long new_G2__SWIG_1(long jarg1, G2 jarg1_);
public final static native long new_G2__SWIG_2(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_, long jarg4, Fp jarg4_);
public final static native boolean G2_equals(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_);
public final static native boolean G2_isZero(long jarg1, G2 jarg1_);
public final static native void G2_set(long jarg1, G2 jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_, long jarg4, Fp jarg4_, long jarg5, Fp jarg5_);
public final static native void G2_clear(long jarg1, G2 jarg1_);
public final static native void G2_setStr__SWIG_0(long jarg1, G2 jarg1_, String jarg2, int jarg3);
public final static native void G2_setStr__SWIG_1(long jarg1, G2 jarg1_, String jarg2);
public final static native String G2_toString__SWIG_0(long jarg1, G2 jarg1_, int jarg2);
public final static native String G2_toString__SWIG_1(long jarg1, G2 jarg1_);
public final static native void G2_deserialize(long jarg1, G2 jarg1_, byte[] jarg2);
public final static native byte[] G2_serialize(long jarg1, G2 jarg1_);
public final static native void delete_G2(long jarg1);
public final static native void mul__SWIG_4(long jarg1, GT jarg1_, long jarg2, GT jarg2_, long jarg3, GT jarg3_);
public final static native void inv__SWIG_2(long jarg1, GT jarg1_, long jarg2, GT jarg2_);
public final static native long new_GT__SWIG_0();
public final static native long new_GT__SWIG_1(long jarg1, GT jarg1_);
public final static native boolean GT_equals(long jarg1, GT jarg1_, long jarg2, GT jarg2_);
public final static native boolean GT_isOne(long jarg1, GT jarg1_);
public final static native void GT_clear(long jarg1, GT jarg1_);
public final static native void GT_setStr__SWIG_0(long jarg1, GT jarg1_, String jarg2, int jarg3);
public final static native void GT_setStr__SWIG_1(long jarg1, GT jarg1_, String jarg2);
public final static native String GT_toString__SWIG_0(long jarg1, GT jarg1_, int jarg2);
public final static native String GT_toString__SWIG_1(long jarg1, GT jarg1_);
public final static native void GT_deserialize(long jarg1, GT jarg1_, byte[] jarg2);
public final static native byte[] GT_serialize(long jarg1, GT jarg1_);
public final static native void delete_GT(long jarg1);
}

@ -0,0 +1,87 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class PrivateKey {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected PrivateKey(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(PrivateKey obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
ElgamalJNI.delete_PrivateKey(swigCPtr);
}
swigCPtr = 0;
}
}
public String toStr() {
return ElgamalJNI.PrivateKey_toStr(swigCPtr, this);
}
public String toString() {
return ElgamalJNI.PrivateKey_toString(swigCPtr, this);
}
public void fromStr(String str) {
ElgamalJNI.PrivateKey_fromStr(swigCPtr, this, str);
}
public void save(String fileName) {
ElgamalJNI.PrivateKey_save(swigCPtr, this, fileName);
}
public void load(String fileName) {
ElgamalJNI.PrivateKey_load(swigCPtr, this, fileName);
}
public void init() {
ElgamalJNI.PrivateKey_init(swigCPtr, this);
}
public PublicKey getPublicKey() {
return new PublicKey(ElgamalJNI.PrivateKey_getPublicKey(swigCPtr, this), true);
}
public int dec(CipherText c, SWIGTYPE_p_bool b) {
return ElgamalJNI.PrivateKey_dec__SWIG_0(swigCPtr, this, CipherText.getCPtr(c), c, SWIGTYPE_p_bool.getCPtr(b));
}
public int dec(CipherText c) {
return ElgamalJNI.PrivateKey_dec__SWIG_1(swigCPtr, this, CipherText.getCPtr(c), c);
}
public void setCache(int rangeMin, int rangeMax) {
ElgamalJNI.PrivateKey_setCache(swigCPtr, this, rangeMin, rangeMax);
}
public void clearCache() {
ElgamalJNI.PrivateKey_clearCache(swigCPtr, this);
}
public PrivateKey() {
this(ElgamalJNI.new_PrivateKey(), true);
}
}

@ -0,0 +1,83 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class PublicKey {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected PublicKey(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(PublicKey obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
ElgamalJNI.delete_PublicKey(swigCPtr);
}
swigCPtr = 0;
}
}
public String toStr() {
return ElgamalJNI.PublicKey_toStr(swigCPtr, this);
}
public String toString() {
return ElgamalJNI.PublicKey_toString(swigCPtr, this);
}
public void fromStr(String str) {
ElgamalJNI.PublicKey_fromStr(swigCPtr, this, str);
}
public void save(String fileName) {
ElgamalJNI.PublicKey_save(swigCPtr, this, fileName);
}
public void load(String fileName) {
ElgamalJNI.PublicKey_load(swigCPtr, this, fileName);
}
public void enc(CipherText c, int m) {
ElgamalJNI.PublicKey_enc__SWIG_0(swigCPtr, this, CipherText.getCPtr(c), c, m);
}
public void enc(CipherText c, String str) {
ElgamalJNI.PublicKey_enc__SWIG_1(swigCPtr, this, CipherText.getCPtr(c), c, str);
}
public void rerandomize(CipherText c) {
ElgamalJNI.PublicKey_rerandomize(swigCPtr, this, CipherText.getCPtr(c), c);
}
public void add(CipherText c, int m) {
ElgamalJNI.PublicKey_add__SWIG_0(swigCPtr, this, CipherText.getCPtr(c), c, m);
}
public void add(CipherText c, String str) {
ElgamalJNI.PublicKey_add__SWIG_1(swigCPtr, this, CipherText.getCPtr(c), c, str);
}
public PublicKey() {
this(ElgamalJNI.new_PublicKey(), true);
}
}

@ -0,0 +1,26 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class SWIGTYPE_p_bool {
private transient long swigCPtr;
protected SWIGTYPE_p_bool(long cPtr, @SuppressWarnings("unused") boolean futureUse) {
swigCPtr = cPtr;
}
protected SWIGTYPE_p_bool() {
swigCPtr = 0;
}
protected static long getCPtr(SWIGTYPE_p_bool obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
}

@ -13,6 +13,11 @@ typedef mcl::FpT<mcl::ZnTag, 521> Zn;
typedef mcl::EcT<Fp> Ec;
typedef mcl::ElgamalT<Ec, Zn> Elgamal;
#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
#endif
/*
init system
@param param [in] string such as "ecParamName hashName"
@ -29,12 +34,12 @@ void SystemInit(const std::string& param) throw(std::exception)
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);
if (p.ecParam) {
mcl::initCurve<Ec, Zn>(p.ecParam->curveType);
p.hashName = cybozu::crypto::Hash::getName(hashNameStr);
return;
}
}
throw cybozu::Exception("SystemInit:bad param") << param;
}
@ -145,3 +150,7 @@ public:
self_.clearCache();
}
};
#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 3.0.12
* Version 4.0.2
*
* 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
@ -190,7 +190,8 @@ typedef enum {
SWIG_JavaIllegalArgumentException,
SWIG_JavaNullPointerException,
SWIG_JavaDirectorPureVirtual,
SWIG_JavaUnknownError
SWIG_JavaUnknownError,
SWIG_JavaIllegalStateException,
} SWIG_JavaExceptionCodes;
typedef struct {
@ -211,6 +212,7 @@ static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionC
{ SWIG_JavaNullPointerException, "java/lang/NullPointerException" },
{ SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" },
{ SWIG_JavaUnknownError, "java/lang/UnknownError" },
{ SWIG_JavaIllegalStateException, "java/lang/IllegalStateException" },
{ (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" }
};
const SWIG_JavaExceptions_t *except_ptr = java_exceptions;
@ -358,12 +360,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_SystemInit(JNIEnv *jenv,
jenv->ReleaseStringUTFChars(jarg1, arg1_pstr);
try {
SystemInit((std::string const &)*arg1);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -378,12 +378,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toStr(JNIE
arg1 = *(CipherText **)&jarg1;
try {
result = ((CipherText const *)arg1)->toStr();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -400,12 +398,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toString(J
arg1 = *(CipherText **)&jarg1;
try {
result = ((CipherText const *)arg1)->toString();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -430,12 +426,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1fromStr(JNIEn
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->fromStr((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -455,12 +449,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1add(JNIEnv *j
}
try {
(arg1)->add((CipherText const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -475,12 +467,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_1
arg2 = (int)jarg2;
try {
(arg1)->mul(arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -503,12 +493,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_1
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->mul((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -545,12 +533,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toStr(JNIEn
arg1 = *(PublicKey **)&jarg1;
try {
result = ((PublicKey const *)arg1)->toStr();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -567,12 +553,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toString(JN
arg1 = *(PublicKey **)&jarg1;
try {
result = ((PublicKey const *)arg1)->toString();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -597,12 +581,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1fromStr(JNIEnv
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->fromStr((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -625,12 +607,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1save(JNIEnv *j
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
((PublicKey const *)arg1)->save((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -653,12 +633,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1load(JNIEnv *j
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->load((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -680,12 +658,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_10
arg3 = (int)jarg3;
try {
((PublicKey const *)arg1)->enc(*arg2,arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -715,12 +691,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_11
jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
try {
((PublicKey const *)arg1)->enc(*arg2,(std::string const &)*arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -740,12 +714,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1rerandomize(JN
}
try {
((PublicKey const *)arg1)->rerandomize(*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -767,12 +739,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_10
arg3 = (int)jarg3;
try {
((PublicKey const *)arg1)->add(*arg2,arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -802,12 +772,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_11
jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
try {
((PublicKey const *)arg1)->add(*arg2,(std::string const &)*arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -844,12 +812,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toStr(JNIE
arg1 = *(PrivateKey **)&jarg1;
try {
result = ((PrivateKey const *)arg1)->toStr();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -866,12 +832,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toString(J
arg1 = *(PrivateKey **)&jarg1;
try {
result = ((PrivateKey const *)arg1)->toString();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -896,12 +860,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1fromStr(JNIEn
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->fromStr((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -924,12 +886,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1save(JNIEnv *
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
((PrivateKey const *)arg1)->save((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -952,12 +912,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1load(JNIEnv *
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->load((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -970,12 +928,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1init(JNIEnv *
arg1 = *(PrivateKey **)&jarg1;
try {
(arg1)->init();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -990,12 +946,10 @@ SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1getPublicKey
arg1 = *(PrivateKey **)&jarg1;
try {
result = ((PrivateKey const *)arg1)->getPublicKey();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
*(PublicKey **)&jresult = new PublicKey((const PublicKey &)result);
return jresult;
}
@ -1021,12 +975,10 @@ SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_1
arg3 = *(bool **)&jarg3;
try {
result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2,arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = (jint)result;
return jresult;
}
@ -1050,12 +1002,10 @@ SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_1
}
try {
result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = (jint)result;
return jresult;
}
@ -1074,12 +1024,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1setCache(JNIE
arg3 = (int)jarg3;
try {
(arg1)->setCache(arg2,arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -1092,12 +1040,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1clearCache(JN
arg1 = *(PrivateKey **)&jarg1;
try {
(arg1)->clearCache();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}

@ -1,13 +1,14 @@
# JNI for mcl (experimental)
This library provides functionality to compute the optimal ate pairing
over Barreto-Naehrig (BN) curves.
over Barreto-Naehrig (BN) or BLS12-381 curves.
# Initialization
Load the library `mcl_bn256`.
Load the library `mcljava`.
```
import com.herumi.mcl.*;
System.loadLibrary("mcl_bn256");
System.loadLibrary(System.mapLibraryName("mcljava"));
Mcl.SystemInit(curveType); // curveType = Mcl.BN254 or Mcl.BLS12_381
```
# Classes
@ -21,75 +22,67 @@ System.loadLibrary("mcl_bn256");
## 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`
* `Fr::setByCSPRNG()` ; randomly set
* `Mcl.neg(Fr y, Fr x)` ; `y = -x`
* `Mcl.add(Fr z, Fr x, Fr y)` ; `z = x + y`
* `Mcl.sub(Fr z, Fr x, Fr y)` ; `z = x - y`
* `Mcl.mul(Fr z, Fr x, Fr y)` ; `z = x * y`
* `Mcl.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`
* `Mcl.neg(G1 y, G1 x)` ; `y = -x`
* `Mcl.dbl(G1 y, G1 x)` ; `y = 2x`
* `Mcl.add(G1 z, G1 x, G1 y)` ; `z = x + y`
* `Mcl.sub(G1 z, G1 x, G1 y)` ; `z = x - y`
* `Mcl.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`
* `Mcl.neg(G2 y, G2 x)` ; `y = -x`
* `Mcl.dbl(G2 y, G2 x)` ; `y = 2x`
* `Mcl.add(G2 z, G2 x, G2 y)` ; `z = x + y`
* `Mcl.sub(G2 z, G2 x, G2 y)` ; `z = x - y`
* `Mcl.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`
* `Mcl.mul(GT z, GT x, GT y)` ; `z = x * y`
* `Mcl.pow(GT z, GT x, Fr y)` ; `z = x ^ y`
* `Mcl.inv(GT y, GT x)` ; `y = x^{-1}`
## pairing
* `Bn256.pairing(GT e, G1 P, G2 Q)` ; e = e(P, Q)
* `Mcl.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
G2 Q = new G2();
Mcl.hashAndMapToG2(Q, "abc".getBytes());
Fr s = new Fr();
s.setRand(); // secret key
s.setByCSPRNG(); // secret key
G2 pub = new G2();
Bn256.mul(pub, Q, s); // public key = sQ
Mcl.mul(pub, Q, s); // public key = sQ
String m = "signature test";
G1 H = new G1();
H.hashAndMapToG1(m); // H = Hash(m)
Mcl.hashAndMapToG1(H, m.getBytes()); // H = Hash(m)
G1 sign = new G1();
Bn256.mul(sign, H, s); // signature of m = s H
Mcl.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);
Mcl.pairing(e1, H, pub); // e1 = e(H, s Q)
Mcl.pairing(e2, sign, Q); // e2 = e(s H, Q);
assertBool("verify signature", e1.equals(e2));
```
# Make test
```
cd java
make test_bn256
cd ffi/java
make test
```
# Sample code
[Bn256Test.java](https://github.com/herumi/mcl/blob/master/java/Bn256Test.java)
[MclTest.java](https://github.com/herumi/mcl/blob/master/ffi/java/MclTest.java)

@ -5,9 +5,11 @@ set SWIG=..\..\..\..\p\swig\swig.exe
set PACKAGE_NAME=com.herumi.mcl
set PACKAGE_DIR=%PACKAGE_NAME:.=\%
if /i "%1"=="" (
set NAME=elgamal
set NAME=mcl
set LIBNAME=
) else (
set NAME=%1
set LIBNAME=%NAME%
)
echo [[run swig]]
@ -15,7 +17,7 @@ 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
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%LIBNAME%java.dll
call run-%NAME%.bat

@ -0,0 +1,29 @@
%module Mcl
%include "std_string.i"
%include "std_except.i"
%apply(char *STRING, size_t LENGTH) { (const char *cbuf, size_t bufSize) };
%{
#include <mcl/bls12_381.hpp>
#include "mcl_impl.hpp"
%}
%typemap(jtype) void serialize "byte[]"
%typemap(jstype) void serialize "byte[]"
%typemap(jni) void serialize "jbyteArray"
%typemap(javaout) void serialize { return $jnicall; }
%typemap(in, numinputs=0) std::string& out (std::string buf) "$1=&buf;"
%typemap(argout) std::string& out {
$result = JCALL1(NewByteArray, jenv, $1->size());
JCALL4(SetByteArrayRegion, jenv, $result, 0, $1->size(), (const jbyte*)$1->c_str());
}
%include "mcl_impl.hpp"
%javaconst(1);
#define BN254 0
#define BLS12_381 5

@ -0,0 +1,436 @@
#include <mcl/bls12_381.hpp>
#include <stdint.h>
#include <sstream>
#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
#endif
void SystemInit(int curveType) throw(std::exception)
{
mcl::CurveParam cp;
switch (curveType) {
case MCL_BN254: cp = mcl::BN254; break;
case MCL_BN_SNARK1: cp = mcl::BN_SNARK1; break;
case MCL_BLS12_381: cp = mcl::BLS12_381; break;
default:
throw std::runtime_error("bad curveType");
}
mcl::bn::initPairing(cp);
}
template<class T>
void deserializeT(T& x, const char *cbuf, size_t bufSize)
{
if (x.deserialize(cbuf, bufSize) == 0) {
throw std::runtime_error("deserialize");
}
}
template<class T>
void setLittleEndianModT(T& x, const char *cbuf, size_t bufSize)
{
x.setLittleEndianMod(cbuf, bufSize);
}
template<class T>
void setHashOfT(T& x, const char *cbuf, size_t bufSize)
{
x.setHashOf(cbuf, bufSize);
}
template<class T>
void serializeT(std::string& out, const T& x)
{
out.resize(48 * 12);
size_t n = x.serialize(&out[0], out.size());
if (n == 0) throw std::runtime_error("serializeT");
out.resize(n);
}
class G1;
class G2;
class GT;
/*
Fr = Z / rZ
*/
class Fr {
mcl::bn::Fr self_;
friend class G1;
friend class G2;
friend class GT;
friend void neg(Fr& y, const Fr& x);
friend void inv(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, int base = 0) throw(std::exception)
: self_(str, base) {}
bool equals(const Fr& rhs) const { return self_ == rhs.self_; }
bool isZero() const { return self_.isZero(); }
bool isOne() const { return self_.isOne(); }
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
void setInt(int x)
{
self_ = x;
}
void clear()
{
self_.clear();
}
void setByCSPRNG()
{
self_.setByCSPRNG();
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void setLittleEndianMod(const char *cbuf, size_t bufSize) throw(std::exception)
{
setLittleEndianModT(self_, cbuf, bufSize);
}
void setHashOf(const char *cbuf, size_t bufSize) throw(std::exception)
{
setHashOfT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void neg(Fr& y, const Fr& x)
{
mcl::bn::Fr::neg(y.self_, x.self_);
}
void inv(Fr& y, const Fr& x)
{
mcl::bn::Fr::inv(y.self_, x.self_);
}
void add(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn::Fr::add(z.self_, x.self_, y.self_);
}
void sub(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn::Fr::sub(z.self_, x.self_, y.self_);
}
void mul(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn::Fr::mul(z.self_, x.self_, y.self_);
}
void div(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn::Fr::div(z.self_, x.self_, y.self_);
}
class Fp {
mcl::bn::Fp self_;
friend class G1;
friend class G2;
friend class GT;
friend void neg(Fp& y, const Fp& x);
friend void inv(Fp& y, const Fp& x);
friend void add(Fp& z, const Fp& x, const Fp& y);
friend void sub(Fp& z, const Fp& x, const Fp& y);
friend void mul(Fp& z, const Fp& x, const Fp& y);
friend void div(Fp& z, const Fp& x, const Fp& y);
public:
Fp() {}
Fp(const Fp& rhs) : self_(rhs.self_) {}
Fp(int x) : self_(x) {}
Fp(const std::string& str, int base = 0) throw(std::exception)
: self_(str, base) {}
bool equals(const Fp& rhs) const { return self_ == rhs.self_; }
bool isZero() const { return self_.isZero(); }
bool isOne() const { return self_.isOne(); }
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
void setInt(int x)
{
self_ = x;
}
void clear()
{
self_.clear();
}
void setByCSPRNG()
{
self_.setByCSPRNG();
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void neg(Fp& y, const Fp& x)
{
mcl::bn::Fp::neg(y.self_, x.self_);
}
void inv(Fp& y, const Fp& x)
{
mcl::bn::Fp::inv(y.self_, x.self_);
}
void add(Fp& z, const Fp& x, const Fp& y)
{
mcl::bn::Fp::add(z.self_, x.self_, y.self_);
}
void sub(Fp& z, const Fp& x, const Fp& y)
{
mcl::bn::Fp::sub(z.self_, x.self_, y.self_);
}
void mul(Fp& z, const Fp& x, const Fp& y)
{
mcl::bn::Fp::mul(z.self_, x.self_, y.self_);
}
void div(Fp& z, const Fp& x, const Fp& y)
{
mcl::bn::Fp::div(z.self_, x.self_, y.self_);
}
/*
#G1 = r
*/
class G1 {
mcl::bn::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);
friend void hashAndMapToG1(G1& P, const char *cbuf, size_t bufSize) throw(std::exception);
public:
G1() {}
G1(const G1& rhs) : self_(rhs.self_) {}
G1(const Fp& x, const Fp& y) throw(std::exception)
: self_(x.self_, y.self_) { }
bool equals(const G1& rhs) const { return self_ == rhs.self_; }
bool isZero() const { return self_.isZero(); }
bool isValidOrder() const { return self_.isValidOrder(); }
void set(const Fp& x, const Fp& y) throw(std::exception)
{
self_.set(x.self_, y.self_);
}
void clear()
{
self_.clear();
}
/*
compressed format
*/
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void neg(G1& y, const G1& x)
{
mcl::bn::G1::neg(y.self_, x.self_);
}
void dbl(G1& y, const G1& x)
{
mcl::bn::G1::dbl(y.self_, x.self_);
}
void add(G1& z, const G1& x, const G1& y)
{
mcl::bn::G1::add(z.self_, x.self_, y.self_);
}
void sub(G1& z, const G1& x, const G1& y)
{
mcl::bn::G1::sub(z.self_, x.self_, y.self_);
}
void mul(G1& z, const G1& x, const Fr& y)
{
mcl::bn::G1::mul(z.self_, x.self_, y.self_);
}
/*
#G2 = r
*/
class G2 {
mcl::bn::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);
friend void hashAndMapToG2(G2& P, const char *cbuf, size_t bufSize) throw(std::exception);
public:
G2() {}
G2(const G2& rhs) : self_(rhs.self_) {}
G2(const Fp& ax, const Fp& ay, const Fp& bx, const Fp& by) throw(std::exception)
: self_(mcl::bn::Fp2(ax.self_, ay.self_), mcl::bn::Fp2(bx.self_, by.self_))
{
}
bool equals(const G2& rhs) const { return self_ == rhs.self_; }
bool isZero() const { return self_.isZero(); }
void set(const Fp& ax, const Fp& ay, const Fp& bx, const Fp& by) throw(std::exception)
{
self_.set(mcl::bn::Fp2(ax.self_, ay.self_), mcl::bn::Fp2(bx.self_, by.self_));
}
void clear()
{
self_.clear();
}
/*
compressed format
*/
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void neg(G2& y, const G2& x)
{
mcl::bn::G2::neg(y.self_, x.self_);
}
void dbl(G2& y, const G2& x)
{
mcl::bn::G2::dbl(y.self_, x.self_);
}
void add(G2& z, const G2& x, const G2& y)
{
mcl::bn::G2::add(z.self_, x.self_, y.self_);
}
void sub(G2& z, const G2& x, const G2& y)
{
mcl::bn::G2::sub(z.self_, x.self_, y.self_);
}
void mul(G2& z, const G2& x, const Fr& y)
{
mcl::bn::G2::mul(z.self_, x.self_, y.self_);
}
/*
#GT = r
*/
class GT {
mcl::bn::Fp12 self_;
friend void mul(GT& z, const GT& x, const GT& y);
friend void inv(GT& y, GT& x);
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_; }
bool isOne() const { return self_.isOne(); }
void clear()
{
self_.clear();
}
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void mul(GT& z, const GT& x, const GT& y)
{
mcl::bn::Fp12::mul(z.self_, x.self_, y.self_);
}
void inv(GT& y, GT& x)
{
mcl::bn::Fp12::unitaryInv(y.self_, x.self_);
}
void pow(GT& z, const GT& x, const Fr& y)
{
mcl::bn::Fp12::pow(z.self_, x.self_, y.self_);
}
void pairing(GT& e, const G1& P, const G2& Q)
{
mcl::bn::pairing(e.self_, P.self_, Q.self_);
}
void hashAndMapToG1(G1& P, const char *cbuf, size_t bufSize) throw(std::exception)
{
mcl::bn::hashAndMapToG1(P.self_, cbuf, bufSize);
}
void hashAndMapToG2(G2& P, const char *cbuf, size_t bufSize) throw(std::exception)
{
mcl::bn::hashAndMapToG2(P.self_, cbuf, bufSize);
}
#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif

File diff suppressed because it is too large Load Diff

@ -1,9 +0,0 @@
@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

@ -0,0 +1,9 @@
@echo off
echo [[compile MclTest.java]]
%JAVA_DIR%\bin\javac MclTest.java
echo [[run MclTest]]
set TOP_DIR=..\..
pushd %TOP_DIR%\bin
%JAVA_DIR%\bin\java -classpath ../ffi/java MclTest %1 %2 %3 %4 %5 %6
popd

@ -0,0 +1,9 @@
include ../../common.mk
SHE384_256_SLIB=libmclshe384_256.$(LIB_SUF)
she_test: ../../lib/$(SHE384_256_SLIB)
cd ../../lib && env LD_LIBRARY_PATH=./ python3 ../ffi/python/she.py
../../lib/$(SHE384_256_SLIB):
make -C ../../ lib/$(SHE384_256_SLIB)

@ -0,0 +1,7 @@
# sample for Python
## SHE
```
make she_test
```

@ -1,6 +1,7 @@
import os
import platform
from ctypes import *
#from ctypes.util import find_library
BN254 = 0
BLS12_381 = 5
@ -34,6 +35,7 @@ def init(curveType=BN254):
libName = 'mclshe384_256.dll'
else:
raise RuntimeError("not support yet", name)
# lib = cdll.LoadLibrary(find_library(libName))
lib = cdll.LoadLibrary(libName)
ret = lib.sheInit(curveType, MCLBN_COMPILED_TIME_VAR)
if ret != 0:

@ -7,7 +7,6 @@
*/
#include <memory.h>
#include <limits.h>
#include <limits>
#include <cybozu/exception.hpp>
@ -173,7 +172,7 @@ public:
}
inline operator int() const
{
return atoi_local::convertToInt<int>(b_, p_, size_, "2147483648", INT_MIN, 214748364, '8');
return atoi_local::convertToInt<int>(b_, p_, size_, "2147483648", /*INT_MIN*/-2147483648, 214748364, '8');
}
inline operator unsigned int() const
{
@ -181,7 +180,7 @@ public:
}
inline operator long long() const
{
return atoi_local::convertToInt<long long>(b_, p_, size_, "9223372036854775808", LLONG_MIN, 922337203685477580LL, '8');
return atoi_local::convertToInt<long long>(b_, p_, size_, "9223372036854775808", CYBOZU_LLONG_MIN, 922337203685477580LL, '8');
}
inline operator unsigned long long() const
{

@ -0,0 +1,146 @@
#pragma once
/**
@file
@brief atomic operation
@author MITSUNARI Shigeo(@herumi)
@author MITSUNARI Shigeo
*/
#include <cybozu/inttype.hpp>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <intrin.h>
#else
#include <emmintrin.h>
#endif
namespace cybozu {
namespace atomic_local {
template<size_t S>
struct Tag {};
template<>
struct Tag<4> {
template<class T>
static inline T AtomicAddSub(T *p, T y)
{
#ifdef _WIN32
return (T)_InterlockedExchangeAdd((long*)p, (long)y);
#else
return static_cast<T>(__sync_fetch_and_add(p, y));
#endif
}
template<class T>
static inline T AtomicCompareExchangeSub(T *p, T newValue, T oldValue)
{
#ifdef _WIN32
return (T)_InterlockedCompareExchange((long*)p, (long)newValue, (long)oldValue);
#else
return static_cast<T>(__sync_val_compare_and_swap(p, oldValue, newValue));
#endif
}
template<class T>
static inline T AtomicExchangeSub(T *p, T newValue)
{
#ifdef _WIN32
return (T)_InterlockedExchange((long*)p, (long)newValue);
#else
return static_cast<T>(__sync_lock_test_and_set(p, newValue));
#endif
}
};
template<>
struct Tag<8> {
#if (CYBOZU_OS_BIT == 64)
template<class T>
static inline T AtomicAddSub(T *p, T y)
{
#ifdef _WIN32
return (T)_InterlockedExchangeAdd64((int64_t*)p, (int64_t)y);
#else
return static_cast<T>(__sync_fetch_and_add(p, y));
#endif
}
#endif
template<class T>
static inline T AtomicCompareExchangeSub(T *p, T newValue, T oldValue)
{
#ifdef _WIN32
return (T)_InterlockedCompareExchange64((int64_t*)p, (int64_t)newValue, (int64_t)oldValue);
#else
return static_cast<T>(__sync_val_compare_and_swap(p, oldValue, newValue));
#endif
}
#if (CYBOZU_OS_BIT == 64)
template<class T>
static inline T AtomicExchangeSub(T *p, T newValue)
{
#ifdef _WIN32
return (T)_InterlockedExchange64((int64_t*)p, (int64_t)newValue);
#else
return static_cast<T>(__sync_lock_test_and_set(p, newValue));
#endif
}
#endif
};
} // atomic_local
/**
atomic operation
see http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Atomic-Builtins.html
http://msdn.microsoft.com/en-us/library/ms683504(VS.85).aspx
*/
/**
tmp = *p;
*p += y;
return tmp;
*/
template<class T>
T AtomicAdd(T *p, T y)
{
return atomic_local::Tag<sizeof(T)>::AtomicAddSub(p, y);
}
/**
tmp = *p;
if (*p == oldValue) *p = newValue;
return tmp;
*/
template<class T>
T AtomicCompareExchange(T *p, T newValue, T oldValue)
{
return atomic_local::Tag<sizeof(T)>::AtomicCompareExchangeSub(p, newValue, oldValue);
}
/**
tmp = *p;
*p = newValue;
return tmp;
*/
template<class T>
T AtomicExchange(T *p, T newValue)
{
return atomic_local::Tag<sizeof(T)>::AtomicExchangeSub(p, newValue);
}
inline void mfence()
{
#ifdef _MSC_VER
MemoryBarrier();
#else
_mm_mfence();
#endif
}
} // cybozu

@ -42,7 +42,9 @@ public:
#include <errno.h>
#include <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <string.h> // for strerror_r
@ -201,7 +203,6 @@ public:
}
/**
convert NativeErrNo to string(maybe UTF8)
@param err [in] errno
@note Linux : same as ConvertErrorNoToString
Windows : for Win32 API(use en-us)
*/

@ -0,0 +1,626 @@
#pragma once
/**
@file
@brief file class and operations
@author MITSUNARI Shigeo(@herumi)
@remark mingw requires -lshlwapi option
*/
#include <assert.h>
#include <sys/stat.h> // for stat
#include <cybozu/exception.hpp>
#include <vector>
#include <ios>
#ifdef _WIN32
#include <shlwapi.h>
#include <io.h>
#include <fcntl.h>
#include <shlobj.h>
#include <direct.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#ifdef _MSC_VER
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "User32.lib")
#endif
#else
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
namespace cybozu {
class File {
std::string name_; // used for only errmsg
#ifdef _WIN32
typedef HANDLE handleType;
#else
typedef int handleType;
enum {
INVALID_HANDLE_VALUE = -1
};
#endif
handleType hdl_;
bool doClose_;
bool isReadOnly_;
File(const File&);
void operator=(const File&);
#ifdef _WIN32
void openSub()
{
}
#endif
void verifyMode(std::ios::openmode mode)
{
doClose_ = true;
bool isCorrectMode = true;
if (!!(mode & std::ios::in) == !!(mode & std::ios::out)) {
isCorrectMode = false;
} else {
if (mode & std::ios::in) {
isReadOnly_ = true;
if ((mode & std::ios::app) || (mode & std::ios::trunc)) isCorrectMode = false;
} else {
isReadOnly_ = false;
if ((mode & std::ios::app) && (mode & std::ios::trunc)) isCorrectMode = false;
}
}
if (!isCorrectMode) {
throw cybozu::Exception("File:open:bad mode") << name_ << mode;
}
}
#ifdef _WIN32
HANDLE createFile(const std::string& name, DWORD access, DWORD share, DWORD disposition)
{
return ::CreateFileA(name.c_str(), access, share, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL);
}
HANDLE createFile(const std::wstring& name, DWORD access, DWORD share, DWORD disposition)
{
return ::CreateFileW(name.c_str(), access, share, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL);
}
template<class T>
void setHandle(const T& name, std::ios::openmode mode)
{
DWORD access = GENERIC_READ;
DWORD disposition = OPEN_EXISTING;
DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
if (mode & std::ios::out) {
access = GENERIC_WRITE;
disposition = CREATE_ALWAYS;
if (mode & std::ios::app) {
disposition = OPEN_ALWAYS;
}
}
hdl_ = createFile(name, access, share, disposition);
}
#else
void setHandle(const std::string& name, std::ios::openmode mode)
{
int flags = O_RDONLY; // | O_NOATIME; /* can't use on NFS */
mode_t access = 0644;
if (mode & std::ios::out) {
flags = O_WRONLY | O_CREAT;
if (mode & std::ios::app) {
flags |= O_APPEND;
} else {
flags |= O_TRUNC;
}
}
hdl_ = ::open(name.c_str(), flags, access);
}
#endif
template<class T>
void openSub(const T& name, std::ios::openmode mode)
{
if (isOpen()) throw cybozu::Exception("File:open:alread opened") << name_;
verifyMode(mode);
setHandle(name, mode);
if (isOpen()) {
if (mode & std::ios::app) {
seek(getSize(), std::ios::beg);
}
return;
}
throw cybozu::Exception("File:open") << name_ << cybozu::ErrorNo() << static_cast<int>(mode);
}
public:
File()
: hdl_(INVALID_HANDLE_VALUE)
, doClose_(true)
, isReadOnly_(false)
{
}
File(const std::string& name, std::ios::openmode mode)
: hdl_(INVALID_HANDLE_VALUE)
, doClose_(true)
, isReadOnly_(false)
{
open(name, mode);
}
/*
construct with file handle
@param hdl [in] file handle
*/
explicit File(handleType hdl)
: hdl_(hdl)
, doClose_(false)
, isReadOnly_(false)
{
}
~File() CYBOZU_NOEXCEPT
{
if (!doClose_) return;
try {
sync();
close();
} catch (std::exception& e) {
fprintf(stderr, "File:dstr:%s\n", e.what());
} catch (...) {
fprintf(stderr, "File:dstr:unknown\n");
}
}
bool isOpen() const CYBOZU_NOEXCEPT { return hdl_ != INVALID_HANDLE_VALUE; }
/**
support mode
always binary mode
ios::in : read only
ios::out : write only(+truncate)
ios::out + ios::app(append)
*/
void open(const std::string& name, std::ios::openmode mode)
{
name_ = name;
openSub(name, mode);
}
void openW(const std::string& name)
{
open(name, std::ios::out | std::ios::binary | std::ios::trunc);
}
void openR(const std::string& name)
{
open(name, std::ios::in | std::ios::binary);
}
#ifdef _WIN32
void open(const std::wstring& name, std::ios::openmode mode)
{
name_ = cybozu::exception::wstr2str(name);
openSub(name, mode);
}
File(const std::wstring& name, std::ios::openmode mode)
: hdl_(INVALID_HANDLE_VALUE)
{
open(name, mode);
}
void openW(const std::wstring& name)
{
open(name, std::ios::out | std::ios::binary | std::ios::trunc);
}
void openR(const std::wstring& name)
{
open(name, std::ios::in | std::ios::binary);
}
#endif
void close()
{
if (!isOpen()) return;
#ifdef _WIN32
bool isOK = ::CloseHandle(hdl_) != 0;
#else
bool isOK = ::close(hdl_) == 0;
#endif
hdl_ = INVALID_HANDLE_VALUE;
if (isOK) return;
throw cybozu::Exception("File:close") << name_ << cybozu::ErrorNo();
}
/*
sync
@param doFullSync [in] call sync(for only Linux)
*/
void sync(bool doFullSync = false)
{
cybozu::disable_warning_unused_variable(doFullSync);
if (!isOpen()) return;
if (isReadOnly_) return;
#ifdef _WIN32
/* fail if isReadOnly_ */
if (!::FlushFileBuffers(hdl_)) goto ERR_EXIT;
#elif defined(__linux__) || defined(__CYGWIN__)
if (doFullSync) {
if (::fsync(hdl_)) goto ERR_EXIT;
} else {
if (::fdatasync(hdl_)) goto ERR_EXIT;
}
#else
if (::fcntl(hdl_, F_FULLFSYNC)) goto ERR_EXIT;
#endif
return;
ERR_EXIT:
throw cybozu::Exception("File:sync") << name_ << cybozu::ErrorNo();
}
void write(const void *buf, size_t bufSize)
{
const char *p = static_cast<const char *>(buf);
while (bufSize > 0) {
uint32_t size = static_cast<uint32_t>(std::min<size_t>(0x7fffffff, bufSize));
#ifdef _WIN32
DWORD writeSize;
if (!::WriteFile(hdl_, p, size, &writeSize, NULL)) goto ERR_EXIT;
#else
ssize_t writeSize = ::write(hdl_, p, size);
if (writeSize < 0) {
if (errno == EINTR) continue;
goto ERR_EXIT;
}
#endif
p += writeSize;
bufSize -= writeSize;
}
return;
ERR_EXIT:
throw cybozu::Exception("File:write") << name_ << cybozu::ErrorNo();
}
size_t readSome(void *buf, size_t bufSize)
{
uint32_t size = static_cast<uint32_t>(std::min<size_t>(0x7fffffff, bufSize));
#ifdef _WIN32
DWORD readSize;
if (!::ReadFile(hdl_, buf, size, &readSize, NULL)) goto ERR_EXIT;
#else
RETRY:
ssize_t readSize = ::read(hdl_, buf, size);
if (readSize < 0) {
if (errno == EINTR) goto RETRY;
goto ERR_EXIT;
}
#endif
return readSize;
ERR_EXIT:
throw cybozu::Exception("File:read") << name_ << cybozu::ErrorNo();
}
void read(void *buf, size_t bufSize)
{
char *p = static_cast<char *>(buf);
while (bufSize > 0) {
size_t readSize = readSome(p, bufSize);
p += readSize;
bufSize -= readSize;
}
}
void seek(int64_t pos, std::ios::seek_dir dir)
{
#ifdef _WIN32
LARGE_INTEGER largePos;
largePos.QuadPart = pos;
DWORD posMode = FILE_BEGIN;
switch (dir) {
case std::ios::beg:
posMode = FILE_BEGIN;
break;
case std::ios::cur:
default:
posMode = FILE_CURRENT;
break;
case std::ios::end:
posMode = FILE_END;
break;
}
bool isOK = SetFilePointerEx(hdl_, largePos, NULL, posMode) != 0;
#else
int whence;
switch (dir) {
case std::ios::beg:
whence = SEEK_SET;
break;
case std::ios::cur:
default:
whence = SEEK_CUR;
break;
case std::ios::end:
whence = SEEK_END;
break;
}
bool isOK = lseek(hdl_, pos, whence) >= 0;
#endif
if (isOK) return;
throw cybozu::Exception("File:seek") << name_ << cybozu::ErrorNo() << pos << static_cast<int>(dir);
}
uint64_t getSize() const
{
uint64_t fileSize;
#ifdef _WIN32
LARGE_INTEGER size;
bool isOK = GetFileSizeEx(hdl_, &size) != 0;
fileSize = size.QuadPart;
#else
struct stat stat;
bool isOK = fstat(hdl_, &stat) == 0;
fileSize = stat.st_size;
#endif
if (isOK) return fileSize;
throw cybozu::Exception("File:getSize") << name_ << cybozu::ErrorNo();
}
};
/*
name has extension
*/
inline bool HasExtension(const std::string& name, const std::string& extension)
{
const size_t extensionSize = extension.size();
if (extensionSize == 0) return true;
const size_t nameSize = name.size();
if (nameSize < extensionSize + 1) return false;
const char *p = &name[nameSize - extensionSize - 1];
return *p == '.' && memcmp(p + 1, &extension[0], extensionSize) == 0;
}
/*
split name as basename.suffix
*/
inline std::string GetBaseName(const std::string& name, std::string *suffix = 0)
{
size_t pos = name.find_last_of('.');
if (pos == std::string::npos) {
if (suffix) suffix->clear();
return name;
}
if (suffix) {
*suffix = name.substr(pos + 1);
}
return name.substr(0, pos);
}
/**
replace \ with /
*/
inline void ReplaceBackSlash(std::string& str)
{
for (size_t i = 0, n = str.size(); i < n; i++) {
if (str[i] == '\\') str[i] = '/';
}
}
/**
get exe path and baseNamme
@note file name is the form "xxx.exe" then baseName = xxx
*/
inline std::string GetExePath(std::string *baseName = 0)
{
std::string path;
path.resize(4096);
#ifdef _WIN32
if (!GetModuleFileNameA(NULL, &path[0], static_cast<int>(path.size()) - 2)) {
return "";
}
PathRemoveExtensionA(&path[0]);
if (baseName) {
*baseName = PathFindFileNameA(&path[0]);
}
if (::PathRemoveFileSpecA(&path[0])) {
::PathAddBackslashA(&path[0]);
path[0] = static_cast<char>(tolower(path[0]));
path.resize(strlen(&path[0]));
ReplaceBackSlash(path);
}
#else
#if defined(__APPLE__)
uint32_t size = (uint32_t)path.size();
if (_NSGetExecutablePath(&path[0], &size) != 0) {
return "";
}
path.resize(strlen(&path[0]));
#else
int ret = readlink("/proc/self/exe", &path[0], path.size() - 2);
if (ret < 0) return "";
path.resize(ret);
#endif
size_t pos = path.find_last_of('/');
if (pos != std::string::npos) {
if (baseName) {
const std::string name = path.substr(pos + 1);
std::string suffix;
std::string base = GetBaseName(name, &suffix);
if (suffix == "exe") {
*baseName = base;
} else {
*baseName = name;
}
}
path.resize(pos + 1);
}
#endif
return path;
}
/**
get file size
*/
inline uint64_t GetFileSize(const std::string& name)
{
#ifdef _WIN32
struct __stat64 buf;
bool isOK = _stat64(name.c_str(), &buf) == 0;
#else
struct stat buf;
bool isOK = stat(name.c_str(), &buf) == 0;
#endif
if (isOK) return buf.st_size;
throw cybozu::Exception("GetFileSize") << name << cybozu::ErrorNo();
}
/**
verify whether path exists or not
*/
inline bool DoesFileExist(const std::string& path)
{
if (path.empty()) return false;
std::string p = path;
char c = p[p.size() - 1];
if (c == '/' || c == '\\') {
p.resize(p.size() - 1);
}
#ifdef _WIN32
struct _stat buf;
return _stat(p.c_str(), &buf) == 0;
#else
struct stat buf;
return stat(p.c_str(), &buf) == 0;
#endif
}
inline void RenameFile(const std::string& from, const std::string& to)
{
if (DoesFileExist(to)) {
throw cybozu::Exception("RenameFile:file already exist") << from << to;
}
#ifdef _WIN32
bool isOK = ::MoveFileExA(from.c_str(), to.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH) != 0;
#else
bool isOK = ::rename(from.c_str(), to.c_str()) == 0;
#endif
if (!isOK) {
throw cybozu::Exception("RenameFile") << from << to << cybozu::ErrorNo();
}
}
/**
remove file
*/
inline void RemoveFile(const std::string& name)
{
#ifdef _WIN32
bool isOK = DeleteFileA(name.c_str()) != 0;
#else
bool isOK = unlink(name.c_str()) == 0;
#endif
if (!isOK) {
throw cybozu::Exception("RemoveFile") << name << cybozu::ErrorNo();
}
}
/*
remark of isFile()
not directory on Windows
not contain symbolic link on Linux
*/
struct FileInfo {
std::string name;
uint32_t attr; // dwFileAttributes for Windows, d_type for Linux
#ifdef _WIN32
bool isUnknown() const { return attr == 0; }
bool isDirectory() const { verify(); return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; }
bool isFile() const { verify(); return !isDirectory(); }
#else
bool isUnknown() const { return attr == DT_UNKNOWN; }
bool isDirectory() const { verify(); return attr == DT_DIR; }
bool isFile() const { verify(); return attr == DT_REG; }
#endif
FileInfo() : attr(0) {}
FileInfo(const std::string& name, uint32_t attr) : name(name), attr(attr) {}
void verify() const
{
if (isUnknown()) throw cybozu::Exception("FileInfo:unknown attr") << name;
}
};
typedef std::vector<FileInfo> FileList;
namespace file_local {
inline void filterAndPush(FileList& list, const FileInfo& fi, const std::string& extension, bool cond(const std::string&, const std::string&))
{
if (fi.name == "." || fi.name == "..") {
return;
}
if (cond(fi.name, extension)) {
list.push_back(fi);
}
}
} // cybozu::file_local
/**
get file name in dir
@param list [out] FileList
@param dir [in] directory
@param extension [in] select files(including directory) having extension such as "cpp" ; select all if suffix is empty
@param cond [in] filter function (select if cond(targetFile, suffix) is true)
@note "." and ".." are excluded
*/
inline bool GetFileList(FileList &list, const std::string& dir, const std::string& extension = "", bool (*cond)(const std::string&, const std::string&) = cybozu::HasExtension)
{
#ifdef _WIN32
std::string path = dir + "/*";
WIN32_FIND_DATAA fd;
struct Handle {
Handle(HANDLE hdl)
: hdl_(hdl)
{
}
~Handle()
{
if (hdl_ != INVALID_HANDLE_VALUE) {
FindClose(hdl_);
}
}
HANDLE hdl_;
};
Handle hdl(FindFirstFileA(path.c_str(), &fd));
if (hdl.hdl_ == INVALID_HANDLE_VALUE) {
return false;
}
do {
FileInfo fi(fd.cFileName, fd.dwFileAttributes);
file_local::filterAndPush(list, fi, extension, cond);
} while (FindNextFileA(hdl.hdl_, &fd) != 0);
return true;
#else
struct Handle {
DIR *dir_;
Handle(DIR *dir)
: dir_(dir)
{
if (dir_ == 0) {
perror("opendir");
}
}
~Handle()
{
if (dir_) {
if (::closedir(dir_)) {
perror("closedir");
}
}
}
bool isValid() const { return dir_ != 0; }
};
Handle hdl(::opendir(dir.c_str()));
if (!hdl.isValid()) return false;
for (;;) {
struct dirent *dp = ::readdir(hdl.dir_);
if (dp == 0) return true;
FileInfo fi(dp->d_name, (uint8_t)dp->d_type);
file_local::filterAndPush(list, fi, extension, cond);
}
#endif
}
inline FileList GetFileList(const std::string& dir, const std::string& extension = "", bool (*cond)(const std::string&, const std::string&) = cybozu::HasExtension)
{
FileList fl;
if (GetFileList(fl, dir, extension, cond)) return fl;
throw cybozu::Exception("cybozu:GetFileList") << dir << cybozu::ErrorNo();
}
} // cybozu

@ -54,7 +54,7 @@ namespace std { CYBOZU_NAMESPACE_TR1_BEGIN
#pragma warning(push)
#pragma warning(disable : 4099) // missmatch class and struct
#endif
#ifndef __APPLE__
#if !(defined(__APPLE__) && defined(__clang__))
template<class T>
struct hash;
#endif

@ -72,6 +72,9 @@
#endif
#endif
// LLONG_MIN in limits.h is not defined in some env.
#define CYBOZU_LLONG_MIN (-9223372036854775807ll-1)
#define CYBOZU_CPP_VERSION_CPP03 0
#define CYBOZU_CPP_VERSION_TR1 1
#define CYBOZU_CPP_VERSION_CPP11 2
@ -88,13 +91,13 @@
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP17
#elif (__cplusplus >= 201402)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP14
#elif (__cplusplus >= 201103) || (_MSC_VER >= 1500) || defined(__GXX_EXPERIMENTAL_CXX0X__)
#elif (__cplusplus >= 201103) || (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__GXX_EXPERIMENTAL_CXX0X__)
#if defined(_MSC_VER) && (_MSC_VER <= 1600)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1
#else
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP11
#endif
#elif CYBOZU_GNUC_PREREQ(4, 5) || (CYBOZU_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || (__clang_major__ >= 3)
#elif CYBOZU_GNUC_PREREQ(4, 5) || (CYBOZU_GNUC_PREREQ(4, 2) && (defined(__GLIBCXX__) &&__GLIBCXX__ >= 20070719)) || defined(__INTEL_COMPILER) || (__clang_major__ >= 3)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1
#else
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP03
@ -150,8 +153,10 @@
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
#define CYBOZU_NOEXCEPT noexcept
#define CYBOZU_NULLPTR nullptr
#else
#define CYBOZU_NOEXCEPT throw()
#define CYBOZU_NULLPTR 0
#endif
namespace cybozu {
template<class T>

@ -5,7 +5,6 @@
@author MITSUNARI Shigeo(@herumi)
*/
#include <limits.h>
#ifndef CYBOZU_DONT_USE_STRING
#include <string>
#endif
@ -122,7 +121,7 @@ size_t uintToBin(char *buf, size_t bufSize, UT x)
template<class T>
size_t intToDec(char *buf, size_t bufSize, T x)
{
if (x == LLONG_MIN) {
if (x == CYBOZU_LLONG_MIN) {
const char minStr[] = "-9223372036854775808";
const size_t minStrLen = sizeof(minStr) - 1;
if (bufSize < minStrLen) {

@ -8,6 +8,9 @@
*/
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <pthread.h>

@ -145,7 +145,7 @@ bool convertInt(T* x, const char *str)
if (factor > 1) {
if ((std::numeric_limits<T>::min)() / factor <= y
&& y <= (std::numeric_limits<T>::max)() / factor) {
*x = y * factor;
*x = static_cast<T>(y * factor);
} else {
return false;
}
@ -155,9 +155,29 @@ bool convertInt(T* x, const char *str)
return true;
}
template<class T>
void convertToStr(std::ostream& os, const T* p)
{
os << *p;
}
template<>inline void convertToStr(std::ostream& os, const int8_t* p)
{
os << static_cast<int>(*p);
}
template<>inline void convertToStr(std::ostream& os, const uint8_t* p)
{
os << static_cast<int>(*p);
}
#define CYBOZU_OPTION_DEFINE_CONVERT_INT(type) \
template<>inline bool convert(type* x, const char *str) { return convertInt(x, str); }
CYBOZU_OPTION_DEFINE_CONVERT_INT(int8_t)
CYBOZU_OPTION_DEFINE_CONVERT_INT(uint8_t)
CYBOZU_OPTION_DEFINE_CONVERT_INT(int16_t)
CYBOZU_OPTION_DEFINE_CONVERT_INT(uint16_t)
CYBOZU_OPTION_DEFINE_CONVERT_INT(int)
CYBOZU_OPTION_DEFINE_CONVERT_INT(long)
CYBOZU_OPTION_DEFINE_CONVERT_INT(long long)
@ -185,7 +205,7 @@ struct Holder : public HolderBase {
std::string toStr() const
{
std::ostringstream os;
os << *p_;
convertToStr(os, p_);
return os.str();
}
const void *get() const { return (void*)p_; }
@ -345,7 +365,7 @@ class Option {
template<class T, class U>
void append(T *pvar, const U& defaultVal, bool isMust, const char *opt, const std::string& help = "")
{
*pvar = defaultVal;
*pvar = static_cast<const T&>(defaultVal);
appendSub(pvar, N_is1, isMust, opt, help);
}
/*

@ -11,13 +11,14 @@
#include <cybozu/exception.hpp>
#endif
#ifdef _WIN32
#include <winsock2.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <wincrypt.h>
#ifdef _MSC_VER
#pragma comment (lib, "advapi32.lib")
#endif
#include <cybozu/critical_section.hpp>
#else
#include <sys/types.h>
#include <fcntl.h>
@ -32,10 +33,9 @@ public:
#ifdef _WIN32
RandomGenerator()
: prov_(0)
, pos_(bufSize)
{
DWORD flagTbl[] = { 0, CRYPT_NEWKEYSET };
for (int i = 0; i < 2; i++) {
DWORD flagTbl[] = { CRYPT_VERIFYCONTEXT | CRYPT_SILENT, 0, CRYPT_MACHINE_KEYSET };
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(flagTbl); i++) {
if (CryptAcquireContext(&prov_, NULL, NULL, PROV_RSA_FULL, flagTbl[i]) != 0) return;
}
#ifdef CYBOZU_DONT_USE_EXCEPTION
@ -62,29 +62,11 @@ public:
template<class T>
void read(bool *pb, T *buf, size_t bufNum)
{
cybozu::AutoLockCs al(cs_);
const size_t byteSize = sizeof(T) * bufNum;
if (byteSize > bufSize) {
if (!read_inner(buf, byteSize)) {
*pb = false;
return;
}
} else {
if (pos_ + byteSize > bufSize) {
read_inner(buf_, bufSize);
pos_ = 0;
}
memcpy(buf, buf_ + pos_, byteSize);
pos_ += byteSize;
}
*pb = true;
*pb = read_inner(buf, byteSize);
}
private:
HCRYPTPROV prov_;
static const size_t bufSize = 1024;
char buf_[bufSize];
size_t pos_;
cybozu::CriticalSection cs_;
#else
RandomGenerator()
: fp_(::fopen("/dev/urandom", "rb"))

@ -13,6 +13,7 @@
#ifndef CYBOZU_DONT_USE_STRING
#include <string>
#endif
#include <memory.h>
#ifdef CYBOZU_USE_OPENSSL_SHA
#ifdef __APPLE__
@ -468,3 +469,61 @@ public:
} // cybozu
#endif
namespace cybozu {
namespace sha2_local {
inline void hmac256_inner(void *hmac, const void *key, size_t keySize, const void *msg, size_t msgSize, bool addZeroByte)
{
const uint8_t ipad = 0x36;
const uint8_t opad = 0x5c;
uint8_t k[64];
Sha256 hash;
if (keySize > 64) {
hash.digest(k, 32, key, keySize);
hash.clear();
keySize = 32;
} else {
memcpy(k, key, keySize);
}
for (size_t i = 0; i < keySize; i++) {
k[i] = k[i] ^ ipad;
}
memset(k + keySize, ipad, 64 - keySize);
hash.update(k, 64);
if (addZeroByte) {
hash.update(msg, msgSize);
const char zero = '\x00';
hash.digest(hmac, 32, &zero, 1);
} else {
hash.digest(hmac, 32, msg, msgSize);
}
hash.clear();
for (size_t i = 0; i < 64; i++) {
k[i] = k[i] ^ (ipad ^ opad);
}
hash.update(k, 64);
hash.digest(hmac, 32, hmac, 32);
}
} // cybozu::sha2_local
/*
HMAC-SHA-256
hmac must have 32 bytes buffer
*/
inline void hmac256(void *hmac, const void *key, size_t keySize, const void *msg, size_t msgSize)
{
sha2_local::hmac256_inner(hmac, key, keySize, msg, msgSize, false);
}
/*
hmac256 for [msg] + [\x00]
*/
inline void hmac256addZeroByte(void *hmac, const void *key, size_t keySize, const void *msg, size_t msgSize)
{
sha2_local::hmac256_inner(hmac, key, keySize, msg, msgSize, true);
}
} // cybozu

@ -0,0 +1,785 @@
#pragma once
/**
@file
@brief tiny socket class
@author MITSUNARI Shigeo(@herumi)
@author MITSUNARI Shigeo
@remark mingw requires -lws2_32 option
*/
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h> // for socklen_t
#ifdef _MSC_VER
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")
#pragma warning(push)
#pragma warning(disable : 4127) // constant condition
#endif
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <memory.h>
#include <signal.h>
#endif
#ifndef NDEBUG
#include <stdio.h>
#endif
#include <cybozu/atomic.hpp>
#include <cybozu/exception.hpp>
#include <cybozu/itoa.hpp>
#include <string>
#ifdef __linux__
// #define CYBOZU_SOCKET_USE_EPOLL
#include <sys/epoll.h>
#endif
namespace cybozu {
#ifdef _MSC_VER
struct NetErrorNo : public cybozu::ErrorNo {
NetErrorNo(NativeErrorNo err)
: cybozu::ErrorNo(err)
{
}
NetErrorNo()
: cybozu::ErrorNo(WSAGetLastError())
{
}
};
#else
typedef cybozu::ErrorNo NetErrorNo;
#endif
#ifdef CYBOZU_SOCKET_USE_EPOLL
namespace experimental {
struct EpollEvent {
struct epoll_event ev_;
EpollEvent()
{
memset(&ev_, 0, sizeof(ev_));
}
void set(int fd, uint32_t events = EPOLLIN)
{
ev_.events = events;
ev_.data.fd = fd;
}
int getFd() const { return ev_.data.fd; }
};
class Epoll {
int efd_;
bool verify(const char *msg, int ret, int *err) const {
if (ret >= 0) return true;
if (err == 0) throw cybozu::Exception(msg) << cybozu::NetErrorNo();
*err = errno;
return false;
}
public:
Epoll() : efd_(-1) {}
bool init(int *err = 0)
{
efd_ = ::epoll_create1(0);
return verify("Epoll:init", efd_, err);
}
~Epoll()
{
if (efd_ >= 0) ::close(efd_);
}
/*
throw if err == NULL
*/
bool ctrl(int op, int fd, EpollEvent *ev, int *err = 0) {
int ret = ::epoll_ctl(efd_, op, fd, &ev->ev_);
return verify("Epoll:ctrl", ret, err);
}
bool add(int fd, uint32_t events = EPOLLIN, int *err = 0) {
EpollEvent ev;
ev.set(fd, events);
return ctrl(EPOLL_CTL_ADD, fd, &ev, err);
}
bool del(int fd, int *err = 0) {
return ctrl(EPOLL_CTL_DEL, fd, NULL, err);
}
/*
msec : 0 : block
*/
int wait(EpollEvent *ev, int maxEv, int msec = 0)
{
/*
0 : return immediately
-1 : block indefinitely
*/
if (msec == 0) {
msec = -1;
} else if (msec == -1) {
msec = 0;
}
int ret = ::epoll_wait(efd_, &ev->ev_, maxEv, msec);
if (ret == 0) return 0; // timeout
if (ret < 0) return -errno;
return ret;
}
};
struct AutoLock {
Epoll& ep_;
int fd_;
AutoLock(Epoll& ep, int fd, int events = EPOLLIN)
: ep_(ep)
, fd_(fd)
{
ep_.add(fd, events);
}
~AutoLock()
{
int err;
ep_.del(fd_, &err);
}
};
} // cybozu::experimental
#endif
namespace ssl {
class ClientSocket;
};
namespace socket_local {
#ifdef _WIN32
typedef SOCKET SocketHandle;
#else
typedef int SocketHandle;
#endif
struct InitTerm {
/** call once for init */
InitTerm()
{
#ifdef _WIN32
WSADATA data;
int err = ::WSAStartup(MAKEWORD(2, 2), &data);
if (err) {
fprintf(stderr, "WSAStartup failed : %d\n", err);
exit(1);
}
#else
::signal(SIGPIPE, SIG_IGN);
#endif
}
/** call once for term */
~InitTerm()
{
#ifdef _WIN32
::WSACleanup();
#endif
}
void dummyCall() { }
};
template<int dummy = 0>
struct InstanceIsHere { static InitTerm it_; };
template<int dummy>
InitTerm InstanceIsHere<dummy>::it_;
struct DummyCall {
DummyCall() { InstanceIsHere<>::it_.dummyCall(); }
};
} // cybozu::socket_local
class SocketAddr {
union {
// http://www.coins.tsukuba.ac.jp/~syspro/2010/No6_files/sockaddr.html
struct sockaddr sa; /* 16byte */
struct sockaddr_in v4; /* 16byte */
struct sockaddr_in6 v6;
} addr_;
socklen_t addrlen_;
int family_;
friend class Socket;
void verify() // call in only Socket::accept
{
if (addrlen_ == sizeof(addr_.v4) && addr_.sa.sa_family == AF_INET) {
family_ = AF_INET;
return;
}
if (addrlen_ == sizeof(addr_.v6) && addr_.sa.sa_family == AF_INET6) {
family_ = AF_INET6;
return;
}
throw cybozu::Exception("cybozu:SocketAddr:verify") << addrlen_;
}
public:
SocketAddr()
: addrlen_(0)
, family_(0)
{
}
SocketAddr(const std::string& address, uint16_t port, bool forceIpV6 = false)
{
set(address, port, forceIpV6);
}
void set(const std::string& address, uint16_t port, bool forceIpV6 = false)
{
char portStr[16];
CYBOZU_SNPRINTF(portStr, sizeof(portStr), "%d", port);
memset(&addr_, 0, sizeof(addr_));
addrlen_ = 0;
family_ = 0;
struct addrinfo *result = 0;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_NUMERICSERV; // AI_PASSIVE;
const int s = getaddrinfo(address.c_str(), portStr, &hints, &result);
// s == EAI_AGAIN
if (s || forceIpV6) {
hints.ai_family = AF_INET6;
hints.ai_flags |= AI_V4MAPPED;
if (getaddrinfo(address.c_str(), portStr, &hints, &result)) {
goto ERR_EXIT;
}
}
{
bool found = false;
for (const struct addrinfo *p = result; p; p = p->ai_next) {
const int family = p->ai_family;
if (family == hints.ai_family) {
if (p->ai_addrlen > sizeof(addr_)) {
break;
}
memcpy(&addr_, p->ai_addr, p->ai_addrlen);
addrlen_ = (socklen_t)p->ai_addrlen;
family_ = family;
found = true;
break;
}
}
freeaddrinfo(result);
if (found) return;
}
ERR_EXIT:
throw cybozu::Exception("SocketAddr:set") << address << port << cybozu::NetErrorNo();
}
socklen_t getSize() const { return addrlen_; }
int getFamily() const { return family_; }
const struct sockaddr *get() const { return &addr_.sa; }
uint16_t getPort() const {
if (family_ == AF_INET) {
return ntohs(addr_.v4.sin_port);
} else if (family_ == AF_INET6) {
return ntohs(addr_.v6.sin6_port);
}
throw cybozu::Exception("SocketAddr:getPort:bad family") << family_;
}
// compare addr without port
bool hasSameAddr(const SocketAddr& rhs) const
{
const uint8_t *v4 = 0;
const uint8_t *v6 = 0;
if (family_ == AF_INET) {
if (rhs.family_ == AF_INET) return memcmp(&addr_.v4.sin_addr, &rhs.addr_.v4.sin_addr, sizeof(in_addr)) == 0;
if (rhs.family_ != AF_INET6) return false;
v4 = (const uint8_t*)&addr_.v4.sin_addr;
v6 = (const uint8_t*)&rhs.addr_.v6.sin6_addr;
} else if (family_ != AF_INET6) {
return false;
} else {
if (rhs.family_ == AF_INET6) return memcmp(&addr_.v6.sin6_addr, &rhs.addr_.v6.sin6_addr, sizeof(in6_addr)) == 0;
if (rhs.family_ != AF_INET) return false;
v4 = (const uint8_t*)&rhs.addr_.v4.sin_addr;
v6 = (const uint8_t*)&addr_.v6.sin6_addr;
}
// Ipv6-mapped?
const uint8_t header[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
return memcmp(v6, header, 12) == 0 && memcmp(v6 + 12, v4, 4) == 0;
}
std::string toStr() const
{
if (family_ == AF_INET || family_ == AF_INET6) {
char buf[INET6_ADDRSTRLEN];
assert(INET_ADDRSTRLEN <= INET6_ADDRSTRLEN);
const bool isIPv4 = family_ == AF_INET;
const void *pa = isIPv4 ? (const void*)&addr_.v4.sin_addr : (const void*)&addr_.v6.sin6_addr;
// not "const void*" because of vc
const char *p = inet_ntop(family_, const_cast<void*>(pa), buf, sizeof(buf));
if (!p) throw cybozu::Exception("cybozu:SocketAddr:toStr") << cybozu::NetErrorNo();
if (isIPv4) return std::string(p) + ':' + cybozu::itoa(getPort());
return std::string("[") + p + "]:" + cybozu::itoa(getPort());
}
throw cybozu::Exception("cybozu:SocketAddr:toStr:bad family_") << family_;
}
};
/*
socket class
@note ower is moved if copied
*/
class Socket {
friend class cybozu::ssl::ClientSocket;
private:
cybozu::socket_local::SocketHandle sd_;
Socket(const Socket&);
void operator=(const Socket&);
#ifdef WIN32
void setTimeout(int type, int msec)
{
setSocketOption(type, msec);
}
/* return msec */
int getTimeout(int type) const
{
return getSocketOption(type);
}
#else
void setTimeout(int type, int msec)
{
struct timeval t;
t.tv_sec = msec / 1000;
t.tv_usec = (msec % 1000) * 1000;
setSocketOption(type, t);
}
/* return msec */
int getTimeout(int type) const
{
struct timeval t;
getSocketOption(type, &t);
return t.tv_sec * 1000 + t.tv_usec / 1000; /* msec */
}
#endif
void setBlocking(bool isBlocking)
{
#ifdef _WIN32
u_long val = isBlocking ? 0 : 1;
int ret = ::ioctlsocket(sd_, FIONBIO, &val);
#else
int val = isBlocking ? 0 : 1;
int ret = ::ioctl(sd_, FIONBIO, &val);
#endif
if (ret < 0) throw cybozu::Exception("Socket:setBlocking") << cybozu::NetErrorNo() << isBlocking;
}
public:
#ifndef _WIN32
static const int INVALID_SOCKET = -1;
#endif
Socket()
: sd_(INVALID_SOCKET)
{
}
bool isValid() const { return sd_ != INVALID_SOCKET; }
// move
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
Socket(Socket&& rhs)
: sd_(INVALID_SOCKET)
{
sd_ = cybozu::AtomicExchange(&rhs.sd_, sd_);
}
#endif
// close and move
void moveFrom(Socket& rhs)
{
close();
sd_ = cybozu::AtomicExchange(&rhs.sd_, INVALID_SOCKET);
}
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
void operator=(Socket&& rhs)
#else
void operator=(Socket& rhs)
#endif
{
moveFrom(rhs);
}
~Socket()
{
close(cybozu::DontThrow);
}
bool close(bool dontThrow = false)
{
cybozu::socket_local::SocketHandle sd = cybozu::AtomicExchange(&sd_, INVALID_SOCKET);
if (sd == INVALID_SOCKET) return true;
#ifdef _WIN32
// ::shutdown(sd, SD_SEND);
// shutdown is called in closesocket
bool isOK = ::closesocket(sd) == 0;
#else
bool isOK = ::close(sd) == 0;
#endif
if (!dontThrow && !isOK) throw cybozu::Exception("Socket:close") << cybozu::NetErrorNo();
return isOK;
}
/*
how 0 : SHUTRD ; disallow read
1 : SHUT_WR ; disallow write
2 : SHUT_RDWR ; disallow read/write
*/
bool shutdown(int how, bool dontThrow = false)
{
bool isOK = ::shutdown(sd_, how) == 0;
if (!dontThrow && !isOK) throw cybozu::Exception("Socket:waitForClose:shutdown") << cybozu::NetErrorNo();
return isOK;
}
/*
send FIN and wait for remote's close().
this function is used for the following situation.
sock.write()
sock.waitForClose()
sock.close()
*/
void waitForClose()
{
if (sd_ == INVALID_SOCKET) return;
// send FIN and this socket can't write any data.
shutdown(1);
// wait for FIN from the peer.
char buf[1];
ssize_t readSize = readSome(buf, sizeof(buf));
if (readSize != 0) {
throw cybozu::Exception("Socket:waitForClose:readSome:bad size") << readSize;
}
}
/*!
receive data
@param buf [out] receive buffer
@param bufSize [in] receive buffer size(byte)
@note return read size
*/
size_t readSome(void *buf, size_t bufSize)
{
int size = (int)(std::min)((size_t)0x7fffffff, bufSize);
#ifdef _WIN32
int readSize = ::recv(sd_, (char *)buf, size, 0);
#else
RETRY:
ssize_t readSize = ::read(sd_, buf, size);
if (readSize < 0 && errno == EINTR) goto RETRY;
#endif
if (readSize < 0) throw cybozu::Exception("Socket:readSome") << cybozu::NetErrorNo() << bufSize;
return readSize;
}
/*!
receive all data unless timeout
@param buf [out] receive buffer
@param bufSize [in] receive buffer size(byte)
*/
void read(void *buf, size_t bufSize)
{
char *p = (char *)buf;
while (bufSize > 0) {
size_t readSize = readSome(p, bufSize);
if (readSize == 0) throw cybozu::Exception("Socket:read:readSize is zero");
p += readSize;
bufSize -= readSize;
}
}
/*!
write all data
@param buf [out] send buffer
@param bufSize [in] send buffer size(byte)
*/
void write(bool *pb, const void *buf, size_t bufSize)
{
const char *p = (const char *)buf;
while (bufSize > 0) {
int size = (int)(std::min)(size_t(0x7fffffff), bufSize);
#ifdef _WIN32
int writeSize = ::send(sd_, p, size, 0);
#else
int writeSize = ::write(sd_, p, size);
if (writeSize < 0 && errno == EINTR) continue;
#endif
if (writeSize < 0) {
*pb = false;
return;
}
p += writeSize;
bufSize -= writeSize;
}
*pb = true;
}
void write(const void *buf, size_t bufSize)
{
bool b;
write(&b, buf, bufSize);
if (!b) throw cybozu::Exception("Socket:write") << cybozu::NetErrorNo() << bufSize;
}
/**
connect to address:port
@param address [in] address
@param port [in] port
@param msec: 0 : block
*/
void connect(const std::string& address, uint16_t port, int msec = 0)
{
SocketAddr addr;
addr.set(address, port);
connect(addr, msec);
}
/**
connect to resolved socket addr
*/
void connect(const cybozu::SocketAddr& addr, int msec = 0)
{
if (isValid()) throw cybozu::Exception("Socket:connect:already connect");
sd_ = ::socket(addr.getFamily(), SOCK_STREAM, IPPROTO_TCP);
if (!isValid()) {
throw cybozu::Exception("Socket:connect:socket") << cybozu::NetErrorNo();
}
if (msec == 0) {
if (::connect(sd_, addr.get(), addr.getSize()) < 0) {
throw cybozu::Exception("Socket:connect") << cybozu::NetErrorNo() << addr.toStr();
}
} else {
setBlocking(false);
if (::connect(sd_, addr.get(), addr.getSize()) < 0) {
#ifdef _WIN32
bool inProgress = WSAGetLastError() == WSAEWOULDBLOCK;
#else
bool inProgress = errno == EINPROGRESS;
#endif
if (!inProgress) throw cybozu::Exception("Socket:connect:not in progress") << cybozu::NetErrorNo() << addr.toStr();
if (!queryAccept(msec, false)) throw cybozu::Exception("Socket:connect:timeout") << addr.toStr();
int err = getSocketOption(SO_ERROR);
if (err != 0) throw cybozu::Exception("Socket::connect:bad socket") << cybozu::NetErrorNo(err);
}
setBlocking(true);
}
}
static const int allowIPv4 = 1;
static const int allowIPv6 = 2;
/**
init for server
@param port [in] port number
*/
void bind(uint16_t port, int mode = allowIPv4 | allowIPv6)
{
const int family = (mode & allowIPv6) ? AF_INET6 : AF_INET;
sd_ = ::socket(family, SOCK_STREAM, IPPROTO_TCP);
if (!isValid()) {
throw cybozu::Exception("Socket:bind:socket") << cybozu::NetErrorNo();
}
setSocketOption(SO_REUSEADDR, 1);
struct sockaddr_in6 addr6;
struct sockaddr_in addr4;
struct sockaddr *addr;
socklen_t addrLen;
if (mode & allowIPv6) {
setSocketOption(IPV6_V6ONLY, (mode & allowIPv4) ? 0 : 1, IPPROTO_IPV6);
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(port);
addr = (struct sockaddr*)&addr6;
addrLen = sizeof(addr6);
} else {
memset(&addr4, 0, sizeof(addr4));
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port);
addr = (struct sockaddr*)&addr4;
addrLen = sizeof(addr4);
}
if (::bind(sd_, addr, addrLen) == 0) {
if (::listen(sd_, SOMAXCONN) == 0) {
return;
}
}
cybozu::NetErrorNo keep;
close(cybozu::DontThrow);
throw cybozu::Exception("Socket:bind") << keep;
}
/**
return positive if accepted
return zero if timeout
return negative(-errno) if error
*/
int queryAcceptNoThrow(int msec = 1000, bool checkWrite = true)
{
if (sd_ == INVALID_SOCKET) return -EBADF;
#ifdef CYBOZU_SOCKET_USE_EPOLL
int err;
experimental::Epoll ep;
if (!ep.init(&err)) return -err;
uint32_t events = checkWrite ? EPOLLIN : EPOLLOUT;
experimental::AutoLock al(ep, sd_, events);
experimental::EpollEvent ev;
int ret = ep.wait(&ev, 1, msec);
if (ret != 1) return ret;
assert(ev.getFd() == sd_);
return ret;
#else
#ifndef _WIN32
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms739169.aspx
if (sd_ >= FD_SETSIZE) return -EMFILE;
#endif
struct timeval timeout;
timeout.tv_sec = msec / 1000;
timeout.tv_usec = (msec % 1000) * 1000;
fd_set fds;
FD_ZERO(&fds);
FD_SET((unsigned)sd_, &fds);
int fdNum;
if (checkWrite) {
fdNum = ::select((int)sd_ + 1, &fds, 0, 0, &timeout);
} else {
fdNum = ::select((int)sd_ + 1, 0, &fds, 0, &timeout);
}
if (fdNum < 0) return -errno;
return fdNum;
#endif
}
/**
return true if acceptable, otherwise false
return false if one second passed
while (!server.queryAccept()) {
}
client.accept(server);
*/
bool queryAccept(int msec = 1000, bool checkWrite = true)
{
int ret = queryAcceptNoThrow(msec, checkWrite);
if (ret < 0) throw cybozu::Exception("Socket:queryAccept") << cybozu::NetErrorNo(-ret);
return ret > 0;
}
/**
accept for server
*/
void accept(Socket& client, SocketAddr *paddr = 0) const
{
if (paddr) {
struct sockaddr *psa = &paddr->addr_.sa;
paddr->addrlen_ = sizeof(paddr->addr_);
client.sd_ = ::accept(sd_, psa, &paddr->addrlen_);
paddr->verify();
} else {
client.sd_ = ::accept(sd_, 0, 0);
}
if (!client.isValid()) throw cybozu::Exception("Socket:accept") << cybozu::NetErrorNo();
}
template<typename T>
void setSocketOption(int optname, const T& value, int level = SOL_SOCKET)
{
bool isOK = setsockopt(sd_, level, optname, cybozu::cast<const char*>(&value), sizeof(T)) == 0;
if (!isOK) throw cybozu::Exception("Socket:setSocketOption") << cybozu::NetErrorNo();
}
template<typename T>
void getSocketOption(int optname, T* value, int level = SOL_SOCKET) const
{
socklen_t len = (socklen_t)sizeof(T);
bool isOK = getsockopt(sd_, level, optname, cybozu::cast<char*>(value), &len) == 0;
if (!isOK) throw cybozu::Exception("Socket:getSocketOption") << cybozu::NetErrorNo();
}
int getSocketOption(int optname) const
{
int ret;
getSocketOption(optname, &ret);
return ret;
}
/**
setup linger
*/
void setLinger(uint16_t l_onoff, uint16_t l_linger)
{
struct linger linger;
linger.l_onoff = l_onoff;
linger.l_linger = l_linger;
setSocketOption(SO_LINGER, &linger);
}
/**
get receive buffer size
@retval positive buffer size(byte)
@retval -1 error
*/
int getReceiveBufferSize() const
{
return getSocketOption(SO_RCVBUF);
}
/**
set receive buffer size
@param size [in] buffer size(byte)
*/
void setReceiveBufferSize(int size)
{
setSocketOption(SO_RCVBUF, size);
}
/**
get send buffer size
@retval positive buffer size(byte)
@retval -1 error
*/
int getSendBufferSize() const
{
return getSocketOption(SO_SNDBUF);
}
/**
sed send buffer size
@param size [in] buffer size(byte)
*/
void setSendBufferSize(int size)
{
setSocketOption(SO_SNDBUF, size);
}
/**
set send timeout
@param msec [in] msec
*/
void setSendTimeout(int msec)
{
setTimeout(SO_SNDTIMEO, msec);
}
/**
set receive timeout
@param msec [in] msec
*/
void setReceiveTimeout(int msec)
{
setTimeout(SO_RCVTIMEO, msec);
}
/**
get send timeout(msec)
*/
int getSendTimeout() const
{
return getTimeout(SO_SNDTIMEO);
}
/**
get receive timeout(msec)
*/
int getReceiveTimeout() const
{
return getTimeout(SO_RCVTIMEO);
}
};
} // cybozu
#ifdef _MSC_VER
#pragma warning(pop)
#endif

@ -9,7 +9,9 @@
#include <string>
#include <iosfwd>
#endif
#ifndef CYBOZU_DONT_USE_EXCEPTION
#include <cybozu/exception.hpp>
#endif
#include <memory.h>
namespace cybozu {

@ -0,0 +1,281 @@
#pragma once
/**
@file
@brief tiny time class
@author MITSUNARI Shigeo(@herumi)
*/
#include <ctime>
#include <cybozu/exception.hpp>
#include <cybozu/atoi.hpp>
#include <cybozu/itoa.hpp>
#ifdef _WIN32
#include <sys/timeb.h>
#else
#include <sys/time.h>
#endif
namespace cybozu {
/**
time struct with time_t and msec
@note time MUST be latesr than 1970/1/1
*/
class Time {
static const uint64_t epochBias = 116444736000000000ull;
std::time_t time_;
int msec_;
public:
explicit Time(std::time_t time = 0, int msec = 0)
: time_(time)
, msec_(msec)
{
}
explicit Time(bool doSet)
{
if (doSet) setCurrentTime();
}
Time& setTime(std::time_t time, int msec = 0)
{
time_ = time;
msec_ = msec;
return *this;
}
/*
Windows FILETIME is defined as
struct FILETILME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
};
the value represents the number of 100-nanosecond intervals since January 1, 1601 (UTC).
*/
void setByFILETIME(uint32_t low, uint32_t high)
{
const uint64_t fileTime = (((uint64_t(high) << 32) | low) - epochBias) / 10000;
time_ = fileTime / 1000;
msec_ = fileTime % 1000;
}
/*
DWORD is defined as unsigned long in windows
*/
template<class dword>
void getFILETIME(dword& low, dword& high) const
{
const uint64_t fileTime = (time_ * 1000 + msec_) * 10000 + epochBias;
low = dword(fileTime);
high = dword(fileTime >> 32);
}
explicit Time(const std::string& in)
{
fromString(in);
}
explicit Time(const char *in)
{
fromString(in, in + strlen(in));
}
const std::time_t& getTime() const { return time_; }
int getMsec() const { return msec_; }
double getTimeSec() const { return time_ + msec_ * 1e-3; }
void addSec(int sec) { time_ += sec; }
bool operator<(const Time& rhs) const { return (time_ < rhs.time_) || (time_ == rhs.time_ && msec_ < rhs.msec_); }
// bool operator<=(const Time& rhs) const { return (*this < rhs) || (*this == rhs); }
// bool operator>(const Time& rhs) const { return rhs < *this; }
bool operator==(const Time& rhs) const { return (time_ == rhs.time_) && (msec_ == rhs.msec_); }
bool operator!=(const Time& rhs) const { return !(*this == rhs); }
/**
set time from string such as
2009-Jan-23T02:53:44Z
2009-Jan-23T02:53:44.078Z
2009-01-23T02:53:44Z
2009-01-23T02:53:44.078Z
@note 'T' may be ' '. '-' may be '/'. last char 'Z' is omissible
*/
void fromString(bool *pb, const std::string& in) { fromString(pb, &in[0], &in[0] + in.size()); }
void fromString(const std::string& in) { fromString(0, in); }
void fromString(bool *pb, const char *begin, const char *end)
{
const size_t len = end - begin;
if (len >= 19) {
const char *p = begin;
struct tm tm;
int num;
bool b;
tm.tm_year = getNum(&b, p, 4, 1970, 3000) - 1900;
if (!b) goto ERR;
p += 4;
char sep = *p++;
if (sep != '-' && sep != '/') goto ERR;
p = getMonth(&num, p);
if (p == 0) goto ERR;
tm.tm_mon = num;
if (*p++ != sep) goto ERR;
tm.tm_mday = getNum(&b, p, 2, 1, 31);
if (!b) goto ERR;
p += 2;
if (*p != ' ' && *p != 'T') goto ERR;
p++;
tm.tm_hour = getNum(&b, p, 2, 0, 23);
if (!b) goto ERR;
p += 2;
if (*p++ != ':') goto ERR;
tm.tm_min = getNum(&b, p, 2, 0, 59);
if (!b) goto ERR;
p += 2;
if (*p++ != ':') goto ERR;
tm.tm_sec = getNum(&b, p, 2, 0, 59);
if (!b) goto ERR;
p += 2;
if (p == end) {
msec_ = 0;
} else if (p + 1 == end && *p == 'Z') {
msec_ = 0;
p++;
} else if (*p == '.' && (p + 4 == end || (p + 5 == end && *(p + 4) == 'Z'))) {
msec_ = getNum(&b, p + 1, 3, 0, 999);
if (!b) goto ERR;
// p += 4;
} else {
goto ERR;
}
#ifdef _WIN32
time_ = _mkgmtime64(&tm);
if (time_ == -1) goto ERR;
#else
time_ = timegm(&tm);
#endif
if (pb) {
*pb = true;
}
return;
}
ERR:
if (pb) {
*pb = false;
return;
}
throw cybozu::Exception("time::fromString") << std::string(begin, 24);
}
void fromString(const char *begin, const char *end) { fromString(0, begin, end); }
/**
get current time with format
@param out [out] output string
@param format [in] foramt for strftime and append three digits for msec
@param appendMsec [in] appemd <mmm>
@param doClear (append to out if false)
@note ex. "%Y-%b-%d %H:%M:%S." to get 2009-Jan-23 02:53:44.078
*/
void toString(std::string& out, const char *format, bool appendMsec = true, bool doClear = true) const
{
if (doClear) out.clear();
char buf[128];
struct tm tm;
#ifdef _WIN32
bool isOK = _gmtime64_s(&tm, &time_) == 0;
#else
bool isOK = gmtime_r(&time_, &tm) != 0;
#endif
if (!isOK) throw cybozu::Exception("time::toString") << time_;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
if (std::strftime(buf, sizeof(buf), format, &tm) == 0) {
throw cybozu::Exception("time::toString::too long") << format << time_;
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
out += buf;
if (appendMsec) {
out += cybozu::itoaWithZero(msec_, 3);
}
}
/**
get current time such as 2009-01-23 02:53:44.078
@param out [out] sink string
*/
void toString(std::string& out, bool appendMsec = true, bool doClear = true) const
{
const char *format = appendMsec ? "%Y-%m-%d %H:%M:%S." : "%Y-%m-%d %H:%M:%S";
toString(out, format, appendMsec, doClear);
}
std::string toString(bool appendMsec = true) const { std::string out; toString(out, appendMsec); return out; }
/**
get current time
*/
Time& setCurrentTime()
{
#ifdef _WIN32
struct _timeb timeb;
_ftime_s(&timeb);
time_ = timeb.time;
msec_ = timeb.millitm;
#else
struct timeval tv;
gettimeofday(&tv, 0);
time_ = tv.tv_sec;
msec_ = tv.tv_usec / 1000;
#endif
return *this;
}
private:
int getNum(bool *b, const char *in, size_t len, int min, int max) const
{
int ret = cybozu::atoi(b, in, len);
if (min <= ret && ret <= max) {
return ret;
} else {
*b = false;
return 0;
}
}
/*
convert month-str to [0, 11]
@param ret [out] return idx
@param p [in] month-str
@retval next pointer or null
*/
const char *getMonth(int *ret, const char *p) const
{
static const char monthTbl[12][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(monthTbl); i++) {
if (memcmp(p, monthTbl[i], 3) == 0) {
*ret = (int)i;
return p + 3;
}
}
bool b;
*ret = getNum(&b, p, 2, 1, 12) - 1;
if (b) {
return p + 2;
} else {
return 0;
}
}
};
inline std::ostream& operator<<(std::ostream& os, const cybozu::Time& time)
{
return os << time.toString();
}
inline double GetCurrentTimeSec()
{
return cybozu::Time(true).getTimeSec();
}
} // cybozu

@ -62,16 +62,32 @@ public:
friend class SecretKey;
friend class PublicKey;
public:
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
S_.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
S_.save(pb, os, ioMode);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
S_.load(is, ioMode);
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("Signature:load");
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
S_.save(os, ioMode);
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("Signature:save");
}
#endif
friend std::istream& operator>>(std::istream& is, Signature& self)
{
self.load(is, fp::detectIoMode(G1::getIoMode(), is));
@ -155,16 +171,32 @@ public:
friend class SecretKey;
friend class Signature;
public:
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
xQ_.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
xQ_.save(pb, os, ioMode);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
xQ_.load(is, ioMode);
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("PublicKey:load");
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
xQ_.save(os, ioMode);
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("PublicKey:save");
}
#endif
friend std::istream& operator>>(std::istream& is, PublicKey& self)
{
self.load(is, fp::detectIoMode(G2::getIoMode(), is));
@ -208,16 +240,32 @@ public:
friend class PublicKey;
friend class Signature;
public:
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
x_.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
x_.save(pb, os, ioMode);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
x_.load(is, ioMode);
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("SecretKey:load");
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
x_.save(os, ioMode);
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("SecretKey:save");
}
#endif
friend std::istream& operator>>(std::istream& is, SecretKey& self)
{
self.load(is, fp::detectIoMode(Fr::getIoMode(), is));

@ -1,76 +0,0 @@
#pragma once
/**
@file
@brief 192/256-bit additive homomorphic encryption by lifted-ElGamal
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/elgamal.hpp>
#include <mcl/ecparam.hpp>
namespace mcl {
#ifdef MCL_USE_AHE192
namespace ahe192 {
const mcl::EcParam& para = mcl::ecparam::NIST_P192;
typedef mcl::FpT<mcl::FpTag, 192> Fp;
typedef mcl::FpT<mcl::ZnTag, 192> Zn;
typedef mcl::EcT<Fp> Ec;
typedef mcl::ElgamalT<Ec, Zn> ElgamalEc;
typedef ElgamalEc::PrivateKey SecretKey;
typedef ElgamalEc::PublicKey PublicKey;
typedef ElgamalEc::CipherText CipherText;
static inline void initAhe()
{
Fp::init(para.p);
Zn::init(para.n);
Ec::init(para.a, para.b);
Ec::setIoMode(16);
Zn::setIoMode(16);
}
static inline void initSecretKey(SecretKey& sec)
{
const Ec P(Fp(para.gx), Fp(para.gy));
sec.init(P, Zn::getBitSize());
}
} //mcl::ahe192
#endif
#ifdef MCL_USE_AHE256
namespace ahe256 {
const mcl::EcParam& para = mcl::ecparam::NIST_P256;
typedef mcl::FpT<mcl::FpTag, 256> Fp;
typedef mcl::FpT<mcl::ZnTag, 256> Zn;
typedef mcl::EcT<Fp> Ec;
typedef mcl::ElgamalT<Ec, Zn> ElgamalEc;
typedef ElgamalEc::PrivateKey SecretKey;
typedef ElgamalEc::PublicKey PublicKey;
typedef ElgamalEc::CipherText CipherText;
static inline void initAhe()
{
Fp::init(para.p);
Zn::init(para.n);
Ec::init(para.a, para.b);
Ec::setIoMode(16);
Zn::setIoMode(16);
}
static inline void initSecretKey(SecretKey& sec)
{
const Ec P(Fp(para.gx), Fp(para.gy));
sec.init(P, Zn::getBitSize());
}
} //mcl::ahe256
#endif
} // mcl

@ -118,6 +118,7 @@ class FixedArray {
y = t;
}
public:
typedef T value_type;
FixedArray() : n_(0) {}
bool resize(size_t n)
{
@ -125,6 +126,15 @@ public:
n_ = n;
return true;
}
void push(bool *pb, const T& x)
{
if (n_ == maxSize) {
*pb = false;
return;
}
p_[n_++] = x;
*pb = true;
}
bool copy(const FixedArray<T, maxSize>& rhs)
{
if (this == &rhs) return true;

@ -75,35 +75,47 @@ typedef struct mclBnFp2 mclBnFp2;
#else
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE];
} mclBnFp;
/*
x = d[0] + d[1] i where i^2 = -1
*/
typedef struct {
mclBnFp d[2];
} mclBnFp2;
/*
G1 and G2 are isomorphism to Fr
*/
typedef struct {
uint64_t d[MCLBN_FR_UNIT_SIZE];
} mclBnFr;
/*
G1 is defined over Fp
*/
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 3];
mclBnFp x, y, z;
} mclBnG1;
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 2 * 3];
mclBnFp2 x, y, z;
} mclBnG2;
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 12];
mclBnFp d[12];
} mclBnGT;
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE];
} mclBnFp;
typedef struct {
mclBnFp d[2];
} mclBnFp2;
#endif
#include <mcl/curve_type.h>
#define MCLBN_IO_EC_AFFINE 0
#define MCLBN_IO_EC_PROJ 1024
#define MCLBN_IO_SERIALIZE_HEX_STR 2048
// for backword compatibility
enum {
mclBn_CurveFp254BNb = 0,
@ -115,7 +127,7 @@ enum {
};
// return 0xABC which means A.BC
MCLBN_DLL_API int mclBn_getVersion();
MCLBN_DLL_API int mclBn_getVersion(void);
/*
init library
@param curve [in] type of bn curve
@ -131,6 +143,7 @@ MCLBN_DLL_API int mclBn_getVersion();
*/
MCLBN_DLL_API int mclBn_init(int curve, int compiledTimeVar);
MCLBN_DLL_API int mclBn_getCurveType(void);
/*
pairing : G1 x G2 -> GT
@ -179,10 +192,20 @@ MCLBN_DLL_API mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize);
/*
set ETH serialization mode for BLS12-381
@param ETHserialization [in] 1:enable, 0:disable
@param enable [in] 1:enable, 0:disable
@note ignore the flag if curve is not BLS12-381
*/
MCLBN_DLL_API void mclBn_setETHserialization(int ETHserialization);
MCLBN_DLL_API void mclBn_setETHserialization(int enable);
// return 1 if ETH serialization mode else 0
MCLBN_DLL_API int mclBn_getETHserialization(void);
/*
set map-to-function to mode (only support MCL_MAP_TO_MODE_HASH_TO_CURVE_07)
return 0 if success else -1
*/
MCLBN_DLL_API int mclBn_setMapToMode(int mode);
////////////////////////////////////////////////
/*
deserialize
@ -238,6 +261,8 @@ 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);
MCLBN_DLL_API void mclBnFp_setInt(mclBnFp *y, mclInt x);
MCLBN_DLL_API void mclBnFp_setInt32(mclBnFp *y, int x);
// x = buf & (1 << bitLen(r)) - 1
// if (x >= r) x &= (1 << (bitLen(r) - 1)) - 1
@ -245,25 +270,49 @@ MCLBN_DLL_API void mclBnFr_setInt32(mclBnFr *y, int x);
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);
/*
write a value as little endian
return written size if success else 0
@note buf[0] = 0 and return 1 if the value is zero
*/
MCLBN_DLL_API mclSize mclBnFr_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFr *x);
MCLBN_DLL_API mclSize mclBnFp_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFp *x);
// 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);
MCLBN_DLL_API int mclBnFr_setBigEndianMod(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);
MCLBN_DLL_API int mclBnFp_setBigEndianMod(mclBnFp *x, const void *buf, mclSize bufSize);
// return 1 if true and 0 otherwise
MCLBN_DLL_API int mclBnFr_isValid(const mclBnFr *x);
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 mclBnFr_isOdd(const mclBnFr *x);
// return 1 if half <= x < r, where half = (r + 1) / 2 else 0
MCLBN_DLL_API int mclBnFr_isNegative(const mclBnFr *x);
MCLBN_DLL_API int mclBnFp_isValid(const mclBnFp *x);
MCLBN_DLL_API int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API int mclBnFp_isZero(const mclBnFp *x);
MCLBN_DLL_API int mclBnFp_isOne(const mclBnFp *x);
MCLBN_DLL_API int mclBnFp_isOdd(const mclBnFp *x);
// return 1 if half <= x < p, where half = (p + 1) / 2 else 0
MCLBN_DLL_API int mclBnFp_isNegative(const mclBnFp *x);
MCLBN_DLL_API int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y);
MCLBN_DLL_API int mclBnFp2_isZero(const mclBnFp2 *x);
MCLBN_DLL_API int mclBnFp2_isOne(const mclBnFp2 *x);
#ifndef MCL_DONT_USE_CSRPNG
// return 0 if success
MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x);
MCLBN_DLL_API int mclBnFp_setByCSPRNG(mclBnFp *x);
/*
set user-defined random function for setByCSPRNG
@ -294,6 +343,28 @@ MCLBN_DLL_API void mclBnFr_sub(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
MCLBN_DLL_API void mclBnFr_mul(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
MCLBN_DLL_API void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
MCLBN_DLL_API void mclBnFp_neg(mclBnFp *y, const mclBnFp *x);
MCLBN_DLL_API void mclBnFp_inv(mclBnFp *y, const mclBnFp *x);
MCLBN_DLL_API void mclBnFp_sqr(mclBnFp *y, const mclBnFp *x);
MCLBN_DLL_API void mclBnFp_add(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API void mclBnFp_sub(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API void mclBnFp_mul(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API void mclBnFp_div(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API void mclBnFp2_neg(mclBnFp2 *y, const mclBnFp2 *x);
MCLBN_DLL_API void mclBnFp2_inv(mclBnFp2 *y, const mclBnFp2 *x);
MCLBN_DLL_API void mclBnFp2_sqr(mclBnFp2 *y, const mclBnFp2 *x);
MCLBN_DLL_API void mclBnFp2_add(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
MCLBN_DLL_API void mclBnFp2_sub(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
MCLBN_DLL_API void mclBnFp2_mul(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
MCLBN_DLL_API void mclBnFp2_div(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
// y is one of square root of x
// return 0 if success else -1
MCLBN_DLL_API int mclBnFr_squareRoot(mclBnFr *y, const mclBnFr *x);
MCLBN_DLL_API int mclBnFp_squareRoot(mclBnFp *y, const mclBnFp *x);
MCLBN_DLL_API int mclBnFp2_squareRoot(mclBnFp2 *y, const mclBnFp2 *x);
////////////////////////////////////////////////
// set zero
MCLBN_DLL_API void mclBnG1_clear(mclBnG1 *x);
@ -365,26 +436,37 @@ MCLBN_DLL_API int mclBnGT_isZero(const mclBnGT *x);
MCLBN_DLL_API int mclBnGT_isOne(const mclBnGT *x);
MCLBN_DLL_API void mclBnGT_neg(mclBnGT *y, const mclBnGT *x);
MCLBN_DLL_API void mclBnGT_inv(mclBnGT *y, const mclBnGT *x);
MCLBN_DLL_API void mclBnGT_sqr(mclBnGT *y, const mclBnGT *x);
MCLBN_DLL_API void mclBnGT_add(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
MCLBN_DLL_API void mclBnGT_sub(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
MCLBN_DLL_API void mclBnGT_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
MCLBN_DLL_API void mclBnGT_div(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
// y = conjugate of x in Fp12, which is equal to the inverse of x if |x|^r = 1
MCLBN_DLL_API void mclBnGT_inv(mclBnGT *y, const mclBnGT *x);
// use invGeneric when x in Fp12 is not in GT
MCLBN_DLL_API void mclBnGT_invGeneric(mclBnGT *y, const mclBnGT *x);
/*
pow for all elements of Fp12
*/
MCLBN_DLL_API void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y);
/*
pow for only {x|x^r = 1} in Fp12 by GLV method
pow for only {x|x^r = 1} in GT by GLV method
the value generated by pairing satisfies the condition
*/
MCLBN_DLL_API void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y);
// z = sum_{i=0}^{n-1} x[i] y[i]
MCLBN_DLL_API void mclBnG1_mulVec(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y, mclSize n);
MCLBN_DLL_API void mclBnG2_mulVec(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y, mclSize n);
MCLBN_DLL_API void mclBnGT_powVec(mclBnGT *z, const mclBnGT *x, const mclBnFr *y, mclSize n);
MCLBN_DLL_API void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
MCLBN_DLL_API void mclBn_finalExp(mclBnGT *y, const mclBnGT *x);
MCLBN_DLL_API void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
// z = prod_{i=0}^{n-1} millerLoop(x[i], y[i])
MCLBN_DLL_API void mclBn_millerLoopVec(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y, mclSize n);
// return precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t)
MCLBN_DLL_API int mclBn_getUint64NumToPrecompute(void);
@ -410,7 +492,8 @@ MCLBN_DLL_API int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVe
/*
evaluate polynomial
out = f(x) = c[0] + c[1] * x + c[2] * x^2 + ... + c[cSize - 1] * x^(cSize - 1)
@note cSize >= 2
return 0 if success else -1
@note cSize >= 1
*/
MCLBN_DLL_API int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, mclSize cSize, const mclBnFr *x);
MCLBN_DLL_API int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, mclSize cSize, const mclBnFr *x);

File diff suppressed because it is too large Load Diff

@ -208,8 +208,6 @@ inline bool parsePrefix(size_t *readSize, bool *isMinus, int *base, const char *
if (*base == 0 || *base == 2) {
*base = 2;
pos += 2;
} else {
return false;
}
}
}

@ -18,7 +18,7 @@ enum {
/*
for only G1
the size of curve must be less or equal to MCLBN_FP_UNIT_SIZE
the size of curve must be <= MCLBN_FP_UNIT_SIZE
*/
MCL_EC_BEGIN = 100,
MCL_SECP192K1 = MCL_EC_BEGIN,
@ -29,7 +29,90 @@ enum {
MCL_NIST_P192 = 105,
MCL_NIST_P224 = 106,
MCL_NIST_P256 = 107,
MCL_EC_END = MCL_NIST_P256 + 1,
MCL_SECP160K1 = 108,
MCL_P160_1 = 109,
MCL_EC_END = MCL_P160_1 + 1,
MCL_NIST_P384 = MCL_SECP384R1,
MCL_NIST_P521 = MCL_SECP521R1
};
/*
remark : if irtf-cfrg-hash-to-curve is compeletely fixed, then
MCL_MAP_TO_MODE_WB19, MCL_MAP_TO_MODE_HASH_TO_CURVE_0? will be removed and
only MCL_MAP_TO_MODE_HASH_TO_CURVE will be available.
*/
enum {
MCL_MAP_TO_MODE_ORIGINAL, // see MapTo::calcBN
MCL_MAP_TO_MODE_TRY_AND_INC, // try-and-incremental-x
MCL_MAP_TO_MODE_ETH2, // (deprecated) old eth2.0 spec
MCL_MAP_TO_MODE_WB19, // (deprecated) used in new eth2.0 spec
MCL_MAP_TO_MODE_HASH_TO_CURVE_05 = MCL_MAP_TO_MODE_WB19, // (deprecated) draft-irtf-cfrg-hash-to-curve-05
MCL_MAP_TO_MODE_HASH_TO_CURVE_06, // (deprecated) draft-irtf-cfrg-hash-to-curve-06
MCL_MAP_TO_MODE_HASH_TO_CURVE_07, // draft-irtf-cfrg-hash-to-curve-07
MCL_MAP_TO_MODE_HASH_TO_CURVE = MCL_MAP_TO_MODE_HASH_TO_CURVE_07 // the latset version
};
#ifdef __cplusplus
#include <string.h>
#include <assert.h>
namespace mcl {
struct CurveParam {
/*
y^2 = x^3 + b
i^2 = -1
xi = xi_a + i
v^3 = xi
w^2 = v
*/
const char *z;
int b; // y^2 = x^3 + b
int xi_a; // xi = xi_a + i
/*
BN254, BN381 : Dtype
BLS12-381 : Mtype
*/
bool isMtype;
int curveType; // same in curve_type.h
bool operator==(const CurveParam& rhs) const
{
return strcmp(z, rhs.z) == 0 && b == rhs.b && xi_a == rhs.xi_a && isMtype == rhs.isMtype;
}
bool operator!=(const CurveParam& rhs) const { return !operator==(rhs); }
};
const CurveParam BN254 = { "-0x4080000000000001", 2, 1, false, MCL_BN254 }; // -(2^62 + 2^55 + 1)
// provisional(experimental) param with maxBitSize = 384
const CurveParam BN381_1 = { "-0x400011000000000000000001", 2, 1, false, MCL_BN381_1 }; // -(2^94 + 2^76 + 2^72 + 1) // A Family of Implementation-Friendly BN Elliptic Curves
const CurveParam BN381_2 = { "-0x400040090001000000000001", 2, 1, false, MCL_BN381_2 }; // -(2^94 + 2^78 + 2^67 + 2^64 + 2^48 + 1) // used in relic-toolkit
const CurveParam BN462 = { "0x4001fffffffffffffffffffffbfff", 5, 2, false, MCL_BN462 }; // 2^114 + 2^101 - 2^14 - 1 // https://eprint.iacr.org/2017/334
const CurveParam BN_SNARK1 = { "4965661367192848881", 3, 9, false, MCL_BN_SNARK1 };
const CurveParam BLS12_381 = { "-0xd201000000010000", 4, 1, true, MCL_BLS12_381 };
const CurveParam BN160 = { "0x4000000031", 3, 4, false, MCL_BN160 };
#ifdef __clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
#endif
inline const CurveParam* getCurveParam(int type)
{
switch (type) {
case MCL_BN254: return &mcl::BN254;
case MCL_BN381_1: return &mcl::BN381_1;
case MCL_BN381_2: return &mcl::BN381_2;
case MCL_BN462: return &mcl::BN462;
case MCL_BN_SNARK1: return &mcl::BN_SNARK1;
case MCL_BLS12_381: return &mcl::BLS12_381;
case MCL_BN160: return &mcl::BN160;
default:
return 0;
}
}
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
} // mcl
#endif

File diff suppressed because it is too large Load Diff

@ -1,105 +0,0 @@
#pragma once
/**
@file
@brief C interface of ECDSA
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <stdint.h> // for uint64_t, uint8_t
#include <stdlib.h> // for size_t
#if defined(_MSC_VER)
#ifdef ECDSA_DLL_EXPORT
#define ECDSA_DLL_API __declspec(dllexport)
#else
#define ECDSA_DLL_API __declspec(dllimport)
#ifndef ECDSA_NO_AUTOLINK
#pragma comment(lib, "mclecdsa.lib")
#endif
#endif
#elif defined(__EMSCRIPTEN__)
#define ECDSA_DLL_API __attribute__((used))
#else
#define ECDSA_DLL_API
#endif
#ifndef mclSize
#ifdef __EMSCRIPTEN__
// avoid 64-bit integer
#define mclSize unsigned int
#define mclInt int
#else
// use #define for cgo
#define mclSize size_t
#define mclInt int64_t
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef ECDSA_NOT_DEFINE_STRUCT
typedef struct ecdsaSecretKey ecdsaSecretKey;
typedef struct ecdsaPublicKey ecdsaPublicKey;
typedef struct ecdsaSignature ecdsaSignature;
#else
typedef struct {
uint64_t d[4];
} ecdsaSecretKey;
typedef struct {
uint64_t d[4 * 3];
} ecdsaPublicKey;
typedef struct {
uint64_t d[4 * 2];
} ecdsaSignature;
#endif
struct ecdsaPrecomputedPublicKey;
/*
init library
return 0 if success
@note not threadsafe
*/
ECDSA_DLL_API int ecdsaInit(void);
// return written byte size if success else 0
ECDSA_DLL_API mclSize ecdsaSecretKeySerialize(void *buf, mclSize maxBufSize, const ecdsaSecretKey *sec);
ECDSA_DLL_API mclSize ecdsaPublicKeySerialize(void *buf, mclSize maxBufSize, const ecdsaPublicKey *pub);
ECDSA_DLL_API mclSize ecdsaSignatureSerialize(void *buf, mclSize maxBufSize, const ecdsaSignature *sig);
// return read byte size if sucess else 0
ECDSA_DLL_API mclSize ecdsaSecretKeyDeserialize(ecdsaSecretKey* sec, const void *buf, mclSize bufSize);
ECDSA_DLL_API mclSize ecdsaPublicKeyDeserialize(ecdsaPublicKey* pub, const void *buf, mclSize bufSize);
ECDSA_DLL_API mclSize ecdsaSignatureDeserialize(ecdsaSignature* sig, const void *buf, mclSize bufSize);
// return 0 if success
ECDSA_DLL_API int ecdsaSecretKeySetByCSPRNG(ecdsaSecretKey *sec);
ECDSA_DLL_API void ecdsaGetPublicKey(ecdsaPublicKey *pub, const ecdsaSecretKey *sec);
ECDSA_DLL_API void ecdsaSign(ecdsaSignature *sig, const ecdsaSecretKey *sec, const void *m, mclSize size);
// return 1 if valid
ECDSA_DLL_API int ecdsaVerify(const ecdsaSignature *sig, const ecdsaPublicKey *pub, const void *m, mclSize size);
ECDSA_DLL_API int ecdsaVerifyPrecomputed(const ecdsaSignature *sig, const ecdsaPrecomputedPublicKey *pub, const void *m, mclSize size);
// return nonzero if success
ECDSA_DLL_API ecdsaPrecomputedPublicKey *ecdsaPrecomputedPublicKeyCreate();
// call this function to avoid memory leak
ECDSA_DLL_API void ecdsaPrecomputedPublicKeyDestroy(ecdsaPrecomputedPublicKey *ppub);
// return 0 if success
ECDSA_DLL_API int ecdsaPrecomputedPublicKeyInit(ecdsaPrecomputedPublicKey *ppub, const ecdsaPublicKey *pub);
#ifdef __cplusplus
}
#endif

@ -1,257 +0,0 @@
#pragma once
/**
@file
@brief ECDSA
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/fp.hpp>
#include <mcl/ec.hpp>
#include <mcl/ecparam.hpp>
#include <mcl/window_method.hpp>
namespace mcl { namespace ecdsa {
namespace local {
#ifndef MCLSHE_WIN_SIZE
#define MCLSHE_WIN_SIZE 10
#endif
static const size_t winSize = MCLSHE_WIN_SIZE;
struct FpTag;
struct ZnTag;
} // mcl::ecdsa::local
typedef mcl::FpT<local::FpTag, 256> Fp;
typedef mcl::FpT<local::ZnTag, 256> Zn;
typedef mcl::EcT<Fp> Ec;
namespace local {
struct Param {
mcl::EcParam ecParam;
Ec P;
mcl::fp::WindowMethod<Ec> Pbase;
};
inline Param& getParam()
{
static Param p;
return p;
}
inline void be32toZn(Zn& x, const mcl::fp::Unit *buf)
{
const size_t n = 32;
const unsigned char *p = (const unsigned char*)buf;
unsigned char be[n];
for (size_t i = 0; i < n; i++) {
be[i] = p[n - 1 - i];
}
x.setArrayMaskMod(be, n);
}
/*
y = x mod n
*/
inline void FpToZn(Zn& y, const Fp& x)
{
fp::Block b;
x.getBlock(b);
y.setArrayMaskMod(b.p, b.n);
}
inline void setHashOf(Zn& x, const void *msg, size_t msgSize)
{
mcl::fp::Unit xBuf[256 / 8 / sizeof(mcl::fp::Unit)];
uint32_t hashSize = mcl::fp::sha256(xBuf, sizeof(xBuf), msg, (uint32_t)msgSize);
assert(hashSize == sizeof(xBuf));
(void)hashSize;
be32toZn(x, xBuf);
}
} // mcl::ecdsa::local
const local::Param& param = local::getParam();
inline void init(bool *pb)
{
const mcl::EcParam& ecParam = mcl::ecparam::secp256k1;
Zn::init(pb, ecParam.n);
if (!*pb) return;
Fp::init(pb, ecParam.p);
if (!*pb) return;
Ec::init(pb, ecParam.a, ecParam.b);
if (!*pb) return;
Zn::setIoMode(16);
Fp::setIoMode(16);
Ec::setIoMode(mcl::IoEcAffine);
local::Param& p = local::getParam();
p.ecParam = ecParam;
Fp x, y;
x.setStr(pb, ecParam.gx);
if (!*pb) return;
y.setStr(pb, ecParam.gy);
if (!*pb) return;
p.P.set(pb, x, y);
if (!*pb) return;
p.Pbase.init(pb, p.P, ecParam.bitSize, local::winSize);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
inline void init()
{
bool b;
init(&b);
if (!b) throw cybozu::Exception("ecdsa:init");
}
#endif
typedef Zn SecretKey;
typedef Ec PublicKey;
struct PrecomputedPublicKey {
mcl::fp::WindowMethod<Ec> pubBase_;
void init(bool *pb, const PublicKey& pub)
{
pubBase_.init(pb, pub, param.ecParam.bitSize, local::winSize);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
void init(const PublicKey& pub)
{
bool b;
init(&b, pub);
if (!b) throw cybozu::Exception("ecdsa:PrecomputedPublicKey:init");
}
#endif
};
inline void getPublicKey(PublicKey& pub, const SecretKey& sec)
{
Ec::mul(pub, param.P, sec);
pub.normalize();
}
struct Signature : public mcl::fp::Serializable<Signature> {
Zn r, s;
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
r.load(pb, is, ioMode); if (!*pb) return;
s.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
const char sep = *fp::getIoSeparator(ioMode);
r.save(pb, os, ioMode); if (!*pb) return;
if (sep) {
cybozu::writeChar(pb, os, sep);
if (!*pb) return;
}
s.save(pb, os, ioMode);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("ecdsa:Signature:load");
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("ecdsa:Signature:save");
}
#endif
#ifndef CYBOZU_DONT_USE_STRING
friend std::istream& operator>>(std::istream& is, Signature& self)
{
self.load(is, fp::detectIoMode(Ec::getIoMode(), is));
return is;
}
friend std::ostream& operator<<(std::ostream& os, const Signature& self)
{
self.save(os, fp::detectIoMode(Ec::getIoMode(), os));
return os;
}
#endif
};
inline void sign(Signature& sig, const SecretKey& sec, const void *msg, size_t msgSize)
{
Zn& r = sig.r;
Zn& s = sig.s;
Zn z, k;
local::setHashOf(z, msg, msgSize);
Ec Q;
for (;;) {
k.setByCSPRNG();
param.Pbase.mul(Q, k);
if (Q.isZero()) continue;
Q.normalize();
local::FpToZn(r, Q.x);
if (r.isZero()) continue;
Zn::mul(s, r, sec);
s += z;
if (s.isZero()) continue;
s /= k;
return;
}
}
namespace local {
inline void mulDispatch(Ec& Q, const PublicKey& pub, const Zn& y)
{
Ec::mul(Q, pub, y);
}
inline void mulDispatch(Ec& Q, const PrecomputedPublicKey& ppub, const Zn& y)
{
ppub.pubBase_.mul(Q, y);
}
template<class Pub>
inline bool verify(const Signature& sig, const Pub& pub, const void *msg, size_t msgSize)
{
const Zn& r = sig.r;
const Zn& s = sig.s;
if (r.isZero() || s.isZero()) return false;
Zn z, w, u1, u2;
local::setHashOf(z, msg, msgSize);
Zn::inv(w, s);
Zn::mul(u1, z, w);
Zn::mul(u2, r, w);
Ec Q1, Q2;
param.Pbase.mul(Q1, u1);
// Ec::mul(Q2, pub, u2);
local::mulDispatch(Q2, pub, u2);
Q1 += Q2;
if (Q1.isZero()) return false;
Q1.normalize();
Zn x;
local::FpToZn(x, Q1.x);
return r == x;
}
} // mcl::ecdsa::local
inline bool verify(const Signature& sig, const PublicKey& pub, const void *msg, size_t msgSize)
{
return local::verify(sig, pub, msg, msgSize);
}
inline bool verify(const Signature& sig, const PrecomputedPublicKey& ppub, const void *msg, size_t msgSize)
{
return local::verify(sig, ppub, msg, msgSize);
}
} } // mcl::ecdsa

@ -6,10 +6,23 @@
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/ec.hpp>
#include <mcl/curve_type.h>
namespace mcl { namespace ecparam {
namespace mcl {
struct EcParam {
const char *name;
const char *p;
const char *a;
const char *b;
const char *gx;
const char *gy;
const char *n;
size_t bitSize; // bit length of p
int curveType;
};
namespace ecparam {
const struct mcl::EcParam secp160k1 = {
"secp160k1",
@ -20,9 +33,9 @@ const struct mcl::EcParam secp160k1 = {
"0x938cf935318fdced6bc28286531733c3f03c4fee",
"0x100000000000000000001b8fa16dfab9aca16b6b3",
160,
-1
MCL_SECP160K1
};
// p=2^160 + 7
// p=2^160 + 7 (for test)
const struct mcl::EcParam p160_1 = {
"p160_1",
"0x10000000000000000000000000000000000000007",
@ -32,7 +45,7 @@ const struct mcl::EcParam p160_1 = {
"1236612389951462151661156731535316138439983579284",
"1461501637330902918203683518218126812711137002561",
161,
-1
MCL_P160_1
};
const struct mcl::EcParam secp192k1 = {
"secp192k1",
@ -181,11 +194,16 @@ inline const mcl::EcParam* getEcParam(int curve)
case MCL_SECP224K1: return &ecparam::secp224k1;
case MCL_SECP256K1: return &ecparam::secp256k1;
case MCL_SECP384R1: return &ecparam::secp384r1;
case MCL_SECP521R1: return &ecparam::secp521r1;
case MCL_NIST_P192: return &ecparam::NIST_P192;
case MCL_NIST_P224: return &ecparam::NIST_P224;
case MCL_NIST_P256: return &ecparam::NIST_P256;
case MCL_SECP160K1: return &ecparam::secp160k1;
case MCL_P160_1: return &ecparam::p160_1;
default: return 0;
}
}
} // mcl
#include <mcl/ec.hpp>

@ -386,7 +386,7 @@ struct ElgamalT {
create table g^i for i in [rangeMin, rangeMax]
*/
struct PowerCache {
#if (CYBOZU_CPP_VERSION > CYBOZU_CPP_VERSION_CP03)
#if (CYBOZU_CPP_VERSION > CYBOZU_CPP_VERSION_CPP03)
typedef CYBOZU_NAMESPACE_STD::unordered_map<Ec, int> Cache;
#else
typedef std::map<Ec, int> Cache;

@ -73,6 +73,9 @@ bool isEnableJIT(); // 1st call is not threadsafe
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);
// draft-07 outSize = 128 or 256
void expand_message_xmd(uint8_t out[], size_t outSize, const void *msg, size_t msgSize, const void *dst, size_t dstSize);
namespace local {
inline void byteSwap(void *x, size_t n)
@ -131,6 +134,9 @@ public:
{
assert(maxBitSize <= MCL_MAX_BIT_SIZE);
*pb = op_.init(p, maxBitSize, xi_a, mode);
#ifdef MCL_DUMP_JIT
return;
#endif
if (!*pb) return;
{ // set oneRep
FpT& one = *reinterpret_cast<FpT*>(op_.oneRep);
@ -157,6 +163,10 @@ public:
if (mul == 0) mul = mulC;
sqr = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_sqrA_);
if (sqr == 0) sqr = sqrC;
mul2 = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_mul2A_);
if (mul2 == 0) mul2 = mul2C;
mul9 = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_mul9A_);
if (mul9 == 0) mul9 = mul9C;
#endif
*pb = true;
}
@ -259,7 +269,7 @@ public:
{
bool isMinus = false;
*pb = false;
if (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) {
if (fp::isIoSerializeMode(ioMode)) {
const size_t n = getByteSize();
v_[op_.N - 1] = 0;
size_t readSize;
@ -295,7 +305,7 @@ public:
void save(bool *pb, OutputStream& os, int ioMode) const
{
const size_t n = getByteSize();
if (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) {
if (fp::isIoSerializeMode(ioMode)) {
if (ioMode & IoArrayRaw) {
cybozu::write(pb, os, v_, n);
} else {
@ -330,6 +340,7 @@ public:
}
/*
mode = Mod : set x mod p if sizeof(S) * n <= 64 else error
set array x as little endian
*/
template<class S>
void setArray(bool *pb, const S *x, size_t n, mcl::fp::MaskMode mode = fp::NoMask)
@ -346,6 +357,15 @@ public:
fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::MaskAndMod);
toMont();
}
/*
set (array mod p)
error if sizeof(S) * n > 64
*/
template<class S>
void setArrayMod(bool *pb, const S *x, size_t n)
{
setArray(pb, x, n, fp::Mod);
}
/*
mask x with (1 << (bitLen - 1)) - 1 if x >= p
@ -366,6 +386,54 @@ public:
b.p = &v_[0];
}
}
/*
write a value with little endian
write buf[0] = 0 and return 1 if the value is 0
return written size if success else 0
*/
size_t getLittleEndian(void *buf, size_t maxBufSize) const
{
fp::Block b;
getBlock(b);
const uint8_t *src = (const uint8_t *)b.p;
uint8_t *dst = (uint8_t *)buf;
size_t n = b.n * sizeof(b.p[0]);
while (n > 0) {
if (src[n - 1]) break;
n--;
}
if (n == 0) n = 1; // zero
if (maxBufSize < n) return 0;
for (size_t i = 0; i < n; i++) {
dst[i] = src[i];
}
return n;
}
/*
set (little endian % p)
error if bufSize > 64
*/
void setLittleEndianMod(bool *pb, const void *buf, size_t bufSize)
{
setArray(pb, (const char *)buf, bufSize, mcl::fp::Mod);
}
/*
set (big endian % p)
error if bufSize > 64
*/
void setBigEndianMod(bool *pb, const void *buf, size_t bufSize)
{
if (bufSize > 64) {
*pb = false;
return;
}
const uint8_t *p = (const uint8_t*)buf;
uint8_t swapBuf[64];
for (size_t i = 0; i < bufSize; i++) {
swapBuf[bufSize - 1 - i] = p[i];
}
setArray(pb, swapBuf, bufSize, mcl::fp::Mod);
}
void setByCSPRNG(bool *pb, fp::RandGen rg = fp::RandGen())
{
if (rg.isZero()) rg = fp::RandGen::get();
@ -374,6 +442,18 @@ public:
setArrayMask(v_, op_.N);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
void setLittleEndianMod(const void *buf, size_t bufSize)
{
bool b;
setLittleEndianMod(&b, buf, bufSize);
if (!b) throw cybozu::Exception("setLittleEndianMod");
}
void setBigEndianMod(const void *buf, size_t bufSize)
{
bool b;
setBigEndianMod(&b, buf, bufSize);
if (!b) throw cybozu::Exception("setBigEndianMod");
}
void setByCSPRNG(fp::RandGen rg = fp::RandGen())
{
bool b;
@ -419,15 +499,31 @@ public:
static inline void mulC(FpT& z, const FpT& x, const FpT& y) { op_.fp_mul(z.v_, x.v_, y.v_, op_.p); }
static void (*sqr)(FpT& y, const FpT& x);
static inline void sqrC(FpT& y, const FpT& x) { op_.fp_sqr(y.v_, x.v_, op_.p); }
static void (*mul2)(FpT& y, const FpT& x);
static inline void mul2C(FpT& y, const FpT& x) { op_.fp_mul2(y.v_, x.v_, op_.p); }
static void (*mul9)(FpT& y, const FpT& x);
static inline void mul9C(FpT& y, const FpT& x) { mulSmall(y, x, 9); }
#else
static inline void add(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); }
static inline void sub(FpT& z, const FpT& x, const FpT& y) { op_.fp_sub(z.v_, x.v_, y.v_, op_.p); }
static inline void neg(FpT& y, const FpT& x) { op_.fp_neg(y.v_, x.v_, op_.p); }
static inline void mul(FpT& z, const FpT& x, const FpT& y) { op_.fp_mul(z.v_, x.v_, y.v_, op_.p); }
static inline void sqr(FpT& y, const FpT& x) { op_.fp_sqr(y.v_, x.v_, op_.p); }
static inline void mul2(FpT& y, const FpT& x) { op_.fp_mul2(y.v_, x.v_, op_.p); }
static inline void mul9(FpT& y, const FpT& x) { mulSmall(y, x, 9); }
#endif
static inline void addPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_addPre(z.v_, x.v_, y.v_); }
static inline void subPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_subPre(z.v_, x.v_, y.v_); }
static inline void mulSmall(FpT& z, const FpT& x, const uint32_t y)
{
assert(y <= op_.smallModp.maxMulN);
Unit xy[maxSize + 1];
op_.fp_mulUnitPre(xy, x.v_, y);
int v = op_.smallModp.approxMul(xy);
const Unit *pv = op_.smallModp.getPmul(v);
op_.fp_subPre(z.v_, xy, pv);
op_.fp_sub(z.v_, z.v_, op_.p, op_.p);
}
static inline void mulUnit(FpT& z, const FpT& x, const Unit y)
{
if (mulSmallUnit(z, x, y)) return;
@ -526,9 +622,12 @@ public:
}
static void setETHserialization(bool ETHserialization)
{
if (getBitSize() != 381) return;
isETHserialization_ = ETHserialization;
}
static bool getETHserialization()
{
return isETHserialization_;
}
static inline bool isETHserialization() { return isETHserialization_; }
static inline int getIoMode() { return ioMode_; }
static inline size_t getModBitLen() { return getBitSize(); }
@ -661,10 +760,13 @@ template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::sub)(FpT& z,
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::neg)(FpT& y, const FpT& x);
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::mul)(FpT& z, const FpT& x, const FpT& y);
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::sqr)(FpT& y, const FpT& x);
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::mul2)(FpT& y, const FpT& x);
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::mul9)(FpT& y, const FpT& x);
#endif
} // mcl
#ifndef CYBOZU_DONT_USE_EXCEPTION
#ifdef CYBOZU_USE_BOOST
namespace mcl {
@ -688,6 +790,7 @@ struct hash<mcl::FpT<tag, maxBitSize> > {
CYBOZU_NAMESPACE_TR1_END } // std::tr1
#endif
#endif
#ifdef _MSC_VER
#pragma warning(pop)

@ -16,16 +16,7 @@ class FpDblT : public fp::Serializable<FpDblT<Fp> > {
Unit v_[Fp::maxSize * 2];
public:
static size_t getUnitSize() { return Fp::op_.N * 2; }
FpDblT() : v_()
{
}
FpDblT(const FpDblT& rhs)
{
const size_t n = getUnitSize();
for (size_t i = 0; i < n; i++) {
v_[i] = rhs.v_[i];
}
}
const fp::Unit *getUnit() const { return v_; }
void dump() const
{
const size_t n = getUnitSize();
@ -135,8 +126,6 @@ public:
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 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_); }
/*
mul(z, x, y) = mulPre(xy, x, y) + mod(z, xy)
*/
@ -162,16 +151,8 @@ public:
subPre = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_subPre);
if (subPre == 0) subPre = subPreC;
#endif
if (op.fpDbl_mulPreA_) {
mulPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&, const Fp&)>(op.fpDbl_mulPreA_);
} else {
mulPre = mulPreC;
}
if (op.fpDbl_sqrPreA_) {
sqrPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&)>(op.fpDbl_sqrPreA_);
} else {
sqrPre = sqrPreC;
}
mulPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&, const Fp&)>(op.fpDbl_mulPre);
sqrPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&)>(op.fpDbl_sqrPre);
}
void operator+=(const FpDblT& x) { add(*this, *this, x); }
void operator-=(const FpDblT& x) { sub(*this, *this, x); }
@ -246,12 +227,14 @@ public:
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);
static void (*mul2)(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); }
static void mul2(Fp2T& y, const Fp2T& x) { mul2C(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); }
@ -389,11 +372,16 @@ public:
}
static uint32_t get_xi_a() { return Fp::getOp().xi_a; }
static void init()
static void init(bool *pb)
{
// assert(Fp::maxSize <= 256);
mcl::fp::Op& op = Fp::op_;
assert(op.xi_a);
// assume p < W/4 where W = 1 << (N * sizeof(Unit) * 8)
if ((op.p[op.N - 1] >> (sizeof(fp::Unit) * 8 - 2)) != 0) {
*pb = false;
return;
}
mul_xi = 0;
#ifdef MCL_XBYAK_DIRECT_CALL
add = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_addA_);
@ -406,6 +394,8 @@ public:
if (mul == 0) mul = mulC;
sqr = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_sqrA_);
if (sqr == 0) sqr = sqrC;
mul2 = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_mul2A_);
if (mul2 == 0) mul2 = mul2C;
mul_xi = fp::func_ptr_cast<void (*)(Fp2T&, const Fp2T&)>(op.fp2_mul_xiA_);
#endif
op.fp2_inv = fp2_invW;
@ -448,6 +438,12 @@ public:
}
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
static void init()
{
bool b;
init(&b);
if (!b) throw cybozu::Exception("Fp2::init");
}
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
@ -503,38 +499,11 @@ private:
Fp::neg(y.a, x.a);
Fp::neg(y.b, x.b);
}
#if 0
/*
x = a + bi, y = c + di, i^2 = -1
z = xy = (a + bi)(c + di) = (ac - bd) + (ad + bc)i
ad+bc = (a + b)(c + d) - ac - bd
# of mod = 3
*/
static void fp2_mulW(Unit *z, const Unit *x, const Unit *y)
static void mul2C(Fp2T& y, const Fp2T& x)
{
const Fp *px = reinterpret_cast<const Fp*>(x);
const Fp *py = reinterpret_cast<const Fp*>(y);
const Fp& a = px[0];
const Fp& b = px[1];
const Fp& c = py[0];
const Fp& d = py[1];
Fp *pz = reinterpret_cast<Fp*>(z);
Fp t1, t2, ac, bd;
Fp::add(t1, a, b);
Fp::add(t2, c, d);
t1 *= t2; // (a + b)(c + d)
Fp::mul(ac, a, c);
Fp::mul(bd, b, d);
Fp::sub(pz[0], ac, bd); // ac - bd
Fp::sub(pz[1], t1, ac);
pz[1] -= bd;
}
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);
Fp::mul2(y.a, x.a);
Fp::mul2(y.b, x.b);
}
#endif
static void mulC(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
Fp2Dbl d;
@ -552,7 +521,7 @@ private:
const Fp& b = x.b;
#if 1 // faster than using FpDbl
Fp t1, t2, t3;
Fp::add(t1, b, b); // 2b
Fp::mul2(t1, b);
t1 *= a; // 2ab
Fp::add(t2, a, b); // a + b
Fp::sub(t3, a, b); // a - b
@ -627,6 +596,7 @@ template<class Fp_> void (*Fp2T<Fp_>::sub)(Fp2T& z, const Fp2T& x, const Fp2T& y
template<class Fp_> void (*Fp2T<Fp_>::neg)(Fp2T& y, const Fp2T& x);
template<class Fp_> void (*Fp2T<Fp_>::mul)(Fp2T& z, const Fp2T& x, const Fp2T& y);
template<class Fp_> void (*Fp2T<Fp_>::sqr)(Fp2T& y, const Fp2T& x);
template<class Fp_> void (*Fp2T<Fp_>::mul2)(Fp2T& y, const Fp2T& x);
#endif
template<class Fp_> void (*Fp2T<Fp_>::mul_xi)(Fp2T& y, const Fp2T& x);
@ -656,20 +626,30 @@ struct Fp2DblT {
FpDbl::subPre(z.a, x.a, y.a);
FpDbl::subPre(z.b, x.b, y.b);
}
/*
imaginary part of Fp2Dbl::mul uses only add,
so it does not require mod.
*/
static void subSpecial(Fp2DblT& y, const Fp2DblT& x)
{
FpDbl::sub(y.a, y.a, x.a);
FpDbl::subPre(y.b, y.b, x.b);
}
static void neg(Fp2DblT& y, const Fp2DblT& x)
{
FpDbl::neg(y.a, x.a);
FpDbl::neg(y.b, x.b);
}
static void mul_xi(Fp2DblT& y, const Fp2DblT& x)
static void mul_xi_1C(Fp2DblT& y, const Fp2DblT& x)
{
const uint32_t xi_a = Fp2::get_xi_a();
if (xi_a == 1) {
FpDbl t;
FpDbl::add(t, x.a, x.b);
FpDbl::sub(y.a, x.a, x.b);
y.b = t;
} else {
}
static void mul_xi_genericC(Fp2DblT& y, const Fp2DblT& x)
{
const uint32_t xi_a = Fp2::get_xi_a();
FpDbl t;
FpDbl::mulUnit(t, x.a, xi_a);
FpDbl::sub(t, t, x.b);
@ -677,9 +657,9 @@ struct Fp2DblT {
FpDbl::add(y.b, y.b, x.a);
y.a = t;
}
}
static void (*mulPre)(Fp2DblT&, const Fp2&, const Fp2&);
static void (*sqrPre)(Fp2DblT&, const Fp2&);
static void (*mul_xi)(Fp2DblT&, const Fp2DblT&);
static void mod(Fp2& y, const Fp2DblT& x)
{
FpDbl::mod(y.a, x.a);
@ -695,33 +675,38 @@ struct Fp2DblT {
void operator-=(const Fp2DblT& x) { sub(*this, *this, x); }
static void init()
{
assert(!Fp::getOp().isFullBit);
const mcl::fp::Op& op = Fp::getOp();
if (op.fp2Dbl_mulPreA_) {
mulPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&, const Fp2&)>(op.fp2Dbl_mulPreA_);
} else {
if (op.isFullBit) {
mulPre = fp2Dbl_mulPreW<true>;
} else {
mulPre = fp2Dbl_mulPreW<false>;
}
mulPre = fp2Dbl_mulPreW;
}
if (op.fp2Dbl_sqrPreA_) {
sqrPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&)>(op.fp2Dbl_sqrPreA_);
} else {
if (op.isFullBit) {
sqrPre = fp2Dbl_sqrPreW<true>;
} else {
sqrPre = fp2Dbl_sqrPreW<false>;
sqrPre = fp2Dbl_sqrPreW;
}
const uint32_t xi_a = Fp2::get_xi_a();
switch (xi_a) {
case 1:
mul_xi = mul_xi_1C;
if (op.fp2Dbl_mul_xiA_) {
mul_xi = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2DblT&)>(op.fp2Dbl_mul_xiA_);
}
break;
default:
mul_xi = mul_xi_genericC;
break;
}
}
/*
Fp2Dbl::mulPre by FpDblT
@note mod of NIST_P192 is fast
*/
template<bool isFullBit>
static void fp2Dbl_mulPreW(Fp2DblT& z, const Fp2& x, const Fp2& y)
{
assert(!Fp::getOp().isFullBit);
const Fp& a = x.a;
const Fp& b = x.b;
const Fp& c = y.a;
@ -730,36 +715,21 @@ struct Fp2DblT {
FpDbl& d1 = z.b;
FpDbl d2;
Fp s, t;
if (isFullBit) {
Fp::add(s, a, b);
Fp::add(t, c, d);
} else {
Fp::addPre(s, a, b);
Fp::addPre(t, c, d);
}
FpDbl::mulPre(d1, s, t); // (a + b)(c + d)
FpDbl::mulPre(d0, a, c);
FpDbl::mulPre(d2, b, d);
if (isFullBit) {
FpDbl::sub(d1, d1, d0); // (a + b)(c + d) - ac
FpDbl::sub(d1, d1, d2); // (a + b)(c + d) - ac - bd
} else {
FpDbl::subPre(d1, d1, d0);
FpDbl::subPre(d1, d1, d2);
}
FpDbl::sub(d0, d0, d2); // ac - bd
}
template<bool isFullBit>
static void fp2Dbl_sqrPreW(Fp2DblT& y, const Fp2& x)
{
assert(!Fp::getOp().isFullBit);
Fp t1, t2;
if (isFullBit) {
Fp::add(t1, x.b, x.b); // 2b
Fp::add(t2, x.a, x.b); // a + b
} else {
Fp::addPre(t1, x.b, x.b); // 2b
Fp::addPre(t2, x.a, x.b); // a + b
}
FpDbl::mulPre(y.b, t1, x.a); // 2ab
Fp::sub(t1, x.a, x.b); // a - b
FpDbl::mulPre(y.a, t1, t2); // (a + b)(a - b)
@ -768,6 +738,7 @@ struct Fp2DblT {
template<class Fp> void (*Fp2DblT<Fp>::mulPre)(Fp2DblT&, const Fp2T<Fp>&, const Fp2T<Fp>&);
template<class Fp> void (*Fp2DblT<Fp>::sqrPre)(Fp2DblT&, const Fp2T<Fp>&);
template<class Fp> void (*Fp2DblT<Fp>::mul_xi)(Fp2DblT<Fp>&, const Fp2DblT<Fp>&);
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g[Fp2T<Fp>::gN];
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g2[Fp2T<Fp>::gN];
@ -889,34 +860,24 @@ struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
Fp2::neg(y.b, x.b);
Fp2::neg(y.c, x.c);
}
/*
x = a + bv + cv^2, v^3 = xi
x^2 = (a^2 + 2bc xi) + (c^2 xi + 2ab)v + (b^2 + 2ac)v^2
b^2 + 2ac = (a + b + c)^2 - a^2 - 2bc - c^2 - 2ab
*/
static void mul2(Fp6T& y, const Fp6T& x)
{
Fp2::mul2(y.a, x.a);
Fp2::mul2(y.b, x.b);
Fp2::mul2(y.c, x.c);
}
static void sqr(Fp6T& y, const Fp6T& x)
{
Fp2 t1, t2, t3;
Fp2::mul(t1, x.a, x.b);
t1 += t1; // 2ab
Fp2::mul(t2, x.b, x.c);
t2 += t2; // 2bc
Fp2::sqr(t3, x.c); // c^2
Fp2::add(y.c, x.a, x.c); // a + c, destroy y.c
y.c += x.b; // a + b + c
Fp2::sqr(y.b, y.c); // (a + b + c)^2, destroy y.b
y.b -= t2; // (a + b + c)^2 - 2bc
Fp2::mul_xi(t2, t2); // 2bc xi
Fp2::sqr(y.a, x.a); // a^2, destroy y.a
y.b -= y.a; // (a + b + c)^2 - 2bc - a^2
y.a += t2; // a^2 + 2bc xi
Fp2::sub(y.c, y.b, t3); // (a + b + c)^2 - 2bc - a^2 - c^2
Fp2::mul_xi(y.b, t3); // c^2 xi
y.b += t1; // c^2 xi + 2ab
y.c -= t1; // b^2 + 2ac
}
static inline void mul(Fp6T& z, const Fp6T& x, const Fp6T& y);
Fp6Dbl XX;
Fp6Dbl::sqrPre(XX, x);
Fp6Dbl::mod(y, XX);
}
static inline void mul(Fp6T& z, const Fp6T& x, const Fp6T& y)
{
Fp6Dbl XY;
Fp6Dbl::mulPre(XY, x, y);
Fp6Dbl::mod(z, XY);
}
/*
x = a + bv + cv^2, v^3 = xi
y = 1/x = p/q where
@ -929,27 +890,34 @@ struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
const Fp2& a = x.a;
const Fp2& b = x.b;
const Fp2& c = x.c;
Fp2 aa, bb, cc, ab, bc, ac;
Fp2::sqr(aa, a);
Fp2::sqr(bb, b);
Fp2::sqr(cc, c);
Fp2::mul(ab, a, b);
Fp2::mul(bc, b, c);
Fp2::mul(ac, c, a);
Fp2Dbl aa, bb, cc, ab, bc, ac;
Fp2Dbl::sqrPre(aa, a);
Fp2Dbl::sqrPre(bb, b);
Fp2Dbl::sqrPre(cc, c);
Fp2Dbl::mulPre(ab, a, b);
Fp2Dbl::mulPre(bc, b, c);
Fp2Dbl::mulPre(ac, c, a);
Fp6T p;
Fp2::mul_xi(p.a, bc);
Fp2::sub(p.a, aa, p.a); // a^2 - bc xi
Fp2::mul_xi(p.b, cc);
p.b -= ab; // c^2 xi - ab
Fp2::sub(p.c, bb, ac); // b^2 - ac
Fp2 q, t;
Fp2::mul(q, p.b, c);
Fp2::mul(t, p.c, b);
q += t;
Fp2::mul_xi(q, q);
Fp2::mul(t, p.a, a);
q += t;
Fp2Dbl T;
Fp2Dbl::mul_xi(T, bc);
Fp2Dbl::sub(T, aa, T); // a^2 - bc xi
Fp2Dbl::mod(p.a, T);
Fp2Dbl::mul_xi(T, cc);
Fp2Dbl::sub(T, T, ab); // c^2 xi - ab
Fp2Dbl::mod(p.b, T);
Fp2Dbl::sub(T, bb, ac); // b^2 - ac
Fp2Dbl::mod(p.c, T);
Fp2Dbl T2;
Fp2Dbl::mulPre(T, p.b, c);
Fp2Dbl::mulPre(T2, p.c, b);
Fp2Dbl::add(T, T, T2);
Fp2Dbl::mul_xi(T, T);
Fp2Dbl::mulPre(T2, p.a, a);
Fp2Dbl::addPre(T, T, T2);
Fp2 q;
Fp2Dbl::mod(q, T);
Fp2::inv(q, q);
Fp2::mul(y.a, p.a, q);
@ -962,6 +930,7 @@ template<class Fp>
struct Fp6DblT {
typedef Fp2T<Fp> Fp2;
typedef Fp6T<Fp> Fp6;
typedef FpDblT<Fp> FpDbl;
typedef Fp2DblT<Fp> Fp2Dbl;
typedef Fp6DblT<Fp> Fp6Dbl;
typedef fp::Unit Unit;
@ -984,51 +953,75 @@ struct Fp6DblT {
bf + ce = (b + c)(e + f) - be - cf
ae + bd = (a + b)(e + d) - ad - be
af + cd = (a + c)(d + f) - ad - cf
assum p < W/4 where W = 1 << (sizeof(Unit) * 8 * N)
then (b + c)(e + f) < 4p^2 < pW
*/
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& ZA = z.a;
Fp2Dbl& ZB = z.b;
Fp2Dbl& ZC = z.c;
Fp2 t1, t2;
Fp2Dbl BE, CF, AD;
Fp2::addPre(t1, b, c);
Fp2::addPre(t2, e, f);
Fp2Dbl::mulPre(ZA, t1, t2);
Fp2::addPre(t1, a, b);
Fp2::addPre(t2, e, d);
Fp2Dbl::mulPre(ZB, t1, t2);
Fp2::addPre(t1, a, c);
Fp2::addPre(t2, d, f);
Fp2Dbl::mulPre(ZC, t1, t2);
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::mulPre(CF, c, f);
Fp2Dbl::mulPre(AD, a, d);
Fp2Dbl::subSpecial(ZA, BE);
Fp2Dbl::subSpecial(ZA, CF);
Fp2Dbl::subSpecial(ZB, AD);
Fp2Dbl::subSpecial(ZB, BE);
Fp2Dbl::subSpecial(ZC, AD);
Fp2Dbl::subSpecial(ZC, CF);
Fp2Dbl::mul_xi(ZA, ZA);
Fp2Dbl::add(ZA, ZA, AD);
Fp2Dbl::mul_xi(CF, CF);
Fp2Dbl::add(ZB, ZB, CF);
Fp2Dbl::add(ZC, ZC, BE);
}
/*
x = a + bv + cv^2, v^3 = xi
x^2 = (a^2 + 2bc xi) + (c^2 xi + 2ab)v + (b^2 + 2ac)v^2
Fp2Dbl::add(za, za, T1);
Fp2Dbl::mul_xi(zb, zb);
Fp2Dbl::add(zb, zb, T2);
Fp2Dbl::add(zc, zc, BE);
//clk.end();
b^2 + 2ac = (a + b + c)^2 - a^2 - 2bc - c^2 - 2ab
*/
static void sqrPre(Fp6DblT& y, const Fp6& x)
{
const Fp2& a = x.a;
const Fp2& b = x.b;
const Fp2& c = x.c;
Fp2 t;
Fp2Dbl BC2, AB2, AA, CC, T;
Fp2::mul2(t, b);
Fp2Dbl::mulPre(BC2, t, c); // 2bc
Fp2Dbl::mulPre(AB2, t, a); // 2ab
Fp2Dbl::sqrPre(AA, a);
Fp2Dbl::sqrPre(CC, c);
Fp2::add(t, a, b);
Fp2::add(t, t, c);
Fp2Dbl::sqrPre(T, t); // (a + b + c)^2
Fp2Dbl::sub(T, T, AA);
Fp2Dbl::sub(T, T, BC2);
Fp2Dbl::sub(T, T, CC);
Fp2Dbl::sub(y.c, T, AB2);
Fp2Dbl::mul_xi(BC2, BC2);
Fp2Dbl::add(y.a, AA, BC2);
Fp2Dbl::mul_xi(CC, CC);
Fp2Dbl::add(y.b, CC, AB2);
}
static void mod(Fp6& y, const Fp6Dbl& x)
{
@ -1038,14 +1031,6 @@ struct Fp6DblT {
}
};
template<class Fp>
inline void Fp6T<Fp>::mul(Fp6T<Fp>& z, const Fp6T<Fp>& x, const Fp6T<Fp>& y)
{
Fp6DblT<Fp> Z;
Fp6DblT<Fp>::mulPre(Z, x, y);
Fp6DblT<Fp>::mod(z, Z);
}
/*
Fp12T = Fp6[w] / (w^2 - v)
x = a + b w
@ -1148,7 +1133,6 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
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);
@ -1158,15 +1142,6 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
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
@ -1182,7 +1157,7 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
mulVadd(t1, b, a); // bv + a
t0 *= t1; // (a + b)(bv + a)
Fp6::mul(t1, a, b); // ab
Fp6::add(y.b, t1, t1); // 2ab
Fp6::mul2(y.b, t1); // 2ab
mulVadd(y.a, t1, t1); // abv + ab
Fp6::sub(y.a, t0, y.a);
}
@ -1194,16 +1169,18 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
{
const Fp6& a = x.a;
const Fp6& b = x.b;
Fp6 t0, t1;
Fp6::sqr(t0, a);
Fp6::sqr(t1, b);
Fp2::mul_xi(t1.c, t1.c);
t0.a -= t1.c;
t0.b -= t1.a;
t0.c -= t1.b; // t0 = a^2 - b^2v
Fp6::inv(t0, t0);
Fp6::mul(y.a, x.a, t0);
Fp6::mul(y.b, x.b, t0);
Fp6Dbl AA, BB;
Fp6Dbl::sqrPre(AA, a);
Fp6Dbl::sqrPre(BB, b);
Fp2Dbl::mul_xi(BB.c, BB.c);
Fp2Dbl::sub(AA.a, AA.a, BB.c);
Fp2Dbl::sub(AA.b, AA.b, BB.a);
Fp2Dbl::sub(AA.c, AA.c, BB.b); // a^2 - b^2 v
Fp6 t;
Fp6Dbl::mod(t, AA);
Fp6::inv(t, t);
Fp6::mul(y.a, x.a, t);
Fp6::mul(y.b, x.b, t);
Fp6::neg(y.b, y.b);
}
/*
@ -1336,6 +1313,12 @@ struct GroupMtoA : public T {
{
T::mul(castT(z), castT(x), castT(y));
}
static void sub(GroupMtoA& z, const GroupMtoA& x, const GroupMtoA& y)
{
T r;
T::unitaryInv(r, castT(y));
T::mul(castT(z), castT(x), r);
}
static void dbl(GroupMtoA& y, const GroupMtoA& x)
{
T::sqr(castT(y), castT(x));
@ -1363,6 +1346,10 @@ struct GroupMtoA : public T {
{
add(*this, *this, rhs);
}
void operator-=(const GroupMtoA& rhs)
{
sub(*this, *this, rhs);
}
void normalize() {}
private:
bool isOne() const;

@ -10,6 +10,7 @@
#include <stdlib.h>
#include <assert.h>
#include <stdint.h>
#include <cybozu/bit_operation.hpp>
#ifndef CYBOZU_DONT_USE_EXCEPTION
#include <cybozu/exception.hpp>
#endif
@ -27,7 +28,7 @@
#define MCL_USE_VINT
#endif
#ifndef MCL_MAX_BIT_SIZE
#define MCL_MAX_BIT_SIZE 521
#define MCL_MAX_BIT_SIZE 512
#endif
#ifdef MCL_USE_VINT
#include <mcl/vint.hpp>
@ -96,7 +97,7 @@ template<class T>
void getArray(bool *pb, T *buf, size_t maxSize, const mpz_class& x)
{
#ifdef MCL_USE_VINT
*pb = getArray_(buf, maxSize, x.getUnit(), x.getUnitSize());
*pb = getArray_(buf, maxSize, x.getUnit(), (int)x.getUnitSize());
#else
*pb = getArray_(buf, maxSize, x.get_mpz_t()->_mp_d, x.get_mpz_t()->_mp_size);
#endif
@ -434,6 +435,36 @@ inline size_t getUnitSize(const mpz_class& x)
return std::abs(x.get_mpz_t()->_mp_size);
#endif
}
/*
get the number of lower zeros
*/
template<class T>
size_t getLowerZeroBitNum(const T *x, size_t n)
{
size_t ret = 0;
for (size_t i = 0; i < n; i++) {
T v = x[i];
if (v == 0) {
ret += sizeof(T) * 8;
} else {
ret += cybozu::bsf<T>(v);
break;
}
}
return ret;
}
/*
get the number of lower zero
@note x != 0
*/
inline size_t getLowerZeroBitNum(const mpz_class& x)
{
assert(!isZero(x));
return getLowerZeroBitNum(getUnit(x), getUnitSize(x));
}
inline mpz_class abs(const mpz_class& x)
{
#ifdef MCL_USE_VINT
@ -576,6 +607,53 @@ bool getNAF(Vec& v, const mpz_class& x)
}
}
/*
v = naf[i]
v = 0 or (|v| <= 2^(w-1) - 1 and odd)
*/
template<class Vec>
void getNAFwidth(bool *pb, Vec& naf, mpz_class x, size_t w)
{
assert(w > 0);
*pb = true;
naf.clear();
bool negative = false;
if (x < 0) {
negative = true;
x = -x;
}
size_t zeroNum = 0;
const int signedMaxW = 1 << (w - 1);
const int maxW = signedMaxW * 2;
const int maskW = maxW - 1;
while (!isZero(x)) {
size_t z = gmp::getLowerZeroBitNum(x);
if (z) {
x >>= z;
zeroNum += z;
}
for (size_t i = 0; i < zeroNum; i++) {
naf.push(pb, 0);
if (!*pb) return;
}
assert(!isZero(x));
int v = getUnit(x)[0] & maskW;
x >>= w;
if (v & signedMaxW) {
x++;
v -= maxW;
}
naf.push(pb, typename Vec::value_type(v));
if (!*pb) return;
zeroNum = w - 1;
}
if (negative) {
for (size_t i = 0; i < naf.size(); i++) {
naf[i] = -naf[i];
}
}
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
inline void setStr(mpz_class& z, const std::string& str, int base = 0)
{
@ -864,6 +942,85 @@ public:
#endif
};
/*
x mod p for a small value x < (pMulTblN * p).
*/
struct SmallModp {
typedef mcl::fp::Unit Unit;
static const size_t unitBitSize = sizeof(Unit) * 8;
static const size_t maxTblSize = (MCL_MAX_BIT_SIZE + unitBitSize - 1) / unitBitSize + 1;
static const size_t maxMulN = 9;
static const size_t pMulTblN = maxMulN + 1;
uint32_t N_;
uint32_t shiftL_;
uint32_t shiftR_;
uint32_t maxIdx_;
// pMulTbl_[i] = (p * i) >> (pBitSize_ - 1)
Unit pMulTbl_[pMulTblN][maxTblSize];
// idxTbl_[x] = (x << (pBitSize_ - 1)) / p
uint8_t idxTbl_[pMulTblN * 2];
// return x >> (pBitSize_ - 1)
SmallModp()
: N_(0)
, shiftL_(0)
, shiftR_(0)
, maxIdx_(0)
, pMulTbl_()
, idxTbl_()
{
}
// return argmax { i : x > i * p }
uint32_t approxMul(const Unit *x) const
{
uint32_t top = getTop(x);
assert(top <= maxIdx_);
return idxTbl_[top];
}
const Unit *getPmul(size_t v) const
{
assert(v < pMulTblN);
return pMulTbl_[v];
}
uint32_t getTop(const Unit *x) const
{
return (x[N_ - 1] >> shiftR_) | (x[N_] << shiftL_);
}
uint32_t cvtInt(const mpz_class& x) const
{
assert(mcl::gmp::getUnitSize(x) <= 1);
if (x == 0) {
return 0;
} else {
return uint32_t(mcl::gmp::getUnit(x)[0]);
}
}
void init(const mpz_class& p)
{
size_t pBitSize = mcl::gmp::getBitSize(p);
N_ = uint32_t((pBitSize + unitBitSize - 1) / unitBitSize);
shiftR_ = (pBitSize - 1) % unitBitSize;
shiftL_ = unitBitSize - shiftR_;
mpz_class t = 0;
for (size_t i = 0; i < pMulTblN; i++) {
bool b;
mcl::gmp::getArray(&b, pMulTbl_[i], maxTblSize, t);
assert(b);
(void)b;
if (i == pMulTblN - 1) {
maxIdx_ = getTop(pMulTbl_[i]);
assert(maxIdx_ < CYBOZU_NUM_OF_ARRAY(idxTbl_));
break;
}
t += p;
}
for (uint32_t i = 0; i <= maxIdx_; i++) {
idxTbl_[i] = cvtInt((mpz_class(int(i)) << (pBitSize - 1)) / p);
}
}
};
/*
Barrett Reduction
for non GMP version

@ -77,12 +77,18 @@ int mclBn_init(int curve, int compiledTimeVar)
initG1only(&b, *para);
return b ? 0 : -1;
}
const mcl::CurveParam& cp = mcl::getCurveParam(curve);
const mcl::CurveParam* cp = mcl::getCurveParam(curve);
if (cp == 0) return -1;
bool b;
initPairing(&b, cp);
initPairing(&b, *cp);
return b ? 0 : -1;
}
int mclBn_getCurveType()
{
return mcl::bn::BN::param.cp.curveType;
}
int mclBn_getOpUnitSize()
{
return (int)Fp::getUnitSize() * sizeof(mcl::fp::Unit) / sizeof(uint64_t);
@ -113,9 +119,21 @@ mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize)
return Fp::getModulo(buf, maxBufSize);
}
void mclBn_setETHserialization(int ETHserialization)
void mclBn_setETHserialization(int enable)
{
if (mclBn_getCurveType() != MCL_BLS12_381) return;
Fp::setETHserialization(enable == 1);
Fr::setETHserialization(enable == 1);
}
int mclBn_getETHserialization()
{
return Fp::getETHserialization() ? 1 : 0;
}
int mclBn_setMapToMode(int mode)
{
Fp::setETHserialization(ETHserialization == 1);
return setMapToMode(mode) ? 0 : -1;
}
////////////////////////////////////////////////
@ -144,6 +162,17 @@ int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize)
cast(x)->setArrayMask((const char *)buf, bufSize);
return 0;
}
int mclBnFr_setBigEndianMod(mclBnFr *x, const void *buf, mclSize bufSize)
{
bool b;
cast(x)->setBigEndianMod(&b, buf, bufSize);
return b ? 0 : -1;
}
mclSize mclBnFr_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFr *x)
{
return cast(x)->getLittleEndian(buf, maxBufSize);
}
int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize)
{
bool b;
@ -171,6 +200,14 @@ int mclBnFr_isOne(const mclBnFr *x)
{
return cast(x)->isOne();
}
int mclBnFr_isOdd(const mclBnFr *x)
{
return cast(x)->isOdd();
}
int mclBnFr_isNegative(const mclBnFr *x)
{
return cast(x)->isNegative();
}
#ifndef MCL_DONT_USE_CSRPNG
int mclBnFr_setByCSPRNG(mclBnFr *x)
@ -179,6 +216,12 @@ int mclBnFr_setByCSPRNG(mclBnFr *x)
cast(x)->setByCSPRNG(&b);
return b ? 0 : -1;
}
int mclBnFp_setByCSPRNG(mclBnFp *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);
@ -230,6 +273,77 @@ void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y)
Fr::div(*cast(z),*cast(x), *cast(y));
}
void mclBnFp_neg(mclBnFp *y, const mclBnFp *x)
{
Fp::neg(*cast(y), *cast(x));
}
void mclBnFp_inv(mclBnFp *y, const mclBnFp *x)
{
Fp::inv(*cast(y), *cast(x));
}
void mclBnFp_sqr(mclBnFp *y, const mclBnFp *x)
{
Fp::sqr(*cast(y), *cast(x));
}
void mclBnFp_add(mclBnFp *z, const mclBnFp *x, const mclBnFp *y)
{
Fp::add(*cast(z),*cast(x), *cast(y));
}
void mclBnFp_sub(mclBnFp *z, const mclBnFp *x, const mclBnFp *y)
{
Fp::sub(*cast(z),*cast(x), *cast(y));
}
void mclBnFp_mul(mclBnFp *z, const mclBnFp *x, const mclBnFp *y)
{
Fp::mul(*cast(z),*cast(x), *cast(y));
}
void mclBnFp_div(mclBnFp *z, const mclBnFp *x, const mclBnFp *y)
{
Fp::div(*cast(z),*cast(x), *cast(y));
}
void mclBnFp2_neg(mclBnFp2 *y, const mclBnFp2 *x)
{
Fp2::neg(*cast(y), *cast(x));
}
void mclBnFp2_inv(mclBnFp2 *y, const mclBnFp2 *x)
{
Fp2::inv(*cast(y), *cast(x));
}
void mclBnFp2_sqr(mclBnFp2 *y, const mclBnFp2 *x)
{
Fp2::sqr(*cast(y), *cast(x));
}
void mclBnFp2_add(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y)
{
Fp2::add(*cast(z),*cast(x), *cast(y));
}
void mclBnFp2_sub(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y)
{
Fp2::sub(*cast(z),*cast(x), *cast(y));
}
void mclBnFp2_mul(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y)
{
Fp2::mul(*cast(z),*cast(x), *cast(y));
}
void mclBnFp2_div(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y)
{
Fp2::div(*cast(z),*cast(x), *cast(y));
}
int mclBnFr_squareRoot(mclBnFr *y, const mclBnFr *x)
{
return Fr::squareRoot(*cast(y), *cast(x)) ? 0 : -1;
}
int mclBnFp_squareRoot(mclBnFp *y, const mclBnFp *x)
{
return Fp::squareRoot(*cast(y), *cast(x)) ? 0 : -1;
}
int mclBnFp2_squareRoot(mclBnFp2 *y, const mclBnFp2 *x)
{
return Fp2::squareRoot(*cast(y), *cast(x)) ? 0 : -1;
}
////////////////////////////////////////////////
// set zero
void mclBnG1_clear(mclBnG1 *x)
@ -443,6 +557,10 @@ void mclBnGT_neg(mclBnGT *y, const mclBnGT *x)
Fp12::neg(*cast(y), *cast(x));
}
void mclBnGT_inv(mclBnGT *y, const mclBnGT *x)
{
Fp12::unitaryInv(*cast(y), *cast(x));
}
void mclBnGT_invGeneric(mclBnGT *y, const mclBnGT *x)
{
Fp12::inv(*cast(y), *cast(x));
}
@ -476,6 +594,19 @@ void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y)
Fp12::powGeneric(*cast(z), *cast(x), *cast(y));
}
void mclBnG1_mulVec(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y, mclSize n)
{
G1::mulVec(*cast(z), cast(x), cast(y), n);
}
void mclBnG2_mulVec(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y, mclSize n)
{
G2::mulVec(*cast(z), cast(x), cast(y), n);
}
void mclBnGT_powVec(mclBnGT *z, const mclBnGT *x, const mclBnFr *y, mclSize n)
{
GT::powVec(*cast(z), cast(x), cast(y), n);
}
void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y)
{
pairing(*cast(z), *cast(x), *cast(y));
@ -488,6 +619,10 @@ void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y)
{
millerLoop(*cast(z), *cast(x), *cast(y));
}
void mclBn_millerLoopVec(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y, mclSize n)
{
millerLoopVec(*cast(z), cast(x), cast(y), n);
}
int mclBn_getUint64NumToPrecompute(void)
{
return int(BN::param.precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t));
@ -560,6 +695,15 @@ void mclBn_verifyOrderG2(int doVerify)
verifyOrderG2(doVerify != 0);
}
void mclBnFp_setInt(mclBnFp *y, mclInt x)
{
*cast(y) = x;
}
void mclBnFp_setInt32(mclBnFp *y, int x)
{
*cast(y) = x;
}
mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode)
{
return cast(x)->getStr(buf, maxBufSize, ioMode);
@ -592,13 +736,45 @@ int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize)
int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize)
{
bool b;
cast(x)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod);
cast(x)->setLittleEndianMod(&b, buf, bufSize);
return b ? 0 : -1;
}
int mclBnFp_setBigEndianMod(mclBnFp *x, const void *buf, mclSize bufSize)
{
bool b;
cast(x)->setBigEndianMod(&b, buf, bufSize);
return b ? 0 : -1;
}
mclSize mclBnFp_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFp *x)
{
return cast(x)->getLittleEndian(buf, maxBufSize);
}
int mclBnFp_isValid(const mclBnFp *x)
{
return cast(x)->isValid();
}
int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y)
{
return *cast(x) == *cast(y);
}
int mclBnFp_isZero(const mclBnFp *x)
{
return cast(x)->isZero();
}
int mclBnFp_isOne(const mclBnFp *x)
{
return cast(x)->isOne();
}
int mclBnFp_isOdd(const mclBnFp *x)
{
return cast(x)->isOdd();
}
int mclBnFp_isNegative(const mclBnFp *x)
{
return cast(x)->isNegative();
}
int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize)
{
@ -632,6 +808,14 @@ int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y)
{
return *cast(x) == *cast(y);
}
int mclBnFp2_isZero(const mclBnFp2 *x)
{
return cast(x)->isZero();
}
int mclBnFp2_isOne(const mclBnFp2 *x)
{
return cast(x)->isOne();
}
int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x)
{

@ -0,0 +1,572 @@
#pragma once
/**
@file
@brief map to G2 on BLS12-381 (must be included from mcl/bn.hpp)
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
ref. https://eprint.iacr.org/2019/403 , https://github.com/algorand/bls_sigs_ref
*/
namespace mcl {
namespace local {
// y^2 = x^3 + 4(1 + i)
template<class F>
struct PointT {
typedef F Fp;
F x, y, z;
static F a_;
static F b_;
static int specialA_;
bool isZero() const
{
return z.isZero();
}
void clear()
{
x.clear();
y.clear();
z.clear();
}
bool isEqual(const PointT<F>& rhs) const
{
return ec::isEqualJacobi(*this, rhs);
}
};
template<class F> F PointT<F>::a_;
template<class F> F PointT<F>::b_;
template<class F> int PointT<F>::specialA_;
} // mcl::local
template<class Fp, class G1, class Fp2, class G2>
struct MapTo_WB19 {
typedef local::PointT<Fp> E1;
typedef local::PointT<Fp2> E2;
mpz_class sqrtConst; // (p^2 - 9) / 16
Fp2 g2A;
Fp2 g2B;
Fp2 root4[4];
Fp2 etas[4];
Fp2 xnum[4];
Fp2 xden[3];
Fp2 ynum[4];
Fp2 yden[4];
Fp g1A, g1B, g1c1, g1c2;
Fp g1xnum[12];
Fp g1xden[11];
Fp g1ynum[16];
Fp g1yden[16];
mpz_class g1cofactor;
int g1Z;
void init()
{
bool b;
g2A.a = 0;
g2A.b = 240;
g2B.a = 1012;
g2B.b = 1012;
E1::a_.clear();
E1::b_ = 4;
E1::specialA_ = ec::Zero;
E2::a_.clear();
E2::b_.a = 4;
E2::b_.b = 4;
E2::specialA_ = ec::Zero;
sqrtConst = Fp::getOp().mp;
sqrtConst *= sqrtConst;
sqrtConst -= 9;
sqrtConst /= 16;
const char *rv1Str = "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09";
root4[0].a = 1;
root4[0].b.clear();
root4[1].a.clear();
root4[1].b = 1;
root4[2].a.setStr(&b, rv1Str);
assert(b); (void)b;
root4[2].b = root4[2].a;
root4[3].a = root4[2].a;
Fp::neg(root4[3].b, root4[3].a);
const char *ev1Str = "0x699be3b8c6870965e5bf892ad5d2cc7b0e85a117402dfd83b7f4a947e02d978498255a2aaec0ac627b5afbdf1bf1c90";
const char *ev2Str = "0x8157cd83046453f5dd0972b6e3949e4288020b5b8a9cc99ca07e27089a2ce2436d965026adad3ef7baba37f2183e9b5";
const char *ev3Str = "0xab1c2ffdd6c253ca155231eb3e71ba044fd562f6f72bc5bad5ec46a0b7a3b0247cf08ce6c6317f40edbc653a72dee17";
const char *ev4Str = "0xaa404866706722864480885d68ad0ccac1967c7544b447873cc37e0181271e006df72162a3d3e0287bf597fbf7f8fc1";
Fp& ev1 = etas[0].a;
Fp& ev2 = etas[0].b;
Fp& ev3 = etas[2].a;
Fp& ev4 = etas[2].b;
ev1.setStr(&b, ev1Str);
assert(b); (void)b;
ev2.setStr(&b, ev2Str);
assert(b); (void)b;
Fp::neg(etas[1].a, ev2);
etas[1].b = ev1;
ev3.setStr(&b, ev3Str);
assert(b); (void)b;
ev4.setStr(&b, ev4Str);
assert(b); (void)b;
Fp::neg(etas[3].a, ev4);
etas[3].b = ev3;
init_iso3();
{
const char *A = "0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d";
const char *B = "0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0";
const char *c1 = "0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaaa";
const char *c2 = "0x3d689d1e0e762cef9f2bec6130316806b4c80eda6fc10ce77ae83eab1ea8b8b8a407c9c6db195e06f2dbeabc2baeff5";
g1A.setStr(&b, A);
assert(b); (void)b;
g1B.setStr(&b, B);
assert(b); (void)b;
g1c1.setStr(&b, c1);
assert(b); (void)b;
g1c2.setStr(&b, c2);
assert(b); (void)b;
g1Z = 11;
gmp::setStr(&b, g1cofactor, "d201000000010001", 16);
assert(b); (void)b;
}
init_iso11();
}
void initArray(Fp *dst, const char **s, size_t n) const
{
bool b;
for (size_t i = 0; i < n; i++) {
dst[i].setStr(&b, s[i]);
assert(b);
(void)b;
}
}
void init_iso3()
{
const char *tbl[] = {
"0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6",
"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a",
"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e",
"0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d",
"0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f",
"0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706",
"0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be",
"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c",
"0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f",
"0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99",
};
bool b;
xnum[0].a.setStr(&b, tbl[0]); assert(b); (void)b;
xnum[0].b = xnum[0].a;
xnum[1].a.clear();
xnum[1].b.setStr(&b, tbl[1]); assert(b); (void)b;
xnum[2].a.setStr(&b, tbl[2]); assert(b); (void)b;
xnum[2].b.setStr(&b, tbl[3]); assert(b); (void)b;
xnum[3].a.setStr(&b, tbl[4]); assert(b); (void)b;
xnum[3].b.clear();
xden[0].a.clear();
xden[0].b.setStr(&b, tbl[5]); assert(b); (void)b;
xden[1].a = 0xc;
xden[1].b.setStr(&b, tbl[6]); assert(b); (void)b;
xden[2].a = 1;
xden[2].b = 0;
ynum[0].a.setStr(&b, tbl[7]); assert(b); (void)b;
ynum[0].b = ynum[0].a;
ynum[1].a.clear();
ynum[1].b.setStr(&b, tbl[8]); assert(b); (void)b;
ynum[2].a.setStr(&b, tbl[9]); assert(b); (void)b;
ynum[2].b.setStr(&b, tbl[10]); assert(b); (void)b;
ynum[3].a.setStr(&b, tbl[11]); assert(b); (void)b;
ynum[3].b.clear();
yden[0].a.setStr(&b, tbl[12]); assert(b); (void)b;
yden[0].b = yden[0].a;
yden[1].a.clear();
yden[1].b.setStr(&b, tbl[13]); assert(b); (void)b;
yden[2].a = 0x12;
yden[2].b.setStr(&b, tbl[14]); assert(b); (void)b;
yden[3].a = 1;
yden[3].b.clear();
}
void init_iso11()
{
const char *xnumStr[] = {
"0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7",
"0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb",
"0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0",
"0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861",
"0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9",
"0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983",
"0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84",
"0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e",
"0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317",
"0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e",
"0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b",
"0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229",
};
const char *xdenStr[] = {
"0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c",
"0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff",
"0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19",
"0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8",
"0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e",
"0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5",
"0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a",
"0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e",
"0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641",
"0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a",
"0x1",
};
const char *ynumStr[] = {
"0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33",
"0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696",
"0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6",
"0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb",
"0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb",
"0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0",
"0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2",
"0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29",
"0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587",
"0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30",
"0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132",
"0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e",
"0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8",
"0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133",
"0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b",
"0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604",
};
const char *ydenStr[] = {
"0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1",
"0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d",
"0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2",
"0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416",
"0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d",
"0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac",
"0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c",
"0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9",
"0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a",
"0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55",
"0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8",
"0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092",
"0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc",
"0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7",
"0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f",
"0x1",
};
initArray(g1xnum, xnumStr, CYBOZU_NUM_OF_ARRAY(xnumStr));
initArray(g1xden, xdenStr, CYBOZU_NUM_OF_ARRAY(xdenStr));
initArray(g1ynum, ynumStr, CYBOZU_NUM_OF_ARRAY(ynumStr));
initArray(g1yden, ydenStr, CYBOZU_NUM_OF_ARRAY(ydenStr));
}
template<class F, size_t N>
void evalPoly(F& y, const F& x, const F *zpows, const F (&cof)[N]) const
{
y = cof[N - 1]; // always zpows[0] = 1
for (size_t i = 1; i < N; i++) {
y *= x;
F t;
F::mul(t, zpows[i - 1], cof[N - 1 - i]);
y += t;
}
}
// refer (xnum, xden, ynum, yden)
void iso3(G2& Q, const E2& P) const
{
Fp2 zpows[3];
Fp2::sqr(zpows[0], P.z);
Fp2::sqr(zpows[1], zpows[0]);
Fp2::mul(zpows[2], zpows[1], zpows[0]);
Fp2 mapvals[4];
evalPoly(mapvals[0], P.x, zpows, xnum);
evalPoly(mapvals[1], P.x, zpows, xden);
evalPoly(mapvals[2], P.x, zpows, ynum);
evalPoly(mapvals[3], P.x, zpows, yden);
mapvals[1] *= zpows[0];
mapvals[2] *= P.y;
mapvals[3] *= zpows[0];
mapvals[3] *= P.z;
Fp2::mul(Q.z, mapvals[1], mapvals[3]);
Fp2::mul(Q.x, mapvals[0], mapvals[3]);
Q.x *= Q.z;
Fp2 t;
Fp2::sqr(t, Q.z);
Fp2::mul(Q.y, mapvals[2], mapvals[1]);
Q.y *= t;
}
template<class X, class C, size_t N>
X evalPoly2(const X& x, const C (&c)[N]) const
{
X ret = c[N - 1];
for (size_t i = 1; i < N; i++) {
ret *= x;
ret += c[N - 1 - i];
}
return ret;
}
// refer (g1xnum, g1xden, g1ynum, g1yden)
void iso11(G1& Q, E1& P) const
{
ec::normalizeJacobi(P);
Fp xn, xd, yn, yd;
xn = evalPoly2(P.x, g1xnum);
xd = evalPoly2(P.x, g1xden);
yn = evalPoly2(P.x, g1ynum);
yd = evalPoly2(P.x, g1yden);
/*
[xn/xd:y * yn/yd:1] = [xn xd yd^2:y yn xd^3 yd^2:xd yd]
=[xn yd z:y yn xd z^2:z] where z = xd yd
*/
Fp::mul(Q.z, xd, yd);
Fp::mul(Q.x, xn, yd);
Q.x *= Q.z;
Fp::mul(Q.y, P.y, yn);
Q.y *= xd;
Fp::sqr(xd, Q.z);
Q.y *= xd;
}
/*
xi = -2-i
(a+bi)*(-2-i) = (b-2a)-(a+2b)i
*/
void mul_xi(Fp2& y, const Fp2& x) const
{
Fp t;
Fp::sub(t, x.b, x.a);
t -= x.a;
Fp::add(y.b, x.b, x.b);
y.b += x.a;
Fp::neg(y.b, y.b);
y.a = t;
}
bool isNegSign(const Fp& x) const
{
return x.isOdd();
}
bool isNegSign(const Fp2& x) const
{
bool sign0 = isNegSign(x.a);
bool zero0 = x.a.isZero();
bool sign1 = isNegSign(x.b);
return sign0 || (zero0 & sign1);
}
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-07#appendix-D.3.5
void sswuG1(Fp& xn, Fp& xd, Fp& y, const Fp& u) const
{
const Fp& A = g1A;
const Fp& B = g1B;
const Fp& c1 = g1c1;
const Fp& c2 = g1c2;
const int Z = g1Z;
Fp u2, u2Z, t, t2, t3;
Fp::sqr(u2, u);
Fp::mulUnit(u2Z, u2, Z);
Fp::sqr(t, u2Z);
Fp::add(xd, t, u2Z);
if (xd.isZero()) {
Fp::mulUnit(xd, A, Z);
xn = B;
} else {
Fp::add(xn, xd, Fp::one());
xn *= B;
xd *= A;
Fp::neg(xd, xd);
}
Fp::sqr(t, xd);
Fp::mul(t2, t, xd);
t *= A;
Fp::sqr(t3, xn);
t3 += t;
t3 *= xn;
Fp::mul(t, t2, B);
t3 += t;
Fp::sqr(y, t2);
Fp::mul(t, t3, t2);
y *= t;
Fp::pow(y, y, c1);
y *= t;
Fp::sqr(t, y);
t *= t2;
if (t != t3) {
xn *= u2Z;
y *= c2;
y *= u2;
y *= u;
}
if (isNegSign(u) != isNegSign(y)) {
Fp::neg(y, y);
}
}
void sswuG1(E1& pt, const Fp& u) const
{
Fp xn, y;
Fp& xd = pt.z;
sswuG1(xn, xd, y, u);
Fp::mul(pt.x, xn, xd);
Fp::sqr(pt.y, xd);
pt.y *= xd;
pt.y *= y;
}
// https://github.com/algorand/bls_sigs_ref
void sswuG2(E2& P, const Fp2& t) const
{
Fp2 t2, t2xi;
Fp2::sqr(t2, t);
Fp2 den, den2;
mul_xi(t2xi, t2);
den = t2xi;
Fp2::sqr(den2, den);
// (t^2 * xi)^2 + (t^2 * xi)
den += den2;
Fp2 x0_num, x0_den;
Fp2::add(x0_num, den, 1);
x0_num *= g2B;
if (den.isZero()) {
mul_xi(x0_den, g2A);
} else {
Fp2::mul(x0_den, -g2A, den);
}
Fp2 x0_den2, x0_den3, gx0_den, gx0_num;
Fp2::sqr(x0_den2, x0_den);
Fp2::mul(x0_den3, x0_den2, x0_den);
gx0_den = x0_den3;
Fp2::mul(gx0_num, g2B, gx0_den);
Fp2 tmp, tmp1, tmp2;
Fp2::mul(tmp, g2A, x0_num);
tmp *= x0_den2;
gx0_num += tmp;
Fp2::sqr(tmp, x0_num);
tmp *= x0_num;
gx0_num += tmp;
Fp2::sqr(tmp1, gx0_den); // x^2
Fp2::sqr(tmp2, tmp1); // x^4
tmp1 *= tmp2;
tmp1 *= gx0_den; // x^7
Fp2::mul(tmp2, gx0_num, tmp1);
tmp1 *= tmp2;
tmp1 *= gx0_den;
Fp2 candi;
Fp2::pow(candi, tmp1, sqrtConst);
candi *= tmp2;
bool isNegT = isNegSign(t);
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(root4); i++) {
Fp2::mul(P.y, candi, root4[i]);
Fp2::sqr(tmp, P.y);
tmp *= gx0_den;
if (tmp == gx0_num) {
if (isNegSign(P.y) != isNegT) {
Fp2::neg(P.y, P.y);
}
Fp2::mul(P.x, x0_num, x0_den);
P.y *= x0_den3;
P.z = x0_den;
return;
}
}
Fp2 x1_num, x1_den, gx1_num, gx1_den;
Fp2::mul(x1_num, t2xi, x0_num);
x1_den = x0_den;
Fp2::mul(gx1_num, den2, t2xi);
gx1_num *= gx0_num;
gx1_den = gx0_den;
candi *= t2;
candi *= t;
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(etas); i++) {
Fp2::mul(P.y, candi, etas[i]);
Fp2::sqr(tmp, P.y);
tmp *= gx1_den;
if (tmp == gx1_num) {
if (isNegSign(P.y) != isNegT) {
Fp2::neg(P.y, P.y);
}
Fp2::mul(P.x, x1_num, x1_den);
Fp2::sqr(tmp, x1_den);
P.y *= tmp;
P.y *= x1_den;
P.z = x1_den;
return;
}
}
assert(0);
}
template<class T>
void put(const T& P) const
{
const int base = 10;
printf("x=%s\n", P.x.getStr(base).c_str());
printf("y=%s\n", P.y.getStr(base).c_str());
printf("z=%s\n", P.z.getStr(base).c_str());
}
void Fp2ToG2(G2& P, const Fp2& t, const Fp2 *t2 = 0) const
{
E2 Pp;
sswuG2(Pp, t);
if (t2) {
E2 P2;
sswuG2(P2, *t2);
ec::addJacobi(Pp, Pp, P2);
}
iso3(P, Pp);
mcl::local::mulByCofactorBLS12fast(P, P);
}
void hashToFp2(Fp2 out[2], const void *msg, size_t msgSize, const void *dst, size_t dstSize) const
{
uint8_t md[256];
mcl::fp::expand_message_xmd(md, sizeof(md), msg, msgSize, dst, dstSize);
Fp *x = out[0].getFp0();
for (size_t i = 0; i < 4; i++) {
bool b;
x[i].setBigEndianMod(&b, &md[64 * i], 64);
assert(b); (void)b;
}
}
void msgToG2(G2& out, const void *msg, size_t msgSize, const void *dst, size_t dstSize) const
{
Fp2 t[2];
hashToFp2(t, msg, msgSize, dst, dstSize);
Fp2ToG2(out, t[0], &t[1]);
}
void msgToG2(G2& out, const void *msg, size_t msgSize) const
{
const char *dst = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
const size_t dstSize = strlen(dst);
msgToG2(out, msg, msgSize, dst, dstSize);
}
void FpToG1(G1& out, const Fp& u0, const Fp *u1 = 0) const
{
E1 P1;
sswuG1(P1, u0);
if (u1) {
E1 P2;
sswuG1(P2, *u1);
ec::addJacobi(P1, P1, P2);
}
iso11(out, P1);
G1::mulGeneric(out, out, g1cofactor);
}
void msgToG1(G1& out, const void *msg, size_t msgSize, const char *dst, size_t dstSize) const
{
uint8_t md[128];
mcl::fp::expand_message_xmd(md, sizeof(md), msg, msgSize, dst, dstSize);
Fp u[2];
for (size_t i = 0; i < 2; i++) {
bool b;
u[i].setBigEndianMod(&b, &md[64 * i], 64);
assert(b); (void)b;
}
FpToG1(out, u[0], &u[1]);
}
void msgToG1(G1& out, const void *msg, size_t msgSize) const
{
const char *dst = "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_POP_";
const size_t dstSize = strlen(dst);
msgToG1(out, msg, msgSize, dst, dstSize);
}
};
} // mcl

@ -14,8 +14,11 @@
#define MCL_DONT_USE_XBYAK
#define MCL_DONT_USE_OPENSSL
#endif
#if !defined(MCL_DONT_USE_XBYAK) && (defined(_WIN64) || defined(__x86_64__)) && (MCL_SIZEOF_UNIT == 8)
#if !defined(MCL_DONT_USE_XBYAK) && (defined(_WIN64) || defined(__x86_64__)) && (MCL_SIZEOF_UNIT == 8) && !defined(MCL_STATIC_CODE)
#define MCL_USE_XBYAK
#endif
#if defined(MCL_USE_XBYAK) || defined(MCL_STATIC_CODE)
#define MCL_X64_ASM
#define MCL_XBYAK_DIRECT_CALL
#endif
@ -23,7 +26,7 @@
namespace mcl {
static const int version = 0x094; /* 0xABC = A.BC */
static const int version = 0x140; /* 0xABC = A.BC */
/*
specifies available string format mode for X::setIoMode()
@ -101,16 +104,29 @@ enum IoMode {
IoSerialize = 512, // use MBS for 1-bit y
IoFixedSizeByteSeq = IoSerialize, // obsolete
IoEcProj = 1024, // projective or jacobi coordinate
IoSerializeHexStr = 2048 // printable hex string
IoSerializeHexStr = 2048, // printable hex string
IoEcAffineSerialize = 4096 // serialize [x:y]
};
namespace fp {
inline bool isIoSerializeMode(int ioMode)
{
return ioMode & (IoArray | IoArrayRaw | IoSerialize | IoEcAffineSerialize | IoSerializeHexStr);
}
const size_t UnitBitSize = sizeof(Unit) * 8;
const size_t maxUnitSize = (MCL_MAX_BIT_SIZE + UnitBitSize - 1) / UnitBitSize;
#define MCL_MAX_UNIT_SIZE ((MCL_MAX_BIT_SIZE + MCL_UNIT_BIT_SIZE - 1) / MCL_UNIT_BIT_SIZE)
const size_t maxMulVecN = 32; // inner loop of mulVec
#ifndef MCL_MAX_MUL_VEC_NGLV
#define MCL_MAX_MUL_VEC_NGLV 16
#endif
const size_t maxMulVecNGLV = MCL_MAX_MUL_VEC_NGLV; // inner loop of mulVec with GLV
struct FpGenerator;
struct Op;
@ -175,6 +191,7 @@ struct Op {
uint32_t pmod4;
mcl::SquareRoot sq;
mcl::Modp modp;
mcl::SmallModp smallModp;
Unit half[maxUnitSize]; // (p + 1) / 2
Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery)
/*
@ -189,6 +206,8 @@ struct Op {
Unit R3[maxUnitSize];
#ifdef MCL_USE_XBYAK
FpGenerator *fg;
#endif
#ifdef MCL_X64_ASM
mcl::Array<Unit> invTbl;
#endif
void3u fp_addA_;
@ -196,18 +215,20 @@ struct Op {
void2u fp_negA_;
void3u fp_mulA_;
void2u fp_sqrA_;
void2u fp_mul2A_;
void2u fp_mul9A_;
void3u fp2_addA_;
void3u fp2_subA_;
void2u fp2_negA_;
void3u fp2_mulA_;
void2u fp2_sqrA_;
void2u fp2_mul2A_;
void3u fpDbl_addA_;
void3u fpDbl_subA_;
void3u fpDbl_mulPreA_;
void2u fpDbl_sqrPreA_;
void2u fpDbl_modA_;
void3u fp2Dbl_mulPreA_;
void2u fp2Dbl_sqrPreA_;
void2u fp2Dbl_mul_xiA_;
size_t maxN;
size_t N;
size_t bitSize;
@ -220,6 +241,7 @@ struct Op {
void4u fp_sub;
void4u fp_mul;
void3u fp_sqr;
void3u fp_mul2;
void2uOp fp_invOp;
void2uIu fp_mulUnit; // fpN1_mod + fp_mulUnitPre
@ -275,7 +297,7 @@ struct Op {
memset(one, 0, sizeof(one));
memset(R2, 0, sizeof(R2));
memset(R3, 0, sizeof(R3));
#ifdef MCL_USE_XBYAK
#ifdef MCL_X64_ASM
invTbl.clear();
#endif
fp_addA_ = 0;
@ -283,18 +305,20 @@ struct Op {
fp_negA_ = 0;
fp_mulA_ = 0;
fp_sqrA_ = 0;
fp_mul2A_ = 0;
fp_mul9A_ = 0;
fp2_addA_ = 0;
fp2_subA_ = 0;
fp2_negA_ = 0;
fp2_mulA_ = 0;
fp2_sqrA_ = 0;
fp2_mul2A_ = 0;
fpDbl_addA_ = 0;
fpDbl_subA_ = 0;
fpDbl_mulPreA_ = 0;
fpDbl_sqrPreA_ = 0;
fpDbl_modA_ = 0;
fp2Dbl_mulPreA_ = 0;
fp2Dbl_sqrPreA_ = 0;
fp2Dbl_mul_xiA_ = 0;
maxN = 0;
N = 0;
bitSize = 0;
@ -307,6 +331,7 @@ struct Op {
fp_sub = 0;
fp_mul = 0;
fp_sqr = 0;
fp_mul2 = 0;
fp_invOp = 0;
fp_mulUnit = 0;
@ -363,13 +388,14 @@ private:
inline const char* getIoSeparator(int ioMode)
{
return (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) ? "" : " ";
return (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr | IoEcAffineSerialize)) ? "" : " ";
}
inline void dump(const char *s, size_t n)
inline void dump(const void *buf, size_t n)
{
const uint8_t *s = (const uint8_t *)buf;
for (size_t i = 0; i < n; i++) {
printf("%02x ", (uint8_t)s[i]);
printf("%02x ", s[i]);
}
printf("\n");
}

@ -84,12 +84,39 @@ struct Operator : public E {
{
powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, true);
}
static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime))
static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime), size_t g(T& z, const T *xVec, const mpz_class *yVec, size_t n) = 0)
{
powArrayGLV = f;
powVecNGLV = g;
}
static const size_t powVecMaxN = 16;
template<class tag, size_t maxBitSize, template<class _tag, size_t _maxBitSize>class FpT>
static void powVec(T& z, const T* xVec, const FpT<tag, maxBitSize> *yVec, size_t n)
{
assert(powVecNGLV);
T r;
r.setOne();
const size_t N = mcl::fp::maxMulVecNGLV;
mpz_class myVec[N];
while (n > 0) {
T t;
size_t tn = fp::min_(n, N);
for (size_t i = 0; i < tn; i++) {
bool b;
yVec[i].getMpz(&b, myVec[i]);
assert(b); (void)b;
}
size_t done = powVecNGLV(t, xVec, myVec, tn);
r *= t;
xVec += done;
yVec += done;
n -= done;
}
z = r;
}
private:
static void (*powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);
static size_t (*powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n);
static void powArray(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)
{
if (powArrayGLV && (constTime || yn > 1)) {
@ -117,6 +144,9 @@ private:
template<class T, class E>
void (*Operator<T, E>::powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);
template<class T, class E>
size_t (*Operator<T, E>::powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n);
/*
T must have save and load
*/
@ -154,6 +184,20 @@ struct Serializable : public E {
getStr(str, ioMode);
return str;
}
std::string serializeToHexStr() const
{
std::string str(sizeof(T) * 2, 0);
size_t n = serialize(&str[0], str.size(), IoSerializeHexStr);
str.resize(n);
return str;
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
void deserializeHexStr(const std::string& str)
{
size_t n = deserialize(str.c_str(), str.size(), IoSerializeHexStr);
if (n == 0) throw cybozu::Exception("bad str") << str;
}
#endif
#endif
// return written bytes
size_t serialize(void *buf, size_t maxBufSize, int ioMode = IoSerialize) const

@ -74,6 +74,18 @@ typedef struct {
typedef struct {
mclBnFr d[7];
} sheZkpBinEq;
typedef struct {
mclBnFr d[2];
} sheZkpDec;
typedef struct {
mclBnGT d[4];
} sheAuxiliaryForZkpDecGT;
typedef struct {
mclBnFr d[4];
} sheZkpDecGT;
/*
initialize this library
call this once before using the other functions
@ -96,6 +108,8 @@ MCLSHE_DLL_API mclSize sheCipherTextGTSerialize(void *buf, mclSize maxBufSize, c
MCLSHE_DLL_API mclSize sheZkpBinSerialize(void *buf, mclSize maxBufSize, const sheZkpBin *zkp);
MCLSHE_DLL_API mclSize sheZkpEqSerialize(void *buf, mclSize maxBufSize, const sheZkpEq *zkp);
MCLSHE_DLL_API mclSize sheZkpBinEqSerialize(void *buf, mclSize maxBufSize, const sheZkpBinEq *zkp);
MCLSHE_DLL_API mclSize sheZkpDecSerialize(void *buf, mclSize maxBufSize, const sheZkpDec *zkp);
MCLSHE_DLL_API mclSize sheZkpDecGTSerialize(void *buf, mclSize maxBufSize, const sheZkpDecGT *zkp);
// return read byte size if sucess else 0
MCLSHE_DLL_API mclSize sheSecretKeyDeserialize(sheSecretKey* sec, const void *buf, mclSize bufSize);
@ -106,6 +120,8 @@ MCLSHE_DLL_API mclSize sheCipherTextGTDeserialize(sheCipherTextGT* c, const void
MCLSHE_DLL_API mclSize sheZkpBinDeserialize(sheZkpBin* zkp, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpEqDeserialize(sheZkpEq* zkp, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpBinEqDeserialize(sheZkpBinEq* zkp, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpDecDeserialize(sheZkpDec* zkp, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpDecGTDeserialize(sheZkpDecGT* zkp, const void *buf, mclSize bufSize);
/*
set secretKey if system has /dev/urandom or CryptGenRandom
@ -115,6 +131,8 @@ MCLSHE_DLL_API int sheSecretKeySetByCSPRNG(sheSecretKey *sec);
MCLSHE_DLL_API void sheGetPublicKey(shePublicKey *pub, const sheSecretKey *sec);
MCLSHE_DLL_API void sheGetAuxiliaryForZkpDecGT(sheAuxiliaryForZkpDecGT *aux, const shePublicKey *pub);
/*
make table to decode DLP
return 0 if success
@ -192,6 +210,13 @@ MCLSHE_DLL_API int shePrecomputedPublicKeyEncWithZkpBinEq(sheCipherTextG1 *c1, s
MCLSHE_DLL_API int sheEncWithZkpEq(sheCipherTextG1 *c1, sheCipherTextG2 *c2, sheZkpEq *zkp, const shePublicKey *pub, mclInt m);
MCLSHE_DLL_API int shePrecomputedPublicKeyEncWithZkpEq(sheCipherTextG1 *c1, sheCipherTextG2 *c2, sheZkpEq *zkp, const shePrecomputedPublicKey *ppub, mclInt m);
/*
Zkp s.t. Dec(c) = m
return 0 if success
*/
MCLSHE_DLL_API int sheDecWithZkpDecG1(mclInt *m, sheZkpDec *zkp, const sheSecretKey *sec, const sheCipherTextG1 *c, const shePublicKey *pub);
MCLSHE_DLL_API int sheDecWithZkpDecGT(mclInt *m, sheZkpDecGT *zkp, const sheSecretKey *sec, const sheCipherTextGT *c, const sheAuxiliaryForZkpDecGT *aux);
/*
decode c and set m
return 0 if success
@ -211,6 +236,8 @@ MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpBinG1(const shePrecomputedPub
MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpBinG2(const shePrecomputedPublicKey *ppub, const sheCipherTextG2 *c, const sheZkpBin *zkp);
MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpEq(const shePrecomputedPublicKey *ppub, const sheCipherTextG1 *c1, const sheCipherTextG2 *c2, const sheZkpEq *zkp);
MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpBinEq(const shePrecomputedPublicKey *ppub, const sheCipherTextG1 *c1, const sheCipherTextG2 *c2, const sheZkpBinEq *zkp);
MCLSHE_DLL_API int sheVerifyZkpDecG1(const shePublicKey *pub, const sheCipherTextG1 *c1, mclInt m, const sheZkpDec *zkp);
MCLSHE_DLL_API int sheVerifyZkpDecGT(const sheAuxiliaryForZkpDecGT *aux, const sheCipherTextGT *ct, mclInt m, const sheZkpDecGT *zkp);
/*
decode c via GT and set m
return 0 if success

@ -26,6 +26,8 @@
#include <mcl/window_method.hpp>
#include <cybozu/endian.hpp>
#include <cybozu/serializer.hpp>
#include <cybozu/sha2.hpp>
#include <mcl/ecparam.hpp>
namespace mcl { namespace she {
@ -324,6 +326,26 @@ int log(const G& P, const G& xP)
throw cybozu::Exception("she:log:not found");
}
struct Hash {
cybozu::Sha256 h_;
template<class T>
Hash& operator<<(const T& t)
{
char buf[sizeof(T)];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
t.save(os);
h_.update(buf, os.getPos());
return *this;
}
template<class F>
void get(F& x)
{
uint8_t md[32];
h_.digest(md, sizeof(md), 0, 0);
x.setArrayMask(md, sizeof(md));
}
};
} // mcl::she::local
template<size_t dummyInpl = 0>
@ -366,11 +388,17 @@ private:
public:
const G& getS() const { return S_; }
const G& getT() const { return T_; }
G& getNonConstRefS() { return S_; }
G& getNonConstRefT() { return T_; }
void clear()
{
S_.clear();
T_.clear();
}
bool isValid() const
{
return S_.isValid() && T_.isValid();
}
static void add(CipherTextAT& z, const CipherTextAT& x, const CipherTextAT& y)
{
/*
@ -537,6 +565,8 @@ private:
struct ZkpBinTag;
struct ZkpEqTag; // d_[] = { c, sp, ss, sm }
struct ZkpBinEqTag; // d_[] = { d0, d1, sp0, sp1, ss, sp, sm }
struct ZkpDecTag; // d_[] = { c, h }
struct ZkpDecGTTag; // d_[] = { d1, d2, d3, h }
public:
/*
Zkp for m = 0 or 1
@ -550,9 +580,66 @@ public:
Zkp for (m = 0 or 1) and decG1(c1) == decG2(c2)
*/
typedef ZkpT<ZkpBinEqTag, 7> ZkpBinEq;
/*
Zkp for Dec(c) = m for c in G1
*/
typedef ZkpT<ZkpDecTag, 2> ZkpDec;
/*
Zkp for Dec(c) = m for c in GT
*/
typedef ZkpT<ZkpDecGTTag, 4> ZkpDecGT;
typedef CipherTextAT<G1> CipherTextG1;
typedef CipherTextAT<G2> CipherTextG2;
/*
auxiliary for ZkpDecGT
@note GT is multiplicative group though treating GT as additive group in comment
*/
struct AuxiliaryForZkpDecGT {
GT R_[4]; // [R = e(R, Q), xR, yR, xyR]
// dst = v[1] a[0] + v[0] a[1] - v[2] a[2]
void f(GT& dst, const GT *v, const Fr *a) const
{
GT t;
GT::pow(dst, v[0], a[1]);
GT::pow(t, v[1], a[0]);
dst *= t;
GT::pow(t, v[2], a[2]);
GT::unitaryInv(t, t);
dst *= t;
}
bool verify(const CipherTextGT& c, int64_t m, const ZkpDecGT& zkp) const
{
const Fr *d = &zkp.d_[0];
const Fr &h = zkp.d_[3];
GT A[4];
GT t;
GT::pow(t, R_[0], m); // m R
GT::unitaryInv(t, t);
GT::mul(A[0], c.g_[0], t);
A[1] = c.g_[1];
A[2] = c.g_[2];
A[3] = c.g_[3];
GT B[3], X;
for (int i = 0; i < 3; i++) {
GT::pow(B[i], R_[0], d[i]);
GT::pow(t, R_[i+1], h);
GT::unitaryInv(t, t);
B[i] *= t;
}
f(X, A + 1, zkp.d_);
GT::pow(t, A[0], h);
GT::unitaryInv(t, t);
X *= t;
local::Hash hash;
hash << R_[1] << R_[2] << R_[3] << A[0] << A[1] << A[2] << A[3] << B[0] << B[1] << B[2] << X;
Fr h2;
hash.get(h2);
return h == h2;
}
};
static void init(const mcl::CurveParam& cp = mcl::BN254, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
{
@ -576,13 +663,7 @@ public:
*/
static void initG1only(const mcl::EcParam& para, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
{
Fp::init(para.p);
Fr::init(para.n);
G1::init(para.a, para.b);
const Fp x0(para.gx);
const Fp y0(para.gy);
P_.set(x0, y0);
mcl::initCurve<G1, Fr>(para.curveType, &P_);
setRangeForG1DLP(hashSize);
useDecG1ViaGT_ = false;
useDecG2ViaGT_ = false;
@ -774,6 +855,88 @@ public:
return isZero(c.a_);
}
}
int64_t decWithZkpDec(bool *pok, ZkpDec& zkp, const CipherTextG1& c, const PublicKey& pub) const
{
/*
c = (S, T)
S = mP + rxP
T = rP
R = S - xT = mP
*/
G1 R;
G1::mul(R, c.T_, x_);
G1::sub(R, c.S_, R);
int64_t m = PhashTbl_.log(R, pok);
if (!*pok) return 0;
const G1& P1 = P_;
const G1& P2 = c.T_; // rP
const G1& A1 = pub.xP_;
G1 A2;
G1::sub(A2, c.S_, R); // rxP
Fr b;
b.setRand();
G1 B1, B2;
G1::mul(B1, P1, b);
G1::mul(B2, P2, b);
Fr& d = zkp.d_[0];
Fr& h = zkp.d_[1];
local::Hash hash;
hash << P2 << A1 << A2 << B1 << B2;
hash.get(h);
Fr::mul(d, h, x_);
d += b;
return m;
}
// @note GT is multiplicative group though treating GT as additive group in comment
int64_t decWithZkpDec(bool *pok, ZkpDecGT& zkp, const CipherTextGT& c, const AuxiliaryForZkpDecGT& aux) const
{
int64_t m = dec(c, pok);
if (!*pok) return 0;
// A = c - Enc(m; 0, 0, 0) = c - (m R, 0, 0, 0)
GT A[4];
GT t;
GT::pow(t, aux.R_[0], m); // m R
GT::unitaryInv(t, t);
GT::mul(A[0], c.g_[0], t);
A[1] = c.g_[1];
A[2] = c.g_[2];
A[3] = c.g_[3];
// dec(A) = 0
Fr b[3];
GT B[3], X;
for (int i = 0; i < 3; i++) {
b[i].setByCSPRNG();
GT::pow(B[i], aux.R_[0], b[i]);
}
aux.f(X, A + 1, b);
local::Hash hash;
hash << aux.R_[1] << aux.R_[2] << aux.R_[3] << A[0] << A[1] << A[2] << A[3] << B[0] << B[1] << B[2] << X;
Fr *d = &zkp.d_[0];
Fr &h = zkp.d_[3];
hash.get(h);
Fr::mul(d[0], h, x_); // h x
Fr::mul(d[1], h, y_); // h y
Fr::mul(d[2], d[1], x_); // h xy
for (int i = 0; i < 3; i++) {
d[i] += b[i];
}
return m;
}
int64_t decWithZkpDec(ZkpDec& zkp, const CipherTextG1& c, const PublicKey& pub) const
{
bool b;
int64_t ret = decWithZkpDec(&b, zkp, c, pub);
if (!b) throw cybozu::Exception("she:SecretKey:decWithZkpDec");
return ret;
}
int64_t decWithZkpDec(ZkpDecGT& zkp, const CipherTextGT& c, const AuxiliaryForZkpDecGT& aux) const
{
bool b;
int64_t ret = decWithZkpDec(&b, zkp, c, aux);
if (!b) throw cybozu::Exception("she:SecretKey:decWithZkpDec");
return ret;
}
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
@ -886,16 +1049,10 @@ private:
r.setRand();
Pmul.mul(static_cast<I&>(R[0][m]), r); // R[0][m] = r P
xPmul.mul(R[1][m], r); // R[1][m] = r xP
char buf[sizeof(G) * 2];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S.save(os);
T.save(os);
R[0][0].save(os);
R[0][1].save(os);
R[1][0].save(os);
R[1][1].save(os);
Fr c;
c.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S << T << R[0][0] << R[0][1] << R[1][0] << R[1][1];
hash.get(c);
d[m] = c - d[1-m];
s[m] = r + d[m] * encRand;
}
@ -925,16 +1082,10 @@ private:
G::sub(T2, S, P);
G::mul(T2, T2, d[1]);
G::sub(R[1][1], T1, T2);
char buf[sizeof(G) * 2];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S.save(os);
T.save(os);
R[0][0].save(os);
R[0][1].save(os);
R[1][0].save(os);
R[1][1].save(os);
Fr c;
c.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S << T << R[0][0] << R[0][1] << R[1][0] << R[1][1];
hash.get(c);
return c == d[0] + d[1];
}
/*
@ -956,21 +1107,13 @@ private:
G2 R3, R4;
ElGamalEnc(R1, R2, rm, Pmul, xPmul, &rp);
ElGamalEnc(R3, R4, rm, Qmul, yQmul, &rs);
char buf[sizeof(G1) * 4 + sizeof(G2) * 4];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S1.save(os);
T1.save(os);
S2.save(os);
T2.save(os);
R1.save(os);
R2.save(os);
R3.save(os);
R4.save(os);
Fr& c = zkp.d_[0];
Fr& sp = zkp.d_[1];
Fr& ss = zkp.d_[2];
Fr& sm = zkp.d_[3];
c.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S1 << T1 << S2 << T2 << R1 << R2 << R3 << R4;
hash.get(c);
Fr::mul(sp, c, p);
sp += rp;
Fr::mul(ss, c, s);
@ -997,18 +1140,10 @@ private:
R3 -= X2;
G2::mul(X2, T2, c);
R4 -= X2;
char buf[sizeof(G1) * 4 + sizeof(G2) * 4];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S1.save(os);
T1.save(os);
S2.save(os);
T2.save(os);
R1.save(os);
R2.save(os);
R3.save(os);
R4.save(os);
Fr c2;
c2.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S1 << T1 << S2 << T2 << R1 << R2 << R3 << R4;
hash.get(c2);
return c == c2;
}
/*
@ -1052,20 +1187,10 @@ private:
G2 R5, R6;
ElGamalEnc(R4, R3, rm, Pmul, xPmul, &rp);
ElGamalEnc(R6, R5, rm, Qmul, yQmul, &rs);
char buf[sizeof(Fp) * 12];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S1.save(os);
T1.save(os);
R1[0].save(os);
R1[1].save(os);
R2[0].save(os);
R2[1].save(os);
R3.save(os);
R4.save(os);
R5.save(os);
R6.save(os);
Fr c;
c.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S1 << T1 << R1[0] << R1[1] << R2[0] << R2[1] << R3 << R4 << R5 << R6;
hash.get(c);
Fr::sub(d[m], c, d[1-m]);
Fr::mul(spm[m], d[m], p);
spm[m] += rpm;
@ -1112,20 +1237,10 @@ private:
R5 -= X2;
G2::mul(X2, S2, c);
R6 -= X2;
char buf[sizeof(Fp) * 12];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S1.save(os);
T1.save(os);
R1[0].save(os);
R1[1].save(os);
R2[0].save(os);
R2[1].save(os);
R3.save(os);
R4.save(os);
R5.save(os);
R6.save(os);
Fr c2;
c2.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S1 << T1 << R1[0] << R1[1] << R2[0] << R2[1] << R3 << R4 << R5 << R6;
hash.get(c2);
return c == c2;
}
/*
@ -1266,6 +1381,13 @@ public:
ElGamalEnc(c.S_, c.T_, m, QhashTbl_.getWM(), yQmul);
}
public:
void getAuxiliaryForZkpDecGT(AuxiliaryForZkpDecGT& aux) const
{
aux.R_[0] = ePQ_;
pairing(aux.R_[1], xP_, Q_);
pairing(aux.R_[2], P_, yQ_);
pairing(aux.R_[3], xP_, yQ_);
}
void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, int m) const
{
Fr encRand;
@ -1287,6 +1409,33 @@ public:
const MulG<G1> xPmul(xP_);
return verifyZkpBin(c.S_, c.T_, P_, zkp, PhashTbl_.getWM(), xPmul);
}
bool verify(const CipherTextG1& c, int64_t m, const ZkpDec& zkp) const
{
/*
Enc(m;r) - Enc(m;0) = (S, T) - (mP, 0) = (S - mP, T)
*/
const Fr& d = zkp.d_[0];
const Fr& h = zkp.d_[1];
const G1& P1 = P_;
const G1& P2 = c.T_; // rP
const G1& A1 = xP_;
G1 A2;
G1::mul(A2, P_, m);
// PhashTbl_.getWM().mul(A2, m);
G1::sub(A2, c.S_, A2); // S - mP = xrP
G1 B1, B2, T;
G1::mul(B1, P1, d);
G1::mul(B2, P2, d);
G1::mul(T, A1, h);
B1 -= T;
G1::mul(T, A2, h);
B2 -= T;
Fr h2;
local::Hash hash;
hash << P2 << A1 << A2 << B1 << B2;
hash.get(h2);
return h == h2;
}
bool verify(const CipherTextG2& c, const ZkpBin& zkp) const
{
const MulG<G2> yQmul(yQ_);
@ -1599,6 +1748,7 @@ public:
friend class PublicKey;
friend class PrecomputedPublicKey;
friend class CipherTextA;
friend struct AuxiliaryForZkpDecGT;
template<class T>
friend struct PublicKeyMethod;
public:
@ -1809,7 +1959,14 @@ public:
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
cybozu::writeChar(pb, isMultiplied_ ? '0' : '1', is); if (!*pb) return;
char c;
if (!cybozu::readChar(&c, is)) return;
if (c == '0' || c == '1') {
isMultiplied_ = c == '0';
} else {
*pb = false;
return;
}
if (isMultiplied()) {
m_.load(pb, is, ioMode);
} else {
@ -1819,14 +1976,7 @@ public:
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
char c;
if (!cybozu::readChar(&c, os)) return;
if (c == '0' || c == '1') {
isMultiplied_ = c == '0';
} else {
*pb = false;
return;
}
cybozu::writeChar(pb, os, isMultiplied_ ? '0' : '1'); if (!*pb) return;
if (isMultiplied()) {
m_.save(pb, os, ioMode);
} else {
@ -1895,6 +2045,9 @@ typedef SHE::CipherText CipherText;
typedef SHE::ZkpBin ZkpBin;
typedef SHE::ZkpEq ZkpEq;
typedef SHE::ZkpBinEq ZkpBinEq;
typedef SHE::ZkpDec ZkpDec;
typedef SHE::AuxiliaryForZkpDecGT AuxiliaryForZkpDecGT;
typedef SHE::ZkpDecGT ZkpDecGT;
inline void init(const mcl::CurveParam& cp = mcl::BN254, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
{

@ -157,7 +157,6 @@ void maskArray(T *x, size_t n, size_t bitSize)
template<class T>
size_t getNonZeroArraySize(const T *x, size_t n)
{
assert(n > 0);
while (n > 0) {
if (x[n - 1]) return n;
n--;
@ -165,6 +164,62 @@ size_t getNonZeroArraySize(const T *x, size_t n)
return 1;
}
template<class T>
class BitIterator {
const T *x_;
size_t bitPos_;
size_t bitSize_;
static const size_t TbitSize = sizeof(T) * 8;
public:
BitIterator(const T *x, size_t n)
: x_(x)
, bitPos_(0)
{
assert(n > 0);
n = getNonZeroArraySize(x, n);
if (n == 1 && x[0] == 0) {
bitSize_ = 1;
} else {
assert(x_[n - 1]);
bitSize_ = (n - 1) * sizeof(T) * 8 + 1 + cybozu::bsr<T>(x_[n - 1]);
}
}
bool hasNext() const { return bitPos_ < bitSize_; }
T getNext(size_t w)
{
assert(0 < w && w <= TbitSize);
assert(hasNext());
const size_t q = bitPos_ / TbitSize;
const size_t r = bitPos_ % TbitSize;
const size_t remain = bitSize_ - bitPos_;
if (w > remain) w = remain;
T v = x_[q] >> r;
if (r + w > TbitSize) {
v |= x_[q + 1] << (TbitSize - r);
}
bitPos_ += w;
return v & mask(w);
}
// whethere next bit is 1 or 0 (bitPos is not moved)
bool peekBit() const
{
assert(hasNext());
const size_t q = bitPos_ / TbitSize;
const size_t r = bitPos_ % TbitSize;
return (x_[q] >> r) & 1;
}
void skipBit()
{
assert(hasNext());
bitPos_++;
}
T mask(size_t w) const
{
assert(w <= TbitSize);
return (w == TbitSize ? T(0) : (T(1) << w)) - 1;
}
};
/*
@param out [inout] : set element of G ; out = x^y[]
@param x [in]
@ -231,7 +286,7 @@ void powGeneric(G& out, const G& x, const T *y, size_t n, const Mul& mul, const
out = x;
}
for (int i = (int)n - 1; i >= 0; i--) {
T v = y[i];
v = y[i];
for (int j = m - 2; j >= 0; j -= 2) {
sqr(out, out);
sqr(out, out);
@ -272,6 +327,8 @@ bool mulSmallUnit(T& z, const T& x, U y)
case 8: T::add(z, x, x); T::add(z, z, z); T::add(z, z, z); break;
case 9: { T t; T::add(t, x, x); T::add(t, t, t); T::add(t, t, t); T::add(z, t, x); break; }
case 10: { T t; T::add(t, x, x); T::add(t, t, t); T::add(t, t, x); T::add(z, t, t); break; }
case 11: { T t; T::add(t, x, x); T::add(t, t, x); T::add(t, t, t); T::add(t, t, t); T::sub(z, t, x); break; }
case 12: { T t; T::add(t, x, x); T::add(t, t, t); T::add(z, t, t); T::add(z, z, t); break; }
default:
return false;
}

@ -90,35 +90,19 @@ inline uint32_t mulUnit(uint32_t *pH, uint32_t x, uint32_t y)
inline uint64_t mulUnit(uint64_t *pH, uint64_t x, uint64_t y)
{
#ifdef MCL_VINT_64BIT_PORTABLE
uint32_t a = uint32_t(x >> 32);
uint32_t b = uint32_t(x);
uint32_t c = uint32_t(y >> 32);
uint32_t d = uint32_t(y);
uint64_t ad = uint64_t(d) * a;
uint64_t bd = uint64_t(d) * b;
uint64_t L = uint32_t(bd);
ad += bd >> 32; // [ad:L]
uint64_t ac = uint64_t(c) * a;
uint64_t bc = uint64_t(c) * b;
uint64_t H = uint32_t(bc);
ac += bc >> 32; // [ac:H]
/*
adL
acH
*/
uint64_t t = (ac << 32) | H;
ac >>= 32;
H = t + ad;
if (H < t) {
ac++;
}
/*
ac:H:L
*/
const uint64_t mask = 0xffffffff;
uint64_t v = (x & mask) * (y & mask);
uint64_t L = uint32_t(v);
uint64_t H = v >> 32;
uint64_t ad = (x & mask) * uint32_t(y >> 32);
uint64_t bc = uint32_t(x >> 32) * (y & mask);
H += uint32_t(ad);
H += uint32_t(bc);
L |= H << 32;
H = (ac << 32) | uint32_t(H >> 32);
H >>= 32;
H += ad >> 32;
H += bc >> 32;
H += (x >> 32) * (y >> 32);
*pH = H;
return L;
#elif defined(_WIN64) && !defined(__INTEL_COMPILER)
@ -150,7 +134,7 @@ inline uint32_t divUnit(uint32_t *pr, uint32_t H, uint32_t L, uint32_t y)
#if MCL_SIZEOF_UNIT == 8
inline uint64_t divUnit(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y)
{
#if defined(MCL_VINT_64BIT_PORTABLE)
#if defined(MCL_VINT_64BIT_PORTABLE) || (defined(_MSC_VER) && _MSC_VER < 1920)
uint32_t px[4] = { uint32_t(L), uint32_t(L >> 32), uint32_t(H), uint32_t(H >> 32) };
uint32_t py[2] = { uint32_t(y), uint32_t(y >> 32) };
size_t xn = 4;
@ -162,7 +146,7 @@ inline uint64_t divUnit(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y)
*pr = make64(r[1], r[0]);
return make64(q[1], q[0]);
#elif defined(_MSC_VER)
#error "divUnit for uint64_t is not supported"
return _udiv128(H, L, y, pr);
#else
typedef __attribute__((mode(TI))) unsigned int uint128;
uint128 t = (uint128(H) << 64) | L;
@ -213,15 +197,12 @@ T addN(T *z, const T *x, const T *y, size_t n)
T c = 0;
for (size_t i = 0; i < n; i++) {
T xc = x[i] + c;
if (xc < c) {
// x[i] = Unit(-1) and c = 1
z[i] = y[i];
} else {
xc += y[i];
c = y[i] > xc ? 1 : 0;
c = xc < c;
T yi = y[i];
xc += yi;
c += xc < yi;
z[i] = xc;
}
}
return c;
}
@ -301,14 +282,12 @@ T subN(T *z, const T *x, const T *y, size_t n)
assert(n > 0);
T c = 0;
for (size_t i = 0; i < n; i++) {
T yc = y[i] + c;
if (yc < c) {
// y[i] = T(-1) and c = 1
z[i] = x[i];
} else {
c = x[i] < yc ? 1 : 0;
z[i] = x[i] - yc;
}
T yi = y[i];
yi += c;
c = yi < c;
T xi = x[i];
c += xi < yi;
z[i] = xi - yi;
}
return c;
}
@ -552,15 +531,6 @@ size_t getRealSize(const T *x, size_t xn)
return 1;
}
template<class T>
size_t getBitSize(const T *x, size_t n)
{
if (n == 1 && x[0] == 0) return 1;
T v = x[n - 1];
assert(v);
return (n - 1) * sizeof(T) * 8 + 1 + cybozu::bsr<Unit>(v);
}
/*
q[qn] = x[xn] / y[yn] ; qn == xn - yn + 1 if xn >= yn if q
r[rn] = x[xn] % y[yn] ; rn = yn before getRealSize
@ -1755,6 +1725,46 @@ public:
static void invMod(VintT& y, const VintT& x, const VintT& m)
{
assert(!x.isZero() && !m.isZero());
#if 0
VintT u = x;
VintT v = m;
VintT x1 = 1, x2 = 0;
VintT t;
while (u != 1 && v != 1) {
while (u.isEven()) {
u >>= 1;
if (x1.isOdd()) {
x1 += m;
}
x1 >>= 1;
}
while (v.isEven()) {
v >>= 1;
if (x2.isOdd()) {
x2 += m;
}
x2 >>= 1;
}
if (u >= v) {
u -= v;
x1 -= x2;
if (x1 < 0) {
x1 += m;
}
} else {
v -= u;
x2 -= x1;
if (x2 < 0) {
x2 += m;
}
}
}
if (u == 1) {
y = x1;
} else {
y = x2;
}
#else
if (x == 1) {
y = 1;
return;
@ -1787,6 +1797,7 @@ public:
}
b -= a * q;
}
#endif
}
/*
Miller-Rabin

@ -23,35 +23,33 @@ struct ArrayIterator {
, bitSize(bitSize)
, w(w)
, pos(0)
, mask((w == TbitSize ? 0 : (T(1) << w)) - 1)
, mask(makeMask(w))
{
assert(w <= TbitSize);
}
T makeMask(size_t w) const
{
return (w == TbitSize) ? ~T(0) : (T(1) << w) - 1;
}
bool hasNext() const { return bitSize > 0; }
T getNext()
{
if (w == TbitSize) {
bitSize -= w;
return *x++;
if (bitSize < w) {
w = bitSize;
mask = makeMask(w);
}
if (pos + w <= TbitSize) {
T v = x[0] >> pos;
if (pos + w < TbitSize) {
T v = (*x >> pos) & mask;
pos += w;
if (bitSize < w) {
bitSize = 0;
v &= mask;
} else {
bitSize -= w;
pos = 0;
x++;
}
bitSize -= w;
return v;
}
if (pos + bitSize <= TbitSize) {
assert(bitSize <= w);
T v = *x >> pos;
assert((v >> bitSize) == 0);
bitSize = 0;
return v & mask;
}
assert(pos > 0);
T v = (x[0] >> pos) | (x[1] << (TbitSize - pos));
v &= mask;
pos = (pos + w) - TbitSize;

@ -0,0 +1,6 @@
all: low_test
CFLAGS=-I ../include/ -m32 -Ofast -Wall -Wextra -DNDEBUG
low_test: low_test.cpp ../src/low_func_wasm.hpp
$(CXX) -o low_test low_test.cpp $(CFLAGS)

@ -0,0 +1,234 @@
#include <stdio.h>
#include <stdint.h>
void dump(const char *msg, const uint32_t *x, size_t n)
{
printf("%s", msg);
for (size_t i = 0; i < n; i++) {
printf("%08x", x[n - 1 - i]);
}
printf("\n");
}
#include "../src/low_func_wasm.hpp"
#define MCL_USE_VINT
#define MCL_VINT_FIXED_BUFFER
#define MCL_SIZEOF_UNIT 4
#define MCL_MAX_BIT_SIZE 768
#include <mcl/vint.hpp>
#include <cybozu/test.hpp>
#include <cybozu/xorshift.hpp>
#include <cybozu/benchmark.hpp>
#include <mcl/util.hpp>
const int C = 10000;
template<class RG>
void setRand(uint32_t *x, size_t n, RG& rg)
{
for (size_t i = 0; i < n; i++) {
x[i] = rg.get32();
}
}
/*
g++ -Ofast -DNDEBUG -Wall -Wextra -m32 -I ./include/ misc/low_test.cpp
Core i7-8700
mulT karatsuba
N = 6, 182clk 225clk
N = 8, 300clk 350clk
N = 12, 594clk 730clk
*/
template<size_t N>
void mulTest()
{
printf("N=%zd (%zdbit)\n", N, N * 32);
cybozu::XorShift rg;
uint32_t x[N];
uint32_t y[N];
uint32_t z[N * 2];
for (size_t i = 0; i < 1000; i++) {
setRand(x, N, rg);
setRand(y, N, rg);
// remove MSB
x[N - 1] &= 0x7fffffff;
y[N - 1] &= 0x7fffffff;
mcl::Vint vx, vy;
vx.setArray(x, N);
vy.setArray(y, N);
vx *= vy;
mcl::mulT<N>(z, x, y);
CYBOZU_TEST_EQUAL_ARRAY(z, vx.getUnit(), N * 2);
memset(z, 0, sizeof(z));
mcl::karatsubaT<N>(z, x, y);
CYBOZU_TEST_EQUAL_ARRAY(z, vx.getUnit(), N * 2);
}
CYBOZU_BENCH_C("mulT", C, mcl::mulT<N>, z, x, y);
CYBOZU_BENCH_C("kara", C, mcl::karatsubaT<N>, z, x, y);
}
CYBOZU_TEST_AUTO(mulT)
{
mulTest<8>();
mulTest<12>();
}
template<size_t N>
void sqrTest()
{
printf("N=%zd (%zdbit)\n", N, N * 32);
cybozu::XorShift rg;
uint32_t x[N];
uint32_t y[N * 2];
for (size_t i = 0; i < 1000; i++) {
setRand(x, N, rg);
// remove MSB
x[N - 1] &= 0x7fffffff;
mcl::Vint vx;
vx.setArray(x, N);
vx *= vx;
mcl::sqrT<N>(y, x);
CYBOZU_TEST_EQUAL_ARRAY(y, vx.getUnit(), N * 2);
}
CYBOZU_BENCH_C("sqrT", C, mcl::sqrT<N>, y, x);
}
CYBOZU_TEST_AUTO(sqrT)
{
sqrTest<8>();
sqrTest<12>();
}
struct Montgomery {
mcl::Vint p_;
mcl::Vint R_; // (1 << (pn_ * 64)) % p
mcl::Vint RR_; // (R * R) % p
uint32_t rp_; // rp * p = -1 mod M = 1 << 64
size_t pn_;
Montgomery() {}
explicit Montgomery(const mcl::Vint& p)
{
p_ = p;
rp_ = mcl::fp::getMontgomeryCoeff(p.getUnit()[0]);
pn_ = p.getUnitSize();
R_ = 1;
R_ = (R_ << (pn_ * 64)) % p_;
RR_ = (R_ * R_) % p_;
}
void toMont(mcl::Vint& x) const { mul(x, x, RR_); }
void fromMont(mcl::Vint& x) const { mul(x, x, 1); }
void mul(mcl::Vint& z, const mcl::Vint& x, const mcl::Vint& y) const
{
const size_t ySize = y.getUnitSize();
mcl::Vint c = x * y.getUnit()[0];
uint32_t q = c.getUnit()[0] * rp_;
c += p_ * q;
c >>= sizeof(uint32_t) * 8;
for (size_t i = 1; i < pn_; i++) {
if (i < ySize) {
c += x * y.getUnit()[i];
}
uint32_t q = c.getUnit()[0] * rp_;
c += p_ * q;
c >>= sizeof(uint32_t) * 8;
}
if (c >= p_) {
c -= p_;
}
z = c;
}
void mod(mcl::Vint& z, const mcl::Vint& xy) const
{
z = xy;
for (size_t i = 0; i < pn_; i++) {
uint32_t q = z.getUnit()[0] * rp_;
mcl::Vint t = q;
z += p_ * t;
z >>= 32;
}
if (z >= p_) {
z -= p_;
}
}
};
template<size_t N>
void mulMontTest(const char *pStr)
{
mcl::Vint vp;
vp.setStr(pStr);
Montgomery mont(vp);
cybozu::XorShift rg;
uint32_t x[N];
uint32_t y[N];
uint32_t z[N];
uint32_t _p[N + 1];
uint32_t *const p = _p + 1;
vp.getArray(p, N);
p[-1] = mont.rp_;
for (size_t i = 0; i < 1000; i++) {
setRand(x, N, rg);
setRand(y, N, rg);
// remove MSB
x[N - 1] &= 0x7fffffff;
y[N - 1] &= 0x7fffffff;
mcl::Vint vx, vy, vz;
vx.setArray(x, N);
vy.setArray(y, N);
mont.mul(vz, vx, vy);
mcl::mulMontT<N>(z, x, y, p);
CYBOZU_TEST_EQUAL_ARRAY(z, vz.getUnit(), N);
mont.mul(vz, vx, vx);
mcl::sqrMontT<N>(z, x, p);
CYBOZU_TEST_EQUAL_ARRAY(z, vz.getUnit(), N);
}
CYBOZU_BENCH_C("mulMontT", C, mcl::mulMontT<N>, x, x, y, p);
CYBOZU_BENCH_C("sqrMontT", C, mcl::sqrMontT<N>, x, x, p);
}
template<size_t N>
void modTest(const char *pStr)
{
mcl::Vint vp;
vp.setStr(pStr);
Montgomery mont(vp);
cybozu::XorShift rg;
uint32_t xy[N * 2];
uint32_t z[N];
uint32_t _p[N + 1];
uint32_t *const p = _p + 1;
vp.getArray(p, N);
p[-1] = mont.rp_;
for (size_t i = 0; i < 1000; i++) {
setRand(xy, N * 2, rg);
// remove MSB
xy[N * 2 - 1] &= 0x7fffffff;
mcl::Vint vxy, vz;
vxy.setArray(xy, N * 2);
mont.mod(vz, vxy);
mcl::modT<N>(z, xy, p);
CYBOZU_TEST_EQUAL_ARRAY(z, vz.getUnit(), N);
}
CYBOZU_BENCH_C("modT", C, mcl::modT<N>, z, xy, p);
}
CYBOZU_TEST_AUTO(mont)
{
const char *pBN254 = "0x2523648240000001ba344d80000000086121000000000013a700000000000013";
puts("BN254");
mulMontTest<8>(pBN254);
modTest<8>(pBN254);
const char *pBLS12_381 = "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab";
puts("BLS12");
mulMontTest<12>(pBLS12_381);
modTest<12>(pBLS12_381);
}

@ -0,0 +1,119 @@
P ; generator
x ; secret key
xP ; public key
Enc(m;r) = (mP + rxP, rP)
c = (S, T)
dec(c) := S - xT
dec(Enc(m;r)) = (mP + rxP) - x(rP) = mP
DLP(mP) := m
Dec(c) := DLP(dec(c))
ZKP of dec(c) = m
z := Enc(m;0) = (mP, 0)
c - z = (rxP, rP) ; r is unknown
ZKP of dec(c - z) = 0
(P1, P2) := (P, rP)
(A1, A2) := (xP, xrP)
Prover shows that x(P1, P2) = (A1, A2) without revealing x.
b ; rand
B = (b P1, b P2)
h = Hash(P2, A1, A2, B1, B2)
d = b + h a
pi = (d, h)
Verifier
Bi := d Pi - h Ai
verify h = Hash(P2, A1, A2, B1, B2)
-----------------------------------------------------------------------------
CipherTextGT
P ; generator of GT, GT=<P>
x1, x2 ; secrect key
(P0, P1, P2, P3) := (P, x1 P, x2 P, x1 x2 P) ; public information
CipherText c = (A0, A1, A2, A3)
dec(c) = 0 <=> A0 = x2 A1 + x1 A2 - x1 x2 A3 ; (*)
F(a1, a2, a3) := a2 A1 + a1 A2 - a3 A3
dec(c) = 0 <=> A0 = F(x1, x2, x1 x2)
Sigma-protocol for dec(c) = 0, i.e., show (*)
Prover:
b1, b2, b3 ; rand
Bi := bi P (i = 1, 2, 3)
X := F(b1, b2, b3)
send (B1, B2, B3, X) to Verfier
Verifier:
takes h randomly and send to Prover
Prover:
d1 := b1 + h x1
d2 := b2 + h x2
d3 := b3 + h x1 x2
send (d1, d2, d3) to Verifier
Verifier:
verify
di P = Bi + h Pi (i = 1, 2, 3)
X = F(d1, d2, d3) - h A0
and accept it
Fiat-Shamir transform:
Prover:
b1, b2, b3 ; random value
Bi := bi P (i = 1, 2, 3)
X := F(b1, b2, b3)
h := Hash(P0, ..., P3, A0, ..., A3, B1, B2, B3, X)
d1 := b1 + h x1
d2 := b2 + h x2
d3 := b3 + h x1 x2
pi := (d1, d2, d3, h)
Verifier:
(pi, {Pi}, {Ai}) given
Bi' := di P - h Pi for i = 1, 2, 3
X' := F(d1, d2, d3) - h A0
verify Hash({Pi}, {Ai}, {Bi'}, X') = h
Completeness
B1' = d1 P - h P1 = (b1 + h x1) P - h x1 P = b1 P = B1
B2' = d2 P - h P2 = (b2 + h x2) P - h x2 P = b2 P = B2
B3' = d3 P - h P3 = (b3 + h x1 x2) P - h x1 x2 P = B3
X' = F(b1 + h x1, b2 + h x2, b3 + h x1 x2) - h A0
= F(b1, b2, b3) + h F(x1, x2, x1 x2) - h A0
= F(b1, b2, b3) + h (F(x1, x2, x1 x2) - A0)
= F(b1, b2, b3) = X
OK
Soundness
{Ai}, pi=(d1, d2, d3, h) ; given
compute Bi', X' as above
Suppose Hash({Pi}, {Ai}, {Bi'}, X') = h
define
b1 := d1 - h x1
b2 := d2 - h x2
b3 := d3 - h x1 x2
where x1, x2 are unknown
d1, d2, d3 are free parameters, so b1, b2, b3 are also free.
B1' = d1 P - h P1 = b1 P
B2' = b2 P
B3' = b3 P
Y := F(x1, x2, x1 x2) - A0; unknown, but it is fixed
X' = F(d1, d2, d3) - h A0 = F(b1 + h x1, b2 + h x2, b3 + h x1 x2) - h A0
= F(b1, b2, b3) + h(F(x1, x2, x1 x2) - A0)
= F(b1, b2, b3) + h Y
Hash({Pi}, {Ai}, b1 P, b2 P, b3 P, F(b1, b2, b3) + h Y) = h
To found {b1, b2, b3, h} to hold this equation, Y must be 0.

@ -250,7 +250,7 @@ PrecomputedPublicKeyはPublicKeyの高速版
* `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)
* `CT 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)
@ -275,7 +275,9 @@ PrecomputedPublicKeyはPublicKeyの高速版
* ZkpBinEq 暗号文encG1(m1), encG2(m2)についてm1 = m2 = 0または1であることを検証できる
### API
PK = PublicKey or PrecomputedPublicKey
- SK = SecretKey
- PK = PublicKey or PrecomputedPublicKey
- AUX = AuxiliaryForZkpDecGT
* `void PK::encWithZkpBin(CipherTextG1& c, Zkp& zkp, int m) const`(C++)
* `void PK::encWithZkpBin(CipherTextG2& c, Zkp& zkp, int m) const`(C++)
@ -290,6 +292,14 @@ PK = PublicKey or PrecomputedPublicKey
* `[CipherTextG1, CipherTextG2, ZkpEqBin] PK::encWithZkpBinEq(m)`(JS)
* m(=0 or 1)を暗号化して暗号文c1, c2とゼロ知識証明zkpをセットする(または[c1, c2, zkp]を返す)
* mが0でも1でもなければ例外
* `SK::decWithZkp(DecZkpDec& zkp, const CipherTextG1& c, const PublicKey& pub) const`(C++)
* `[m, ZkpDecG1] SK::decWithZkpDec(c, pub)`(JS)
* CipherTextG1暗号文`c`を復号して`m`と`zkp`を返す. `zkp`は`dec(c) = m`の証明
* `pub`は計算コストを減らすために利用する
* `SK::decWithZkpDec(ZkpDecGT& zkp, const CipherTextGT& c, const AuxiliaryForZkpDecGT& aux) const`(C++)
* `[m, ZkpDecGT] SK::decWithZkpDecGT(c, aux)`(JS)
* CipherTextGT暗号文`c`を復号して`m`と`zkp`を返す. `zkp`は`dec(c) = m`の証明
* `aux = pub.getAuxiliaryForZkpDecGT()`. auxは計算コストを減らすために利用する
## グローバル関数

@ -1,6 +1,6 @@
# she ; Two-level homomorphic encryption library for browser/Node.js by WebAssembly
# Abstruct
# Abstract
she is a somewhat(two-level) homomorphic encryption library,
which is based on pairings.
This library supports polynomially many homomorphic additions and
@ -31,7 +31,7 @@ Sum_i Enc(x_i) Enc(y_i) = Enc(Sum_i x_i y_i).
* decrypt a ciphertext with a secret key
## Homomorphic operations
* homomorphic addtion/substraction over ciphertexts of the same ciphertext class
* homomorphic addition/subtraction over ciphertexts of the same ciphertext class
* homomprphic multiplication over ciphertext of CipherTextG1 and CipherTextG2
* The class of the result is CipherTextGT.
@ -39,7 +39,7 @@ Sum_i Enc(x_i) Enc(y_i) = Enc(Sum_i x_i y_i).
* 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)`.
* The maximum `m/s` is set by `setTryNum(tryNum)`.
## Zero-knowledge proof class
* A zero-knowledge proof is simultaneously created when encrypting a plaintext `m`.
@ -66,7 +66,7 @@ and read `she.js`.
## A sample for JS
```
```js
// initialize a library
she.init().then(() => {
const sec = new she.SecretKey()
@ -103,7 +103,7 @@ she.init().then(() => {
# A sample for C++
How to build the library, see [mcl](https://github.com/herumi/mcl/#installation-requirements).
```
```c++
#include <mcl/she.hpp>
int main()
try
@ -255,7 +255,7 @@ PK means PublicKey or PrecomputedPublicKey
* `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)
* `CT 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)
@ -281,7 +281,9 @@ PK means PublicKey or PrecomputedPublicKey
* ZkpBinEq ; verify whether `m1 = m2 = 0` or `1` for ciphertexts `encG1(m1)` and `encG2(m2)`
### API
PK = PublicKey or PrecomputedPublicKey
- SK = SecretKey
- PK = PublicKey or PrecomputedPublicKey
- AUX = AuxiliaryForZkpDecGT
* `void PK::encWithZkpBin(CipherTextG1& c, Zkp& zkp, int m) const`(C++)
* `void PK::encWithZkpBin(CipherTextG2& c, Zkp& zkp, int m) const`(C++)
@ -296,6 +298,14 @@ PK = PublicKey or PrecomputedPublicKey
* `[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
* `SK::decWithZkp(DecZkpDec& zkp, const CipherTextG1& c, const PublicKey& pub) const`(C++)
* `[m, ZkpDecG1] SK::decWithZkpDec(c, pub)`(JS)
* decrypt CipherTextG1 `c` and get `m` and zkp, which proves that `dec(c) = m`.
* `pub` is used for reducing some computation.
* `SK::decWithZkpDec(ZkpDecGT& zkp, const CipherTextGT& c, const AuxiliaryForZkpDecGT& aux) const`(C++)
* `[m, ZkpDecGT] SK::decWithZkpDecGT(c, aux)`(JS)
* decrypt CipherTextGT `c` and get `m` and zkp, which proves that `dec(c) = m`.
* `aux = pub.getAuxiliaryForZkpDecGT()`, which is used for reducing some computation.
## Global functions

@ -0,0 +1,18 @@
p=21888242871839275222246405745257275088696311157297823662689037894645226208583
print("over 253 bit")
for i in range (10):
print(i, (p * i) >> 253)
def maxarg(x):
return x // p
print("maxarg")
for i in range(16):
print(i, maxarg(i << 253))
x=0x2c130429c1d4802eb8703197d038ebd5109f96aee333bd027963094f5bb33ad
y = x * 9
print(hex(y))

@ -8,6 +8,10 @@ if "%1"=="dll" (
rem nasm -f win64 -D_WIN64 src\asm\low_x86-64.asm
rem lib /OUT:lib\mcl.lib /nodefaultlib fp.obj src\asm\low_x86-64.obj
if "%1"=="dll" (
set CFLAGS=%CFLAGS% /DMCL_NO_AUTOLINK /DMCLBN_NO_AUTOLINK
)
echo cl /c %CFLAGS% src\fp.cpp /Foobj\fp.obj
cl /c %CFLAGS% src\fp.cpp /Foobj\fp.obj
echo lib /nologo /OUT:lib\mcl.lib /nodefaultlib obj\fp.obj
@ -15,22 +19,17 @@ echo lib /nologo /OUT:lib\mcl.lib /nodefaultlib obj\fp.obj
if "%1"=="dll" (
echo cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj
cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj /DMCLBN_NO_AUTOLINK
cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj
echo link /nologo /DLL /OUT:bin\mclbn256.dll obj\bn_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn256.lib
link /nologo /DLL /OUT:bin\mclbn256.dll obj\bn_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn256.lib
echo cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj
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
echo cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
echo link /nologo /DLL /OUT:bin\mclbn384_256.dll obj\bn_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384_256.lib
link /nologo /DLL /OUT:bin\mclbn384_256.dll obj\bn_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384_256.lib
echo cl /c %CFLAGS% src\she_c384_256.cpp /Foobj\she_c384_256.obj /DMCLBN_NO_AUTOLINK
cl /c %CFLAGS% src\she_c384_256.cpp /Foobj\she_c384_256.obj /DMCLBN_NO_AUTOLINK
echo cl /c %CFLAGS% src\she_c384_256.cpp /Foobj\she_c384_256.obj /DMCL_NO_AUTOLINK
cl /c %CFLAGS% src\she_c384_256.cpp /Foobj\she_c384_256.obj /DMCL_NO_AUTOLINK
echo link /nologo /DLL /OUT:bin\mclshe384_256.dll obj\she_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c384_256.lib
link /nologo /DLL /OUT:bin\mclshe384_256.dll obj\she_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c384_256.lib
) else (
@ -38,7 +37,7 @@ if "%1"=="dll" (
cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj
lib /nologo /OUT:lib\mclbn256.lib /nodefaultlib obj\bn_c256.obj lib\mcl.lib
echo cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj
cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj
lib /nologo /OUT:lib\mclbn384.lib /nodefaultlib obj\bn_c384.obj lib\mcl.lib
echo cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
lib /nologo /OUT:lib\mclbn384_256.lib /nodefaultlib obj\bn_c384_256.obj lib\mcl.lib
)

@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/herumi/mcl.png)](https://travis-ci.org/herumi/mcl)
[![Build Status](https://github.com/herumi/mcl/actions/workflows/main.yml/badge.svg)](https://github.com/herumi/mcl/actions/workflows/main.yml)
# mcl
@ -6,173 +6,141 @@ A portable and fast pairing-based cryptography library.
# Abstract
mcl is a library for pairing-based cryptography.
The current version supports the optimal Ate pairing over BN curves and BLS12-381 curves.
mcl is a library for pairing-based cryptography,
which supports the optimal Ate pairing over BN curves and BLS12-381 curves.
# News
* mclBn_setETHserialization(true) (de)serialize acoording to [ETH2.0 serialization of BLS12-381](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/bls_signature.md#point-representations) when BLS12-381 is used.
* (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.
- improve M1 mac performance
- set default `MCL_MAX_BIT_SIZE=512` so disable to support `NICT_P521`.
- improve performance
- support M1 mac
- dst for mapToG1 has changed to `BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_POP_`.
- `mclBn_eth*` functions are removed.
- `mcl::bn::mapToG1(G1& out, const Fp& v)` supports `BLS12_MAP_FP_TO_G1` in [EIP 2537](https://eips.ethereum.org/EIPS/eip-2537).
- `mcl::bn::hashAndMapToG1(G1& out, const void *msg, size_t msgSize)` supports ([hash-to-curve-09 BLS12381G1_XMD:SHA-256_SSWU_RO_](https://www.ietf.org/id/draft-irtf-cfrg-hash-to-curve-09.html#name-bls12381g1_xmdsha-256_sswu_))
- `MCL_MAP_TO_MODE_HASH_TO_CURVE_07` is added for [hash-to-curve-draft-07](https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/07/).
# Support architecture
* x86-64 Windows + Visual Studio
* x86, x86-64 Linux + gcc/clang
* ARM Linux
* ARM64 Linux
* (maybe any platform to be supported by LLVM)
* WebAssembly
- x86-64 Windows + Visual Studio
- x86, x86-64 Linux + gcc/clang
- x86-64, M1 macOS
- ARM / ARM64 Linux
- WebAssembly
- Android
- iPhone
- (maybe any platform to be supported by LLVM)
# Support curves
p(z) = 36z^4 + 36z^3 + 24z^2 + 6z + 1.
* BN254 ; a BN curve over the 254-bit prime p(z) where z = -(2^62 + 2^55 + 1).
* BN\_SNARK1 ; a BN curve over a 254-bit prime p such that n := p + 1 - t has high 2-adicity.
* BN381\_1 ; a BN curve over the 381-bit prime p(z) where z = -(2^94 + 2^76 + 2^72 + 1).
* BN462 ; a BN curve over the 462-bit prime p(z) where z = 2^114 + 2^101 - 2^14 - 1.
* BLS12\_381 ; [a BLS12-381 curve](https://blog.z.cash/new-snark-curve/)
# Benchmark
## The latest benchmark(2018/11/7)
### Intel Core i7-6700 3.4GHz(Skylake), Ubuntu 18.04.1 LTS
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|
### Intel Core i7-7700 3.6GHz(Kaby Lake), Ubuntu 18.04.1 LTS on Windows 10 Vmware
- BN curve ; p(z) = 36z^4 + 36z^3 + 24z^2 + 6z + 1.
- BN254 ; a BN curve over the 254-bit prime p(z) where z = -(2^62 + 2^55 + 1).
- BN\_SNARK1 ; a BN curve over a 254-bit prime p such that n := p + 1 - t has high 2-adicity.
- BN381\_1 ; a BN curve over the 381-bit prime p(z) where z = -(2^94 + 2^76 + 2^72 + 1).
- BN462 ; a BN curve over the 462-bit prime p(z) where z = 2^114 + 2^101 - 2^14 - 1.
- BLS12\_381 ; [a BLS12-381 curve](https://blog.z.cash/new-snark-curve/)
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|
# C-API
see [api.md](api.md)
* now investigating the reason why gcc is slower than clang.
# How to build on Linux and macOS
x86-64/ARM/ARM64 Linux, macOS and mingw64 are supported.
## Higher-bit BN curve benchmark
## Installation Requirements
For JavaScript(WebAssembly), see [ID based encryption demo](https://herumi.github.io/mcl-wasm/ibe-demo.html).
[GMP](https://gmplib.org/) is necessary (default setting).
paramter | x64| Firefox on x64|Safari on iPhone7|
-----------|-----|---------------|-----------------|
BN254 | 0.25| 2.48| 4.78|
BN381\_1 | 0.95| 7.91| 11.74|
BN462 | 2.16| 14.73| 22.77|
* x64 : 'Kaby Lake Core i7-7700(3.6GHz)'.
* Firefox : 64-bit version 58.
* iPhone7 : iOS 11.2.1.
* BN254 is by `test/bn_test.cpp`.
* BN381\_1 and BN462 are by `test/bn512_test.cpp`.
* All the timings are given in ms(milliseconds).
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"
apt install libgmp-dev # on Ubuntu
```
# Installation Requirements
## How to build with Makefile
* [GMP](https://gmplib.org/) and OpenSSL
```
apt install libgmp-dev libssl-dev
git clone git://github.com/herumi/mcl
cd mcl
make -j4
```
Create a working directory (e.g., work) and clone the following repositories.
- `lib/libmcl.*` ; core library
- `lib/libmclbn384_256.*` ; library to use C-API of BLS12-381 pairing
## How to test of BLS12-381 pairing
```
mkdir work
cd work
git clone git://github.com/herumi/mcl
git clone git://github.com/herumi/cybozulib_ext ; for only Windows
# C
make bin/bn_c384_256_test.exe && bin/bn_c384_256_test.exe
# C++
make bin/bls12_test.exe && bin/bls12_test.exe
```
* Cybozulib\_ext is a prerequisite for running OpenSSL and GMP on VC (Visual C++).
# (Option) Without GMP
## How to build 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`
Define `MCL_USE_VINT` if using C++ header files.
# Build and test on x86-64 Linux, macOS, ARM and ARM64 Linux
To make lib/libmcl.a and test it:
```
cd work/mcl
make test
```
To benchmark a pairing:
```
bin/bn_test.exe
```
To make sample programs:
## How to profile on Linux
### Use perf
```
make sample
make MCL_USE_PROF=1 bin/bls12_test.exe
env MCL_PROF=1 bin/bls12_test.exe
```
if you want to change compiler options for optimization, then set `CFLAGS_OPT_USER`.
### Use Intel VTune profiler
Supporse VTune is installed in `/opt/intel/vtune_amplifier/`.
```
make CLFAGS_OPT_USER="-O2"
make MCL_USE_PROF=2 bin/bls12_test.exe
env MCL_PROF=2 bin/bls12_test.exe
```
## Build for 32-bit Linux
Build openssl and gmp for 32-bit mode and install `<lib32>`
## How to build on 32-bit x86 Linux
Build GMP for 32-bit mode (`env ABI=32 ./configure --enable-cxx ...`) and install `<lib32>` at yourself.
```
make ARCH=x86 CFLAGS_USER="-I <lib32>/include" LDFLAGS_USER="-L <lib32>/lib -Wl,-rpath,<lib32>/lib"
```
## Build for 64-bit Windows
1) make static library and use it
# How to build on 64-bit Windows with Visual Studio
Open a console window, and
```
git clone https://github.com/herumi/mcl
cd mcl
# static library
mklib
mk -s test\bn_c256_test.cpp
bin\bn_c256_test.exe
```
2) make dynamic library and use it
mk -s test\bls12_test.cpp && bin\bls12_test.exe
```
# dynamic library
mklib dll
mk -d test\bn_c256_test.cpp
bin\bn_c256_test.exe
mk -d test\bls12_test.cpp && bin\bls12_test.exe
```
open mcl.sln and build or if you have msbuild.exe
(not maintenanced)
Open mcl.sln and build or if you have msbuild.exe
```
msbuild /p:Configuration=Release
```
## Build with cmake
For Linux,
# C# test
```
cd mcl
mklib dll
cd ffi/cs
dotnet build mcl.sln
cd ../../bin
../ffi/cs/test/bin/Debug/netcoreapp3.1/test.exe
```
# How to build with CMake
For Linux, macOS, etc.
```
mkdir build
cd build
@ -186,228 +154,122 @@ cd build
cmake .. -A x64
msbuild mcl.sln /p:Configuration=Release /m
```
## Build for wasm(WebAssembly)
mcl supports emcc (Emscripten) and `test/bn_test.cpp` runs on browers such as Firefox, Chrome and Edge.
* [IBE on browser](https://herumi.github.io/mcl-wasm/ibe-demo.html)
* [SHE on browser](https://herumi.github.io/she-wasm/she-demo.html)
* [BLS signature on brower](https://herumi.github.io/bls-wasm/bls-demo.html)
The timing of a pairing on `BN254` is 2.8msec on 64-bit Firefox with Skylake 3.4GHz.
For your convenience you could use the build script `build.sh` on Linux, macOS and
Windows (requires Git Bash).
### Node.js
On Windows, `build.sh` expects [cybozulib_ext](https://github.com/herumi/cybozulib_ext) to be within the same parent directory, otherwise, it will be downloaded into `external\cybozulib_ext` directory.
* [mcl-wasm](https://www.npmjs.com/package/mcl-wasm) pairing library
* [bls-wasm](https://www.npmjs.com/package/bls-wasm) BLS signature library
* [she-wasm](https://www.npmjs.com/package/she-wasm) 2 Level Homomorphic Encryption library
## options
### SELinux
mcl uses Xbyak JIT engine if it is available on x64 architecture,
otherwise mcl uses a little slower functions generated by LLVM.
The default mode enables SELinux security policy on CentOS, then JIT is disabled.
```
% sudo setenforce 1
% getenforce
Enforcing
% bin/bn_test.exe
JIT 0
pairing 1.496Mclk
finalExp 581.081Kclk
% sudo setenforce 0
% getenforce
Permissive
% bin/bn_test.exe
JIT 1
pairing 1.394Mclk
finalExp 546.259Kclk
cmake .. MCL_USE_GMP=OFF ; without GMP
```
see `cmake .. -LA`.
# Libraries
* G1 and G2 is defined over Fp
* The order of G1 and G2 is r.
* Use `bn256.hpp` if only BN254 is used.
## C++ library
* libmcl.a ; static 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|
--------------|-------------------------|---------|---------|
bn256.hpp |BN254 | 32 | 32 |
bls12_381.hpp |BLS12_381, BN254 | 32 | 48 |
bn384.hpp |BN381_1, BLS12_381, BN254| 48 | 48 |
## C library
* 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*.so ; shared C library
### 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.
## tests
make test binaries in `./bin`.
```
#include <mcl/bn256.hpp>
mcl::bn::CurveParam cp = mcl::BN254; // or mcl::BN_SNARK1
mcl::bn256::initPairing(cp);
mcl::bn256::G1 P(...);
mcl::bn256::G2 Q(...);
mcl::bn256::Fp12 e;
mcl::bn256::pairing(e, P, Q);
cmake .. -DBUILD_TESTING=ON
make -j4
```
1. (BN254) a BN curve over the 254-bit prime p = p(z) where z = -(2^62 + 2^55 + 1).
2. (BN_SNARK1) a BN curve over a 254-bit prime p such that n := p + 1 - t has high 2-adicity.
3. BN381_1 with `mcl/bn384.hpp`.
4. BN462 with `mcl/bn512.hpp`.
See [test/bn_test.cpp](https://github.com/herumi/mcl/blob/master/test/bn_test.cpp).
## Default constructor of Fp, Ec, etc.
A default constructor does not initialize the instance.
Set a valid value before reffering it.
## Definition of groups
The curve equation for a BN curve is:
E/Fp: y^2 = x^3 + b .
* the cyclic group G1 is instantiated as E(Fp)[n] where n := p + 1 - t;
* the cyclic group G2 is instantiated as the inverse image of E'(Fp^2)[n] under a twisting isomorphism phi from E' to E; and
* the pairing e: G1 x G2 -> Fp12 is the optimal ate pairing.
The field Fp12 is constructed via the following tower:
* Fp2 = Fp[u] / (u^2 + 1)
* Fp6 = Fp2[v] / (v^3 - Xi) where Xi = u + 1
* Fp12 = Fp6[w] / (w^2 - v)
* GT = { x in Fp12 | x^r = 1 }
# How to build for wasm(WebAssembly)
mcl supports emcc (Emscripten) and `test/bn_test.cpp` runs on browers such as Firefox, Chrome and Edge.
## Curve Parameter
r = |G1| = |G2| = |GT|
* [IBE on browser](https://herumi.github.io/mcl-wasm/ibe-demo.html)
* [SHE on browser](https://herumi.github.io/she-wasm/she-demo.html)
* [BLS signature on brower](https://herumi.github.io/bls-wasm/bls-demo.html)
curveType | hexadecimal number|
------------|-------------------|
BN254 r | 2523648240000001ba344d8000000007ff9f800000000010a10000000000000d |
BN254 p | 2523648240000001ba344d80000000086121000000000013a700000000000013 |
BN381 r | 240026400f3d82b2e42de125b00158405b710818ac000007e0042f008e3e00000000001080046200000000000000000d |
BN381 p | 240026400f3d82b2e42de125b00158405b710818ac00000840046200950400000000001380052e000000000000000013 |
BN462 r | 240480360120023ffffffffff6ff0cf6b7d9bfca0000000000d812908ee1c201f7fffffffff6ff66fc7bf717f7c0000000002401b007e010800d |
BN462 r | 240480360120023ffffffffff6ff0cf6b7d9bfca0000000000d812908f41c8020ffffffffff6ff66fc6ff687f640000000002401b00840138013 |
BLS12-381 r | 73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 |
BLS12-381 r | 1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab |
The timing of a pairing on `BN254` is 2.8msec on 64-bit Firefox with Skylake 3.4GHz.
## Arithmetic operations
# Node.js
G1 and G2 is additive group and has the following operations:
* [mcl-wasm](https://www.npmjs.com/package/mcl-wasm) pairing library
* [bls-wasm](https://www.npmjs.com/package/bls-wasm) BLS signature library
* [she-wasm](https://www.npmjs.com/package/she-wasm) 2 Level Homomorphic Encryption library
* T::add(T& z, const T& x, const T& y); // z = x + y
* T::sub(T& z, const T& x, const T& y); // z = x - y
* T::neg(T& y, const T& x); // y = -x
* T::mul(T& z, const T& x, const INT& y); // z = y times scalar multiplication of x
# Benchmark
Remark: &z == &x or &y are allowed. INT means integer type such as Fr, int and mpz_class.
## The latest benchmark(2018/11/7)
`T::mul` uses GLV method then `G2::mul` returns wrong value if x is not in G2.
Use `T::mulGeneric(T& z, const T& x, const INT& y)` for x in phi^-1(E'(Fp^2)) - G2.
### Intel Core i7-6700 3.4GHz(Skylake), Ubuntu 18.04.1 LTS
Fp, Fp2, Fp6 and Fp12 have the following operations:
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|
* T::add(T& z, const T& x, const T& y); // z = x + y
* T::sub(T& z, const T& x, const T& y); // z = x - y
* T::mul(T& z, const T& x, const T& y); // z = x * y
* T::div(T& z, const T& x, const T& y); // z = x / y
* T::neg(T& y, const T& x); // y = -x
* T::inv(T& y, const T& x); // y = 1/x
* T::pow(T& z, const T& x, const INT& y); // z = x^y
* Fp12::unitaryInv(T& y, const T& x); // y = conjugate of x
### Intel Core i7-7700 3.6GHz(Kaby Lake), Ubuntu 18.04.1 LTS on Windows 10 Vmware
Remark: `Fp12::mul` uses GLV method then returns wrong value if x is not in GT.
Use `Fp12::mulGeneric` for x in Fp12 - GT.
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|
## Map To points
* now investigating the reason why gcc is slower than clang.
Use these functions to make a point of G1 and G2.
## Higher-bit BN curve benchmark
* 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);
For JavaScript(WebAssembly), see [ID based encryption demo](https://herumi.github.io/mcl-wasm/ibe-demo.html).
These functions maps x into Gi according to [\[_Faster hashing to G2_\]].
paramter | x64| Firefox on x64|Safari on iPhone7|
-----------|-----|---------------|-----------------|
BN254 | 0.25| 2.48| 4.78|
BN381\_1 | 0.95| 7.91| 11.74|
BN462 | 2.16| 14.73| 22.77|
## String format of G1 and G2
G1 and G2 have three elements of Fp (x, y, z) for Jacobi coordinate.
normalize() method normalizes it to affine coordinate (x, y, 1) or (0, 0, 0).
* x64 : 'Kaby Lake Core i7-7700(3.6GHz)'.
* Firefox : 64-bit version 58.
* iPhone7 : iOS 11.2.1.
* BN254 is by `test/bn_test.cpp`.
* BN381\_1 and BN462 are by `test/bn512_test.cpp`.
* All the timings are given in ms(milliseconds).
getStr() method gets
The other benchmark results are [bench.txt](bench.txt).
* `0` ; infinity
* `1 <x> <y>` ; not compressed format
* `2 <x>` ; compressed format for even y
* `3 <x>` ; compressed format for odd y
## An old benchmark of a BN curve BN254(2016/12/25).
## Generator of G1 and G2
* 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/)
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,
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
```
// G1 P
P.setStr('1 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569')
// G2 Q
Q.setStr('1 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582')
cmake -DARITH=x64-asm-254 -DFP_PRIME=254 -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP"
```
## 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
# SELinux
mcl uses Xbyak JIT engine if it is available on x64 architecture,
otherwise mcl uses a little slower functions generated by LLVM.
The default mode enables SELinux security policy on CentOS, then JIT is disabled.
```
% sudo setenforce 1
% getenforce
Enforcing
% bin/bn_test.exe
JIT 0
pairing 1.496Mclk
finalExp 581.081Kclk
## 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.
If you check it out of the library, then you can stop the verification by calling `G2::verifyOrderG2(false)`.
% sudo setenforce 0
% getenforce
Permissive
% bin/bn_test.exe
JIT 1
pairing 1.394Mclk
finalExp 546.259Kclk
```
# How to make asm files (optional)
The asm files generated by this way are already put in `src/asm`, then it is not necessary to do this.
@ -430,7 +292,7 @@ K. Shimizu, and T. Teruya. ASIACCS 2018
* [she-api(Japanese)](https://github.com/herumi/mcl/blob/master/misc/she/she-api-ja.md)
# Java API
See [java.md](https://github.com/herumi/mcl/blob/master/java/java.md)
See [java.md](https://github.com/herumi/mcl/blob/master/ffi/java/java.md)
# License
@ -438,8 +300,8 @@ modified new BSD License
http://opensource.org/licenses/BSD-3-Clause
This library contains some part of the followings software licensed by BSD-3-Clause.
* [xbyak](https://github.com/heurmi/xbyak)
* [cybozulib](https://github.com/heurmi/cybozulib)
* [xbyak](https://github.com/herumi/xbyak)
* [cybozulib](https://github.com/herumi/cybozulib)
* [Lifted-ElGamal](https://github.com/aistcrypt/Lifted-ElGamal)
# References
@ -450,24 +312,56 @@ This library contains some part of the followings software licensed by BSD-3-Cla
* [_High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig Curves_](http://dx.doi.org/10.1007/978-3-642-17455-1_2),
Jean-Luc Beuchat, Jorge Enrique González Díaz, Shigeo Mitsunari, Eiji Okamoto, Francisco Rodríguez-Henríquez, Tadanori Teruya,
Pairing 2010, ([preprint](http://eprint.iacr.org/2010/354))
* [_Faster hashing to G2_](http://dx.doi.org/10.1007/978-3-642-28496-0_25),Laura Fuentes-Castañeda, Edward Knapp, Francisco Rodríguez-Henríquez,
SAC 2011, ([preprint](https://eprint.iacr.org/2008/530))
* [_Faster hashing to G2_](https://link.springer.com/chapter/10.1007/978-3-642-28496-0_25),Laura Fuentes-Castañeda, Edward Knapp, Francisco Rodríguez-Henríquez,
SAC 2011, ([PDF](http://cacr.uwaterloo.ca/techreports/2011/cacr2011-26.pdf))
* [_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.
# compatilibity
- mclBnGT_inv returns a - b w, a conjugate of x for x = a + b w in Fp12 = Fp6[w]
- use mclBnGT_invGeneric if x is not in GT
- mclBn_setETHserialization(true) (de)serialize acoording to [ETH2.0 serialization of BLS12-381](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/bls_signature.md#point-representations) when BLS12-381 is used.
- (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.
# History
* 2019/Apr/29 v0.94 mclBn_setETHserialization supports [ETH2.0 serialization of BLS12-381](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/bls_signature.md#point-representations)
* 2019/Apr/24 v0.93 support ios
* 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)
- 2021/May/24 v1.40 fix sigsegv in valgrind
- 2021/Jan/28 v1.31 fix : call setOrder in init for isValidOrder
- 2021/Jan/28 v1.30 a little optimization of Fp operations
- 2020/Nov/14 v1.28 support M1 mac
- 2020/Jun/07 v1.22 remove old hash-to-curve functions
- 2020/Jun/04 v1.21 mapToG1 and hashAndMapToG1 are compatible to irtf/eip-2537
- 2020/May/13 v1.09 support draft-irtf-cfrg-hash-to-curve-07
- 2020/Mar/26 v1.07 change DST for hash-to-curve-06
- 2020/Mar/15 v1.06 support hash-to-curve-06
- 2020/Jan/31 v1.05 mclBn_ethMsgToFp2 has changed to append zero byte at the end of msg
- 2020/Jan/25 v1.04 add new hash functions
- 2019/Dec/05 v1.03 disable to check the order in setStr
- 2019/Sep/30 v1.00 add some functions to bn.h ; [api.md](api.md).
- 2019/Sep/22 v0.99 add mclBnG1_mulVec, etc.
- 2019/Sep/08 v0.98 bugfix Ec::add(P, Q, R) when P == R
- 2019/Aug/14 v0.97 add some C api functions
- 2019/Jul/26 v0.96 improved scalar multiplication
- 2019/Jun/03 v0.95 fix a parser of 0b10 with base = 16
- 2019/Apr/29 v0.94 mclBn_setETHserialization supports [ETH2.0 serialization of BLS12-381](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/bls_signature.md#point-representations)
- 2019/Apr/24 v0.93 support ios
- 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)
MITSUNARI Shigeo(herumi@nifty.com)
# Sponsors welcome
[GitHub Sponsor](https://github.com/sponsors/herumi)

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

Loading…
Cancel
Save