1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

initial commit

This commit is contained in:
initial commit 2019-09-07 14:03:22 +04:00 committed by vvaltman
commit c2da007f40
1610 changed files with 398047 additions and 0 deletions

256
crypto/openssl/bignum.cpp Normal file
View file

@ -0,0 +1,256 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "openssl/bignum.h"
// impl only
#include <cstring>
namespace arith {
BN_CTX* get_ctx(void) {
thread_local BN_CTX* ctx = BN_CTX_new();
return ctx;
}
BignumBitref& BignumBitref::operator=(bool val) {
if (val) {
BN_set_bit(ptr, n);
} else {
BN_clear_bit(ptr, n);
}
return *this;
}
const Bignum operator+(const Bignum& x, const Bignum& y) {
Bignum z;
bn_assert(BN_add(z.bn_ptr(), x.bn_ptr(), y.bn_ptr()));
return z;
}
const Bignum operator+(const Bignum& x, long y) {
if (y > 0) {
Bignum z(x);
bn_assert(BN_add_word(z.bn_ptr(), y));
return z;
} else if (y < 0) {
Bignum z(x);
bn_assert(BN_sub_word(z.bn_ptr(), -y));
return z;
} else {
return x;
}
}
/*
const Bignum operator+ (Bignum&& x, long y) {
if (y > 0) {
bn_assert (BN_add_word (x.bn_ptr(), y));
} else if (y < 0) {
bn_assert (BN_sub_word (x.bn_ptr(), -y));
}
return std::move (x);
}
*/
/*
const Bignum operator+ (long y, Bignum&& x) {
return x + y;
}
*/
const Bignum operator-(const Bignum& x, const Bignum& y) {
Bignum z;
bn_assert(BN_sub(z.bn_ptr(), x.bn_ptr(), y.bn_ptr()));
return z;
}
/*
const Bignum operator- (Bignum&& x, long y) {
return x + (-y);
}
*/
const Bignum operator*(const Bignum& x, const Bignum& y) {
Bignum z;
bn_assert(BN_mul(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx()));
return z;
}
const Bignum operator*(const Bignum& x, long y) {
if (y > 0) {
Bignum z(x);
bn_assert(BN_mul_word(z.bn_ptr(), y));
return z;
} else if (y < 0) {
Bignum z(x);
z.negate();
bn_assert(BN_mul_word(z.bn_ptr(), -y));
return z;
} else {
Bignum z(0);
return z;
}
}
/*
const Bignum operator* (Bignum&& x, long y) {
if (y > 0) {
bn_assert (BN_mul_word (x.bn_ptr(), y));
} else if (y < 0) {
x.negate();
bn_assert (BN_mul_word (x.bn_ptr(), -y));
} else {
x = 0;
}
return std::move (x);
}
*/
const Bignum operator/(const Bignum& x, const Bignum& y) {
Bignum z, w;
bn_assert(BN_div(z.bn_ptr(), w.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx()));
return z;
}
const Bignum Bignum::divmod(const Bignum& y) {
Bignum w;
bn_assert(BN_div(val, w.bn_ptr(), val, y.bn_ptr(), get_ctx()));
return w;
}
const Bignum operator%(const Bignum& x, const Bignum& y) {
Bignum z;
bn_assert(BN_mod(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx()));
return z;
}
unsigned long operator%(const Bignum& x, unsigned long y) {
BN_ULONG rem = BN_mod_word(x.bn_ptr(), y);
bn_assert(rem != (BN_ULONG)(-1));
return static_cast<unsigned long>(rem);
}
const Bignum operator<<(const Bignum& x, int r) {
Bignum z;
bn_assert(BN_lshift(z.bn_ptr(), x.bn_ptr(), r));
return z;
}
const Bignum operator>>(const Bignum& x, int r) {
Bignum z;
bn_assert(BN_rshift(z.bn_ptr(), x.bn_ptr(), r));
return z;
}
const Bignum abs(const Bignum& x) {
Bignum T(x);
if (T.sign() < 0) {
T.negate();
}
return T;
}
const Bignum sqr(const Bignum& x) {
Bignum z;
bn_assert(BN_sqr(z.bn_ptr(), x.bn_ptr(), get_ctx()));
return z;
}
void Bignum::export_msb(unsigned char* buffer, std::size_t size) const {
bn_assert(size <= (1 << 20));
bn_assert(sign() >= 0);
std::size_t n = BN_num_bytes(val);
bn_assert(n <= size);
bn_assert(BN_bn2bin(val, buffer + size - n) == static_cast<int>(n));
std::memset(buffer, 0, size - n);
}
Bignum& Bignum::import_msb(const unsigned char* buffer, std::size_t size) {
bn_assert(size <= (1 << 20));
std::size_t i = 0;
while (i < size && !buffer[i]) {
i++;
}
bn_assert(BN_bin2bn(buffer + i, static_cast<int>(size - i), val) == val);
return *this;
}
void Bignum::export_lsb(unsigned char* buffer, std::size_t size) const {
bn_assert(size <= (1 << 20));
bn_assert(sign() >= 0);
std::size_t n = BN_num_bytes(val);
bn_assert(n <= size);
bn_assert(BN_bn2bin(val, buffer) == (int)n);
std::memset(buffer + n, 0, size - n);
for (std::size_t i = 0; 2 * i + 1 < n; i++) {
std::swap(buffer[i], buffer[n - 1 - i]);
}
}
Bignum& Bignum::import_lsb(const unsigned char* buffer, std::size_t size) {
bn_assert(size <= (1 << 20));
while (size > 0 && !buffer[size - 1]) {
size--;
}
if (!size) {
bn_assert(BN_zero(val));
return *this;
}
unsigned char tmp_buff[1024];
unsigned char* tmp = (size < 1024 ? tmp_buff : new unsigned char[size]);
unsigned char* ptr = tmp + size;
for (std::size_t i = 0; i < size; i++) {
*--ptr = buffer[i];
}
bn_assert(BN_bin2bn(tmp, static_cast<int>(size), val) == val);
if (tmp != tmp_buff) {
delete[] tmp;
}
return *this;
}
std::string Bignum::to_str() const {
char* ptr = BN_bn2dec(val);
std::string z(ptr);
OPENSSL_free(ptr);
return z;
}
std::string Bignum::to_hex() const {
char* ptr = BN_bn2hex(val);
std::string z(ptr);
OPENSSL_free(ptr);
return z;
}
std::ostream& operator<<(std::ostream& os, const Bignum& x) {
return os << x.to_str();
}
std::istream& operator>>(std::istream& is, Bignum& x) {
std::string word;
is >> word;
x = dec_string(word);
return is;
}
bool is_prime(const Bignum& p, int nchecks, bool trial_div) {
return BN_is_prime_fasttest_ex(p.bn_ptr(), BN_prime_checks, get_ctx(), trial_div, 0);
}
} // namespace arith

