diff --git a/include/mcl/bn.hpp b/include/mcl/bn.hpp index 61886d0..7a19d0b 100644 --- a/include/mcl/bn.hpp +++ b/include/mcl/bn.hpp @@ -584,6 +584,10 @@ struct MapTo { } bool calc(G1& P, const Fp& t) const { + if (mapToMode_ == MCL_MAP_TO_MODE_HASH_TO_CURVE_07) { + mapTo_WB19_.FpToG1(P, t); + return true; + } if (!mapToEc(P, t)) return false; mulByCofactor(P); return true; diff --git a/include/mcl/mapto_wb19.hpp b/include/mcl/mapto_wb19.hpp index 17246d9..4ecaed9 100644 --- a/include/mcl/mapto_wb19.hpp +++ b/include/mcl/mapto_wb19.hpp @@ -599,6 +599,18 @@ struct MapTo_WB19 { } map2curve_osswu2(out, msg, msgSize, dst, strlen(dst)); } + void FpToG1(G1& out, const Fp& u0, const Fp *u1 = 0) const + { + E1 P1; + sswuG1(P1, u0); + if (u1) { + E1 P2; + sswuG1(P2, *u1); + ec::addJacobi(P1, P1, P2); + } + iso11(out, P1); + G1::mulGeneric(out, out, g1cofactor); + } void msgToG1(G1& out, const void *msg, size_t msgSize, const char *dst, size_t dstSize) const { assert(draftVersion_ == 7); @@ -610,12 +622,7 @@ struct MapTo_WB19 { u[i].setBigEndianMod(&b, &md[64 * i], 64); assert(b); (void)b; } - E1 P1, P2; - sswuG1(P1, u[0]); - sswuG1(P2, u[1]); - ec::addJacobi(P1, P1, P2); - iso11(out, P1); - G1::mulGeneric(out, out, g1cofactor); + FpToG1(out, u[0], &u[1]); } void msgToG1(G1& out, const void *msg, size_t msgSize) const { diff --git a/include/mcl/op.hpp b/include/mcl/op.hpp index 3993f1e..2d2a72e 100644 --- a/include/mcl/op.hpp +++ b/include/mcl/op.hpp @@ -23,7 +23,7 @@ namespace mcl { -static const int version = 0x120; /* 0xABC = A.BC */ +static const int version = 0x121; /* 0xABC = A.BC */ /* specifies available string format mode for X::setIoMode() diff --git a/readme.md b/readme.md index 742cb80..c1b1b56 100644 --- a/readme.md +++ b/readme.md @@ -10,7 +10,8 @@ mcl is a library for pairing-based cryptography, which supports the optimal Ate pairing over BN curves and BLS12-381 curves. # News -- `hashAndMapToG1` is compatible with [hash-to-curve-09 BLS12381G1_XMD:SHA-256_SSWU_RO_](https://www.ietf.org/id/draft-irtf-cfrg-hash-to-curve-09.html#name-bls12381g1_xmdsha-256_sswu_) +- `mcl::bn::mapToG1(G1& out, const Fp& v)` supports `BLS12_MAP_FP_TO_G1` in [EIP 2537](https://eips.ethereum.org/EIPS/eip-2537). +- `mcl::bn::hashAndMapToG1(G1& out, const void *msg, size_t msgSize)` supports ([hash-to-curve-09 BLS12381G1_XMD:SHA-256_SSWU_RO_](https://www.ietf.org/id/draft-irtf-cfrg-hash-to-curve-09.html#name-bls12381g1_xmdsha-256_sswu_)) - `MCL_MAP_TO_MODE_HASH_TO_CURVE_07` is added for [hash-to-curve-draft-07](https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/07/). - The older version will be removed in the future. - change DST of hash-to-curve for `MCL_MAP_TO_MODE_HASH_TO_CURVE_06`. @@ -313,6 +314,7 @@ If `MCL_USE_OLD_MAPTO_FOR_BLS12` is defined, then the old function is used, but # History +- 2020/Jun/04 v1.21 mapToG1 and hashAndMapToG1 are compatible to irtf/eip-2537 - 2020/May/13 v1.09 support draft-irtf-cfrg-hash-to-curve-07 - 2020/Mar/26 v1.07 change DST for hash-to-curve-06 - 2020/Mar/15 v1.06 support hash-to-curve-06 diff --git a/test/mapto_wb19_test.cpp b/test/mapto_wb19_test.cpp index 80a9663..7528ce1 100644 --- a/test/mapto_wb19_test.cpp +++ b/test/mapto_wb19_test.cpp @@ -1168,6 +1168,59 @@ CYBOZU_BENCH_C("msgToG1", 1000, mapto.msgToG1, P, msg, msgSize, dst, dstSize); } } +std::string appendZeroToRight(const std::string& s, size_t n) +{ + if (s.size() >= n) return s; + return std::string(n - s.size(), '0') + s; +} + +template +void testFpToG1(const T& mapto) +{ + const struct { + const char *in; + const char *out; + } tbl[] = { + // https://github.com/matter-labs/eip1962/blob/master/src/test/test_vectors/eip2537/fp_to_g1.csv + { + "0000000000000000000000000000000014406e5bfb9209256a3820879a29ac2f62d6aca82324bf3ae2aa7d3c54792043bd8c791fccdb080c1a52dc68b8b69350", + "000000000000000000000000000000000d7721bcdb7ce1047557776eb2659a444166dc6dd55c7ca6e240e21ae9aa18f529f04ac31d861b54faf3307692545db700000000000000000000000000000000108286acbdf4384f67659a8abe89e712a504cb3ce1cba07a716869025d60d499a00d1da8cdc92958918c222ea93d87f0", + }, + { + "000000000000000000000000000000000e885bb33996e12f07da69073e2c0cc880bc8eff26d2a724299eb12d54f4bcf26f4748bb020e80a7e3794a7b0e47a641", + "00000000000000000000000000000000191ba6e4c4dafa22c03d41b050fe8782629337641be21e0397dc2553eb8588318a21d30647182782dee7f62a22fd020c000000000000000000000000000000000a721510a67277eabed3f153bd91df0074e1cbd37ef65b85226b1ce4fb5346d943cf21c388f0c5edbc753888254c760a", + }, + { + "000000000000000000000000000000000ba1b6d79150bdc368a14157ebfe8b5f691cf657a6bbe30e79b6654691136577d2ef1b36bfb232e3336e7e4c9352a8ed", + "000000000000000000000000000000001658c31c0db44b5f029dba56786776358f184341458577b94d3a53c877af84ffbb1a13cc47d228a76abb4b67912991850000000000000000000000000000000018cf1f27eab0a1a66f28a227bd624b7d1286af8f85562c3f03950879dd3b8b4b72e74b034223c6fd93de7cd1ade367cb", + }, + }; + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { + Uint8Vec v = fromHexStr(tbl[i].in); + Fp x; + /* + serialize() accepts only values in [0, p). + The test values exceed p, so use setBigEndianMod to set (v mod p). + */ + x.setBigEndianMod(v.data(), v.size()); + G1 P; + mapto.FpToG1(P, x); + /* + The test value is the form such as "000...000...". + So normalize P and pad zeros to compare it. + */ + P.normalize(); + const size_t L = 128; + std::string s = appendZeroToRight(P.x.getStr(16), L) + appendZeroToRight(P.y.getStr(16), L); + CYBOZU_TEST_EQUAL(s, tbl[i].out); + { + G1 Q; + mcl::bn::mapToG1(Q, x); + CYBOZU_TEST_EQUAL(P, Q); + } + } +} + CYBOZU_TEST_AUTO(test) { initPairing(mcl::BLS12_381); @@ -1194,4 +1247,5 @@ CYBOZU_TEST_AUTO(test) testEth2phase0(); testSswuG1(mapto); testMsgToG1(mapto); + testFpToG1(mapto); }