Ton

Форк
0
/
rand.cpp 
122 строки · 3.0 Кб
1
/*
2
    This file is part of TON Blockchain Library.
3

4
    TON Blockchain Library is free software: you can redistribute it and/or modify
5
    it under the terms of the GNU Lesser General Public License as published by
6
    the Free Software Foundation, either version 2 of the License, or
7
    (at your option) any later version.
8

9
    TON Blockchain Library is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU Lesser General Public License for more details.
13

14
    You should have received a copy of the GNU Lesser General Public License
15
    along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
16

17
    Copyright 2017-2020 Telegram Systems LLP
18
*/
19
#include "openssl/rand.hpp"
20

21
#include "td/utils/common.h"
22

23
#include <openssl/rand.h>
24
#include <openssl/opensslv.h>
25

26
namespace prng {
27
int os_get_random_bytes(void *buf, int n);
28

29
bool RandomGen::ok() const {
30
  return RAND_status();
31
}
32

33
void RandomGen::seed_add(const void *data, std::size_t size, double entropy) {
34
  RAND_add(data, static_cast<int>(size), entropy > 0 ? entropy : static_cast<double>(size));
35
}
36

37
void RandomGen::randomize(bool force) {
38
  if (!force && ok()) {
39
    return;
40
  }
41
  unsigned char buffer[128];
42
  int n = os_get_random_bytes(buffer, 128);
43
  seed_add(buffer, n);
44
  assert(ok());
45
}
46

47
bool RandomGen::rand_bytes(void *data, std::size_t size, bool strong) {
48
#if OPENSSL_VERSION_NUMBER < 0x10101000L
49
  int res = (strong ? RAND_bytes : RAND_pseudo_bytes)((unsigned char *)data, static_cast<int>(size));
50
#else
51
  int res = RAND_bytes((unsigned char *)data, static_cast<int>(size));
52
#endif
53
  if (res != 0 && res != 1) {
54
    throw rand_error();
55
  }
56
  return res;
57
}
58

59
std::string RandomGen::rand_string(std::size_t size, bool strong) {
60
  std::string result(size, '\0');
61
  if (size > 0 && !rand_bytes(&result[0], size, strong)) {
62
    throw rand_error();
63
  }
64
  return result;
65
}
66

67
RandomGen &rand_gen() {
68
  // RandomGen is stateless, OpenSSL will handle concurrent access
69
  static RandomGen MainPRNG;
70
  return MainPRNG;
71
}
72
}  // namespace prng
73

74
//------------------------- move to separate OS-dependent file?
75
#if TD_WINDOWS
76
namespace prng {
77
int os_get_random_bytes(void *buf, int n) {
78
  return 0;
79
}
80
}  // namespace prng
81
#else
82
#include <fcntl.h>
83
#include <unistd.h>
84

85
namespace prng {
86

87
int os_get_random_bytes(void *buf, int n) {
88
  using namespace std;
89
  int r = 0;
90
  int h = open("/dev/random", O_RDONLY | O_NONBLOCK);
91
  if (h >= 0) {
92
    r = static_cast<int>(read(h, buf, n));
93
    if (r > 0) {
94
      //std::cerr << "added " << r << " bytes of real entropy to secure random numbers seed" << std::endl;
95
    } else {
96
      r = 0;
97
    }
98
    close(h);
99
  }
100

101
  if (r < n) {
102
    h = open("/dev/urandom", O_RDONLY);
103
    if (h < 0) {
104
      return r;
105
    }
106
    int s = static_cast<int>(read(h, (char *)buf + r, n - r));
107
    close(h);
108
    if (s < 0) {
109
      return r;
110
    }
111
    r += s;
112
  }
113

114
  if (r >= 8) {
115
    *(long *)buf ^= lrand48();
116
    srand48(*(long *)buf);
117
  }
118

119
  return r;
120
}
121
}  // namespace prng
122
#endif
123

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.