Ton

Форк
0
/
bignum.cpp 
269 строк · 6.2 Кб
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/bignum.h"
20

21
#ifdef OPENSSL_IS_BORINGSSL
22
#include <openssl/mem.h>
23
#endif
24

25
// impl only
26
#include <cstring>
27

28
namespace arith {
29

30
BN_CTX* get_ctx(void) {
31
  thread_local BN_CTX* ctx = BN_CTX_new();
32
  return ctx;
33
}
34

35
BignumBitref& BignumBitref::operator=(bool val) {
36
  if (val) {
37
    BN_set_bit(ptr, n);
38
  } else {
39
    BN_clear_bit(ptr, n);
40
  }
41
  return *this;
42
}
43

44
const Bignum operator+(const Bignum& x, const Bignum& y) {
45
  Bignum z;
46
  bn_assert(BN_add(z.bn_ptr(), x.bn_ptr(), y.bn_ptr()));
47
  return z;
48
}
49

50
const Bignum operator+(const Bignum& x, long y) {
51
  if (y > 0) {
52
    Bignum z(x);
53
    bn_assert(BN_add_word(z.bn_ptr(), y));
54
    return z;
55
  } else if (y < 0) {
56
    Bignum z(x);
57
    bn_assert(BN_sub_word(z.bn_ptr(), -y));
58
    return z;
59
  } else {
60
    return x;
61
  }
62
}
63

64
/*
65
  const Bignum operator+ (Bignum&& x, long y) {
66
    if (y > 0) {
67
      bn_assert (BN_add_word (x.bn_ptr(), y));
68
    } else if (y < 0) {
69
      bn_assert (BN_sub_word (x.bn_ptr(), -y));
70
    }
71
    return std::move (x);
72
  }
73
  */
74

75
/*
76
  const Bignum operator+ (long y, Bignum&& x) {
77
    return x + y;
78
  }
79
  */
80

81
const Bignum operator-(const Bignum& x, const Bignum& y) {
82
  Bignum z;
83
  bn_assert(BN_sub(z.bn_ptr(), x.bn_ptr(), y.bn_ptr()));
84
  return z;
85
}
86

87
/*
88
  const Bignum operator- (Bignum&& x, long y) {
89
    return x + (-y);
90
  }
91
  */
92

93
const Bignum operator*(const Bignum& x, const Bignum& y) {
94
  Bignum z;
95
  bn_assert(BN_mul(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx()));
96
  return z;
97
}
98

99
const Bignum operator*(const Bignum& x, long y) {
100
  if (y > 0) {
101
    Bignum z(x);
102
    bn_assert(BN_mul_word(z.bn_ptr(), y));
103
    return z;
104
  } else if (y < 0) {
105
    Bignum z(x);
106
    z.negate();
107
    bn_assert(BN_mul_word(z.bn_ptr(), -y));
108
    return z;
109
  } else {
110
    Bignum z(0);
111
    return z;
112
  }
113
}
114

115
/*
116
  const Bignum operator* (Bignum&& x, long y) {
117
    if (y > 0) {
118
      bn_assert (BN_mul_word (x.bn_ptr(), y));
119
    } else if (y < 0) {
120
      x.negate();
121
      bn_assert (BN_mul_word (x.bn_ptr(), -y));
122
    } else {
123
      x = 0;
124
    }
125
    return std::move (x);
126
  }
127
  */
128

129
const Bignum operator/(const Bignum& x, const Bignum& y) {
130
  Bignum z, w;
131
  bn_assert(BN_div(z.bn_ptr(), w.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx()));
132
  return z;
133
}
134

135
const Bignum Bignum::divmod(const Bignum& y) {
136
  Bignum w;
137
  bn_assert(BN_div(val, w.bn_ptr(), val, y.bn_ptr(), get_ctx()));
138
  return w;
139
}
140

141
const Bignum operator%(const Bignum& x, const Bignum& y) {
142
  Bignum z;
143
  bn_assert(BN_mod(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx()));
144
  return z;
145
}
146

147
unsigned long operator%(const Bignum& x, unsigned long y) {
148
  BN_ULONG rem = BN_mod_word(x.bn_ptr(), y);
149
  bn_assert(rem != (BN_ULONG)(-1));
150
  return static_cast<unsigned long>(rem);
151
}
152

153
const Bignum operator<<(const Bignum& x, int r) {
154
  Bignum z;
155
  bn_assert(BN_lshift(z.bn_ptr(), x.bn_ptr(), r));
156
  return z;
157
}
158

159
const Bignum operator>>(const Bignum& x, int r) {
160
  Bignum z;
161
  bn_assert(BN_rshift(z.bn_ptr(), x.bn_ptr(), r));
162
  return z;
163
}
164

165
const Bignum abs(const Bignum& x) {
166
  Bignum T(x);
167
  if (T.sign() < 0) {
168
    T.negate();
169
  }
170
  return T;
171
}
172

173
const Bignum sqr(const Bignum& x) {
174
  Bignum z;
175
  bn_assert(BN_sqr(z.bn_ptr(), x.bn_ptr(), get_ctx()));
176
  return z;
177
}
178

179
void Bignum::export_msb(unsigned char* buffer, std::size_t size) const {
180
  bn_assert(size <= (1 << 20));
181
  bn_assert(sign() >= 0);
182
  std::size_t n = BN_num_bytes(val);
183
  bn_assert(n <= size);
184
  bn_assert(BN_bn2bin(val, buffer + size - n) == static_cast<int>(n));
185
  std::memset(buffer, 0, size - n);
186
}
187

188
Bignum& Bignum::import_msb(const unsigned char* buffer, std::size_t size) {
189
  bn_assert(size <= (1 << 20));
190
  std::size_t i = 0;
191
  while (i < size && !buffer[i]) {
192
    i++;
193
  }
194
  bn_assert(BN_bin2bn(buffer + i, static_cast<int>(size - i), val) == val);
195
  return *this;
196
}
197

198
void Bignum::export_lsb(unsigned char* buffer, std::size_t size) const {
199
  bn_assert(size <= (1 << 20));
200
  bn_assert(sign() >= 0);
201
  std::size_t n = BN_num_bytes(val);
202
  bn_assert(n <= size);
203
  bn_assert(BN_bn2bin(val, buffer) == (int)n);
204
  std::memset(buffer + n, 0, size - n);
205
  for (std::size_t i = 0; 2 * i + 1 < n; i++) {
206
    std::swap(buffer[i], buffer[n - 1 - i]);
207
  }
208
}
209

210
Bignum& Bignum::import_lsb(const unsigned char* buffer, std::size_t size) {
211
  bn_assert(size <= (1 << 20));
212
  while (size > 0 && !buffer[size - 1]) {
213
    size--;
214
  }
215
  if (!size) {
216
    // Use BN_set_word, because from 1.1.0 BN_zero may return void
217
    bn_assert(BN_set_word(val, 0));
218
    return *this;
219
  }
220
  unsigned char tmp_buff[1024];
221
  unsigned char* tmp = (size < 1024 ? tmp_buff : new unsigned char[size]);
222
  unsigned char* ptr = tmp + size;
223
  for (std::size_t i = 0; i < size; i++) {
224
    *--ptr = buffer[i];
225
  }
226
  bn_assert(BN_bin2bn(tmp, static_cast<int>(size), val) == val);
227
  if (tmp != tmp_buff) {
228
    delete[] tmp;
229
  }
230
  return *this;
231
}
232

233
std::string Bignum::to_str() const {
234
  char* ptr = BN_bn2dec(val);
235
  CHECK(ptr);
236
  std::string z(ptr);
237
  OPENSSL_free(ptr);
238
  return z;
239
}
240

241
std::string Bignum::to_hex() const {
242
  char* ptr = BN_bn2hex(val);
243
  CHECK(ptr);
244
  std::string z(ptr);
245
  OPENSSL_free(ptr);
246
  return z;
247
}
248

249
std::ostream& operator<<(std::ostream& os, const Bignum& x) {
250
  return os << x.to_str();
251
}
252

253
std::istream& operator>>(std::istream& is, Bignum& x) {
254
  std::string word;
255
  is >> word;
256
  x = dec_string(word);
257
  return is;
258
}
259

260
bool is_prime(const Bignum& p) {
261
#if OPENSSL_VERSION_MAJOR >= 3
262
  int result = BN_check_prime(p.bn_ptr(), get_ctx(), nullptr);
263
  LOG_IF(FATAL, result == -1);
264
  return result;
265
#else
266
  return BN_is_prime_fasttest_ex(p.bn_ptr(), BN_prime_checks, get_ctx(), true, 0);
267
#endif
268
}
269
}  // namespace arith
270

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

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

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

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