aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <herumi@nifty.com>2018-10-28 14:10:57 +0800
committerMITSUNARI Shigeo <herumi@nifty.com>2018-10-28 14:10:57 +0800
commit494ebb1439b5942824f5cbe3a5ccf87406b45815 (patch)
tree0f5610c80ed4cc60fa7b4d7c071ebb88847d3959
parent05dc2da2e222b691c662910ff902a72342067364 (diff)
downloadtangerine-mcl-494ebb1439b5942824f5cbe3a5ccf87406b45815.tar.gz
tangerine-mcl-494ebb1439b5942824f5cbe3a5ccf87406b45815.tar.zst
tangerine-mcl-494ebb1439b5942824f5cbe3a5ccf87406b45815.zip
add mclBn_setRandFunc
-rw-r--r--include/mcl/bn.h10
-rw-r--r--include/mcl/fp.hpp23
-rw-r--r--include/mcl/gmp_util.hpp3
-rw-r--r--include/mcl/randgen.hpp58
-rw-r--r--include/mcl/vint.hpp3
-rw-r--r--src/bn_c_impl.hpp5
-rw-r--r--src/fp.cpp6
-rw-r--r--test/bn_c_test.hpp37
-rw-r--r--test/fp_util_test.cpp14
9 files changed, 136 insertions, 23 deletions
diff --git a/include/mcl/bn.h b/include/mcl/bn.h
index 9c78f92..c130004 100644
--- a/include/mcl/bn.h
+++ b/include/mcl/bn.h
@@ -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
diff --git a/include/mcl/fp.hpp b/include/mcl/fp.hpp
index 4850012..dc8dc95 100644
--- a/include/mcl/fp.hpp
+++ b/include/mcl/fp.hpp
@@ -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);
diff --git a/include/mcl/gmp_util.hpp b/include/mcl/gmp_util.hpp
index 2dd71eb..a64bed4 100644
--- a/include/mcl/gmp_util.hpp
+++ b/include/mcl/gmp_util.hpp
@@ -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;
diff --git a/include/mcl/randgen.hpp b/include/mcl/randgen.hpp
index 4bfb30b..30502fc 100644
--- a/include/mcl/randgen.hpp
+++ b/include/mcl/randgen.hpp
@@ -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
diff --git a/include/mcl/vint.hpp b/include/mcl/vint.hpp
index 32a51bb..c2a7a10 100644
--- a/include/mcl/vint.hpp
+++ b/include/mcl/vint.hpp
@@ -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;
}
diff --git a/src/bn_c_impl.hpp b/src/bn_c_impl.hpp
index bb0b4ba..497ae2b 100644
--- a/src/bn_c_impl.hpp
+++ b/src/bn_c_impl.hpp
@@ -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
diff --git a/src/fp.cpp b/src/fp.cpp
index bea1dff..8db755d 100644
--- a/src/fp.cpp
+++ b/src/fp.cpp
@@ -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;
}
diff --git a/test/bn_c_test.hpp b/test/bn_c_test.hpp
index d33cdf5..fc81652 100644
--- a/test/bn_c_test.hpp
+++ b/test/bn_c_test.hpp
@@ -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);
+ }
+ }
+}
diff --git a/test/fp_util_test.cpp b/test/fp_util_test.cpp
index b11311b..b6d5efc 100644
--- a/test/fp_util_test.cpp
+++ b/test/fp_util_test.cpp
@@ -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()()
{