add mclBn_setRandFunc

dev
MITSUNARI Shigeo 6 years ago
parent 05dc2da2e2
commit 494ebb1439
  1. 10
      include/mcl/bn.h
  2. 23
      include/mcl/fp.hpp
  3. 3
      include/mcl/gmp_util.hpp
  4. 58
      include/mcl/randgen.hpp
  5. 3
      include/mcl/vint.hpp
  6. 5
      src/bn_c_impl.hpp
  7. 6
      src/fp.cpp
  8. 37
      test/bn_c_test.hpp
  9. 14
      test/fp_util_test.cpp

@ -219,6 +219,16 @@ MCLBN_DLL_API int mclBnFr_isOne(const mclBnFr *x);
#ifndef MCL_DONT_USE_CSRPNG #ifndef MCL_DONT_USE_CSRPNG
// return 0 if success // return 0 if success
MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x); MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x);
/*
set user-defined random function for setByCSPRNG
@param self [in] user-defined pointer
@param readFunc [in] user-defined function,
which writes random bufSize bytes to buf and returns bufSize if success else returns 0
@note if self == 0 and readFunc == 0 then set default random function
@note not threadsafe
*/
MCLBN_DLL_API void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize));
#endif #endif
// hash(s) and set x // hash(s) and set x

@ -70,7 +70,15 @@ inline void dumpUnit(Unit x)
bool isEnableJIT(); // 1st call is not threadsafe bool isEnableJIT(); // 1st call is not threadsafe
void getRandVal(Unit *out, RandGen& rg, const Unit *in, size_t bitSize); void getRandVal(bool *pb, void *p, RandGen& rg, const Unit *in, size_t bitSize);
#ifndef CYBOZU_DONT_USE_EXCEPTION
inline void getRandVal(void *p, RandGen& rg, const Unit *in, size_t bitSize)
{
bool b;
getRandVal(&b, p, rg, in, bitSize);
if (!b) throw cybozu::Exception("getRandVal") << bitSize;
}
#endif
uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);
uint32_t sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize); uint32_t sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);
@ -331,12 +339,21 @@ public:
b.p = &v_[0]; b.p = &v_[0];
} }
} }
void setByCSPRNG(fp::RandGen rg = fp::RandGen()) void setByCSPRNG(bool *pb, fp::RandGen rg = fp::RandGen())
{ {
if (rg.isZero()) rg = fp::RandGen::get(); if (rg.isZero()) rg = fp::RandGen::get();
fp::getRandVal(v_, rg, op_.p, op_.bitSize); fp::getRandVal(pb, v_, rg, op_.p, op_.bitSize);
if (!*pb) return;
toMont(); toMont();
} }
#ifndef CYBOZU_DONT_USE_EXCEPTION
void setByCSPRNG(fp::RandGen rg = fp::RandGen())
{
bool b;
setByCSPRNG(&b, rg);
if (!b) throw cybozu::Exception("setByCSPRNG");
}
#endif
void setRand(fp::RandGen rg = fp::RandGen()) // old api void setRand(fp::RandGen rg = fp::RandGen()) // old api
{ {
setByCSPRNG(rg); setByCSPRNG(rg);

@ -450,7 +450,8 @@ inline void getRand(bool *pb, mpz_class& z, size_t bitSize, fp::RandGen rg = fp:
*pb = false; *pb = false;
return; return;
} }
rg.read(buf, n * sizeof(buf[0])); rg.read(pb, buf, n * sizeof(buf[0]));
if (!*pb) return;
uint32_t v = buf[n - 1]; uint32_t v = buf[n - 1];
if (rem == 0) { if (rem == 0) {
v |= 1U << 31; v |= 1U << 31;

@ -15,10 +15,16 @@
namespace mcl { namespace mcl {
struct RandomGeneratorJS { struct RandomGeneratorJS {
void read(void *buf, size_t bufSize) void read(bool *pb, void *buf, uint32_t byteSize)
{ {
// cf. https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
if (byteSize > 65536) {
*pb = false;
return;
}
// use crypto.getRandomValues // use crypto.getRandomValues
EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, bufSize); EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, byteSize);
*pb = true;
} }
}; };
} // mcl } // mcl
@ -38,28 +44,33 @@ namespace mcl { namespace fp {
namespace local { namespace local {
template<class RG> template<class RG>
void readWrapper(void *self, void *buf, uint32_t bufSize) uint32_t readWrapper(void *self, void *buf, uint32_t byteSize)
{ {
reinterpret_cast<RG*>(self)->read((uint8_t*)buf, bufSize); bool b;
reinterpret_cast<RG*>(self)->read(&b, (uint8_t*)buf, byteSize);
if (b) return byteSize;
return 0;
} }
#if 0 // #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 #if 0 // #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
template<> template<>
inline void readWrapper<std::random_device>(void *self, void *buf, uint32_t bufSize) inline uint32_t readWrapper<std::random_device>(void *self, void *buf, uint32_t byteSize)
{ {
const uint32_t keep = byteSize;
std::random_device& rg = *reinterpret_cast<std::random_device*>(self); std::random_device& rg = *reinterpret_cast<std::random_device*>(self);
uint8_t *p = reinterpret_cast<uint8_t*>(buf); uint8_t *p = reinterpret_cast<uint8_t*>(buf);
uint32_t v; uint32_t v;
while (bufSize >= 4) { while (byteSize >= 4) {
v = rg(); v = rg();
memcpy(p, &v, 4); memcpy(p, &v, 4);
p += 4; p += 4;
bufSize -= 4; byteSize -= 4;
} }
if (bufSize > 0) { if (byteSize > 0) {
v = rg(); v = rg();
memcpy(p, &v, bufSize); memcpy(p, &v, byteSize);
} }
return keep;
} }
#endif #endif
} // local } // local
@ -67,7 +78,7 @@ inline void readWrapper<std::random_device>(void *self, void *buf, uint32_t bufS
wrapper of cryptographically secure pseudo random number generator wrapper of cryptographically secure pseudo random number generator
*/ */
class RandGen { class RandGen {
typedef void (*readFuncType)(void *self, void *buf, uint32_t bufSize); typedef uint32_t (*readFuncType)(void *self, void *buf, uint32_t byteSize);
void *self_; void *self_;
readFuncType readFunc_; readFuncType readFunc_;
public: public:
@ -87,16 +98,17 @@ public:
, readFunc_(local::readWrapper<RG>) , readFunc_(local::readWrapper<RG>)
{ {
} }
void read(void *out, size_t byteSize) void read(bool *pb, void *out, size_t byteSize)
{ {
readFunc_(self_, out, static_cast<uint32_t>(byteSize)); uint32_t size = readFunc_(self_, out, static_cast<uint32_t>(byteSize));
*pb = size == byteSize;
} }
#ifdef MCL_DONT_USE_CSPRNG #ifdef MCL_DONT_USE_CSPRNG
bool isZero() const { return false; } /* return false to avoid copying default rg */ bool isZero() const { return false; } /* return false to avoid copying default rg */
#else #else
bool isZero() const { return self_ == 0 && readFunc_ == 0; } bool isZero() const { return self_ == 0 && readFunc_ == 0; }
#endif #endif
static RandGen& get() static RandGen& getDefaultRandGen()
{ {
#ifdef MCL_DONT_USE_CSPRNG #ifdef MCL_DONT_USE_CSPRNG
static RandGen wrg; static RandGen wrg;
@ -109,14 +121,32 @@ public:
#endif #endif
return wrg; return wrg;
} }
static RandGen& get()
{
static RandGen wrg(getDefaultRandGen());
return wrg;
}
/* /*
rg must be thread safe rg must be thread safe
rg.read(void *buf, size_t bufSize); rg.read(void *buf, size_t byteSize);
*/ */
static void setRandGen(const RandGen& rg) static void setRandGen(const RandGen& rg)
{ {
get() = rg; get() = rg;
} }
/*
set rand function
if self and readFunc are NULL then set default rand function
*/
static void setRandFunc(void *self, readFuncType readFunc)
{
if (self == 0 && readFunc == 0) {
setRandGen(getDefaultRandGen());
} else {
RandGen rg(self, readFunc);
setRandGen(rg);
}
}
}; };
} } // mcl::fp } } // mcl::fp

@ -1138,7 +1138,8 @@ public:
size_t n = max.size(); size_t n = max.size();
buf_.alloc(pb, n); buf_.alloc(pb, n);
if (!*pb) return; if (!*pb) return;
rg.read(&buf_[0], n * sizeof(buf_[0])); rg.read(pb, &buf_[0], n * sizeof(buf_[0]));
if (!*pb) return;
trim(n); trim(n);
*this %= max; *this %= max;
} }

@ -84,6 +84,7 @@ mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize)
{ {
return Fp::getModulo(buf, maxBufSize); return Fp::getModulo(buf, maxBufSize);
} }
//////////////////////////////////////////////// ////////////////////////////////////////////////
// set zero // set zero
void mclBnFr_clear(mclBnFr *x) void mclBnFr_clear(mclBnFr *x)
@ -138,6 +139,10 @@ int mclBnFr_setByCSPRNG(mclBnFr *x)
cast(x)->setByCSPRNG(); cast(x)->setByCSPRNG();
return 0; return 0;
} }
void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize))
{
mcl::fp::RandGen::setRandFunc(self, readFunc);
}
#endif #endif
// hash(buf) and set x // hash(buf) and set x