368
crypto/openssl/bignum.h Normal file
View file

@ -0,0 +1,368 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <string>
#include <iostream>
#include <openssl/bn.h>
#include "td/utils/bits.h"
namespace arith {
struct dec_string {
std::string str;
explicit dec_string(const std::string& s) : str(s) {
}
};
struct hex_string {
std::string str;
explicit hex_string(const std::string& s) : str(s) {
}
};
} // namespace arith
namespace arith {
inline void bn_assert(int cond);
BN_CTX* get_ctx();
class BignumBitref {
BIGNUM* ptr;
int n;
public:
BignumBitref(BIGNUM* x, int _n) : ptr(x), n(_n){};
operator bool() const {
return BN_is_bit_set(ptr, n);
}
BignumBitref& operator=(bool val);
};
class Bignum {
BIGNUM* val;
public:
class bignum_error {};
Bignum() {
val = BN_new();
}
Bignum(long x) {
val = BN_new();
set_long(x);
}
~Bignum() {
BN_free(val);
}
Bignum(const dec_string& ds) {
val = BN_new();
set_dec_str(ds.str);
}
Bignum(const hex_string& hs) {
val = BN_new();
set_hex_str(hs.str);
}
Bignum(const Bignum& x) {
val = BN_new();
BN_copy(val, x.val);
}
//Bignum (Bignum&& x) { val = x.val; }
void clear() {
BN_clear(val);
} // use this for sensitive data
Bignum& operator=(const Bignum& x) {
BN_copy(val, x.val);
return *this;
}
Bignum& operator=(Bignum&& x) {
swap(x);
return *this;
}
Bignum& operator=(long x) {
return set_long(x);
}
Bignum& operator=(const dec_string& ds) {
return set_dec_str(ds.str);
}
Bignum& operator=(const hex_string& hs) {
return set_hex_str(hs.str);
}
Bignum& swap(Bignum& x) {
BN_swap(val, x.val);
return *this;
}
BIGNUM* bn_ptr() {
return val;
}
const BIGNUM* bn_ptr() const {
return val;
}
bool is_zero() const {
return BN_is_zero(val);
}
int sign() const {
return BN_is_zero(val) ? 0 : (BN_is_negative(val) ? -1 : 1);
}
bool odd() const {
return BN_is_odd(val);
}
int num_bits() const {
return BN_num_bits(val);
}
int num_bytes() const {
return BN_num_bytes(val);
}
bool operator[](int n) const {
return BN_is_bit_set(val, n);
}
BignumBitref operator[](int n) {
return BignumBitref(val, n);
}
void export_msb(unsigned char* buffer, std::size_t size) const;
Bignum& import_msb(const unsigned char* buffer, std::size_t size);
Bignum& import_msb(const std::string& s) {
return import_msb((const unsigned char*)s.c_str(), s.size());
}
void export_lsb(unsigned char* buffer, std::size_t size) const;
Bignum& import_lsb(const unsigned char* buffer, std::size_t size);
Bignum& import_lsb(const std::string& s) {
return import_lsb((const unsigned char*)s.c_str(), s.size());
}
Bignum& set_dec_str(std::string s) {
bn_assert(BN_dec2bn(&val, s.c_str()));
return *this;
}
Bignum& set_hex_str(std::string s) {
bn_assert(BN_hex2bn(&val, s.c_str()));
return *this;
}
Bignum& set_ulong(unsigned long x) {
bn_assert(BN_set_word(val, x));
return *this;
}
Bignum& set_long(long x) {
set_ulong(std::abs(x));
return x < 0 ? negate() : *this;
}
Bignum& negate() {
BN_set_negative(val, !BN_is_negative(val));
return *this;
}
Bignum& operator+=(const Bignum& y) {
bn_assert(BN_add(val, val, y.val));
return *this;
}
Bignum& operator+=(long y) {
bn_assert((y >= 0 ? BN_add_word : BN_sub_word)(val, std::abs(y)));
return *this;
}
Bignum& operator-=(long y) {
bn_assert((y >= 0 ? BN_sub_word : BN_add_word)(val, std::abs(y)));
return *this;
}
Bignum& operator*=(const Bignum& y) {
bn_assert(BN_mul(val, val, y.val, get_ctx()));
return *this;
}
Bignum& operator*=(long y) {
if (y < 0) {
negate();
}
bn_assert(BN_mul_word(val, std::abs(y)));
return *this;
}
Bignum& operator<<=(int r) {
bn_assert(BN_lshift(val, val, r));
return *this;
}
Bignum& operator>>=(int r) {
bn_assert(BN_rshift(val, val, r));
return *this;
}
Bignum& operator/=(const Bignum& y) {
Bignum w;
bn_assert(BN_div(val, w.val, val, y.val, get_ctx()));
return *this;
}
Bignum& operator/=(long y) {
bn_assert(BN_div_word(val, std::abs(y)) != (BN_ULONG)(-1));
return y < 0 ? negate() : *this;
}
Bignum& operator%=(const Bignum& y) {
bn_assert(BN_mod(val, val, y.val, get_ctx()));
return *this;
}
Bignum& operator%=(long y) {
BN_ULONG rem = BN_mod_word(val, std::abs(y));
bn_assert(rem != (BN_ULONG)(-1));
return set_long(static_cast<long>(y < 0 ? td::bits_negate64(rem) : rem));
}
unsigned long divmod(unsigned long y) {
BN_ULONG rem = BN_div_word(val, y);
bn_assert(rem != (BN_ULONG)(-1));
return static_cast<unsigned long>(rem);
}
const Bignum divmod(const Bignum& y);
std::string to_str() const;
std::string to_hex() const;
};
inline void bn_assert(int cond) {
if (!cond) {
throw Bignum::bignum_error();
}
}
BN_CTX* get_ctx(void);
const Bignum operator+(const Bignum& x, const Bignum& y);
const Bignum operator+(const Bignum& x, long y);
/*
const Bignum operator+ (Bignum&& x, long y) {
if (y > 0) {
bn_assert (BN_add_word (x.bn_ptr(), y));
} else if (y < 0) {
bn_assert (BN_sub_word (x.bn_ptr(), -y));
}
return std::move (x);
}
*/
inline const Bignum operator+(long y, const Bignum& x) {
return x + y;
}
/*
const Bignum operator+ (long y, Bignum&& x) {
return x + y;
}
*/
const Bignum operator-(const Bignum& x, const Bignum& y);
inline const Bignum operator-(const Bignum& x, long y) {
return x + (-y);
}
/*
const Bignum operator- (Bignum&& x, long y) {
return x + (-y);
}
*/
const Bignum operator*(const Bignum& x, const Bignum& y);
const Bignum operator*(const Bignum& x, long y);
/*
const Bignum operator* (Bignum&& x, long y) {
if (y > 0) {
bn_assert (BN_mul_word (x.bn_ptr(), y));
} else if (y < 0) {
x.negate();
bn_assert (BN_mul_word (x.bn_ptr(), -y));
} else {
x = 0;
}
return std::move (x);
}
*/
inline const Bignum operator*(long y, const Bignum& x) {
return x * y;
}
const Bignum operator/(const Bignum& x, const Bignum& y);
const Bignum operator%(const Bignum& x, const Bignum& y);
unsigned long operator%(const Bignum& x, unsigned long y);
const Bignum operator<<(const Bignum& x, int r);
const Bignum operator>>(const Bignum& x, int r);
const Bignum abs(const Bignum& x);
const Bignum sqr(const Bignum& x);
std::ostream& operator<<(std::ostream& os, const Bignum& x);
std::istream& operator>>(std::istream& is, Bignum& x);
bool is_prime(const Bignum& p, int nchecks = 64, bool trial_div = true);
inline int cmp(const Bignum& x, const Bignum& y) {
return BN_cmp(x.bn_ptr(), y.bn_ptr());
}
inline bool operator==(const Bignum& x, const Bignum& y) {
return cmp(x, y) == 0;
}
inline bool operator!=(const Bignum& x, const Bignum& y) {
return cmp(x, y) != 0;
}
inline bool operator<(const Bignum& x, const Bignum& y) {
return cmp(x, y) < 0;
}
inline bool operator<=(const Bignum& x, const Bignum& y) {
return cmp(x, y) <= 0;
}
inline bool operator>(const Bignum& x, const Bignum& y) {
return cmp(x, y) > 0;
}
inline bool operator>=(const Bignum& x, const Bignum& y) {
return cmp(x, y) >= 0;
}
inline bool operator==(const Bignum& x, long y) {
if (y >= 0) {
return BN_is_word(x.bn_ptr(), y);
} else {
return x == Bignum(y);
}
}
inline bool operator!=(const Bignum& x, long y) {
if (y >= 0) {
return !BN_is_word(x.bn_ptr(), y);
} else {
return x != Bignum(y);
}
}
} // namespace arith

