github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/cybozu/random_generator.hpp (about) 1 #pragma once 2 /** 3 @file 4 @brief pseudrandom generator 5 @author MITSUNARI Shigeo(@herumi) 6 @license modified new BSD license 7 http://opensource.org/licenses/BSD-3-Clause 8 */ 9 10 #ifndef CYBOZU_DONT_USE_EXCEPTION 11 #include <cybozu/exception.hpp> 12 #endif 13 #ifdef _WIN32 14 #include <winsock2.h> 15 #include <windows.h> 16 #include <wincrypt.h> 17 #ifdef _MSC_VER 18 #pragma comment (lib, "advapi32.lib") 19 #endif 20 #include <cybozu/critical_section.hpp> 21 #else 22 #include <sys/types.h> 23 #include <fcntl.h> 24 #endif 25 26 namespace cybozu { 27 28 class RandomGenerator { 29 RandomGenerator(const RandomGenerator&); 30 void operator=(const RandomGenerator&); 31 public: 32 #ifdef _WIN32 33 RandomGenerator() 34 : prov_(0) 35 , pos_(bufSize) 36 { 37 DWORD flagTbl[] = { 0, CRYPT_NEWKEYSET }; 38 for (int i = 0; i < 2; i++) { 39 if (CryptAcquireContext(&prov_, NULL, NULL, PROV_RSA_FULL, flagTbl[i]) != 0) return; 40 } 41 #ifdef CYBOZU_DONT_USE_EXCEPTION 42 prov_ = 0; 43 #else 44 throw cybozu::Exception("randomgenerator"); 45 #endif 46 } 47 bool read_inner(void *buf, size_t byteSize) 48 { 49 if (prov_ == 0) return false; 50 return CryptGenRandom(prov_, static_cast<DWORD>(byteSize), static_cast<BYTE*>(buf)) != 0; 51 } 52 ~RandomGenerator() 53 { 54 if (prov_) { 55 CryptReleaseContext(prov_, 0); 56 } 57 } 58 /* 59 fill buf[0..bufNum-1] with random data 60 @note bufNum is not byte size 61 */ 62 template<class T> 63 void read(bool *pb, T *buf, size_t bufNum) 64 { 65 cybozu::AutoLockCs al(cs_); 66 const size_t byteSize = sizeof(T) * bufNum; 67 if (byteSize > bufSize) { 68 if (!read_inner(buf, byteSize)) { 69 *pb = false; 70 return; 71 } 72 } else { 73 if (pos_ + byteSize > bufSize) { 74 read_inner(buf_, bufSize); 75 pos_ = 0; 76 } 77 memcpy(buf, buf_ + pos_, byteSize); 78 pos_ += byteSize; 79 } 80 *pb = true; 81 } 82 private: 83 HCRYPTPROV prov_; 84 static const size_t bufSize = 1024; 85 char buf_[bufSize]; 86 size_t pos_; 87 cybozu::CriticalSection cs_; 88 #else 89 RandomGenerator() 90 : fp_(::fopen("/dev/urandom", "rb")) 91 { 92 #ifndef CYBOZU_DONT_USE_EXCEPTION 93 if (!fp_) throw cybozu::Exception("randomgenerator"); 94 #endif 95 } 96 ~RandomGenerator() 97 { 98 if (fp_) ::fclose(fp_); 99 } 100 /* 101 fill buf[0..bufNum-1] with random data 102 @note bufNum is not byte size 103 */ 104 template<class T> 105 void read(bool *pb, T *buf, size_t bufNum) 106 { 107 if (fp_ == 0) { 108 *pb = false; 109 return; 110 } 111 const size_t byteSize = sizeof(T) * bufNum; 112 *pb = ::fread(buf, 1, (int)byteSize, fp_) == byteSize; 113 } 114 private: 115 FILE *fp_; 116 #endif 117 #ifndef CYBOZU_DONT_USE_EXCEPTION 118 public: 119 template<class T> 120 void read(T *buf, size_t bufNum) 121 { 122 bool b; 123 read(&b, buf, bufNum); 124 if (!b) throw cybozu::Exception("RandomGenerator:read") << bufNum; 125 } 126 uint32_t get32() 127 { 128 uint32_t ret; 129 read(&ret, 1); 130 return ret; 131 } 132 uint64_t get64() 133 { 134 uint64_t ret; 135 read(&ret, 1); 136 return ret; 137 } 138 uint32_t operator()() 139 { 140 return get32(); 141 } 142 #endif 143 }; 144 145 template<class T, class RG> 146 void shuffle(T* v, size_t n, RG& rg) 147 { 148 if (n <= 1) return; 149 for (size_t i = 0; i < n - 1; i++) { 150 size_t r = i + size_t(rg.get64() % (n - i)); 151 using namespace std; 152 swap(v[i], v[r]); 153 } 154 } 155 156 template<class V, class RG> 157 void shuffle(V& v, RG& rg) 158 { 159 shuffle(v.data(), v.size(), rg); 160 } 161 162 } // cybozu