@ -120,14 +120,16 @@ bool isEnableJIT()
#endif #endif
} }
void getRandVal(Unit *out, RandGen& rg, const Unit *in, size_t bitSize) void getRandVal(bool *pb, void *p, RandGen& rg, const Unit *in, size_t bitSize)
{ {
if (rg.isZero()) rg = RandGen::get(); if (rg.isZero()) rg = RandGen::get();
Unit *out = reinterpret_cast<Unit*>(p);
const size_t n = (bitSize + UnitBitSize - 1) / UnitBitSize; const size_t n = (bitSize + UnitBitSize - 1) / UnitBitSize;
const size_t rem = bitSize & (UnitBitSize - 1); const size_t rem = bitSize & (UnitBitSize - 1);
assert(n > 0); assert(n > 0);
for (;;) { for (;;) {
rg.read(out, n * sizeof(Unit)); rg.read(pb, out, n * sizeof(Unit)); // byte size
if (!*pb) return;
if (rem > 0) out[n - 1] &= (Unit(1) << rem) - 1; if (rem > 0) out[n - 1] &= (Unit(1) << rem) - 1;
if (isLessArray(out, in, n)) return; if (isLessArray(out, in, n)) return;
} }

@ -522,3 +522,40 @@ CYBOZU_TEST_AUTO(badG2)
} }
#endif #endif
struct Sequential {
uint32_t pos;
Sequential() : pos(0) {}
static uint32_t read(void *self, void *buf, uint32_t bufSize)
{
Sequential *seq = reinterpret_cast<Sequential*>(self);
uint8_t *p = reinterpret_cast<uint8_t*>(buf);
for (uint32_t i = 0; i < bufSize; i++) {
p[i] = uint8_t(seq->pos + i) & 0x1f; // mask is to make valid Fp
}
seq->pos += bufSize;
return bufSize;
}
};
CYBOZU_TEST_AUTO(setRandFunc)
{
Sequential seq;
for (int j = 0; j < 3; j++) {
puts(j == 1 ? "sequential rand" : "true rand");
for (int i = 0; i < 5; i++) {
mclBnFr x;
int ret;
char buf[1024];
ret = mclBnFr_setByCSPRNG(&x);
CYBOZU_TEST_EQUAL(ret, 0);
ret = mclBnFr_getStr(buf, sizeof(buf), &x, 16);
CYBOZU_TEST_ASSERT(ret > 0);
printf("%d %s\n", i, buf);
}
if (j == 0) {
mclBn_setRandFunc(&seq, Sequential::read);
} else {
mclBn_setRandFunc(0, 0);
}
}
}

@ -158,12 +158,22 @@ struct Rand {
const uint8_t *p; const uint8_t *p;
size_t pos; size_t pos;
size_t endPos; size_t endPos;
void read(void *x, size_t n) void read(bool *pb, void *x, size_t n)
{ {
if (pos + n > endPos) throw cybozu::Exception("Rand:get:bad n") << pos << n << endPos; if (pos + n > endPos) {
*pb = false;
return;
}
uint8_t *dst = (uint8_t*)x; uint8_t *dst = (uint8_t*)x;
memcpy(dst, p + pos, n); memcpy(dst, p + pos, n);
pos += n; pos += n;
*pb = true;
}
void read(void *x, size_t n)
{
bool b;
read(&b, x, n);
if (!b) throw cybozu::Exception("Rand") << n;
} }
uint32_t operator()() uint32_t operator()()
{ {

Loading…
Cancel
Save