151
crypto/openssl/digest.h Normal file
View file

@ -0,0 +1,151 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <assert.h>
#include <openssl/evp.h>
#include <openssl/opensslv.h>
#include "td/utils/Slice.h"
namespace digest {
struct OpensslEVP_SHA1 {
enum { digest_bytes = 20 };
static const EVP_MD *get_evp() {
return EVP_sha1();
}
};
struct OpensslEVP_SHA256 {
enum { digest_bytes = 32 };
static const EVP_MD *get_evp() {
return EVP_sha256();
}
};
struct OpensslEVP_SHA512 {
enum { digest_bytes = 64 };
static const EVP_MD *get_evp() {
return EVP_sha512();
}
};
template <typename H>
class HashCtx {
EVP_MD_CTX *ctx{nullptr};
void init();
void clear();
public:
enum { digest_bytes = H::digest_bytes };
HashCtx() {
init();
}
HashCtx(const void *data, std::size_t len) {
init();
feed(data, len);
}
~HashCtx() {
clear();
}
void reset();
void feed(const void *data, std::size_t len);
void feed(td::Slice slice) {
feed(slice.data(), slice.size());
}
std::size_t extract(unsigned char buffer[digest_bytes]);
std::size_t extract(td::MutableSlice slice);
std::string extract();
};
template <typename H>
void HashCtx<H>::init() {
ctx = EVP_MD_CTX_create();
reset();
}
template <typename H>
void HashCtx<H>::reset() {
EVP_DigestInit_ex(ctx, H::get_evp(), 0);
}
template <typename H>
void HashCtx<H>::clear() {
EVP_MD_CTX_destroy(ctx);
ctx = nullptr;
}
template <typename H>
void HashCtx<H>::feed(const void *data, std::size_t len) {
EVP_DigestUpdate(ctx, data, len);
}
template <typename H>
std::size_t HashCtx<H>::extract(unsigned char buffer[digest_bytes]) {
unsigned olen = 0;
EVP_DigestFinal_ex(ctx, buffer, &olen);
assert(olen == digest_bytes);
return olen;
}
template <typename H>
std::size_t HashCtx<H>::extract(td::MutableSlice slice) {
return extract(slice.ubegin());
}
template <typename H>
std::string HashCtx<H>::extract() {
unsigned char buffer[digest_bytes];
unsigned olen = 0;
EVP_DigestFinal_ex(ctx, buffer, &olen);
assert(olen == digest_bytes);
return std::string((char *)buffer, olen);
}
typedef HashCtx<OpensslEVP_SHA1> SHA1;
typedef HashCtx<OpensslEVP_SHA256> SHA256;
typedef HashCtx<OpensslEVP_SHA512> SHA512;
template <typename T>
std::size_t hash_str(unsigned char buffer[T::digest_bytes], const void *data, std::size_t size) {
T hasher(data, size);
return hasher.extract(buffer);
}
template <typename T>
std::size_t hash_two_str(unsigned char buffer[T::digest_bytes], const void *data1, std::size_t size1, const void *data2,
std::size_t size2) {
T hasher(data1, size1);
hasher.feed(data2, size2);
return hasher.extract(buffer);
}
template <typename T>
std::string hash_str(const void *data, std::size_t size) {
T hasher(data, size);
return hasher.extract();
}
template <typename T>
std::string hash_two_str(const void *data1, std::size_t size1, const void *data2, std::size_t size2) {
T hasher(data1, size1);
hasher.feed(data2, size2);
return hasher.extract();
}
} // namespace digest

