Compare commits

..

662 Commits

Author SHA1 Message Date
Hao Chen fec57a49f5 Merge tag 'v1.51' into mm 3 years ago
MITSUNARI Shigeo a4fe1155c3 v1.51 4 years ago
MITSUNARI Shigeo bacb6573fc remove cast of function 4 years ago
MITSUNARI Shigeo 86dd59e3c3 avoid cast of Fp::sub/neg/mul/sqr/mul2/mul9 4 years ago
MITSUNARI Shigeo ead99eb002 avoid cast of Fp::add 4 years ago
MITSUNARI Shigeo 3be037a853 tweak 4 years ago
MITSUNARI Shigeo 8f195134f7 avoid cast in Fp2Dbl::mul_xi 4 years ago
MITSUNARI Shigeo de21f2ea4c avoid cast of Fp2Dbl::mulPre 4 years ago
MITSUNARI Shigeo 0f141988bd tweak 4 years ago
MITSUNARI Shigeo e25fc2fa62 refactor cast of Fp2T 4 years ago
MITSUNARI Shigeo 125451649c use FpDbl in Fp2::inv 4 years ago
MITSUNARI Shigeo f474245e87 avoid cast in Fp2::inv 4 years ago
MITSUNARI Shigeo 02a51c8077 avoid cast of Fp2::mul_xi 4 years ago
MITSUNARI Shigeo 5f95d70767 avoid cast of Fp2::mul2 4 years ago
MITSUNARI Shigeo 7d56a7fbf8 avoid cast of Fp2::sqr 4 years ago
MITSUNARI Shigeo 646f008ded avoid cast of Fp2::mul 4 years ago
MITSUNARI Shigeo 76e87c23c6 avoid cast of Fp2::neg 4 years ago
MITSUNARI Shigeo a36e6f276b avoid cast of Fp2::sub 4 years ago
MITSUNARI Shigeo bb83774fad avoid cast of Fp2::add 4 years ago
MITSUNARI Shigeo 676488081a avoid cast of fpDbl_addPre/subPre 4 years ago
MITSUNARI Shigeo 55cd686b22 avoid cast of fpDbl_mod 4 years ago
MITSUNARI Shigeo 52a83ac526 avoid cast of fpDbl_sub 4 years ago
MITSUNARI Shigeo 5dcd5c53b7 avoid cast of fpDbl_add 4 years ago
MITSUNARI Shigeo 1653541c0a fix init bool 4 years ago
MITSUNARI Shigeo 093e916151 fix for (bitlen(p) + 1) % 64 = 0 4 years ago
MITSUNARI Shigeo 7806835e9c [pedantic] avoid undefined behavior of abs 4 years ago
MITSUNARI Shigeo 3a2f09ca73 compatible setByCSPRNG for big-endian 4 years ago
MITSUNARI Shigeo 2e397d13dc v1.50 4 years ago
MITSUNARI Shigeo a1ae68e806 Merge branch 'dev' 4 years ago
MITSUNARI Shigeo 61947e921c update doc for s390x 4 years ago
MITSUNARI Shigeo 9f1a685097 ensure validness of proj code 4 years ago
MITSUNARI Shigeo 20dad03800 IoArrayRaw outputs little endian 4 years ago
MITSUNARI Shigeo dec82f6f1d Fp::load/save support big endian 4 years ago
MITSUNARI Shigeo 35b2682699 refactor getLittleEndian 4 years ago
MITSUNARI Shigeo f83f1ccb72 set{Little/Big}EndianMod takes const uint8_t* 4 years ago
MITSUNARI Shigeo 6c5fda3e62 refactor convertArrayAsLE 4 years ago
MITSUNARI Shigeo 385efd3fc5 remove MaskMode 4 years ago
MITSUNARI Shigeo a1cf697e91 remove unused functions 4 years ago
MITSUNARI Shigeo 04b13fb039 refactor setArrayMask and requires unsigned 4 years ago
MITSUNARI Shigeo a4efdaee14 refactor setArray and requires unsigned 4 years ago
MITSUNARI Shigeo 852804f15b refactor setArrayMod 4 years ago
MITSUNARI Shigeo dd0b16ca3f refactoring setArray 4 years ago
MITSUNARI Shigeo 8ff04a209a copyUnitToByteAsLE is removed 4 years ago
MITSUNARI Shigeo 687445ca41 remove unused warning 4 years ago
MITSUNARI Shigeo 9c3782c3b9 rename setArrayAsLE to convertArrayAsLE 4 years ago
MITSUNARI Shigeo 71ae0bb970 getArray supports big endian 4 years ago
MITSUNARI Shigeo 580d574c7a fix test/arrayToDec for big endian 4 years ago
MITSUNARI Shigeo f25fe506b3 refine arrayToDec 4 years ago
MITSUNARI Shigeo e15bfe5157 fix comment of setHashOf 4 years ago
MITSUNARI Shigeo 9080ac305e remove cast in decToArray 4 years ago
MITSUNARI Shigeo 79624a1fec config.hpp define const var 4 years ago
MITSUNARI Shigeo 1c699118c6 split fp::setArrayAsLE 4 years ago
MITSUNARI Shigeo a26075e566 setArray accepts only unsigned 4 years ago
MITSUNARI Shigeo bb08a49249 fix sign for alised var for Vint::divMod 4 years ago
MITSUNARI Shigeo 3c4abd4c3c fix sign for alised var for Vint::quotRem 4 years ago
MITSUNARI Shigeo dcd5404185 setArray on big endian 4 years ago
MITSUNARI Shigeo 6b4850093a add macro for systemz 4 years ago
MITSUNARI Shigeo dd702ba232 finalExp checks zero 4 years ago
MITSUNARI Shigeo 17b8da25e0 Revert "finalExp checks zero for safety" 4 years ago
MITSUNARI Shigeo 8e9144e1af finalExp checks zero for safety 4 years ago
MITSUNARI Shigeo f796cfc915 [go] check buf is zero 4 years ago
MITSUNARI Shigeo f76f7f69e1 avoid cast of Fp2DblT::sqrPre 4 years ago
MITSUNARI Shigeo f412f768a4 avoid cast of FpDbl::mulPre, sqrPre 4 years ago
MITSUNARI Shigeo 551c462467 add comment Fp::load 4 years ago
MITSUNARI Shigeo 4cc28add06 update doc 4 years ago
MITSUNARI Shigeo b01ef452a5 fix expand_message_xmd for dst with size > 255 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 5 years ago
MITSUNARI Shigeo f3f27d5b0d maxMulVecNGLV can be redefined 5 years ago
MITSUNARI Shigeo f6c46616ed update xbyak 5 years ago
MITSUNARI Shigeo 74f1b42f72 some old eth* functions will be duplicated 5 years ago
MITSUNARI Shigeo 3acf697650 reduce stack size for Gi::mul 5 years ago
MITSUNARI Shigeo 7fe3e07cdb [doc] fix link 5 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) 6 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. 111
      Makefile
  6. 548
      api.md
  7. 67
      build.sh
  8. 88
      cmake/FindGMP.cmake
  9. 56
      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. 681
      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. 19
      ffi/java/elgamal_impl.hpp
  44. 124
      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. 13
      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. 915
      include/mcl/bn.hpp
  74. 34
      include/mcl/config.hpp
  75. 102
      include/mcl/conversion.hpp
  76. 87
      include/mcl/curve_type.h
  77. 1664
      include/mcl/ec.hpp
  78. 105
      include/mcl/ecdsa.h
  79. 257
      include/mcl/ecdsa.hpp
  80. 28
      include/mcl/ecparam.hpp
  81. 2
      include/mcl/elgamal.hpp
  82. 352
      include/mcl/fp.hpp
  83. 715
      include/mcl/fp_tower.hpp
  84. 205
      include/mcl/gmp_util.hpp
  85. 200
      include/mcl/impl/bn_c_impl.hpp
  86. 572
      include/mcl/mapto_wb19.hpp
  87. 57
      include/mcl/op.hpp
  88. 46
      include/mcl/operator.hpp
  89. 27
      include/mcl/she.h
  90. 317
      include/mcl/she.hpp
  91. 78
      include/mcl/util.hpp
  92. 163
      include/mcl/vint.hpp
  93. 34
      include/mcl/window_method.hpp
  94. 6
      misc/Makefile
  95. 234
      misc/low_test.cpp
  96. 119
      misc/she/memo.txt
  97. 14
      misc/she/she-api-ja.md
  98. 24
      misc/she/she-api.md
  99. 18
      misc/snark-p.py
  100. 29
      mklib.bat
  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 *.exe
