diff options
author | MITSUNARI Shigeo <herumi@nifty.com> | 2018-05-03 05:42:16 +0800 |
---|---|---|
committer | MITSUNARI Shigeo <herumi@nifty.com> | 2018-05-03 05:42:16 +0800 |
commit | 1189ddf898f069d9f892abca7b47d2839064b5eb (patch) | |
tree | ae4da501fecee957e4661cee11d20acf9368d04b | |
parent | 443edad6e697c3d7a409b974c77f5e27194ad1e5 (diff) | |
parent | 37a8efcc83c1187be1a3ad74fbb0c7c7f2d7c6e3 (diff) | |
download | tangerine-mcl-1189ddf898f069d9f892abca7b47d2839064b5eb.tar.gz tangerine-mcl-1189ddf898f069d9f892abca7b47d2839064b5eb.tar.zst tangerine-mcl-1189ddf898f069d9f892abca7b47d2839064b5eb.zip |
Merge branch 'master' into zkp
41 files changed, 2459 insertions, 2087 deletions
@@ -4,7 +4,7 @@ OBJ_DIR=obj EXE_DIR=bin SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c512.cpp she_c256.cpp TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp -TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c512_test.cpp she_c256_test.cpp +TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c512_test.cpp she_c256_test.cpp she_c384_test.cpp TEST_SRC+=aggregate_sig_test.cpp TEST_SRC+=bls12_test.cpp ifeq ($(CPU),x86-64) @@ -41,7 +41,8 @@ BN384_SLIB=$(LIB_DIR)/lib$(BN384_SNAME).$(LIB_SUF) BN512_LIB=$(LIB_DIR)/libmclbn512.a BN512_SLIB=$(LIB_DIR)/lib$(BN512_SNAME).$(LIB_SUF) SHE256_LIB=$(LIB_DIR)/libmclshe256.a -all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE256_LIB) +SHE384_LIB=$(LIB_DIR)/libmclshe384.a +all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE256_LIB) $(SHE384_lib) #LLVM_VER=-3.8 LLVM_LLC=llc$(LLVM_VER) @@ -68,6 +69,7 @@ BN256_OBJ=$(OBJ_DIR)/bn_c256.o BN384_OBJ=$(OBJ_DIR)/bn_c384.o BN512_OBJ=$(OBJ_DIR)/bn_c512.o SHE256_OBJ=$(OBJ_DIR)/she_c256.o +SHE384_OBJ=$(OBJ_DIR)/she_c384.o FUNC_LIST=src/func.list MCL_USE_LLVM?=1 ifeq ($(MCL_USE_LLVM),1) @@ -115,6 +117,9 @@ $(BN256_LIB): $(BN256_OBJ) $(SHE256_LIB): $(SHE256_OBJ) $(AR) $@ $(SHE256_OBJ) +$(SHE384_LIB): $(SHE384_OBJ) + $(AR) $@ $(SHE384_OBJ) + ifeq ($(OS),mac) MAC_LDFLAGS+=-l$(MCL_SNAME) -L./lib endif @@ -214,6 +219,9 @@ $(EXE_DIR)/pairing_c.exe: $(OBJ_DIR)/pairing_c.o $(BN256_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) +$(EXE_DIR)/she_c384_test.exe: $(OBJ_DIR)/she_c384_test.o $(SHE384_LIB) $(MCL_LIB) + $(PRE)$(CXX) $< -o $@ $(SHE384_LIB) $(MCL_LIB) $(LDFLAGS) + SAMPLE_EXE=$(addprefix $(EXE_DIR)/,$(addsuffix .exe,$(basename $(SAMPLE_SRC)))) sample: $(SAMPLE_EXE) $(MCL_LIB) @@ -233,6 +241,7 @@ ifeq ($(MCL_USE_LLVM),2) endif ../she-wasm/she_c.js: $(JS_DEP) Makefile emcc -o $@ src/fp.cpp src/she_c256.cpp $(EMCC_OPT) -s TOTAL_MEMORY=67108864 +# emcc -o $@ src/fp.cpp src/she_c384.cpp $(EMCC_OPT) -s TOTAL_MEMORY=67108864 ../mcl-wasm/mcl_c.js: src/fp.cpp src/bn_c256.cpp include/mcl/bn.h Makefile emcc -o $@ src/fp.cpp src/bn_c256.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=256 diff --git a/ffi/go/mcl/mcl.go b/ffi/go/mcl/mcl.go index 8a030fc..bce2d56 100644 --- a/ffi/go/mcl/mcl.go +++ b/ffi/go/mcl/mcl.go @@ -18,6 +18,9 @@ const CurveFp382_1 = C.mclBn_CurveFp382_1 // CurveFp382_2 -- 382 bit curve 2 const CurveFp382_2 = C.mclBn_CurveFp382_2 +// BLS12_381 +const BLS12_381 = C.MCL_BLS12_381 + // Init -- // call this function before calling all the other operations // this function is not thread safe @@ -102,7 +105,7 @@ func (x *Fr) SetString(s string, base int) error { func (x *Fr) Deserialize(buf []byte) error { // #nosec err := C.mclBnFr_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) - if err != 0 { + if err == 0 { return fmt.Errorf("err mclBnFr_deserialize %x", buf) } return nil @@ -231,7 +234,7 @@ func (x *G1) SetString(s string, base int) error { func (x *G1) Deserialize(buf []byte) error { // #nosec err := C.mclBnG1_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) - if err != 0 { + if err == 0 { return fmt.Errorf("err mclBnG1_deserialize %x", buf) } return nil @@ -341,7 +344,7 @@ func (x *G2) SetString(s string, base int) error { func (x *G2) Deserialize(buf []byte) error { // #nosec err := C.mclBnG2_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) - if err != 0 { + if err == 0 { return fmt.Errorf("err mclBnG2_deserialize %x", buf) } return nil @@ -452,7 +455,7 @@ func (x *GT) SetString(s string, base int) error { func (x *GT) Deserialize(buf []byte) error { // #nosec err := C.mclBnGT_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) - if err != 0 { + if err == 0 { return fmt.Errorf("err mclBnGT_deserialize %x", buf) } return nil diff --git a/ffi/go/mcl/mcl_test.go b/ffi/go/mcl/mcl_test.go index b1e0aba..85900be 100644 --- a/ffi/go/mcl/mcl_test.go +++ b/ffi/go/mcl/mcl_test.go @@ -124,7 +124,7 @@ func TestMclMain(t *testing.T) { if GetMaxOpUnitSize() == 6 { t.Log("CurveFp382_1") testMcl(t, CurveFp382_1) - t.Log("CurveFp382_2") - testMcl(t, CurveFp382_2) + t.Log("BLS12_381") + testMcl(t, BLS12_381) } } diff --git a/include/mcl/aggregate_sig.hpp b/include/mcl/aggregate_sig.hpp index 249bf67..f314057 100644 --- a/include/mcl/aggregate_sig.hpp +++ b/include/mcl/aggregate_sig.hpp @@ -17,17 +17,17 @@ #if MCLBN_FP_UNIT_SIZE == 4 #include <mcl/bn256.hpp> namespace mcl { -namespace bn_current = mcl::bn256; +using namespace mcl::bn256; } #elif MCLBN_FP_UNIT_SIZE == 6 #include <mcl/bn384.hpp> namespace mcl { -namespace bn_current = mcl::bn384; +using namespace mcl::bn384; } #elif MCLBN_FP_UNIT_SIZE == 8 #include <mcl/bn512.hpp> namespace mcl { -namespace bn_current = mcl::bn512; +using namespace mcl::bn512; } #else #error "MCLBN_FP_UNIT_SIZE must be 4, 6, or 8" @@ -38,12 +38,9 @@ namespace mcl { namespace aggs { /* AGGregate Signature Template class */ -template<class BN, class Fr> +template<size_t dummyImpl = 0> struct AGGST { - typedef typename BN::G1 G1; typedef typename G1::BaseFp Fp; - typedef typename BN::G2 G2; - typedef typename BN::Fp12 GT; class SecretKey; class PublicKey; @@ -51,14 +48,14 @@ struct AGGST { static G1 P_; static G2 Q_; - static std::vector<bn_current::Fp6> Qcoeff_; + static std::vector<Fp6> Qcoeff_; public: - static void init(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp254BNb) + static void init(const mcl::CurveParam& cp = mcl::BN254) { - bn_current::initPairing(cp); - BN::hashAndMapToG1(P_, "0"); - BN::hashAndMapToG2(Q_, "0"); - BN::precomputeG2(Qcoeff_, Q_); + initPairing(cp); + hashAndMapToG1(P_, "0"); + hashAndMapToG2(Q_, "0"); + precomputeG2(Qcoeff_, Q_); } class Signature : public fp::Serializable<Signature> { G1 S_; @@ -121,22 +118,22 @@ public: h.setHashOf(msgVec[i], sizeVec[i]); std::pair<typename FpSet::iterator, bool> ret = msgSet.insert(h); if (!ret.second) throw cybozu::Exception("aggs::verify:same msg"); - BN::mapToG1(hv[i], h); + mapToG1(hv[i], h); } /* e(aggSig, xQ) = prod_i e(hv[i], pub[i].Q) <=> finalExp(e(-aggSig, xQ) * prod_i millerLoop(hv[i], pub[i].xQ)) == 1 */ GT e1, e2; - BN::precomputedMillerLoop(e1, -S_, Qcoeff_); - BN::millerLoop(e2, hv[0], pubVec[0].xQ_); + precomputedMillerLoop(e1, -S_, Qcoeff_); + millerLoop(e2, hv[0], pubVec[0].xQ_); for (size_t i = 1; i < n; i++) { GT e; - BN::millerLoop(e, hv[i], pubVec[i].xQ_); + millerLoop(e, hv[i], pubVec[i].xQ_); e2 *= e; } e1 *= e2; - BN::finalExp(e1, e1); + finalExp(e1, e1); return e1.isOne(); } bool verify(const std::vector<std::string>& msgVec, const std::vector<PublicKey>& pubVec) const @@ -192,13 +189,13 @@ public: <=> finalExp(millerLoop(S, Q)e(-H, x)) = 1 */ G1 H; - BN::hashAndMapToG1(H, m, mSize); + hashAndMapToG1(H, m, mSize); G1::neg(H, H); GT e1, e2; - BN::precomputedMillerLoop(e1, sig.S_, Qcoeff_); - BN::millerLoop(e2, H, xQ_); + precomputedMillerLoop(e1, sig.S_, Qcoeff_); + millerLoop(e2, H, xQ_); e1 *= e2; - BN::finalExp(e1, e1); + finalExp(e1, e1); return e1.isOne(); } bool verify(const Signature& sig, const std::string& m) const @@ -246,7 +243,7 @@ public: } void sign(Signature& sig, const void *m, size_t mSize) const { - BN::hashAndMapToG1(sig.S_, m, mSize); + hashAndMapToG1(sig.S_, m, mSize); G1::mul(sig.S_, sig.S_, x_); } void sign(Signature& sig, const std::string& m) const @@ -256,11 +253,11 @@ public: }; }; -template<class BN, class Fr> typename BN::G1 AGGST<BN, Fr>::P_; -template<class BN, class Fr> typename BN::G2 AGGST<BN, Fr>::Q_; -template<class BN, class Fr> std::vector<bn_current::Fp6> AGGST<BN, Fr>::Qcoeff_; +template<size_t dummyImpl> G1 AGGST<dummyImpl>::P_; +template<size_t dummyImpl> G2 AGGST<dummyImpl>::Q_; +template<size_t dummyImpl> std::vector<Fp6> AGGST<dummyImpl>::Qcoeff_; -typedef AGGST<bn_current::BN, bn_current::Fr> AGGS; +typedef AGGST<> AGGS; typedef AGGS::SecretKey SecretKey; typedef AGGS::PublicKey PublicKey; typedef AGGS::Signature Signature; diff --git a/include/mcl/bls12.hpp b/include/mcl/bls12.hpp deleted file mode 100644 index f97c2f7..0000000 --- a/include/mcl/bls12.hpp +++ /dev/null @@ -1,171 +0,0 @@ -#pragma once -/** - @file - @brief BLS12-381 curve - @author MITSUNARI Shigeo(@herumi) - @license modified new BSD license - http://opensource.org/licenses/BSD-3-Clause -*/ -#include <mcl/pairing_util.hpp> - -namespace mcl { namespace bls12 { - -using mcl::CurveParam; -using mcl::getCurveParam; - -template<class Fp> -struct MapToT { - typedef mcl::Fp2T<Fp> Fp2; - typedef mcl::EcT<Fp> G1; - typedef mcl::EcT<Fp2> G2; - typedef util::HaveFrobenius<G2> G2withF; - mpz_class z_; - mpz_class cofactor1_; - /* - #(Fp) / r = (z + 1 - t) / r = (z - 1)^2 / 3 - */ - void mulByCofactor(G1& Q, const G1& P) const - { - assert(cofactor1_ != 0); - G1::mulGeneric(Q, P, cofactor1_); - } - /* - Efficient hash maps to G2 on BLS curves - Alessandro Budroni, Federico Pintore - Q = (z(z-1)-1)P + Frob((z-1)P) + Frob^2(2P) - */ - void mulByCofactor(G2& Q, const G2& P) const - { - G2 T0, T1; - G2::mulGeneric(T0, P, z_ - 1); - G2::mulGeneric(T1, T0, z_); - T1 -= P; - G2withF::Frobenius(T0, T0); - T0 += T1; - G2::dbl(T1, P); - G2withF::Frobenius2(T1, T1); - G2::add(Q, T0, T1); - } - void init(const mpz_class& z) - { - z_ = z; - cofactor1_ = (z - 1) * (z - 1) / 3; - } - template<class G, class F> - void calc(G& P, const F& t) const - { - F x = t; - for (;;) { - F y; - G::getWeierstrass(y, x); - if (F::squareRoot(y, y)) { - P.set(x, y, false); - return; - } - *x.getFp0() += Fp::one(); - } - } - void calcG1(G1& P, const Fp& t) const - { - calc<G1, Fp>(P, t); - mulByCofactor(P, P); - } - /* - get the element in G2 by multiplying the cofactor - */ - void calcG2(G2& P, const Fp2& t) const - { - calc<G2, Fp2>(P, t); - mulByCofactor(P, P); - } -}; - -template<class Fp> -struct ParamT : public util::CommonParamT<Fp> { - typedef util::CommonParamT<Fp> Common; - typedef Fp2T<Fp> Fp2; - typedef mcl::EcT<Fp> G1; - typedef mcl::EcT<Fp2> G2; - MapToT<Fp> mapTo; - - void init(const CurveParam& cp = CurveFp381, fp::Mode mode = fp::FP_AUTO) - { - Common::initCommonParam(cp, mode); - mapTo.init(this->z); - } -}; - -template<class Fp> -struct BLS12T : mcl::util::BasePairingT<BLS12T<Fp>, Fp, ParamT<Fp> > { - typedef ParamT<Fp> Param; - typedef typename mcl::util::BasePairingT<BLS12T<Fp>, Fp, Param> Base; - typedef mcl::Fp2T<Fp> Fp2; - typedef mcl::Fp6T<Fp> Fp6; - typedef mcl::Fp12T<Fp> Fp12; - typedef mcl::EcT<Fp> G1; - typedef mcl::EcT<Fp2> G2; - typedef util::HaveFrobenius<G2> G2withF; - typedef mcl::FpDblT<Fp> FpDbl; - typedef mcl::Fp2DblT<Fp> Fp2Dbl; - static void init(const mcl::bls12::CurveParam& cp = CurveFp381, fp::Mode mode = fp::FP_AUTO) - { - Base::param.init(cp, mode); - G2withF::init(cp.isMtype); - } - /* - Implementing Pairings at the 192-bit Security Level - D.F.Aranha, L.F.Castaneda, E.Knapp, A.Menezes, F.R.Henriquez - Section 4 - */ - static void expHardPart(Fp12& y, const Fp12& x) - { -#if 0 - const mpz_class& p = param.p; - mpz_class p2 = p * p; - mpz_class p4 = p2 * p2; - Fp12::pow(y, x, (p4 - p2 + 1) / param.r * 3); - return; -#endif -#if 1 - Fp12 a0, a1, a2, a3, a4, a5, a6, a7; - Fp12::unitaryInv(a0, x); // a0 = x^-1 - Base::fasterSqr(a1, a0); // x^-2 - Base::pow_z(a2, x); // x^z - Base::fasterSqr(a3, a2); // x^2z - a1 *= a2; // a1 = x^(z-2) - Base::pow_z(a7, a1); // a7 = x^(z^2-2z) - Base::pow_z(a4, a7); // a4 = x^(z^3-2z^2) - Base::pow_z(a5, a4); // a5 = x^(z^4-2z^3) - a3 *= a5; // a3 = x^(z^4-2z^3+2z) - Base::pow_z(a6, a3); // a6 = x^(z^5-2z^4+2z^2) - - Fp12::unitaryInv(a1, a1); // x^(2-z) - a1 *= a6; // x^(z^5-2z^4+2z^2-z+2) - a1 *= x; // x^(z^5-2z^4+2z^2-z+3) = x^c0 - a3 *= a0; // x^(z^4-2z^3-1) = x^c1 - Fp12::Frobenius(a3, a3); // x^(c1 p) - a1 *= a3; // x^(c0 + c1 p) - a4 *= a2; // x^(z^3-2z^2+z) = x^c2 - Fp12::Frobenius2(a4, a4); // x^(c2 p^2) - a1 *= a4; // x^(c0 + c1 p + c2 p^2) - a7 *= x; // x^(z^2-2z+1) = x^c3 - Fp12::Frobenius3(y, a7); - y *= a1; -#else - Fp12 t1, t2, t3; - Fp12::Frobenius(t1, x); - Fp12::Frobenius(t2, t1); - Fp12::Frobenius(t3, t2); - Fp12::pow(t1, t1, param.exp_c1); - Fp12::pow(t2, t2, param.exp_c2); - Fp12::pow(t3, t3, param.exp_c3); - Fp12::pow(y, x, param.exp_c0); - y *= t1; - y *= t2; - y *= t3; -#endif - } -}; - -} } // mcl::bls12 - diff --git a/include/mcl/bls12_381.hpp b/include/mcl/bls12_381.hpp deleted file mode 100644 index e5e4906..0000000 --- a/include/mcl/bls12_381.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -/** - @file - @brief preset class for 381-bit optimal ate pairing over BLS12 curves - @author MITSUNARI Shigeo(@herumi) - @license modified new BSD license - http://opensource.org/licenses/BSD-3-Clause -*/ -#include <mcl/bls12.hpp> - -namespace mcl { namespace bls12_381 { - -namespace local { -struct FpTag; -struct FrTag; -} - -typedef mcl::FpT<local::FpTag, 384> Fp; -typedef mcl::bls12::BLS12T<Fp> BLS12; -typedef BLS12::Fp2 Fp2; -typedef BLS12::Fp6 Fp6; -typedef BLS12::Fp12 Fp12; -typedef BLS12::G1 G1; -typedef BLS12::G2 G2; -typedef BLS12::Fp12 GT; - -/* the order of G1 is r */ -typedef mcl::FpT<local::FrTag, 256> Fr; - -static inline void initPairing(const mcl::bls12::CurveParam& cp = mcl::bls12::CurveFp381, fp::Mode mode = fp::FP_AUTO) -{ - BLS12::init(cp, mode); - G1::setCompressedExpression(); - G2::setCompressedExpression(); - Fr::init(BLS12::param.r); -} - -} } // mcl::bls12_381 - diff --git a/include/mcl/bn.h b/include/mcl/bn.h index c064a01..43df24c 100644 --- a/include/mcl/bn.h +++ b/include/mcl/bn.h @@ -85,8 +85,8 @@ typedef struct { */ MCLBN_DLL_API int mclBn_setErrFile(const char *name); -#ifndef MCL_CURVE_TYPE_DEFINED -#define MCL_CURVE_TYPE_DEFINED +#include <mcl/curve_type.h> +// for backword compatibility enum { mclBn_CurveFp254BNb = 0, mclBn_CurveFp382_1 = 1, @@ -95,17 +95,16 @@ enum { mclBn_CurveSNARK1 = 4, mclBls12_CurveFp381 = 5 }; -#endif /* init library @param curve [in] type of bn curve @param maxUnitSize [in] MCLBN_FP_UNIT_SIZE - curve = MCLBN_CurveFp254BNb is allowed if maxUnitSize = 4 - curve = MCLBN_CurveFp254BNb/MCLBN_CurveFp382_1/MCLBN_CurveFp382_2 are allowed if maxUnitSize = 6 + curve = BN254/BN_SNARK1 is allowed if maxUnitSize = 4 + curve = BN381_1/BN381_2/BLS12_381 are allowed if maxUnitSize = 6 This parameter is used to detect a library compiled with different MCLBN_FP_UNIT_SIZE for safety. @note not threadsafe - @note MCLBN_init is used in libeay32 + @note BN_init is used in libeay32 */ MCLBN_DLL_API int mclBn_init(int curve, int maxUnitSize); @@ -116,25 +115,28 @@ MCLBN_DLL_API int mclBn_init(int curve, int maxUnitSize); G1 is a curve defined on Fp serialized size of elements - |Fr| = |G1| = 32 bytes (if CurveFp254BNb), 48 bytes (if CurevFp382_{1,2}), 58 bytes (if CurveFp462) + |Fr| |Fp| + BN254 32 32 + BN381 48 48 + BLS12_381 32 48 + BN462 58 58 + |G1| = |Fp| |G2| = |G1| * 2 |GT| = |G1| * 12 */ /* return the num of Unit(=uint64_t) to store Fr - 4 if curve is mclBn_CurveFp254BNb - 6 if curve is mclBn_CurveFp382_{1,2} - 8 if curve is mclBn_CurveFp462 */ MCLBN_DLL_API int mclBn_getOpUnitSize(); /* - return bytes for serialized G1 - 32 if mclBn_CurveFp254BNb - 48 if mclBn_CurveFp382_{1,2} - 58 if mclBn_CurveFpA462 + return bytes for serialized G1(=Fp) */ MCLBN_DLL_API int mclBn_getG1ByteSize(); +/* + return bytes for serialized Fr +*/ +MCLBN_DLL_API int mclBn_getFrByteSize(); /* return decimal string of the order of the curve(=the characteristic of Fr) @@ -327,6 +329,13 @@ MCLBN_DLL_API int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, MCLBN_DLL_API int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, mclSize cSize, const mclBnFr *x); MCLBN_DLL_API int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, mclSize cSize, const mclBnFr *x); +/* + verify whether a point of an elliptic curve has order r + This api affetcs setStr(), deserialize() for G2 on BN or G1/G2 on BLS12 + @param doVerify [in] does not verify if zero(default 1) +*/ +MCLBN_DLL_API void mclBn_verifyOrderG1(int doVerify); +MCLBN_DLL_API void mclBn_verifyOrderG2(int doVerify); #ifdef __cplusplus } diff --git a/include/mcl/bn.hpp b/include/mcl/bn.hpp index a1b4878..0bea577 100644 --- a/include/mcl/bn.hpp +++ b/include/mcl/bn.hpp @@ -1,28 +1,319 @@ #pragma once /** @file - @brief optimal ate pairing over BN-curve + @brief optimal ate pairing over BN-curve / BLS12-curve @author MITSUNARI Shigeo(@herumi) @license modified new BSD license http://opensource.org/licenses/BSD-3-Clause */ -#include <mcl/pairing_util.hpp> +#include <mcl/fp_tower.hpp> +#include <mcl/ec.hpp> +#include <mcl/curve_type.h> +#include <assert.h> -namespace mcl { namespace bn { +/* + set bit size of Fp and Fr +*/ +#ifndef MCL_MAX_FP_BIT_SIZE + #define MCL_MAX_FP_BIT_SIZE 256 +#endif -using mcl::CurveParam; -using mcl::getCurveParam; - -template<class Fp> -struct MapToT { - typedef mcl::Fp2T<Fp> Fp2; - typedef mcl::EcT<Fp> G1; - typedef mcl::EcT<Fp2> G2; - typedef util::HaveFrobenius<G2> G2withF; +#ifndef MCL_MAX_FR_BIT_SIZE + #define MCL_MAX_FR_BIT_SIZE MCL_MAX_FP_BIT_SIZE +#endif +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 std::string(z) == rhs.z && 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 }; + +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; + default: + throw cybozu::Exception("getCurveParam:bad type") << type; + } +} + +namespace bn { + +namespace local { +struct FpTag; +struct FrTag; +} + +typedef mcl::FpT<local::FpTag, MCL_MAX_FP_BIT_SIZE> Fp; +typedef mcl::FpT<local::FrTag, MCL_MAX_FR_BIT_SIZE> Fr; +typedef mcl::Fp2T<Fp> Fp2; +typedef mcl::Fp6T<Fp> Fp6; +typedef mcl::Fp12T<Fp> Fp12; +typedef mcl::EcT<Fp> G1; +typedef mcl::EcT<Fp2> G2; +typedef Fp12 GT; + +typedef mcl::FpDblT<Fp> FpDbl; +typedef mcl::Fp2DblT<Fp> Fp2Dbl; + +inline void Frobenius(Fp2& y, const Fp2& x) +{ + Fp2::Frobenius(y, x); +} +inline void Frobenius(Fp12& y, const Fp12& x) +{ + Fp12::Frobenius(y, x); +} +/* + twisted Frobenius for G2 +*/ +void Frobenius(G2& D, const G2& S); +void Frobenius2(G2& D, const G2& S); +void Frobenius3(G2& D, const G2& S); + +namespace local { + +typedef std::vector<int8_t> SignVec; + +inline size_t getPrecomputeQcoeffSize(const SignVec& sv) +{ + size_t idx = 2 + 2; + for (size_t i = 2; i < sv.size(); i++) { + idx++; + if (sv[i]) idx++; + } + return idx; +} + +template<class X, class C, size_t N> +X evalPoly(const X& x, const C (&c)[N]) +{ + X ret = c[N - 1]; + for (size_t i = 1; i < N; i++) { + ret *= x; + ret += c[N - 1 - i]; + } + return ret; +} + +enum TwistBtype { + tb_generic, + tb_1m1i, // 1 - 1i + tb_1m2i // 1 - 2i +}; + +/* + l = (a, b, c) => (a, b * P.y, c * P.x) +*/ +inline void updateLine(Fp6& l, const G1& P) +{ + l.b.a *= P.y; + l.b.b *= P.y; + l.c.a *= P.x; + l.c.b *= P.x; +} + +struct Compress { + Fp12& z_; + Fp2& g1_; + Fp2& g2_; + Fp2& g3_; + Fp2& g4_; + Fp2& g5_; + // z is output area + Compress(Fp12& z, const Fp12& x) + : z_(z) + , g1_(z.getFp2()[4]) + , g2_(z.getFp2()[3]) + , g3_(z.getFp2()[2]) + , g4_(z.getFp2()[1]) + , g5_(z.getFp2()[5]) + { + g2_ = x.getFp2()[3]; + g3_ = x.getFp2()[2]; + g4_ = x.getFp2()[1]; + g5_ = x.getFp2()[5]; + } + Compress(Fp12& z, const Compress& c) + : z_(z) + , g1_(z.getFp2()[4]) + , g2_(z.getFp2()[3]) + , g3_(z.getFp2()[2]) + , g4_(z.getFp2()[1]) + , g5_(z.getFp2()[5]) + { + g2_ = c.g2_; + g3_ = c.g3_; + g4_ = c.g4_; + g5_ = c.g5_; + } + void decompressBeforeInv(Fp2& nume, Fp2& denomi) const + { + assert(&nume != &denomi); + + if (g2_.isZero()) { + Fp2::add(nume, g4_, g4_); + nume *= g5_; + denomi = g3_; + } else { + Fp2 t; + Fp2::sqr(nume, g5_); + Fp2::mul_xi(denomi, nume); + Fp2::sqr(nume, g4_); + Fp2::sub(t, nume, g3_); + t += t; + t += nume; + Fp2::add(nume, denomi, t); + Fp2::divBy4(nume, nume); + denomi = g2_; + } + } + + // output to z + void decompressAfterInv() + { + Fp2& g0 = z_.getFp2()[0]; + Fp2 t0, t1; + // Compute g0. + Fp2::sqr(t0, g1_); + Fp2::mul(t1, g3_, g4_); + t0 -= t1; + t0 += t0; + t0 -= t1; + Fp2::mul(t1, g2_, g5_); + t0 += t1; + Fp2::mul_xi(g0, t0); + g0.a += Fp::one(); + } + +public: + void decompress() // for test + { + Fp2 nume, denomi; + decompressBeforeInv(nume, denomi); + Fp2::inv(denomi, denomi); + g1_ = nume * denomi; // g1 is recoverd. + decompressAfterInv(); + } + /* + 2275clk * 186 = 423Kclk QQQ + */ + static void squareC(Compress& z) + { + Fp2 t0, t1, t2; + Fp2Dbl T0, T1, T2, T3; + Fp2Dbl::sqrPre(T0, z.g4_); + Fp2Dbl::sqrPre(T1, z.g5_); + Fp2Dbl::mul_xi(T2, T1); + T2 += T0; + Fp2Dbl::mod(t2, T2); + Fp2::add(t0, z.g4_, z.g5_); + Fp2Dbl::sqrPre(T2, t0); + T0 += T1; + T2 -= T0; + Fp2Dbl::mod(t0, T2); + Fp2::add(t1, z.g2_, z.g3_); + Fp2Dbl::sqrPre(T3, t1); + Fp2Dbl::sqrPre(T2, z.g2_); + Fp2::mul_xi(t1, t0); + z.g2_ += t1; + z.g2_ += z.g2_; + z.g2_ += t1; + Fp2::sub(t1, t2, z.g3_); + t1 += t1; + Fp2Dbl::sqrPre(T1, z.g3_); + Fp2::add(z.g3_, t1, t2); + Fp2Dbl::mul_xi(T0, T1); + T0 += T2; + Fp2Dbl::mod(t0, T0); + Fp2::sub(z.g4_, t0, z.g4_); + z.g4_ += z.g4_; + z.g4_ += t0; + Fp2Dbl::addPre(T2, T2, T1); + T3 -= T2; + Fp2Dbl::mod(t0, T3); + z.g5_ += t0; + z.g5_ += z.g5_; + z.g5_ += t0; + } + static void square_n(Compress& z, int n) + { + for (int i = 0; i < n; i++) { + squareC(z); + } + } + /* + Exponentiation over compression for: + z = x^Param::z.abs() + */ + static void fixed_power(Fp12& z, const Fp12& x) + { + if (x.isOne()) { + z = 1; + return; + } + Fp12 x_org = x; + Fp12 d62; + Fp2 c55nume, c55denomi, c62nume, c62denomi; + Compress c55(z, x); + square_n(c55, 55); + c55.decompressBeforeInv(c55nume, c55denomi); + Compress c62(d62, c55); + square_n(c62, 62 - 55); + c62.decompressBeforeInv(c62nume, c62denomi); + Fp2 acc; + Fp2::mul(acc, c55denomi, c62denomi); + Fp2::inv(acc, acc); + Fp2 t; + Fp2::mul(t, acc, c62denomi); + Fp2::mul(c55.g1_, c55nume, t); + c55.decompressAfterInv(); + Fp2::mul(t, acc, c55denomi); + Fp2::mul(c62.g1_, c62nume, t); + c62.decompressAfterInv(); + z *= x_org; + z *= d62; + } +}; + +struct MapTo { Fp c1_; // sqrt(-3) Fp c2_; // (-1 + sqrt(-3)) / 2 - mpz_class cofactor_; mpz_class z_; + mpz_class cofactor_; + bool isBN_; int legendre(const Fp& x) const { return gmp::legendre(x.getMpz(), Fp::getOp().mp); @@ -51,7 +342,7 @@ struct MapToT { Remark: throw exception if t = 0, c1, -c1 and b = 2 */ template<class G, class F> - void calc(G& P, const F& t) const + void calcBN(G& P, const F& t) const { F x, y, w; bool negative = legendre(t) < 0; @@ -77,7 +368,7 @@ struct MapToT { } } ERR_POINT: - throw cybozu::Exception("MapToT:calc:bad") << t; + throw cybozu::Exception("MapTo:calcBN:bad") << t; } /* Faster Hashing to G2 @@ -87,7 +378,7 @@ struct MapToT { Q = zP + Frob(3zP) + Frob^2(zP) + Frob^3(P) = -(18x^3 + 12x^2 + 3x + 1)cofactor_ P */ - void mulByCofactor(G2& Q, const G2& P) const + void mulByCofactorBN(G2& Q, const G2& P) const { #if 0 G2::mulGeneric(Q, P, cofactor_); @@ -103,28 +394,86 @@ struct MapToT { G2::mulGeneric(T0, P, z_); G2::dbl(T1, T0); T1 += T0; // 3zP - G2withF::Frobenius(T1, T1); - G2withF::Frobenius2(T2, T0); + Frobenius(T1, T1); + Frobenius2(T2, T0); T0 += T1; T0 += T2; - G2withF::Frobenius3(T2, P); + Frobenius3(T2, P); G2::add(Q, T0, T2); #endif #endif } + template<class G, class F> + void naiveMapTo(G& P, const F& t) const + { + F x = t; + for (;;) { + F y; + G::getWeierstrass(y, x); + if (F::squareRoot(y, y)) { + P.set(x, y, false); + return; + } + *x.getFp0() += Fp::one(); + } + } + /* + #(Fp) / r = (z + 1 - t) / r = (z - 1)^2 / 3 + */ + void mulByCofactorBLS12(G1& Q, const G1& P) const + { + G1::mulGeneric(Q, P, cofactor_); + } + /* + Efficient hash maps to G2 on BLS curves + Alessandro Budroni, Federico Pintore + Q = (z(z-1)-1)P + Frob((z-1)P) + Frob^2(2P) + */ + void mulByCofactorBLS12(G2& Q, const G2& P) const + { + G2 T0, T1; + G2::mulGeneric(T0, P, z_ - 1); + G2::mulGeneric(T1, T0, z_); + T1 -= P; + Frobenius(T0, T0); + T0 += T1; + G2::dbl(T1, P); + Frobenius2(T1, T1); + G2::add(Q, T0, T1); + } /* - cofactor_ is for G2 + cofactor_ is for G2(not used now) */ - void init(const mpz_class& cofactor, const mpz_class &z) + void initBN(const mpz_class& cofactor, const mpz_class &z) { - if (!Fp::squareRoot(c1_, -3)) throw cybozu::Exception("MapToT:init:c1_"); + if (!Fp::squareRoot(c1_, -3)) throw cybozu::Exception("MapTo:init:c1_"); c2_ = (c1_ - 1) / 2; + z_ = z; cofactor_ = cofactor; + } + void initBLS12(const mpz_class& z) + { z_ = z; + // cofactor for G1 + cofactor_ = (z - 1) * (z - 1) / 3; + } + void init(const mpz_class& cofactor, const mpz_class &z, bool isBN) + { + isBN_ = isBN; + if (isBN_) { + initBN(cofactor, z); + } else { + initBLS12(z); + } } void calcG1(G1& P, const Fp& t) const { - calc<G1, Fp>(P, t); + if (isBN_) { + calcBN<G1, Fp>(P, t); + } else { + naiveMapTo<G1, Fp>(P, t); + mulByCofactorBLS12(P, P); + } assert(P.isValid()); } /* @@ -132,42 +481,64 @@ struct MapToT { */ void calcG2(G2& P, const Fp2& t) const { - calc<G2, Fp2>(P, t); - assert(cofactor_ != 0); - mulByCofactor(P, P); - assert(!P.isZero()); + if (isBN_) { + calcBN<G2, Fp2>(P, t); + mulByCofactorBN(P, P); + } else { + naiveMapTo<G2, Fp2>(P, t); + mulByCofactorBLS12(P, P); + } + assert(P.isValid()); } }; /* Software implementation of Attribute-Based Encryption: Appendixes - GLV for G1 + GLV for G1 on BN/BLS12 */ -template<class Fp> struct GLV1 { - typedef mcl::EcT<Fp> G1; Fp rw; // rw = 1 / w = (-1 - sqrt(-3)) / 2 - size_t m; + size_t rBitSize; mpz_class v0, v1; mpz_class B[2][2]; mpz_class r; - void init(const mpz_class& r, const mpz_class& z) + void init(const mpz_class& r, const mpz_class& z, bool isBLS12 = false) { if (!Fp::squareRoot(rw, -3)) throw cybozu::Exception("GLV1:init"); rw = -(rw + 1) / 2; this->r = r; - m = gmp::getBitSize(r); - m = (m + fp::UnitBitSize - 1) & ~(fp::UnitBitSize - 1);// a little better size - v0 = ((6 * z * z + 4 * z + 1) << m) / r; - v1 = ((-2 * z - 1) << m) / r; - B[0][0] = 6 * z * z + 2 * z; - B[0][1] = -2 * z - 1; - B[1][0] = -2 * z - 1; - B[1][1] = -6 * z * z - 4 * z - 1; + rBitSize = gmp::getBitSize(r); + rBitSize = (rBitSize + fp::UnitBitSize - 1) & ~(fp::UnitBitSize - 1);// a little better size + if (isBLS12) { + /* + BLS12 + L = z^4 + (-z^2+1) + L = 0 + 1 + z^2 L = 0 + */ + B[0][0] = -z * z + 1; + B[0][1] = 1; + B[1][0] = 1; + B[1][1] = z * z; + } else { + /* + BN + L = 36z^4 - 1 + (6z^2+2z) - (2z+1) L = 0 + (-2z-1) - (6z^2+4z+1)L = 0 + */ + B[0][0] = 6 * z * z + 2 * z; + B[0][1] = -2 * z - 1; + B[1][0] = -2 * z - 1; + B[1][1] = -6 * z * z - 4 * z - 1; + } + // [v0 v1] = [r 0] * B^(-1) + v0 = ((-B[1][1]) << rBitSize) / r; + v1 = ((B[1][0]) << rBitSize) / r; } /* - lambda = 36z^4 - 1 - lambda (x, y) = (rw x, y) + L = lambda = p^4 + L (x, y) = (rw x, y) */ void mulLambda(G1& Q, const G1& P) const { @@ -176,14 +547,13 @@ struct GLV1 { Q.z = P.z; } /* - lambda = 36 z^4 - 1 x = a + b * lambda mod r */ void split(mpz_class& a, mpz_class& b, const mpz_class& x) const { mpz_class t; - t = (x * v0) >> m; - b = (x * v1) >> m; + t = (x * v0) >> rBitSize; + b = (x * v1) >> rBitSize; a = x - (t * B[0][0] + b * B[1][0]); b = - (t * B[0][1] + b * B[1][1]); } @@ -263,7 +633,7 @@ struct GLV1 { #endif DummyLoop: if (!constTime) return; - const int limitBit = (int)Fp::getBitSize() / splitN; + const int limitBit = (int)rBitSize / splitN; G1 D = tbl[0]; for (int i = maxBit + 1; i < limitBit; i++) { G1::dbl(D, D); @@ -273,30 +643,25 @@ struct GLV1 { }; /* - GLV method for G2 and GT + GLV method for G2 and GT on BN/BLS12 */ -template<class Fp2> struct GLV2 { - typedef typename Fp2::BaseFp Fp; - typedef mcl::EcT<Fp2> G2; - typedef mcl::Fp12T<Fp> Fp12; - size_t m; + size_t rBitSize; mpz_class B[4][4]; mpz_class r; mpz_class v[4]; - GLV2() : m(0) {} - void init(const mpz_class& r, const mpz_class& z) + mpz_class z; + mpz_class abs_z; + bool isBLS12; + GLV2() : rBitSize(0), isBLS12(false) {} + void init(const mpz_class& r, const mpz_class& z, bool isBLS12 = false) { this->r = r; - m = mcl::gmp::getBitSize(r); - m = (m + mcl::fp::UnitBitSize - 1) & ~(mcl::fp::UnitBitSize - 1);// a little better size - /* - v[] = [1, 0, 0, 0] * B^(-1) = [2z^2+3z+1, 12z^3+8z^2+z, 6z^3+4z^2+z, -(2z+1)] - */ - v[0] = ((1 + z * (3 + z * 2)) << m) / r; - v[1] = ((z * (1 + z * (8 + z * 12))) << m) / r; - v[2] = ((z * (1 + z * (4 + z * 6))) << m) / r; - v[3] = -((z * (1 + z * 2)) << m) / r; + this->z = z; + this->abs_z = z < 0 ? -z : z; + this->isBLS12 = isBLS12; + rBitSize = mcl::gmp::getBitSize(r); + rBitSize = (rBitSize + mcl::fp::UnitBitSize - 1) & ~(mcl::fp::UnitBitSize - 1);// a little better size mpz_class z2p1 = z * 2 + 1; B[0][0] = z + 1; B[0][1] = z; @@ -314,15 +679,43 @@ struct GLV2 { B[3][1] = 2 * z2p1; B[3][2] = -2 * z + 1; B[3][3] = z - 1; + /* + v[] = [r 0 0 0] * B^(-1) = [2z^2+3z+1, 12z^3+8z^2+z, 6z^3+4z^2+z, -(2z+1)] + */ + v[0] = ((1 + z * (3 + z * 2)) << rBitSize) / r; + v[1] = ((z * (1 + z * (8 + z * 12))) << rBitSize) / r; + v[2] = ((z * (1 + z * (4 + z * 6))) << rBitSize) / r; + v[3] = -((z * (1 + z * 2)) << rBitSize) / r; } /* u[] = [x, 0, 0, 0] - v[] * x * B */ void split(mpz_class u[4], const mpz_class& x) const { + if (isBLS12) { + /* + Frob(P) = zP + x = u[0] + u[1] z + u[2] z^2 + u[3] z^3 + */ + bool isNeg = false; + mpz_class t = x; + if (t < 0) { + t = -t; + isNeg = true; + } + for (int i = 0; i < 4; i++) { + // t = t / abs_z, u[i] = t % abs_z + mcl::gmp::divmod(t, u[i], t, abs_z); + if (((z < 0) && (i & 1)) ^ isNeg) { + u[i] = -u[i]; + } + } + return; + } + // BN mpz_class t[4]; for (int i = 0; i < 4; i++) { - t[i] = (x * v[i]) >> m; + t[i] = (x * v[i]) >> rBitSize; } for (int i = 0; i < 4; i++) { u[i] = (i == 0) ? x : 0; @@ -364,9 +757,9 @@ struct GLV2 { } split(u, x); in[0] = P; - T::Frobenius(in[1], in[0]); - T::Frobenius(in[2], in[1]); - T::Frobenius(in[3], in[2]); + Frobenius(in[1], in[0]); + Frobenius(in[2], in[1]); + Frobenius(in[3], in[2]); for (int i = 0; i < splitN; i++) { if (u[i] < 0) { u[i] = -u[i]; @@ -433,20 +826,13 @@ struct GLV2 { #endif DummyLoop: if (!constTime) return; - const int limitBit = (int)Fp::getBitSize() / splitN; + const int limitBit = (int)rBitSize / splitN; T D = tbl[0]; for (int i = maxBit + 1; i < limitBit; i++) { T::dbl(D, D); D += tbl[0]; } } - void mul(G2& Q, const G2& P, mpz_class x, bool constTime = false) const - { - typedef util::HaveFrobenius<G2> G2withF; - G2withF& QQ(static_cast<G2withF&>(Q)); - const G2withF& PP(static_cast<const G2withF&>(P)); - mul(QQ, PP, x, constTime); - } void pow(Fp12& z, const Fp12& x, mpz_class y, bool constTime = false) const { typedef GroupMtoA<Fp12> AG; // as additive group @@ -456,133 +842,1057 @@ struct GLV2 { } }; -template<class Fp> -struct ParamT : public util::CommonParamT<Fp> { - typedef util::CommonParamT<Fp> Common; - typedef Fp2T<Fp> Fp2; - typedef mcl::EcT<Fp> G1; - typedef mcl::EcT<Fp2> G2; - MapToT<Fp> mapTo; - GLV1<Fp> glv1; - GLV2<Fp2> glv2; +struct Param { + CurveParam cp; + mpz_class z; + mpz_class abs_z; + bool isNegative; + bool isBLS12; + mpz_class p; + mpz_class r; + local::MapTo mapTo; + local::GLV1 glv1; + local::GLV2 glv2; + // for G2 Frobenius + Fp2 g2; + Fp2 g3; + /* + Dtype twist + (x', y') = phi(x, y) = (x/w^2, y/w^3) + y^2 = x^3 + b + => (y'w^3)^2 = (x'w^2)^3 + b + => y'^2 = x'^3 + b / w^6 ; w^6 = xi + => y'^2 = x'^3 + twist_b; + */ + Fp2 twist_b; + local::TwistBtype twist_b_type; +/* + mpz_class exp_c0; + mpz_class exp_c1; + mpz_class exp_c2; + mpz_class exp_c3; +*/ + + // Loop parameter for the Miller loop part of opt. ate pairing. + local::SignVec siTbl; + size_t precomputedQcoeffSize; + bool useNAF; + local::SignVec zReplTbl; - void init(const CurveParam& cp = CurveFp254BNb, fp::Mode mode = fp::FP_AUTO) + void init(const mcl::CurveParam& cp, fp::Mode mode) { - Common::initCommonParam(cp, mode); - mapTo.init(2 * this->p - this->r, this->z); - glv1.init(this->r, this->z); - glv2.init(this->r, this->z); + this->cp = cp; + isBLS12 = cp.curveType == MCL_BLS12_381; + z = mpz_class(cp.z); + isNegative = z < 0; + if (isNegative) { + abs_z = -z; + } else { + abs_z = z; + } + if (isBLS12) { + mpz_class z2 = z * z; + mpz_class z4 = z2 * z2; + r = z4 - z2 + 1; + p = z - 1; + p = p * p * r / 3 + z; + } else { + const int pCoff[] = { 1, 6, 24, 36, 36 }; + const int rCoff[] = { 1, 6, 18, 36, 36 }; + p = local::evalPoly(z, pCoff); + assert((p % 6) == 1); + r = local::evalPoly(z, rCoff); + } + Fp::init(p, mode); + Fp2::init(cp.xi_a); + Fp2 xi(cp.xi_a, 1); + g2 = Fp2::get_gTbl()[0]; + g3 = Fp2::get_gTbl()[3]; + if (cp.isMtype) { + Fp2::inv(g2, g2); + Fp2::inv(g3, g3); + } + if (cp.isMtype) { + twist_b = Fp2(cp.b) * xi; + } else { + twist_b = Fp2(cp.b) / xi; + } + if (twist_b == Fp2(1, -1)) { + twist_b_type = tb_1m1i; + } else if (twist_b == Fp2(1, -2)) { + twist_b_type = tb_1m2i; + } else { + twist_b_type = tb_generic; + } + G1::init(0, cp.b, mcl::ec::Proj); + if (isBLS12) { + G1::setOrder(r); + } + G2::init(0, twist_b, mcl::ec::Proj); + G2::setOrder(r); + + const mpz_class largest_c = isBLS12 ? abs_z : gmp::abs(z * 6 + 2); + useNAF = gmp::getNAF(siTbl, largest_c); + precomputedQcoeffSize = local::getPrecomputeQcoeffSize(siTbl); + gmp::getNAF(zReplTbl, gmp::abs(z)); +/* + if (isBLS12) { + mpz_class z2 = z * z; + mpz_class z3 = z2 * z; + mpz_class z4 = z3 * z; + mpz_class z5 = z4 * z; + exp_c0 = z5 - 2 * z4 + 2 * z2 - z + 3; + exp_c1 = z4 - 2 * z3 + 2 * z - 1; + exp_c2 = z3 - 2 * z2 + z; + exp_c3 = z2 - 2 * z + 1; + } else { + exp_c0 = -2 + z * (-18 + z * (-30 - 36 * z)); + exp_c1 = 1 + z * (-12 + z * (-18 - 36 * z)); + exp_c2 = 6 * z * z + 1; + } +*/ + if (isBLS12) { + mapTo.init(0, z, false); + } else { + mapTo.init(2 * p - r, z, true); + } + glv1.init(r, z, isBLS12); + glv2.init(r, z, isBLS12); } }; -template<class Fp> -struct BNT : mcl::util::BasePairingT<BNT<Fp>, Fp, ParamT<Fp> > { - typedef ParamT<Fp> Param; - typedef typename mcl::util::BasePairingT<BNT<Fp>, Fp, Param> Base; - typedef mcl::Fp2T<Fp> Fp2; - typedef mcl::Fp6T<Fp> Fp6; - typedef mcl::Fp12T<Fp> Fp12; - typedef mcl::EcT<Fp> G1; - typedef mcl::EcT<Fp2> G2; - typedef util::HaveFrobenius<G2> G2withF; - typedef mcl::FpDblT<Fp> FpDbl; - typedef mcl::Fp2DblT<Fp> Fp2Dbl; - static void mulArrayGLV1(G1& z, const G1& x, const mcl::fp::Unit *y, size_t yn, bool isNegative, bool constTime) - { - mpz_class s; - mcl::gmp::setArray(s, y, yn); - if (isNegative) s = -s; - Base::param.glv1.mul(z, x, s, constTime); - } - static void mulArrayGLV2(G2& z, const G2& x, const mcl::fp::Unit *y, size_t yn, bool isNegative, bool constTime) - { - mpz_class s; - mcl::gmp::setArray(s, y, yn); - if (isNegative) s = -s; - Base::param.glv2.mul(z, x, s, constTime); - } - static void powArrayGLV2(Fp12& z, const Fp12& x, const mcl::fp::Unit *y, size_t yn, bool isNegative, bool constTime) - { - mpz_class s; - mcl::gmp::setArray(s, y, yn); - if (isNegative) s = -s; - Base::param.glv2.pow(z, x, s, constTime); - } - static void init(const mcl::bn::CurveParam& cp = CurveFp254BNb, fp::Mode mode = fp::FP_AUTO) - { - Base::param.init(cp, mode); - G2withF::init(cp.isMtype); - G1::setMulArrayGLV(mulArrayGLV1); - G2::setMulArrayGLV(mulArrayGLV2); - Fp12::setPowArrayGLV(powArrayGLV2); - } - /* - Faster Hashing to G2 - Laura Fuentes-Castaneda, Edward Knapp, Francisco Rodriguez-Henriquez - section 4.1 - y = x^(d 2z(6z^2 + 3z + 1)) where - p = p(z) = 36z^4 + 36z^3 + 24z^2 + 6z + 1 - r = r(z) = 36z^4 + 36z^3 + 18z^2 + 6z + 1 - d = (p^4 - p^2 + 1) / r - d1 = d 2z(6z^2 + 3z + 1) - = c0 + c1 p + c2 p^2 + c3 p^3 - - c0 = 1 + 6z + 12z^2 + 12z^3 - c1 = 4z + 6z^2 + 12z^3 - c2 = 6z + 6z^2 + 12z^3 - c3 = -1 + 4z + 6z^2 + 12z^3 - x -> x^z -> x^2z -> x^4z -> x^6z -> x^(6z^2) -> x^(12z^2) -> x^(12z^3) - a = x^(6z) x^(6z^2) x^(12z^3) - b = a / (x^2z) - x^d1 = (a x^(6z^2) x) b^p a^(p^2) (b / x)^(p^3) - */ - static void expHardPart(Fp12& y, const Fp12& x) - { +template<size_t dummyImpl = 0> +struct StaticVar { + static local::Param param; +}; + +template<size_t dummyImpl> +local::Param StaticVar<dummyImpl>::param; + +} // mcl::bn::local + +namespace BN { + +static const local::Param& param = local::StaticVar<>::param; + +} // mcl::bn::BN + +namespace local { + +inline void mulArrayGLV1(G1& z, const G1& x, const mcl::fp::Unit *y, size_t yn, bool isNegative, bool constTime) +{ + mpz_class s; + mcl::gmp::setArray(s, y, yn); + if (isNegative) s = -s; + BN::param.glv1.mul(z, x, s, constTime); +} +inline void mulArrayGLV2(G2& z, const G2& x, const mcl::fp::Unit *y, size_t yn, bool isNegative, bool constTime) +{ + mpz_class s; + mcl::gmp::setArray(s, y, yn); + if (isNegative) s = -s; + BN::param.glv2.mul(z, x, s, constTime); +} +inline void powArrayGLV2(Fp12& z, const Fp12& x, const mcl::fp::Unit *y, size_t yn, bool isNegative, bool constTime) +{ + mpz_class s; + mcl::gmp::setArray(s, y, yn); + if (isNegative) s = -s; + BN::param.glv2.pow(z, x, s, constTime); +} + +/* + Faster Squaring in the Cyclotomic Subgroup of Sixth Degree Extensions + Robert Granger, Michael Scott +*/ +inline void sqrFp4(Fp2& z0, Fp2& z1, const Fp2& x0, const Fp2& x1) +{ +#if 1 + Fp2Dbl T0, T1, T2; + Fp2Dbl::sqrPre(T0, x0); + Fp2Dbl::sqrPre(T1, x1); + Fp2Dbl::mul_xi(T2, T1); + Fp2Dbl::add(T2, T2, T0); + Fp2::add(z1, x0, x1); + Fp2Dbl::mod(z0, T2); + Fp2Dbl::sqrPre(T2, z1); + Fp2Dbl::sub(T2, T2, T0); + Fp2Dbl::sub(T2, T2, T1); + Fp2Dbl::mod(z1, T2); +#else + Fp2 t0, t1, t2; + Fp2::sqr(t0, x0); + Fp2::sqr(t1, x1); + Fp2::mul_xi(z0, t1); + z0 += t0; + Fp2::add(z1, x0, x1); + Fp2::sqr(z1, z1); + z1 -= t0; + z1 -= t1; +#endif +} + +inline void fasterSqr(Fp12& y, const Fp12& x) +{ #if 0 - const mpz_class& p = param.p; - mpz_class p2 = p * p; - mpz_class p4 = p2 * p2; - Fp12::pow(y, x, (p4 - p2 + 1) / param.r); + Fp12::sqr(y, x); +#else + const Fp2& x0(x.a.a); + const Fp2& x4(x.a.b); + const Fp2& x3(x.a.c); + const Fp2& x2(x.b.a); + const Fp2& x1(x.b.b); + const Fp2& x5(x.b.c); + Fp2& y0(y.a.a); + Fp2& y4(y.a.b); + Fp2& y3(y.a.c); + Fp2& y2(y.b.a); + Fp2& y1(y.b.b); + Fp2& y5(y.b.c); + Fp2 t0, t1; + sqrFp4(t0, t1, x0, x1); + Fp2::sub(y0, t0, x0); + y0 += y0; + y0 += t0; + Fp2::add(y1, t1, x1); + y1 += y1; + y1 += t1; + Fp2 t2, t3; + sqrFp4(t0, t1, x2, x3); + sqrFp4(t2, t3, x4, x5); + Fp2::sub(y4, t0, x4); + y4 += y4; + y4 += t0; + Fp2::add(y5, t1, x5); + y5 += y5; + y5 += t1; + Fp2::mul_xi(t0, t3); + Fp2::add(y2, t0, x2); + y2 += y2; + y2 += t0; + Fp2::sub(y3, t2, x3); + y3 += y3; + y3 += t2; +#endif +} + +/* + y = x^z if z > 0 + = unitaryInv(x^(-z)) if z < 0 +*/ +inline void pow_z(Fp12& y, const Fp12& x) +{ +#if 1 + if (BN::param.cp.curveType == MCL_BN254) { + Compress::fixed_power(y, x); + } else { + Fp12 orgX = x; + y = x; + Fp12 conj; + conj.a = x.a; + Fp6::neg(conj.b, x.b); + for (size_t i = 1; i < BN::param.zReplTbl.size(); i++) { + fasterSqr(y, y); + if (BN::param.zReplTbl[i] > 0) { + y *= orgX; + } else if (BN::param.zReplTbl[i] < 0) { + y *= conj; + } + } + } +#else + Fp12::pow(y, x, param.abs_z); +#endif + if (BN::param.isNegative) { + Fp12::unitaryInv(y, y); + } +} +inline void mul_b_div_xi(Fp2& y, const Fp2& x) +{ + switch (BN::param.twist_b_type) { + case local::tb_1m1i: + /* + b / xi = 1 - 1i + (a + bi)(1 - 1i) = (a + b) + (b - a)i + */ + { + Fp t; + Fp::add(t, x.a, x.b); + Fp::sub(y.b, x.b, x.a); + y.a = t; + } + return; + case local::tb_1m2i: + /* + b / xi = 1 - 2i + (a + bi)(1 - 2i) = (a + 2b) + (b - 2a)i + */ + { + Fp t; + Fp::sub(t, x.b, x.a); + t -= x.a; + Fp::add(y.a, x.a, x.b); + y.a += x.b; + y.b = t; + } return; + case local::tb_generic: + Fp2::mul(y, x, BN::param.twist_b); + return; + } +} + +inline void dblLineWithoutP(Fp6& l, G2& Q) +{ + Fp2 t0, t1, t2, t3, t4, t5; + Fp2Dbl T0, T1; + Fp2::sqr(t0, Q.z); + Fp2::mul(t4, Q.x, Q.y); + Fp2::sqr(t1, Q.y); + Fp2::add(t3, t0, t0); + Fp2::divBy2(t4, t4); + Fp2::add(t5, t0, t1); + t0 += t3; + mul_b_div_xi(t2, t0); + Fp2::sqr(t0, Q.x); + Fp2::add(t3, t2, t2); + t3 += t2; + Fp2::sub(Q.x, t1, t3); + t3 += t1; + Q.x *= t4; + Fp2::divBy2(t3, t3); + Fp2Dbl::sqrPre(T0, t3); + Fp2Dbl::sqrPre(T1, t2); + Fp2Dbl::sub(T0, T0, T1); + Fp2Dbl::add(T1, T1, T1); + Fp2Dbl::sub(T0, T0, T1); + Fp2::add(t3, Q.y, Q.z); + Fp2Dbl::mod(Q.y, T0); + Fp2::sqr(t3, t3); + t3 -= t5; + Fp2::mul(Q.z, t1, t3); + Fp2::sub(l.a, t2, t1); + l.c = t0; + l.b = t3; +} +inline void addLineWithoutP(Fp6& l, G2& R, const G2& Q) +{ + Fp2 t1, t2, t3, t4; + Fp2Dbl T1, T2; + Fp2::mul(t1, R.z, Q.x); + Fp2::mul(t2, R.z, Q.y); + Fp2::sub(t1, R.x, t1); + Fp2::sub(t2, R.y, t2); + Fp2::sqr(t3, t1); + Fp2::mul(R.x, t3, R.x); + Fp2::sqr(t4, t2); + t3 *= t1; + t4 *= R.z; + t4 += t3; + t4 -= R.x; + t4 -= R.x; + R.x -= t4; + Fp2Dbl::mulPre(T1, t2, R.x); + Fp2Dbl::mulPre(T2, t3, R.y); + Fp2Dbl::sub(T2, T1, T2); + Fp2Dbl::mod(R.y, T2); + Fp2::mul(R.x, t1, t4); + Fp2::mul(R.z, t3, R.z); + Fp2::neg(l.c, t2); + Fp2Dbl::mulPre(T1, t2, Q.x); + Fp2Dbl::mulPre(T2, t1, Q.y); + Fp2Dbl::sub(T1, T1, T2); + l.b = t1; + Fp2Dbl::mod(l.a, T1); +} +inline void dblLine(Fp6& l, G2& Q, const G1& P) +{ + dblLineWithoutP(l, Q); + local::updateLine(l, P); +} +inline void addLine(Fp6& l, G2& R, const G2& Q, const G1& P) +{ + addLineWithoutP(l, R, Q); + local::updateLine(l, P); +} +inline void mulFp6cb_by_G1xy(Fp6& y, const Fp6& x, const G1& P) +{ + assert(P.isNormalized()); + if (&y != &x) y.a = x.a; + Fp2::mulFp(y.c, x.c, P.x); + Fp2::mulFp(y.b, x.b, P.y); +} + +/* + x = a + bv + cv^2 + y = (y0, y4, y2) -> (y0, 0, y2, 0, y4, 0) + z = xy = (a + bv + cv^2)(d + ev) + = (ad + ce xi) + ((a + b)(d + e) - ad - be)v + (be + cd)v^2 +*/ +inline void Fp6mul_01(Fp6& z, const Fp6& x, const Fp2& d, const Fp2& e) +{ + const Fp2& a = x.a; + const Fp2& b = x.b; + const Fp2& c = x.c; + Fp2 t0, t1; + Fp2Dbl AD, CE, BE, CD, T; + Fp2Dbl::mulPre(AD, a, d); + Fp2Dbl::mulPre(CE, c, e); + Fp2Dbl::mulPre(BE, b, e); + Fp2Dbl::mulPre(CD, c, d); + Fp2::add(t0, a, b); + Fp2::add(t1, d, e); + Fp2Dbl::mulPre(T, t0, t1); + T -= AD; + T -= BE; + Fp2Dbl::mod(z.b, T); + Fp2Dbl::mul_xi(CE, CE); + AD += CE; + Fp2Dbl::mod(z.a, AD); + BE += CD; + Fp2Dbl::mod(z.c, BE); +} +/* + input + z = (z0 + z1v + z2v^2) + (z3 + z4v + z5v^2)w = Z0 + Z1w + 0 3 4 + x = (a, b, c) -> (b, 0, 0, c, a, 0) = X0 + X1w + X0 = b = (b, 0, 0) + X1 = c + av = (c, a, 0) + w^2 = v, v^3 = xi + output + z <- zx = (Z0X0 + Z1X1v) + ((Z0 + Z1)(X0 + X1) - Z0X0 - Z1X1)w + Z0X0 = Z0 b + Z1X1 = Z1 (c, a, 0) + (Z0 + Z1)(X0 + X1) = (Z0 + Z1) (b + c, a, 0) +*/ +inline void mul_403(Fp12& z, const Fp6& x) +{ + const Fp2& a = x.a; + const Fp2& b = x.b; + const Fp2& c = x.c; +#if 1 + Fp6& z0 = z.a; + Fp6& z1 = z.b; + Fp6 z0x0, z1x1, t0; + Fp2 t1; + Fp2::add(t1, x.b, c); + Fp6::add(t0, z0, z1); + Fp2::mul(z0x0.a, z0.a, b); + Fp2::mul(z0x0.b, z0.b, b); + Fp2::mul(z0x0.c, z0.c, b); + Fp6mul_01(z1x1, z1, c, a); + Fp6mul_01(t0, t0, t1, a); + Fp6::sub(z.b, t0, z0x0); + z.b -= z1x1; + // a + bv + cv^2 = cxi + av + bv^2 + Fp2::mul_xi(z1x1.c, z1x1.c); + Fp2::add(z.a.a, z0x0.a, z1x1.c); + Fp2::add(z.a.b, z0x0.b, z1x1.a); + Fp2::add(z.a.c, z0x0.c, z1x1.b); +#else + Fp2& z0 = z.a.a; + Fp2& z1 = z.a.b; + Fp2& z2 = z.a.c; + Fp2& z3 = z.b.a; + Fp2& z4 = z.b.b; + Fp2& z5 = z.b.c; + Fp2Dbl Z0B, Z1B, Z2B, Z3C, Z4C, Z5C; + Fp2Dbl T0, T1, T2, T3, T4, T5; + Fp2 bc, t; + Fp2::addPre(bc, b, c); + Fp2::addPre(t, z5, z2); + Fp2Dbl::mulPre(T5, t, bc); + Fp2Dbl::mulPre(Z5C, z5, c); + Fp2Dbl::mulPre(Z2B, z2, b); + Fp2Dbl::sub(T5, T5, Z5C); + Fp2Dbl::sub(T5, T5, Z2B); + Fp2Dbl::mulPre(T0, z1, a); + T5 += T0; + + Fp2::addPre(t, z4, z1); + Fp2Dbl::mulPre(T4, t, bc); + Fp2Dbl::mulPre(Z4C, z4, c); + Fp2Dbl::mulPre(Z1B, z1, b); + Fp2Dbl::sub(T4, T4, Z4C); + Fp2Dbl::sub(T4, T4, Z1B); + Fp2Dbl::mulPre(T0, z0, a); + T4 += T0; + + Fp2::addPre(t, z3, z0); + Fp2Dbl::mulPre(T3, t, bc); + Fp2Dbl::mulPre(Z3C, z3, c); + Fp2Dbl::mulPre(Z0B, z0, b); + Fp2Dbl::sub(T3, T3, Z3C); + Fp2Dbl::sub(T3, T3, Z0B); + Fp2::mul_xi(t, z2); + Fp2Dbl::mulPre(T0, t, a); + T3 += T0; + + Fp2Dbl::mulPre(T2, z3, a); + T2 += Z2B; + T2 += Z4C; + + Fp2::mul_xi(t, z5); + Fp2Dbl::mulPre(T1, t, a); + T1 += Z1B; + T1 += Z3C; + + Fp2Dbl::mulPre(T0, z4, a); + T0 += Z5C; + Fp2Dbl::mul_xi(T0, T0); + T0 += Z0B; + + Fp2Dbl::mod(z0, T0); + Fp2Dbl::mod(z1, T1); + Fp2Dbl::mod(z2, T2); + Fp2Dbl::mod(z3, T3); + Fp2Dbl::mod(z4, T4); + Fp2Dbl::mod(z5, T5); +#endif +} +/* + input + z = (z0 + z1v + z2v^2) + (z3 + z4v + z5v^2)w = Z0 + Z1w + 0 1 4 + x = (a, b, c) -> (a, c, 0, 0, b, 0) = X0 + X1w + X0 = (a, c, 0) + X1 = (0, b, 0) + w^2 = v, v^3 = xi + output + z <- zx = (Z0X0 + Z1X1v) + ((Z0 + Z1)(X0 + X1) - Z0X0 - Z1X1)w + Z0X0 = Z0 (a, c, 0) + Z1X1 = Z1 (0, b, 0) = Z1 bv + (Z0 + Z1)(X0 + X1) = (Z0 + Z1) (a, b + c, 0) + + (a + bv + cv^2)v = c xi + av + bv^2 +*/ +inline void mul_041(Fp12& z, const Fp6& x) +{ + const Fp2& a = x.a; + const Fp2& b = x.b; + const Fp2& c = x.c; + Fp6& z0 = z.a; + Fp6& z1 = z.b; + Fp6 z0x0, z1x1, t0; + Fp2 t1; + Fp2::mul(z1x1.a, z1.c, b); + Fp2::mul_xi(z1x1.a, z1x1.a); + Fp2::mul(z1x1.b, z1.a, b); + Fp2::mul(z1x1.c, z1.b, b); + Fp2::add(t1, x.b, c); + Fp6::add(t0, z0, z1); + Fp6mul_01(z0x0, z0, a, c); + Fp6mul_01(t0, t0, a, t1); + Fp6::sub(z.b, t0, z0x0); + z.b -= z1x1; + // a + bv + cv^2 = cxi + av + bv^2 + Fp2::mul_xi(z1x1.c, z1x1.c); + Fp2::add(z.a.a, z0x0.a, z1x1.c); + Fp2::add(z.a.b, z0x0.b, z1x1.a); + Fp2::add(z.a.c, z0x0.c, z1x1.b); +} +inline void mulSparse(Fp12& z, const Fp6& x) +{ + if (BN::param.cp.isMtype) { + mul_041(z, x); + } else { + mul_403(z, x); + } +} +inline void convertFp6toFp12(Fp12& y, const Fp6& x) +{ + y.clear(); + if (BN::param.cp.isMtype) { + // (a, b, c) -> (a, c, 0, 0, b, 0) + y.a.a = x.a; + y.b.b = x.b; + y.a.b = x.c; + } else { + // (a, b, c) -> (b, 0, 0, c, a, 0) + y.b.b = x.a; + y.a.a = x.b; + y.b.a = x.c; + } +} +inline void mulSparse2(Fp12& z, const Fp6& x, const Fp6& y) +{ + convertFp6toFp12(z, x); + mulSparse(z, y); +} +inline void mapToCyclotomic(Fp12& y, const Fp12& x) +{ + Fp12 z; + Fp12::Frobenius2(z, x); // z = x^(p^2) + z *= x; // x^(p^2 + 1) + Fp12::inv(y, z); + Fp6::neg(z.b, z.b); // z^(p^6) = conjugate of z + y *= z; +} +/* + Implementing Pairings at the 192-bit Security Level + D.F.Aranha, L.F.Castaneda, E.Knapp, A.Menezes, F.R.Henriquez + Section 4 +*/ +inline void expHardPartBLS12(Fp12& y, const Fp12& x) +{ +#if 0 + const mpz_class& p = param.p; + mpz_class p2 = p * p; + mpz_class p4 = p2 * p2; + Fp12::pow(y, x, (p4 - p2 + 1) / param.r * 3); + return; +#endif +#if 1 + Fp12 a0, a1, a2, a3, a4, a5, a6, a7; + Fp12::unitaryInv(a0, x); // a0 = x^-1 + fasterSqr(a1, a0); // x^-2 + pow_z(a2, x); // x^z + fasterSqr(a3, a2); // x^2z + a1 *= a2; // a1 = x^(z-2) + pow_z(a7, a1); // a7 = x^(z^2-2z) + pow_z(a4, a7); // a4 = x^(z^3-2z^2) + pow_z(a5, a4); // a5 = x^(z^4-2z^3) + a3 *= a5; // a3 = x^(z^4-2z^3+2z) + pow_z(a6, a3); // a6 = x^(z^5-2z^4+2z^2) + + Fp12::unitaryInv(a1, a1); // x^(2-z) + a1 *= a6; // x^(z^5-2z^4+2z^2-z+2) + a1 *= x; // x^(z^5-2z^4+2z^2-z+3) = x^c0 + a3 *= a0; // x^(z^4-2z^3-1) = x^c1 + Fp12::Frobenius(a3, a3); // x^(c1 p) + a1 *= a3; // x^(c0 + c1 p) + a4 *= a2; // x^(z^3-2z^2+z) = x^c2 + Fp12::Frobenius2(a4, a4); // x^(c2 p^2) + a1 *= a4; // x^(c0 + c1 p + c2 p^2) + a7 *= x; // x^(z^2-2z+1) = x^c3 + Fp12::Frobenius3(y, a7); + y *= a1; +#else + Fp12 t1, t2, t3; + Fp12::Frobenius(t1, x); + Fp12::Frobenius(t2, t1); + Fp12::Frobenius(t3, t2); + Fp12::pow(t1, t1, param.exp_c1); + Fp12::pow(t2, t2, param.exp_c2); + Fp12::pow(t3, t3, param.exp_c3); + Fp12::pow(y, x, param.exp_c0); + y *= t1; + y *= t2; + y *= t3; +#endif +} +/* + Faster Hashing to G2 + Laura Fuentes-Castaneda, Edward Knapp, Francisco Rodriguez-Henriquez + section 4.1 + y = x^(d 2z(6z^2 + 3z + 1)) where + p = p(z) = 36z^4 + 36z^3 + 24z^2 + 6z + 1 + r = r(z) = 36z^4 + 36z^3 + 18z^2 + 6z + 1 + d = (p^4 - p^2 + 1) / r + d1 = d 2z(6z^2 + 3z + 1) + = c0 + c1 p + c2 p^2 + c3 p^3 + + c0 = 1 + 6z + 12z^2 + 12z^3 + c1 = 4z + 6z^2 + 12z^3 + c2 = 6z + 6z^2 + 12z^3 + c3 = -1 + 4z + 6z^2 + 12z^3 + x -> x^z -> x^2z -> x^4z -> x^6z -> x^(6z^2) -> x^(12z^2) -> x^(12z^3) + a = x^(6z) x^(6z^2) x^(12z^3) + b = a / (x^2z) + x^d1 = (a x^(6z^2) x) b^p a^(p^2) (b / x)^(p^3) +*/ +inline void expHardPartBN(Fp12& y, const Fp12& x) +{ +#if 0 + const mpz_class& p = param.p; + mpz_class p2 = p * p; + mpz_class p4 = p2 * p2; + Fp12::pow(y, x, (p4 - p2 + 1) / param.r); + return; +#endif +#if 1 + Fp12 a, b; + Fp12 a2, a3; + pow_z(b, x); // x^z + fasterSqr(b, b); // x^2z + fasterSqr(a, b); // x^4z + a *= b; // x^6z + pow_z(a2, a); // x^(6z^2) + a *= a2; + fasterSqr(a3, a2); // x^(12z^2) + pow_z(a3, a3); // x^(12z^3) + a *= a3; + Fp12::unitaryInv(b, b); + b *= a; + a2 *= a; + Fp12::Frobenius2(a, a); + a *= a2; + a *= x; + Fp12::unitaryInv(y, x); + y *= b; + Fp12::Frobenius(b, b); + a *= b; + Fp12::Frobenius3(y, y); + y *= a; +#else + Fp12 t1, t2, t3; + Fp12::Frobenius(t1, x); + Fp12::Frobenius(t2, t1); + Fp12::Frobenius(t3, t2); + Fp12::pow(t1, t1, param.exp_c1); + Fp12::pow(t2, t2, param.exp_c2); + Fp12::pow(y, x, param.exp_c0); + y *= t1; + y *= t2; + y *= t3; #endif +} +/* + remark : returned value is NOT on a curve +*/ +inline G1 makeAdjP(const G1& P) +{ + G1 adjP; + Fp::add(adjP.x, P.x, P.x); + adjP.x += P.x; + Fp::neg(adjP.y, P.y); + adjP.z = 1; + return adjP; +} + +inline void init(const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode = fp::FP_AUTO) +{ + local::StaticVar<>::param.init(cp, mode); + G1::setMulArrayGLV(local::mulArrayGLV1); + G2::setMulArrayGLV(local::mulArrayGLV2); + Fp12::setPowArrayGLV(local::powArrayGLV2); +} + +} // mcl::bn::local + +/* + y = x^((p^12 - 1) / r) + (p^12 - 1) / r = (p^2 + 1) (p^6 - 1) (p^4 - p^2 + 1)/r + (a + bw)^(p^6) = a - bw in Fp12 + (p^4 - p^2 + 1)/r = c0 + c1 p + c2 p^2 + p^3 +*/ +inline void finalExp(Fp12& y, const Fp12& x) +{ #if 1 - Fp12 a, b; - Fp12 a2, a3; - Base::pow_z(b, x); // x^z - Base::fasterSqr(b, b); // x^2z - Base::fasterSqr(a, b); // x^4z - a *= b; // x^6z - Base::pow_z(a2, a); // x^(6z^2) - a *= a2; - Base::fasterSqr(a3, a2); // x^(12z^2) - Base::pow_z(a3, a3); // x^(12z^3) - a *= a3; - Fp12::unitaryInv(b, b); - b *= a; - a2 *= a; - Fp12::Frobenius2(a, a); - a *= a2; - a *= x; - Fp12::unitaryInv(y, x); - y *= b; - Fp12::Frobenius(b, b); - a *= b; - Fp12::Frobenius3(y, y); - y *= a; + mapToCyclotomic(y, x); #else - Fp12 t1, t2, t3; - Fp12::Frobenius(t1, x); - Fp12::Frobenius(t2, t1); - Fp12::Frobenius(t3, t2); - Fp12::pow(t1, t1, param.exp_c1); - Fp12::pow(t2, t2, param.exp_c2); - Fp12::pow(y, x, param.exp_c0); - y *= t1; - y *= t2; - y *= t3; + const mpz_class& p = param.p; + mpz_class p2 = p * p; + mpz_class p4 = p2 * p2; + Fp12::pow(y, x, p2 + 1); + Fp12::pow(y, y, p4 * p2 - 1); #endif + if (BN::param.isBLS12) { + expHardPartBLS12(y, y); + } else { + expHardPartBN(y, y); } -}; +} +inline void millerLoop(Fp12& f, const G1& P_, const G2& Q_) +{ + G1 P(P_); + G2 Q(Q_); + P.normalize(); + Q.normalize(); + if (Q.isZero()) { + f = 1; + return; + } + assert(BN::param.siTbl[1] == 1); + G2 T = Q; + G2 negQ; + if (BN::param.useNAF) { + G2::neg(negQ, Q); + } + Fp6 d, e, l; + d = e = l = 1; + G1 adjP = makeAdjP(P); + dblLine(d, T, adjP); + addLine(l, T, Q, P); + mulSparse2(f, d, l); + for (size_t i = 2; i < BN::param.siTbl.size(); i++) { + dblLine(l, T, adjP); + Fp12::sqr(f, f); + mulSparse(f, l); + if (BN::param.siTbl[i]) { + if (BN::param.siTbl[i] > 0) { + addLine(l, T, Q, P); + } else { + addLine(l, T, negQ, P); + } + mulSparse(f, l); + } + } + if (BN::param.z < 0) { + G2::neg(T, T); + Fp6::neg(f.b, f.b); + } + if (BN::param.isBLS12) return; + G2 Q1, Q2; + Frobenius(Q1, Q); + Frobenius(Q2, Q1); + G2::neg(Q2, Q2); + addLine(d, T, Q1, P); + addLine(e, T, Q2, P); + Fp12 ft; + mulSparse2(ft, d, e); + f *= ft; +} +inline void pairing(Fp12& f, const G1& P, const G2& Q) +{ + millerLoop(f, P, Q); + finalExp(f, f); +} +/* + allocate param.precomputedQcoeffSize elements of Fp6 for Qcoeff +*/ +inline void precomputeG2(Fp6 *Qcoeff, const G2& Q_) +{ + size_t idx = 0; + G2 Q(Q_); + Q.normalize(); + if (Q.isZero()) { + for (size_t i = 0; i < BN::param.precomputedQcoeffSize; i++) { + Qcoeff[i] = 1; + } + return; + } + G2 T = Q; + G2 negQ; + if (BN::param.useNAF) { + G2::neg(negQ, Q); + } + assert(BN::param.siTbl[1] == 1); + dblLineWithoutP(Qcoeff[idx++], T); + addLineWithoutP(Qcoeff[idx++], T, Q); + for (size_t i = 2; i < BN::param.siTbl.size(); i++) { + dblLineWithoutP(Qcoeff[idx++], T); + if (BN::param.siTbl[i]) { + if (BN::param.siTbl[i] > 0) { + addLineWithoutP(Qcoeff[idx++], T, Q); + } else { + addLineWithoutP(Qcoeff[idx++], T, negQ); + } + } + } + if (BN::param.z < 0) { + G2::neg(T, T); + } + if (BN::param.isBLS12) return; + G2 Q1, Q2; + Frobenius(Q1, Q); + Frobenius(Q2, Q1); + G2::neg(Q2, Q2); + addLineWithoutP(Qcoeff[idx++], T, Q1); + addLineWithoutP(Qcoeff[idx++], T, Q2); + assert(idx == BN::param.precomputedQcoeffSize); +} +/* + millerLoop(e, P, Q) is same as the following + std::vector<Fp6> Qcoeff; + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e, P, Qcoeff); +*/ +inline void precomputeG2(std::vector<Fp6>& Qcoeff, const G2& Q) +{ + Qcoeff.resize(BN::param.precomputedQcoeffSize); + precomputeG2(Qcoeff.data(), Q); +} +inline void precomputedMillerLoop(Fp12& f, const G1& P_, const Fp6* Qcoeff) +{ + G1 P(P_); + P.normalize(); + G1 adjP = makeAdjP(P); + size_t idx = 0; + Fp6 d, e, l; + mulFp6cb_by_G1xy(d, Qcoeff[idx], adjP); + idx++; + + mulFp6cb_by_G1xy(e, Qcoeff[idx], P); + idx++; + mulSparse2(f, d, e); + for (size_t i = 2; i < BN::param.siTbl.size(); i++) { + mulFp6cb_by_G1xy(l, Qcoeff[idx], adjP); + idx++; + Fp12::sqr(f, f); + mulSparse(f, l); + if (BN::param.siTbl[i]) { + mulFp6cb_by_G1xy(l, Qcoeff[idx], P); + idx++; + mulSparse(f, l); + } + } + if (BN::param.z < 0) { + Fp6::neg(f.b, f.b); + } + if (BN::param.isBLS12) return; + mulFp6cb_by_G1xy(d, Qcoeff[idx], P); + idx++; + mulFp6cb_by_G1xy(e, Qcoeff[idx], P); + idx++; + Fp12 ft; + mulSparse2(ft, d, e); + f *= ft; +} +inline void precomputedMillerLoop(Fp12& f, const G1& P, const std::vector<Fp6>& Qcoeff) +{ + precomputedMillerLoop(f, P, Qcoeff.data()); +} +/* + f = MillerLoop(P1, Q1) x MillerLoop(P2, Q2) +*/ +inline void precomputedMillerLoop2(Fp12& f, const G1& P1_, const Fp6* Q1coeff, const G1& P2_, const Fp6* Q2coeff) +{ + G1 P1(P1_), P2(P2_); + P1.normalize(); + P2.normalize(); + G1 adjP1 = makeAdjP(P1); + G1 adjP2 = makeAdjP(P2); + size_t idx = 0; + Fp6 d1, d2, e1, e2, l1, l2; + mulFp6cb_by_G1xy(d1, Q1coeff[idx], adjP1); + mulFp6cb_by_G1xy(d2, Q2coeff[idx], adjP2); + idx++; + + Fp12 f1, f2; + mulFp6cb_by_G1xy(e1, Q1coeff[idx], P1); + mulSparse2(f1, d1, e1); + + mulFp6cb_by_G1xy(e2, Q2coeff[idx], P2); + mulSparse2(f2, d2, e2); + Fp12::mul(f, f1, f2); + idx++; + for (size_t i = 2; i < BN::param.siTbl.size(); i++) { + mulFp6cb_by_G1xy(l1, Q1coeff[idx], adjP1); + mulFp6cb_by_G1xy(l2, Q2coeff[idx], adjP2); + idx++; + Fp12::sqr(f, f); + mulSparse2(f1, l1, l2); + f *= f1; + if (BN::param.siTbl[i]) { + mulFp6cb_by_G1xy(l1, Q1coeff[idx], P1); + mulFp6cb_by_G1xy(l2, Q2coeff[idx], P2); + idx++; + mulSparse2(f1, l1, l2); + f *= f1; + } + } + if (BN::param.z < 0) { + Fp6::neg(f.b, f.b); + } + if (BN::param.isBLS12) return; + mulFp6cb_by_G1xy(d1, Q1coeff[idx], P1); + mulFp6cb_by_G1xy(d2, Q2coeff[idx], P2); + idx++; + mulFp6cb_by_G1xy(e1, Q1coeff[idx], P1); + mulFp6cb_by_G1xy(e2, Q2coeff[idx], P2); + idx++; + mulSparse2(f1, d1, e1); + mulSparse2(f2, d2, e2); + f *= f1; + f *= f2; +} +inline void precomputedMillerLoop2(Fp12& f, const G1& P1, const std::vector<Fp6>& Q1coeff, const G1& P2, const std::vector<Fp6>& Q2coeff) +{ + precomputedMillerLoop2(f, P1, Q1coeff.data(), P2, Q2coeff.data()); +} +inline void mapToG1(G1& P, const Fp& x) { BN::param.mapTo.calcG1(P, x); } +inline void mapToG2(G2& P, const Fp2& x) { BN::param.mapTo.calcG2(P, x); } +inline void hashAndMapToG1(G1& P, const void *buf, size_t bufSize) +{ + Fp t; + t.setHashOf(buf, bufSize); + mapToG1(P, t); +} +inline void hashAndMapToG2(G2& P, const void *buf, size_t bufSize) +{ + Fp2 t; + t.a.setHashOf(buf, bufSize); + t.b.clear(); + mapToG2(P, t); +} +inline void hashAndMapToG1(G1& P, const std::string& str) +{ + hashAndMapToG1(P, str.c_str(), str.size()); +} +inline void hashAndMapToG2(G2& P, const std::string& str) +{ + hashAndMapToG2(P, str.c_str(), str.size()); +} +inline void verifyOrderG1(bool doVerify) +{ + if (BN::param.isBLS12) { + G1::setOrder(doVerify ? BN::param.r : 0); + } +} +inline void verifyOrderG2(bool doVerify) +{ + G2::setOrder(doVerify ? BN::param.r : 0); +} + +// backward compatibility +using mcl::CurveParam; +static const CurveParam& CurveFp254BNb = BN254; +static const CurveParam& CurveFp382_1 = BN381_1; +static const CurveParam& CurveFp382_2 = BN381_2; +static const CurveParam& CurveFp462 = BN462; +static const CurveParam& CurveSNARK1 = BN_SNARK1; + +/* + FrobeniusOnTwist for Dtype + p mod 6 = 1, w^6 = xi + Frob(x', y') = phi Frob phi^-1(x', y') + = phi Frob (x' w^2, y' w^3) + = phi (x'^p w^2p, y'^p w^3p) + = (F(x') w^2(p - 1), F(y') w^3(p - 1)) + = (F(x') g^2, F(y') g^3) + + FrobeniusOnTwist for Dtype + use (1/g) instead of g +*/ +inline void Frobenius(G2& D, const G2& S) +{ + Fp2::Frobenius(D.x, S.x); + Fp2::Frobenius(D.y, S.y); + Fp2::Frobenius(D.z, S.z); + D.x *= BN::param.g2; + D.y *= BN::param.g3; +} +inline void Frobenius2(G2& D, const G2& S) +{ + Frobenius(D, S); + Frobenius(D, D); +} +inline void Frobenius3(G2& D, const G2& S) +{ + Frobenius(D, S); + Frobenius(D, D); + Frobenius(D, D); +} + +inline void initPairing(const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode = fp::FP_AUTO) +{ + local::init(cp, mode); + G1::setCompressedExpression(); + G2::setCompressedExpression(); + Fr::init(BN::param.r); +} + +namespace BN { + +using namespace mcl::bn; // backward compatibility +inline void init(const mcl::CurveParam& cp = mcl::BN254, fp::Mode mode = fp::FP_AUTO) +{ + local::init(cp, mode); +} + +} // mcl::bn::BN } } // mcl::bn diff --git a/include/mcl/bn256.hpp b/include/mcl/bn256.hpp index c22e82f..7a5da7a 100644 --- a/include/mcl/bn256.hpp +++ b/include/mcl/bn256.hpp @@ -6,39 +6,10 @@ @license modified new BSD license http://opensource.org/licenses/BSD-3-Clause */ +#define MCL_MAX_FP_BIT_SIZE 256 #include <mcl/bn.hpp> namespace mcl { namespace bn256 { - -namespace local { -struct FpTag; -struct FrTag; -} - -typedef mcl::FpT<local::FpTag, 256> Fp; -typedef mcl::bn::BNT<Fp> BN; -typedef BN::Fp2 Fp2; -typedef BN::Fp6 Fp6; -typedef BN::Fp12 Fp12; -typedef BN::G1 G1; -typedef BN::G2 G2; -typedef BN::Fp12 GT; - -/* the order of G1 is r */ -typedef mcl::FpT<local::FrTag, 256> Fr; - -static inline void initPairing(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp254BNb, fp::Mode mode = fp::FP_AUTO) -{ - BN::init(cp, mode); - G1::setCompressedExpression(); - G2::setCompressedExpression(); - Fr::init(BN::param.r); -} - -static inline void bn256init(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp254BNb, fp::Mode mode = fp::FP_AUTO) -{ - initPairing(cp, mode); -} - -} } // mcl::bn256 +using namespace mcl::bn; +} } diff --git a/include/mcl/bn384.hpp b/include/mcl/bn384.hpp index f2e6078..8aa14fe 100644 --- a/include/mcl/bn384.hpp +++ b/include/mcl/bn384.hpp @@ -6,39 +6,10 @@ @license modified new BSD license http://opensource.org/licenses/BSD-3-Clause */ +#define MCL_MAX_FP_BIT_SIZE 384 #include <mcl/bn.hpp> +// #define MCL_MAX_FR_BIT_SIZE 256 // can set if BLS12_381 namespace mcl { namespace bn384 { - -namespace local { -struct FpTag; -struct FrTag; -} - -typedef mcl::FpT<local::FpTag, 384> Fp; -typedef mcl::bn::BNT<Fp> BN; -typedef BN::Fp2 Fp2; -typedef BN::Fp6 Fp6; -typedef BN::Fp12 Fp12; -typedef BN::G1 G1; -typedef BN::G2 G2; -typedef BN::Fp12 GT; - -/* the order of G1 is r */ -typedef mcl::FpT<local::FrTag, 384> Fr; - -static inline void initPairing(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp382_2, fp::Mode mode = fp::FP_AUTO) -{ - BN::init(cp, mode); - G1::setCompressedExpression(); - G2::setCompressedExpression(); - Fr::init(BN::param.r); -} - -static inline void bn384init(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp382_2, fp::Mode mode = fp::FP_AUTO) -{ - initPairing(cp, mode); -} - -} } // mcl::bn384 - +using namespace mcl::bn; +} } diff --git a/include/mcl/bn512.hpp b/include/mcl/bn512.hpp index 6979606..c87ad90 100644 --- a/include/mcl/bn512.hpp +++ b/include/mcl/bn512.hpp @@ -6,34 +6,9 @@ @license modified new BSD license http://opensource.org/licenses/BSD-3-Clause */ +#define MCL_MAX_FP_BIT_SIZE 512 #include <mcl/bn.hpp> namespace mcl { namespace bn512 { - -namespace local { -struct FpTag; -struct FrTag; -} - -typedef mcl::FpT<local::FpTag, 512> Fp; -typedef mcl::bn::BNT<Fp> BN; -typedef BN::Fp2 Fp2; -typedef BN::Fp6 Fp6; -typedef BN::Fp12 Fp12; -typedef BN::G1 G1; -typedef BN::G2 G2; -typedef BN::Fp12 GT; - -/* the order of G1 is r */ -typedef mcl::FpT<local::FrTag, 512> Fr; - -static inline void initPairing(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp254BNb, fp::Mode mode = fp::FP_AUTO) -{ - BN::init(cp, mode); - G1::setCompressedExpression(); - G2::setCompressedExpression(); - Fr::init(BN::param.r); -} - -} } // mcl::bn512 - +using namespace mcl::bn; +} } diff --git a/include/mcl/curve_type.h b/include/mcl/curve_type.h index 7ab3de6..537ce11 100644 --- a/include/mcl/curve_type.h +++ b/include/mcl/curve_type.h @@ -7,14 +7,11 @@ http://opensource.org/licenses/BSD-3-Clause */ -#ifndef MCL_CURVE_TYPE_DEFINED -#define MCL_CURVE_TYPE_DEFINED enum { - mclBn_CurveFp254BNb = 0, - mclBn_CurveFp382_1 = 1, - mclBn_CurveFp382_2 = 2, - mclBn_CurveFp462 = 3, - mclBn_CurveSNARK1 = 4, - mclBls12_CurveFp381 = 5 + MCL_BN254 = 0, + MCL_BN381_1 = 1, + MCL_BN381_2 = 2, + MCL_BN462 = 3, + MCL_BN_SNARK1 = 4, + MCL_BLS12_381 = 5 }; -#endif diff --git a/include/mcl/ec.hpp b/include/mcl/ec.hpp index 5f7ce26..4a71bc0 100644 --- a/include/mcl/ec.hpp +++ b/include/mcl/ec.hpp @@ -726,7 +726,7 @@ public: getYfromX(y, x, isYodd); } else { char c = 0; - if (!cybozu::readChar(&c, is)) throw cybozu::Exception("EcT:load:no header"); + if (!fp::local::skipSpace(&c, is)) throw cybozu::Exception("EcT:load:no header"); if (c == '0') { clear(); return; diff --git a/include/mcl/fp.hpp b/include/mcl/fp.hpp index c166657..7163d8c 100644 --- a/include/mcl/fp.hpp +++ b/include/mcl/fp.hpp @@ -65,17 +65,21 @@ inline bool isSpace(char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; } +template<class InputStream> +bool skipSpace(char *c, InputStream& is) +{ + for (;;) { + if (!cybozu::readChar(c, is)) return false; + if (!isSpace(*c)) return true; + } +} template<class InputStream> void loadWord(std::string& s, InputStream& is) { s.clear(); char c; - // skip space - for (;;) { - if (!cybozu::readChar(&c, is)) return; - if (!isSpace(c)) break; - } + if (!skipSpace(&c, is)) return; s = c; for (;;) { if (!cybozu::readChar(&c, is)) return; diff --git a/include/mcl/pairing_util.hpp b/include/mcl/pairing_util.hpp deleted file mode 100644 index 4214637..0000000 --- a/include/mcl/pairing_util.hpp +++ /dev/null @@ -1,1156 +0,0 @@ -#pragma once -/** - @file - @brief utility for pairings - @author MITSUNARI Shigeo(@herumi) - @license modified new BSD license - http://opensource.org/licenses/BSD-3-Clause -*/ -#include <mcl/fp_tower.hpp> -#include <mcl/ec.hpp> -#include <mcl/curve_type.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 std::string(z) == rhs.z && b == rhs.b && xi_a == rhs.xi_a && isMtype == rhs.isMtype; - } - bool operator!=(const CurveParam& rhs) const { return !operator==(rhs); } -}; - -namespace bn { - -const CurveParam CurveFp254BNb = { "-0x4080000000000001", 2, 1, false, mclBn_CurveFp254BNb }; // -(2^62 + 2^55 + 1) -// provisional(experimental) param with maxBitSize = 384 -const CurveParam CurveFp382_1 = { "-0x400011000000000000000001", 2, 1, false, mclBn_CurveFp382_1 }; // -(2^94 + 2^76 + 2^72 + 1) // A Family of Implementation-Friendly BN Elliptic Curves -const CurveParam CurveFp382_2 = { "-0x400040090001000000000001", 2, 1, false, mclBn_CurveFp382_2 }; // -(2^94 + 2^78 + 2^67 + 2^64 + 2^48 + 1) // used in relic-toolkit -const CurveParam CurveFp462 = { "0x4001fffffffffffffffffffffbfff", 5, 2, false, mclBn_CurveFp462 }; // 2^114 + 2^101 - 2^14 - 1 // https://eprint.iacr.org/2017/334 -const CurveParam CurveSNARK1 = { "4965661367192848881", 3, 9, false, mclBn_CurveSNARK1 }; - -} // mcl::bn - -namespace bls12 { - -const CurveParam CurveFp381 = { "-0xd201000000010000", 4, 1, true, mclBls12_CurveFp381 }; - -} // mcl::bls12 - -inline const CurveParam& getCurveParam(int type) -{ - switch (type) { - case mclBn_CurveFp254BNb: return bn::CurveFp254BNb; - case mclBn_CurveFp382_1: return bn::CurveFp382_1; - case mclBn_CurveFp382_2: return bn::CurveFp382_2; - case mclBn_CurveFp462: return bn::CurveFp462; - case mclBn_CurveSNARK1: return bn::CurveSNARK1; - case mclBls12_CurveFp381: return bls12::CurveFp381; - default: - throw cybozu::Exception("getCurveParam:bad type") << type; - } -} - -namespace util { - -typedef std::vector<int8_t> SignVec; - -inline size_t getPrecomputeQcoeffSize(const SignVec& sv) -{ - size_t idx = 2 + 2; - for (size_t i = 2; i < sv.size(); i++) { - idx++; - if (sv[i]) idx++; - } - return idx; -} - -template<class X, class C, size_t N> -X evalPoly(const X& x, const C (&c)[N]) -{ - X ret = c[N - 1]; - for (size_t i = 1; i < N; i++) { - ret *= x; - ret += c[N - 1 - i]; - } - return ret; -} -enum TwistBtype { - tb_generic, - tb_1m1i, // 1 - 1i - tb_1m2i // 1 - 2i -}; - -template<class _Fp> -struct CommonParamT { - typedef _Fp Fp; - typedef Fp2T<Fp> Fp2; - typedef mcl::EcT<Fp> G1; - typedef mcl::EcT<Fp2> G2; - mcl::CurveParam cp; - mpz_class z; - mpz_class abs_z; - bool isNegative; - bool isBLS12; - mpz_class p; - mpz_class r; - /* - Dtype twist - (x', y') = phi(x, y) = (x/w^2, y/w^3) - y^2 = x^3 + b - => (y'w^3)^2 = (x'w^2)^3 + b - => y'^2 = x'^3 + b / w^6 ; w^6 = xi - => y'^2 = x'^3 + twist_b; - */ - Fp2 twist_b; - util::TwistBtype twist_b_type; - mpz_class exp_c0; - mpz_class exp_c1; - mpz_class exp_c2; - mpz_class exp_c3; - - // Loop parameter for the Miller loop part of opt. ate pairing. - util::SignVec siTbl; - size_t precomputedQcoeffSize; - bool useNAF; - util::SignVec zReplTbl; - - void initCommonParam(const CurveParam& cp, fp::Mode mode) - { - this->cp = cp; - isBLS12 = cp.curveType == mclBls12_CurveFp381; - z = mpz_class(cp.z); - isNegative = z < 0; - if (isNegative) { - abs_z = -z; - } else { - abs_z = z; - } - if (isBLS12) { - mpz_class z2 = z * z; - mpz_class z4 = z2 * z2; - r = z4 - z2 + 1; - p = z - 1; - p = p * p * r / 3 + z; - } else { - const int pCoff[] = { 1, 6, 24, 36, 36 }; - const int rCoff[] = { 1, 6, 18, 36, 36 }; - p = util::evalPoly(z, pCoff); - assert((p % 6) == 1); - r = util::evalPoly(z, rCoff); - } - Fp::init(p, mode); - Fp2::init(cp.xi_a); - Fp2 xi(cp.xi_a, 1); - if (cp.isMtype) { - twist_b = Fp2(cp.b) * xi; - } else { - twist_b = Fp2(cp.b) / xi; - } - if (twist_b == Fp2(1, -1)) { - twist_b_type = tb_1m1i; - } else if (twist_b == Fp2(1, -2)) { - twist_b_type = tb_1m2i; - } else { - twist_b_type = tb_generic; - } - G1::init(0, cp.b, mcl::ec::Proj); - G2::init(0, twist_b, mcl::ec::Proj); - G2::setOrder(r); - - const mpz_class largest_c = isBLS12 ? abs_z : gmp::abs(z * 6 + 2); - useNAF = gmp::getNAF(siTbl, largest_c); - precomputedQcoeffSize = util::getPrecomputeQcoeffSize(siTbl); - gmp::getNAF(zReplTbl, gmp::abs(z)); - if (isBLS12) { - mpz_class z2 = z * z; - mpz_class z3 = z2 * z; - mpz_class z4 = z3 * z; - mpz_class z5 = z4 * z; - exp_c0 = z5 - 2 * z4 + 2 * z2 - z + 3; - exp_c1 = z4 - 2 * z3 + 2 * z - 1; - exp_c2 = z3 - 2 * z2 + z; - exp_c3 = z2 - 2 * z + 1; - } else { - exp_c0 = -2 + z * (-18 + z * (-30 - 36 * z)); - exp_c1 = 1 + z * (-12 + z * (-18 - 36 * z)); - exp_c2 = 6 * z * z + 1; - } - } -}; - -/* - l = (a, b, c) => (a, b * P.y, c * P.x) -*/ -template<class Fp6, class G1> -void updateLine(Fp6& l, const G1& P) -{ - l.b.a *= P.y; - l.b.b *= P.y; - l.c.a *= P.x; - l.c.b *= P.x; -} - -/* - twisted Frobenius for G2 -*/ -template<class G2> -struct HaveFrobenius : public G2 { - typedef typename G2::Fp Fp2; - static Fp2 g2; - static Fp2 g3; - /* - BN254 is Dtype - BLS12-381 is Mtype - */ - static void init(bool isMtype) - { - g2 = Fp2::get_gTbl()[0]; - g3 = Fp2::get_gTbl()[3]; - if (isMtype) { - Fp2::inv(g2, g2); - Fp2::inv(g3, g3); - } - } - /* - FrobeniusOnTwist for Dtype - p mod 6 = 1, w^6 = xi - Frob(x', y') = phi Frob phi^-1(x', y') - = phi Frob (x' w^2, y' w^3) - = phi (x'^p w^2p, y'^p w^3p) - = (F(x') w^2(p - 1), F(y') w^3(p - 1)) - = (F(x') g^2, F(y') g^3) - - FrobeniusOnTwist for Dtype - use (1/g) instead of g - */ - static void Frobenius(G2& D, const G2& S) - { - Fp2::Frobenius(D.x, S.x); - Fp2::Frobenius(D.y, S.y); - Fp2::Frobenius(D.z, S.z); - D.x *= g2; - D.y *= g3; - } - static void Frobenius2(G2& D, const G2& S) - { - Frobenius(D, S); - Frobenius(D, D); - } - static void Frobenius3(G2& D, const G2& S) - { - Frobenius(D, S); - Frobenius(D, D); - Frobenius(D, D); - } - static void Frobenius(HaveFrobenius& y, const HaveFrobenius& x) - { - Frobenius(static_cast<G2&>(y), static_cast<const G2&>(x)); - } -}; -template<class G2> -typename G2::Fp HaveFrobenius<G2>::g2; -template<class G2> -typename G2::Fp HaveFrobenius<G2>::g3; - -template<class CT, class Fp, class Param> -struct BasePairingT { - typedef mcl::Fp2T<Fp> Fp2; - typedef mcl::Fp6T<Fp> Fp6; - typedef mcl::Fp12T<Fp> Fp12; - typedef mcl::EcT<Fp> G1; - typedef mcl::EcT<Fp2> G2; - typedef util::HaveFrobenius<G2> G2withF; - typedef mcl::FpDblT<Fp> FpDbl; - typedef mcl::Fp2DblT<Fp> Fp2Dbl; - static Param param; - - struct Compress { - Fp12& z_; - Fp2& g1_; - Fp2& g2_; - Fp2& g3_; - Fp2& g4_; - Fp2& g5_; - // z is output area - Compress(Fp12& z, const Fp12& x) - : z_(z) - , g1_(z.getFp2()[4]) - , g2_(z.getFp2()[3]) - , g3_(z.getFp2()[2]) - , g4_(z.getFp2()[1]) - , g5_(z.getFp2()[5]) - { - g2_ = x.getFp2()[3]; - g3_ = x.getFp2()[2]; - g4_ = x.getFp2()[1]; - g5_ = x.getFp2()[5]; - } - Compress(Fp12& z, const Compress& c) - : z_(z) - , g1_(z.getFp2()[4]) - , g2_(z.getFp2()[3]) - , g3_(z.getFp2()[2]) - , g4_(z.getFp2()[1]) - , g5_(z.getFp2()[5]) - { - g2_ = c.g2_; - g3_ = c.g3_; - g4_ = c.g4_; - g5_ = c.g5_; - } - void decompressBeforeInv(Fp2& nume, Fp2& denomi) const - { - assert(&nume != &denomi); - - if (g2_.isZero()) { - Fp2::add(nume, g4_, g4_); - nume *= g5_; - denomi = g3_; - } else { - Fp2 t; - Fp2::sqr(nume, g5_); - Fp2::mul_xi(denomi, nume); - Fp2::sqr(nume, g4_); - Fp2::sub(t, nume, g3_); - t += t; - t += nume; - Fp2::add(nume, denomi, t); - Fp2::divBy4(nume, nume); - denomi = g2_; - } - } - - // output to z - void decompressAfterInv() - { - Fp2& g0 = z_.getFp2()[0]; - Fp2 t0, t1; - // Compute g0. - Fp2::sqr(t0, g1_); - Fp2::mul(t1, g3_, g4_); - t0 -= t1; - t0 += t0; - t0 -= t1; - Fp2::mul(t1, g2_, g5_); - t0 += t1; - Fp2::mul_xi(g0, t0); - g0.a += Fp::one(); - } - - public: - void decompress() // for test - { - Fp2 nume, denomi; - decompressBeforeInv(nume, denomi); - Fp2::inv(denomi, denomi); - g1_ = nume * denomi; // g1 is recoverd. - decompressAfterInv(); - } - /* - 2275clk * 186 = 423Kclk QQQ - */ - static void squareC(Compress& z) - { - Fp2 t0, t1, t2; - Fp2Dbl T0, T1, T2, T3; - Fp2Dbl::sqrPre(T0, z.g4_); - Fp2Dbl::sqrPre(T1, z.g5_); - Fp2Dbl::mul_xi(T2, T1); - T2 += T0; - Fp2Dbl::mod(t2, T2); - Fp2::add(t0, z.g4_, z.g5_); - Fp2Dbl::sqrPre(T2, t0); - T0 += T1; - T2 -= T0; - Fp2Dbl::mod(t0, T2); - Fp2::add(t1, z.g2_, z.g3_); - Fp2Dbl::sqrPre(T3, t1); - Fp2Dbl::sqrPre(T2, z.g2_); - Fp2::mul_xi(t1, t0); - z.g2_ += t1; - z.g2_ += z.g2_; - z.g2_ += t1; - Fp2::sub(t1, t2, z.g3_); - t1 += t1; - Fp2Dbl::sqrPre(T1, z.g3_); - Fp2::add(z.g3_, t1, t2); - Fp2Dbl::mul_xi(T0, T1); - T0 += T2; - Fp2Dbl::mod(t0, T0); - Fp2::sub(z.g4_, t0, z.g4_); - z.g4_ += z.g4_; - z.g4_ += t0; - Fp2Dbl::addPre(T2, T2, T1); - T3 -= T2; - Fp2Dbl::mod(t0, T3); - z.g5_ += t0; - z.g5_ += z.g5_; - z.g5_ += t0; - } - static void square_n(Compress& z, int n) - { - for (int i = 0; i < n; i++) { - squareC(z); - } - } - /* - Exponentiation over compression for: - z = x^Param::z.abs() - */ - static void fixed_power(Fp12& z, const Fp12& x) - { - if (x.isOne()) { - z = 1; - return; - } - assert(param.cp.curveType == mclBn_CurveFp254BNb); - Fp12 x_org = x; - Fp12 d62; - Fp2 c55nume, c55denomi, c62nume, c62denomi; - Compress c55(z, x); - Compress::square_n(c55, 55); - c55.decompressBeforeInv(c55nume, c55denomi); - Compress c62(d62, c55); - Compress::square_n(c62, 62 - 55); - c62.decompressBeforeInv(c62nume, c62denomi); - Fp2 acc; - Fp2::mul(acc, c55denomi, c62denomi); - Fp2::inv(acc, acc); - Fp2 t; - Fp2::mul(t, acc, c62denomi); - Fp2::mul(c55.g1_, c55nume, t); - c55.decompressAfterInv(); - Fp2::mul(t, acc, c55denomi); - Fp2::mul(c62.g1_, c62nume, t); - c62.decompressAfterInv(); - z *= x_org; - z *= d62; - } - }; - /* - y = x^z if z > 0 - = unitaryInv(x^(-z)) if z < 0 - */ - static void pow_z(Fp12& y, const Fp12& x) - { -#if 1 - if (param.cp.curveType == mclBn_CurveFp254BNb) { - Compress::fixed_power(y, x); - } else { - Fp12 orgX = x; - y = x; - Fp12 conj; - conj.a = x.a; - Fp6::neg(conj.b, x.b); - for (size_t i = 1; i < param.zReplTbl.size(); i++) { - fasterSqr(y, y); - if (param.zReplTbl[i] > 0) { - y *= orgX; - } else if (param.zReplTbl[i] < 0) { - y *= conj; - } - } - } -#else - Fp12::pow(y, x, param.abs_z); -#endif - if (param.isNegative) { - Fp12::unitaryInv(y, y); - } - } - static void mul_b_div_xi(Fp2& y, const Fp2& x) - { - switch (param.twist_b_type) { - case util::tb_1m1i: - /* - b / xi = 1 - 1i - (a + bi)(1 - 1i) = (a + b) + (b - a)i - */ - { - Fp t; - Fp::add(t, x.a, x.b); - Fp::sub(y.b, x.b, x.a); - y.a = t; - } - return; - case util::tb_1m2i: - /* - b / xi = 1 - 2i - (a + bi)(1 - 2i) = (a + 2b) + (b - 2a)i - */ - { - Fp t; - Fp::sub(t, x.b, x.a); - t -= x.a; - Fp::add(y.a, x.a, x.b); - y.a += x.b; - y.b = t; - } - return; - case util::tb_generic: - Fp2::mul(y, x, param.twist_b); - return; - } - } - - static void dblLineWithoutP(Fp6& l, G2& Q) - { - Fp2 t0, t1, t2, t3, t4, t5; - Fp2Dbl T0, T1; - Fp2::sqr(t0, Q.z); - Fp2::mul(t4, Q.x, Q.y); - Fp2::sqr(t1, Q.y); - Fp2::add(t3, t0, t0); - Fp2::divBy2(t4, t4); - Fp2::add(t5, t0, t1); - t0 += t3; - mul_b_div_xi(t2, t0); - Fp2::sqr(t0, Q.x); - Fp2::add(t3, t2, t2); - t3 += t2; - Fp2::sub(Q.x, t1, t3); - t3 += t1; - Q.x *= t4; - Fp2::divBy2(t3, t3); - Fp2Dbl::sqrPre(T0, t3); - Fp2Dbl::sqrPre(T1, t2); - Fp2Dbl::sub(T0, T0, T1); - Fp2Dbl::add(T1, T1, T1); - Fp2Dbl::sub(T0, T0, T1); - Fp2::add(t3, Q.y, Q.z); - Fp2Dbl::mod(Q.y, T0); - Fp2::sqr(t3, t3); - t3 -= t5; - Fp2::mul(Q.z, t1, t3); - Fp2::sub(l.a, t2, t1); - l.c = t0; - l.b = t3; - } - static void addLineWithoutP(Fp6& l, G2& R, const G2& Q) - { - Fp2 t1, t2, t3, t4; - Fp2Dbl T1, T2; - Fp2::mul(t1, R.z, Q.x); - Fp2::mul(t2, R.z, Q.y); - Fp2::sub(t1, R.x, t1); - Fp2::sub(t2, R.y, t2); - Fp2::sqr(t3, t1); - Fp2::mul(R.x, t3, R.x); - Fp2::sqr(t4, t2); - t3 *= t1; - t4 *= R.z; - t4 += t3; - t4 -= R.x; - t4 -= R.x; - R.x -= t4; - Fp2Dbl::mulPre(T1, t2, R.x); - Fp2Dbl::mulPre(T2, t3, R.y); - Fp2Dbl::sub(T2, T1, T2); - Fp2Dbl::mod(R.y, T2); - Fp2::mul(R.x, t1, t4); - Fp2::mul(R.z, t3, R.z); - Fp2::neg(l.c, t2); - Fp2Dbl::mulPre(T1, t2, Q.x); - Fp2Dbl::mulPre(T2, t1, Q.y); - Fp2Dbl::sub(T1, T1, T2); - l.b = t1; - Fp2Dbl::mod(l.a, T1); - } - static void dblLine(Fp6& l, G2& Q, const G1& P) - { - dblLineWithoutP(l, Q); - util::updateLine(l, P); - } - static void addLine(Fp6& l, G2& R, const G2& Q, const G1& P) - { - addLineWithoutP(l, R, Q); - util::updateLine(l, P); - } - static void mulFp6cb_by_G1xy(Fp6& y, const Fp6& x, const G1& P) - { - assert(P.isNormalized()); - if (&y != &x) y.a = x.a; - Fp2::mulFp(y.c, x.c, P.x); - Fp2::mulFp(y.b, x.b, P.y); - } - - /* - x = a + bv + cv^2 - y = (y0, y4, y2) -> (y0, 0, y2, 0, y4, 0) - z = xy = (a + bv + cv^2)(d + ev) - = (ad + ce xi) + ((a + b)(d + e) - ad - be)v + (be + cd)v^2 - */ - static void Fp6mul_01(Fp6& z, const Fp6& x, const Fp2& d, const Fp2& e) - { - const Fp2& a = x.a; - const Fp2& b = x.b; - const Fp2& c = x.c; - Fp2 t0, t1; - Fp2Dbl AD, CE, BE, CD, T; - Fp2Dbl::mulPre(AD, a, d); - Fp2Dbl::mulPre(CE, c, e); - Fp2Dbl::mulPre(BE, b, e); - Fp2Dbl::mulPre(CD, c, d); - Fp2::add(t0, a, b); - Fp2::add(t1, d, e); - Fp2Dbl::mulPre(T, t0, t1); - T -= AD; - T -= BE; - Fp2Dbl::mod(z.b, T); - Fp2Dbl::mul_xi(CE, CE); - AD += CE; - Fp2Dbl::mod(z.a, AD); - BE += CD; - Fp2Dbl::mod(z.c, BE); - } - /* - input - z = (z0 + z1v + z2v^2) + (z3 + z4v + z5v^2)w = Z0 + Z1w - 0 3 4 - x = (a, b, c) -> (b, 0, 0, c, a, 0) = X0 + X1w - X0 = b = (b, 0, 0) - X1 = c + av = (c, a, 0) - w^2 = v, v^3 = xi - output - z <- zx = (Z0X0 + Z1X1v) + ((Z0 + Z1)(X0 + X1) - Z0X0 - Z1X1)w - Z0X0 = Z0 b - Z1X1 = Z1 (c, a, 0) - (Z0 + Z1)(X0 + X1) = (Z0 + Z1) (b + c, a, 0) - */ - static void mul_403(Fp12& z, const Fp6& x) - { - const Fp2& a = x.a; - const Fp2& b = x.b; - const Fp2& c = x.c; -#if 0 - Fp6& z0 = z.a; - Fp6& z1 = z.b; - Fp6 z0x0, z1x1, t0; - Fp2 t1; - Fp2::add(t1, x.b, c); - Fp6::add(t0, z0, z1); - Fp2::mul(z0x0.a, z0.a, b); - Fp2::mul(z0x0.b, z0.b, b); - Fp2::mul(z0x0.c, z0.c, b); - Fp6mul_01(z1x1, z1, c, a); - Fp6mul_01(t0, t0, t1, a); - Fp6::sub(z.b, t0, z0x0); - z.b -= z1x1; - // a + bv + cv^2 = cxi + av + bv^2 - Fp2::mul_xi(z1x1.c, z1x1.c); - Fp2::add(z.a.a, z0x0.a, z1x1.c); - Fp2::add(z.a.b, z0x0.b, z1x1.a); - Fp2::add(z.a.c, z0x0.c, z1x1.b); -#else - Fp2& z0 = z.a.a; - Fp2& z1 = z.a.b; - Fp2& z2 = z.a.c; - Fp2& z3 = z.b.a; - Fp2& z4 = z.b.b; - Fp2& z5 = z.b.c; - Fp2Dbl Z0B, Z1B, Z2B, Z3C, Z4C, Z5C; - Fp2Dbl T0, T1, T2, T3, T4, T5; - Fp2 bc, t; - Fp2::addPre(bc, b, c); - Fp2::addPre(t, z5, z2); - Fp2Dbl::mulPre(T5, t, bc); - Fp2Dbl::mulPre(Z5C, z5, c); - Fp2Dbl::mulPre(Z2B, z2, b); - Fp2Dbl::sub(T5, T5, Z5C); - Fp2Dbl::sub(T5, T5, Z2B); - Fp2Dbl::mulPre(T0, z1, a); - T5 += T0; - - Fp2::addPre(t, z4, z1); - Fp2Dbl::mulPre(T4, t, bc); - Fp2Dbl::mulPre(Z4C, z4, c); - Fp2Dbl::mulPre(Z1B, z1, b); - Fp2Dbl::sub(T4, T4, Z4C); - Fp2Dbl::sub(T4, T4, Z1B); - Fp2Dbl::mulPre(T0, z0, a); - T4 += T0; - - Fp2::addPre(t, z3, z0); - Fp2Dbl::mulPre(T3, t, bc); - Fp2Dbl::mulPre(Z3C, z3, c); - Fp2Dbl::mulPre(Z0B, z0, b); - Fp2Dbl::sub(T3, T3, Z3C); - Fp2Dbl::sub(T3, T3, Z0B); - Fp2::mul_xi(t, z2); - Fp2Dbl::mulPre(T0, t, a); - T3 += T0; - - Fp2Dbl::mulPre(T2, z3, a); - T2 += Z2B; - T2 += Z4C; - - Fp2::mul_xi(t, z5); - Fp2Dbl::mulPre(T1, t, a); - T1 += Z1B; - T1 += Z3C; - - Fp2Dbl::mulPre(T0, z4, a); - T0 += Z5C; - Fp2Dbl::mul_xi(T0, T0); - T0 += Z0B; - - Fp2Dbl::mod(z0, T0); - Fp2Dbl::mod(z1, T1); - Fp2Dbl::mod(z2, T2); - Fp2Dbl::mod(z3, T3); - Fp2Dbl::mod(z4, T4); - Fp2Dbl::mod(z5, T5); -#endif - } - /* - input - z = (z0 + z1v + z2v^2) + (z3 + z4v + z5v^2)w = Z0 + Z1w - 0 1 4 - x = (a, b, c) -> (a, c, 0, 0, b, 0) = X0 + X1w - X0 = (a, c, 0) - X1 = (0, b, 0) - w^2 = v, v^3 = xi - output - z <- zx = (Z0X0 + Z1X1v) + ((Z0 + Z1)(X0 + X1) - Z0X0 - Z1X1)w - Z0X0 = Z0 (a, c, 0) - Z1X1 = Z1 (0, b, 0) = Z1 bv - (Z0 + Z1)(X0 + X1) = (Z0 + Z1) (a, b + c, 0) - - (a + bv + cv^2)v = c xi + av + bv^2 - */ - static void mul_041(Fp12& z, const Fp6& x) - { - const Fp2& a = x.a; - const Fp2& b = x.b; - const Fp2& c = x.c; - Fp6& z0 = z.a; - Fp6& z1 = z.b; - Fp6 z0x0, z1x1, t0; - Fp2 t1; - Fp2::mul(z1x1.a, z1.c, b); - Fp2::mul_xi(z1x1.a, z1x1.a); - Fp2::mul(z1x1.b, z1.a, b); - Fp2::mul(z1x1.c, z1.b, b); - Fp2::add(t1, x.b, c); - Fp6::add(t0, z0, z1); - Fp6mul_01(z0x0, z0, a, c); - Fp6mul_01(t0, t0, a, t1); - Fp6::sub(z.b, t0, z0x0); - z.b -= z1x1; - // a + bv + cv^2 = cxi + av + bv^2 - Fp2::mul_xi(z1x1.c, z1x1.c); - Fp2::add(z.a.a, z0x0.a, z1x1.c); - Fp2::add(z.a.b, z0x0.b, z1x1.a); - Fp2::add(z.a.c, z0x0.c, z1x1.b); - } - /* - input - z = (z0 + z1v + z2v^2) + (z3 + z4v + z5v^2)w - x = (a, b, c) -> (a, 0, c, 0, b, 0) - output - z <- zx = (z0a + (z1c + z4b)xi) + (z1a + (z2c + z5b)xi)v + (z0c + z2a + z3b)v^2 - + (z3a + (z2b + z4c)xi)w + (z0b + z4a + z5cxi)vw + (z1b + z3c + z5a)v^2w - - z1c + z4b = (z1 + z4)(c + b) - z1b - z4c - z2c + z5b = (z2 + z5)(c + b) - z2b - z5c - z0c + z3b = (z0 + z3)(c + b) - z0b - z3c - */ - static void mulSparse(Fp12& z, const Fp6& x) - { - if (param.cp.isMtype) { - mul_041(z, x); - } else { - mul_403(z, x); - } - } - static void convertFp6toFp12(Fp12& y, const Fp6& x) - { - y.clear(); - if (param.cp.isMtype) { - // (a, b, c) -> (a, c, 0, 0, b, 0) - y.a.a = x.a; - y.b.b = x.b; - y.a.b = x.c; - } else { - // (a, b, c) -> (b, 0, 0, c, a, 0) - y.b.b = x.a; - y.a.a = x.b; - y.b.a = x.c; - } - } - static void mulSparse2(Fp12& z, const Fp6& x, const Fp6& y) - { - convertFp6toFp12(z, x); - mulSparse(z, y); - } - /* - Faster Squaring in the Cyclotomic Subgroup of Sixth Degree Extensions - Robert Granger, Michael Scott - */ - static void sqrFp4(Fp2& z0, Fp2& z1, const Fp2& x0, const Fp2& x1) - { -#if 1 - Fp2Dbl T0, T1, T2; - Fp2Dbl::sqrPre(T0, x0); - Fp2Dbl::sqrPre(T1, x1); - Fp2Dbl::mul_xi(T2, T1); - Fp2Dbl::add(T2, T2, T0); - Fp2::add(z1, x0, x1); - Fp2Dbl::mod(z0, T2); - Fp2Dbl::sqrPre(T2, z1); - Fp2Dbl::sub(T2, T2, T0); - Fp2Dbl::sub(T2, T2, T1); - Fp2Dbl::mod(z1, T2); -#else - Fp2 t0, t1, t2; - Fp2::sqr(t0, x0); - Fp2::sqr(t1, x1); - Fp2::mul_xi(z0, t1); - z0 += t0; - Fp2::add(z1, x0, x1); - Fp2::sqr(z1, z1); - z1 -= t0; - z1 -= t1; -#endif - } - static void fasterSqr(Fp12& y, const Fp12& x) - { -#if 0 - Fp12::sqr(y, x); -#else - const Fp2& x0(x.a.a); - const Fp2& x4(x.a.b); - const Fp2& x3(x.a.c); - const Fp2& x2(x.b.a); - const Fp2& x1(x.b.b); - const Fp2& x5(x.b.c); - Fp2& y0(y.a.a); - Fp2& y4(y.a.b); - Fp2& y3(y.a.c); - Fp2& y2(y.b.a); - Fp2& y1(y.b.b); - Fp2& y5(y.b.c); - Fp2 t0, t1; - sqrFp4(t0, t1, x0, x1); - Fp2::sub(y0, t0, x0); - y0 += y0; - y0 += t0; - Fp2::add(y1, t1, x1); - y1 += y1; - y1 += t1; - Fp2 t2, t3; - sqrFp4(t0, t1, x2, x3); - sqrFp4(t2, t3, x4, x5); - Fp2::sub(y4, t0, x4); - y4 += y4; - y4 += t0; - Fp2::add(y5, t1, x5); - y5 += y5; - y5 += t1; - Fp2::mul_xi(t0, t3); - Fp2::add(y2, t0, x2); - y2 += y2; - y2 += t0; - Fp2::sub(y3, t2, x3); - y3 += y3; - y3 += t2; -#endif - } - static void mapToCyclotomic(Fp12& y, const Fp12& x) - { - Fp12 z; - Fp12::Frobenius2(z, x); // z = x^(p^2) - z *= x; // x^(p^2 + 1) - Fp12::inv(y, z); - Fp6::neg(z.b, z.b); // z^(p^6) = conjugate of z - y *= z; - } - /* - y = x^((p^12 - 1) / r) - (p^12 - 1) / r = (p^2 + 1) (p^6 - 1) (p^4 - p^2 + 1)/r - (a + bw)^(p^6) = a - bw in Fp12 - (p^4 - p^2 + 1)/r = c0 + c1 p + c2 p^2 + p^3 - */ - static void finalExp(Fp12& y, const Fp12& x) - { -#if 1 - mapToCyclotomic(y, x); -#else - const mpz_class& p = param.p; - mpz_class p2 = p * p; - mpz_class p4 = p2 * p2; - Fp12::pow(y, x, p2 + 1); - Fp12::pow(y, y, p4 * p2 - 1); -#endif - CT::expHardPart(y, y); - } - /* - remark : returned value is NOT on a curve - */ - static G1 makeAdjP(const G1& P) - { - G1 adjP; - Fp::add(adjP.x, P.x, P.x); - adjP.x += P.x; - Fp::neg(adjP.y, P.y); - adjP.z = 1; - return adjP; - } - static void millerLoop(Fp12& f, const G1& P_, const G2& Q_) - { - G1 P(P_); - G2 Q(Q_); - P.normalize(); - Q.normalize(); - if (Q.isZero()) { - f = 1; - return; - } - assert(param.siTbl[1] == 1); - G2 T = Q; - G2 negQ; - if (param.useNAF) { - G2::neg(negQ, Q); - } - Fp6 d, e, l; - d = e = l = 1; - G1 adjP = makeAdjP(P); - dblLine(d, T, adjP); - addLine(l, T, Q, P); - mulSparse2(f, d, l); - for (size_t i = 2; i < param.siTbl.size(); i++) { - dblLine(l, T, adjP); - Fp12::sqr(f, f); - mulSparse(f, l); - if (param.siTbl[i]) { - if (param.siTbl[i] > 0) { - addLine(l, T, Q, P); - } else { - addLine(l, T, negQ, P); - } - mulSparse(f, l); - } - } - if (param.z < 0) { - G2::neg(T, T); - Fp6::neg(f.b, f.b); - } - if (param.isBLS12) return; - G2 Q1, Q2; - G2withF::Frobenius(Q1, Q); - G2withF::Frobenius(Q2, Q1); - G2::neg(Q2, Q2); - addLine(d, T, Q1, P); - addLine(e, T, Q2, P); - Fp12 ft; - mulSparse2(ft, d, e); - f *= ft; - } - static void pairing(Fp12& f, const G1& P, const G2& Q) - { - millerLoop(f, P, Q); - finalExp(f, f); - } - /* - millerLoop(e, P, Q) is same as the following - std::vector<Fp6> Qcoeff; - precomputeG2(Qcoeff, Q); - precomputedMillerLoop(e, P, Qcoeff); - */ - static void precomputeG2(std::vector<Fp6>& Qcoeff, const G2& Q) - { - Qcoeff.resize(param.precomputedQcoeffSize); - precomputeG2(Qcoeff.data(), Q); - } - /* - allocate param.precomputedQcoeffSize elements of Fp6 for Qcoeff - */ - static void precomputeG2(Fp6 *Qcoeff, const G2& Q_) - { - size_t idx = 0; - G2 Q(Q_); - Q.normalize(); - if (Q.isZero()) { - for (size_t i = 0; i < param.precomputedQcoeffSize; i++) { - Qcoeff[i] = 1; - } - return; - } - G2 T = Q; - G2 negQ; - if (param.useNAF) { - G2::neg(negQ, Q); - } - assert(param.siTbl[1] == 1); - dblLineWithoutP(Qcoeff[idx++], T); - addLineWithoutP(Qcoeff[idx++], T, Q); - for (size_t i = 2; i < param.siTbl.size(); i++) { - dblLineWithoutP(Qcoeff[idx++], T); - if (param.siTbl[i]) { - if (param.siTbl[i] > 0) { - addLineWithoutP(Qcoeff[idx++], T, Q); - } else { - addLineWithoutP(Qcoeff[idx++], T, negQ); - } - } - } - if (param.z < 0) { - G2::neg(T, T); - } - if (param.isBLS12) return; - G2 Q1, Q2; - G2withF::Frobenius(Q1, Q); - G2withF::Frobenius(Q2, Q1); - G2::neg(Q2, Q2); - addLineWithoutP(Qcoeff[idx++], T, Q1); - addLineWithoutP(Qcoeff[idx++], T, Q2); - assert(idx == param.precomputedQcoeffSize); - } - static void precomputedMillerLoop(Fp12& f, const G1& P, const std::vector<Fp6>& Qcoeff) - { - precomputedMillerLoop(f, P, Qcoeff.data()); - } - static void precomputedMillerLoop(Fp12& f, const G1& P_, const Fp6* Qcoeff) - { - G1 P(P_); - P.normalize(); - G1 adjP = makeAdjP(P); - size_t idx = 0; - Fp6 d, e, l; - mulFp6cb_by_G1xy(d, Qcoeff[idx], adjP); - idx++; - - mulFp6cb_by_G1xy(e, Qcoeff[idx], P); - idx++; - mulSparse2(f, d, e); - for (size_t i = 2; i < param.siTbl.size(); i++) { - mulFp6cb_by_G1xy(l, Qcoeff[idx], adjP); - idx++; - Fp12::sqr(f, f); - mulSparse(f, l); - if (param.siTbl[i]) { - mulFp6cb_by_G1xy(l, Qcoeff[idx], P); - idx++; - mulSparse(f, l); - } - } - if (param.z < 0) { - Fp6::neg(f.b, f.b); - } - if (param.isBLS12) return; - mulFp6cb_by_G1xy(d, Qcoeff[idx], P); - idx++; - mulFp6cb_by_G1xy(e, Qcoeff[idx], P); - idx++; - Fp12 ft; - mulSparse2(ft, d, e); - f *= ft; - } - /* - f = MillerLoop(P1, Q1) x MillerLoop(P2, Q2) - */ - static void precomputedMillerLoop2(Fp12& f, const G1& P1, const std::vector<Fp6>& Q1coeff, const G1& P2, const std::vector<Fp6>& Q2coeff) - { - precomputedMillerLoop2(f, P1, Q1coeff.data(), P2, Q2coeff.data()); - } - static void precomputedMillerLoop2(Fp12& f, const G1& P1_, const Fp6* Q1coeff, const G1& P2_, const Fp6* Q2coeff) - { - G1 P1(P1_), P2(P2_); - P1.normalize(); - P2.normalize(); - G1 adjP1 = makeAdjP(P1); - G1 adjP2 = makeAdjP(P2); - size_t idx = 0; - Fp6 d1, d2, e1, e2, l1, l2; - mulFp6cb_by_G1xy(d1, Q1coeff[idx], adjP1); - mulFp6cb_by_G1xy(d2, Q2coeff[idx], adjP2); - idx++; - - Fp12 f1, f2; - mulFp6cb_by_G1xy(e1, Q1coeff[idx], P1); - mulSparse2(f1, d1, e1); - - mulFp6cb_by_G1xy(e2, Q2coeff[idx], P2); - mulSparse2(f2, d2, e2); - Fp12::mul(f, f1, f2); - idx++; - for (size_t i = 2; i < param.siTbl.size(); i++) { - mulFp6cb_by_G1xy(l1, Q1coeff[idx], adjP1); - mulFp6cb_by_G1xy(l2, Q2coeff[idx], adjP2); - idx++; - Fp12::sqr(f, f); - mulSparse2(f1, l1, l2); - f *= f1; - if (param.siTbl[i]) { - mulFp6cb_by_G1xy(l1, Q1coeff[idx], P1); - mulFp6cb_by_G1xy(l2, Q2coeff[idx], P2); - idx++; - mulSparse2(f1, l1, l2); - f *= f1; - } - } - if (param.z < 0) { - Fp6::neg(f.b, f.b); - } - if (param.isBLS12) return; - mulFp6cb_by_G1xy(d1, Q1coeff[idx], P1); - mulFp6cb_by_G1xy(d2, Q2coeff[idx], P2); - idx++; - mulFp6cb_by_G1xy(e1, Q1coeff[idx], P1); - mulFp6cb_by_G1xy(e2, Q2coeff[idx], P2); - idx++; - mulSparse2(f1, d1, e1); - mulSparse2(f2, d2, e2); - f *= f1; - f *= f2; - } - static void mapToG1(G1& P, const Fp& x) { param.mapTo.calcG1(P, x); } - static void mapToG2(G2& P, const Fp2& x) { param.mapTo.calcG2(P, x); } - static void hashAndMapToG1(G1& P, const void *buf, size_t bufSize) - { - Fp t; - t.setHashOf(buf, bufSize); - mapToG1(P, t); - } - static void hashAndMapToG2(G2& P, const void *buf, size_t bufSize) - { - Fp2 t; - t.a.setHashOf(buf, bufSize); - t.b.clear(); - mapToG2(P, t); - } - static void hashAndMapToG1(G1& P, const std::string& str) - { - hashAndMapToG1(P, str.c_str(), str.size()); - } - static void hashAndMapToG2(G2& P, const std::string& str) - { - hashAndMapToG2(P, str.c_str(), str.size()); - } -}; - -template<class CT, class Fp, class Param> -Param BasePairingT<CT, Fp, Param>::param; - -} // mcl::util - -} // mcl - diff --git a/include/mcl/she.h b/include/mcl/she.h index 0e99c97..d8f5514 100644 --- a/include/mcl/she.h +++ b/include/mcl/she.h @@ -209,6 +209,12 @@ MCLSHE_DLL_API int sheIsZeroG2(const sheSecretKey *sec, const sheCipherTextG2 *c MCLSHE_DLL_API int sheIsZeroGT(const sheSecretKey *sec, const sheCipherTextGT *c); // return 0 if success +// y = -x +MCLSHE_DLL_API int sheNegG1(sheCipherTextG1 *y, const sheCipherTextG1 *x); +MCLSHE_DLL_API int sheNegG2(sheCipherTextG2 *y, const sheCipherTextG2 *x); +MCLSHE_DLL_API int sheNegGT(sheCipherTextGT *y, const sheCipherTextGT *x); + +// return 0 if success // z = x + y MCLSHE_DLL_API int sheAddG1(sheCipherTextG1 *z, const sheCipherTextG1 *x, const sheCipherTextG1 *y); MCLSHE_DLL_API int sheAddG2(sheCipherTextG2 *z, const sheCipherTextG2 *x, const sheCipherTextG2 *y); diff --git a/include/mcl/she.hpp b/include/mcl/she.hpp index c40288c..285ee3d 100644 --- a/include/mcl/she.hpp +++ b/include/mcl/she.hpp @@ -37,13 +37,15 @@ namespace bn_current = mcl::bn512; namespace mcl { namespace she { +using namespace mcl::bn_current; + namespace local { #ifndef MCLSHE_WIN_SIZE #define MCLSHE_WIN_SIZE 10 #endif static const size_t winSize = MCLSHE_WIN_SIZE; -static const size_t defaultTryNum = 1024; +static const size_t defaultTryNum = 2048; struct KeyCount { uint32_t key; @@ -255,7 +257,7 @@ public: template<class OutputStream> void save(OutputStream& os) const { - cybozu::save(os, bn_current::BN::param.cp.curveType); + cybozu::save(os, BN::param.cp.curveType); cybozu::writeChar(os, GtoChar<G>()); cybozu::save(os, kcv_.size()); cybozu::write(os, &kcv_[0], sizeof(kcv_[0]) * kcv_.size()); @@ -276,7 +278,7 @@ public: { int curveType; cybozu::load(curveType, is); - if (curveType != bn_current::BN::param.cp.curveType) throw cybozu::Exception("HashTable:bad curveType") << curveType; + if (curveType != BN::param.cp.curveType) throw cybozu::Exception("HashTable:bad curveType") << curveType; char c = 0; if (!cybozu::readChar(&c, is) || c != GtoChar<G>()) throw cybozu::Exception("HashTable:bad c") << (int)c; size_t kcvSize; @@ -325,12 +327,8 @@ int log(const G& P, const G& xP) } // mcl::she::local -template<class BN, class Fr> +template<size_t dummyInpl = 0> struct SHET { - typedef typename BN::G1 G1; - typedef typename BN::G2 G2; - typedef typename BN::Fp12 GT; - class SecretKey; class PublicKey; class PrecomputedPublicKey; @@ -342,7 +340,7 @@ struct SHET { static G1 P_; static G2 Q_; static GT ePQ_; // e(P, Q) - static std::vector<bn_current::Fp6> Qcoeff_; + static std::vector<Fp6> Qcoeff_; static local::HashTable<G1> PhashTbl_; static local::HashTable<G2> QhashTbl_; static mcl::fp::WindowMethod<G2> Qwm_; @@ -440,19 +438,19 @@ private: static void doubleMillerLoop(GT& g1, GT& g2, const G1& P1, const G1& P2, const G2& Q) { #if 1 - std::vector<bn_current::Fp6> Qcoeff; - BN::precomputeG2(Qcoeff, Q); - BN::precomputedMillerLoop(g1, P1, Qcoeff); - BN::precomputedMillerLoop(g2, P2, Qcoeff); + std::vector<Fp6> Qcoeff; + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(g1, P1, Qcoeff); + precomputedMillerLoop(g2, P2, Qcoeff); #else - BN::millerLoop(g1, P1, Q); - BN::millerLoop(g2, P2, Q); + millerLoop(g1, P1, Q); + millerLoop(g2, P2, Q); #endif } static void finalExp4(GT out[4], const GT in[4]) { for (int i = 0; i < 4; i++) { - BN::finalExp(out[i], in[i]); + finalExp(out[i], in[i]); } } static void tensorProductML(GT g[4], const G1& S1, const G1& T1, const G2& S2, const G2& T2) @@ -522,13 +520,19 @@ public: typedef CipherTextAT<G1> CipherTextG1; typedef CipherTextAT<G2> CipherTextG2; - static void init(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp254BNb) + static void init(const mcl::CurveParam& cp = mcl::BN254, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum) + { + initPairing(cp); + hashAndMapToG1(P_, "0"); + hashAndMapToG2(Q_, "0"); + pairing(ePQ_, P_, Q_); + precomputeG2(Qcoeff_, Q_); + setRangeForDLP(hashSize); + setTryNum(tryNum); + } + static void init(size_t hashSize, size_t tryNum = local::defaultTryNum) { - bn_current::initPairing(cp); - BN::hashAndMapToG1(P_, "0"); - BN::hashAndMapToG2(Q_, "0"); - BN::pairing(ePQ_, P_, Q_); - BN::precomputeG2(Qcoeff_, Q_); + init(mcl::BN254, hashSize, tryNum); } /* set range for G1-DLP @@ -669,7 +673,7 @@ public: G1::mul(R, c.T_, x_); G1::sub(R, c.S_, R); GT v; - BN::pairing(v, R, Q_); + pairing(v, R, Q_); return ePQhashTbl_.log(v); } int64_t decViaGT(const CipherTextG2& c) const @@ -678,7 +682,7 @@ public: G2::mul(R, c.T_, y_); G2::sub(R, c.S_, R); GT v; - BN::pairing(v, P_, R); + pairing(v, P_, R); return ePQhashTbl_.log(v); } int64_t dec(const CipherText& c) const @@ -1119,10 +1123,10 @@ private: Enc(1) = (S, T) = (Q + r yQ, rQ) = (Q, 0) if r = 0 cm = c1 * (Q, 0) = (S, T) * (Q, 0) = (e(S, Q), 1, e(T, Q), 1) */ - BN::precomputedMillerLoop(cm.g_[0], c1.getS(), Qcoeff_); - BN::finalExp(cm.g_[0], cm.g_[0]); - BN::precomputedMillerLoop(cm.g_[2], c1.getT(), Qcoeff_); - BN::finalExp(cm.g_[2], cm.g_[2]); + precomputedMillerLoop(cm.g_[0], c1.getS(), Qcoeff_); + finalExp(cm.g_[0], cm.g_[0]); + precomputedMillerLoop(cm.g_[2], c1.getT(), Qcoeff_); + finalExp(cm.g_[2], cm.g_[2]); cm.g_[1] = cm.g_[3] = 1; } @@ -1135,8 +1139,8 @@ private: Enc(1) = (S, T) = (P + r xP, rP) = (P, 0) if r = 0 cm = (P, 0) * c2 = (e(P, S), e(P, T), 1, 1) */ - BN::pairing(cm.g_[0], P_, c2.getS()); - BN::pairing(cm.g_[1], P_, c2.getT()); + pairing(cm.g_[0], P_, c2.getS()); + pairing(cm.g_[1], P_, c2.getT()); cm.g_[2] = cm.g_[3] = 1; } void convert(CipherTextGT& cm, const CipherTextA& ca) const @@ -1258,15 +1262,15 @@ public: PhashTbl_.mulByWindowMethod(P2, m); P1 += P2; } -// BN::millerLoop(c.g[0], P1, Q); - BN::precomputedMillerLoop(c.g_[0], P1, Qcoeff_); +// millerLoop(c.g[0], P1, Q); + precomputedMillerLoop(c.g_[0], P1, Qcoeff_); // G1::mul(P1, P, rb); PhashTbl_.mulByWindowMethod(P1, rb); G1::mul(P2, xP_, rc); P1 -= P2; - BN::millerLoop(e, P1, yQ_); + millerLoop(e, P1, yQ_); c.g_[0] *= e; - BN::finalExp(c.g_[0], c.g_[0]); + finalExp(c.g_[0], c.g_[0]); #if 1 ePQhashTbl_.mulByWindowMethod(c.g_[1], rb); ePQhashTbl_.mulByWindowMethod(c.g_[2], ra); @@ -1361,9 +1365,9 @@ public: public: void init(const PublicKey& pub) { - BN::pairing(exPQ_, pub.xP_, Q_); - BN::pairing(eyPQ_, P_, pub.yQ_); - BN::pairing(exyPQ_, pub.xP_, pub.yQ_); + pairing(exPQ_, pub.xP_, Q_); + pairing(eyPQ_, P_, pub.yQ_); + pairing(exyPQ_, pub.xP_, pub.yQ_); const size_t bitSize = Fr::getBitSize(); exPQwm_.init(static_cast<const GTasEC&>(exPQ_), bitSize, local::winSize); eyPQwm_.init(static_cast<const GTasEC&>(eyPQ_), bitSize, local::winSize); @@ -1493,6 +1497,12 @@ public: g_[i].setOne(); } } + static void neg(CipherTextGT& y, const CipherTextGT& x) + { + for (int i = 0; i < 4; i++) { + GT::unitaryInv(y.g_[i], x.g_[i]); + } + } static void add(CipherTextGT& z, const CipherTextGT& x, const CipherTextGT& y) { /* @@ -1697,16 +1707,16 @@ public: }; }; -template<class BN, class Fr> typename BN::G1 SHET<BN, Fr>::P_; -template<class BN, class Fr> typename BN::G2 SHET<BN, Fr>::Q_; -template<class BN, class Fr> typename BN::Fp12 SHET<BN, Fr>::ePQ_; -template<class BN, class Fr> std::vector<bn_current::Fp6> SHET<BN, Fr>::Qcoeff_; -template<class BN, class Fr> local::HashTable<typename BN::G1> SHET<BN, Fr>::PhashTbl_; -template<class BN, class Fr> local::HashTable<typename BN::G2> SHET<BN, Fr>::QhashTbl_; -template<class BN, class Fr> local::HashTable<typename BN::Fp12, false> SHET<BN, Fr>::ePQhashTbl_; -template<class BN, class Fr> bool SHET<BN, Fr>::useDecG1ViaGT_; -template<class BN, class Fr> bool SHET<BN, Fr>::useDecG2ViaGT_; -typedef mcl::she::SHET<bn_current::BN, bn_current::Fr> SHE; +template<size_t dummyInpl> G1 SHET<dummyInpl>::P_; +template<size_t dummyInpl> G2 SHET<dummyInpl>::Q_; +template<size_t dummyInpl> Fp12 SHET<dummyInpl>::ePQ_; +template<size_t dummyInpl> std::vector<Fp6> SHET<dummyInpl>::Qcoeff_; +template<size_t dummyInpl> local::HashTable<G1> SHET<dummyInpl>::PhashTbl_; +template<size_t dummyInpl> local::HashTable<G2> SHET<dummyInpl>::QhashTbl_; +template<size_t dummyInpl> local::HashTable<Fp12, false> SHET<dummyInpl>::ePQhashTbl_; +template<size_t dummyInpl> bool SHET<dummyInpl>::useDecG1ViaGT_; +template<size_t dummyInpl> bool SHET<dummyInpl>::useDecG2ViaGT_; +typedef mcl::she::SHET<> SHE; typedef SHE::SecretKey SecretKey; typedef SHE::PublicKey PublicKey; typedef SHE::PrecomputedPublicKey PrecomputedPublicKey; @@ -1720,5 +1730,18 @@ typedef SHE::ZkpBin ZkpBin; typedef SHE::ZkpEq ZkpEq; typedef SHE::ZkpBinEq ZkpBinEq; +inline void init(const mcl::CurveParam& cp = mcl::BN254, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum) +{ + SHE::init(cp, hashSize, tryNum); +} +inline void init(size_t hashSize, size_t tryNum = local::defaultTryNum) { SHE::init(hashSize, tryNum); } +inline void setRangeForG1DLP(size_t hashSize) { SHE::setRangeForG1DLP(hashSize); } +inline void setRangeForG2DLP(size_t hashSize) { SHE::setRangeForG2DLP(hashSize); } +inline void setRangeForGTDLP(size_t hashSize) { SHE::setRangeForGTDLP(hashSize); } +inline void setRangeForDLP(size_t hashSize) { SHE::setRangeForDLP(hashSize); } +inline void setTryNum(size_t tryNum) { SHE::setTryNum(tryNum); } +inline void useDecG1ViaGT(bool use = true) { SHE::useDecG1ViaGT(use); } +inline void useDecG2ViaGT(bool use = true) { SHE::useDecG2ViaGT(use); } + } } // mcl::she diff --git a/java/bn256_impl.hpp b/java/bn256_impl.hpp index 33cea4e..c4caaf3 100644 --- a/java/bn256_impl.hpp +++ b/java/bn256_impl.hpp @@ -245,5 +245,5 @@ void pow(GT& z, const GT& x, const Fr& y) } void pairing(GT& e, const G1& P, const G2& Q) { - mcl::bn256::BN::pairing(e.self_, P.self_, Q.self_); + mcl::bn256::pairing(e.self_, P.self_, Q.self_); } diff --git a/misc/she/she-api-ja.md b/misc/she/she-api-ja.md new file mode 100644 index 0000000..4e79c05 --- /dev/null +++ b/misc/she/she-api-ja.md @@ -0,0 +1,263 @@ +# L2準同型暗号ライブラリshe + +# 概要 +she(somewhat homomorphic encryption)はペアリングベースのL2準同型暗号と呼ばれる公開鍵暗号ライブラリである。 +L2準同型暗号とは暗号文同士の加算を複数回、乗算を一度だけできる性質を表す。 + +特に2個の整数値ベクトルx = (x_i), y = (y_i)の各要素が暗号化された状態で、その2個のベクトルの内積を暗号化したまま計算できる。 + +ΣEnc(x_i) Enc(y_i) = Enc(Σx_i y_i). + +# 特長 +* ペアリングベースの最新アルゴリズムを実装 + * [Efficient Two-level Homomorphic Encryption in Prime-order Bilinear Groups and A Fast Implementation in WebAssembly : ASIA CCS2018](http://asiaccs2018.org/?page_id=632) +* C++版はWindows(x64), Linux(x64, ARM64), OSX(x64)に対応 +* JavaScript(WebAssembly 以降JSと記す)版はChrome, Firefox, Edge, Safari(Android, iPhone含む), Node.jsに対応 + +# クラスと主な機能 + +## 主なクラス +* 秘密鍵クラス SecretKey +* 公開鍵クラス PublicKey +* 暗号文クラス CipherTextG1, CipherTextG2, CipherTextGT + +## 暗号化と復号方法 +* 秘密鍵から公開鍵を作成する +* 公開鍵を用いて整数から暗号文を作る +* 秘密鍵を用いて暗号文を復号する + +## 暗号文同士の計算 +* 同じ暗号文クラス同士は加算・減算できる +* CipherTextG1とCipherTextG2を乗算するとCipherTextGTになる + +## 復号の重要な注意点 +* このsheは復号時に小さな離散対数問題(DLP)を解く必要がある。 +* DLPのテーブルサイズをs、暗号文をEnc(m)とすると復号時間はm/sに比例する。 +* テーブルサイズの設定は`setRangeForDLP(s)`を使う。 +`m/s`の最大値は`setTryNum(tryNum)`で行う。 + +# JS版 + +## Node.jsでの読み込み + +``` +>npm install she-wasm +>node +>const she = require('she-wasm') +``` + +## ブラウザでの読み込み +``` +// HTML +<script src="she.js"></script> +``` + +## JS版サンプル + +``` +// システムの初期化 +she.init().then(() => { + const sec = new she.SecretKey() + // 秘密鍵の初期化 + sec.setByCSPRNG() + + // 秘密鍵secから公開鍵pubを作成 + const pub = sec.getPublicKey() + + const m1 = 1 + const m2 = 2 + const m3 = 3 + const m4 = -1 + + // 平文m1とm2をCipherTextG1として暗号化 + const c11 = pub.encG1(m1) + const c12 = pub.encG1(m2) + + // 平文m3とm4をCipherTextG2として暗号化 + const c21 = pub.encG2(m3) + const c22 = pub.encG2(m4) + + // c11とc12, c21とc22をそれぞれ加算 + const c1 = she.add(c11, c12) + const c2 = she.add(c21, c22) + + // c1とc2を乗算するとCipherTextGT型になる + const ct = she.mul(c1, c2) + + // 暗号文ctを復号する + console.log(`(${m1} + ${m2}) * (${m3} + ${m4}) = ${sec.dec(ct)}`) +}) +``` + +# C++版サンプル +``` +#include <mcl/she.hpp> +int main() + try +{ + using namespace mcl::she; + // システのム初期化 + init(); + + SecretKey sec; + + // 秘密鍵の初期化 + sec.setByCSPRNG(); + + // 秘密鍵secから公開鍵pubを作成 + PublicKey pub; + sec.getPublicKey(pub); + + int m1 = 1; + int m2 = 2; + int m3 = 3; + int m4 = -1; + + // 平文m1とm2をCipherTextG1として暗号化 + CipherTextG1 c11, c12; + pub.enc(c11, m1); + pub.enc(c12, m2); + + // 平文m3とm4をCipherTextG2として暗号化 + CipherTextG2 c21, c22; + pub.enc(c21, m3); + pub.enc(c22, m4); + + // c11とc12, c21とc22をそれぞれ加算 + CipherTextG1 c1; + CipherTextG2 c2; + CipherTextG1::add(c1, c11, c12); + CipherTextG2::add(c2, c21, c22); + + // c1とc2を乗算するとCipherTextGT型になる + CipherTextGT ct; + CipherTextGT::mul(ct, c1, c2); + + // 暗号文ctを復号する + printf("(%d + %d) * (%d + %d) = %d\n", m1, m2, m3, m4, (int)sec.dec(ct)); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); + return 1; +} + +``` + +# クラス共通メソッド + +## シリアライズ(C++) + +* `setStr(const std::string& str, int ioMode = 0)` + * ioModeに従ってstrで設定する + +* `getStr(std::string& str, int ioMode = 0) const` +* `std::string getStr(int ioMode = 0) const` + * ioModeに従ってstrを取得する +* `size_t serialize(void *buf, size_t maxBufSize) const` + * maxBufSize確保されたbufにシリアライズする + * bufに書き込まれたbyte長が返る + * エラーの場合は0が返る +* `size_t deserialize(const void *buf, size_t bufSize)` + * bufから最大bufSizeまで値を読み込みデリシアライズする + * 読み込まれたbyte長が返る + * エラーの場合は0が返る + +## シリアライズ(JS) + +* `deserialize(s)` + * Uint8Array型sでデシリアライズ +* `serialize()` + * シリアライズしてUint8Arrayの値を返す +* `deserializeHexStr(s)` + * 16進数文字列sでデシリアライズ +* `serializeToHexStr()` + * 16進数文字列sでシリアライズ + +## ioMode + +* 2 ; 2進数 +* 10 ; 10進数 +* 16 ; 16進数 +* IoPrefix ; 2または16とorの値を設定すると0bまたは0xがつく +* IoEcAffine ; (G1, G2のみ)アフィン座標 +* IoEcProj ; (G1, G2のみ)射影座標 +* IoSerialize ; serialize()/deserialize()と同じ + +## 注意 +* C++の名前空間は`mcl::she` +* 以下CTはCipherTextG1, CipherTextG2, CipherTextGTのいずれかを表す +* JS版の平文は32ビット整数の範囲に制限される + +## SecretKeyクラス + +* `void setByCSPRNG()`(C++) +* `void setByCSPRNG()`(JS) + * 疑似乱数で秘密鍵を初期化する + +* `int64_t dec(const CT& c) const`(C++) +* `int dec(CT c)`(JS) + * 暗号文cを復号する +* `int64_t decViaGT(const CipherTextG1& c) const`(C++) +* `int64_t decViaGT(const CipherTextG2& c) const`(C++) +* `int decViaGT(CT c)`(JS) + * 暗号文をGT経由で復号する +* `bool isZero(const CT& c) const`(C++) +* `bool isZero(CT c)`(JS) + * cの復号結果が0ならばtrue + * decしてから0と比較するよりも高速 + +## PublicKeyクラス + +* `void enc(CT& c, int64_t m) const`(C++) +* `CipherTextG1 encG1(m)`(JS) +* `CipherTextG2 encG2(m)`(JS) +* `CipherTextGT encGT(m)`(JS) + * mを暗号化してcにセットする(またはその値を返す) + +* `void reRand(CT& c) const`(C++) +* `CT reRand(CT c)`(JS) + * cを再ランダム化する + * 再ランダム化された暗号文と元の暗号文は同じ平文を暗号化したものかどうか判定できない + +* `void convert(CipherTextGT& cm, const CT& ca) const` +* `CipherTextGT convert(CT ca)` + * 暗号文ca(CipherTextG1かCipherTextG2)をCipherTextGTに変換する + +## CipherTextクラス + +* `void CT::add(CT& z, const CT& x const CT& y)`(C++) +* `CT she.add(CT x, CT y)`(JS) + * 暗号文xと暗号文yを足してzにセットする(またはその値を返す) +* `void CT::sub(CT& z, const CT& x const CT& y)`(C++) +* `CT she.sub(CT x, CT y)`(JS) + * 暗号文xから暗号文yを引いてzにセットする(またはその値を返す) +* `void CT::neg(CT& y, const CT& x)`(C++) +* `void she.neg(CT x)`(JS) + * 暗号文xの符号反転をyにセットする(またはその値を返す) +* `void CT::mul(CT& z, const CT& x, int y)`(C++) +* `CT she.mulInt(CT x, int y)`(JS) + * 暗号文xを整数倍yしてzにセットする(またはその値を返す) + +* `void CipherTextGT::mul(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++) +* `CipherTextGT she.mul(CipherTextG1 x, CipherTextG2 y)`(JS) + * 暗号文xと暗号文yを掛けてzにセットする(またはその値を返す) + +* `void CipherTextGT::mulML(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y)`(C++) + * 暗号文xと暗号文yを掛けて(Millerループだけして)zにセットする(またはその値を返す) +* `CipherTextGT::finalExp(CipherText& , const CipherTextG1& x, const CipherTextG2& y)`(C++) + * mul(a, b) = finalExp(mulML(a, b)) + * add(mul(a, b), mul(c, d)) = finalExp(add(mulML(a, b), mulML(c, d))) + * すなわち積和演算はmulMLしたものを足してから最後に一度finalExpするのがよい + +## グローバル関数 + +* `void init(const CurveParam& cp, size_t hashSize = 1024, size_t tryNum = 2048)`(C++) +* `void init(curveType = she.BN254, hashSize = 1024, tryNum = 2048)`(JS) + * hashSizeの大きさの復号用テーブルとtryNumを元に初期化する + * 復号可能な平文mの範囲は|m| <= hashSize * tryNum +* `she.loadTableForGTDLP(Uint8Array a)`(JS) + * 復号用テーブルを読み込む + * 現在は`https://herumi.github.io/she-dlp-table/she-dlp-0-20-gt.bin`のみがある +* `void useDecG1ViaGT(bool use)`(C++/JS) +* `void useDecG2ViaGT(bool use)`(C++/JS) + * CipherTextG1, CipherTextG2の復号をCipherTextGT経由で行う + * 大きな値を復号するときはDLP用の巨大なテーブルをそれぞれに持つよりもGTに集約した方が効率がよい @@ -2,12 +2,12 @@ # mcl
-A generic and fast pairing-based cryptography library.
+A portable and fast pairing-based cryptography library.
# Abstract
mcl is a library for pairing-based cryptography.
-The current version supports the optimal Ate pairing over BN curves.
+The current version supports the optimal Ate pairing over BN curves and BLS12-381 curves.
# Support architecture
@@ -22,14 +22,15 @@ The current version supports the optimal Ate pairing over BN curves. p(z) = 36z^4 + 36z^3 + 24z^2 + 6z + 1.
-* CurveFp254BNb ; a BN curve over the 254-bit prime p(z) where z = -(2^62 + 2^55 + 1).
-* CurveSNARK1 ; a BN curve over a 254-bit prime p such that n := p + 1 - t has high 2-adicity.
-* CurveFp381 ; a BN curve over the 381-bit prime p(z) where z = -(2^94 + 2^76 + 2^72 + 1).
-* CurveFp462 ; a BN curve over the 462-bit prime p(z) where z = 2^114 + 2^101 - 2^14 - 1.
+* BN254 ; a BN curve over the 254-bit prime p(z) where z = -(2^62 + 2^55 + 1).
+* BN\_SNARK1 ; a BN curve over a 254-bit prime p such that n := p + 1 - t has high 2-adicity.
+* BN381\_1 ; a BN curve over the 381-bit prime p(z) where z = -(2^94 + 2^76 + 2^72 + 1).
+* BN462 ; a BN curve over the 462-bit prime p(z) where z = 2^114 + 2^101 - 2^14 - 1.
+* BLS12\_381 ; [a BLS12-381 curve](https://blog.z.cash/new-snark-curve/)
# Benchmark
-A benchmark of a BN curve CurveFp254BNb(2016/12/25).
+A benchmark of a BN curve BN254(2016/12/25).
* x64, x86 ; Inte Core i7-6700 3.4GHz(Skylake) upto 4GHz on Ubuntu 16.04.
* `sudo cpufreq-set -g performance`
@@ -53,17 +54,17 @@ cmake -DARITH=x64-asm-254 -DFP_PRIME=254 -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_ME For JavaScript(WebAssembly), see [ID based encryption demo](https://herumi.github.io/mcl-wasm/ibe-demo.html).
-paramter | x64| Firefox on x64|Safari on iPhone7|
-----------------|-----|---------------|-----------------|
-CurveFpBN254BNb | 0.29| 2.48| 4.78|
-CurveFp382_1 | 0.95| 7.91| 11.74|
-CurveFp462 | 2.16| 14.73| 22.77|
+paramter | x64| Firefox on x64|Safari on iPhone7|
+-----------|-----|---------------|-----------------|
+BN254 | 0.29| 2.48| 4.78|
+BN381\_1 | 0.95| 7.91| 11.74|
+BN462 | 2.16| 14.73| 22.77|
* x64 : 'Kaby Lake Core i7-7700(3.6GHz)'.
* Firefox : 64-bit version 58.
* iPhone7 : iOS 11.2.1.
-* CurveFpBN254BNb is by `test/bn_test.cpp`.
-* CurveFp382_1 and CurveFp462 are by `test/bn512_test.cpp`.
+* BN254 is by `test/bn_test.cpp`.
+* BN381\_1 and BN462 are by `test/bn512_test.cpp`.
* All the timings are given in ms(milliseconds).
The other benchmark results are [bench.txt](bench.txt).
@@ -84,7 +85,7 @@ git clone git://github.com/herumi/cybozulib git clone git://github.com/herumi/xbyak ; for only x86/x64
git clone git://github.com/herumi/cybozulib_ext ; for only Windows
```
-* Cybozulib_ext is a prerequisite for running OpenSSL and GMP on VC (Visual C++).
+* Cybozulib\_ext is a prerequisite for running OpenSSL and GMP on VC (Visual C++).
# Build and test on x86-64 Linux, macOS, ARM and ARM64 Linux
To make lib/libmcl.a and test it:
@@ -156,7 +157,7 @@ emcc -O3 -I ./include/ -I ../cybozulib/include/ src/fp.cpp test/bn_test.cpp -DND emrun --no_browser --port 8080 --no_emrun_detect .
```
and open `http://<address>:8080/t.html`.
-The timing of a pairing on `CurveFp254BNb` is 2.8msec on 64-bit Firefox with Skylake 3.4GHz.
+The timing of a pairing on `BN254` is 2.8msec on 64-bit Firefox with Skylake 3.4GHz.
### Node.js
@@ -189,27 +190,27 @@ finalExp 546.259Kclk # Libraries
* libmcl.a ; static C++ library of mcl
-* libmcl_dy.so ; shared C++ library of mcl
+* libmcl\_dy.so ; shared C++ library of mcl
* libbn256.a ; static C library for `mcl/bn256f.h`
-* libbn256_dy.so ; shared C library
+* libbn256\_dy.so ; shared C library
-If you want to remove '_dy` of so files, then `makeSHARE_BASENAME_SUF=`.
+If you want to remove '_dy` of so files, then `makeSHARE_BASENAME\_SUF=`.
# How to initialize pairing library
Call `mcl::bn256::initPairing` before calling any operations.
```
#include <mcl/bn256.hpp>
-mcl::bn::CurveParam cp = mcl::bn::CurveFp254BNb; // or mcl::bn::CurveSNARK1
+mcl::bn::CurveParam cp = mcl::BN254; // or mcl::BN_SNARK1
mcl::bn256::initPairing(cp);
mcl::bn256::G1 P(...);
mcl::bn256::G2 Q(...);
mcl::bn256::Fp12 e;
-mcl::bn256::BN::pairing(e, P, Q);
+mcl::bn256::pairing(e, P, Q);
```
-1. (CurveFp254BNb) a BN curve over the 254-bit prime p = p(z) where z = -(2^62 + 2^55 + 1).
-2. (CurveSNARK1) a BN curve over a 254-bit prime p such that n := p + 1 - t has high 2-adicity.
-3. CurveFp381 with `mcl/bn384.hpp`.
-4. CurveFp462 with `mcl/bn512.hpp`.
+1. (BN254) a BN curve over the 254-bit prime p = p(z) where z = -(2^62 + 2^55 + 1).
+2. (BN_SNARK1) a BN curve over a 254-bit prime p such that n := p + 1 - t has high 2-adicity.
+3. BN381_1 with `mcl/bn384.hpp`.
+4. BN462 with `mcl/bn512.hpp`.
See [test/bn_test.cpp](https://github.com/herumi/mcl/blob/master/test/bn_test.cpp).
@@ -265,8 +266,8 @@ Use `Fp12::mulGeneric` for x in Fp12 - GT. ## Map To points
-* BN::mapToG1(G1& P, const Fp& x);
-* BN::mapToG2(G2& P, const Fp2& x);
+* mapToG1(G1& P, const Fp& x);
+* mapToG2(G2& P, const Fp2& x);
These functions maps x into Gi according to [_Faster hashing to G2_].
diff --git a/sample/bls_sig.cpp b/sample/bls_sig.cpp index acc4a70..c574087 100644 --- a/sample/bls_sig.cpp +++ b/sample/bls_sig.cpp @@ -23,7 +23,7 @@ void Hash(G1& P, const std::string& m) { Fp t; t.setHashOf(m); - BN::mapToG1(P, t); + mapToG1(P, t); } void KeyGen(Fr& s, G2& pub, const G2& Q) @@ -44,8 +44,8 @@ bool Verify(const G1& sign, const G2& Q, const G2& pub, const std::string& m) Fp12 e1, e2; G1 Hm; Hash(Hm, m); - BN::pairing(e1, sign, Q); // e1 = e(sign, Q) - BN::pairing(e2, Hm, pub); // e2 = e(Hm, sQ) + pairing(e1, sign, Q); // e1 = e(sign, Q) + pairing(e2, Hm, pub); // e2 = e(Hm, sQ) return e1 == e2; } @@ -56,7 +56,7 @@ int main(int argc, char *argv[]) // setup parameter initPairing(); G2 Q; - BN::mapToG2(Q, 1); + mapToG2(Q, 1); // generate secret key and public key Fr s; diff --git a/sample/pairing.cpp b/sample/pairing.cpp index b18a17f..230583b 100644 --- a/sample/pairing.cpp +++ b/sample/pairing.cpp @@ -7,12 +7,12 @@ void minimum_sample(const G1& P, const G2& Q) const mpz_class a = 123; const mpz_class b = 456; Fp12 e1, e2; - BN::pairing(e1, P, Q); + pairing(e1, P, Q); G2 aQ; G1 bP; G2::mul(aQ, Q, a); G1::mul(bP, P, b); - BN::pairing(e2, bP, aQ); + pairing(e2, bP, aQ); Fp12::pow(e1, e1, a * b); printf("%s\n", e1 == e2 ? "ok" : "ng"); } @@ -20,21 +20,21 @@ void minimum_sample(const G1& P, const G2& Q) void miller_and_finel_exp(const G1& P, const G2& Q) { Fp12 e1, e2; - BN::pairing(e1, P, Q); + pairing(e1, P, Q); - BN::millerLoop(e2, P, Q); - BN::finalExp(e2, e2); + millerLoop(e2, P, Q); + finalExp(e2, e2); printf("%s\n", e1 == e2 ? "ok" : "ng"); } void precomputed(const G1& P, const G2& Q) { Fp12 e1, e2; - BN::pairing(e1, P, Q); + pairing(e1, P, Q); std::vector<Fp6> Qcoeff; - BN::precomputeG2(Qcoeff, Q); - BN::precomputedMillerLoop(e2, P, Qcoeff); - BN::finalExp(e2, e2); + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e2, P, Qcoeff); + finalExp(e2, e2); printf("%s\n", e1 == e2 ? "ok" : "ng"); } diff --git a/sample/pairing_c.c b/sample/pairing_c.c index 3337afe..b9f159a 100644 --- a/sample/pairing_c.c +++ b/sample/pairing_c.c @@ -11,7 +11,7 @@ int main() char buf[1024]; const char *aStr = "123"; const char *bStr = "456"; - mclBn_init(mclBn_CurveFp254BNb, MCLBN_FP_UNIT_SIZE); + mclBn_init(MCL_BN254, MCLBN_FP_UNIT_SIZE); mclBnFr a, b, ab; mclBnG1 P, aP; mclBnG2 Q, bQ; diff --git a/sample/she_make_dlp_table.cpp b/sample/she_make_dlp_table.cpp new file mode 100644 index 0000000..6b57999 --- /dev/null +++ b/sample/she_make_dlp_table.cpp @@ -0,0 +1,69 @@ +/* + make she DLP table +*/ +#include <mcl/she.hpp> +#include <cybozu/option.hpp> +#include <fstream> + +using namespace mcl::she; + +struct Param { + int curveType; + int hashBitSize; + int group; + std::string path; +}; + +template<class HashTable, class G> +void makeTable(const Param& param, const char *groupStr, HashTable& hashTbl, const G& P) +{ + char baseName[32]; + CYBOZU_SNPRINTF(baseName, sizeof(baseName), "she-dlp-%d-%d-%s.bin", param.curveType, param.hashBitSize, groupStr); + const std::string fileName = param.path + baseName; + printf("file=%s\n", fileName.c_str()); + std::ofstream ofs(fileName.c_str(), std::ios::binary); + + const size_t hashSize = 1u << param.hashBitSize; + hashTbl.init(P, hashSize); + hashTbl.save(ofs); +} + +void run(const Param& param) +{ + SHE::init(mcl::getCurveParam(param.curveType)); + + switch (param.group) { + case 1: + makeTable(param, "g1", SHE::PhashTbl_, SHE::P_); + break; + case 2: + makeTable(param, "g2", SHE::QhashTbl_, SHE::Q_); + break; + case 3: + makeTable(param, "gt", SHE::ePQhashTbl_, SHE::ePQ_); + break; + default: + throw cybozu::Exception("bad group") << param.group; + } +} + +int main(int argc, char *argv[]) + try +{ + cybozu::Option opt; + Param param; + opt.appendOpt(¶m.curveType, 0, "ct", ": curveType(0:BN254, 1:BN381_1, 5:BLS12_381)"); + opt.appendOpt(¶m.hashBitSize, 20, "hb", ": hash bit size"); + opt.appendOpt(¶m.group, 3, "g", ": group(1:G1, 2:G2, 3:GT"); + opt.appendOpt(¶m.path, "./", "path", ": path to table"); + opt.appendHelp("h"); + if (opt.parse(argc, argv)) { + run(param); + } else { + opt.usage(); + return 1; + } +} catch (std::exception& e) { + printf("err %s\n", e.what()); + return 1; +} diff --git a/sample/she_smpl.cpp b/sample/she_smpl.cpp index 06d8fac..c136d92 100644 --- a/sample/she_smpl.cpp +++ b/sample/she_smpl.cpp @@ -18,7 +18,7 @@ void miniSample() sec.setByCSPRNG(); // set range to decode GT DLP - SHE::setRangeForGTDLP(1000); + SHE::setRangeForDLP(1000); PublicKey pub; // get public key diff --git a/sample/tri-dh.cpp b/sample/tri-dh.cpp index 3859344..8b720ed 100644 --- a/sample/tri-dh.cpp +++ b/sample/tri-dh.cpp @@ -65,11 +65,11 @@ void share(const std::string& skFile, const std::string& pk1File, const std::str load(P1, Q1, pk1File); load(P2, Q2, pk2File); Fp12 e; - BN::pairing(e, P1, Q2); + pairing(e, P1, Q2); { // verify(not necessary) Fp12 e2; - BN::pairing(e2, P2, Q1); + pairing(e2, P2, Q1); if (e != e2) { throw cybozu::Exception("share:bad public key file") << e << e2; } diff --git a/src/bn_c_impl.hpp b/src/bn_c_impl.hpp index 49962c5..d2ce738 100644 --- a/src/bn_c_impl.hpp +++ b/src/bn_c_impl.hpp @@ -126,7 +126,7 @@ int mclBn_init(int curve, int maxUnitSize) fprintf(stderr, "mclBn_init:maxUnitSize is mismatch %d %d\n", maxUnitSize, MCLBN_FP_UNIT_SIZE); return -1; } - const mcl::bn::CurveParam& cp = mcl::bn::getCurveParam(curve); + const mcl::CurveParam& cp = mcl::getCurveParam(curve); initPairing(cp); return 0; } catch (std::exception& e) { @@ -144,6 +144,11 @@ int mclBn_getG1ByteSize() return (int)Fp::getByteSize(); } +int mclBn_getFrByteSize() +{ + return (int)Fr::getByteSize(); +} + mclSize copyStrAndReturnSize(char *buf, mclSize maxBufSize, const std::string& str) { if (str.size() >= maxBufSize) return 0; @@ -309,7 +314,7 @@ int mclBnG1_isZero(const mclBnG1 *x) int mclBnG1_hashAndMapTo(mclBnG1 *x, const void *buf, mclSize bufSize) try { - BN::hashAndMapToG1(*cast(x), buf, bufSize); + hashAndMapToG1(*cast(x), buf, bufSize); return 0; } catch (std::exception& e) { if (g_fp) fprintf(g_fp, "mclBnG1_hashAndMapTo %s\n", e.what()); @@ -388,7 +393,7 @@ int mclBnG2_isZero(const mclBnG2 *x) int mclBnG2_hashAndMapTo(mclBnG2 *x, const void *buf, mclSize bufSize) try { - BN::hashAndMapToG2(*cast(x), buf, bufSize); + hashAndMapToG2(*cast(x), buf, bufSize); return 0; } catch (std::exception& e) { if (g_fp) fprintf(g_fp, "mclBnG2_hashAndMapTo %s\n", e.what()); @@ -523,15 +528,15 @@ void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y) void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y) { - BN::pairing(*cast(z), *cast(x), *cast(y)); + pairing(*cast(z), *cast(x), *cast(y)); } void mclBn_finalExp(mclBnGT *y, const mclBnGT *x) { - BN::finalExp(*cast(y), *cast(x)); + finalExp(*cast(y), *cast(x)); } void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y) { - BN::millerLoop(*cast(z), *cast(x), *cast(y)); + millerLoop(*cast(z), *cast(x), *cast(y)); } int mclBn_getUint64NumToPrecompute(void) { @@ -540,17 +545,17 @@ int mclBn_getUint64NumToPrecompute(void) void mclBn_precomputeG2(uint64_t *Qbuf, const mclBnG2 *Q) { - BN::precomputeG2(cast(Qbuf), *cast(Q)); + precomputeG2(cast(Qbuf), *cast(Q)); } void mclBn_precomputedMillerLoop(mclBnGT *f, const mclBnG1 *P, const uint64_t *Qbuf) { - BN::precomputedMillerLoop(*cast(f), *cast(P), cast(Qbuf)); + precomputedMillerLoop(*cast(f), *cast(P), cast(Qbuf)); } void mclBn_precomputedMillerLoop2(mclBnGT *f, const mclBnG1 *P1, const uint64_t *Q1buf, const mclBnG1 *P2, const uint64_t *Q2buf) { - BN::precomputedMillerLoop2(*cast(f), *cast(P1), cast(Q1buf), *cast(P2), cast(Q2buf)); + precomputedMillerLoop2(*cast(f), *cast(P1), cast(Q1buf), *cast(P2), cast(Q2buf)); } int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, mclSize k) @@ -607,3 +612,14 @@ int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, mclSize cSize, if (g_fp) fprintf(g_fp, "mclBn_G2EvaluatePolynomial %s\n", e.what()); return -1; } + +void mclBn_verifyOrderG1(int doVerify) +{ + verifyOrderG1(doVerify != 0); +} + +void mclBn_verifyOrderG2(int doVerify) +{ + verifyOrderG2(doVerify != 0); +} + @@ -201,6 +201,7 @@ void getRandVal(Unit *out, RandGen& rg, const Unit *in, size_t bitSize) if (rg.isZero()) rg = RandGen::get(); const size_t n = (bitSize + UnitBitSize - 1) / UnitBitSize; const size_t rem = bitSize & (UnitBitSize - 1); + assert(n > 0); for (;;) { rg.read(out, n * sizeof(Unit)); if (rem > 0) out[n - 1] &= (Unit(1) << rem) - 1; diff --git a/src/she_c384.cpp b/src/she_c384.cpp new file mode 100644 index 0000000..bfc456a --- /dev/null +++ b/src/she_c384.cpp @@ -0,0 +1,2 @@ +#define MCLBN_FP_UNIT_SIZE 6 +#include "she_c_impl.hpp" diff --git a/src/she_c_impl.hpp b/src/she_c_impl.hpp index fcd78a2..520da8c 100644 --- a/src/she_c_impl.hpp +++ b/src/she_c_impl.hpp @@ -65,19 +65,25 @@ int sheInit(int curve, int maxUnitSize) static int g_curve = -1; if (g_curve == curve) return 0; - mcl::bn::CurveParam cp; + mcl::CurveParam cp; switch (curve) { - case mclBn_CurveFp254BNb: - cp = mcl::bn::CurveFp254BNb; + case MCL_BN254: + cp = mcl::BN254; break; - case mclBn_CurveFp382_1: - cp = mcl::bn::CurveFp382_1; + case MCL_BN381_1: + cp = mcl::BN381_1; break; - case mclBn_CurveFp382_2: - cp = mcl::bn::CurveFp382_2; + case MCL_BN381_2: + cp = mcl::BN381_2; break; - case mclBn_CurveFp462: - cp = mcl::bn::CurveFp462; + case MCL_BN462: + cp = mcl::BN462; + break; + case MCL_BN_SNARK1: + cp = mcl::BN_SNARK1; + break; + case MCL_BLS12_381: + cp = mcl::BLS12_381; break; default: fprintf(stderr, "err bad curve %d\n", curve); @@ -96,8 +102,7 @@ mclSize serialize(void *buf, mclSize maxBufSize, const T *x) try { return cast(x)->serialize(buf, maxBufSize); -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return 0; } @@ -146,8 +151,7 @@ mclSize deserialize(T *x, const void *buf, mclSize bufSize) try { return cast(x)->deserialize(buf, bufSize); -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return 0; } @@ -196,8 +200,7 @@ int sheSecretKeySetByCSPRNG(sheSecretKey *sec) { cast(sec)->setByCSPRNG(); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -211,8 +214,7 @@ static int setRangeForDLP(void (*f)(mclSize), mclSize hashSize) { f(hashSize); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -251,8 +253,7 @@ mclSize loadTable(HashTable& table, const void *buf, mclSize bufSize) try { return table.load(buf, bufSize); -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return 0; } @@ -274,8 +275,7 @@ mclSize saveTable(void *buf, mclSize maxBufSize, const HashTable& table) try { return table.save(buf, maxBufSize); -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return 0; } mclSize sheSaveTableForG1DLP(void *buf, mclSize maxBufSize) @@ -297,8 +297,7 @@ int encT(CT *c, const shePublicKey *pub, mclInt m) { cast(pub)->enc(*cast(c), m); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -323,8 +322,7 @@ int encWithZkpBinT(CT *c, sheZkpBin *zkp, const PK *pub, int m) { cast(pub)->encWithZkpBin(*cast(c), *cast(zkp), m); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -396,8 +394,7 @@ int decT(mclInt *m, const sheSecretKey *sec, const CT *c) { *m = (cast(sec)->dec)(*cast(c)); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -422,8 +419,7 @@ int decViaGTT(mclInt *m, const sheSecretKey *sec, const CT *c) { *m = (cast(sec)->decViaGT)(*cast(c)); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -443,8 +439,7 @@ int isZeroT(const sheSecretKey *sec, const CT *c) try { return cast(sec)->isZero(*cast(c)); -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return 0; } @@ -461,6 +456,30 @@ int sheIsZeroGT(const sheSecretKey *sec, const sheCipherTextGT *c) return isZeroT(sec, c); } +template<class CT> +int negT(CT& y, const CT& x) + try +{ + CT::neg(y, x); + return 0; +} catch (std::exception&) { + return -1; +} + +int sheNegG1(sheCipherTextG1 *y, const sheCipherTextG1 *x) +{ + return negT(*cast(y), *cast(x)); +} + +int sheNegG2(sheCipherTextG2 *y, const sheCipherTextG2 *x) +{ + return negT(*cast(y), *cast(x)); +} + +int sheNegGT(sheCipherTextGT *y, const sheCipherTextGT *x) +{ + return negT(*cast(y), *cast(x)); +} template<class CT> int addT(CT& z, const CT& x, const CT& y) @@ -468,8 +487,7 @@ int addT(CT& z, const CT& x, const CT& y) { CT::add(z, x, y); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -494,8 +512,7 @@ int subT(CT& z, const CT& x, const CT& y) { CT::sub(z, x, y); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -520,8 +537,7 @@ int mulT(CT1& z, const CT2& x, const CT3& y) { CT1::mul(z, x, y); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -550,8 +566,7 @@ int sheMulML(sheCipherTextGT *z, const sheCipherTextG1 *x, const sheCipherTextG2 { CipherTextGT::mulML(*cast(z), *cast(x), *cast(y)); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -560,8 +575,7 @@ int sheFinalExpGT(sheCipherTextGT *y, const sheCipherTextGT *x) { CipherTextGT::finalExp(*cast(y), *cast(x)); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -571,8 +585,7 @@ int reRandT(CT& c, const shePublicKey *pub) { cast(pub)->reRand(c); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -597,8 +610,7 @@ int convert(sheCipherTextGT *y, const shePublicKey *pub, const CT *x) { cast(pub)->convert(*cast(y), *cast(x)); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -640,8 +652,7 @@ int pEncT(CT *c, const shePrecomputedPublicKey *pub, mclInt m) { cast(pub)->enc(*cast(c), m); return 0; -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return -1; } @@ -665,8 +676,7 @@ int verifyT(const PK& pub, const CT& c, const ZkpBin& zkp) try { return pub.verify(c, zkp); -} catch (std::exception& e) { - fprintf(stderr, "err %s\n", e.what()); +} catch (std::exception&) { return 0; } diff --git a/test/aggregate_sig_test.cpp b/test/aggregate_sig_test.cpp index ff90507..c3a0e75 100644 --- a/test/aggregate_sig_test.cpp +++ b/test/aggregate_sig_test.cpp @@ -9,8 +9,8 @@ using namespace mcl::aggs; CYBOZU_TEST_AUTO(init) { AGGS::init(); -// AGGS::init(mcl::bn::CurveFp382_1); -// AGGS::init(mcl::bn::CurveFp462); +// AGGS::init(mcl::BN381_1); +// AGGS::init(mcl::BLS12_381); SecretKey sec; sec.init(); PublicKey pub; diff --git a/test/bench.hpp b/test/bench.hpp index 52728ec..8506b5a 100644 --- a/test/bench.hpp +++ b/test/bench.hpp @@ -1,10 +1,9 @@ -template<class CT> void testBench(const G1& P, const G2& Q) { G1 Pa; G2 Qa; Fp12 e1, e2; - CT::pairing(e1, P, Q); + pairing(e1, P, Q); Fp12::pow(e2, e1, 12345); const int C = 500; const int C2 = 1000; @@ -26,16 +25,22 @@ void testBench(const G1& P, const G2& Q) CYBOZU_BENCH_C("G2::add ", C, G2::add, Qa, Qa, Q); CYBOZU_BENCH_C("G2::dbl ", C, G2::dbl, Qa, Qa); CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e1, e1, a); -// CYBOZU_BENCH_C("GT::powGLV ", C, CT::param.glv2.pow, e1, e1, a); +// CYBOZU_BENCH_C("GT::powGLV ", C, BN::param.glv2.pow, e1, e1, a); G1 PP; G2 QQ; std::string s; s = P.getStr(); + CYBOZU_BENCH_C("G1::setStr chk", C, PP.setStr, s); + verifyOrderG1(false); CYBOZU_BENCH_C("G1::setStr ", C, PP.setStr, s); + verifyOrderG1(true); s = Q.getStr(); + CYBOZU_BENCH_C("G2::setStr chk", C, QQ.setStr, s); + verifyOrderG2(false); CYBOZU_BENCH_C("G2::setStr ", C, QQ.setStr, s); - CYBOZU_BENCH_C("hashAndMapToG1", C, CT::hashAndMapToG1, PP, "abc", 3); - CYBOZU_BENCH_C("hashAndMapToG2", C, CT::hashAndMapToG2, QQ, "abc", 3); + verifyOrderG2(true); + CYBOZU_BENCH_C("hashAndMapToG1", C, hashAndMapToG1, PP, "abc", 3); + CYBOZU_BENCH_C("hashAndMapToG2", C, hashAndMapToG2, QQ, "abc", 3); CYBOZU_BENCH_C("Fp::add ", C2, Fp::add, x, x, y); CYBOZU_BENCH_C("Fp::mul ", C2, Fp::mul, x, x, y); CYBOZU_BENCH_C("Fp::sqr ", C2, Fp::sqr, x, x); @@ -45,10 +50,10 @@ void testBench(const G1& P, const G2& Q) CYBOZU_BENCH_C("GT::mul ", C2, GT::mul, e1, e1, e2); CYBOZU_BENCH_C("GT::sqr ", C2, GT::sqr, e1, e1); CYBOZU_BENCH_C("GT::inv ", C2, GT::inv, e1, e1); - CYBOZU_BENCH_C("pairing ", C, CT::pairing, e1, P, Q); - CYBOZU_BENCH_C("millerLoop ", C, CT::millerLoop, e1, P, Q); - CYBOZU_BENCH_C("finalExp ", C, CT::finalExp, e1, e1); + CYBOZU_BENCH_C("pairing ", C, pairing, e1, P, Q); + CYBOZU_BENCH_C("millerLoop ", C, millerLoop, e1, P, Q); + CYBOZU_BENCH_C("finalExp ", C, finalExp, e1, e1); std::vector<Fp6> Qcoeff; - CT::precomputeG2(Qcoeff, Q); - CYBOZU_BENCH_C("precomputedML ", C, CT::precomputedMillerLoop, e2, P, Qcoeff); + precomputeG2(Qcoeff, Q); + CYBOZU_BENCH_C("precomputedML ", C, precomputedMillerLoop, e2, P, Qcoeff); } diff --git a/test/bls12_test.cpp b/test/bls12_test.cpp index a115fef..4b6eb7a 100644 --- a/test/bls12_test.cpp +++ b/test/bls12_test.cpp @@ -3,7 +3,7 @@ #include <cybozu/benchmark.hpp> cybozu::CpuClock clk; #include <cybozu/test.hpp> -#include <mcl/bls12_381.hpp> +#include <mcl/bn384.hpp> #include <cybozu/option.hpp> #include <cybozu/xorshift.hpp> @@ -11,13 +11,12 @@ cybozu::CpuClock clk; #define MCL_AVOID_EXCEPTION_TEST #endif -//typedef mcl::bls12::BLS12::Compress Compress; -using namespace mcl::bls12_381; +using namespace mcl::bn384; mcl::fp::Mode g_mode; const struct TestSet { - mcl::bls12::CurveParam cp; + mcl::CurveParam cp; const char *name; const char *p; const char *r; @@ -34,8 +33,8 @@ const struct TestSet { const char *e; } g_testSetTbl[] = { { - mcl::bls12::CurveFp381, - "CurveFp381", + mcl::BLS12_381, + "BLS12_381", "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", { @@ -75,14 +74,14 @@ CYBOZU_TEST_AUTO(size) void testParam(const TestSet& ts) { - CYBOZU_TEST_EQUAL(BLS12::param.r, mpz_class(ts.r)); - CYBOZU_TEST_EQUAL(BLS12::param.p, mpz_class(ts.p)); + CYBOZU_TEST_EQUAL(BN::param.r, mpz_class(ts.r)); + CYBOZU_TEST_EQUAL(BN::param.p, mpz_class(ts.p)); } void finalExpC(Fp12& y, const Fp12& x) { - const mpz_class& r = BLS12::param.r; - const mpz_class& p = BLS12::param.p; + const mpz_class& r = BN::param.r; + const mpz_class& p = BN::param.p; mpz_class p2 = p * p; mpz_class p4 = p2 * p2; #if 1 @@ -96,8 +95,8 @@ void finalExpC(Fp12& y, const Fp12& x) void pairingC(Fp12& e, const G1& P, const G2& Q) { - BLS12::millerLoop(e, P, Q); - BLS12::finalExp(e, e); + millerLoop(e, P, Q); + finalExp(e, e); } void testIoAll(const G1& P, const G2& Q) { @@ -153,10 +152,10 @@ void testMapToG1() { G1 g; for (int i = 1; i < 10; i++) { - BLS12::mapToG1(g, i); + mapToG1(g, i); CYBOZU_TEST_ASSERT(!g.isZero()); G1 gr; - G1::mul(gr, g, BLS12::param.r); + G1::mul(gr, g, BN::param.r); CYBOZU_TEST_ASSERT(gr.isZero()); } } @@ -165,26 +164,26 @@ void testMapToG2() { G2 g; for (int i = 1; i < 10; i++) { - BLS12::mapToG2(g, i); + mapToG2(g, i); CYBOZU_TEST_ASSERT(!g.isZero()); G2 gr; - G2::mul(gr, g, BLS12::param.r); + G2::mul(gr, g, BN::param.r); CYBOZU_TEST_ASSERT(gr.isZero()); } Fp x; x.setHashOf("abc"); - BLS12::mapToG2(g, Fp2(x, 0)); + mapToG2(g, Fp2(x, 0)); CYBOZU_TEST_ASSERT(g.isValid()); } void testPrecomputed(const G1& P, const G2& Q) { Fp12 e1, e2; - BLS12::pairing(e1, P, Q); + pairing(e1, P, Q); std::vector<Fp6> Qcoeff; - BLS12::precomputeG2(Qcoeff, Q); - BLS12::precomputedMillerLoop(e2, P, Qcoeff); - BLS12::finalExp(e2, e2); + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e2, P, Qcoeff); + finalExp(e2, e2); CYBOZU_TEST_EQUAL(e1, e2); } @@ -192,7 +191,7 @@ void testPrecomputed(const G1& P, const G2& Q) void testFp12pow(const G1& P, const G2& Q) { Fp12 e, e1, e2; - BLS12::pairing(e, P, Q); + pairing(e, P, Q); cybozu::XorShift rg; for (int i = -10; i < 10; i++) { mpz_class xm = i; @@ -205,7 +204,7 @@ void testFp12pow(const G1& P, const G2& Q) x.setRand(rg); mpz_class xm = x.getMpz(); Fp12::pow(e1, e, xm); - BLS12::param.glv2.pow(e2, e, xm); + param.glv2.pow(e2, e, xm); CYBOZU_TEST_EQUAL(e1, e2); } } @@ -220,22 +219,22 @@ void testMillerLoop2(const G1& P1, const G2& Q1) G1 P2; G2::mul(Q2, Q1, c1); G1::mul(P2, P1, c2); - BLS12::pairing(e1, P1, Q1); - BLS12::pairing(e2, P2, Q2); + pairing(e1, P1, Q1); + pairing(e2, P2, Q2); e1 *= e2; std::vector<Fp6> Q1coeff, Q2coeff; - BLS12::precomputeG2(Q1coeff, Q1); - BLS12::precomputeG2(Q2coeff, Q2); - BLS12::precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff); - BLS12::finalExp(e2, e2); + precomputeG2(Q1coeff, Q1); + precomputeG2(Q2coeff, Q2); + precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff); + finalExp(e2, e2); CYBOZU_TEST_EQUAL(e1, e2); } void testPairing(const G1& P, const G2& Q, const char *eStr) { Fp12 e1; - BLS12::pairing(e1, P, Q); + pairing(e1, P, Q); Fp12 e2; { std::stringstream ss(eStr); @@ -262,8 +261,8 @@ void testPairing(const G1& P, const G2& Q, const char *eStr) G1 T; G1::mulCT(T, P, a); CYBOZU_TEST_EQUAL(Pa, T); - BLS12::pairing(e1, Pa, Q); - BLS12::pairing(e2, P, Qa); + pairing(e1, Pa, Q); + pairing(e2, P, Qa); CYBOZU_TEST_EQUAL(ea, e1); CYBOZU_TEST_EQUAL(ea, e2); } @@ -274,22 +273,22 @@ void testTrivial(const G1& P, const G2& Q) G1 Z1; Z1.clear(); G2 Z2; Z2.clear(); Fp12 e; - BLS12::pairing(e, Z1, Q); + pairing(e, Z1, Q); CYBOZU_TEST_EQUAL(e, 1); - BLS12::pairing(e, P, Z2); + pairing(e, P, Z2); CYBOZU_TEST_EQUAL(e, 1); - BLS12::pairing(e, Z1, Z2); + pairing(e, Z1, Z2); CYBOZU_TEST_EQUAL(e, 1); std::vector<Fp6> Qcoeff; - BLS12::precomputeG2(Qcoeff, Z2); - BLS12::precomputedMillerLoop(e, P, Qcoeff); - BLS12::finalExp(e, e); + precomputeG2(Qcoeff, Z2); + precomputedMillerLoop(e, P, Qcoeff); + finalExp(e, e); CYBOZU_TEST_EQUAL(e, 1); - BLS12::precomputeG2(Qcoeff, Q); - BLS12::precomputedMillerLoop(e, Z1, Qcoeff); - BLS12::finalExp(e, e); + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e, Z1, Qcoeff); + finalExp(e, e); CYBOZU_TEST_EQUAL(e, 1); } @@ -306,7 +305,7 @@ CYBOZU_TEST_AUTO(naive) #ifdef ONLY_BENCH { Fp12 e; - for (int i = 0; i < 1000; i++) BLS12::pairing(e, P, Q); + for (int i = 0; i < 1000; i++) pairing(e, P, Q); } clk.put(); return; @@ -321,7 +320,7 @@ CYBOZU_TEST_AUTO(naive) testPairing(P, Q, ts.e); testPrecomputed(P, Q); testMillerLoop2(P, Q); - testBench<BLS12>(P, Q); + testBench(P, Q); } int count = (int)clk.getCount(); if (count) { @@ -363,10 +362,10 @@ const char *e1Str = Fp12 e0, e1, e2; e0.setStr(e0Str, 16); e1.setStr(e1Str, 16); - BLS12::finalExp(e2, e0); + finalExp(e2, e0); // finalExpC(e2, e0); CYBOZU_TEST_EQUAL(e1, e2); - CYBOZU_BENCH_C("finalExp", 100, BLS12::finalExp, e2, e0); + CYBOZU_BENCH_C("finalExp", 100, finalExp, e2, e0); } CYBOZU_TEST_AUTO(addLine) @@ -431,7 +430,7 @@ const char *r1Str = l.a.setStr(l0Str, mode); l.b.setStr(l4Str, mode); l.c.setStr(l1Str, mode); - BLS12::addLine(l, R, Q, P); + local::addLine(l, R, Q, P); m.a.setStr(m0Str, mode); m.b.setStr(m4Str, mode); m.c.setStr(m1Str, mode); @@ -489,18 +488,20 @@ const char *q1Str = G2 Q, Q1; G1 P; + G1::setOrder(0); Q.setStr(qStr, mode); P.setStr(pStr, mode); l.a.setStr(l0Str, mode); l.b.setStr(l4Str, mode); l.c.setStr(l1Str, mode); - BLS12::dblLine(l, Q, P); + local::dblLine(l, Q, P); m.a.setStr(m0Str, mode); m.b.setStr(m4Str, mode); m.c.setStr(m1Str, mode); Q1.setStr(q1Str, mode); CYBOZU_TEST_EQUAL(l, m); CYBOZU_TEST_EQUAL(Q, Q1); + G1::setOrder(BN::param.r); } CYBOZU_TEST_AUTO(mul_012) @@ -550,7 +551,7 @@ const char *f2Str = l.c.setStr(l1Str, 16); f.setStr(fStr, 16); f2.setStr(f2Str, 16); - BLS12::mulSparse(f, l); + local::mulSparse(f, l); CYBOZU_TEST_EQUAL(f, f2); } @@ -588,10 +589,46 @@ const char *eStr = Q.setStr(qStr, mode); Fp12 e1, e2; e1.setStr(eStr, 16); - BLS12::pairing(e2, P, Q); + pairing(e2, P, Q); CYBOZU_TEST_EQUAL(e1, e2); } +void testCurve(const mcl::CurveParam& cp) +{ + initPairing(cp, g_mode); + G1 P; + G2 Q; + mapToG1(P, 1); + mapToG2(Q, 1); + GT e1, e2; + pairing(e1, P, Q); + cybozu::XorShift rg; + mpz_class a, b; + Fr r; + r.setRand(rg); a = r.getMpz(); + r.setRand(rg); b = r.getMpz(); + G1 aP; + G2 bQ; + G1::mul(aP, P, a); + G2::mul(bQ, Q, b); + pairing(e2, aP, bQ); + GT::pow(e1, e1, a * b); + CYBOZU_TEST_EQUAL(e1, e2); +} +CYBOZU_TEST_AUTO(multi) +{ + puts("BN254"); + testCurve(mcl::BN254); + puts("BLS12_381"); + testCurve(mcl::BLS12_381); +} + +CYBOZU_TEST_AUTO(BLS12_G1mulCofactor) +{ + if (BN::param.cp.curveType != MCL_BLS12_381) return; + +} + int main(int argc, char *argv[]) try { diff --git a/test/bn384_test.cpp b/test/bn384_test.cpp index ea36284..11f1690 100644 --- a/test/bn384_test.cpp +++ b/test/bn384_test.cpp @@ -12,15 +12,15 @@ mcl::fp::Mode g_mode; #include "bench.hpp" -void testCurve(const mcl::bn::CurveParam& cp) +void testCurve(const mcl::CurveParam& cp) { initPairing(cp, g_mode); G1 P; G2 Q; - BN::mapToG1(P, 1); - BN::mapToG2(Q, 1); + mapToG1(P, 1); + mapToG2(Q, 1); GT e1, e2; - BN::pairing(e1, P, Q); + pairing(e1, P, Q); cybozu::XorShift rg; mpz_class a, b; Fr r; @@ -30,21 +30,23 @@ void testCurve(const mcl::bn::CurveParam& cp) G2 bQ; G1::mul(aP, P, a); G2::mul(bQ, Q, b); - BN::pairing(e2, aP, bQ); + pairing(e2, aP, bQ); GT::pow(e1, e1, a * b); CYBOZU_TEST_EQUAL(e1, e2); - testBench<BN>(P, Q); + testBench(P, Q); } CYBOZU_TEST_AUTO(pairing) { - puts("CurveFp254BNb"); + puts("BN254"); // support 256-bit pairing - testCurve(mcl::bn::CurveFp254BNb); - puts("CurveFp382_1"); - testCurve(mcl::bn::CurveFp382_1); - puts("CurveFp382_2"); - testCurve(mcl::bn::CurveFp382_2); + testCurve(mcl::BN254); + puts("BN381_1"); + testCurve(mcl::BN381_1); + puts("BN381_2"); + testCurve(mcl::BN381_2); + puts("BLS12_381"); + testCurve(mcl::BLS12_381); // Q is not on EcT, but bad order { const char *s = "1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50"; diff --git a/test/bn512_test.cpp b/test/bn512_test.cpp index a5bc660..dde8950 100644 --- a/test/bn512_test.cpp +++ b/test/bn512_test.cpp @@ -12,15 +12,15 @@ mcl::fp::Mode g_mode; #include "bench.hpp" -void testCurve(const mcl::bn::CurveParam& cp) +void testCurve(const mcl::CurveParam& cp) { initPairing(cp, g_mode); G1 P; G2 Q; - BN::mapToG1(P, 1); - BN::mapToG2(Q, 1); + mapToG1(P, 1); + mapToG2(Q, 1); GT e1, e2; - BN::pairing(e1, P, Q); + pairing(e1, P, Q); cybozu::XorShift rg; mpz_class a, b; Fr r; @@ -30,22 +30,22 @@ void testCurve(const mcl::bn::CurveParam& cp) G2 bQ; G1::mul(aP, P, a); G2::mul(bQ, Q, b); - BN::pairing(e2, aP, bQ); + pairing(e2, aP, bQ); GT::pow(e1, e1, a * b); CYBOZU_TEST_EQUAL(e1, e2); - testBench<BN>(P, Q); + testBench(P, Q); } CYBOZU_TEST_AUTO(pairing) { - puts("CurveFp462"); - testCurve(mcl::bn::CurveFp462); - puts("CurveFp382_1"); - testCurve(mcl::bn::CurveFp382_1); - puts("CurveFp382_2"); - testCurve(mcl::bn::CurveFp382_2); - puts("CurveFp254BNb"); - testCurve(mcl::bn::CurveFp254BNb); + puts("BN462"); + testCurve(mcl::BN462); + puts("BN381_1"); + testCurve(mcl::BN381_1); + puts("BLS12_381"); + testCurve(mcl::BLS12_381); + puts("BN254"); + testCurve(mcl::BN254); } int main(int argc, char *argv[]) diff --git a/test/bn_c_test.hpp b/test/bn_c_test.hpp index 305e35b..5f34d2f 100644 --- a/test/bn_c_test.hpp +++ b/test/bn_c_test.hpp @@ -28,14 +28,14 @@ CYBOZU_TEST_AUTO(init) // CYBOZU_TEST_EQUAL(ret, 0); #if MCLBN_FP_UNIT_SIZE == 4 - printf("test MCLBN_curveFp254BNb %d\n", MCLBN_FP_UNIT_SIZE); - ret = mclBn_init(mclBn_CurveFp254BNb, MCLBN_FP_UNIT_SIZE); + printf("test BN254 %d\n", MCLBN_FP_UNIT_SIZE); + ret = mclBn_init(MCL_BN254, MCLBN_FP_UNIT_SIZE); #elif MCLBN_FP_UNIT_SIZE == 6 - printf("test MCLBN_curveFp382_1 %d\n", MCLBN_FP_UNIT_SIZE); - ret = mclBn_init(mclBn_CurveFp382_1, MCLBN_FP_UNIT_SIZE); + printf("test BN381_1 %d\n", MCLBN_FP_UNIT_SIZE); + ret = mclBn_init(MCL_BN381_1, MCLBN_FP_UNIT_SIZE); #elif MCLBN_FP_UNIT_SIZE == 8 - printf("test MCLBN_curveFp462 %d\n", MCLBN_FP_UNIT_SIZE); - ret = mclBn_init(mclBn_CurveFp462, MCLBN_FP_UNIT_SIZE); + printf("test BN462 %d\n", MCLBN_FP_UNIT_SIZE); + ret = mclBn_init(MCL_BN462, MCLBN_FP_UNIT_SIZE); #else #error "bad MCLBN_FP_UNIT_SIZE" #endif @@ -421,7 +421,7 @@ CYBOZU_TEST_AUTO(serialize) CYBOZU_TEST_AUTO(badG2) { int ret; - ret = mclBn_init(mclBn_CurveFp382_1, MCLBN_FP_UNIT_SIZE); + ret = mclBn_init(MCL_BN381_1, MCLBN_FP_UNIT_SIZE); CYBOZU_TEST_EQUAL(ret, 0); const char *s = "1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50"; mclBnG2 Q; diff --git a/test/bn_test.cpp b/test/bn_test.cpp index 2c82746..c33e1d9 100644 --- a/test/bn_test.cpp +++ b/test/bn_test.cpp @@ -11,13 +11,13 @@ cybozu::CpuClock clk; #define MCL_AVOID_EXCEPTION_TEST #endif -typedef mcl::bn256::BN::Compress Compress; +typedef mcl::bn::local::Compress Compress; using namespace mcl::bn256; mcl::fp::Mode g_mode; const struct TestSet { - mcl::bn::CurveParam cp; + mcl::CurveParam cp; const char *name; struct G2 { const char *aa; @@ -32,8 +32,8 @@ const struct TestSet { const char *e; } g_testSetTbl[] = { { - mcl::bn::CurveFp254BNb, - "CurveFp254BNb", + mcl::BN254, + "BN254", { "12723517038133731887338407189719511622662176727675373276651903807414909099441", "4168783608814932154536427934509895782246573715297911553964171371032945126671", @@ -57,8 +57,8 @@ const struct TestSet { "10688745994254573144943003027511098295097561129365638275727908595677791826005" }, { - mcl::bn::CurveSNARK1, - "CurveSNARK1", + mcl::BN_SNARK1, + "BN_SNARK1", { "15267802884793550383558706039165621050290089775961208824303765753922461897946", "9034493566019742339402378670461897774509967669562610788113215988055021632533", @@ -110,7 +110,7 @@ void testMapToG1() { G1 g; for (int i = 1; i < 10; i++) { - BN::mapToG1(g, i); + mapToG1(g, i); CYBOZU_TEST_ASSERT(!g.isZero()); G1 gr; G1::mulGeneric(gr, g, BN::param.r); @@ -118,9 +118,9 @@ void testMapToG1() } #ifndef MCL_AVOID_EXCEPTION_TEST if (BN::param.cp.b == 2) { - CYBOZU_TEST_EXCEPTION(BN::mapToG1(g, 0), cybozu::Exception); - CYBOZU_TEST_EXCEPTION(BN::mapToG1(g, BN::param.mapTo.c1_), cybozu::Exception); - CYBOZU_TEST_EXCEPTION(BN::mapToG1(g, -BN::param.mapTo.c1_), cybozu::Exception); + CYBOZU_TEST_EXCEPTION(mapToG1(g, 0), cybozu::Exception); + CYBOZU_TEST_EXCEPTION(mapToG1(g, BN::param.mapTo.c1_), cybozu::Exception); + CYBOZU_TEST_EXCEPTION(mapToG1(g, -BN::param.mapTo.c1_), cybozu::Exception); } #endif } @@ -129,7 +129,7 @@ void testMapToG2() { G2 g; for (int i = 1; i < 10; i++) { - BN::mapToG2(g, i); + mapToG2(g, i); CYBOZU_TEST_ASSERT(!g.isZero()); G2 gr; G2::mulGeneric(gr, g, BN::param.r); @@ -137,12 +137,12 @@ void testMapToG2() } #ifndef MCL_AVOID_EXCEPTION_TEST if (BN::param.cp.b == 2) { - CYBOZU_TEST_EXCEPTION(BN::mapToG2(g, 0), cybozu::Exception); + CYBOZU_TEST_EXCEPTION(mapToG2(g, 0), cybozu::Exception); } #endif Fp x; x.setHashOf("abc"); - BN::mapToG2(g, Fp2(x, 0)); + mapToG2(g, Fp2(x, 0)); CYBOZU_TEST_ASSERT(g.isValid()); } @@ -152,7 +152,7 @@ void testCyclotomic() for (int i = 0; i < 12; ++i) { a.getFp0()[i] = i * i; } - BN::mapToCyclotomic(a, a); + local::mapToCyclotomic(a, a); Fp12 d; Compress b(d, a); a *= a; @@ -168,10 +168,10 @@ void testCyclotomic() void testCompress(const G1& P, const G2& Q) { - if (BN::param.cp.curveType != mclBn_CurveFp254BNb) return; + if (BN::param.cp.curveType != MCL_BN254) return; Fp12 a; - BN::pairing(a, P, Q); - BN::mapToCyclotomic(a, a); + pairing(a, P, Q); + local::mapToCyclotomic(a, a); Fp12 b; Compress::fixed_power(b, a); Fp12 c; @@ -182,18 +182,18 @@ void testCompress(const G1& P, const G2& Q) void testPrecomputed(const G1& P, const G2& Q) { Fp12 e1, e2; - BN::pairing(e1, P, Q); + pairing(e1, P, Q); std::vector<Fp6> Qcoeff; - BN::precomputeG2(Qcoeff, Q); - BN::precomputedMillerLoop(e2, P, Qcoeff); - BN::finalExp(e2, e2); + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e2, P, Qcoeff); + finalExp(e2, e2); CYBOZU_TEST_EQUAL(e1, e2); } void testFp12pow(const G1& P, const G2& Q) { Fp12 e, e1, e2; - BN::pairing(e, P, Q); + pairing(e, P, Q); cybozu::XorShift rg; for (int i = -10; i < 10; i++) { mpz_class xm = i; @@ -220,22 +220,22 @@ void testMillerLoop2(const G1& P1, const G2& Q1) G1 P2; G2::mul(Q2, Q1, c1); G1::mul(P2, P1, c2); - BN::pairing(e1, P1, Q1); - BN::pairing(e2, P2, Q2); + pairing(e1, P1, Q1); + pairing(e2, P2, Q2); e1 *= e2; std::vector<Fp6> Q1coeff, Q2coeff; - BN::precomputeG2(Q1coeff, Q1); - BN::precomputeG2(Q2coeff, Q2); - BN::precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff); - BN::finalExp(e2, e2); + precomputeG2(Q1coeff, Q1); + precomputeG2(Q2coeff, Q2); + precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff); + finalExp(e2, e2); CYBOZU_TEST_EQUAL(e1, e2); } void testPairing(const G1& P, const G2& Q, const char *eStr) { Fp12 e1; - BN::pairing(e1, P, Q); + pairing(e1, P, Q); Fp12 e2; { std::stringstream ss(eStr); @@ -263,8 +263,8 @@ void testPairing(const G1& P, const G2& Q, const char *eStr) G1 T; G1::mulCT(T, P, a); CYBOZU_TEST_EQUAL(Pa, T); - BN::pairing(e1, Pa, Q); - BN::pairing(e2, P, Qa); + pairing(e1, Pa, Q); + pairing(e2, P, Qa); CYBOZU_TEST_EQUAL(ea, e1); CYBOZU_TEST_EQUAL(ea, e2); } @@ -275,22 +275,22 @@ void testTrivial(const G1& P, const G2& Q) G1 Z1; Z1.clear(); G2 Z2; Z2.clear(); Fp12 e; - BN::pairing(e, Z1, Q); + pairing(e, Z1, Q); CYBOZU_TEST_EQUAL(e, 1); - BN::pairing(e, P, Z2); + pairing(e, P, Z2); CYBOZU_TEST_EQUAL(e, 1); - BN::pairing(e, Z1, Z2); + pairing(e, Z1, Z2); CYBOZU_TEST_EQUAL(e, 1); std::vector<Fp6> Qcoeff; - BN::precomputeG2(Qcoeff, Z2); - BN::precomputedMillerLoop(e, P, Qcoeff); - BN::finalExp(e, e); + precomputeG2(Qcoeff, Z2); + precomputedMillerLoop(e, P, Qcoeff); + finalExp(e, e); CYBOZU_TEST_EQUAL(e, 1); - BN::precomputeG2(Qcoeff, Q); - BN::precomputedMillerLoop(e, Z1, Qcoeff); - BN::finalExp(e, e); + precomputeG2(Qcoeff, Q); + precomputedMillerLoop(e, Z1, Qcoeff); + finalExp(e, e); CYBOZU_TEST_EQUAL(e, 1); } @@ -344,7 +344,7 @@ CYBOZU_TEST_AUTO(naive) #ifdef ONLY_BENCH { Fp12 e; - for (int i = 0; i < 1000; i++) BN::pairing(e, P, Q); + for (int i = 0; i < 1000; i++) pairing(e, P, Q); } clk.put(); return; @@ -360,7 +360,7 @@ CYBOZU_TEST_AUTO(naive) testPairing(P, Q, ts.e); testPrecomputed(P, Q); testMillerLoop2(P, Q); - testBench<BN>(P, Q); + testBench(P, Q); } int count = (int)clk.getCount(); if (count) { diff --git a/test/glv_test.cpp b/test/glv_test.cpp index db7b9a8..a917f51 100644 --- a/test/glv_test.cpp +++ b/test/glv_test.cpp @@ -80,9 +80,9 @@ template<class GLV1, class GLV2> void compareLength(const GLV1& rhs, const GLV2& lhs) { cybozu::XorShift rg; - int Rc = 0; - int Lc = 0; + int lt = 0; int eq = 0; + int gt = 0; mpz_class R0, R1, L0, L1, x; Fr r; for (int i = 1; i < 1000; i++) { @@ -101,30 +101,34 @@ void compareLength(const GLV1& rhs, const GLV2& lhs) eq++; } if (Rn > Ln) { - Rc++; + gt++; } if (Rn < Ln) { - Lc++; + lt++; } } - printf("eq=%d small is better rhs=%d, lhs=%d\n", eq, Rc, Lc); + printf("#of{<} = %d, #of{=} = %d #of{>} = %d\n", lt, eq, gt); } void testGLV1() { G1 P0, P1, P2; - BN::mapToG1(P0, 1); + mapToG1(P0, 1); cybozu::XorShift rg; oldGLV oldGlv; - oldGlv.init(BN::param.r, BN::param.z); + if (!BN::param.isBLS12) { + oldGlv.init(BN::param.r, BN::param.z); + } - mcl::bn::GLV1<Fp> glv; - glv.init(BN::param.r, BN::param.z); - compareLength(glv, oldGlv); + mcl::bn::local::GLV1 glv; + glv.init(BN::param.r, BN::param.z, BN::param.isBLS12); + if (!BN::param.isBLS12) { + compareLength(glv, oldGlv); + } for (int i = 1; i < 100; i++) { - BN::mapToG1(P0, i); + mapToG1(P0, i); Fr s; s.setRand(rg); mpz_class ss = s.getMpz(); @@ -133,8 +137,10 @@ void testGLV1() CYBOZU_TEST_EQUAL(P1, P2); glv.mul(P2, P0, ss, true); CYBOZU_TEST_EQUAL(P1, P2); - oldGlv.mul(P2, P0, ss); - CYBOZU_TEST_EQUAL(P1, P2); + if (!BN::param.isBLS12) { + oldGlv.mul(P2, P0, ss); + CYBOZU_TEST_EQUAL(P1, P2); + } } for (int i = -100; i < 100; i++) { mpz_class ss = i; @@ -145,7 +151,7 @@ void testGLV1() CYBOZU_TEST_EQUAL(P1, P2); } Fr s; - BN::mapToG1(P0, 123); + mapToG1(P0, 123); CYBOZU_BENCH_C("Ec::mul", 100, P1 = P0; s.setRand(rg); G1::mulGeneric, P2, P1, s.getMpz()); CYBOZU_BENCH_C("Ec::glv", 100, P1 = P0; s.setRand(rg); glv.mul, P2, P1, s.getMpz()); } @@ -160,11 +166,11 @@ void testGLV2() mpz_class z = BN::param.z; mpz_class r = BN::param.r; mpz_class lambda = 6 * z * z; - mcl::bn::GLV2<Fp2> glv2; - glv2.init(r, z); + mcl::bn::local::GLV2 glv2; + glv2.init(r, z, BN::param.isBLS12); mpz_class n; cybozu::XorShift rg; - BN::mapToG2(Q0, 1); + mapToG2(Q0, 1); for (int i = -10; i < 10; i++) { n = i; G2::mulGeneric(Q1, Q0, n); @@ -172,28 +178,30 @@ void testGLV2() CYBOZU_TEST_EQUAL(Q1, Q2); } for (int i = 1; i < 100; i++) { - mcl::gmp::getRand(n, glv2.m, rg); + mcl::gmp::getRand(n, glv2.rBitSize, rg); n %= r; - BN::mapToG2(Q0, i); + n -= r/2; + mapToG2(Q0, i); G2::mulGeneric(Q1, Q0, n); glv2.mul(Q2, Q0, n); CYBOZU_TEST_EQUAL(Q1, Q2); } Fr s; - BN::mapToG2(Q0, 123); + mapToG2(Q0, 123); CYBOZU_BENCH_C("G2::mul", 1000, Q2 = Q0; s.setRand(rg); G2::mulGeneric, Q2, Q1, s.getMpz()); CYBOZU_BENCH_C("G2::glv", 1000, Q1 = Q0; s.setRand(rg); glv2.mul, Q2, Q1, s.getMpz()); } CYBOZU_TEST_AUTO(glv) { - const mcl::bn::CurveParam tbl[] = { - mcl::bn::CurveFp254BNb, - mcl::bn::CurveFp382_1, - mcl::bn::CurveFp382_2, + const mcl::CurveParam tbl[] = { + mcl::BN254, + mcl::BN381_1, + mcl::BN381_2, + mcl::BLS12_381, }; for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { - const mcl::bn::CurveParam& cp = tbl[i]; + const mcl::CurveParam& cp = tbl[i]; initPairing(cp); testGLV1(); testGLV2(); diff --git a/test/she_c384_test.cpp b/test/she_c384_test.cpp new file mode 100644 index 0000000..5c7bd98 --- /dev/null +++ b/test/she_c384_test.cpp @@ -0,0 +1,2 @@ +#define MCLBN_FP_UNIT_SIZE 6 +#include "she_c_test.hpp" diff --git a/test/she_c_test.hpp b/test/she_c_test.hpp index 7c7d659..912fda0 100644 --- a/test/she_c_test.hpp +++ b/test/she_c_test.hpp @@ -11,11 +11,12 @@ CYBOZU_TEST_AUTO(init) { int curve; #if MCLBN_FP_UNIT_SIZE == 4 - curve = mclBn_CurveFp254BNb; + curve = MCL_BN254; #elif MCLBN_FP_UNIT_SIZE == 6 - curve = mclBn_CurveFp382_1; +// curve = MCL_BN381_1; + curve = MCL_BLS12_381; #elif MCLBN_FP_UNIT_SIZE == 8 - curve = mclBn_CurveFp462; + curve = MCL_BN462; #endif int ret; ret = sheInit(curve, MCLBN_FP_UNIT_SIZE); @@ -97,15 +98,24 @@ CYBOZU_TEST_AUTO(allOp) int64_t m2 = -9; int64_t m3 = 12; int64_t m4 = -9; + int64_t dec; sheCipherTextG1 c11, c12; sheCipherTextG2 c21, c22; sheCipherTextGT ct; + sheEncG1(&c11, &pub, m1); + sheNegG1(&c12, &c11); + CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c12), 0); + CYBOZU_TEST_EQUAL(dec, -m1); + sheEncG1(&c12, &pub, m2); sheSubG1(&c11, &c11, &c12); // m1 - m2 sheMulG1(&c11, &c11, 4); // 4 * (m1 - m2) sheEncG2(&c21, &pub, m3); + sheNegG2(&c22, &c21); + CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c22), 0); + CYBOZU_TEST_EQUAL(dec, -m3); sheEncG2(&c22, &pub, m4); sheSubG2(&c21, &c21, &c22); // m3 - m4 sheMulG2(&c21, &c21, -5); // -5 * (m3 - m4) @@ -114,9 +124,13 @@ CYBOZU_TEST_AUTO(allOp) sheMulGT(&ct, &ct, -4); // 160 * (m1 - m2) * (m3 - m4) int64_t t = 160 * (m1 - m2) * (m3 - m4); - int64_t dec; CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0); CYBOZU_TEST_EQUAL(dec, t); + + sheCipherTextGT ct2; + sheNegGT(&ct2, &ct); + CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct2), 0); + CYBOZU_TEST_EQUAL(dec, -t); } CYBOZU_TEST_AUTO(rerand) @@ -157,10 +171,11 @@ CYBOZU_TEST_AUTO(serialize) shePublicKey pub1, pub2; sheGetPublicKey(&pub1, &sec1); - char buf1[2048], buf2[2048]; + char buf1[4096], buf2[4096]; size_t n1, n2; size_t r, size; - const size_t sizeofFr = mclBn_getOpUnitSize() * 8; + const size_t sizeofFr = mclBn_getFrByteSize(); + const size_t sizeofFp = mclBn_getG1ByteSize(); size = sizeofFr * 2; n1 = sheSecretKeySerialize(buf1, sizeof(buf1), &sec1); @@ -171,7 +186,7 @@ CYBOZU_TEST_AUTO(serialize) CYBOZU_TEST_EQUAL(n2, size); CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2); - size = sizeofFr * 3; + size = sizeofFp * 3; n1 = shePublicKeySerialize(buf1, sizeof(buf1), &pub1); CYBOZU_TEST_EQUAL(n1, size); r = shePublicKeyDeserialize(&pub2, buf1, n1); @@ -188,7 +203,7 @@ CYBOZU_TEST_AUTO(serialize) sheEncG2(&c21, &pub2, m); sheEncGT(&ct1, &pub2, m); - size = sizeofFr * 2; + size = sizeofFp * 2; n1 = sheCipherTextG1Serialize(buf1, sizeof(buf1), &c11); CYBOZU_TEST_EQUAL(n1, size); r = sheCipherTextG1Deserialize(&c12, buf1, n1); @@ -197,7 +212,7 @@ CYBOZU_TEST_AUTO(serialize) CYBOZU_TEST_EQUAL(n2, size); CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2); - size = sizeofFr * 4; + size = sizeofFp * 4; n1 = sheCipherTextG2Serialize(buf1, sizeof(buf1), &c21); CYBOZU_TEST_EQUAL(n1, size); r = sheCipherTextG2Deserialize(&c22, buf1, n1); @@ -206,7 +221,7 @@ CYBOZU_TEST_AUTO(serialize) CYBOZU_TEST_EQUAL(n2, size); CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2); - size = sizeofFr * 12 * 4; + size = sizeofFp * 12 * 4; n1 = sheCipherTextGTSerialize(buf1, sizeof(buf1), &ct1); CYBOZU_TEST_EQUAL(n1, size); r = sheCipherTextGTDeserialize(&ct2, buf1, n1); @@ -284,13 +299,15 @@ void ZkpBinTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZk CYBOZU_TEST_EQUAL(mDec, m); CYBOZU_TEST_EQUAL(verify(pub, &c, &zkp), 1); { - char buf[2048]; + char buf[4096]; size_t n = sheZkpBinSerialize(buf, sizeof(buf), &zkp); - CYBOZU_TEST_EQUAL(n, mclBn_getOpUnitSize() * 8 * 4); + CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * 4); sheZkpBin zkp2; size_t r = sheZkpBinDeserialize(&zkp2, buf, n); CYBOZU_TEST_EQUAL(r, n); - CYBOZU_TEST_ASSERT(memcmp(&zkp, &zkp2, n) == 0); + char buf2[4096]; + sheZkpBinSerialize(buf2, sizeof(buf2), &zkp2); + CYBOZU_TEST_EQUAL_ARRAY(buf, buf2, n); } zkp.d[0].d[0]++; CYBOZU_TEST_EQUAL(verify(pub, &c, &zkp), 0); @@ -472,6 +489,7 @@ CYBOZU_TEST_AUTO(saveLoad) const size_t n1 = sheSaveTableForGTDLP(&buf[0], buf.size()); CYBOZU_TEST_ASSERT(n1 > 0); if (!g_tableName.empty()) { + printf("use table=%s\n", g_tableName.c_str()); std::ofstream ofs(g_tableName.c_str(), std::ios::binary); ofs.write(buf.c_str(), n1); } @@ -482,6 +500,12 @@ CYBOZU_TEST_AUTO(saveLoad) sheSetTryNum(1); int64_t dec = 0; CYBOZU_TEST_ASSERT(sheDecGT(&dec, &sec, &ct) != 0); + if (!g_tableName.empty()) { + std::ifstream ifs(g_tableName.c_str(), std::ios::binary); + buf.clear(); + buf.resize(n1); + ifs.read(&buf[0], n1); + } const size_t n2 = sheLoadTableForGTDLP(&buf[0], n1); CYBOZU_TEST_ASSERT(n2 > 0); CYBOZU_TEST_ASSERT(sheDecGT(&dec, &sec, &ct) == 0); diff --git a/test/she_test.cpp b/test/she_test.cpp index ff5cb6e..aedadc0 100644 --- a/test/she_test.cpp +++ b/test/she_test.cpp @@ -14,18 +14,18 @@ SecretKey g_sec; CYBOZU_TEST_AUTO(log) { #if MCLBN_FP_UNIT_SIZE == 4 - const mcl::bn::CurveParam& cp = mcl::bn::CurveFp254BNb; - puts("CurveFp254BNb"); + const mcl::CurveParam& cp = mcl::BN254; + puts("BN254"); #elif MCLBN_FP_UNIT_SIZE == 6 - const mcl::bn::CurveParam& cp = mcl::bn::CurveFp382_1; - puts("CurveFp382_1"); + const mcl::CurveParam& cp = mcl::BN381_1; + puts("BN381_1"); #elif MCLBN_FP_UNIT_SIZE == 8 - const mcl::bn::CurveParam& cp = mcl::bn::CurveFp462; - puts("CurveFp462"); + const mcl::CurveParam& cp = mcl::BN462; + puts("BN462"); #endif - SHE::init(cp); + init(cp); G1 P; - BN::hashAndMapToG1(P, "abc"); + hashAndMapToG1(P, "abc"); for (int i = -5; i < 5; i++) { G1 iP; G1::mul(iP, P, i); @@ -43,15 +43,15 @@ double clk2msec(const cybozu::CpuClock& clk, int n) CYBOZU_TEST_AUTO(bench2) { - SHE::setRangeForDLP(1 << 21); - SHE::setTryNum(1 << 16); - SHE::useDecG1ViaGT(true); - SHE::useDecG2ViaGT(true); + setRangeForDLP(1 << 21); + setTryNum(1 << 16); + useDecG1ViaGT(true); + useDecG2ViaGT(true); #if 0 { const char *tblName = "../she-dlp-table/she-dlp-0-20-gt.bin"; std::ifstream ifs(tblName, std::ios::binary); - SHE::ePQhashTbl_.load(ifs); + ePQhashTbl_.load(ifs); } #endif SecretKey sec; @@ -115,49 +115,72 @@ CYBOZU_TEST_AUTO(bench2) } #endif -CYBOZU_TEST_AUTO(HashTable) +template<class G> +void HashTableTest(const G& P) { - mcl::she::local::HashTable<G1> hashTbl; - G1 P; - BN::hashAndMapToG1(P, "abc"); + mcl::she::local::HashTable<G> hashTbl; const int maxSize = 100; const int tryNum = 3; hashTbl.init(P, maxSize, tryNum); - for (int i = -maxSize; i <= maxSize; i++) { - G1 xP; - G1::mul(xP, P, i); - CYBOZU_TEST_EQUAL(hashTbl.basicLog(xP), i); - } - for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) { - G1 xP; - G1::mul(xP, P, i); - CYBOZU_TEST_EQUAL(hashTbl.log(xP), i); + for (int j = 0; j < 2; j++) { + for (int i = -maxSize; i <= maxSize; i++) { + G xP; + G::mul(xP, P, i); + CYBOZU_TEST_EQUAL(hashTbl.basicLog(xP), i); + } + for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) { + G xP; + G::mul(xP, P, i); + CYBOZU_TEST_EQUAL(hashTbl.log(xP), i); + } + std::stringstream ss; + hashTbl.save(ss); + mcl::she::local::HashTable<G> hashTbl2; + hashTbl2.load(ss); + hashTbl = hashTbl2; } } +CYBOZU_TEST_AUTO(HashTable) +{ + G1 P; + hashAndMapToG1(P, "abc"); + G2 Q; + hashAndMapToG2(Q, "abc"); + HashTableTest(P); + HashTableTest(Q); +} + CYBOZU_TEST_AUTO(GTHashTable) { mcl::she::local::HashTable<GT, false> hashTbl; GT g; { G1 P; - BN::hashAndMapToG1(P, "abc"); + hashAndMapToG1(P, "abc"); G2 Q; - BN::hashAndMapToG2(Q, "abc"); - BN::pairing(g, P, Q); + hashAndMapToG2(Q, "abc"); + pairing(g, P, Q); } const int maxSize = 100; const int tryNum = 3; hashTbl.init(g, maxSize, tryNum); - for (int i = -maxSize; i <= maxSize; i++) { - GT gx; - GT::pow(gx, g, i); - CYBOZU_TEST_EQUAL(hashTbl.basicLog(gx), i); - } - for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) { - GT gx; - GT::pow(gx, g, i); - CYBOZU_TEST_EQUAL(hashTbl.log(gx), i); + for (int j = 0; j < 2; j++) { + for (int i = -maxSize; i <= maxSize; i++) { + GT gx; + GT::pow(gx, g, i); + CYBOZU_TEST_EQUAL(hashTbl.basicLog(gx), i); + } + for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) { + GT gx; + GT::pow(gx, g, i); + CYBOZU_TEST_EQUAL(hashTbl.log(gx), i); + } + std::stringstream ss; + hashTbl.save(ss); + mcl::she::local::HashTable<GT, false> hashTbl2; + hashTbl2.load(ss); + hashTbl = hashTbl2; } } @@ -165,7 +188,7 @@ CYBOZU_TEST_AUTO(enc_dec) { SecretKey& sec = g_sec; sec.setByCSPRNG(); - SHE::setRangeForDLP(1024); + setRangeForDLP(1024); PublicKey pub; sec.getPublicKey(pub); CipherText c; @@ -460,7 +483,7 @@ T testIo(const T& x) CYBOZU_TEST_AUTO(io) { - SHE::setRangeForDLP(100); + setRangeForDLP(100); int64_t m; for (int i = 0; i < 2; i++) { if (i == 1) { @@ -513,7 +536,7 @@ CYBOZU_TEST_AUTO(bench) CYBOZU_TEST_AUTO(saveHash) { - mcl::she::local::HashTable<SHE::G1> hashTbl1, hashTbl2; + mcl::she::local::HashTable<G1> hashTbl1, hashTbl2; hashTbl1.init(SHE::P_, 1234, 123); std::stringstream ss; hashTbl1.save(ss); @@ -555,15 +578,15 @@ CYBOZU_TEST_AUTO(hashBench) const size_t hashSize = 1u << 21; clock_t begin = clock(), end; - SHE::setRangeForG1DLP(hashSize); + setRangeForG1DLP(hashSize); end = clock(); printf("init G1 DLP %f\n", double(end - begin) / CLOCKS_PER_SEC); begin = end; - SHE::setRangeForG2DLP(hashSize); + setRangeForG2DLP(hashSize); end = clock(); printf("init G2 DLP %f\n", double(end - begin) / CLOCKS_PER_SEC); begin = end; - SHE::setRangeForGTDLP(hashSize); + setRangeForGTDLP(hashSize); end = clock(); printf("init GT DLP %f\n", double(end - begin) / CLOCKS_PER_SEC); @@ -592,9 +615,9 @@ CYBOZU_TEST_AUTO(hashBench) r.setRand(); mr = r.getMpz(); } - BN::hashAndMapToG1(P, "abc"); - BN::hashAndMapToG2(Q, "abc"); - BN::pairing(e, P, Q); + hashAndMapToG1(P, "abc"); + hashAndMapToG2(Q, "abc"); + pairing(e, P, Q); P2.clear(); Q2.clear(); e2 = 1; @@ -622,9 +645,9 @@ CYBOZU_TEST_AUTO(hashBench) // CYBOZU_BENCH_C("GTwindow", C, wm.mul, static_cast<AG&>(e), mr); #endif - CYBOZU_BENCH_C("miller ", C, BN::millerLoop, e, P, Q); - CYBOZU_BENCH_C("finalExp", C, BN::finalExp, e, e); - CYBOZU_BENCH_C("precomML", C, BN::precomputedMillerLoop, e, P, SHE::Qcoeff_); + CYBOZU_BENCH_C("miller ", C, millerLoop, e, P, Q); + CYBOZU_BENCH_C("finalExp", C, finalExp, e, e); + CYBOZU_BENCH_C("precomML", C, precomputedMillerLoop, e, P, SHE::Qcoeff_); CipherTextG1 c1; CipherTextG2 c2; |