122
crypto/openssl/rand.cpp Normal file
View file

@ -0,0 +1,122 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "openssl/rand.hpp"
#include "td/utils/common.h"
#include <openssl/rand.h>
#include <openssl/opensslv.h>
namespace prng {
int os_get_random_bytes(void *buf, int n);
bool RandomGen::ok() const {
return RAND_status();
}
void RandomGen::seed_add(const void *data, std::size_t size, double entropy) {
RAND_add(data, static_cast<int>(size), entropy > 0 ? entropy : static_cast<double>(size));
}
void RandomGen::randomize(bool force) {
if (!force && ok()) {
return;
}
unsigned char buffer[128];
int n = os_get_random_bytes(buffer, 128);
seed_add(buffer, n);
assert(ok());
}
bool RandomGen::rand_bytes(void *data, std::size_t size, bool strong) {
#if OPENSSL_VERSION_NUMBER < 0x10101000L
int res = (strong ? RAND_bytes : RAND_pseudo_bytes)((unsigned char *)data, static_cast<int>(size));
#else
int res = RAND_bytes((unsigned char *)data, static_cast<int>(size));
#endif
if (res != 0 && res != 1) {
throw rand_error();
}
return res;
}
std::string RandomGen::rand_string(std::size_t size, bool strong) {
std::string result(size, '\0');
if (size > 0 && !rand_bytes(&result[0], size, strong)) {
throw rand_error();
}
return result;
}
RandomGen &rand_gen() {
// RandomGen is stateless, OpenSSL will handle concurrent access
static RandomGen MainPRNG;
return MainPRNG;
}
} // namespace prng
//------------------------- move to separate OS-dependent file?
#if TD_WINDOWS
namespace prng {
int os_get_random_bytes(void *buf, int n) {
return 0;
}
} // namespace prng
#else
#include <fcntl.h>
#include <unistd.h>
namespace prng {
int os_get_random_bytes(void *buf, int n) {
using namespace std;
int r = 0;
int h = open("/dev/random", O_RDONLY | O_NONBLOCK);
if (h >= 0) {
r = static_cast<int>(read(h, buf, n));
if (r > 0) {
//std::cerr << "added " << r << " bytes of real entropy to secure random numbers seed" << std::endl;
} else {
r = 0;
}
close(h);
}
if (r < n) {
h = open("/dev/urandom", O_RDONLY);
if (h < 0) {
return r;
}
int s = static_cast<int>(read(h, (char *)buf + r, n - r));
close(h);
if (s < 0) {
return r;
}
r += s;
}
if (r >= 8) {
*(long *)buf ^= lrand48();
srand48(*(long *)buf);
}
return r;
}
} // namespace prng
#endif

