1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#pragma once
/**
@file
@brief definition of Op
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#ifdef MCL_DONT_USE_CSRPNG
// nothing
#elif defined(MCL_USE_WEB_CRYPTO_API)
#include <emscripten.h>
namespace mcl {
struct RandomGeneratorJS {
void read(void *buf, size_t bufSize)
{
// use crypto.getRandomValues
EM_ASM({Module.cryptoGetRandomValues($0, $1)}, buf, bufSize);
}
};
} // mcl
#else
#include <cybozu/random_generator.hpp>
#if 0 // #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
#include <random>
#endif
#endif
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4521)
#endif
namespace mcl { namespace fp {
namespace local {
template<class RG>
void readWrapper(void *self, void *buf, uint32_t bufSize)
{
reinterpret_cast<RG*>(self)->read((uint8_t*)buf, bufSize);
}
#if 0 // #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
template<>
inline void readWrapper<std::random_device>(void *self, void *buf, uint32_t bufSize)
{
std::random_device& rg = *reinterpret_cast<std::random_device*>(self);
uint8_t *p = reinterpret_cast<uint8_t*>(buf);
uint32_t v;
while (bufSize >= 4) {
v = rg();
memcpy(p, &v, 4);
p += 4;
bufSize -= 4;
}
if (bufSize > 0) {
v = rg();
memcpy(p, &v, bufSize);
}
}
#endif
} // local
/*
wrapper of cryptographically secure pseudo random number generator
*/
class RandGen {
typedef void (*readFuncType)(void *self, void *buf, uint32_t bufSize);
void *self_;
readFuncType readFunc_;
public:
RandGen() : self_(0), readFunc_(0) {}
RandGen(void *self, readFuncType readFunc) : self_(self) , readFunc_(readFunc) {}
RandGen(const RandGen& rhs) : self_(rhs.self_), readFunc_(rhs.readFunc_) {}
RandGen(RandGen& rhs) : self_(rhs.self_), readFunc_(rhs.readFunc_) {}
RandGen& operator=(const RandGen& rhs)
{
self_ = rhs.self_;
readFunc_ = rhs.readFunc_;
return *this;
}
template<class RG>
RandGen(RG& rg)
: self_(reinterpret_cast<void*>(&rg))
, readFunc_(local::readWrapper<RG>)
{
}
void read(void *out, size_t byteSize)
{
readFunc_(self_, out, static_cast<uint32_t>(byteSize));
}
#ifdef MCL_DONT_USE_CSRPNG
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()
{
#ifdef MCL_DONT_USE_CSRPNG
static RandGen wrg;
#elif defined(MCL_USE_WEB_CRYPTO_API)
static mcl::RandomGeneratorJS rg;
static RandGen wrg(rg);
#else
static cybozu::RandomGenerator rg;
static RandGen wrg(rg);
#endif
return wrg;
}
/*
rg must be thread safe
rg.read(void *buf, size_t bufSize);
*/
static void setRandGen(const RandGen& rg)
{
get() = rg;
}
};
} } // mcl::fp
#ifdef _MSC_VER
#pragma warning(pop)
#endif
|