*.swp *.swp
.cvsignore .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) cmake_minimum_required (VERSION 3.8)
project(mcl CXX ASM)
set(SRCS src/fp.cpp) project(mcl
VERSION 1.22
LANGUAGES CXX C ASM)
set(CMAKE_BUILD_TYPE "Release")
option( option(
MCL_MAX_BIT_SIZE MCL_MAX_BIT_SIZE
"max bit size for Fp" "max bit size for Fp"
0 384
) )
option( option(
DOWNLOAD_SOURCE MCL_STATIC_LIB
"download cybozulib_ext" "build static library"
OFF OFF
) )
if(MSVC)
option(
MCL_DOWNLOAD_SOURCE
"download cybozulib_ext"
OFF
)
endif()
option( option(
USE_OPENSSL MCL_USE_OPENSSL
"use openssl" "use openssl"
ON OFF
) )
option( option(
USE_GMP MCL_USE_GMP
"use gmp" "use gmp"
ON ON
) )
option( option(
USE_ASM MCL_USE_ASM
"use asm" "use asm"
ON ON
) )
option( option(
USE_XBYAK MCL_USE_XBYAK
"use xbyak" "use xbyak"
ON ON
) )
option( option(
USE_LLVM MCL_USE_LLVM
"use base64.ll with -DCMAKE_CXX_COMPILER=clang++" "use base64.ll with -DCMAKE_CXX_COMPILER=clang++"
OFF OFF
) )
option( option(
ONLY_LIB MCL_BUILD_SAMPLE
"only lib" "Build mcl samples"
OFF 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_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(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_executable(gen src/gen.cpp)
add_custom_target(base64.ll target_include_directories(gen PRIVATE
DEPENDS gen ${CMAKE_CURRENT_SOURCE_DIR}/include)
SOURCES base64.ll if(MCL_USE_GMP)
) find_package(GMP REQUIRED)
target_link_libraries(gen PRIVATE GMP::GMPXX GMP::GMP)
endif()
add_custom_command(OUTPUT base64.ll add_custom_command(OUTPUT base64.ll
COMMAND gen > base64.ll COMMAND gen > base64.ll
) DEPENDS gen
add_custom_target(base64.o WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
DEPENDS base64.ll add_custom_target(gen_base64.ll
SOURCES base64.o SOURCES ${CMAKE_CURRENT_BINARY_DIR}/base64.ll)
)
add_custom_command(OUTPUT base64.o add_custom_command(OUTPUT base64.o
COMMAND ${CMAKE_CXX_COMPILER} -c -o base64.o base64.ll -O3 -fPIC 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() endif()
if(MSVC) if(MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MT /W4 /Oy /Ox /EHsc /GS- /Zi /DNDEBUG /DNOMINMAX") if(MCL_MSVC_RUNTIME_DLL)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /MTd /W4 /DNOMINMAX") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MD /Oy /Ox /EHsc /GS- /Zi /DNDEBUG")
link_directories(${CMAKE_SOURCE_DIR}/../cybozulib_ext/lib) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /MDd")
link_directories(${CMAKE_SOURCE_DIR}/lib) else()
else() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MT /Oy /Ox /EHsc /GS- /Zi /DNDEBUG")
if("${CFLAGS_OPT_USER}" STREQUAL "") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /MTd")
set(CFLAGS_OPT_USER "-O3 -DNDEBUG -march=native")
endif() 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) 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() endif()
if(USE_LLVM) if(MCL_USE_LLVM AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_definitions(-DMCL_USE_LLVM=1 -DMCL_LLVM_BMI2=0) target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1 MCL_LLVM_BMI2=0)
elseif(USE_ASM) target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1 MCL_LLVM_BMI2=0)
elseif(MCL_USE_ASM)
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
add_definitions(-DMCL_USE_LLVM=1) target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/aarch64.s) 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) set(CPU arch64)
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm") elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm")
add_definitions(-DMCL_USE_LLVM=1) target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/arm.s) 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) set(CPU arm)
elseif(APPLE) elseif(APPLE)
add_definitions(-DMCL_USE_LLVM=1) target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/x86-64mac.s src/asm/x86-64mac.bmi2.s) 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) set(CPU x86-64)
elseif(UNIX) elseif(UNIX)
add_definitions(-DMCL_USE_LLVM=1) target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/x86-64.s src/asm/x86-64.bmi2.s) 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) set(CPU x86-64)
endif() endif()
endif() endif()
if(USE_GMP) if(MCL_USE_GMP)
set(EXT_LIBS ${EXT_LIBS} gmp gmpxx) find_package(GMP REQUIRED)
target_link_libraries(mcl PUBLIC GMP::GMPXX GMP::GMP)
target_link_libraries(mcl_st PUBLIC GMP::GMPXX GMP::GMP)
endif() endif()
if(USE_OPENSSL) if(MCL_USE_OPENSSL)
set(EXT_LIBS ${EXT_LIBS} crypto) find_package(OpenSSL REQUIRED)
target_link_libraries(mcl PUBLIC OpenSSL::Crypto)
target_link_libraries(mcl_st PUBLIC OpenSSL::Crypto)
endif() endif()
endif() endif()
if(NOT USE_GMP) if(NOT MCL_USE_GMP)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER") 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() endif()
if(NOT USE_OPENSSL) if(NOT MCL_USE_OPENSSL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_DONT_USE_OPENSSL") target_compile_definitions(mcl PUBLIC MCL_DONT_USE_OPENSSL)
target_compile_definitions(mcl_st PUBLIC MCL_DONT_USE_OPENSSL)
endif() endif()
if(NOT USE_XBYAK) if(NOT MCL_USE_XBYAK)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_DONT_USE_XBYAK") target_compile_definitions(mcl PUBLIC MCL_DONT_USE_XBYAK)
target_compile_definitions(mcl_st PUBLIC MCL_DONT_USE_XBYAK)
endif() endif()
if(DOWNLOAD_SOURCE) if(MCL_DOWNLOAD_SOURCE)
if(MSVC) if(MSVC)
set(CYBOZULIB_EXT_DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/cybozulib_ext)
set(CYBOZULIB_EXT_TAG release20170521) 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) 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}) 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}) message("download cybozulib_ext/" ${file})
endforeach() 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) 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}) 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}) message("download cybozulib_ext/openssl/" ${file})
endforeach() endforeach()
set(FILES mpir.lib mpirxx.lib mpirxx.pdb ssleay32.lib libeay32.lib mpir.pdb) set(FILES mpir.lib mpirxx.lib mpirxx.pdb ssleay32.lib libeay32.lib mpir.pdb)
foreach(file IN ITEMS ${FILES}) 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}) message("download lib/mt/14/" ${file})
endforeach() endforeach()
if(MSVC)
include_directories( # mpir
${mcl_SOURCE_DIR}/include/cybozulib_ext add_library(cybozulib_ext::mpir STATIC IMPORTED)
) set_target_properties(cybozulib_ext::mpir PROPERTIES
endif() 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() endif()
else() else()
if(MSVC) if(MSVC)
include_directories( # mpir
${mcl_SOURCE_DIR}/../cybozulib_ext/include 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()
endif() endif()
include_directories( # mclbnXXX
${mcl_SOURCE_DIR}/include 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) if(MSVC)
add_library(mcl SHARED ${SRCS} base64.o) install(TARGETS mcl mcl_st mclbn256 mclbn384 mclbn384_256 windows_specific
add_library(mcl_st STATIC ${SRCS} base64.o) EXPORT mclTargets
add_dependencies(mcl base64.o) LIBRARY DESTINATION lib
add_dependencies(mcl_st base64.o) ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib)
else() else()
add_library(mcl SHARED ${SRCS}) install(TARGETS mcl mcl_st mclbn256 mclbn384 mclbn384_256
add_library(mcl_st STATIC ${SRCS}) EXPORT mclTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib)
endif() endif()
target_link_libraries(mcl ${EXT_LIBS}) install(DIRECTORY include/mcl
target_link_libraries(mcl_st ${EXT_LIBS}) DESTINATION include
set_target_properties(mcl_st PROPERTIES OUTPUT_NAME mcl) FILES_MATCHING PATTERN "*.hpp"
#set_target_properties(mcl_st PROPERTIES PREFIX "lib") PATTERN "curve_type.h"
#set_target_properties(mcl PROPERTIES OUTPUT_NAME mcl VERSION 1.0.0 SOVERSION 1) PATTERN "bn.h"
# For semantics of ABI compatibility including when you must bump SOVERSION, see: PATTERN "bn_c256.h"
# https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B#The_Do.27s_and_Don.27ts PATTERN "bn_c384_256.h"
PATTERN "bn_c384.h")
install(DIRECTORY include/cybozu
DESTINATION include
FILES_MATCHING PATTERN "*.hpp")
set(LIBS mcl ${EXT_LIBS}) install(EXPORT mclTargets
foreach(bit IN ITEMS 256 384 384_256 512) FILE mclTargets.cmake
add_library(mclbn${bit} SHARED src/bn_c${bit}.cpp) NAMESPACE mcl::
target_link_libraries(mclbn${bit} ${LIBS}) DESTINATION lib/cmake/mcl)
add_executable(bn_c${bit}_test test/bn_c${bit}_test.cpp)
target_link_libraries(bn_c${bit}_test mclbn${bit})
endforeach()
file(GLOB MCL_HEADERS include/mcl/*.hpp include/mcl/bn.h include/mcl/curve_type.h) # support local build-tree export to allow import from external projects
file(GLOB CYBOZULIB_HEADERS include/cybozu/*.hpp) export(EXPORT mclTargets
FILE mclTargets.cmake
install(TARGETS mcl DESTINATION lib) NAMESPACE mcl::)
install(TARGETS mcl_st DESTINATION lib) set(CMAKE_EXPORT_PACKAGE_REGISTRY ON)
install(TARGETS mclbn256 DESTINATION lib) export(PACKAGE mcl)
install(TARGETS mclbn384 DESTINATION lib)
install(TARGETS mclbn384_256 DESTINATION lib)
install(TARGETS mclbn512 DESTINATION lib) # Tests
install(FILES ${MCL_HEADERS} DESTINATION include/mcl) if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MCL_BUILD_TESTING)
install(FILES include/mcl/impl/bn_c_impl.hpp DESTINATION include/mcl/impl) AND BUILD_TESTING)
install(FILES ${CYBOZULIB_HEADERS} DESTINATION include/cybozu) enable_testing()
add_subdirectory(test)
if(NOT ONLY_LIB) endif()
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) if(MCL_BUILD_SAMPLE)
foreach(base IN ITEMS ${TEST_BASE}) # sample code
add_executable( add_subdirectory(sample)
${base}
test/${base}.cpp
)
target_link_libraries(
${base}
${LIBS}
)
endforeach()
endif() endif()

@ -2,14 +2,19 @@ include common.mk
LIB_DIR=lib LIB_DIR=lib
OBJ_DIR=obj OBJ_DIR=obj
EXE_DIR=bin EXE_DIR=bin
SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c512.cpp she_c256.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 ecdsa_test.cpp conversion_test.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+=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+=she_c256_test.cpp she_c384_test.cpp she_c384_256_test.cpp
TEST_SRC+=aggregate_sig_test.cpp array_test.cpp TEST_SRC+=aggregate_sig_test.cpp array_test.cpp
TEST_SRC+=bls12_test.cpp TEST_SRC+=bls12_test.cpp
TEST_SRC+=ecdsa_c_test.cpp TEST_SRC+=mapto_wb19_test.cpp
TEST_SRC+=modp_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) ifeq ($(CPU),x86-64)
MCL_USE_XBYAK?=1 MCL_USE_XBYAK?=1
TEST_SRC+=mont_fp_test.cpp sq_test.cpp TEST_SRC+=mont_fp_test.cpp sq_test.cpp
@ -28,6 +33,13 @@ endif
ifeq ($(MCL_USE_XBYAK),0) ifeq ($(MCL_USE_XBYAK),0)
CFLAGS+=-DMCL_DONT_USE_XBYAK CFLAGS+=-DMCL_DONT_USE_XBYAK
endif 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_LIB=$(LIB_DIR)/libmcl.a
MCL_SNAME=mcl MCL_SNAME=mcl
@ -53,20 +65,19 @@ SHE384_LIB=$(LIB_DIR)/libmclshe384.a
SHE384_SLIB=$(LIB_DIR)/lib$(SHE384_SNAME).$(LIB_SUF) SHE384_SLIB=$(LIB_DIR)/lib$(SHE384_SNAME).$(LIB_SUF)
SHE384_256_LIB=$(LIB_DIR)/libmclshe384_256.a SHE384_256_LIB=$(LIB_DIR)/libmclshe384_256.a
SHE384_256_SLIB=$(LIB_DIR)/lib$(SHE384_256_SNAME).$(LIB_SUF) 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) 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_VER=-3.8
LLVM_LLC=llc$(LLVM_VER) LLVM_LLC=llc$(LLVM_VER)
LLVM_OPT=opt$(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=src/gen
GEN_EXE_OPT=-u $(BIT) GEN_EXE_OPT=-u $(BIT)
# incompatibility between llvm 3.4 and the later version # incompatibility between llvm 3.4 and the later version
ifneq ($(LLVM_OPT_VERSION),) ifneq ($(LLVM_OPT_VERSION),)
ifeq ($(shell expr $(LLVM_OPT_VERSION) \< 3.5.0),1) ifeq ($(shell expr $(LLVM_OPT_VERSION) \>= 9),1)
GEN_EXE_OPT+=-old GEN_EXE_OPT+=-ver 0x90
endif endif
endif endif
ifeq ($(OS),mac) ifeq ($(OS),mac)
@ -82,7 +93,6 @@ ifeq ($(OS),mac-m1)
ASM_SRC=src/base64.ll ASM_SRC=src/base64.ll
ASM_OBJ=$(OBJ_DIR)/base64.o ASM_OBJ=$(OBJ_DIR)/base64.o
endif endif
LIB_OBJ=$(OBJ_DIR)/fp.o
BN256_OBJ=$(OBJ_DIR)/bn_c256.o BN256_OBJ=$(OBJ_DIR)/bn_c256.o
BN384_OBJ=$(OBJ_DIR)/bn_c384.o BN384_OBJ=$(OBJ_DIR)/bn_c384.o
BN384_256_OBJ=$(OBJ_DIR)/bn_c384_256.o BN384_256_OBJ=$(OBJ_DIR)/bn_c384_256.o
@ -90,7 +100,6 @@ BN512_OBJ=$(OBJ_DIR)/bn_c512.o
SHE256_OBJ=$(OBJ_DIR)/she_c256.o SHE256_OBJ=$(OBJ_DIR)/she_c256.o
SHE384_OBJ=$(OBJ_DIR)/she_c384.o SHE384_OBJ=$(OBJ_DIR)/she_c384.o
SHE384_256_OBJ=$(OBJ_DIR)/she_c384_256.o SHE384_256_OBJ=$(OBJ_DIR)/she_c384_256.o
ECDSA_OBJ=$(OBJ_DIR)/ecdsa_c.o
FUNC_LIST=src/func.list FUNC_LIST=src/func.list
ifeq ($(findstring $(OS),mingw64/cygwin),) ifeq ($(findstring $(OS),mingw64/cygwin),)
MCL_USE_LLVM?=1 MCL_USE_LLVM?=1
@ -102,7 +111,9 @@ ifeq ($(MCL_USE_LLVM),1)
LIB_OBJ+=$(ASM_OBJ) LIB_OBJ+=$(ASM_OBJ)
# special case for intel with bmi2 # special case for intel with bmi2
ifeq ($(INTEL),1) ifeq ($(INTEL),1)
LIB_OBJ+=$(OBJ_DIR)/$(CPU).bmi2.o ifneq ($(MCL_STATIC_CODE),1)
LIB_OBJ+=$(OBJ_DIR)/$(CPU).bmi2.o
endif
endif endif
endif endif
LLVM_SRC=src/base$(BIT).ll LLVM_SRC=src/base$(BIT).ll
@ -139,15 +150,6 @@ ifneq ($(findstring $(OS),mac/mingw64),)
SHE384_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib SHE384_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
SHE384_256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib SHE384_256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
endif endif
ifneq ($(findstring $(OS),mac/mac-m1/mingw64),)
BN256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
BN384_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
BN384_256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
BN512_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
SHE256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
SHE384_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
SHE384_256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
endif
ifeq ($(OS),mingw64) ifeq ($(OS),mingw64)
MCL_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(MCL_SNAME).a MCL_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(MCL_SNAME).a
BN256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN256_SNAME).a BN256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN256_SNAME).a
@ -186,9 +188,6 @@ $(SHE384_SLIB): $(SHE384_OBJ) $(MCL_LIB)
$(SHE384_256_SLIB): $(SHE384_256_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) $(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) $(BN256_SLIB): $(BN256_OBJ) $(MCL_SLIB)
$(PRE)$(CXX) -o $@ $(BN256_OBJ) -shared $(LDFLAGS) $(BN256_SLIB_LDFLAGS) $(PRE)$(CXX) -o $@ $(BN256_OBJ) -shared $(LDFLAGS) $(BN256_SLIB_LDFLAGS)
@ -240,8 +239,20 @@ else
endif endif
$(GEN_EXE): src/gen.cpp src/llvm_gen.hpp $(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) asm: $(LLVM_SRC)
$(LLVM_OPT) -O3 -o - $(LLVM_SRC) | $(LLVM_LLC) -O3 $(LLVM_FLAGS) -x86-asm-syntax=intel $(LLVM_OPT) -O3 -o - $(LLVM_SRC) | $(LLVM_LLC) -O3 $(LLVM_FLAGS) -x86-asm-syntax=intel
@ -300,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) $(EXE_DIR)/bn_c512_test.exe: $(OBJ_DIR)/bn_c512_test.o $(BN512_LIB) $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(BN512_LIB) $(MCL_LIB) $(LDFLAGS) $(PRE)$(CXX) $< -o $@ $(BN512_LIB) $(MCL_LIB) $(LDFLAGS)
$(EXE_DIR)/pairing_c.exe: $(OBJ_DIR)/pairing_c.o $(BN256_LIB) $(MCL_LIB) $(EXE_DIR)/pairing_c.exe: $(OBJ_DIR)/pairing_c.o $(BN384_256_LIB) $(MCL_LIB)
$(PRE)$(CC) $< -o $@ $(BN256_LIB) $(MCL_LIB) $(LDFLAGS) -lstdc++ $(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) $(EXE_DIR)/she_c256_test.exe: $(OBJ_DIR)/she_c256_test.o $(SHE256_LIB) $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(SHE256_LIB) $(MCL_LIB) $(LDFLAGS) $(PRE)$(CXX) $< -o $@ $(SHE256_LIB) $(MCL_LIB) $(LDFLAGS)
@ -312,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) $(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) $(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 $(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) $(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)
@ -326,7 +334,7 @@ sample: $(SAMPLE_EXE) $(MCL_LIB)
TEST_EXE=$(addprefix $(EXE_DIR)/,$(TEST_SRC:.cpp=.exe)) TEST_EXE=$(addprefix $(EXE_DIR)/,$(TEST_SRC:.cpp=.exe))
test_ci: $(TEST_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) test: $(TEST_EXE)
@echo test $(TEST_EXE) @echo test $(TEST_EXE)
@sh -ec 'for i in $(TEST_EXE); do $$i|grep "ctest:name"; done' > result.txt @sh -ec 'for i in $(TEST_EXE); do $$i|grep "ctest:name"; done' > result.txt
@ -334,7 +342,7 @@ test: $(TEST_EXE)
EMCC_OPT=-I./include -I./src -Wall -Wextra EMCC_OPT=-I./include -I./src -Wall -Wextra
EMCC_OPT+=-O3 -DNDEBUG -DMCLSHE_WIN_SIZE=8 EMCC_OPT+=-O3 -DNDEBUG -DMCLSHE_WIN_SIZE=8
EMCC_OPT+=-s WASM=1 -s NO_EXIT_RUNTIME=1 -s MODULARIZE=1 #-s ASSERTIONS=1 EMCC_OPT+=-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+=-DCYBOZU_MINIMUM_EXCEPTION
EMCC_OPT+=-s ABORTING_MALLOC=0 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 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
@ -343,37 +351,18 @@ ifeq ($(MCL_USE_LLVM),2)
EMCC_OPT+=src/base64m.ll -DMCL_USE_LLVM EMCC_OPT+=src/base64m.ll -DMCL_USE_LLVM
SHE_C_DEP+=src/base64m.ll SHE_C_DEP+=src/base64m.ll
endif 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 # test
bin/emu: 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 $(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 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_tbl:
$(MAKE) ../bls/src/qcoeff-bn254.hpp $(MAKE) ../bls/src/qcoeff-bn254.hpp
@ -389,7 +378,7 @@ update_cybozulib:
cp -a $(addprefix ../cybozulib/,$(wildcard include/cybozu/*.hpp)) include/cybozu/ cp -a $(addprefix ../cybozulib/,$(wildcard include/cybozu/*.hpp)) include/cybozu/
clean: 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) ALL_SRC=$(SRC_SRC) $(TEST_SRC) $(SAMPLE_SRC)
DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC)))) DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC))))
@ -398,12 +387,12 @@ DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC))))
PREFIX?=/usr/local PREFIX?=/usr/local
install: lib/libmcl.a lib/libmcl.$(LIB_SUF) install: lib/libmcl.a lib/libmcl.$(LIB_SUF)
$(MKDIR) $(PREFIX)/include/mcl $(MKDIR) $(PREFIX)/include/mcl
cp -a include/mcl/ $(PREFIX)/include/ cp -a include/mcl $(PREFIX)/include/
cp -a include/cybozu/ $(PREFIX)/include/ cp -a include/cybozu $(PREFIX)/include/
$(MKDIR) $(PREFIX)/lib $(MKDIR) $(PREFIX)/lib
cp -a lib/libmcl.a lib/libmcl.$(LIB_SUF) $(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 # don't remove these files automatically
.SECONDARY: $(addprefix $(OBJ_DIR)/, $(ALL_SRC:.cpp=.o)) .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,12 +1,14 @@
GCC_VER=$(shell $(PRE)$(CC) -dumpversion) GCC_VER=$(shell $(PRE)$(CC) -dumpversion)
UNAME_S=$(shell uname -s) UNAME_S=$(shell uname -s)
ARCH?=$(shell uname -m) ARCH?=$(shell uname -m)
NASM_ELF_OPT=-felf64
ifeq ($(UNAME_S),Linux) ifeq ($(UNAME_S),Linux)
OS=Linux OS=Linux
endif endif
ifeq ($(findstring MINGW64,$(UNAME_S)),MINGW64) ifeq ($(findstring MINGW64,$(UNAME_S)),MINGW64)
OS=mingw64 OS=mingw64
CFLAGS+=-D__USE_MINGW_ANSI_STDIO=1 CFLAGS+=-D__USE_MINGW_ANSI_STDIO=1
NASM_ELF_OPT=-fwin64
endif endif
ifeq ($(findstring CYGWIN,$(UNAME_S)),CYGWIN) ifeq ($(findstring CYGWIN,$(UNAME_S)),CYGWIN)
OS=cygwin OS=cygwin
@ -14,20 +16,27 @@ endif
ifeq ($(UNAME_S),Darwin) ifeq ($(UNAME_S),Darwin)
ifeq ($(ARCH),x86_64) ifeq ($(ARCH),x86_64)
OS=mac OS=mac
GMP_DIR?=/usr/local/opt/gmp
else else
OS=mac-m1 OS=mac-m1
GMP_DIR?=/opt/homebrew/opt/gmp
endif endif
LIB_SUF=dylib LIB_SUF=dylib
OPENSSL_DIR?=/opt/homebrew/opt/openssl@1.1 NASM_ELF_OPT=-fmacho64
CFLAGS+=-I$(OPENSSL_DIR)/include
LDFLAGS+=-L$(OPENSSL_DIR)/lib
CFLAGS+=-I$(GMP_DIR)/include
LDFLAGS+=-L$(GMP_DIR)/lib
else else
LIB_SUF=so LIB_SUF=so
endif endif
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),) ifneq ($(findstring $(ARCH),x86_64/amd64),)
CPU=x86-64 CPU=x86-64
INTEL=1 INTEL=1
@ -46,11 +55,12 @@ ifeq ($(ARCH),x86)
BIT_OPT=-m32 BIT_OPT=-m32
#LOW_ASM_SRC=src/asm/low_x86.asm #LOW_ASM_SRC=src/asm/low_x86.asm
endif endif
ifeq ($(ARCH),armv7l) ifneq ($(findstring $(ARCH),armv7l/armv6l),)
CPU=arm CPU=arm
BIT=32 BIT=32
#LOW_ASM_SRC=src/asm/low_arm.s #LOW_ASM_SRC=src/asm/low_arm.s
endif endif
#ifeq ($(ARCH),aarch64)
ifneq ($(findstring $(ARCH),aarch64/arm64),) ifneq ($(findstring $(ARCH),aarch64/arm64),)
CPU=aarch64 CPU=aarch64
BIT=64 BIT=64
@ -58,6 +68,10 @@ endif
ifeq ($(findstring $(OS),mac/mac-m1/mingw64/openbsd),) ifeq ($(findstring $(OS),mac/mac-m1/mingw64/openbsd),)
LDFLAGS+=-lrt LDFLAGS+=-lrt
endif endif
ifeq ($(ARCH),s390x)
CPU=systemz
BIT=64
endif
CP=cp -f CP=cp -f
AR=ar r AR=ar r
@ -70,12 +84,12 @@ ifeq ($(DEBUG),1)
LDFLAGS+=-fsanitize=address LDFLAGS+=-fsanitize=address
endif endif
else else
CFLAGS_OPT+=-fomit-frame-pointer -DNDEBUG CFLAGS_OPT+=-fomit-frame-pointer -DNDEBUG -fno-stack-protector
ifeq ($(CXX),clang++) ifeq ($(CXX),clang++)
CFLAGS_OPT+=-O3 CFLAGS_OPT+=-O3
else else
ifeq ($(shell expr $(GCC_VER) \> 4.6.0),1) ifeq ($(shell expr $(GCC_VER) \> 4.6.0),1)
CFLAGS_OPT+=-Ofast CFLAGS_OPT+=-O3
else else
CFLAGS_OPT+=-O3 CFLAGS_OPT+=-O3
endif endif
@ -88,7 +102,7 @@ else
CFLAGS_OPT+=$(MARCH) CFLAGS_OPT+=$(MARCH)
endif endif
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 CFLAGS+=-g3
INC_OPT=-I include -I test INC_OPT=-I include -I test
CFLAGS+=$(CFLAGS_WARN) $(BIT_OPT) $(INC_OPT) CFLAGS+=$(CFLAGS_WARN) $(BIT_OPT) $(INC_OPT)
@ -99,7 +113,10 @@ CFLAGS+=$(CFLAGS_OPT_USER)
endif endif
CFLAGS+=$(CFLAGS_USER) CFLAGS+=$(CFLAGS_USER)
MCL_USE_GMP?=1 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) ifeq ($(MCL_USE_GMP),0)
CFLAGS+=-DMCL_USE_VINT CFLAGS+=-DMCL_USE_VINT
endif endif
@ -111,9 +128,24 @@ ifeq ($(MCL_USE_OPENSSL),0)
endif endif
ifeq ($(MCL_USE_GMP),1) ifeq ($(MCL_USE_GMP),1)
GMP_LIB=-lgmp -lgmpxx 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 endif
ifeq ($(MCL_USE_OPENSSL),1) ifeq ($(MCL_USE_OPENSSL),1)
OPENSSL_LIB=-L${OPENSSL_DIR}/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 endif
LDFLAGS+=$(GMP_LIB) $(OPENSSL_LIB) $(BIT_OPT) $(LDFLAGS_USER) LDFLAGS+=$(GMP_LIB) $(OPENSSL_LIB) $(BIT_OPT) $(LDFLAGS_USER)

@ -4,125 +4,126 @@ using System.Runtime.InteropServices;
namespace mcl { namespace mcl {
public class BN256 { public class BN256 {
[DllImport("mclBn256.dll")] public const string dllName = "mclBn256";
[DllImport(dllName)]
public static extern int mclBn_init(int curve, int compiledTimeVar); public static extern int mclBn_init(int curve, int compiledTimeVar);
[DllImport("mclBn256.dll")] [DllImport(dllName)]
public static extern void mclBnFr_clear(ref Fr x); 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); 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); 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); 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); 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); public static extern int mclBnFr_isZero(ref Fr x);
[DllImport("mclBn256.dll")] [DllImport(dllName)]
public static extern int mclBnFr_isOne(ref Fr x); public static extern int mclBnFr_isOne(ref Fr x);
[DllImport("mclBn256.dll")] [DllImport(dllName)]
public static extern void mclBnFr_setByCSPRNG(ref Fr x); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); public static extern int mclBnGT_isZero(ref GT x);
[DllImport("mclBn256.dll")] [DllImport(dllName)]
public static extern int mclBnGT_isOne(ref GT x); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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 extern void mclBn_millerLoop(ref GT z, ref G1 x, ref G2 y);
public static void init() 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 "C"
import "fmt" import "fmt"
// Init -- // Init --
// call this function before calling all the other operations // call this function before calling all the other operations
// this function is not thread safe // this function is not thread safe
@ -21,5 +22,3 @@ func Init(curve int) error {
} }
return nil return nil
} }

@ -19,18 +19,27 @@ const CurveFp382_1 = C.mclBn_CurveFp382_1
// CurveFp382_2 -- 382 bit curve 2 // CurveFp382_2 -- 382 bit curve 2
const CurveFp382_2 = C.mclBn_CurveFp382_2 const CurveFp382_2 = C.mclBn_CurveFp382_2
// BLS12_381 // BLS12_381 --
const BLS12_381 = C.MCL_BLS12_381 const BLS12_381 = C.MCL_BLS12_381
// IoSerializeHexStr // IoSerializeHexStr --
const IoSerializeHexStr = C.MCLBN_IO_SERIALIZE_HEX_STR 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 { func GetFrUnitSize() int {
return int(C.MCLBN_FR_UNIT_SIZE) return int(C.MCLBN_FR_UNIT_SIZE)
} }
// GetFpUnitSize() -- // GetFpUnitSize --
// same as GetMaxOpUnitSize() // same as GetMaxOpUnitSize()
func GetFpUnitSize() int { func GetFpUnitSize() int {
return int(C.MCLBN_FP_UNIT_SIZE) return int(C.MCLBN_FP_UNIT_SIZE)
@ -47,6 +56,34 @@ func GetOpUnitSize() int {
return int(C.mclBn_getOpUnitSize()) 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
}
// allow zero length byte
func getPointer(msg []byte) unsafe.Pointer {
if len(msg) == 0 {
return nil
}
return unsafe.Pointer(&msg[0])
}
// GetCurveOrder -- // GetCurveOrder --
// return the order of G1 // return the order of G1
func GetCurveOrder() string { func GetCurveOrder() string {
@ -71,6 +108,42 @@ func GetFieldOrder() string {
return string(buf[:n]) 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 -- // Fr --
type Fr struct { type Fr struct {
v C.mclBnFr v C.mclBnFr
@ -98,7 +171,7 @@ func (x *Fr) SetInt64(v int64) {
func (x *Fr) SetString(s string, base int) error { func (x *Fr) SetString(s string, base int) error {
buf := []byte(s) buf := []byte(s)
// #nosec // #nosec
err := C.mclBnFr_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) err := C.mclBnFr_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base))
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBnFr_setStr %x", err) return fmt.Errorf("err mclBnFr_setStr %x", err)
} }
@ -108,8 +181,8 @@ func (x *Fr) SetString(s string, base int) error {
// Deserialize -- // Deserialize --
func (x *Fr) Deserialize(buf []byte) error { func (x *Fr) Deserialize(buf []byte) error {
// #nosec // #nosec
err := C.mclBnFr_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) n := C.mclBnFr_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err == 0 { if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnFr_deserialize %x", buf) return fmt.Errorf("err mclBnFr_deserialize %x", buf)
} }
return nil return nil
@ -118,13 +191,33 @@ func (x *Fr) Deserialize(buf []byte) error {
// SetLittleEndian -- // SetLittleEndian --
func (x *Fr) SetLittleEndian(buf []byte) error { func (x *Fr) SetLittleEndian(buf []byte) error {
// #nosec // #nosec
err := C.mclBnFr_setLittleEndian(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) err := C.mclBnFr_setLittleEndian(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBnFr_setLittleEndian %x", err) return fmt.Errorf("err mclBnFr_setLittleEndian %x", err)
} }
return nil return nil
} }
// SetLittleEndianMod --
func (x *Fr) SetLittleEndianMod(buf []byte) error {
// #nosec
err := C.mclBnFr_setLittleEndianMod(x.getPointer(), getPointer(buf), 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(), getPointer(buf), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFr_setBigEndianMod %x", err)
}
return nil
}
// IsEqual -- // IsEqual --
func (x *Fr) IsEqual(rhs *Fr) bool { func (x *Fr) IsEqual(rhs *Fr) bool {
return C.mclBnFr_isEqual(x.getPointer(), rhs.getPointer()) == 1 return C.mclBnFr_isEqual(x.getPointer(), rhs.getPointer()) == 1
@ -135,11 +228,26 @@ func (x *Fr) IsZero() bool {
return C.mclBnFr_isZero(x.getPointer()) == 1 return C.mclBnFr_isZero(x.getPointer()) == 1
} }
// IsValid --
func (x *Fr) IsValid() bool {
return C.mclBnFr_isValid(x.getPointer()) == 1
}
// IsOne -- // IsOne --
func (x *Fr) IsOne() bool { func (x *Fr) IsOne() bool {
return C.mclBnFr_isOne(x.getPointer()) == 1 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 -- // SetByCSPRNG --
func (x *Fr) SetByCSPRNG() { func (x *Fr) SetByCSPRNG() {
err := C.mclBnFr_setByCSPRNG(x.getPointer()) err := C.mclBnFr_setByCSPRNG(x.getPointer())
@ -151,7 +259,7 @@ func (x *Fr) SetByCSPRNG() {
// SetHashOf -- // SetHashOf --
func (x *Fr) SetHashOf(buf []byte) bool { func (x *Fr) SetHashOf(buf []byte) bool {
// #nosec // #nosec
return C.mclBnFr_setHashOf(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) == 0 return C.mclBnFr_setHashOf(x.getPointer(), getPointer(buf), C.size_t(len(buf))) == 0
} }
// GetString -- // GetString --
@ -186,6 +294,11 @@ func FrInv(out *Fr, x *Fr) {
C.mclBnFr_inv(out.getPointer(), x.getPointer()) C.mclBnFr_inv(out.getPointer(), x.getPointer())
} }
// FrSqr --
func FrSqr(out *Fr, x *Fr) {
C.mclBnFr_sqr(out.getPointer(), x.getPointer())
}
// FrAdd -- // FrAdd --
func FrAdd(out *Fr, x *Fr, y *Fr) { func FrAdd(out *Fr, x *Fr, y *Fr) {
C.mclBnFr_add(out.getPointer(), x.getPointer(), y.getPointer()) C.mclBnFr_add(out.getPointer(), x.getPointer(), y.getPointer())
@ -206,9 +319,289 @@ func FrDiv(out *Fr, x *Fr, y *Fr) {
C.mclBnFr_div(out.getPointer(), x.getPointer(), y.getPointer()) 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)(getPointer(buf)), 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(), getPointer(buf), 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(), getPointer(buf), 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(), getPointer(buf), 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(), getPointer(buf), 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(), getPointer(buf), 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(), getPointer(buf), 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 -- // G1 --
type G1 struct { type G1 struct {
v C.mclBnG1 X Fp
Y Fp
Z Fp
} }
// getPointer -- // getPointer --
@ -227,7 +620,7 @@ func (x *G1) Clear() {
func (x *G1) SetString(s string, base int) error { func (x *G1) SetString(s string, base int) error {
buf := []byte(s) buf := []byte(s)
// #nosec // #nosec
err := C.mclBnG1_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) err := C.mclBnG1_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base))
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBnG1_setStr %x", err) return fmt.Errorf("err mclBnG1_setStr %x", err)
} }
@ -237,13 +630,54 @@ func (x *G1) SetString(s string, base int) error {
// Deserialize -- // Deserialize --
func (x *G1) Deserialize(buf []byte) error { func (x *G1) Deserialize(buf []byte) error {
// #nosec // #nosec
err := C.mclBnG1_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) n := C.mclBnG1_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err == 0 { if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnG1_deserialize %x", buf) return fmt.Errorf("err mclBnG1_deserialize %x", buf)
} }
return nil 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(), getPointer(buf), 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(), getPointer(buf), 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 -- // IsEqual --
func (x *G1) IsEqual(rhs *G1) bool { func (x *G1) IsEqual(rhs *G1) bool {
return C.mclBnG1_isEqual(x.getPointer(), rhs.getPointer()) == 1 return C.mclBnG1_isEqual(x.getPointer(), rhs.getPointer()) == 1
@ -254,10 +688,20 @@ func (x *G1) IsZero() bool {
return C.mclBnG1_isZero(x.getPointer()) == 1 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 -- // HashAndMapTo --
func (x *G1) HashAndMapTo(buf []byte) error { func (x *G1) HashAndMapTo(buf []byte) error {
// #nosec // #nosec
err := C.mclBnG1_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) err := C.mclBnG1_hashAndMapTo(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBnG1_hashAndMapTo %x", err) return fmt.Errorf("err mclBnG1_hashAndMapTo %x", err)
} }
@ -277,13 +721,39 @@ func (x *G1) GetString(base int) string {
// Serialize -- // Serialize --
func (x *G1) Serialize() []byte { func (x *G1) Serialize() []byte {
buf := make([]byte, 2048) buf := make([]byte, GetG1ByteSize())
// #nosec // #nosec
n := C.mclBnG1_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) n := C.mclBnG1_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
if n == 0 { if n == 0 {
panic("err mclBnG1_serialize") 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 -- // G1Neg --
@ -311,6 +781,19 @@ func G1Mul(out *G1, x *G1, y *Fr) {
C.mclBnG1_mul(out.getPointer(), x.getPointer(), y.getPointer()) 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) {
n := len(xVec)
if n != len(yVec) {
panic("xVec and yVec have the same size")
}
if n == 0 {
out.Clear()
return
}
C.mclBnG1_mulVec(out.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
}
// G1MulCT -- constant time (depending on bit lengh of y) // G1MulCT -- constant time (depending on bit lengh of y)
func G1MulCT(out *G1, x *G1, y *Fr) { func G1MulCT(out *G1, x *G1, y *Fr) {
C.mclBnG1_mulCT(out.getPointer(), x.getPointer(), y.getPointer()) C.mclBnG1_mulCT(out.getPointer(), x.getPointer(), y.getPointer())
@ -318,7 +801,9 @@ func G1MulCT(out *G1, x *G1, y *Fr) {
// G2 -- // G2 --
type G2 struct { type G2 struct {
v C.mclBnG2 X Fp2
Y Fp2
Z Fp2
} }
// getPointer -- // getPointer --
@ -337,7 +822,7 @@ func (x *G2) Clear() {
func (x *G2) SetString(s string, base int) error { func (x *G2) SetString(s string, base int) error {
buf := []byte(s) buf := []byte(s)
// #nosec // #nosec
err := C.mclBnG2_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) err := C.mclBnG2_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base))
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBnG2_setStr %x", err) return fmt.Errorf("err mclBnG2_setStr %x", err)
} }
@ -347,13 +832,38 @@ func (x *G2) SetString(s string, base int) error {
// Deserialize -- // Deserialize --
func (x *G2) Deserialize(buf []byte) error { func (x *G2) Deserialize(buf []byte) error {
// #nosec // #nosec
err := C.mclBnG2_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) n := C.mclBnG2_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err == 0 { if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnG2_deserialize %x", buf) return fmt.Errorf("err mclBnG2_deserialize %x", buf)
} }
return nil 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(), getPointer(buf), 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(), getPointer(buf), 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 -- // IsEqual --
func (x *G2) IsEqual(rhs *G2) bool { func (x *G2) IsEqual(rhs *G2) bool {
return C.mclBnG2_isEqual(x.getPointer(), rhs.getPointer()) == 1 return C.mclBnG2_isEqual(x.getPointer(), rhs.getPointer()) == 1
@ -364,10 +874,20 @@ func (x *G2) IsZero() bool {
return C.mclBnG2_isZero(x.getPointer()) == 1 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 -- // HashAndMapTo --
func (x *G2) HashAndMapTo(buf []byte) error { func (x *G2) HashAndMapTo(buf []byte) error {
// #nosec // #nosec
err := C.mclBnG2_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) err := C.mclBnG2_hashAndMapTo(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBnG2_hashAndMapTo %x", err) return fmt.Errorf("err mclBnG2_hashAndMapTo %x", err)
} }
@ -396,6 +916,32 @@ func (x *G2) Serialize() []byte {
return buf[:n] 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 -- // G2Neg --
func G2Neg(out *G2, x *G2) { func G2Neg(out *G2, x *G2) {
C.mclBnG2_neg(out.getPointer(), x.getPointer()) C.mclBnG2_neg(out.getPointer(), x.getPointer())
@ -421,6 +967,19 @@ func G2Mul(out *G2, x *G2, y *Fr) {
C.mclBnG2_mul(out.getPointer(), x.getPointer(), y.getPointer()) 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) {
n := len(xVec)
if n != len(yVec) {
panic("xVec and yVec have the same size")
}
if n == 0 {
out.Clear()
return
}
C.mclBnG2_mulVec(out.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
}
// GT -- // GT --
type GT struct { type GT struct {
v C.mclBnGT v C.mclBnGT
@ -448,7 +1007,7 @@ func (x *GT) SetInt64(v int64) {
func (x *GT) SetString(s string, base int) error { func (x *GT) SetString(s string, base int) error {
buf := []byte(s) buf := []byte(s)
// #nosec // #nosec
err := C.mclBnGT_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) err := C.mclBnGT_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base))
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBnGT_setStr %x", err) return fmt.Errorf("err mclBnGT_setStr %x", err)
} }
@ -458,8 +1017,8 @@ func (x *GT) SetString(s string, base int) error {
// Deserialize -- // Deserialize --
func (x *GT) Deserialize(buf []byte) error { func (x *GT) Deserialize(buf []byte) error {
// #nosec // #nosec
err := C.mclBnGT_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) n := C.mclBnGT_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err == 0 { if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnGT_deserialize %x", buf) return fmt.Errorf("err mclBnGT_deserialize %x", buf)
} }
return nil return nil
@ -537,6 +1096,22 @@ func GTPow(out *GT, x *GT, y *Fr) {
C.mclBnGT_pow(out.getPointer(), x.getPointer(), y.getPointer()) 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 -- // Pairing --
func Pairing(out *GT, x *G1, y *G2) { func Pairing(out *GT, x *G1, y *G2) {
C.mclBn_pairing(out.getPointer(), x.getPointer(), y.getPointer()) C.mclBn_pairing(out.getPointer(), x.getPointer(), y.getPointer())
@ -552,6 +1127,19 @@ func MillerLoop(out *GT, x *G1, y *G2) {
C.mclBn_millerLoop(out.getPointer(), x.getPointer(), y.getPointer()) 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) {
n := len(xVec)
if n != len(yVec) {
panic("xVec and yVec have the same size")
}
if n == 0 {
out.SetInt64(1)
return
}
C.mclBn_millerLoopVec(out.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
}
// GetUint64NumToPrecompute -- // GetUint64NumToPrecompute --
func GetUint64NumToPrecompute() int { func GetUint64NumToPrecompute() int {
return int(C.mclBn_getUint64NumToPrecompute()) return int(C.mclBn_getUint64NumToPrecompute())
@ -577,8 +1165,13 @@ func PrecomputedMillerLoop2(out *GT, P1 *G1, Q1buf []uint64, P2 *G1, Q2buf []uin
// FrEvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... // FrEvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ...
func FrEvaluatePolynomial(y *Fr, c []Fr, x *Fr) error { func FrEvaluatePolynomial(y *Fr, c []Fr, x *Fr) error {
n := len(c)
if n == 0 {
y.Clear()
return nil
}
// #nosec // #nosec
err := C.mclBn_FrEvaluatePolynomial(y.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer()) err := C.mclBn_FrEvaluatePolynomial(y.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&c[0])), (C.size_t)(n), x.getPointer())
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBn_FrEvaluatePolynomial") return fmt.Errorf("err mclBn_FrEvaluatePolynomial")
} }
@ -587,8 +1180,13 @@ func FrEvaluatePolynomial(y *Fr, c []Fr, x *Fr) error {
// G1EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... // G1EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ...
func G1EvaluatePolynomial(y *G1, c []G1, x *Fr) error { func G1EvaluatePolynomial(y *G1, c []G1, x *Fr) error {
n := len(c)
if n == 0 {
y.Clear()
return nil
}
// #nosec // #nosec
err := C.mclBn_G1EvaluatePolynomial(y.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer()) err := C.mclBn_G1EvaluatePolynomial(y.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&c[0])), (C.size_t)(n), x.getPointer())
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBn_G1EvaluatePolynomial") return fmt.Errorf("err mclBn_G1EvaluatePolynomial")
} }
@ -597,8 +1195,13 @@ func G1EvaluatePolynomial(y *G1, c []G1, x *Fr) error {
// G2EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... // G2EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ...
func G2EvaluatePolynomial(y *G2, c []G2, x *Fr) error { func G2EvaluatePolynomial(y *G2, c []G2, x *Fr) error {
n := len(c)
if n == 0 {
y.Clear()
return nil
}
// #nosec // #nosec
err := C.mclBn_G2EvaluatePolynomial(y.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer()) err := C.mclBn_G2EvaluatePolynomial(y.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&c[0])), (C.size_t)(n), x.getPointer())
if err != 0 { if err != 0 {
return fmt.Errorf("err mclBn_G2EvaluatePolynomial") return fmt.Errorf("err mclBn_G2EvaluatePolynomial")
} }
@ -607,11 +1210,15 @@ func G2EvaluatePolynomial(y *G2, c []G2, x *Fr) error {
// FrLagrangeInterpolation -- // FrLagrangeInterpolation --
func FrLagrangeInterpolation(out *Fr, xVec []Fr, yVec []Fr) error { func FrLagrangeInterpolation(out *Fr, xVec []Fr, yVec []Fr) error {
if len(xVec) != len(yVec) { n := len(xVec)
if n == 0 {
return fmt.Errorf("err FrLagrangeInterpolation:n=0")
}
if n != len(yVec) {
return fmt.Errorf("err FrLagrangeInterpolation:bad size") return fmt.Errorf("err FrLagrangeInterpolation:bad size")
} }
// #nosec // #nosec
err := C.mclBn_FrLagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec))) err := C.mclBn_FrLagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
if err != 0 { if err != 0 {
return fmt.Errorf("err FrLagrangeInterpolation") return fmt.Errorf("err FrLagrangeInterpolation")
} }
@ -620,11 +1227,15 @@ func FrLagrangeInterpolation(out *Fr, xVec []Fr, yVec []Fr) error {
// G1LagrangeInterpolation -- // G1LagrangeInterpolation --
func G1LagrangeInterpolation(out *G1, xVec []Fr, yVec []G1) error { func G1LagrangeInterpolation(out *G1, xVec []Fr, yVec []G1) error {
if len(xVec) != len(yVec) { n := len(xVec)
if n == 0 {
return fmt.Errorf("err G1LagrangeInterpolation:n=0")
}
if n != len(yVec) {
return fmt.Errorf("err G1LagrangeInterpolation:bad size") return fmt.Errorf("err G1LagrangeInterpolation:bad size")
} }
// #nosec // #nosec
err := C.mclBn_G1LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG1)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec))) err := C.mclBn_G1LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG1)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
if err != 0 { if err != 0 {
return fmt.Errorf("err G1LagrangeInterpolation") return fmt.Errorf("err G1LagrangeInterpolation")
} }
@ -633,11 +1244,15 @@ func G1LagrangeInterpolation(out *G1, xVec []Fr, yVec []G1) error {
// G2LagrangeInterpolation -- // G2LagrangeInterpolation --
func G2LagrangeInterpolation(out *G2, xVec []Fr, yVec []G2) error { func G2LagrangeInterpolation(out *G2, xVec []Fr, yVec []G2) error {
if len(xVec) != len(yVec) { n := len(xVec)
if n == 0 {
return fmt.Errorf("err G2LagrangeInterpolation:n=0")
}
if n != len(yVec) {
return fmt.Errorf("err G2LagrangeInterpolation:bad size") return fmt.Errorf("err G2LagrangeInterpolation:bad size")
} }
// #nosec // #nosec
err := C.mclBn_G2LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec))) err := C.mclBn_G2LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
if err != 0 { if err != 0 {
return fmt.Errorf("err G2LagrangeInterpolation") return fmt.Errorf("err G2LagrangeInterpolation")
} }

@ -2,6 +2,7 @@ package mcl
import "testing" import "testing"
import "fmt" import "fmt"
import "encoding/hex"
func testBadPointOfG2(t *testing.T) { func testBadPointOfG2(t *testing.T) {
var Q G2 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) { func testPairing(t *testing.T) {
var a, b, ab Fr var a, b, ab Fr
err := a.SetString("123", 10) 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) { func testMcl(t *testing.T, c int) {
err := Init(c) err := Init(c)
if err != nil { if err != nil {
@ -138,8 +242,47 @@ func testMcl(t *testing.T, c int) {
testHash(t) testHash(t)
testNegAdd(t) testNegAdd(t)
testPairing(t) testPairing(t)
testVec(t)
testGT(t) testGT(t)
testBadPointOfG2(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) { func TestMclMain(t *testing.T) {
@ -153,5 +296,7 @@ func TestMclMain(t *testing.T) {
} }
t.Log("BLS12_381") t.Log("BLS12_381")
testMcl(t, 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 { public class ElgamalTest {
static { static {
String lib = "mcl_elgamal"; String lib = "mclelgamaljava";
String libName = System.mapLibraryName(lib); String libName = System.mapLibraryName(lib);
System.out.println("libName : " + libName); System.out.println("libName : " + libName);
System.loadLibrary(lib); System.loadLibrary(lib);

@ -1,46 +1,50 @@
TOP_DIR=../.. TOP_DIR=../..
include $(TOP_DIR)/common.mk include $(TOP_DIR)/common.mk
ifeq ($(UNAME_S),Darwin) 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 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 #JAVA_INC=-I/usr/lib/jvm/java-7-openjdk-amd64/include
CFLAGS+=$(JAVA_INC)/linux
CFLAGS+=-z noexecstack CFLAGS+=-z noexecstack
LDFLAGS+=-lrt LDFLAGS+=-lrt
endif 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 MCL_LIB=$(TOP_DIR)/lib/libmcl.a
PACKAGE_NAME=com.herumi.mcl PACKAGE_NAME=com.herumi.mcl
PACKAGE_DIR=$(subst .,/,$(PACKAGE_NAME)) PACKAGE_DIR=$(subst .,/,$(PACKAGE_NAME))
ELGAMAL_LIB=$(TOP_DIR)/bin/libmcl_elgamal.$(LIB_SUF) ELGAMAL_LIB=$(TOP_DIR)/lib/libmclelgamaljava.$(LIB_SUF)
BN256_LIB=$(TOP_DIR)/bin/libmcl_bn256.$(LIB_SUF) MCLJAVA_LIB=$(TOP_DIR)/lib/libmcljava.$(LIB_SUF)
JAVA_EXE=cd $(TOP_DIR)/bin && LD_LIBRARY_PATH=./:$(LD_LIBRARY_PATH) java -classpath ../ffi/java JAVA_EXE=cd $(TOP_DIR)/lib && LD_LIBRARY_PATH=../lib:$(LD_LIBRARY_PATH) java -classpath ../ffi/java
all: $(ELGAMAL_LIB) all: $(ELGAMAL_LIB)
elgamal_wrap.cxx: elgamal.i elgamal_impl.hpp elgamal_wrap.cxx: elgamal.i elgamal_impl.hpp
$(MKDIR) $(PACKAGE_DIR) $(MKDIR) $(PACKAGE_DIR)
swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall elgamal.i 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) $(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): $(MCL_LIB):
make -C $(TOP_DIR) make -C $(TOP_DIR) lib/libmcl.a
$(ELGAMAL_LIB): elgamal_wrap.cxx $(MCL_LIB) $(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) $(MCLJAVA_LIB): mcl_wrap.cxx $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(CFLAGS) $(LDFLAGS) $(MCL_LIB) -shared $(PRE)$(CXX) $< -o $@ $(CFLAGS) $(MCL_LIB) $(LDFLAGS) -shared
%.class: %.java %.class: %.java
javac $< javac $<
ElgamalTest.class: ElgamalTest.java $(ELGAMAL_LIB) ElgamalTest.class: ElgamalTest.java $(ELGAMAL_LIB)
Bn256Test.class: Bn256Test.java $(BN256_LIB) MclTest.class: MclTest.java $(MCLJAVA_LIB)
jar: jar:
jar cvf mcl.jar com jar cvf mcl.jar com
@ -49,16 +53,17 @@ test_elgamal: ElgamalTest.class $(ELGAMAL_LIB)
$(JAVA_EXE) ElgamalTest $(JAVA_EXE) ElgamalTest
$(JAVA_EXE) ElgamalTest -e NIST_P192 $(JAVA_EXE) ElgamalTest -e NIST_P192
$(JAVA_EXE) ElgamalTest -e NIST_P256 -h sha256 $(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_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) test_mcl: MclTest.class $(MCLJAVA_LIB)
$(JAVA_EXE) Bn256Test $(JAVA_EXE) MclTest
test: test:
$(MAKE) test_elgamal $(MAKE) test_elgamal
$(MAKE) test_bn256 $(MAKE) test_mcl
clean: 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::EcT<Fp> Ec;
typedef mcl::ElgamalT<Ec, Zn> Elgamal; 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 init system
@param param [in] string such as "ecParamName hashName" @param param [in] string such as "ecParamName hashName"
@ -29,11 +34,11 @@ void SystemInit(const std::string& param) throw(std::exception)
if (iss >> ecParamStr >> hashNameStr) { if (iss >> ecParamStr >> hashNameStr) {
Param& p = Param::getParam(); Param& p = Param::getParam();
p.ecParam = mcl::getEcParam(ecParamStr); p.ecParam = mcl::getEcParam(ecParamStr);
Zn::init(p.ecParam->n); if (p.ecParam) {
Fp::init(p.ecParam->p); mcl::initCurve<Ec, Zn>(p.ecParam->curveType);
Ec::init(p.ecParam->a, p.ecParam->b); p.hashName = cybozu::crypto::Hash::getName(hashNameStr);
p.hashName = cybozu::crypto::Hash::getName(hashNameStr); return;
return; }
} }
throw cybozu::Exception("SystemInit:bad param") << param; throw cybozu::Exception("SystemInit:bad param") << param;
} }
@ -145,3 +150,7 @@ public:
self_.clearCache(); 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). * 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 * 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 * coding conventions designed to improve portability and efficiency. Do not make
@ -182,15 +182,16 @@ template <typename T> T SwigValueInit() {
/* Support for throwing Java exceptions */ /* Support for throwing Java exceptions */
typedef enum { typedef enum {
SWIG_JavaOutOfMemoryError = 1, SWIG_JavaOutOfMemoryError = 1,
SWIG_JavaIOException, SWIG_JavaIOException,
SWIG_JavaRuntimeException, SWIG_JavaRuntimeException,
SWIG_JavaIndexOutOfBoundsException, SWIG_JavaIndexOutOfBoundsException,
SWIG_JavaArithmeticException, SWIG_JavaArithmeticException,
SWIG_JavaIllegalArgumentException, SWIG_JavaIllegalArgumentException,
SWIG_JavaNullPointerException, SWIG_JavaNullPointerException,
SWIG_JavaDirectorPureVirtual, SWIG_JavaDirectorPureVirtual,
SWIG_JavaUnknownError SWIG_JavaUnknownError,
SWIG_JavaIllegalStateException,
} SWIG_JavaExceptionCodes; } SWIG_JavaExceptionCodes;
typedef struct { typedef struct {
@ -211,6 +212,7 @@ static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionC
{ SWIG_JavaNullPointerException, "java/lang/NullPointerException" }, { SWIG_JavaNullPointerException, "java/lang/NullPointerException" },
{ SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" }, { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" },
{ SWIG_JavaUnknownError, "java/lang/UnknownError" }, { SWIG_JavaUnknownError, "java/lang/UnknownError" },
{ SWIG_JavaIllegalStateException, "java/lang/IllegalStateException" },
{ (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" } { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" }
}; };
const SWIG_JavaExceptions_t *except_ptr = java_exceptions; 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); jenv->ReleaseStringUTFChars(jarg1, arg1_pstr);
try { try {
SystemInit((std::string const &)*arg1); SystemInit((std::string const &)*arg1);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -378,12 +378,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toStr(JNIE
arg1 = *(CipherText **)&jarg1; arg1 = *(CipherText **)&jarg1;
try { try {
result = ((CipherText const *)arg1)->toStr(); result = ((CipherText const *)arg1)->toStr();
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0; return 0;
} }
jresult = jenv->NewStringUTF((&result)->c_str()); jresult = jenv->NewStringUTF((&result)->c_str());
return jresult; return jresult;
} }
@ -400,12 +398,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toString(J
arg1 = *(CipherText **)&jarg1; arg1 = *(CipherText **)&jarg1;
try { try {
result = ((CipherText const *)arg1)->toString(); result = ((CipherText const *)arg1)->toString();
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0; return 0;
} }
jresult = jenv->NewStringUTF((&result)->c_str()); jresult = jenv->NewStringUTF((&result)->c_str());
return jresult; return jresult;
} }
@ -430,12 +426,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1fromStr(JNIEn
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try { try {
(arg1)->fromStr((std::string const &)*arg2); (arg1)->fromStr((std::string const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -455,12 +449,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1add(JNIEnv *j
} }
try { try {
(arg1)->add((CipherText const &)*arg2); (arg1)->add((CipherText const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -475,12 +467,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_1
arg2 = (int)jarg2; arg2 = (int)jarg2;
try { try {
(arg1)->mul(arg2); (arg1)->mul(arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -503,12 +493,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_1
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try { try {
(arg1)->mul((std::string const &)*arg2); (arg1)->mul((std::string const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -545,12 +533,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toStr(JNIEn
arg1 = *(PublicKey **)&jarg1; arg1 = *(PublicKey **)&jarg1;
try { try {
result = ((PublicKey const *)arg1)->toStr(); result = ((PublicKey const *)arg1)->toStr();
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0; return 0;
} }
jresult = jenv->NewStringUTF((&result)->c_str()); jresult = jenv->NewStringUTF((&result)->c_str());
return jresult; return jresult;
} }
@ -567,12 +553,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toString(JN
arg1 = *(PublicKey **)&jarg1; arg1 = *(PublicKey **)&jarg1;
try { try {
result = ((PublicKey const *)arg1)->toString(); result = ((PublicKey const *)arg1)->toString();
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0; return 0;
} }
jresult = jenv->NewStringUTF((&result)->c_str()); jresult = jenv->NewStringUTF((&result)->c_str());
return jresult; return jresult;
} }
@ -597,12 +581,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1fromStr(JNIEnv
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try { try {
(arg1)->fromStr((std::string const &)*arg2); (arg1)->fromStr((std::string const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -625,12 +607,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1save(JNIEnv *j
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try { try {
((PublicKey const *)arg1)->save((std::string const &)*arg2); ((PublicKey const *)arg1)->save((std::string const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -653,12 +633,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1load(JNIEnv *j
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try { try {
(arg1)->load((std::string const &)*arg2); (arg1)->load((std::string const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -680,12 +658,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_10
arg3 = (int)jarg3; arg3 = (int)jarg3;
try { try {
((PublicKey const *)arg1)->enc(*arg2,arg3); ((PublicKey const *)arg1)->enc(*arg2,arg3);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -715,12 +691,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_11
jenv->ReleaseStringUTFChars(jarg3, arg3_pstr); jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
try { try {
((PublicKey const *)arg1)->enc(*arg2,(std::string const &)*arg3); ((PublicKey const *)arg1)->enc(*arg2,(std::string const &)*arg3);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -740,12 +714,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1rerandomize(JN
} }
try { try {
((PublicKey const *)arg1)->rerandomize(*arg2); ((PublicKey const *)arg1)->rerandomize(*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -767,12 +739,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_10
arg3 = (int)jarg3; arg3 = (int)jarg3;
try { try {
((PublicKey const *)arg1)->add(*arg2,arg3); ((PublicKey const *)arg1)->add(*arg2,arg3);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -802,12 +772,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_11
jenv->ReleaseStringUTFChars(jarg3, arg3_pstr); jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
try { try {
((PublicKey const *)arg1)->add(*arg2,(std::string const &)*arg3); ((PublicKey const *)arg1)->add(*arg2,(std::string const &)*arg3);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -844,12 +812,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toStr(JNIE
arg1 = *(PrivateKey **)&jarg1; arg1 = *(PrivateKey **)&jarg1;
try { try {
result = ((PrivateKey const *)arg1)->toStr(); result = ((PrivateKey const *)arg1)->toStr();
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0; return 0;
} }
jresult = jenv->NewStringUTF((&result)->c_str()); jresult = jenv->NewStringUTF((&result)->c_str());
return jresult; return jresult;
} }
@ -866,12 +832,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toString(J
arg1 = *(PrivateKey **)&jarg1; arg1 = *(PrivateKey **)&jarg1;
try { try {
result = ((PrivateKey const *)arg1)->toString(); result = ((PrivateKey const *)arg1)->toString();
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0; return 0;
} }
jresult = jenv->NewStringUTF((&result)->c_str()); jresult = jenv->NewStringUTF((&result)->c_str());
return jresult; return jresult;
} }
@ -896,12 +860,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1fromStr(JNIEn
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try { try {
(arg1)->fromStr((std::string const &)*arg2); (arg1)->fromStr((std::string const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -924,12 +886,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1save(JNIEnv *
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try { try {
((PrivateKey const *)arg1)->save((std::string const &)*arg2); ((PrivateKey const *)arg1)->save((std::string const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -952,12 +912,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1load(JNIEnv *
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try { try {
(arg1)->load((std::string const &)*arg2); (arg1)->load((std::string const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -970,12 +928,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1init(JNIEnv *
arg1 = *(PrivateKey **)&jarg1; arg1 = *(PrivateKey **)&jarg1;
try { try {
(arg1)->init(); (arg1)->init();
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -990,12 +946,10 @@ SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1getPublicKey
arg1 = *(PrivateKey **)&jarg1; arg1 = *(PrivateKey **)&jarg1;
try { try {
result = ((PrivateKey const *)arg1)->getPublicKey(); result = ((PrivateKey const *)arg1)->getPublicKey();
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0; return 0;
} }
*(PublicKey **)&jresult = new PublicKey((const PublicKey &)result); *(PublicKey **)&jresult = new PublicKey((const PublicKey &)result);
return jresult; return jresult;
} }
@ -1021,12 +975,10 @@ SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_1
arg3 = *(bool **)&jarg3; arg3 = *(bool **)&jarg3;
try { try {
result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2,arg3); 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()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0; return 0;
} }
jresult = (jint)result; jresult = (jint)result;
return jresult; return jresult;
} }
@ -1050,12 +1002,10 @@ SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_1
} }
try { try {
result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2); result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0; return 0;
} }
jresult = (jint)result; jresult = (jint)result;
return jresult; return jresult;
} }
@ -1074,12 +1024,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1setCache(JNIE
arg3 = (int)jarg3; arg3 = (int)jarg3;
try { try {
(arg1)->setCache(arg2,arg3); (arg1)->setCache(arg2,arg3);
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }
@ -1092,12 +1040,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1clearCache(JN
arg1 = *(PrivateKey **)&jarg1; arg1 = *(PrivateKey **)&jarg1;
try { try {
(arg1)->clearCache(); (arg1)->clearCache();
} } catch(std::exception &_e) {
catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what()); SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ; return ;
} }
} }

@ -1,13 +1,14 @@
# JNI for mcl (experimental) # JNI for mcl (experimental)
This library provides functionality to compute the optimal ate pairing This library provides functionality to compute the optimal ate pairing
over Barreto-Naehrig (BN) curves. over Barreto-Naehrig (BN) or BLS12-381 curves.
# Initialization # Initialization
Load the library `mcl_bn256`. Load the library `mcljava`.
``` ```
import com.herumi.mcl.*; import com.herumi.mcl.*;
System.loadLibrary("mcl_bn256"); System.loadLibrary(System.mapLibraryName("mcljava"));
Mcl.SystemInit(curveType); // curveType = Mcl.BN254 or Mcl.BLS12_381
``` ```
# Classes # Classes
@ -21,75 +22,67 @@ System.loadLibrary("mcl_bn256");
## Fr ## Fr
* `Fr::setInt(int x)` ; set by x * `Fr::setInt(int x)` ; set by x
* `Fr::setStr(String str)` ; set by str such as "123", "0xfff", etc. * `Fr::setStr(String str)` ; set by str such as "123", "0xfff", etc.
* `Fr::setRand()` ; randomly set * `Fr::setByCSPRNG()` ; randomly set
* `Bn256.neg(Fr y, Fr x)` ; `y = -x` * `Mcl.neg(Fr y, Fr x)` ; `y = -x`
* `Bn256.add(Fr z, Fr x, Fr y)` ; `z = x + y` * `Mcl.add(Fr z, Fr x, Fr y)` ; `z = x + y`
* `Bn256.sub(Fr z, Fr x, Fr y)` ; `z = x - y` * `Mcl.sub(Fr z, Fr x, Fr y)` ; `z = x - y`
* `Bn256.mul(Fr z, Fr x, Fr y)` ; `z = x * y` * `Mcl.mul(Fr z, Fr x, Fr y)` ; `z = x * y`
* `Bn256.div(Fr z, Fr x, Fr y)` ; `z = x / y` * `Mcl.div(Fr z, Fr x, Fr y)` ; `z = x / y`
## G1 ## G1
* `G1::set(String x, String y)` ; set by (x, y) * `Mcl.neg(G1 y, G1 x)` ; `y = -x`
* `G1::hashAndMapToG1(String m)` ; take SHA-256 of m and map it to an element of G1 * `Mcl.dbl(G1 y, G1 x)` ; `y = 2x`
* `G1::setStr(String str)` ; set by the result of `toString()` method * `Mcl.add(G1 z, G1 x, G1 y)` ; `z = x + y`
* `Bn256.neg(G1 y, G1 x)` ; `y = -x` * `Mcl.sub(G1 z, G1 x, G1 y)` ; `z = x - y`
* `Bn256.dbl(G1 y, G1 x)` ; `y = 2x` * `Mcl.mul(G1 z, G1 x, Fr y)` ; `z = x * y`
* `Bn256.add(G1 z, G1 x, G1 y)` ; `z = x + y`
* `Bn256.sub(G1 z, G1 x, G1 y)` ; `z = x - y`
* `Bn256.mul(G1 z, G1 x, Fr y)` ; `z = x * y`
## G2 ## G2
* `G2::set(String xa, String xb, String ya, String yb)` ; set by ((xa, xb), (ya, yb)) * `Mcl.neg(G2 y, G2 x)` ; `y = -x`
* `G2::setStr(String str)` ; set by the result of `toString()` method * `Mcl.dbl(G2 y, G2 x)` ; `y = 2x`
* `Bn256.neg(G2 y, G2 x)` ; `y = -x` * `Mcl.add(G2 z, G2 x, G2 y)` ; `z = x + y`
* `Bn256.dbl(G2 y, G2 x)` ; `y = 2x` * `Mcl.sub(G2 z, G2 x, G2 y)` ; `z = x - y`
* `Bn256.add(G2 z, G2 x, G2 y)` ; `z = x + y` * `Mcl.mul(G2 z, G2 x, Fr y)` ; `z = x * y`
* `Bn256.sub(G2 z, G2 x, G2 y)` ; `z = x - y`
* `Bn256.mul(G2 z, G2 x, Fr y)` ; `z = x * y`
## GT ## GT
* `GT::setStr(String str)` ; set by the result of `toString()` method * `GT::setStr(String str)` ; set by the result of `toString()` method
* `Bn256.mul(GT z, GT x, GT y)` ; `z = x * y` * `Mcl.mul(GT z, GT x, GT y)` ; `z = x * y`
* `Bn256.pow(GT z, GT x, Fr 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 ## 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 # BLS signature sample
``` ```
String xa = "12723517038133731887338407189719511622662176727675373276651903807414909099441"; G2 Q = new G2();
String xb = "4168783608814932154536427934509895782246573715297911553964171371032945126671"; Mcl.hashAndMapToG2(Q, "abc".getBytes());
String ya = "13891744915211034074451795021214165905772212241412891944830863846330766296736";
String yb = "7937318970632701341203597196594272556916396164729705624521405069090520231616";
G2 Q = new G2(xa, xb, ya, yb); // fixed point of G2
Fr s = new Fr(); Fr s = new Fr();
s.setRand(); // secret key s.setByCSPRNG(); // secret key
G2 pub = new G2(); G2 pub = new G2();
Bn256.mul(pub, Q, s); // public key = sQ Mcl.mul(pub, Q, s); // public key = sQ
String m = "signature test"; String m = "signature test";
G1 H = new G1(); G1 H = new G1();
H.hashAndMapToG1(m); // H = Hash(m) Mcl.hashAndMapToG1(H, m.getBytes()); // H = Hash(m)
G1 sign = new G1(); 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 e1 = new GT();
GT e2 = new GT(); GT e2 = new GT();
Bn256.pairing(e1, H, pub); // e1 = e(H, s Q) Mcl.pairing(e1, H, pub); // e1 = e(H, s Q)
Bn256.pairing(e2, sign, Q); // e2 = e(s H, Q); Mcl.pairing(e2, sign, Q); // e2 = e(s H, Q);
assertBool("verify signature", e1.equals(e2)); assertBool("verify signature", e1.equals(e2));
``` ```
# Make test # Make test
``` ```
cd java cd ffi/java
make test_bn256 make test
``` ```
# Sample code # 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_NAME=com.herumi.mcl
set PACKAGE_DIR=%PACKAGE_NAME:.=\% set PACKAGE_DIR=%PACKAGE_NAME:.=\%
if /i "%1"=="" ( if /i "%1"=="" (
set NAME=elgamal set NAME=mcl
set LIBNAME=
) else ( ) else (
set NAME=%1 set NAME=%1
set LIBNAME=%NAME%
) )
echo [[run swig]] echo [[run swig]]
@ -15,7 +17,7 @@ mkdir %PACKAGE_DIR%
set TOP_DIR=../.. set TOP_DIR=../..
%SWIG% -java -package %PACKAGE_NAME% -outdir %PACKAGE_DIR% -c++ -Wall %NAME%.i %SWIG% -java -package %PACKAGE_NAME% -outdir %PACKAGE_DIR% -c++ -Wall %NAME%.i
echo [[make dll]] 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 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 os
import platform import platform
from ctypes import * from ctypes import *
#from ctypes.util import find_library
BN254 = 0 BN254 = 0
BLS12_381 = 5 BLS12_381 = 5
@ -34,6 +35,7 @@ def init(curveType=BN254):
libName = 'mclshe384_256.dll' libName = 'mclshe384_256.dll'
else: else:
raise RuntimeError("not support yet", name) raise RuntimeError("not support yet", name)
# lib = cdll.LoadLibrary(find_library(libName))
lib = cdll.LoadLibrary(libName) lib = cdll.LoadLibrary(libName)
ret = lib.sheInit(curveType, MCLBN_COMPILED_TIME_VAR) ret = lib.sheInit(curveType, MCLBN_COMPILED_TIME_VAR)
if ret != 0: if ret != 0:

@ -7,7 +7,6 @@
*/ */
#include <memory.h> #include <memory.h>
#include <limits.h>
#include <limits> #include <limits>
#include <cybozu/exception.hpp> #include <cybozu/exception.hpp>
@ -173,7 +172,7 @@ public:
} }
inline operator int() const 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 inline operator unsigned int() const
{ {
@ -181,7 +180,7 @@ public:
} }
inline operator long long() const 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 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 <errno.h>
#include <stdio.h> #include <stdio.h>
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h> #include <windows.h>
#else #else
#include <string.h> // for strerror_r #include <string.h> // for strerror_r
@ -201,7 +203,6 @@ public:
} }
/** /**
convert NativeErrNo to string(maybe UTF8) convert NativeErrNo to string(maybe UTF8)
@param err [in] errno
@note Linux : same as ConvertErrorNoToString @note Linux : same as ConvertErrorNoToString
Windows : for Win32 API(use en-us) 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(push)
#pragma warning(disable : 4099) // missmatch class and struct #pragma warning(disable : 4099) // missmatch class and struct
#endif #endif
#ifndef __APPLE__ #if !(defined(__APPLE__) && defined(__clang__))
template<class T> template<class T>
struct hash; struct hash;
#endif #endif

@ -72,6 +72,9 @@
#endif #endif
#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_CPP03 0
#define CYBOZU_CPP_VERSION_TR1 1 #define CYBOZU_CPP_VERSION_TR1 1
#define CYBOZU_CPP_VERSION_CPP11 2 #define CYBOZU_CPP_VERSION_CPP11 2
@ -88,13 +91,13 @@
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP17 #define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP17
#elif (__cplusplus >= 201402) #elif (__cplusplus >= 201402)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP14 #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) #if defined(_MSC_VER) && (_MSC_VER <= 1600)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1 #define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1
#else #else
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP11 #define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP11
#endif #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 #define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1
#else #else
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP03 #define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP03
@ -115,7 +118,7 @@
#endif #endif
#ifndef CYBOZU_OS_BIT #ifndef CYBOZU_OS_BIT
#if defined(_WIN64) || defined(__x86_64__) || defined(__AARCH64EL__) || defined(__EMSCRIPTEN__) #if defined(_WIN64) || defined(__x86_64__) || defined(__AARCH64EL__) || defined(__EMSCRIPTEN__) || defined(__LP64__)
#define CYBOZU_OS_BIT 64 #define CYBOZU_OS_BIT 64
#else #else
#define CYBOZU_OS_BIT 32 #define CYBOZU_OS_BIT 32
@ -143,6 +146,8 @@
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE #define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE
#elif (CYBOZU_HOST == CYBOZU_HOST_ARM) && (defined(__ARM_EABI__) || defined(__AARCH64EL__)) #elif (CYBOZU_HOST == CYBOZU_HOST_ARM) && (defined(__ARM_EABI__) || defined(__AARCH64EL__))
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE #define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE
#elif defined(__s390x__)
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_BIG
#else #else
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_UNKNOWN #define CYBOZU_ENDIAN CYBOZU_ENDIAN_UNKNOWN
#endif #endif
@ -150,8 +155,10 @@
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
#define CYBOZU_NOEXCEPT noexcept #define CYBOZU_NOEXCEPT noexcept
#define CYBOZU_NULLPTR nullptr
#else #else
#define CYBOZU_NOEXCEPT throw() #define CYBOZU_NOEXCEPT throw()
#define CYBOZU_NULLPTR 0
#endif #endif
namespace cybozu { namespace cybozu {
template<class T> template<class T>

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

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

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

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

@ -13,6 +13,7 @@
#ifndef CYBOZU_DONT_USE_STRING #ifndef CYBOZU_DONT_USE_STRING
#include <string> #include <string>
#endif #endif
#include <memory.h>
#ifdef CYBOZU_USE_OPENSSL_SHA #ifdef CYBOZU_USE_OPENSSL_SHA
#ifdef __APPLE__ #ifdef __APPLE__
@ -468,3 +469,61 @@ public:
} // cybozu } // cybozu
#endif #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 <string>
#include <iosfwd> #include <iosfwd>
#endif #endif
#ifndef CYBOZU_DONT_USE_EXCEPTION
#include <cybozu/exception.hpp> #include <cybozu/exception.hpp>
#endif
#include <memory.h> #include <memory.h>
namespace cybozu { 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 SecretKey;
friend class PublicKey; friend class PublicKey;
public: 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> template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize) 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> template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const 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) friend std::istream& operator>>(std::istream& is, Signature& self)
{ {
self.load(is, fp::detectIoMode(G1::getIoMode(), is)); self.load(is, fp::detectIoMode(G1::getIoMode(), is));
@ -155,16 +171,32 @@ public:
friend class SecretKey; friend class SecretKey;
friend class Signature; friend class Signature;
public: 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> template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize) 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> template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const 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) friend std::istream& operator>>(std::istream& is, PublicKey& self)
{ {
self.load(is, fp::detectIoMode(G2::getIoMode(), is)); self.load(is, fp::detectIoMode(G2::getIoMode(), is));
@ -208,16 +240,32 @@ public:
friend class PublicKey; friend class PublicKey;
friend class Signature; friend class Signature;
public: 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> template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize) 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> template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const 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) friend std::istream& operator>>(std::istream& is, SecretKey& self)
{ {
self.load(is, fp::detectIoMode(Fr::getIoMode(), is)); 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; y = t;
} }
public: public:
typedef T value_type;
FixedArray() : n_(0) {} FixedArray() : n_(0) {}
bool resize(size_t n) bool resize(size_t n)
{ {
@ -125,6 +126,15 @@ public:
n_ = n; n_ = n;
return true; 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) bool copy(const FixedArray<T, maxSize>& rhs)
{ {
if (this == &rhs) return true; if (this == &rhs) return true;

@ -75,35 +75,47 @@ typedef struct mclBnFp2 mclBnFp2;
#else #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 { typedef struct {
uint64_t d[MCLBN_FR_UNIT_SIZE]; uint64_t d[MCLBN_FR_UNIT_SIZE];
} mclBnFr; } mclBnFr;
/*
G1 is defined over Fp
*/
typedef struct { typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 3]; mclBnFp x, y, z;
} mclBnG1; } mclBnG1;
typedef struct { typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 2 * 3]; mclBnFp2 x, y, z;
} mclBnG2; } mclBnG2;
typedef struct { typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 12]; mclBnFp d[12];
} mclBnGT; } mclBnGT;
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE];
} mclBnFp;
typedef struct {
mclBnFp d[2];
} mclBnFp2;
#endif #endif
#include <mcl/curve_type.h> #include <mcl/curve_type.h>
#define MCLBN_IO_EC_AFFINE 0
#define MCLBN_IO_EC_PROJ 1024
#define MCLBN_IO_SERIALIZE_HEX_STR 2048 #define MCLBN_IO_SERIALIZE_HEX_STR 2048
// for backword compatibility // for backword compatibility
enum { enum {
mclBn_CurveFp254BNb = 0, mclBn_CurveFp254BNb = 0,
@ -115,7 +127,7 @@ enum {
}; };
// return 0xABC which means A.BC // return 0xABC which means A.BC
MCLBN_DLL_API int mclBn_getVersion(); MCLBN_DLL_API int mclBn_getVersion(void);
/* /*
init library init library
@param curve [in] type of bn curve @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_init(int curve, int compiledTimeVar);
MCLBN_DLL_API int mclBn_getCurveType(void);
/* /*
pairing : G1 x G2 -> GT 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 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 @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 deserialize
@ -238,6 +261,8 @@ MCLBN_DLL_API void mclBnFp2_clear(mclBnFp2 *x);
// set x to y // set x to y
MCLBN_DLL_API void mclBnFr_setInt(mclBnFr *y, mclInt x); MCLBN_DLL_API void mclBnFr_setInt(mclBnFr *y, mclInt x);
MCLBN_DLL_API void mclBnFr_setInt32(mclBnFr *y, int 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 // x = buf & (1 << bitLen(r)) - 1
// if (x >= r) x &= (1 << (bitLen(r) - 1)) - 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 mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize);
MCLBN_DLL_API int mclBnFp_setLittleEndian(mclBnFp *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 // set (buf mod r) to x
// return 0 if bufSize <= (byte size of Fr * 2) else -1 // 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_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 // set (buf mod p) to x
// return 0 if bufSize <= (byte size of Fp * 2) else -1 // 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_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 // return 1 if true and 0 otherwise
MCLBN_DLL_API int mclBnFr_isValid(const mclBnFr *x); 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_isEqual(const mclBnFr *x, const mclBnFr *y);
MCLBN_DLL_API int mclBnFr_isZero(const mclBnFr *x); MCLBN_DLL_API int mclBnFr_isZero(const mclBnFr *x);
MCLBN_DLL_API int mclBnFr_isOne(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_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_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 #ifndef MCL_DONT_USE_CSRPNG
// return 0 if success // return 0 if success
MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x); MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x);
MCLBN_DLL_API int mclBnFp_setByCSPRNG(mclBnFp *x);
/* /*
set user-defined random function for setByCSPRNG 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_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 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 // set zero
MCLBN_DLL_API void mclBnG1_clear(mclBnG1 *x); 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 int mclBnGT_isOne(const mclBnGT *x);
MCLBN_DLL_API void mclBnGT_neg(mclBnGT *y, 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_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_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_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_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
MCLBN_DLL_API void mclBnGT_div(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 pow for all elements of Fp12
*/ */
MCLBN_DLL_API void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y); 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 the value generated by pairing satisfies the condition
*/ */
MCLBN_DLL_API void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y); 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_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_finalExp(mclBnGT *y, const mclBnGT *x);
MCLBN_DLL_API void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y); 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) // return precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t)
MCLBN_DLL_API int mclBn_getUint64NumToPrecompute(void); MCLBN_DLL_API int mclBn_getUint64NumToPrecompute(void);
@ -410,7 +492,8 @@ MCLBN_DLL_API int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVe
/* /*
evaluate polynomial evaluate polynomial
out = f(x) = c[0] + c[1] * x + c[2] * x^2 + ... + c[cSize - 1] * x^(cSize - 1) 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_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); 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

@ -0,0 +1,34 @@
#pragma once
/**
@file
@brief constant macro
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <cybozu/inttype.hpp>
#ifndef MCL_SIZEOF_UNIT
#if defined(CYBOZU_OS_BIT) && (CYBOZU_OS_BIT == 32)
#define MCL_SIZEOF_UNIT 4
#else
#define MCL_SIZEOF_UNIT 8
#endif
#endif
#ifndef MCL_MAX_BIT_SIZE
#define MCL_MAX_BIT_SIZE 512
#endif
namespace mcl {
namespace fp {
#if MCL_SIZEOF_UNIT == 8
typedef uint64_t Unit;
#else
typedef uint32_t Unit;
#endif
#define MCL_UNIT_BIT_SIZE (MCL_SIZEOF_UNIT * 8)
} } // mcl::fp

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <cybozu/itoa.hpp> #include <cybozu/itoa.hpp>
#include <cybozu/stream.hpp> #include <cybozu/stream.hpp>
#include <mcl/config.hpp>
/** /**
@file @file
@brief convertion bin/dec/hex <=> array @brief convertion bin/dec/hex <=> array
@ -15,6 +16,44 @@
namespace mcl { namespace fp { namespace mcl { namespace fp {
/*
treat src[] as a little endian and set dst[]
fill remain of dst if sizeof(D) * dstN > sizeof(S) * srcN
return false if sizeof(D) * dstN < sizeof(S) * srcN
*/
template<class D, class S>
bool convertArrayAsLE(D *dst, size_t dstN, const S *src, size_t srcN)
{
char assert_D_is_unsigned[D(-1) < 0 ? -1 : 1];
char assert_S_is_unsigned[S(-1) < 0 ? -1 : 1];
(void)assert_D_is_unsigned;
(void)assert_S_is_unsigned;
if (sizeof(D) * dstN < sizeof(S) * srcN) return false;
size_t pos = 0;
if (sizeof(D) < sizeof(S)) {
for (size_t i = 0; i < srcN; i++) {
S s = src[i];
for (size_t j = 0; j < sizeof(S); j += sizeof(D)) {
dst[pos++] = D(s);
s >>= sizeof(D) * 8;
}
}
for (; pos < dstN; pos++) {
dst[pos] = 0;
}
} else {
for (size_t i = 0; i < dstN; i++) {
D u = 0;
for (size_t j = 0; j < sizeof(D); j += sizeof(S)) {
S s = (pos < srcN) ? src[pos++] : 0;
u |= D(s) << (j * 8);
}
dst[i] = u;
}
}
return true;
}
namespace local { namespace local {
inline bool isSpace(char c) inline bool isSpace(char c)
@ -208,8 +247,6 @@ inline bool parsePrefix(size_t *readSize, bool *isMinus, int *base, const char *
if (*base == 0 || *base == 2) { if (*base == 0 || *base == 2) {
*base = 2; *base = 2;
pos += 2; pos += 2;
} else {
return false;
} }
} }
} }
@ -337,31 +374,22 @@ inline size_t binToArray(UT *x, size_t maxN, const char *buf, size_t bufSize)
} }
/* /*
little endian x[0, xn) to buf little endian t[0, tn) to buf
return written size if success else 0 return written size if success else 0
data is buf[bufSize - retval, bufSize) data is buf[bufSize - retval, bufSize)
*/ */
template<class UT> inline size_t inner_arrayToDec(char *buf, size_t bufSize, uint32_t *t, size_t tn)
inline size_t arrayToDec(char *buf, size_t bufSize, const UT *x, size_t xn)
{ {
const size_t maxN = 64;
uint32_t t[maxN];
if (sizeof(UT) == 8) {
xn *= 2;
}
if (xn > maxN) return 0;
memcpy(t, x, xn * sizeof(t[0]));
const size_t width = 9; const size_t width = 9;
const uint32_t i1e9 = 1000000000U; const uint32_t i1e9 = 1000000000U;
size_t pos = 0; size_t pos = 0;
for (;;) { for (;;) {
uint32_t r = local::divU32(t, t, xn, i1e9); uint32_t r = local::divU32(t, t, tn, i1e9);
while (xn > 0 && t[xn - 1] == 0) xn--; while (tn > 0 && t[tn - 1] == 0) tn--;
size_t len = cybozu::itoa_local::uintToDec(buf, bufSize - pos, r); size_t len = cybozu::itoa_local::uintToDec(buf, bufSize - pos, r);
if (len == 0) return 0; if (len == 0) return 0;
assert(0 < len && len <= width); assert(0 < len && len <= width);
if (xn == 0) return pos + len; if (tn == 0) return pos + len;
// fill (width - len) '0' // fill (width - len) '0'
for (size_t j = 0; j < width - len; j++) { for (size_t j = 0; j < width - len; j++) {
buf[bufSize - pos - width + j] = '0'; buf[bufSize - pos - width + j] = '0';
@ -370,21 +398,33 @@ inline size_t arrayToDec(char *buf, size_t bufSize, const UT *x, size_t xn)
} }
} }
inline size_t arrayToDec(char *buf, size_t bufSize, const uint32_t *x, size_t xn)
{
uint32_t *t = (uint32_t*)CYBOZU_ALLOCA(sizeof(uint32_t) * xn);
memcpy(t, x, sizeof(uint32_t) * xn);
return inner_arrayToDec(buf, bufSize, t, xn);
}
inline size_t arrayToDec(char *buf, size_t bufSize, const uint64_t *x, size_t xn)
{
uint32_t *t = (uint32_t*)CYBOZU_ALLOCA(sizeof(uint32_t) * xn * 2);
for (size_t i = 0; i < xn; i++) {
uint64_t v = x[i];
t[i * 2 + 0] = uint32_t(v);
t[i * 2 + 1] = uint32_t(v >> 32);
}
return inner_arrayToDec(buf, bufSize, t, xn * 2);
}
/* /*
convert buf[0, bufSize) to x[0, num) convert buf[0, bufSize) to x[0, num)
return written num if success else 0 return written num if success else 0
*/ */
template<class UT> inline size_t decToArray(uint32_t *x, size_t maxN, const char *buf, size_t bufSize)
inline size_t decToArray(UT *_x, size_t maxN, const char *buf, size_t bufSize)
{ {
assert(sizeof(UT) == 4 || sizeof(UT) == 8);
const size_t width = 9; const size_t width = 9;
const uint32_t i1e9 = 1000000000U; const uint32_t i1e9 = 1000000000U;
if (maxN == 0) return 0; if (maxN == 0) return 0;
if (sizeof(UT) == 8) {
maxN *= 2;
}
uint32_t *x = reinterpret_cast<uint32_t*>(_x);
size_t xn = 1; size_t xn = 1;
x[0] = 0; x[0] = 0;
while (bufSize > 0) { while (bufSize > 0) {
@ -406,10 +446,20 @@ inline size_t decToArray(UT *_x, size_t maxN, const char *buf, size_t bufSize)
buf += n; buf += n;
bufSize -= n; bufSize -= n;
} }
if (sizeof(UT) == 8 && (xn & 1)) { return xn;
x[xn++] = 0; }
inline size_t decToArray(uint64_t *x, size_t maxN, const char *buf, size_t bufSize)
{
uint32_t *t = (uint32_t*)CYBOZU_ALLOCA(sizeof(uint32_t) * maxN * 2);
size_t xn = decToArray(t, maxN * 2, buf, bufSize);
if (xn & 1) {
t[xn++] = 0;
}
for (size_t i = 0; i < xn; i += 2) {
x[i / 2] = (uint64_t(t[i + 1]) << 32) | t[i];
} }
return xn / (sizeof(UT) / 4); return xn / 2;
} }
/* /*

@ -18,7 +18,7 @@ enum {
/* /*
for only G1 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_EC_BEGIN = 100,
MCL_SECP192K1 = MCL_EC_BEGIN, MCL_SECP192K1 = MCL_EC_BEGIN,
@ -29,7 +29,90 @@ enum {
MCL_NIST_P192 = 105, MCL_NIST_P192 = 105,
MCL_NIST_P224 = 106, MCL_NIST_P224 = 106,
MCL_NIST_P256 = 107, 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_P384 = MCL_SECP384R1,
MCL_NIST_P521 = MCL_SECP521R1 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 @license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause http://opensource.org/licenses/BSD-3-Clause
*/ */
#include <mcl/ec.hpp>
#include <mcl/curve_type.h> #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 = { const struct mcl::EcParam secp160k1 = {
"secp160k1", "secp160k1",
@ -20,9 +33,9 @@ const struct mcl::EcParam secp160k1 = {
"0x938cf935318fdced6bc28286531733c3f03c4fee", "0x938cf935318fdced6bc28286531733c3f03c4fee",
"0x100000000000000000001b8fa16dfab9aca16b6b3", "0x100000000000000000001b8fa16dfab9aca16b6b3",
160, 160,
-1 MCL_SECP160K1
}; };
// p=2^160 + 7 // p=2^160 + 7 (for test)
const struct mcl::EcParam p160_1 = { const struct mcl::EcParam p160_1 = {
"p160_1", "p160_1",
"0x10000000000000000000000000000000000000007", "0x10000000000000000000000000000000000000007",
@ -32,7 +45,7 @@ const struct mcl::EcParam p160_1 = {
"1236612389951462151661156731535316138439983579284", "1236612389951462151661156731535316138439983579284",
"1461501637330902918203683518218126812711137002561", "1461501637330902918203683518218126812711137002561",
161, 161,
-1 MCL_P160_1
}; };
const struct mcl::EcParam secp192k1 = { const struct mcl::EcParam secp192k1 = {
"secp192k1", "secp192k1",
@ -181,11 +194,16 @@ inline const mcl::EcParam* getEcParam(int curve)
case MCL_SECP224K1: return &ecparam::secp224k1; case MCL_SECP224K1: return &ecparam::secp224k1;
case MCL_SECP256K1: return &ecparam::secp256k1; case MCL_SECP256K1: return &ecparam::secp256k1;
case MCL_SECP384R1: return &ecparam::secp384r1; case MCL_SECP384R1: return &ecparam::secp384r1;
case MCL_SECP521R1: return &ecparam::secp521r1;
case MCL_NIST_P192: return &ecparam::NIST_P192; case MCL_NIST_P192: return &ecparam::NIST_P192;
case MCL_NIST_P224: return &ecparam::NIST_P224; case MCL_NIST_P224: return &ecparam::NIST_P224;
case MCL_NIST_P256: return &ecparam::NIST_P256; 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; default: return 0;
} }
} }
} // mcl } // mcl
#include <mcl/ec.hpp>

@ -386,7 +386,7 @@ struct ElgamalT {
create table g^i for i in [rangeMin, rangeMax] create table g^i for i in [rangeMin, rangeMax]
*/ */
struct PowerCache { 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; typedef CYBOZU_NAMESPACE_STD::unordered_map<Ec, int> Cache;
#else #else
typedef std::map<Ec, int> Cache; typedef std::map<Ec, int> Cache;

@ -38,13 +38,6 @@ struct ZnTag;
namespace fp { namespace fp {
// copy src to dst as little endian
void copyUnitToByteAsLE(uint8_t *dst, const Unit *src, size_t byteSize);
// copy src to dst as little endian
void copyByteToUnitAsLE(Unit *dst, const uint8_t *src, size_t byteSize);
bool copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, MaskMode maskMode);
uint64_t getUint64(bool *pb, const fp::Block& b); uint64_t getUint64(bool *pb, const fp::Block& b);
int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op); int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op);
@ -73,13 +66,15 @@ bool isEnableJIT(); // 1st call is not threadsafe
uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); 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); 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 { namespace local {
inline void byteSwap(void *x, size_t n) inline void byteSwap(uint8_t *x, size_t n)
{ {
char *p = (char *)x;
for (size_t i = 0; i < n / 2; i++) { for (size_t i = 0; i < n / 2; i++) {
fp::swap_(p[i], p[n - 1 - i]); fp::swap_(x[i], x[n - 1 - i]);
} }
} }
@ -105,6 +100,47 @@ private:
template<class Fp> friend class FpDblT; template<class Fp> friend class FpDblT;
template<class Fp> friend class Fp2T; template<class Fp> friend class Fp2T;
template<class Fp> friend struct Fp6T; template<class Fp> friend struct Fp6T;
#ifdef MCL_XBYAK_DIRECT_CALL
static inline void addA(Unit *z, const Unit *x, const Unit *y)
{
op_.fp_add(z, x, y, op_.p);
}
static inline void subA(Unit *z, const Unit *x, const Unit *y)
{
op_.fp_sub(z, x, y, op_.p);
}
static inline void negA(Unit *y, const Unit *x)
{
op_.fp_neg(y, x, op_.p);
}
static inline void mulA(Unit *z, const Unit *x, const Unit *y)
{
op_.fp_mul(z, x, y, op_.p);
}
static inline void sqrA(Unit *y, const Unit *x)
{
op_.fp_sqr(y, x, op_.p);
}
static inline void mul2A(Unit *y, const Unit *x)
{
op_.fp_mul2(y, x, op_.p);
}
#endif
static inline void mul9A(Unit *y, const Unit *x)
{
mulSmall(y, x, 9);
// op_.fp_mul9(y, x, op_.p);
}
static inline void mulSmall(Unit *z, const Unit *x, const uint32_t y)
{
assert(y <= op_.smallModp.maxMulN);
Unit xy[maxSize + 1];
op_.fp_mulUnitPre(xy, x, y);
int v = op_.smallModp.approxMul(xy);
const Unit *pv = op_.smallModp.getPmul(v);
op_.fp_subPre(z, xy, pv);
op_.fp_sub(z, z, op_.p, op_.p);
}
public: public:
typedef FpT<tag, maxBitSize> BaseFp; typedef FpT<tag, maxBitSize> BaseFp;
// return pointer to array v_[] // return pointer to array v_[]
@ -115,6 +151,7 @@ public:
static inline size_t getBitSize() { return op_.bitSize; } static inline size_t getBitSize() { return op_.bitSize; }
static inline size_t getByteSize() { return (op_.bitSize + 7) / 8; } static inline size_t getByteSize() { return (op_.bitSize + 7) / 8; }
static inline const fp::Op& getOp() { return op_; } static inline const fp::Op& getOp() { return op_; }
static inline fp::Op& getOpNonConst() { return op_; }
void dump() const void dump() const
{ {
const size_t N = op_.N; const size_t N = op_.N;
@ -131,6 +168,9 @@ public:
{ {
assert(maxBitSize <= MCL_MAX_BIT_SIZE); assert(maxBitSize <= MCL_MAX_BIT_SIZE);
*pb = op_.init(p, maxBitSize, xi_a, mode); *pb = op_.init(p, maxBitSize, xi_a, mode);
#ifdef MCL_DUMP_JIT
return;
#endif
if (!*pb) return; if (!*pb) return;
{ // set oneRep { // set oneRep
FpT& one = *reinterpret_cast<FpT*>(op_.oneRep); FpT& one = *reinterpret_cast<FpT*>(op_.oneRep);
@ -147,16 +187,27 @@ public:
ioMode_ = 0; ioMode_ = 0;
isETHserialization_ = false; isETHserialization_ = false;
#ifdef MCL_XBYAK_DIRECT_CALL #ifdef MCL_XBYAK_DIRECT_CALL
add = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_addA_); if (op_.fp_addA_ == 0) {
if (add == 0) add = addC; op_.fp_addA_ = addA;
sub = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_subA_); }
if (sub == 0) sub = subC; if (op_.fp_subA_ == 0) {
neg = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_negA_); op_.fp_subA_ = subA;
if (neg == 0) neg = negC; }
mul = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_mulA_); if (op_.fp_negA_ == 0) {
if (mul == 0) mul = mulC; op_.fp_negA_ = negA;
sqr = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_sqrA_); }
if (sqr == 0) sqr = sqrC; if (op_.fp_mulA_ == 0) {
op_.fp_mulA_ = mulA;
}
if (op_.fp_sqrA_ == 0) {
op_.fp_sqrA_ = sqrA;
}
if (op_.fp_mul2A_ == 0) {
op_.fp_mul2A_ = mul2A;
}
if (op_.fp_mul9A_ == 0) {
op_.fp_mul9A_ = mul9A;
}
#endif #endif
*pb = true; *pb = true;
} }
@ -224,7 +275,7 @@ public:
} else { } else {
clear(); clear();
if (x) { if (x) {
int64_t y = x < 0 ? -x : x; uint64_t y = fp::abs_(x);
if (sizeof(Unit) == 8) { if (sizeof(Unit) == 8) {
v_[0] = y; v_[0] = y;
} else { } else {
@ -254,26 +305,28 @@ public:
{ {
if (isMont()) op_.fromMont(v_, v_); if (isMont()) op_.fromMont(v_, v_);
} }
// deny a string with large length even if the value is in Fp
template<class InputStream> template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode) void load(bool *pb, InputStream& is, int ioMode)
{ {
bool isMinus = false; bool isMinus = false;
*pb = false; *pb = false;
if (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) { if (fp::isIoSerializeMode(ioMode)) {
const size_t n = getByteSize(); const size_t n = getByteSize();
v_[op_.N - 1] = 0; uint8_t *buf = (uint8_t*)CYBOZU_ALLOCA(n);
size_t readSize; size_t readSize;
if (ioMode & IoSerializeHexStr) { if (ioMode & IoSerializeHexStr) {
readSize = mcl::fp::readHexStr(v_, n, is); readSize = mcl::fp::readHexStr(buf, n, is);
} else { } else {
readSize = cybozu::readSome(v_, n, is); readSize = cybozu::readSome(buf, n, is);
} }
if (readSize != n) return;
if (isETHserialization_ && ioMode & (IoSerialize | IoSerializeHexStr)) { if (isETHserialization_ && ioMode & (IoSerialize | IoSerializeHexStr)) {
fp::local::byteSwap(v_, n); fp::local::byteSwap(buf, n);
} }
if (readSize != n) return; fp::convertArrayAsLE(v_, op_.N, buf, n);
} else { } else {
char buf[1024]; char buf[sizeof(*this) * 8 + 2]; // '0b' + max binary format length
size_t n = fp::local::loadWord(buf, sizeof(buf), is); size_t n = fp::local::loadWord(buf, sizeof(buf), is);
if (n == 0) return; if (n == 0) return;
n = fp::strToArray(&isMinus, v_, op_.N, buf, n, ioMode); n = fp::strToArray(&isMinus, v_, op_.N, buf, n, ioMode);
@ -295,24 +348,23 @@ public:
void save(bool *pb, OutputStream& os, int ioMode) const void save(bool *pb, OutputStream& os, int ioMode) const
{ {
const size_t n = getByteSize(); const size_t n = getByteSize();
if (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) { if (fp::isIoSerializeMode(ioMode)) {
const size_t xn = sizeof(fp::Unit) * op_.N;
uint8_t *x = (uint8_t*)CYBOZU_ALLOCA(xn);
if (ioMode & IoArrayRaw) { if (ioMode & IoArrayRaw) {
cybozu::write(pb, os, v_, n); fp::convertArrayAsLE(x, xn, v_, op_.N);
cybozu::write(pb, os, x, n);
} else { } else {
fp::Block b; fp::Block b;
getBlock(b); getBlock(b);
const char *src = (const char *)b.p; fp::convertArrayAsLE(x, xn, b.p, b.n);
char rev[fp::maxUnitSize * sizeof(fp::Unit)];
if (isETHserialization_ && ioMode & (IoSerialize | IoSerializeHexStr)) { if (isETHserialization_ && ioMode & (IoSerialize | IoSerializeHexStr)) {
for (size_t i = 0; i < n; i++) { fp::local::byteSwap(x, n);
rev[i] = src[n - 1 - i];
}
src = rev;
} }
if (ioMode & IoSerializeHexStr) { if (ioMode & IoSerializeHexStr) {
mcl::fp::writeHexStr(pb, os, src, n); mcl::fp::writeHexStr(pb, os, x, n);
} else { } else {
cybozu::write(pb, os, src, n); cybozu::write(pb, os, x, n);
} }
} }
return; return;
@ -329,31 +381,65 @@ public:
cybozu::write(pb, os, buf + sizeof(buf) - len, len); cybozu::write(pb, os, buf + sizeof(buf) - len, len);
} }
/* /*
mode = Mod : set x mod p if sizeof(S) * n <= 64 else error treat x as little endian
if x >= p then error
*/ */
template<class S> template<class S>
void setArray(bool *pb, const S *x, size_t n, mcl::fp::MaskMode mode = fp::NoMask) void setArray(bool *pb, const S *x, size_t n)
{ {
*pb = fp::copyAndMask(v_, x, sizeof(S) * n, op_, mode); if (!fp::convertArrayAsLE(v_, op_.N, x, n)) {
*pb = false;
return;
}
if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) {
*pb = false;
return;
}
*pb = true;
toMont(); toMont();
} }
/* /*
mask x with (1 << bitLen) and subtract p if x >= p treat x as little endian
x &= (1 << bitLen) = 1
x &= (1 << (bitLen - 1)) - 1 if x >= p
*/ */
template<class S> template<class S>
void setArrayMaskMod(const S *x, size_t n) void setArrayMask(const S *x, size_t n)
{ {
fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::MaskAndMod); const size_t dstByte = sizeof(fp::Unit) * op_.N;
if (sizeof(S) * n > dstByte) {
n = dstByte / sizeof(S);
}
bool b = fp::convertArrayAsLE(v_, op_.N, x, n);
assert(b);
(void)b;
fp::maskArray(v_, op_.N, op_.bitSize);
if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) {
fp::maskArray(v_, op_.N, op_.bitSize - 1);
}
toMont(); toMont();
} }
/* /*
mask x with (1 << (bitLen - 1)) - 1 if x >= p set (x as little endian) % p
error if size of x >= sizeof(Fp) * 2
*/ */
template<class S> template<class S>
void setArrayMask(const S *x, size_t n) void setArrayMod(bool *pb, const S *x, size_t n)
{ {
fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::SmallMask); if (sizeof(S) * n > sizeof(fp::Unit) * op_.N * 2) {
*pb = false;
return;
}
mpz_class mx;
gmp::setArray(pb, mx, x, n);
if (!*pb) return;
#ifdef MCL_USE_VINT
op_.modp.modp(mx, mx);
#else
mx %= op_.mp;
#endif
gmp::getArray(pb, v_, op_.N, mx);
if (!*pb) return;
toMont(); toMont();
} }
void getBlock(fp::Block& b) const void getBlock(fp::Block& b) const
@ -366,14 +452,82 @@ public:
b.p = &v_[0]; 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(uint8_t *buf, size_t maxN) const
{
fp::Block b;
getBlock(b);
size_t n = sizeof(fp::Unit) * b.n;
uint8_t *t = (uint8_t*)CYBOZU_ALLOCA(n);
if (!fp::convertArrayAsLE(t, n, b.p, b.n)) {
return 0;
}
while (n > 0) {
if (t[n - 1]) break;
n--;
}
if (n == 0) n = 1; // zero
if (maxN < n) return 0;
for (size_t i = 0; i < n; i++) {
buf[i] = t[i];
}
return n;
}
/*
set (little endian % p)
error if xn > 64
*/
void setLittleEndianMod(bool *pb, const uint8_t *x, size_t xn)
{
if (xn > 64) {
*pb = false;
return;
}
setArrayMod(pb, x, xn);
}
/*
set (big endian % p)
error if xn > 64
*/
void setBigEndianMod(bool *pb, const uint8_t *x, size_t xn)
{
if (xn > 64) {
*pb = false;
return;
}
uint8_t swapX[64];
for (size_t i = 0; i < xn; i++) {
swapX[xn - 1 - i] = x[i];
}
setArrayMod(pb, swapX, xn);
}
void setByCSPRNG(bool *pb, fp::RandGen rg = fp::RandGen()) void setByCSPRNG(bool *pb, fp::RandGen rg = fp::RandGen())
{ {
if (rg.isZero()) rg = fp::RandGen::get(); if (rg.isZero()) rg = fp::RandGen::get();
rg.read(pb, v_, op_.N * sizeof(Unit)); // byte size uint8_t x[sizeof(*this)];
const size_t n = op_.N * sizeof(Unit);
rg.read(pb, x, n); // byte size
if (!pb) return; if (!pb) return;
fp::convertArrayAsLE(v_, op_.N, x, n);
setArrayMask(v_, op_.N); setArrayMask(v_, op_.N);
} }
#ifndef CYBOZU_DONT_USE_EXCEPTION #ifndef CYBOZU_DONT_USE_EXCEPTION
void setLittleEndianMod(const uint8_t *buf, size_t bufSize)
{
bool b;
setLittleEndianMod(&b, buf, bufSize);
if (!b) throw cybozu::Exception("setLittleEndianMod");
}
void setBigEndianMod(const uint8_t *buf, size_t bufSize)
{
bool b;
setBigEndianMod(&b, buf, bufSize);
if (!b) throw cybozu::Exception("setBigEndianMod");
}
void setByCSPRNG(fp::RandGen rg = fp::RandGen()) void setByCSPRNG(fp::RandGen rg = fp::RandGen())
{ {
bool b; bool b;
@ -386,11 +540,15 @@ public:
setByCSPRNG(rg); setByCSPRNG(rg);
} }
/* /*
hash msg and mask with (1 << (bitLen - 1)) - 1 x = SHA-256(msg) as little endian
p = order of a finite field
L = bit size of p
x &= (1 << L) - 1
if (x >= p) x &= (1 << (L - 1)) - 1
*/ */
void setHashOf(const void *msg, size_t msgSize) void setHashOf(const void *msg, size_t msgSize)
{ {
char buf[MCL_MAX_HASH_BIT_SIZE / 8]; uint8_t buf[MCL_MAX_HASH_BIT_SIZE / 8];
uint32_t size = op_.hash(buf, static_cast<uint32_t>(sizeof(buf)), msg, static_cast<uint32_t>(msgSize)); uint32_t size = op_.hash(buf, static_cast<uint32_t>(sizeof(buf)), msg, static_cast<uint32_t>(msgSize));
setArrayMask(buf, size); setArrayMask(buf, size);
} }
@ -408,32 +566,78 @@ public:
} }
setArray(pb, gmp::getUnit(x), gmp::getUnitSize(x)); setArray(pb, gmp::getUnit(x), gmp::getUnitSize(x));
} }
static void add(FpT& z, const FpT& x, const FpT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_addA_(z.v_, x.v_, y.v_);
#else
op_.fp_add(z.v_, x.v_, y.v_, op_.p);
#endif
}
static void sub(FpT& z, const FpT& x, const FpT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_subA_(z.v_, x.v_, y.v_);
#else
op_.fp_sub(z.v_, x.v_, y.v_, op_.p);
#endif
}
static void neg(FpT& y, const FpT& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_negA_(y.v_, x.v_);
#else
op_.fp_neg(y.v_, x.v_, op_.p);
#endif
}
static void mul(FpT& z, const FpT& x, const FpT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_mulA_(z.v_, x.v_, y.v_);
#else
op_.fp_mul(z.v_, x.v_, y.v_, op_.p);
#endif
}
static void sqr(FpT& y, const FpT& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_sqrA_(y.v_, x.v_);
#else
op_.fp_sqr(y.v_, x.v_, op_.p);
#endif
}
static void mul2(FpT& y, const FpT& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL #ifdef MCL_XBYAK_DIRECT_CALL
static void (*add)(FpT& z, const FpT& x, const FpT& y); op_.fp_mul2A_(y.v_, x.v_);
static inline void addC(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); }
static void (*sub)(FpT& z, const FpT& x, const FpT& y);
static inline void subC(FpT& z, const FpT& x, const FpT& y) { op_.fp_sub(z.v_, x.v_, y.v_, op_.p); }
static void (*neg)(FpT& y, const FpT& x);
static inline void negC(FpT& y, const FpT& x) { op_.fp_neg(y.v_, x.v_, op_.p); }
static void (*mul)(FpT& z, const FpT& x, const FpT& y);
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); }
#else #else
static inline void add(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); } op_.fp_mul2(y.v_, x.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); }
#endif #endif
}
static void mul9(FpT& y, const FpT& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_mul9A_(y.v_, x.v_);
#else
mul9A(y.v_, x.v_);
#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 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 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)
{
mulSmall(z.v_, x.v_, y);
}
static inline void mulUnit(FpT& z, const FpT& x, const Unit y) static inline void mulUnit(FpT& z, const FpT& x, const Unit y)
{ {
if (mulSmallUnit(z, x, y)) return; if (mulSmallUnit(z, x, y)) return;
op_.fp_mulUnit(z.v_, x.v_, y, op_.p); op_.fp_mulUnit(z.v_, x.v_, y, op_.p);
} }
static inline void inv(FpT& y, const FpT& x) { op_.fp_invOp(y.v_, x.v_, op_); } static inline void inv(FpT& y, const FpT& x)
{
assert(!x.isZero());
op_.fp_invOp(y.v_, x.v_, op_);
}
static inline void divBy2(FpT& y, const FpT& x) static inline void divBy2(FpT& y, const FpT& x)
{ {
#if 0 #if 0
@ -526,9 +730,12 @@ public:
} }
static void setETHserialization(bool ETHserialization) static void setETHserialization(bool ETHserialization)
{ {
if (getBitSize() != 381) return;
isETHserialization_ = ETHserialization; isETHserialization_ = ETHserialization;
} }
static bool getETHserialization()
{
return isETHserialization_;
}
static inline bool isETHserialization() { return isETHserialization_; } static inline bool isETHserialization() { return isETHserialization_; }
static inline int getIoMode() { return ioMode_; } static inline int getIoMode() { return ioMode_; }
static inline size_t getModBitLen() { return getBitSize(); } static inline size_t getModBitLen() { return getBitSize(); }
@ -655,16 +862,10 @@ template<class tag, size_t maxBitSize> fp::Op FpT<tag, maxBitSize>::op_;
template<class tag, size_t maxBitSize> FpT<tag, maxBitSize> FpT<tag, maxBitSize>::inv2_; template<class tag, size_t maxBitSize> FpT<tag, maxBitSize> FpT<tag, maxBitSize>::inv2_;
template<class tag, size_t maxBitSize> int FpT<tag, maxBitSize>::ioMode_ = IoAuto; template<class tag, size_t maxBitSize> int FpT<tag, maxBitSize>::ioMode_ = IoAuto;
template<class tag, size_t maxBitSize> bool FpT<tag, maxBitSize>::isETHserialization_ = false; template<class tag, size_t maxBitSize> bool FpT<tag, maxBitSize>::isETHserialization_ = false;
#ifdef MCL_XBYAK_DIRECT_CALL
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::add)(FpT& z, const FpT& x, const FpT& y);
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::sub)(FpT& z, const FpT& x, const FpT& y);
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);
#endif
} // mcl } // mcl
#ifndef CYBOZU_DONT_USE_EXCEPTION
#ifdef CYBOZU_USE_BOOST #ifdef CYBOZU_USE_BOOST
namespace mcl { namespace mcl {
@ -688,6 +889,7 @@ struct hash<mcl::FpT<tag, maxBitSize> > {
CYBOZU_NAMESPACE_TR1_END } // std::tr1 CYBOZU_NAMESPACE_TR1_END } // std::tr1
#endif #endif
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)

@ -10,22 +10,18 @@
namespace mcl { namespace mcl {
template<class Fp> struct Fp12T;
template<class Fp> class BNT;
template<class Fp> struct Fp2DblT;
template<class Fp> template<class Fp>
class FpDblT : public fp::Serializable<FpDblT<Fp> > { class FpDblT : public fp::Serializable<FpDblT<Fp> > {
typedef fp::Unit Unit; typedef fp::Unit Unit;
Unit v_[Fp::maxSize * 2]; Unit v_[Fp::maxSize * 2];
friend struct Fp2DblT<Fp>;
public: public:
static size_t getUnitSize() { return Fp::op_.N * 2; } static size_t getUnitSize() { return Fp::op_.N * 2; }
FpDblT() : v_() const fp::Unit *getUnit() const { return v_; }
{
}
FpDblT(const FpDblT& rhs)
{
const size_t n = getUnitSize();
for (size_t i = 0; i < n; i++) {
v_[i] = rhs.v_[i];
}
}
void dump() const void dump() const
{ {
const size_t n = getUnitSize(); const size_t n = getUnitSize();
@ -117,31 +113,42 @@ public:
{ {
gmp::setArray(pb, x, v_, Fp::op_.N * 2); gmp::setArray(pb, x, v_, Fp::op_.N * 2);
} }
static inline void add(FpDblT& z, const FpDblT& x, const FpDblT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fpDbl_addA_(z.v_, x.v_, y.v_);
#else
Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p);
#endif
}
static inline void sub(FpDblT& z, const FpDblT& x, const FpDblT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fpDbl_subA_(z.v_, x.v_, y.v_);
#else
Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p);
#endif
}
static inline void mod(Fp& z, const FpDblT& xy)
{
#ifdef MCL_XBYAK_DIRECT_CALL #ifdef MCL_XBYAK_DIRECT_CALL
static void (*add)(FpDblT& z, const FpDblT& x, const FpDblT& y); Fp::op_.fpDbl_modA_(z.v_, xy.v_);
static void (*sub)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void (*mod)(Fp& z, const FpDblT& xy);
static void (*addPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void (*subPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void addC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); }
static void subC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); }
static void modC(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); }
static void addPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); }
static void subPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); }
#else #else
static void add(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); } Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p);
static void sub(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); } #endif
static void mod(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); } }
#ifdef MCL_XBYAK_DIRECT_CALL
static void addA(Unit *z, const Unit *x, const Unit *y) { Fp::op_.fpDbl_add(z, x, y, Fp::op_.p); }
static void subA(Unit *z, const Unit *x, const Unit *y) { Fp::op_.fpDbl_sub(z, x, y, Fp::op_.p); }
static void modA(Unit *z, const Unit *xy) { Fp::op_.fpDbl_mod(z, xy, Fp::op_.p); }
#endif
static void addPre(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); } 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_); } 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) mul(z, x, y) = mulPre(xy, x, y) + mod(z, xy)
*/ */
static void (*mulPre)(FpDblT& xy, const Fp& x, const Fp& y); static void mulPre(FpDblT& xy, const Fp& x, const Fp& y) { Fp::op_.fpDbl_mulPre(xy.v_, x.v_, y.v_); }
static void (*sqrPre)(FpDblT& xx, const Fp& x); static void sqrPre(FpDblT& xx, const Fp& x) { Fp::op_.fpDbl_sqrPre(xx.v_, x.v_); }
static void mulUnit(FpDblT& z, const FpDblT& x, Unit y) static void mulUnit(FpDblT& z, const FpDblT& x, Unit y)
{ {
if (mulSmallUnit(z, x, y)) return; if (mulSmallUnit(z, x, y)) return;
@ -149,47 +156,23 @@ public:
} }
static void init() static void init()
{ {
const mcl::fp::Op& op = Fp::getOp();
#ifdef MCL_XBYAK_DIRECT_CALL #ifdef MCL_XBYAK_DIRECT_CALL
add = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_addA_); mcl::fp::Op& op = Fp::op_;
if (add == 0) add = addC; if (op.fpDbl_addA_ == 0) {
sub = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_subA_); op.fpDbl_addA_ = addA;
if (sub == 0) sub = subC;
mod = fp::func_ptr_cast<void (*)(Fp&, const FpDblT&)>(op.fpDbl_modA_);
if (mod == 0) mod = modC;
addPre = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_addPre);
if (addPre == 0) addPre = addPreC;
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_) { if (op.fpDbl_subA_ == 0) {
sqrPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&)>(op.fpDbl_sqrPreA_); op.fpDbl_subA_ = subA;
} else {
sqrPre = sqrPreC;
} }
if (op.fpDbl_modA_ == 0) {
op.fpDbl_modA_ = modA;
}
#endif
} }
void operator+=(const FpDblT& x) { add(*this, *this, x); } void operator+=(const FpDblT& x) { add(*this, *this, x); }
void operator-=(const FpDblT& x) { sub(*this, *this, x); } void operator-=(const FpDblT& x) { sub(*this, *this, x); }
}; };
#ifdef MCL_XBYAK_DIRECT_CALL
template<class Fp> void (*FpDblT<Fp>::add)(FpDblT&, const FpDblT&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::sub)(FpDblT&, const FpDblT&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::mod)(Fp&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::addPre)(FpDblT&, const FpDblT&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::subPre)(FpDblT&, const FpDblT&, const FpDblT&);
#endif
template<class Fp> void (*FpDblT<Fp>::mulPre)(FpDblT&, const Fp&, const Fp&);
template<class Fp> void (*FpDblT<Fp>::sqrPre)(FpDblT&, const Fp&);
template<class Fp> struct Fp12T;
template<class Fp> class BNT;
template<class Fp> struct Fp2DblT;
/* /*
beta = -1 beta = -1
Fp2 = F[i] / (i^2 + 1) Fp2 = F[i] / (i^2 + 1)
@ -240,22 +223,79 @@ public:
a = a_; a = a_;
b = b_; b = b_;
} }
static void add(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_addA_(z.a.v_, x.a.v_, y.a.v_);
#else
addA(z.a.v_, x.a.v_, y.a.v_);
#endif
}
static void sub(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_subA_(z.a.v_, x.a.v_, y.a.v_);
#else
subA(z.a.v_, x.a.v_, y.a.v_);
#endif
}
static void neg(Fp2T& y, const Fp2T& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL #ifdef MCL_XBYAK_DIRECT_CALL
static void (*add)(Fp2T& z, const Fp2T& x, const Fp2T& y); Fp::op_.fp2_negA_(y.a.v_, x.a.v_);
static void (*sub)(Fp2T& z, const Fp2T& x, const Fp2T& y);
static void (*neg)(Fp2T& y, const Fp2T& x);
static void (*mul)(Fp2T& z, const Fp2T& x, const Fp2T& y);
static void (*sqr)(Fp2T& y, const Fp2T& x);
#else #else
static void add(Fp2T& z, const Fp2T& x, const Fp2T& y) { addC(z, x, y); } negA(y.a.v_, x.a.v_);
static void sub(Fp2T& z, const Fp2T& x, const Fp2T& y) { subC(z, x, y); }
static void neg(Fp2T& y, const Fp2T& x) { negC(y, x); }
static void mul(Fp2T& z, const Fp2T& x, const Fp2T& y) { mulC(z, x, y); }
static void sqr(Fp2T& y, const Fp2T& x) { sqrC(y, x); }
#endif #endif
static void (*mul_xi)(Fp2T& y, const Fp2T& x); }
static void addPre(Fp2T& z, const Fp2T& x, const Fp2T& y) { Fp::addPre(z.a, x.a, y.a); Fp::addPre(z.b, x.b, y.b); } static void mul(Fp2T& z, const Fp2T& x, const Fp2T& y)
static void inv(Fp2T& y, const Fp2T& x) { Fp::op_.fp2_inv(y.a.v_, x.a.v_); } {
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_mulA_(z.a.v_, x.a.v_, y.a.v_);
#else
mulA(z.a.v_, x.a.v_, y.a.v_);
#endif
}
static void sqr(Fp2T& y, const Fp2T& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_sqrA_(y.a.v_, x.a.v_);
#else
sqrA(y.a.v_, x.a.v_);
#endif
}
static void mul2(Fp2T& y, const Fp2T& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_mul2A_(y.a.v_, x.a.v_);
#else
mul2A(y.a.v_, x.a.v_);
#endif
}
static void mul_xi(Fp2T& y, const Fp2T& x)
{
Fp::op_.fp2_mul_xiA_(y.a.v_, x.a.v_);
}
/*
x = a + bi
1 / x = (a - bi) / (a^2 + b^2)
*/
static void inv(Fp2T& y, const Fp2T& x)
{
assert(!x.isZero());
const Fp& a = x.a;
const Fp& b = x.b;
Fp r;
norm(r, x);
Fp::inv(r, r); // r = 1 / (a^2 + b^2)
Fp::mul(y.a, a, r);
Fp::mul(y.b, b, r);
Fp::neg(y.b, y.b);
}
static void addPre(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
Fp::addPre(z.a, x.a, y.a);
Fp::addPre(z.b, x.b, y.b);
}
static void divBy2(Fp2T& y, const Fp2T& x) static void divBy2(Fp2T& y, const Fp2T& x)
{ {
Fp::divBy2(y.a, x.a); Fp::divBy2(y.a, x.a);
@ -360,12 +400,14 @@ public:
Fp::mul(y.b, x.b, t2); Fp::mul(y.b, x.b, t2);
return true; return true;
} }
// y = a^2 + b^2
static void inline norm(Fp& y, const Fp2T& x) static void inline norm(Fp& y, const Fp2T& x)
{ {
Fp aa, bb; FpDbl AA, BB;
Fp::sqr(aa, x.a); FpDbl::sqrPre(AA, x.a);
Fp::sqr(bb, x.b); FpDbl::sqrPre(BB, x.b);
Fp::add(y, aa, bb); FpDbl::addPre(AA, AA, BB);
FpDbl::mod(y, AA);
} }
/* /*
Frobenius Frobenius
@ -389,31 +431,40 @@ public:
} }
static uint32_t get_xi_a() { return Fp::getOp().xi_a; } 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_; mcl::fp::Op& op = Fp::op_;
assert(op.xi_a); assert(op.xi_a);
mul_xi = 0; // 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;
}
#ifdef MCL_XBYAK_DIRECT_CALL #ifdef MCL_XBYAK_DIRECT_CALL
add = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_addA_); if (op.fp2_addA_ == 0) {
if (add == 0) add = addC; op.fp2_addA_ = addA;
sub = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_subA_); }
if (sub == 0) sub = subC; if (op.fp2_subA_ == 0) {
neg = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_negA_); op.fp2_subA_ = subA;
if (neg == 0) neg = negC; }
mul = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_mulA_); if (op.fp2_negA_ == 0) {
if (mul == 0) mul = mulC; op.fp2_negA_ = negA;
sqr = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_sqrA_); }
if (sqr == 0) sqr = sqrC; if (op.fp2_mulA_ == 0) {
mul_xi = fp::func_ptr_cast<void (*)(Fp2T&, const Fp2T&)>(op.fp2_mul_xiA_); op.fp2_mulA_ = mulA;
}
if (op.fp2_sqrA_ == 0) {
op.fp2_sqrA_ = sqrA;
}
if (op.fp2_mul2A_ == 0) {
op.fp2_mul2A_ = mul2A;
}
#endif #endif
op.fp2_inv = fp2_invW; if (op.fp2_mul_xiA_ == 0) {
if (mul_xi == 0) {
if (op.xi_a == 1) { if (op.xi_a == 1) {
mul_xi = fp2_mul_xi_1_1iC; op.fp2_mul_xiA_ = fp2_mul_xi_1_1iA;
} else { } else {
mul_xi = fp2_mul_xiC; op.fp2_mul_xiA_ = fp2_mul_xiA;
} }
} }
FpDblT<Fp>::init(); FpDblT<Fp>::init();
@ -446,8 +497,15 @@ public:
Fp2T::mul(g2[i], t, g[i]); Fp2T::mul(g2[i], t, g[i]);
g3[i] = g[i] * g2[i]; g3[i] = g[i] * g2[i];
} }
*pb = true;
} }
#ifndef CYBOZU_DONT_USE_EXCEPTION #ifndef CYBOZU_DONT_USE_EXCEPTION
static void init()
{
bool b;
init(&b);
if (!b) throw cybozu::Exception("Fp2::init");
}
template<class InputStream> template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize) void load(InputStream& is, int ioMode = IoSerialize)
{ {
@ -484,75 +542,65 @@ public:
} }
#endif #endif
private: private:
static Fp2T& cast(Unit *x) { return *reinterpret_cast<Fp2T*>(x); }
static const Fp2T& cast(const Unit *x) { return *reinterpret_cast<const Fp2T*>(x); }
/* /*
default Fp2T operator default Fp2T operator
Fp2T = Fp[i]/(i^2 + 1) Fp2T = Fp[i]/(i^2 + 1)
*/ */
static void addC(Fp2T& z, const Fp2T& x, const Fp2T& y) static void addA(Unit *pz, const Unit *px, const Unit *py)
{ {
Fp2T& z = cast(pz);
const Fp2T& x = cast(px);
const Fp2T& y = cast(py);
Fp::add(z.a, x.a, y.a); Fp::add(z.a, x.a, y.a);
Fp::add(z.b, x.b, y.b); Fp::add(z.b, x.b, y.b);
} }
static void subC(Fp2T& z, const Fp2T& x, const Fp2T& y) static void subA(Unit *pz, const Unit *px, const Unit *py)
{ {
Fp2T& z = cast(pz);
const Fp2T& x = cast(px);
const Fp2T& y = cast(py);
Fp::sub(z.a, x.a, y.a); Fp::sub(z.a, x.a, y.a);
Fp::sub(z.b, x.b, y.b); Fp::sub(z.b, x.b, y.b);
} }
static void negC(Fp2T& y, const Fp2T& x) static void negA(Unit *py, const Unit *px)
{ {
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
Fp::neg(y.a, x.a); Fp::neg(y.a, x.a);
Fp::neg(y.b, x.b); Fp::neg(y.b, x.b);
} }
#if 0 static void mulA(Unit *pz, const Unit *px, const Unit *py)
/*
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)
{
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);
}
#endif
static void mulC(Fp2T& z, const Fp2T& x, const Fp2T& y)
{ {
Fp2T& z = cast(pz);
const Fp2T& x = cast(px);
const Fp2T& y = cast(py);
Fp2Dbl d; Fp2Dbl d;
Fp2Dbl::mulPre(d, x, y); Fp2Dbl::mulPre(d, x, y);
FpDbl::mod(z.a, d.a); FpDbl::mod(z.a, d.a);
FpDbl::mod(z.b, d.b); FpDbl::mod(z.b, d.b);
} }
static void mul2A(Unit *py, const Unit *px)
{
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
Fp::mul2(y.a, x.a);
Fp::mul2(y.b, x.b);
}
/* /*
x = a + bi, i^2 = -1 x = a + bi, i^2 = -1
y = x^2 = (a + bi)^2 = (a + b)(a - b) + 2abi y = x^2 = (a + bi)^2 = (a + b)(a - b) + 2abi
*/ */
static void sqrC(Fp2T& y, const Fp2T& x) static void sqrA(Unit *py, const Unit *px)
{ {
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
const Fp& a = x.a; const Fp& a = x.a;
const Fp& b = x.b; const Fp& b = x.b;
#if 1 // faster than using FpDbl #if 1 // faster than using FpDbl
Fp t1, t2, t3; Fp t1, t2, t3;
Fp::add(t1, b, b); // 2b Fp::mul2(t1, b);
t1 *= a; // 2ab t1 *= a; // 2ab
Fp::add(t2, a, b); // a + b Fp::add(t2, a, b); // a + b
Fp::sub(t3, a, b); // a - b Fp::sub(t3, a, b); // a - b
@ -576,8 +624,10 @@ private:
y = (a + bi)xi = (a + bi)(xi_a + i) y = (a + bi)xi = (a + bi)(xi_a + i)
=(a * x_ia - b) + (a + b xi_a)i =(a * x_ia - b) + (a + b xi_a)i
*/ */
static void fp2_mul_xiC(Fp2T& y, const Fp2T& x) static void fp2_mul_xiA(Unit *py, const Unit *px)
{ {
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
const Fp& a = x.a; const Fp& a = x.a;
const Fp& b = x.b; const Fp& b = x.b;
Fp t; Fp t;
@ -591,8 +641,10 @@ private:
xi = 1 + i ; xi_a = 1 xi = 1 + i ; xi_a = 1
y = (a + bi)xi = (a - b) + (a + b)i y = (a + bi)xi = (a - b) + (a + b)i
*/ */
static void fp2_mul_xi_1_1iC(Fp2T& y, const Fp2T& x) static void fp2_mul_xi_1_1iA(Unit *py, const Unit *px)
{ {
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
const Fp& a = x.a; const Fp& a = x.a;
const Fp& b = x.b; const Fp& b = x.b;
Fp t; Fp t;
@ -600,38 +652,11 @@ private:
Fp::sub(y.a, a, b); Fp::sub(y.a, a, b);
y.b = t; y.b = t;
} }
/*
x = a + bi
1 / x = (a - bi) / (a^2 + b^2)
*/
static void fp2_invW(Unit *y, const Unit *x)
{
const Fp *px = reinterpret_cast<const Fp*>(x);
Fp *py = reinterpret_cast<Fp*>(y);
const Fp& a = px[0];
const Fp& b = px[1];
Fp aa, bb;
Fp::sqr(aa, a);
Fp::sqr(bb, b);
aa += bb;
Fp::inv(aa, aa); // aa = 1 / (a^2 + b^2)
Fp::mul(py[0], a, aa);
Fp::mul(py[1], b, aa);
Fp::neg(py[1], py[1]);
}
}; };
#ifdef MCL_XBYAK_DIRECT_CALL
template<class Fp_> void (*Fp2T<Fp_>::add)(Fp2T& z, const Fp2T& x, const Fp2T& y);
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);
#endif
template<class Fp_> void (*Fp2T<Fp_>::mul_xi)(Fp2T& y, const Fp2T& x);
template<class Fp> template<class Fp>
struct Fp2DblT { struct Fp2DblT {
typedef Fp2DblT<Fp> Fp2Dbl;
typedef FpDblT<Fp> FpDbl; typedef FpDblT<Fp> FpDbl;
typedef Fp2T<Fp> Fp2; typedef Fp2T<Fp> Fp2;
typedef fp::Unit Unit; typedef fp::Unit Unit;
@ -656,30 +681,32 @@ struct Fp2DblT {
FpDbl::subPre(z.a, x.a, y.a); FpDbl::subPre(z.a, x.a, y.a);
FpDbl::subPre(z.b, x.b, y.b); 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) static void neg(Fp2DblT& y, const Fp2DblT& x)
{ {
FpDbl::neg(y.a, x.a); FpDbl::neg(y.a, x.a);
FpDbl::neg(y.b, x.b); FpDbl::neg(y.b, x.b);
} }
static void mulPre(Fp2DblT& z, const Fp2& x, const Fp2& y)
{
Fp::getOp().fp2Dbl_mulPreA_(z.a.v_, x.getUnit(), y.getUnit());
}
static void sqrPre(Fp2DblT& y, const Fp2& x)
{
Fp::getOp().fp2Dbl_sqrPreA_(y.a.v_, x.getUnit());
}
static void mul_xi(Fp2DblT& y, const Fp2DblT& x) static void mul_xi(Fp2DblT& y, const Fp2DblT& x)
{ {
const uint32_t xi_a = Fp2::get_xi_a(); Fp::getOp().fp2Dbl_mul_xiA_(y.a.v_, x.a.getUnit());
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 {
FpDbl t;
FpDbl::mulUnit(t, x.a, xi_a);
FpDbl::sub(t, t, x.b);
FpDbl::mulUnit(y.b, x.b, xi_a);
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 mod(Fp2& y, const Fp2DblT& x) static void mod(Fp2& y, const Fp2DblT& x)
{ {
FpDbl::mod(y.a, x.a); FpDbl::mod(y.a, x.a);
@ -695,33 +722,38 @@ struct Fp2DblT {
void operator-=(const Fp2DblT& x) { sub(*this, *this, x); } void operator-=(const Fp2DblT& x) { sub(*this, *this, x); }
static void init() static void init()
{ {
const mcl::fp::Op& op = Fp::getOp(); assert(!Fp::getOp().isFullBit);
if (op.fp2Dbl_mulPreA_) { mcl::fp::Op& op = Fp::getOpNonConst();
mulPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&, const Fp2&)>(op.fp2Dbl_mulPreA_); if (op.fp2Dbl_mulPreA_ == 0) {
} else { op.fp2Dbl_mulPreA_ = mulPreA;
if (op.isFullBit) {
mulPre = fp2Dbl_mulPreW<true>;
} else {
mulPre = fp2Dbl_mulPreW<false>;
}
} }
if (op.fp2Dbl_sqrPreA_) { if (op.fp2Dbl_sqrPreA_ == 0) {
sqrPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&)>(op.fp2Dbl_sqrPreA_); op.fp2Dbl_sqrPreA_ = sqrPreA;
} else { }
if (op.isFullBit) { if (op.fp2Dbl_mul_xiA_ == 0) {
sqrPre = fp2Dbl_sqrPreW<true>; const uint32_t xi_a = Fp2::get_xi_a();
if (xi_a == 1) {
op.fp2Dbl_mul_xiA_ = mul_xi_1A;
} else { } else {
sqrPre = fp2Dbl_sqrPreW<false>; op.fp2Dbl_mul_xiA_ = mul_xi_genericA;
} }
} }
} }
private:
static Fp2 cast(Unit *x) { return *reinterpret_cast<Fp2*>(x); }
static const Fp2 cast(const Unit *x) { return *reinterpret_cast<const Fp2*>(x); }
static Fp2Dbl& castD(Unit *x) { return *reinterpret_cast<Fp2Dbl*>(x); }
static const Fp2Dbl& castD(const Unit *x) { return *reinterpret_cast<const Fp2Dbl*>(x); }
/* /*
Fp2Dbl::mulPre by FpDblT Fp2Dbl::mulPre by FpDblT
@note mod of NIST_P192 is fast @note mod of NIST_P192 is fast
*/ */
template<bool isFullBit> static void mulPreA(Unit *pz, const Unit *px, const Unit *py)
static void fp2Dbl_mulPreW(Fp2DblT& z, const Fp2& x, const Fp2& y)
{ {
Fp2Dbl& z = castD(pz);
const Fp2& x = cast(px);
const Fp2& y = cast(py);
assert(!Fp::getOp().isFullBit);
const Fp& a = x.a; const Fp& a = x.a;
const Fp& b = x.b; const Fp& b = x.b;
const Fp& c = y.a; const Fp& c = y.a;
@ -730,45 +762,50 @@ struct Fp2DblT {
FpDbl& d1 = z.b; FpDbl& d1 = z.b;
FpDbl d2; FpDbl d2;
Fp s, t; Fp s, t;
if (isFullBit) { Fp::addPre(s, a, b);
Fp::add(s, a, b); Fp::addPre(t, c, d);
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(d1, s, t); // (a + b)(c + d)
FpDbl::mulPre(d0, a, c); FpDbl::mulPre(d0, a, c);
FpDbl::mulPre(d2, b, d); FpDbl::mulPre(d2, b, d);
if (isFullBit) { FpDbl::subPre(d1, d1, d0);
FpDbl::sub(d1, d1, d0); // (a + b)(c + d) - ac FpDbl::subPre(d1, d1, d2);
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 FpDbl::sub(d0, d0, d2); // ac - bd
} }
template<bool isFullBit> static void sqrPreA(Unit *py, const Unit *px)
static void fp2Dbl_sqrPreW(Fp2DblT& y, const Fp2& x)
{ {
assert(!Fp::getOp().isFullBit);
Fp2Dbl& y = castD(py);
const Fp2& x = cast(px);
Fp t1, t2; Fp t1, t2;
if (isFullBit) { Fp::addPre(t1, x.b, x.b); // 2b
Fp::add(t1, x.b, x.b); // 2b Fp::addPre(t2, x.a, x.b); // a + b
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 FpDbl::mulPre(y.b, t1, x.a); // 2ab
Fp::sub(t1, x.a, x.b); // a - b Fp::sub(t1, x.a, x.b); // a - b
FpDbl::mulPre(y.a, t1, t2); // (a + b)(a - b) FpDbl::mulPre(y.a, t1, t2); // (a + b)(a - b)
} }
static void mul_xi_1A(Unit *py, const Unit *px)
{
Fp2Dbl& y = castD(py);
const Fp2Dbl& x = castD(px);
FpDbl t;
FpDbl::add(t, x.a, x.b);
FpDbl::sub(y.a, x.a, x.b);
y.b = t;
}
static void mul_xi_genericA(Unit *py, const Unit *px)
{
const uint32_t xi_a = Fp2::get_xi_a();
Fp2Dbl& y = castD(py);
const Fp2Dbl& x = castD(px);
FpDbl t;
FpDbl::mulUnit(t, x.a, xi_a);
FpDbl::sub(t, t, x.b);
FpDbl::mulUnit(y.b, x.b, xi_a);
FpDbl::add(y.b, y.b, x.a);
y.a = t;
}
}; };
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> Fp2T<Fp> Fp2T<Fp>::g[Fp2T<Fp>::gN]; template<class Fp> Fp2T<Fp> Fp2T<Fp>::g[Fp2T<Fp>::gN];
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g2[Fp2T<Fp>::gN]; template<class Fp> Fp2T<Fp> Fp2T<Fp>::g2[Fp2T<Fp>::gN];
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g3[Fp2T<Fp>::gN]; template<class Fp> Fp2T<Fp> Fp2T<Fp>::g3[Fp2T<Fp>::gN];
@ -889,34 +926,24 @@ struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
Fp2::neg(y.b, x.b); Fp2::neg(y.b, x.b);
Fp2::neg(y.c, x.c); Fp2::neg(y.c, x.c);
} }
/* static void mul2(Fp6T& y, const Fp6T& x)
x = a + bv + cv^2, v^3 = xi {
x^2 = (a^2 + 2bc xi) + (c^2 xi + 2ab)v + (b^2 + 2ac)v^2 Fp2::mul2(y.a, x.a);
Fp2::mul2(y.b, x.b);
b^2 + 2ac = (a + b + c)^2 - a^2 - 2bc - c^2 - 2ab Fp2::mul2(y.c, x.c);
*/ }
static void sqr(Fp6T& y, const Fp6T& x) static void sqr(Fp6T& y, const Fp6T& x)
{ {
Fp2 t1, t2, t3; Fp6Dbl XX;
Fp2::mul(t1, x.a, x.b); Fp6Dbl::sqrPre(XX, x);
t1 += t1; // 2ab Fp6Dbl::mod(y, XX);
Fp2::mul(t2, x.b, x.c); }
t2 += t2; // 2bc static inline void mul(Fp6T& z, const Fp6T& x, const Fp6T& y)
Fp2::sqr(t3, x.c); // c^2 {
Fp2::add(y.c, x.a, x.c); // a + c, destroy y.c Fp6Dbl XY;
y.c += x.b; // a + b + c Fp6Dbl::mulPre(XY, x, y);
Fp2::sqr(y.b, y.c); // (a + b + c)^2, destroy y.b Fp6Dbl::mod(z, XY);
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);
/* /*
x = a + bv + cv^2, v^3 = xi x = a + bv + cv^2, v^3 = xi
y = 1/x = p/q where y = 1/x = p/q where
@ -929,27 +956,34 @@ struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
const Fp2& a = x.a; const Fp2& a = x.a;
const Fp2& b = x.b; const Fp2& b = x.b;
const Fp2& c = x.c; const Fp2& c = x.c;
Fp2 aa, bb, cc, ab, bc, ac; Fp2Dbl aa, bb, cc, ab, bc, ac;
Fp2::sqr(aa, a); Fp2Dbl::sqrPre(aa, a);
Fp2::sqr(bb, b); Fp2Dbl::sqrPre(bb, b);
Fp2::sqr(cc, c); Fp2Dbl::sqrPre(cc, c);
Fp2::mul(ab, a, b); Fp2Dbl::mulPre(ab, a, b);
Fp2::mul(bc, b, c); Fp2Dbl::mulPre(bc, b, c);
Fp2::mul(ac, c, a); Fp2Dbl::mulPre(ac, c, a);
Fp6T p; Fp6T p;
Fp2::mul_xi(p.a, bc); Fp2Dbl T;
Fp2::sub(p.a, aa, p.a); // a^2 - bc xi Fp2Dbl::mul_xi(T, bc);
Fp2::mul_xi(p.b, cc); Fp2Dbl::sub(T, aa, T); // a^2 - bc xi
p.b -= ab; // c^2 xi - ab Fp2Dbl::mod(p.a, T);
Fp2::sub(p.c, bb, ac); // b^2 - ac Fp2Dbl::mul_xi(T, cc);
Fp2 q, t; Fp2Dbl::sub(T, T, ab); // c^2 xi - ab
Fp2::mul(q, p.b, c); Fp2Dbl::mod(p.b, T);
Fp2::mul(t, p.c, b); Fp2Dbl::sub(T, bb, ac); // b^2 - ac
q += t; Fp2Dbl::mod(p.c, T);
Fp2::mul_xi(q, q);
Fp2::mul(t, p.a, a); Fp2Dbl T2;
q += t; 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::inv(q, q);
Fp2::mul(y.a, p.a, q); Fp2::mul(y.a, p.a, q);
@ -962,6 +996,7 @@ template<class Fp>
struct Fp6DblT { struct Fp6DblT {
typedef Fp2T<Fp> Fp2; typedef Fp2T<Fp> Fp2;
typedef Fp6T<Fp> Fp6; typedef Fp6T<Fp> Fp6;
typedef FpDblT<Fp> FpDbl;
typedef Fp2DblT<Fp> Fp2Dbl; typedef Fp2DblT<Fp> Fp2Dbl;
typedef Fp6DblT<Fp> Fp6Dbl; typedef Fp6DblT<Fp> Fp6Dbl;
typedef fp::Unit Unit; typedef fp::Unit Unit;
@ -984,51 +1019,75 @@ struct Fp6DblT {
bf + ce = (b + c)(e + f) - be - cf bf + ce = (b + c)(e + f) - be - cf
ae + bd = (a + b)(e + d) - ad - be ae + bd = (a + b)(e + d) - ad - be
af + cd = (a + c)(d + f) - ad - cf 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) static void mulPre(Fp6DblT& z, const Fp6& x, const Fp6& y)
{ {
//clk.begin();
const Fp2& a = x.a; const Fp2& a = x.a;
const Fp2& b = x.b; const Fp2& b = x.b;
const Fp2& c = x.c; const Fp2& c = x.c;
const Fp2& d = y.a; const Fp2& d = y.a;
const Fp2& e = y.b; const Fp2& e = y.b;
const Fp2& f = y.c; const Fp2& f = y.c;
Fp2Dbl& za = z.a; Fp2Dbl& ZA = z.a;
Fp2Dbl& zb = z.b; Fp2Dbl& ZB = z.b;
Fp2Dbl& zc = z.c; Fp2Dbl& ZC = z.c;
Fp2Dbl BE; Fp2 t1, t2;
Fp2Dbl::mulPre(za, a, d); 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(BE, b, e);
Fp2Dbl::mulPre(zb, c, f); Fp2Dbl::mulPre(CF, c, f);
Fp2Dbl::mulPre(AD, a, d);
Fp2 t1, t2, t3, t4; Fp2Dbl::subSpecial(ZA, BE);
Fp2::add(t1, b, c); Fp2Dbl::subSpecial(ZA, CF);
Fp2::add(t2, e, f); Fp2Dbl::subSpecial(ZB, AD);
Fp2Dbl T1; Fp2Dbl::subSpecial(ZB, BE);
Fp2Dbl::mulPre(T1, t1, t2); Fp2Dbl::subSpecial(ZC, AD);
Fp2Dbl::sub(T1, T1, BE); Fp2Dbl::subSpecial(ZC, CF);
Fp2Dbl::sub(T1, T1, zb); Fp2Dbl::mul_xi(ZA, ZA);
Fp2Dbl::mul_xi(T1, T1); Fp2Dbl::add(ZA, ZA, AD);
Fp2Dbl::mul_xi(CF, CF);
Fp2::add(t2, a, b); Fp2Dbl::add(ZB, ZB, CF);
Fp2::add(t3, e, d); Fp2Dbl::add(ZC, ZC, BE);
Fp2Dbl T2; }
Fp2Dbl::mulPre(T2, t2, t3); /*
Fp2Dbl::sub(T2, T2, za); x = a + bv + cv^2, v^3 = xi
Fp2Dbl::sub(T2, T2, BE); x^2 = (a^2 + 2bc xi) + (c^2 xi + 2ab)v + (b^2 + 2ac)v^2
Fp2::add(t3, a, c);
Fp2::add(t4, d, f);
Fp2Dbl::mulPre(zc, t3, t4);
Fp2Dbl::sub(zc, zc, za);
Fp2Dbl::sub(zc, zc, zb);
Fp2Dbl::add(za, za, T1); b^2 + 2ac = (a + b + c)^2 - a^2 - 2bc - c^2 - 2ab
Fp2Dbl::mul_xi(zb, zb); */
Fp2Dbl::add(zb, zb, T2); static void sqrPre(Fp6DblT& y, const Fp6& x)
Fp2Dbl::add(zc, zc, BE); {
//clk.end(); 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) static void mod(Fp6& y, const Fp6Dbl& x)
{ {
@ -1038,14 +1097,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) Fp12T = Fp6[w] / (w^2 - v)
x = a + b w x = a + b w
@ -1148,7 +1199,6 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
Fp6 t1, t2; Fp6 t1, t2;
Fp6::add(t1, a, b); Fp6::add(t1, a, b);
Fp6::add(t2, c, d); Fp6::add(t2, c, d);
#if 1
Fp6Dbl T, AC, BD; Fp6Dbl T, AC, BD;
Fp6Dbl::mulPre(AC, a, c); Fp6Dbl::mulPre(AC, a, c);
Fp6Dbl::mulPre(BD, b, d); Fp6Dbl::mulPre(BD, b, d);
@ -1158,15 +1208,6 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
Fp6Dbl::sub(T, T, AC); Fp6Dbl::sub(T, T, AC);
Fp6Dbl::sub(T, T, BD); Fp6Dbl::sub(T, T, BD);
Fp6Dbl::mod(z.b, T); 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 x = a + bw, w^2 = v
@ -1182,7 +1223,7 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
mulVadd(t1, b, a); // bv + a mulVadd(t1, b, a); // bv + a
t0 *= t1; // (a + b)(bv + a) t0 *= t1; // (a + b)(bv + a)
Fp6::mul(t1, a, b); // ab 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 mulVadd(y.a, t1, t1); // abv + ab
Fp6::sub(y.a, t0, y.a); Fp6::sub(y.a, t0, y.a);
} }
@ -1194,16 +1235,18 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
{ {
const Fp6& a = x.a; const Fp6& a = x.a;
const Fp6& b = x.b; const Fp6& b = x.b;
Fp6 t0, t1; Fp6Dbl AA, BB;
Fp6::sqr(t0, a); Fp6Dbl::sqrPre(AA, a);
Fp6::sqr(t1, b); Fp6Dbl::sqrPre(BB, b);
Fp2::mul_xi(t1.c, t1.c); Fp2Dbl::mul_xi(BB.c, BB.c);
t0.a -= t1.c; Fp2Dbl::sub(AA.a, AA.a, BB.c);
t0.b -= t1.a; Fp2Dbl::sub(AA.b, AA.b, BB.a);
t0.c -= t1.b; // t0 = a^2 - b^2v Fp2Dbl::sub(AA.c, AA.c, BB.b); // a^2 - b^2 v
Fp6::inv(t0, t0); Fp6 t;
Fp6::mul(y.a, x.a, t0); Fp6Dbl::mod(t, AA);
Fp6::mul(y.b, x.b, t0); Fp6::inv(t, t);
Fp6::mul(y.a, x.a, t);
Fp6::mul(y.b, x.b, t);
Fp6::neg(y.b, y.b); Fp6::neg(y.b, y.b);
} }
/* /*
@ -1336,6 +1379,12 @@ struct GroupMtoA : public T {
{ {
T::mul(castT(z), castT(x), castT(y)); 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) static void dbl(GroupMtoA& y, const GroupMtoA& x)
{ {
T::sqr(castT(y), castT(x)); T::sqr(castT(y), castT(x));
@ -1363,6 +1412,10 @@ struct GroupMtoA : public T {
{ {
add(*this, *this, rhs); add(*this, *this, rhs);
} }
void operator-=(const GroupMtoA& rhs)
{
sub(*this, *this, rhs);
}
void normalize() {} void normalize() {}
private: private:
bool isOne() const; bool isOne() const;

@ -10,10 +10,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <cybozu/bit_operation.hpp>
#ifndef CYBOZU_DONT_USE_EXCEPTION #ifndef CYBOZU_DONT_USE_EXCEPTION
#include <cybozu/exception.hpp> #include <cybozu/exception.hpp>
#endif #endif
#include <mcl/randgen.hpp> #include <mcl/randgen.hpp>
#include <mcl/config.hpp>
#include <mcl/conversion.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4616) #pragma warning(disable : 4616)
@ -26,9 +30,6 @@
#if defined(__EMSCRIPTEN__) || defined(__wasm__) #if defined(__EMSCRIPTEN__) || defined(__wasm__)
#define MCL_USE_VINT #define MCL_USE_VINT
#endif #endif
#ifndef MCL_MAX_BIT_SIZE
#define MCL_MAX_BIT_SIZE 521
#endif
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
#include <mcl/vint.hpp> #include <mcl/vint.hpp>
typedef mcl::Vint mpz_class; typedef mcl::Vint mpz_class;
@ -40,27 +41,8 @@ typedef mcl::Vint mpz_class;
#endif #endif
#endif #endif
#ifndef MCL_SIZEOF_UNIT
#if defined(CYBOZU_OS_BIT) && (CYBOZU_OS_BIT == 32)
#define MCL_SIZEOF_UNIT 4
#else
#define MCL_SIZEOF_UNIT 8
#endif
#endif
namespace mcl { namespace mcl {
namespace fp {
#if MCL_SIZEOF_UNIT == 8
typedef uint64_t Unit;
#else
typedef uint32_t Unit;
#endif
#define MCL_UNIT_BIT_SIZE (MCL_SIZEOF_UNIT * 8)
} // mcl::fp
namespace gmp { namespace gmp {
typedef mpz_class ImplType; typedef mpz_class ImplType;
@ -81,24 +63,20 @@ void setArray(bool *pb, mpz_class& z, const T *buf, size_t n)
buf[0, size) = x buf[0, size) = x
buf[size, maxSize) with zero buf[size, maxSize) with zero
*/ */
template<class T, class U>
bool getArray_(T *buf, size_t maxSize, const U *x, int xn)//const mpz_srcptr x)
{
const size_t bufByteSize = sizeof(T) * maxSize;
if (xn < 0) return false;
size_t xByteSize = sizeof(*x) * xn;
if (xByteSize > bufByteSize) return false;
memcpy(buf, x, xByteSize);
memset((char*)buf + xByteSize, 0, bufByteSize - xByteSize);
return true;
}
template<class T> template<class T>
void getArray(bool *pb, T *buf, size_t maxSize, const mpz_class& x) void getArray(bool *pb, T *buf, size_t maxSize, const mpz_class& x)
{ {
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
*pb = getArray_(buf, maxSize, x.getUnit(), x.getUnitSize()); const fp::Unit *src = x.getUnit();
const size_t n = x.getUnitSize();
*pb = fp::convertArrayAsLE(buf, maxSize, src, n);
#else #else
*pb = getArray_(buf, maxSize, x.get_mpz_t()->_mp_d, x.get_mpz_t()->_mp_size); int n = x.get_mpz_t()->_mp_size;
if (n < 0) {
*pb = false;
return;
}
*pb = fp::convertArrayAsLE(buf, maxSize, x.get_mpz_t()->_mp_d, n);
#endif #endif
} }
inline void set(mpz_class& z, uint64_t x) inline void set(mpz_class& z, uint64_t x)
@ -434,6 +412,36 @@ inline size_t getUnitSize(const mpz_class& x)
return std::abs(x.get_mpz_t()->_mp_size); return std::abs(x.get_mpz_t()->_mp_size);
#endif #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) inline mpz_class abs(const mpz_class& x)
{ {
#ifdef MCL_USE_VINT #ifdef MCL_USE_VINT
@ -576,6 +584,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 #ifndef CYBOZU_DONT_USE_EXCEPTION
inline void setStr(mpz_class& z, const std::string& str, int base = 0) inline void setStr(mpz_class& z, const std::string& str, int base = 0)
{ {
@ -864,6 +919,86 @@ public:
#endif #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
{
if (shiftR_ == 0) return x[N_ - 1];
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 Barrett Reduction
for non GMP version for non GMP version

@ -77,12 +77,18 @@ int mclBn_init(int curve, int compiledTimeVar)
initG1only(&b, *para); initG1only(&b, *para);
return b ? 0 : -1; 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; bool b;
initPairing(&b, cp); initPairing(&b, *cp);
return b ? 0 : -1; return b ? 0 : -1;
} }
int mclBn_getCurveType()
{
return mcl::bn::BN::param.cp.curveType;
}
int mclBn_getOpUnitSize() int mclBn_getOpUnitSize()
{ {
return (int)Fp::getUnitSize() * sizeof(mcl::fp::Unit) / sizeof(uint64_t); 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); 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;
} }
//////////////////////////////////////////////// ////////////////////////////////////////////////
@ -141,13 +159,24 @@ int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, int ioMode)
} }
int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize) int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize)
{ {
cast(x)->setArrayMask((const char *)buf, bufSize); cast(x)->setArrayMask((const uint8_t *)buf, bufSize);
return 0; return 0;
} }
int mclBnFr_setBigEndianMod(mclBnFr *x, const void *buf, mclSize bufSize)
{
bool b;
cast(x)->setBigEndianMod(&b, (const uint8_t*)buf, bufSize);
return b ? 0 : -1;
}
mclSize mclBnFr_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFr *x)
{
return cast(x)->getLittleEndian((uint8_t*)buf, maxBufSize);
}
int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize) int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize)
{ {
bool b; bool b;
cast(x)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod); cast(x)->setArrayMod(&b, (const uint8_t *)buf, bufSize);
return b ? 0 : -1; return b ? 0 : -1;
} }
mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize bufSize) mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize bufSize)
@ -171,6 +200,14 @@ int mclBnFr_isOne(const mclBnFr *x)
{ {
return cast(x)->isOne(); 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 #ifndef MCL_DONT_USE_CSRPNG
int mclBnFr_setByCSPRNG(mclBnFr *x) int mclBnFr_setByCSPRNG(mclBnFr *x)
@ -179,6 +216,12 @@ int mclBnFr_setByCSPRNG(mclBnFr *x)
cast(x)->setByCSPRNG(&b); cast(x)->setByCSPRNG(&b);
return b ? 0 : -1; 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)) void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize))
{ {
mcl::fp::RandGen::setRandFunc(self, readFunc); 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)); 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 // set zero
void mclBnG1_clear(mclBnG1 *x) void mclBnG1_clear(mclBnG1 *x)
@ -443,6 +557,10 @@ void mclBnGT_neg(mclBnGT *y, const mclBnGT *x)
Fp12::neg(*cast(y), *cast(x)); Fp12::neg(*cast(y), *cast(x));
} }
void mclBnGT_inv(mclBnGT *y, const mclBnGT *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)); 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)); 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) void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y)
{ {
pairing(*cast(z), *cast(x), *cast(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)); 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) int mclBn_getUint64NumToPrecompute(void)
{ {
return int(BN::param.precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t)); return int(BN::param.precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t));
@ -560,6 +695,15 @@ void mclBn_verifyOrderG2(int doVerify)
verifyOrderG2(doVerify != 0); 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) mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode)
{ {
return cast(x)->getStr(buf, maxBufSize, ioMode); return cast(x)->getStr(buf, maxBufSize, ioMode);
@ -585,20 +729,52 @@ void mclBnFp_clear(mclBnFp *x)
int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize) int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize)
{ {
cast(x)->setArrayMask((const char *)buf, bufSize); cast(x)->setArrayMask((const uint8_t *)buf, bufSize);
return 0; return 0;
} }
int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize) int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize)
{ {
bool b; bool b;
cast(x)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod); cast(x)->setLittleEndianMod(&b, (const uint8_t*)buf, bufSize);
return b ? 0 : -1; return b ? 0 : -1;
} }
int mclBnFp_setBigEndianMod(mclBnFp *x, const void *buf, mclSize bufSize)
{
bool b;
cast(x)->setBigEndianMod(&b, (const uint8_t*)buf, bufSize);
return b ? 0 : -1;
}
mclSize mclBnFp_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFp *x)
{
return cast(x)->getLittleEndian((uint8_t*)buf, maxBufSize);
}
int mclBnFp_isValid(const mclBnFp *x)
{
return cast(x)->isValid();
}
int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y) int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y)
{ {
return *cast(x) == *cast(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) 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); 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) 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_XBYAK
#define MCL_DONT_USE_OPENSSL #define MCL_DONT_USE_OPENSSL
#endif #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 #define MCL_USE_XBYAK
#endif
#if defined(MCL_USE_XBYAK) || defined(MCL_STATIC_CODE)
#define MCL_X64_ASM
#define MCL_XBYAK_DIRECT_CALL #define MCL_XBYAK_DIRECT_CALL
#endif #endif
@ -23,7 +26,7 @@
namespace mcl { namespace mcl {
static const int version = 0x094; /* 0xABC = A.BC */ static const int version = 0x151; /* 0xABC = A.BC */
/* /*
specifies available string format mode for X::setIoMode() specifies available string format mode for X::setIoMode()
@ -101,16 +104,29 @@ enum IoMode {
IoSerialize = 512, // use MBS for 1-bit y IoSerialize = 512, // use MBS for 1-bit y
IoFixedSizeByteSeq = IoSerialize, // obsolete IoFixedSizeByteSeq = IoSerialize, // obsolete
IoEcProj = 1024, // projective or jacobi coordinate IoEcProj = 1024, // projective or jacobi coordinate
IoSerializeHexStr = 2048 // printable hex string IoSerializeHexStr = 2048, // printable hex string
IoEcAffineSerialize = 4096 // serialize [x:y]
}; };
namespace fp { namespace fp {
inline bool isIoSerializeMode(int ioMode)
{
return ioMode & (IoArray | IoArrayRaw | IoSerialize | IoEcAffineSerialize | IoSerializeHexStr);
}
const size_t UnitBitSize = sizeof(Unit) * 8; const size_t UnitBitSize = sizeof(Unit) * 8;
const size_t maxUnitSize = (MCL_MAX_BIT_SIZE + UnitBitSize - 1) / UnitBitSize; 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) #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 FpGenerator;
struct Op; struct Op;
@ -157,13 +173,6 @@ enum PrimeMode {
PM_NIST_P521 PM_NIST_P521
}; };
enum MaskMode {
NoMask = 0, // throw if greater or equal
SmallMask = 1, // 1-bit smaller mask if greater or equal
MaskAndMod = 2, // mask and substract if greater or equal
Mod = 3 // mod p
};
struct Op { struct Op {
/* /*
don't change the layout of rp and p don't change the layout of rp and p
@ -175,6 +184,7 @@ struct Op {
uint32_t pmod4; uint32_t pmod4;
mcl::SquareRoot sq; mcl::SquareRoot sq;
mcl::Modp modp; mcl::Modp modp;
mcl::SmallModp smallModp;
Unit half[maxUnitSize]; // (p + 1) / 2 Unit half[maxUnitSize]; // (p + 1) / 2
Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery) Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery)
/* /*
@ -189,6 +199,8 @@ struct Op {
Unit R3[maxUnitSize]; Unit R3[maxUnitSize];
#ifdef MCL_USE_XBYAK #ifdef MCL_USE_XBYAK
FpGenerator *fg; FpGenerator *fg;
#endif
#ifdef MCL_X64_ASM
mcl::Array<Unit> invTbl; mcl::Array<Unit> invTbl;
#endif #endif
void3u fp_addA_; void3u fp_addA_;
@ -196,18 +208,20 @@ struct Op {
void2u fp_negA_; void2u fp_negA_;
void3u fp_mulA_; void3u fp_mulA_;
void2u fp_sqrA_; void2u fp_sqrA_;
void2u fp_mul2A_;
void2u fp_mul9A_;
void3u fp2_addA_; void3u fp2_addA_;
void3u fp2_subA_; void3u fp2_subA_;
void2u fp2_negA_; void2u fp2_negA_;
void3u fp2_mulA_; void3u fp2_mulA_;
void2u fp2_sqrA_; void2u fp2_sqrA_;
void2u fp2_mul2A_;
void3u fpDbl_addA_; void3u fpDbl_addA_;
void3u fpDbl_subA_; void3u fpDbl_subA_;
void3u fpDbl_mulPreA_;
void2u fpDbl_sqrPreA_;
void2u fpDbl_modA_; void2u fpDbl_modA_;
void3u fp2Dbl_mulPreA_; void3u fp2Dbl_mulPreA_;
void2u fp2Dbl_sqrPreA_; void2u fp2Dbl_sqrPreA_;
void2u fp2Dbl_mul_xiA_;
size_t maxN; size_t maxN;
size_t N; size_t N;
size_t bitSize; size_t bitSize;
@ -220,6 +234,7 @@ struct Op {
void4u fp_sub; void4u fp_sub;
void4u fp_mul; void4u fp_mul;
void3u fp_sqr; void3u fp_sqr;
void3u fp_mul2;
void2uOp fp_invOp; void2uOp fp_invOp;
void2uIu fp_mulUnit; // fpN1_mod + fp_mulUnitPre void2uIu fp_mulUnit; // fpN1_mod + fp_mulUnitPre
@ -243,7 +258,6 @@ struct Op {
*/ */
int xi_a; // xi = xi_a + u int xi_a; // xi = xi_a + u
void4u fp2_mulNF; void4u fp2_mulNF;
void2u fp2_inv;
void2u fp2_mul_xiA_; void2u fp2_mul_xiA_;
uint32_t (*hash)(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); uint32_t (*hash)(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);
@ -275,7 +289,7 @@ struct Op {
memset(one, 0, sizeof(one)); memset(one, 0, sizeof(one));
memset(R2, 0, sizeof(R2)); memset(R2, 0, sizeof(R2));
memset(R3, 0, sizeof(R3)); memset(R3, 0, sizeof(R3));
#ifdef MCL_USE_XBYAK #ifdef MCL_X64_ASM
invTbl.clear(); invTbl.clear();
#endif #endif
fp_addA_ = 0; fp_addA_ = 0;
@ -283,18 +297,20 @@ struct Op {
fp_negA_ = 0; fp_negA_ = 0;
fp_mulA_ = 0; fp_mulA_ = 0;
fp_sqrA_ = 0; fp_sqrA_ = 0;
fp_mul2A_ = 0;
fp_mul9A_ = 0;
fp2_addA_ = 0; fp2_addA_ = 0;
fp2_subA_ = 0; fp2_subA_ = 0;
fp2_negA_ = 0; fp2_negA_ = 0;
fp2_mulA_ = 0; fp2_mulA_ = 0;
fp2_sqrA_ = 0; fp2_sqrA_ = 0;
fp2_mul2A_ = 0;
fpDbl_addA_ = 0; fpDbl_addA_ = 0;
fpDbl_subA_ = 0; fpDbl_subA_ = 0;
fpDbl_mulPreA_ = 0;
fpDbl_sqrPreA_ = 0;
fpDbl_modA_ = 0; fpDbl_modA_ = 0;
fp2Dbl_mulPreA_ = 0; fp2Dbl_mulPreA_ = 0;
fp2Dbl_sqrPreA_ = 0; fp2Dbl_sqrPreA_ = 0;
fp2Dbl_mul_xiA_ = 0;
maxN = 0; maxN = 0;
N = 0; N = 0;
bitSize = 0; bitSize = 0;
@ -307,6 +323,7 @@ struct Op {
fp_sub = 0; fp_sub = 0;
fp_mul = 0; fp_mul = 0;
fp_sqr = 0; fp_sqr = 0;
fp_mul2 = 0;
fp_invOp = 0; fp_invOp = 0;
fp_mulUnit = 0; fp_mulUnit = 0;
@ -327,7 +344,6 @@ struct Op {
xi_a = 0; xi_a = 0;
fp2_mulNF = 0; fp2_mulNF = 0;
fp2_inv = 0;
fp2_mul_xiA_ = 0; fp2_mul_xiA_ = 0;
hash = 0; hash = 0;
@ -363,13 +379,14 @@ private:
inline const char* getIoSeparator(int ioMode) 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++) { for (size_t i = 0; i < n; i++) {
printf("%02x ", (uint8_t)s[i]); printf("%02x ", s[i]);
} }
printf("\n"); printf("\n");
} }

@ -84,12 +84,39 @@ struct Operator : public E {
{ {
powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, true); 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; 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: private:
static void (*powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime); 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) static void powArray(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)
{ {
if (powArrayGLV && (constTime || yn > 1)) { if (powArrayGLV && (constTime || yn > 1)) {
@ -117,6 +144,9 @@ private:
template<class T, class E> 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); 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 T must have save and load
*/ */
@ -154,6 +184,20 @@ struct Serializable : public E {
getStr(str, ioMode); getStr(str, ioMode);
return str; 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 #endif
// return written bytes // return written bytes
size_t serialize(void *buf, size_t maxBufSize, int ioMode = IoSerialize) const size_t serialize(void *buf, size_t maxBufSize, int ioMode = IoSerialize) const

@ -74,6 +74,18 @@ typedef struct {
typedef struct { typedef struct {
mclBnFr d[7]; mclBnFr d[7];
} sheZkpBinEq; } sheZkpBinEq;
typedef struct {
mclBnFr d[2];
} sheZkpDec;
typedef struct {
mclBnGT d[4];
} sheAuxiliaryForZkpDecGT;
typedef struct {
mclBnFr d[4];
} sheZkpDecGT;
/* /*
initialize this library initialize this library
call this once before using the other functions 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 sheZkpBinSerialize(void *buf, mclSize maxBufSize, const sheZkpBin *zkp);
MCLSHE_DLL_API mclSize sheZkpEqSerialize(void *buf, mclSize maxBufSize, const sheZkpEq *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 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 // return read byte size if sucess else 0
MCLSHE_DLL_API mclSize sheSecretKeyDeserialize(sheSecretKey* sec, const void *buf, mclSize bufSize); 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 sheZkpBinDeserialize(sheZkpBin* zkp, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpEqDeserialize(sheZkpEq* 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 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 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 sheGetPublicKey(shePublicKey *pub, const sheSecretKey *sec);
MCLSHE_DLL_API void sheGetAuxiliaryForZkpDecGT(sheAuxiliaryForZkpDecGT *aux, const shePublicKey *pub);
/* /*
make table to decode DLP make table to decode DLP
return 0 if success 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 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); 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 decode c and set m
return 0 if success 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 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 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 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 decode c via GT and set m
return 0 if success return 0 if success

@ -26,6 +26,8 @@
#include <mcl/window_method.hpp> #include <mcl/window_method.hpp>
#include <cybozu/endian.hpp> #include <cybozu/endian.hpp>
#include <cybozu/serializer.hpp> #include <cybozu/serializer.hpp>
#include <cybozu/sha2.hpp>
#include <mcl/ecparam.hpp>
namespace mcl { namespace she { namespace mcl { namespace she {
@ -324,6 +326,26 @@ int log(const G& P, const G& xP)
throw cybozu::Exception("she:log:not found"); 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 } // mcl::she::local
template<size_t dummyInpl = 0> template<size_t dummyInpl = 0>
@ -366,11 +388,17 @@ private:
public: public:
const G& getS() const { return S_; } const G& getS() const { return S_; }
const G& getT() const { return T_; } const G& getT() const { return T_; }
G& getNonConstRefS() { return S_; }
G& getNonConstRefT() { return T_; }
void clear() void clear()
{ {
S_.clear(); S_.clear();
T_.clear(); T_.clear();
} }
bool isValid() const
{
return S_.isValid() && T_.isValid();
}
static void add(CipherTextAT& z, const CipherTextAT& x, const CipherTextAT& y) static void add(CipherTextAT& z, const CipherTextAT& x, const CipherTextAT& y)
{ {
/* /*
@ -537,6 +565,8 @@ private:
struct ZkpBinTag; struct ZkpBinTag;
struct ZkpEqTag; // d_[] = { c, sp, ss, sm } struct ZkpEqTag; // d_[] = { c, sp, ss, sm }
struct ZkpBinEqTag; // d_[] = { d0, d1, sp0, sp1, ss, sp, sm } struct ZkpBinEqTag; // d_[] = { d0, d1, sp0, sp1, ss, sp, sm }
struct ZkpDecTag; // d_[] = { c, h }
struct ZkpDecGTTag; // d_[] = { d1, d2, d3, h }
public: public:
/* /*
Zkp for m = 0 or 1 Zkp for m = 0 or 1
@ -550,9 +580,66 @@ public:
Zkp for (m = 0 or 1) and decG1(c1) == decG2(c2) Zkp for (m = 0 or 1) and decG1(c1) == decG2(c2)
*/ */
typedef ZkpT<ZkpBinEqTag, 7> ZkpBinEq; 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<G1> CipherTextG1;
typedef CipherTextAT<G2> CipherTextG2; 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) 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) static void initG1only(const mcl::EcParam& para, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
{ {
Fp::init(para.p); mcl::initCurve<G1, Fr>(para.curveType, &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);
setRangeForG1DLP(hashSize); setRangeForG1DLP(hashSize);
useDecG1ViaGT_ = false; useDecG1ViaGT_ = false;
useDecG2ViaGT_ = false; useDecG2ViaGT_ = false;
@ -774,6 +855,88 @@ public:
return isZero(c.a_); 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> template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize) void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{ {
@ -886,16 +1049,10 @@ private:
r.setRand(); r.setRand();
Pmul.mul(static_cast<I&>(R[0][m]), r); // R[0][m] = r P 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 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; 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]; d[m] = c - d[1-m];
s[m] = r + d[m] * encRand; s[m] = r + d[m] * encRand;
} }
@ -925,16 +1082,10 @@ private:
G::sub(T2, S, P); G::sub(T2, S, P);
G::mul(T2, T2, d[1]); G::mul(T2, T2, d[1]);
G::sub(R[1][1], T1, T2); 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; 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]; return c == d[0] + d[1];
} }
/* /*
@ -956,21 +1107,13 @@ private:
G2 R3, R4; G2 R3, R4;
ElGamalEnc(R1, R2, rm, Pmul, xPmul, &rp); ElGamalEnc(R1, R2, rm, Pmul, xPmul, &rp);
ElGamalEnc(R3, R4, rm, Qmul, yQmul, &rs); 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& c = zkp.d_[0];
Fr& sp = zkp.d_[1]; Fr& sp = zkp.d_[1];
Fr& ss = zkp.d_[2]; Fr& ss = zkp.d_[2];
Fr& sm = zkp.d_[3]; 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); Fr::mul(sp, c, p);
sp += rp; sp += rp;
Fr::mul(ss, c, s); Fr::mul(ss, c, s);
@ -997,18 +1140,10 @@ private:
R3 -= X2; R3 -= X2;
G2::mul(X2, T2, c); G2::mul(X2, T2, c);
R4 -= X2; 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; 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; return c == c2;
} }
/* /*
@ -1052,20 +1187,10 @@ private:
G2 R5, R6; G2 R5, R6;
ElGamalEnc(R4, R3, rm, Pmul, xPmul, &rp); ElGamalEnc(R4, R3, rm, Pmul, xPmul, &rp);
ElGamalEnc(R6, R5, rm, Qmul, yQmul, &rs); 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; 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::sub(d[m], c, d[1-m]);
Fr::mul(spm[m], d[m], p); Fr::mul(spm[m], d[m], p);
spm[m] += rpm; spm[m] += rpm;
@ -1112,20 +1237,10 @@ private:
R5 -= X2; R5 -= X2;
G2::mul(X2, S2, c); G2::mul(X2, S2, c);
R6 -= X2; 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; 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; return c == c2;
} }
/* /*
@ -1266,6 +1381,13 @@ public:
ElGamalEnc(c.S_, c.T_, m, QhashTbl_.getWM(), yQmul); ElGamalEnc(c.S_, c.T_, m, QhashTbl_.getWM(), yQmul);
} }
public: 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 void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, int m) const
{ {
Fr encRand; Fr encRand;
@ -1287,6 +1409,33 @@ public:
const MulG<G1> xPmul(xP_); const MulG<G1> xPmul(xP_);
return verifyZkpBin(c.S_, c.T_, P_, zkp, PhashTbl_.getWM(), xPmul); 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 bool verify(const CipherTextG2& c, const ZkpBin& zkp) const
{ {
const MulG<G2> yQmul(yQ_); const MulG<G2> yQmul(yQ_);
@ -1599,6 +1748,7 @@ public:
friend class PublicKey; friend class PublicKey;
friend class PrecomputedPublicKey; friend class PrecomputedPublicKey;
friend class CipherTextA; friend class CipherTextA;
friend struct AuxiliaryForZkpDecGT;
template<class T> template<class T>
friend struct PublicKeyMethod; friend struct PublicKeyMethod;
public: public:
@ -1809,7 +1959,14 @@ public:
template<class InputStream> template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize) 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()) { if (isMultiplied()) {
m_.load(pb, is, ioMode); m_.load(pb, is, ioMode);
} else { } else {
@ -1819,14 +1976,7 @@ public:
template<class OutputStream> template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{ {
char c; cybozu::writeChar(pb, os, isMultiplied_ ? '0' : '1'); if (!*pb) return;
if (!cybozu::readChar(&c, os)) return;
if (c == '0' || c == '1') {
isMultiplied_ = c == '0';
} else {
*pb = false;
return;
}
if (isMultiplied()) { if (isMultiplied()) {
m_.save(pb, os, ioMode); m_.save(pb, os, ioMode);
} else { } else {
@ -1895,6 +2045,9 @@ typedef SHE::CipherText CipherText;
typedef SHE::ZkpBin ZkpBin; typedef SHE::ZkpBin ZkpBin;
typedef SHE::ZkpEq ZkpEq; typedef SHE::ZkpEq ZkpEq;
typedef SHE::ZkpBinEq ZkpBinEq; 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) inline void init(const mcl::CurveParam& cp = mcl::BN254, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
{ {

@ -17,8 +17,21 @@
namespace mcl { namespace fp { namespace mcl { namespace fp {
// some environments do not have utility // some environments do not have utility
template<class T> inline uint32_t abs_(int32_t x)
T abs_(T x) { return x < 0 ? -x : x; } {
if (x >= 0) return uint32_t(x);
// avoid undefined behavior
if (x == -2147483647 - 1) return 2147483648u;
return uint32_t(-x);
}
inline uint64_t abs_(int64_t x)
{
if (x >= 0) return uint64_t(x);
// avoid undefined behavior
if (x == -9223372036854775807ll - 1) return 9223372036854775808ull;
return uint64_t(-x);
}
template<class T> template<class T>
T min_(T x, T y) { return x < y ? x : y; } T min_(T x, T y) { return x < y ? x : y; }
@ -157,7 +170,6 @@ void maskArray(T *x, size_t n, size_t bitSize)
template<class T> template<class T>
size_t getNonZeroArraySize(const T *x, size_t n) size_t getNonZeroArraySize(const T *x, size_t n)
{ {
assert(n > 0);
while (n > 0) { while (n > 0) {
if (x[n - 1]) return n; if (x[n - 1]) return n;
n--; n--;
@ -165,6 +177,62 @@ size_t getNonZeroArraySize(const T *x, size_t n)
return 1; 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 out [inout] : set element of G ; out = x^y[]
@param x [in] @param x [in]
@ -231,7 +299,7 @@ void powGeneric(G& out, const G& x, const T *y, size_t n, const Mul& mul, const
out = x; out = x;
} }
for (int i = (int)n - 1; i >= 0; i--) { 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) { for (int j = m - 2; j >= 0; j -= 2) {
sqr(out, out); sqr(out, out);
sqr(out, out); sqr(out, out);
@ -272,6 +340,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 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 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 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: default:
return false; return false;
} }

@ -11,6 +11,7 @@
#ifndef CYBOZU_DONT_USE_STRING #ifndef CYBOZU_DONT_USE_STRING
#include <iostream> #include <iostream>
#endif #endif
#include <mcl/config.hpp>
#include <mcl/array.hpp> #include <mcl/array.hpp>
#include <mcl/util.hpp> #include <mcl/util.hpp>
#include <mcl/randgen.hpp> #include <mcl/randgen.hpp>
@ -24,23 +25,11 @@
#error "define MCL_MAX_BIT_SZIE" #error "define MCL_MAX_BIT_SZIE"
#endif #endif
#ifndef MCL_SIZEOF_UNIT
#if defined(CYBOZU_OS_BIT) && (CYBOZU_OS_BIT == 32)
#define MCL_SIZEOF_UNIT 4
#else
#define MCL_SIZEOF_UNIT 8
#endif
#endif
namespace mcl { namespace mcl {
namespace vint { namespace vint {
#if MCL_SIZEOF_UNIT == 8 typedef fp::Unit Unit;
typedef uint64_t Unit;
#else
typedef uint32_t Unit;
#endif
template<size_t x> template<size_t x>
struct RoundUp { struct RoundUp {
@ -90,35 +79,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) inline uint64_t mulUnit(uint64_t *pH, uint64_t x, uint64_t y)
{ {
#ifdef MCL_VINT_64BIT_PORTABLE #ifdef MCL_VINT_64BIT_PORTABLE
uint32_t a = uint32_t(x >> 32); const uint64_t mask = 0xffffffff;
uint32_t b = uint32_t(x); uint64_t v = (x & mask) * (y & mask);
uint32_t c = uint32_t(y >> 32); uint64_t L = uint32_t(v);
uint32_t d = uint32_t(y); uint64_t H = v >> 32;
uint64_t ad = (x & mask) * uint32_t(y >> 32);
uint64_t ad = uint64_t(d) * a; uint64_t bc = uint32_t(x >> 32) * (y & mask);
uint64_t bd = uint64_t(d) * b; H += uint32_t(ad);
uint64_t L = uint32_t(bd); H += uint32_t(bc);
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
*/
L |= H << 32; 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; *pH = H;
return L; return L;
#elif defined(_WIN64) && !defined(__INTEL_COMPILER) #elif defined(_WIN64) && !defined(__INTEL_COMPILER)
@ -142,6 +115,7 @@ void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn);
*/ */
inline uint32_t divUnit(uint32_t *pr, uint32_t H, uint32_t L, uint32_t y) inline uint32_t divUnit(uint32_t *pr, uint32_t H, uint32_t L, uint32_t y)
{ {
assert(y != 0);
uint64_t t = make64(H, L); uint64_t t = make64(H, L);
uint32_t q = uint32_t(t / y); uint32_t q = uint32_t(t / y);
*pr = uint32_t(t % y); *pr = uint32_t(t % y);
@ -150,7 +124,8 @@ inline uint32_t divUnit(uint32_t *pr, uint32_t H, uint32_t L, uint32_t y)
#if MCL_SIZEOF_UNIT == 8 #if MCL_SIZEOF_UNIT == 8
inline uint64_t divUnit(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y) inline uint64_t divUnit(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y)
{ {
#if defined(MCL_VINT_64BIT_PORTABLE) assert(y != 0);
#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 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) }; uint32_t py[2] = { uint32_t(y), uint32_t(y >> 32) };
size_t xn = 4; size_t xn = 4;
@ -162,7 +137,7 @@ inline uint64_t divUnit(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y)
*pr = make64(r[1], r[0]); *pr = make64(r[1], r[0]);
return make64(q[1], q[0]); return make64(q[1], q[0]);
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
#error "divUnit for uint64_t is not supported" return _udiv128(H, L, y, pr);
#else #else
typedef __attribute__((mode(TI))) unsigned int uint128; typedef __attribute__((mode(TI))) unsigned int uint128;
uint128 t = (uint128(H) << 64) | L; uint128 t = (uint128(H) << 64) | L;
@ -213,14 +188,11 @@ T addN(T *z, const T *x, const T *y, size_t n)
T c = 0; T c = 0;
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
T xc = x[i] + c; T xc = x[i] + c;
if (xc < c) { c = xc < c;
// x[i] = Unit(-1) and c = 1 T yi = y[i];
z[i] = y[i]; xc += yi;
} else { c += xc < yi;
xc += y[i]; z[i] = xc;
c = y[i] > xc ? 1 : 0;
z[i] = xc;
}
} }
return c; return c;
} }
@ -301,14 +273,12 @@ T subN(T *z, const T *x, const T *y, size_t n)
assert(n > 0); assert(n > 0);
T c = 0; T c = 0;
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
T yc = y[i] + c; T yi = y[i];
if (yc < c) { yi += c;
// y[i] = T(-1) and c = 1 c = yi < c;
z[i] = x[i]; T xi = x[i];
} else { c += xi < yi;
c = x[i] < yc ? 1 : 0; z[i] = xi - yi;
z[i] = x[i] - yc;
}
} }
return c; return c;
} }
@ -552,15 +522,6 @@ size_t getRealSize(const T *x, size_t xn)
return 1; 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 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 r[rn] = x[xn] % y[yn] ; rn = yn before getRealSize
@ -1204,7 +1165,7 @@ public:
} }
/* /*
set positive value set positive value
@note assume little endian system @note x is treated as a little endian
*/ */
template<class S> template<class S>
void setArray(bool *pb, const S *x, size_t size) void setArray(bool *pb, const S *x, size_t size)
@ -1218,15 +1179,9 @@ public:
size_t unitSize = (sizeof(S) * size + sizeof(Unit) - 1) / sizeof(Unit); size_t unitSize = (sizeof(S) * size + sizeof(Unit) - 1) / sizeof(Unit);
buf_.alloc(pb, unitSize); buf_.alloc(pb, unitSize);
if (!*pb) return; if (!*pb) return;
char *dst = (char *)&buf_[0]; bool b = fp::convertArrayAsLE(&buf_[0], unitSize, x, size);
const char *src = (const char *)x; assert(b);
size_t i = 0; (void)b;
for (; i < sizeof(S) * size; i++) {
dst[i] = src[i];
}
for (; i < sizeof(Unit) * unitSize; i++) {
dst[i] = 0;
}
trim(unitSize); trim(unitSize);
} }
/* /*
@ -1510,9 +1465,10 @@ public:
*/ */
static void divMod(VintT *q, VintT& r, const VintT& x, const VintT& y) static void divMod(VintT *q, VintT& r, const VintT& x, const VintT& y)
{ {
bool qsign = x.isNeg_ ^ y.isNeg_; bool xNeg = x.isNeg_;
bool qsign = xNeg ^ y.isNeg_;
udiv(q, r, x.buf_, x.size(), y.buf_, y.size()); udiv(q, r, x.buf_, x.size(), y.buf_, y.size());
r.isNeg_ = x.isNeg_; r.isNeg_ = xNeg;
if (q) q->isNeg_ = qsign; if (q) q->isNeg_ = qsign;
} }
static void div(VintT& q, const VintT& x, const VintT& y) static void div(VintT& q, const VintT& x, const VintT& y)
@ -1563,10 +1519,12 @@ public:
*/ */
static void quotRem(VintT *q, VintT& r, const VintT& x, const VintT& y) static void quotRem(VintT *q, VintT& r, const VintT& x, const VintT& y)
{ {
assert(q != &r);
VintT yy = y; VintT yy = y;
bool qsign = x.isNeg_ ^ y.isNeg_; bool yNeg = y.isNeg_;
bool qsign = x.isNeg_ ^ yNeg;
udiv(q, r, x.buf_, x.size(), y.buf_, y.size()); udiv(q, r, x.buf_, x.size(), y.buf_, y.size());
r.isNeg_ = y.isNeg_; r.isNeg_ = yNeg;
if (q) q->isNeg_ = qsign; if (q) q->isNeg_ = qsign;
if (!r.isZero() && qsign) { if (!r.isZero() && qsign) {
if (q) { if (q) {
@ -1755,6 +1713,46 @@ public:
static void invMod(VintT& y, const VintT& x, const VintT& m) static void invMod(VintT& y, const VintT& x, const VintT& m)
{ {
assert(!x.isZero() && !m.isZero()); 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) { if (x == 1) {
y = 1; y = 1;
return; return;
@ -1787,6 +1785,7 @@ public:
} }
b -= a * q; b -= a * q;
} }
#endif
} }
/* /*
Miller-Rabin Miller-Rabin

@ -23,35 +23,33 @@ struct ArrayIterator {
, bitSize(bitSize) , bitSize(bitSize)
, w(w) , w(w)
, pos(0) , pos(0)
, mask((w == TbitSize ? 0 : (T(1) << w)) - 1) , mask(makeMask(w))
{ {
assert(w <= TbitSize); assert(w <= TbitSize);
} }
T makeMask(size_t w) const
{
return (w == TbitSize) ? ~T(0) : (T(1) << w) - 1;
}
bool hasNext() const { return bitSize > 0; } bool hasNext() const { return bitSize > 0; }
T getNext() T getNext()
{ {
if (w == TbitSize) { if (bitSize < w) {
bitSize -= w; w = bitSize;
return *x++; mask = makeMask(w);
} }
if (pos + w < TbitSize) { if (pos + w <= TbitSize) {
T v = (*x >> pos) & mask; T v = x[0] >> pos;
pos += w; if (pos + w < TbitSize) {
if (bitSize < w) { pos += w;
bitSize = 0; v &= mask;
} else { } else {
bitSize -= w; pos = 0;
x++;
} }
bitSize -= w;
return v; 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)); T v = (x[0] >> pos) | (x[1] << (TbitSize - pos));
v &= mask; v &= mask;
pos = (pos + w) - TbitSize; 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) * `CT she.sub(CT x, CT y)`(JS)
* 暗号文xから暗号文yを引いてzにセットする(またはその値を返す) * 暗号文xから暗号文yを引いてzにセットする(またはその値を返す)
* `void CT::neg(CT& y, const CT& x)`(C++) * `void CT::neg(CT& y, const CT& x)`(C++)
* `void she.neg(CT x)`(JS) * `CT she.neg(CT x)`(JS)
* 暗号文xの符号反転をyにセットする(またはその値を返す) * 暗号文xの符号反転をyにセットする(またはその値を返す)
* `void CT::mul(CT& z, const CT& x, int y)`(C++) * `void CT::mul(CT& z, const CT& x, int y)`(C++)
* `CT she.mulInt(CT x, int y)`(JS) * `CT she.mulInt(CT x, int y)`(JS)
@ -275,7 +275,9 @@ PrecomputedPublicKeyはPublicKeyの高速版
* ZkpBinEq 暗号文encG1(m1), encG2(m2)についてm1 = m2 = 0または1であることを検証できる * ZkpBinEq 暗号文encG1(m1), encG2(m2)についてm1 = m2 = 0または1であることを検証できる
### API ### 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(CipherTextG1& c, Zkp& zkp, int m) const`(C++)
* `void PK::encWithZkpBin(CipherTextG2& 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) * `[CipherTextG1, CipherTextG2, ZkpEqBin] PK::encWithZkpBinEq(m)`(JS)
* m(=0 or 1)を暗号化して暗号文c1, c2とゼロ知識証明zkpをセットする(または[c1, c2, zkp]を返す) * m(=0 or 1)を暗号化して暗号文c1, c2とゼロ知識証明zkpをセットする(または[c1, c2, zkp]を返す)
* mが0でも1でもなければ例外 * 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 # she ; Two-level homomorphic encryption library for browser/Node.js by WebAssembly
# Abstruct # Abstract
she is a somewhat(two-level) homomorphic encryption library, she is a somewhat(two-level) homomorphic encryption library,
which is based on pairings. which is based on pairings.
This library supports polynomially many homomorphic additions and 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 * decrypt a ciphertext with a secret key
## Homomorphic operations ## 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 * homomprphic multiplication over ciphertext of CipherTextG1 and CipherTextG2
* The class of the result is CipherTextGT. * 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. * 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. * 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. * 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 ## Zero-knowledge proof class
* A zero-knowledge proof is simultaneously created when encrypting a plaintext `m`. * A zero-knowledge proof is simultaneously created when encrypting a plaintext `m`.
@ -66,7 +66,7 @@ and read `she.js`.
## A sample for JS ## A sample for JS
``` ```js
// initialize a library // initialize a library
she.init().then(() => { she.init().then(() => {
const sec = new she.SecretKey() const sec = new she.SecretKey()
@ -103,7 +103,7 @@ she.init().then(() => {
# A sample for C++ # A sample for C++
How to build the library, see [mcl](https://github.com/herumi/mcl/#installation-requirements). How to build the library, see [mcl](https://github.com/herumi/mcl/#installation-requirements).
``` ```c++
#include <mcl/she.hpp> #include <mcl/she.hpp>
int main() int main()
try try
@ -255,7 +255,7 @@ PK means PublicKey or PrecomputedPublicKey
* `CT she.sub(CT x, CT y)`(JS) * `CT she.sub(CT x, CT y)`(JS)
* subtract `x` and `y` and set the value to `z`(or return the value) * subtract `x` and `y` and set the value to `z`(or return the value)
* `void CT::neg(CT& y, const CT& x)`(C++) * `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) * negate `x` and set the value to `y`(or return the value)
* `void CT::mul(CT& z, const CT& x, int y)`(C++) * `void CT::mul(CT& z, const CT& x, int y)`(C++)
* `CT she.mulInt(CT x, int y)`(JS) * `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)` * ZkpBinEq ; verify whether `m1 = m2 = 0` or `1` for ciphertexts `encG1(m1)` and `encG2(m2)`
### API ### 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(CipherTextG1& c, Zkp& zkp, int m) const`(C++)
* `void PK::encWithZkpBin(CipherTextG2& 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) * `[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]) * 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 * 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 ## 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 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 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 echo cl /c %CFLAGS% src\fp.cpp /Foobj\fp.obj
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 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" ( if "%1"=="dll" (
echo cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj 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 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 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 echo cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj /DMCLBN_NO_AUTOLINK cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
echo link /nologo /DLL /OUT:bin\mclbn384.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.lib 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.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.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_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\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 /DMCLBN_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 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 link /nologo /DLL /OUT:bin\mclshe384_256.dll obj\she_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c384_256.lib
) else ( ) else (
@ -38,7 +37,7 @@ if "%1"=="dll" (
cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj 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 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 echo cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
lib /nologo /OUT:lib\mclbn384.lib /nodefaultlib obj\bn_c384.obj lib\mcl.lib lib /nologo /OUT:lib\mclbn384_256.lib /nodefaultlib obj\bn_c384_256.obj lib\mcl.lib
) )

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

Loading…
Cancel
Save