56
crypto/openssl/rand.hpp Normal file
View file

@ -0,0 +1,56 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <string>
#include <cassert>
namespace prng {
// use this generator unless need a separate one
class RandomGen;
RandomGen &rand_gen();
class RandomGen {
public:
struct rand_error {};
void randomize(bool force = true);
void seed_add(const void *data, std::size_t size, double entropy = 0);
bool ok() const;
RandomGen() {
randomize(false);
}
RandomGen(const void *seed, std::size_t size) {
seed_add(seed, size);
randomize(false);
}
bool rand_bytes(void *data, std::size_t size, bool strong = false);
bool strong_rand_bytes(void *data, std::size_t size) {
return rand_bytes(data, size, true);
}
template <class T>
bool rand_obj(T &obj) {
return rand_bytes(&obj, sizeof(T));
}
template <class T>
bool rand_objs(T *ptr, std::size_t count) {
return rand_bytes(ptr, sizeof(T) * count);
}
std::string rand_string(std::size_t size, bool strong = false);
};
} // namespace prng

176
crypto/openssl/residue.cpp Normal file
View file

@ -0,0 +1,176 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "residue.h"
// --- impl
#include <assert.h>
namespace arith {
class Residue;
class ResidueRing;
void ResidueRing::init() {
Zero = new Residue(0, td::Ref<ResidueRing>(this));
One = new Residue(1, td::Ref<ResidueRing>(this));
}
ResidueRing::~ResidueRing() {
delete Zero;
delete One;
delete Img_i;
Zero = One = Img_i = 0;
}
const Residue operator+(const Residue& x, const Residue& y) {
x.same_ring(y);
Residue z(x.ring_ref());
bn_assert(BN_mod_add(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
return z;
}
const Residue operator-(const Residue& x, const Residue& y) {
x.same_ring(y);
Residue z(x.ring_ref());
bn_assert(BN_mod_sub(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
return z;
}
const Residue operator*(const Residue& x, const Residue& y) {
x.same_ring(y);
Residue z(x.ring_ref());
bn_assert(BN_mod_mul(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
return z;
}
const Residue operator-(const Residue& x) {
Residue z(x);
z.val.negate();
return z.reduce();
}
Residue& Residue::operator+=(const Residue& y) {
same_ring(y);
bn_assert(BN_mod_add(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx()));
return *this;
}
Residue& Residue::operator-=(const Residue& y) {
same_ring(y);
bn_assert(BN_mod_sub(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx()));
return *this;
}
Residue& Residue::operator*=(const Residue& y) {
same_ring(y);
bn_assert(BN_mod_mul(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx()));
return *this;
}
bool operator==(const Residue& x, const Residue& y) {
x.same_ring(y);
return x.extract() == y.extract();
}
bool operator!=(const Residue& x, const Residue& y) {
x.same_ring(y);
return x.extract() != y.extract();
}
Residue sqr(const Residue& x) {
Residue z(x.ring_ref());
bn_assert(BN_mod_sqr(z.val.bn_ptr(), x.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
return z;
}
Residue power(const Residue& x, const Bignum& y) {
Residue z(x.ring_ref());
bn_assert(BN_mod_exp(z.val.bn_ptr(), x.val.bn_ptr(), y.bn_ptr(), x.modulus().bn_ptr(), get_ctx()));
return z;
}
Residue inverse(const Residue& x) {
assert(x.ring_ref()->is_prime());
return power(x, x.ring_ref()->get_modulus() - 2);
}
const Residue& ResidueRing::img_i() const {
if (!Img_i) {
assert(is_prime());
assert(modulus % 4 == 1);
int g = 2;
Bignum n = (modulus - 1) / 4;
while (true) {
Residue t = power(frac(g), n);
if (t != one() && t != frac(-1)) {
Img_i = new Residue(t);
break;
}
g++;
}
}
return *Img_i;
}
Residue sqrt(const Residue& x) {
assert(x.ring_of().is_prime());
const ResidueRing& R = x.ring_of();
const Bignum& p = R.get_modulus();
if (x.is_zero() || !p.odd()) {
return x;
}
if (p[1]) { // p=3 (mod 4)
return power(x, (p + 1) >> 2);
} else if (p[2]) {
// p=5 (mod 8)
Residue t = power(x, (p + 3) >> 3);
return (sqr(t) == x) ? t : R.img_i() * t;
} else {
assert(p[2]);
return R.zero();
}
}
Residue ResidueRing::frac(long num, long denom) const {
assert(denom);
if (denom < 0) {
num = -num;
denom = -denom;
}
if (!(num % denom)) {
return Residue(num / denom, self_ref());
} else {
return Residue(num, self_ref()) * inverse(Residue(denom, self_ref()));
}
}
std::string Residue::to_str() const {
return "Mod(" + val.to_str() + "," + modulus().to_str() + ")";
}
std::ostream& operator<<(std::ostream& os, const Residue& x) {
return os << x.to_str();
}
std::istream& operator>>(std::istream& is, Residue& x) {
std::string word;
is >> word;
x = dec_string(word);
return is;
}
} // namespace arith

189
crypto/openssl/residue.h Normal file
View file

@ -0,0 +1,189 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "bignum.h"
#include "common/refcnt.hpp"
namespace arith {
class Residue;
class ResidueRing;
class ResidueRing : public td::CntObject {
public:
struct bad_modulus {};
private:
const Bignum modulus;
bool prime;
Residue* Zero;
Residue* One;
mutable Residue* Img_i;
void init();
public:
typedef Residue element;
explicit ResidueRing(Bignum mod) : modulus(mod), prime(arith::is_prime(mod)), Zero(0), One(0), Img_i(0) {
init();
}
~ResidueRing();
const Bignum& get_modulus() const {
return modulus;
}
bool is_prime() const {
return prime;
}
const Residue& zero() const {
return *Zero;
}
const Residue& one() const {
return *One;
}
const Residue& img_i() const;
Residue frac(long num, long denom = 1) const;
Residue convert(long num) const;
Residue convert(const Bignum& x) const;
Bignum reduce(const Bignum& x) const {
Bignum r = x % modulus;
if (r.sign() < 0) {
r += modulus;
}
return r;
}
Bignum& do_reduce(Bignum& x) const {
x %= modulus;
if (x.sign() < 0) {
x += modulus;
}
return x;
}
private:
td::Ref<ResidueRing> self_ref() const {
return td::Ref<ResidueRing>{this};
}
};
class Residue {
public:
struct not_same_ring {};
private:
td::Ref<ResidueRing> ring;
mutable Bignum val;
Residue& reduce() {
ring->do_reduce(val);
return *this;
}
public:
explicit Residue(td::Ref<ResidueRing> R) : ring(R) {
}
Residue(const Bignum& x, td::Ref<ResidueRing> R) : ring(R), val(R->reduce(x)) {
}
~Residue() {
}
Residue(const Residue& x) : ring(x.ring), val(x.val) {
}
Bignum extract() const {
return val;
}
const Bignum& extract_raw() const {
return val;
}
const Bignum& modulus() const {
return ring->get_modulus();
}
void same_ring(const Residue& y) const {
if (ring != y.ring) {
throw not_same_ring();
}
}
const ResidueRing& ring_of() const {
return *ring;
}
td::Ref<ResidueRing> ring_ref() const {
return ring;
}
bool is_zero() const {
return (val == 0);
}
Residue& operator=(const Residue& x) {
same_ring(x);
val = x.val;
return *this;
}
Residue& operator=(const Bignum& x) {
val = ring->reduce(x);
return *this;
}
Residue& operator+=(const Residue& y);
Residue& operator-=(const Residue& y);
Residue& operator*=(const Residue& y);
Residue& operator+=(long y) {
val += y;
return reduce();
}
Residue& operator-=(long y) {
val -= y;
return reduce();
}
Residue& operator*=(long y) {
val *= y;
return reduce();
}
Residue& negate() {
val.negate();
return reduce();
}
friend const Residue operator+(const Residue& x, const Residue& y);
friend const Residue operator-(const Residue& x, const Residue& y);
friend const Residue operator*(const Residue& x, const Residue& y);
friend const Residue operator-(const Residue& x);
friend Residue sqr(const Residue& x);
friend Residue power(const Residue& x, const Bignum& y);
friend Residue inverse(const Residue& x);
std::string to_str() const;
};
const Residue operator+(const Residue& x, const Residue& y);
const Residue operator-(const Residue& x, const Residue& y);
const Residue operator*(const Residue& x, const Residue& y);
const Residue operator-(const Residue& x);
bool operator==(const Residue& x, const Residue& y);
bool operator!=(const Residue& x, const Residue& y);
Residue sqr(const Residue& x);
Residue power(const Residue& x, const Bignum& y);
Residue inverse(const Residue& x);
Residue sqrt(const Residue& x);
inline Residue ResidueRing::convert(long x) const {
return Residue(x, td::Ref<ResidueRing>(this));
}
inline Residue ResidueRing::convert(const Bignum& x) const {
return Residue(x, td::Ref<ResidueRing>(this));
}
std::ostream& operator<<(std::ostream& os, const Residue& x);
std::istream& operator>>(std::istream& is, Residue& x);
} // namespace arith