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
// return 0 if success
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
// hash(s) and set x

@ -70,7 +70,15 @@ inline void dumpUnit(Unit x)
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 sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);
@ -331,12 +339,21 @@ public:
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();
fp::getRandVal(v_, rg, op_.p, op_.bitSize);
fp::getRandVal(pb, v_, rg, op_.p, op_.bitSize);
if (!*pb) return;
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
{
setByCSPRNG(rg);

@ -450,7 +450,8 @@ inline void getRand(bool *pb, mpz_class& z, size_t bitSize, fp::RandGen rg = fp:
*pb = false;
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];
if (rem == 0) {
v |= 1U << 31;

@ -15,10 +15,16 @@
namespace mcl {
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
EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, bufSize);
EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, byteSize);
*pb = true;
}
};
} // mcl
@ -38,28 +44,33 @@ namespace mcl { namespace fp {
namespace local {
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
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);
uint8_t *p = reinterpret_cast<uint8_t*>(buf);
uint32_t v;
while (bufSize >= 4) {
while (byteSize >= 4) {
v = rg();
memcpy(p, &v, 4);
p += 4;
bufSize -= 4;
byteSize -= 4;
}
if (bufSize > 0) {
if (byteSize > 0) {
v = rg();
memcpy(p, &v, bufSize);
memcpy(p, &v, byteSize);
}
return keep;
}
#endif
} // 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
*/
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_;
readFuncType readFunc_;
public:
@ -87,16 +98,17 @@ public:
, 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
bool isZero() const { return false; } /* return false to avoid copying default rg */
#else
bool isZero() const { return self_ == 0 && readFunc_ == 0; }
#endif
static RandGen& get()
static RandGen& getDefaultRandGen()
{
#ifdef MCL_DONT_USE_CSPRNG
static RandGen wrg;
@ -109,14 +121,32 @@ public:
#endif
return wrg;
}
static RandGen& get()
{
static RandGen wrg(getDefaultRandGen());
return wrg;
}
/*
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)
{
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

@ -1138,7 +1138,8 @@ public:
size_t n = max.size();
buf_.alloc(pb, n);
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);
*this %= max;
}

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

@ -120,14 +120,16 @@ bool isEnableJIT()
#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();
Unit *out = reinterpret_cast<Unit*>(p);
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));
rg.read(pb, out, n * sizeof(Unit)); // byte size
if (!*pb) return;
if (rem > 0) out[n - 1] &= (Unit(1) << rem) - 1;
if (isLessArray(out, in, n)) return;
}

@ -522,3 +522,40 @@ CYBOZU_TEST_AUTO(badG2)
}
#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;
size_t pos;
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;
memcpy(dst, p + 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()()
{

Loading…
Cancel
Save