support hash-to-curve-06

update-fork
MITSUNARI Shigeo 5 years ago
parent 00c9cb00a1
commit 9c3f370c88
  1. 16
      include/mcl/bn.hpp
  2. 10
      include/mcl/curve_type.h
  3. 2
      include/mcl/fp.hpp
  4. 32
      include/mcl/mapto_wb19.hpp
  5. 2
      include/mcl/op.hpp
  6. 12
      readme.md
  7. 36
      src/fp.cpp
  8. 25
      test/mapto_wb19_test.cpp

@ -494,10 +494,19 @@ struct MapTo {
case MCL_MAP_TO_MODE_ORIGINAL:
case MCL_MAP_TO_MODE_TRY_AND_INC:
case MCL_MAP_TO_MODE_ETH2:
case MCL_MAP_TO_MODE_WB19:
mapToMode_ = mode;
return true;
break;
case MCL_MAP_TO_MODE_HASH_TO_CURVE_05:
mapToMode_ = mode;
mapToG2_WB19_.setDraftVersion(5);
return true;
break;
case MCL_MAP_TO_MODE_HASH_TO_CURVE_06:
mapToMode_ = mode;
mapToG2_WB19_.setDraftVersion(6);
return true;
break;
default:
return false;
}
@ -569,7 +578,7 @@ struct MapTo {
}
bool calc(G2& P, const Fp2& t, bool fast = false) const
{
if (mapToMode_ == MCL_MAP_TO_MODE_WB19) {
if (mapToMode_ == MCL_MAP_TO_MODE_WB19 || mapToMode_ == MCL_MAP_TO_MODE_HASH_TO_CURVE_06) {
mapToG2_WB19_.opt_swu2_map(P, t);
return true;
}
@ -2132,7 +2141,8 @@ inline void hashAndMapToG1(G1& P, const void *buf, size_t bufSize)
}
inline void hashAndMapToG2(G2& P, const void *buf, size_t bufSize)
{
if (getMapToMode() == MCL_MAP_TO_MODE_WB19) {
int mode = getMapToMode();
if (mode == MCL_MAP_TO_MODE_WB19 || mode == MCL_MAP_TO_MODE_HASH_TO_CURVE_06) {
BN::param.mapTo.mapToG2_WB19_.msgToG2(P, buf, bufSize);
return;
}

@ -36,11 +36,19 @@ enum {
MCL_NIST_P521 = MCL_SECP521R1
};
/*
remark : if irtf-cfrg-hash-to-curve is compeletely fixed, then
MCL_MAP_TO_MODE_WB19, MCL_MAP_TO_MODE_HASH_TO_CURVE_0? will be removed and
only MCL_MAP_TO_MODE_HASH_TO_CURVE will be available.
*/
enum {
MCL_MAP_TO_MODE_ORIGINAL, // see MapTo::calcBN
MCL_MAP_TO_MODE_TRY_AND_INC, // try-and-incremental-x
MCL_MAP_TO_MODE_ETH2, // old eth2.0 spec
MCL_MAP_TO_MODE_WB19 // used in new eth2.0 spec
MCL_MAP_TO_MODE_WB19, // used in new eth2.0 spec
MCL_MAP_TO_MODE_HASH_TO_CURVE_05 = MCL_MAP_TO_MODE_WB19, // draft-irtf-cfrg-hash-to-curve-05
MCL_MAP_TO_MODE_HASH_TO_CURVE_06, // draft-irtf-cfrg-hash-to-curve-06
MCL_MAP_TO_MODE_HASH_TO_CURVE = MCL_MAP_TO_MODE_HASH_TO_CURVE_06 // the latset version
};
#ifdef __cplusplus

@ -77,6 +77,8 @@ void hkdf_extract_addZeroByte(uint8_t hmac[32], const uint8_t *salt, size_t salt
void hkdf_extract(uint8_t hmac[32], const uint8_t *salt, size_t saltSize, const uint8_t *msg, size_t msgSize);
void hkdf_expand(uint8_t out[64], const uint8_t prk[32], char info[6]);
void expand_message_xmd(uint8_t out[256], const void *msg, size_t msgSize, const void *dst, size_t dstSize);
namespace local {
inline void byteSwap(void *x, size_t n)

@ -50,6 +50,11 @@ struct MapToG2_WB19 {
Fp2 xden[3];
Fp2 ynum[4];
Fp2 yden[4];
int draftVersion_;
void setDraftVersion(int version)
{
draftVersion_ = version;
}
struct Point {
Fp2 x, y, z;
bool isZero() const
@ -209,6 +214,7 @@ struct MapToG2_WB19 {
Fp::neg(etas[3].a, ev4);
etas[3].b = ev3;
init_iso();
draftVersion_ = 5;
}
void init_iso()
{
@ -656,12 +662,30 @@ struct MapToG2_WB19 {
P1 += P2;
clear_h2(out, P1);
}
// hash-to-curve-06
void hashToFp2v6(Fp2 out[2], const void *msg, size_t msgSize, const void *dst, size_t dstSize) const
{
uint8_t md[256];
mcl::fp::expand_message_xmd(md, msg, msgSize, dst, dstSize);
Fp *x = out[0].getFp0();
for (size_t i = 0; i < 4; i++) {
uint8_t *p = &md[64 * i];
fp::local::byteSwap(p, 64);
bool b;
x[i].setArrayMod(&b, p, 64);
assert(b); (void)b;
}
}
void map2curve_osswu2(G2& out, const void *msg, size_t msgSize, const void *dst, size_t dstSize) const
{
Fp2 t1, t2;
hashToFp2(t1, msg, msgSize, 0, dst, dstSize);
hashToFp2(t2, msg, msgSize, 1, dst, dstSize);
opt_swu2_map(out, t1, &t2);
Fp2 t[2];
if (draftVersion_ == 5) {
hashToFp2(t[0], msg, msgSize, 0, dst, dstSize);
hashToFp2(t[1], msg, msgSize, 1, dst, dstSize);
} else {
hashToFp2v6(t, msg, msgSize, dst, dstSize);
}
opt_swu2_map(out, t[0], &t[1]);
}
void msgToG2(G2& out, const void *msg, size_t msgSize) const
{

@ -23,7 +23,7 @@
namespace mcl {
static const int version = 0x105; /* 0xABC = A.BC */
static const int version = 0x106; /* 0xABC = A.BC */
/*
specifies available string format mode for X::setIoMode()

@ -10,10 +10,13 @@ mcl is a library for pairing-based cryptography,
which supports the optimal Ate pairing over BN curves and BLS12-381 curves.
# News
add new hash functions corresponding to python-impl of [algorand/bls_sig_ref](https://github.com/algorand/bls_sigs_ref).
* `mclBn_ethMsgToFp2`(resp. `Hp2`)
* `mclBn_ethFp2ToG2`(resp. `opt_swu2_map`)
* `mclBn_ethMsgToG2`(resp. `map2curve_osswu2`)
- add new hash-to-curve function of [draft-irtf-cfrg-hash-to-curve](https://cfrg.github.io/draft-irtf-cfrg-hash-to-curve/draft-irtf-cfrg-hash-to-curve.txt) at March 2020.
- call `setETHmode(MCL_MAP_TO_MODE_HASH_TO_CURVE_06);`
- The older `MAP_TO_MODE` will be removed after the draft is fixed.
- add new hash functions corresponding to python-impl of [algorand/bls_sig_ref](https://github.com/algorand/bls_sigs_ref).
- `mclBn_ethMsgToFp2`(resp. `Hp2`)
- `mclBn_ethFp2ToG2`(resp. `opt_swu2_map`)
- `mclBn_ethMsgToG2`(resp. `map2curve_osswu2`)
# Support architecture
@ -292,6 +295,7 @@ If `MCL_USE_OLD_MAPTO_FOR_BLS12` is defined, then the old function is used, but
# History
- 2020/Mar/15 v1.06 support hash-to-curve-06
- 2020/Jan/31 v1.05 mclBn_ethMsgToFp2 has changed to append zero byte at the end of msg
- 2020/Jan/25 v1.04 add new hash functions
- 2019/Dec/05 v1.03 disable to check the order in setStr

@ -159,6 +159,42 @@ void hkdf_expand(uint8_t out[64], const uint8_t prk[32], char info[6])
cybozu::hmac256(out + 32, prk, 32, out, 32 + 6);
}
void expand_message_xmd(uint8_t out[256], const void *msg, size_t msgSize, const void *dst, size_t dstSize)
{
const size_t len_in_bytes = 256;
const size_t mdSize = 32;
const size_t r_in_bytes = 64;
const size_t ell = len_in_bytes / mdSize;
uint8_t Z_pad[r_in_bytes] = {};
assert(dstSize < 256);
// BE(len_in_bytes, 2) + BE(0, 1) + BE(dstSize, 1)
uint8_t buf[2 + 1 + 1] = { 1, 0, 0, uint8_t(dstSize) };
uint8_t *const buf2 = buf + 2; // BE(0, 1) + BE(dstSize, 1)
cybozu::Sha256 h;
h.update(Z_pad, r_in_bytes);
h.update(msg, msgSize);
h.update(buf, sizeof(buf));
uint8_t md[mdSize];
h.digest(md, mdSize, dst, dstSize);
h.clear();
buf2[0] = 1;
h.update(md, mdSize);
h.update(buf2, 2);
h.digest(out, mdSize, dst, dstSize);
uint8_t mdXor[mdSize];
for (size_t i = 1; i < ell; i++) {
h.clear();
for (size_t j = 0; j < mdSize; j++) {
mdXor[j] = md[j] ^ out[mdSize * (i - 1) + j];
}
h.update(mdXor, mdSize);
buf2[0] = uint8_t(i + 1);
h.update(buf2, 2);
h.digest(out + mdSize * i, mdSize, dst, dstSize);
}
}
#ifndef MCL_USE_VINT
static inline void set_mpz_t(mpz_t& z, const Unit* p, int n)
{

@ -629,6 +629,30 @@ void py_eccTest2(const T& mapto)
CYBOZU_TEST_EQUAL(P, Q);
}
template<class T>
void testHashToFp2v6(const T& mapto)
{
const char msg[] = "asdf";
const char dst[] = "QUUX-V01-CS02";
Fp2 out[2];
mapto.hashToFp2v6(out, msg, strlen(msg), dst, strlen(dst));
const Fp2Str expectStr[] = {
{
"2036684013374073670470642478097435082393965905216073159069132582313283074894808330704754509140183015844408257838394",
"1442095344782436377607687657711937282361342321405422912347590889376773969332935605209326528060836557922932229521614",
},
{
"712603160732423529538850938327197859251773848793464448294977148617985113767869616209273456982966659285651019780554",
"3549454379036632156704729135192770954406411172309331582430747991672599371642148666322072960024366511631069032927782",
},
};
Fp2 expect[2];
for (int i = 0; i < 2; i++) {
set(expect[i], expectStr[i]);
CYBOZU_TEST_EQUAL(out[i], expect[i]);
}
}
CYBOZU_TEST_AUTO(test)
{
initPairing(mcl::BLS12_381);
@ -648,4 +672,5 @@ CYBOZU_TEST_AUTO(test)
testVec("../misc/mapto/fips_186_3_B233.txt");
testVec("../misc/mapto/misc.txt");
ethMsgToG2testAll("../bls_sigs_ref/test-vectors/hash_g2/");
testHashToFp2v6(mapto);
}

Loading…
Cancel
Save