mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Start cleanup into ripple_data, split out some hash_value() instances Tidy up CBigNum into ripple_data, moving definitions to .cpp Split and clean up base58 stuff Remove unused files from VS2012 project Clean up some bignum stuff and remove unused files Partial cleanup of RFC1751 Enormous cleanup with RippleAddress and related, into ripple_data Remove unused VS project files Move ECIES stuff into CKey
531 lines
12 KiB
C++
531 lines
12 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2011 The Bitcoin developers
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
CBigNum::CBigNum()
|
|
{
|
|
BN_init(this);
|
|
}
|
|
|
|
CBigNum::CBigNum(const CBigNum& b)
|
|
{
|
|
BN_init(this);
|
|
if (!BN_copy(this, &b))
|
|
{
|
|
BN_clear_free(this);
|
|
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
|
|
}
|
|
}
|
|
|
|
CBigNum& CBigNum::operator=(const CBigNum& b)
|
|
{
|
|
if (!BN_copy(this, &b))
|
|
throw bignum_error("CBigNum::operator= : BN_copy failed");
|
|
return (*this);
|
|
}
|
|
|
|
CBigNum::~CBigNum()
|
|
{
|
|
BN_clear_free(this);
|
|
}
|
|
|
|
CBigNum::CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
|
CBigNum::CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
|
CBigNum::CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
|
CBigNum::CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
|
CBigNum::CBigNum(int64 n) { BN_init(this); setint64(n); }
|
|
CBigNum::CBigNum(unsigned char n) { BN_init(this); setulong(n); }
|
|
CBigNum::CBigNum(unsigned short n) { BN_init(this); setulong(n); }
|
|
CBigNum::CBigNum(unsigned int n) { BN_init(this); setulong(n); }
|
|
CBigNum::CBigNum(uint64 n) { BN_init(this); setuint64(n); }
|
|
CBigNum::CBigNum(uint256 n) { BN_init(this); setuint256(n); }
|
|
|
|
CBigNum::CBigNum(const std::vector<unsigned char>& vch)
|
|
{
|
|
BN_init(this);
|
|
setvch(vch);
|
|
}
|
|
|
|
void CBigNum::setuint(unsigned int n)
|
|
{
|
|
setulong(static_cast<unsigned long>(n));
|
|
}
|
|
|
|
unsigned int CBigNum::getuint() const
|
|
{
|
|
return BN_get_word(this);
|
|
}
|
|
|
|
int CBigNum::getint() const
|
|
{
|
|
unsigned long n = BN_get_word(this);
|
|
if (!BN_is_negative(this))
|
|
return (n > INT_MAX ? INT_MAX : n);
|
|
else
|
|
return (n > INT_MAX ? INT_MIN : -(int)n);
|
|
}
|
|
|
|
void CBigNum::setint64(int64 n)
|
|
{
|
|
unsigned char pch[sizeof(n) + 6];
|
|
unsigned char* p = pch + 4;
|
|
bool fNegative = false;
|
|
if (n < (int64)0)
|
|
{
|
|
n = -n;
|
|
fNegative = true;
|
|
}
|
|
bool fLeadingZeroes = true;
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
unsigned char c = (n >> 56) & 0xff;
|
|
n <<= 8;
|
|
if (fLeadingZeroes)
|
|
{
|
|
if (c == 0)
|
|
continue;
|
|
if (c & 0x80)
|
|
*p++ = (fNegative ? 0x80 : 0);
|
|
else if (fNegative)
|
|
c |= 0x80;
|
|
fLeadingZeroes = false;
|
|
}
|
|
*p++ = c;
|
|
}
|
|
unsigned int nSize = p - (pch + 4);
|
|
pch[0] = (nSize >> 24) & 0xff;
|
|
pch[1] = (nSize >> 16) & 0xff;
|
|
pch[2] = (nSize >> 8) & 0xff;
|
|
pch[3] = (nSize) & 0xff;
|
|
BN_mpi2bn(pch, p - pch, this);
|
|
}
|
|
|
|
uint64 CBigNum::getuint64() const
|
|
{
|
|
#if (ULONG_MAX > UINT_MAX)
|
|
return static_cast<uint64>(getulong());
|
|
#else
|
|
int len = BN_num_bytes(this);
|
|
if (len > 8)
|
|
throw std::runtime_error("BN getuint64 overflow");
|
|
|
|
unsigned char buf[8];
|
|
memset(buf, 0, sizeof(buf));
|
|
BN_bn2bin(this, buf + 8 - len);
|
|
return
|
|
static_cast<uint64>(buf[0]) << 56 | static_cast<uint64>(buf[1]) << 48 |
|
|
static_cast<uint64>(buf[2]) << 40 | static_cast<uint64>(buf[3]) << 32 |
|
|
static_cast<uint64>(buf[4]) << 24 | static_cast<uint64>(buf[5]) << 16 |
|
|
static_cast<uint64>(buf[6]) << 8 | static_cast<uint64>(buf[7]);
|
|
#endif
|
|
}
|
|
|
|
void CBigNum::setuint64(uint64 n)
|
|
{
|
|
#if (ULONG_MAX > UINT_MAX)
|
|
setulong(static_cast<unsigned long>(n));
|
|
#else
|
|
unsigned char buf[8];
|
|
buf[0] = static_cast<unsigned char>((n >> 56) & 0xff);
|
|
buf[1] = static_cast<unsigned char>((n >> 48) & 0xff);
|
|
buf[2] = static_cast<unsigned char>((n >> 40) & 0xff);
|
|
buf[3] = static_cast<unsigned char>((n >> 32) & 0xff);
|
|
buf[4] = static_cast<unsigned char>((n >> 24) & 0xff);
|
|
buf[5] = static_cast<unsigned char>((n >> 16) & 0xff);
|
|
buf[6] = static_cast<unsigned char>((n >> 8) & 0xff);
|
|
buf[7] = static_cast<unsigned char>((n) & 0xff);
|
|
BN_bin2bn(buf, 8, this);
|
|
#endif
|
|
}
|
|
|
|
void CBigNum::setuint256(const uint256& n)
|
|
{
|
|
BN_bin2bn(n.begin(), n.size(), NULL);
|
|
}
|
|
|
|
uint256 CBigNum::getuint256()
|
|
{
|
|
uint256 ret;
|
|
unsigned int size = BN_num_bytes(this);
|
|
if (size > ret.size())
|
|
return ret;
|
|
BN_bn2bin(this, ret.begin() + (ret.size() - BN_num_bytes(this)));
|
|
return ret;
|
|
}
|
|
|
|
void CBigNum::setvch(const std::vector<unsigned char>& vch)
|
|
{
|
|
std::vector<unsigned char> vch2(vch.size() + 4);
|
|
unsigned int nSize = vch.size();
|
|
// BIGNUM's byte stream format expects 4 bytes of
|
|
// big endian size data info at the front
|
|
vch2[0] = (nSize >> 24) & 0xff;
|
|
vch2[1] = (nSize >> 16) & 0xff;
|
|
vch2[2] = (nSize >> 8) & 0xff;
|
|
vch2[3] = (nSize >> 0) & 0xff;
|
|
// swap data to big endian
|
|
std::reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
|
|
BN_mpi2bn(&vch2[0], vch2.size(), this);
|
|
}
|
|
|
|
std::vector<unsigned char> CBigNum::getvch() const
|
|
{
|
|
unsigned int nSize = BN_bn2mpi(this, NULL);
|
|
if (nSize < 4)
|
|
return std::vector<unsigned char>();
|
|
std::vector<unsigned char> vch(nSize);
|
|
BN_bn2mpi(this, &vch[0]);
|
|
vch.erase(vch.begin(), vch.begin() + 4);
|
|
reverse(vch.begin(), vch.end());
|
|
return vch;
|
|
}
|
|
|
|
CBigNum& CBigNum::SetCompact(unsigned int nCompact)
|
|
{
|
|
unsigned int nSize = nCompact >> 24;
|
|
std::vector<unsigned char> vch(4 + nSize);
|
|
vch[3] = nSize;
|
|
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
|
|
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
|
|
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
|
|
BN_mpi2bn(&vch[0], vch.size(), this);
|
|
return *this;
|
|
}
|
|
|
|
unsigned int CBigNum::GetCompact() const
|
|
{
|
|
unsigned int nSize = BN_bn2mpi(this, NULL);
|
|
std::vector<unsigned char> vch(nSize);
|
|
nSize -= 4;
|
|
BN_bn2mpi(this, &vch[0]);
|
|
unsigned int nCompact = nSize << 24;
|
|
if (nSize >= 1) nCompact |= (vch[4] << 16);
|
|
if (nSize >= 2) nCompact |= (vch[5] << 8);
|
|
if (nSize >= 3) nCompact |= (vch[6] << 0);
|
|
return nCompact;
|
|
}
|
|
|
|
void CBigNum::SetHex(const std::string& str)
|
|
{
|
|
// skip 0x
|
|
const char* psz = str.c_str();
|
|
while (isspace(*psz))
|
|
psz++;
|
|
bool fNegative = false;
|
|
if (*psz == '-')
|
|
{
|
|
fNegative = true;
|
|
psz++;
|
|
}
|
|
if (psz[0] == '0' && tolower(psz[1]) == 'x')
|
|
psz += 2;
|
|
while (isspace(*psz))
|
|
psz++;
|
|
|
|
// hex string to bignum
|
|
static char phexdigit[256] = {
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
|
|
0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
|
|
*this = 0;
|
|
while (isxdigit(*psz))
|
|
{
|
|
*this <<= 4;
|
|
int n = phexdigit[(int) *psz++];
|
|
*this += n;
|
|
}
|
|
if (fNegative)
|
|
*this = 0 - *this;
|
|
}
|
|
|
|
std::string CBigNum::ToString(int nBase) const
|
|
{
|
|
CAutoBN_CTX pctx;
|
|
CBigNum bnBase = nBase;
|
|
CBigNum bn0 = 0;
|
|
std::string str;
|
|
CBigNum bn = *this;
|
|
BN_set_negative(&bn, false);
|
|
CBigNum dv;
|
|
CBigNum rem;
|
|
if (BN_cmp(&bn, &bn0) == 0)
|
|
return "0";
|
|
while (BN_cmp(&bn, &bn0) > 0)
|
|
{
|
|
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
|
|
throw bignum_error("CBigNum::ToString() : BN_div failed");
|
|
bn = dv;
|
|
unsigned int c = rem.getuint();
|
|
str += "0123456789abcdef"[c];
|
|
}
|
|
if (BN_is_negative(this))
|
|
str += "-";
|
|
reverse(str.begin(), str.end());
|
|
return str;
|
|
}
|
|
|
|
std::string CBigNum::GetHex() const
|
|
{
|
|
return ToString(16);
|
|
}
|
|
|
|
bool CBigNum::operator!() const
|
|
{
|
|
return BN_is_zero(this);
|
|
}
|
|
|
|
CBigNum& CBigNum::operator+=(const CBigNum& b)
|
|
{
|
|
if (!BN_add(this, this, &b))
|
|
throw bignum_error("CBigNum::operator+= : BN_add failed");
|
|
return *this;
|
|
}
|
|
|
|
CBigNum& CBigNum::operator-=(const CBigNum& b)
|
|
{
|
|
*this = *this - b;
|
|
return *this;
|
|
}
|
|
|
|
CBigNum& CBigNum::operator*=(const CBigNum& b)
|
|
{
|
|
CAutoBN_CTX pctx;
|
|
if (!BN_mul(this, this, &b, pctx))
|
|
throw bignum_error("CBigNum::operator*= : BN_mul failed");
|
|
return *this;
|
|
}
|
|
|
|
CBigNum& CBigNum::operator/=(const CBigNum& b)
|
|
{
|
|
*this = *this / b;
|
|
return *this;
|
|
}
|
|
|
|
CBigNum& CBigNum::operator%=(const CBigNum& b)
|
|
{
|
|
*this = *this % b;
|
|
return *this;
|
|
}
|
|
|
|
CBigNum& CBigNum::operator<<=(unsigned int shift)
|
|
{
|
|
if (!BN_lshift(this, this, shift))
|
|
throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
|
|
return *this;
|
|
}
|
|
|
|
CBigNum& CBigNum::operator>>=(unsigned int shift)
|
|
{
|
|
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
|
|
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
|
|
CBigNum a = 1;
|
|
a <<= shift;
|
|
if (BN_cmp(&a, this) > 0)
|
|
{
|
|
*this = 0;
|
|
return *this;
|
|
}
|
|
|
|
if (!BN_rshift(this, this, shift))
|
|
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
|
|
return *this;
|
|
}
|
|
|
|
|
|
CBigNum& CBigNum::operator++()
|
|
{
|
|
// prefix operator
|
|
if (!BN_add(this, this, BN_value_one()))
|
|
throw bignum_error("CBigNum::operator++ : BN_add failed");
|
|
return *this;
|
|
}
|
|
|
|
const CBigNum CBigNum::operator++(int)
|
|
{
|
|
// postfix operator
|
|
const CBigNum ret = *this;
|
|
++(*this);
|
|
return ret;
|
|
}
|
|
|
|
CBigNum& CBigNum::operator--()
|
|
{
|
|
// prefix operator
|
|
CBigNum r;
|
|
if (!BN_sub(&r, this, BN_value_one()))
|
|
throw bignum_error("CBigNum::operator-- : BN_sub failed");
|
|
*this = r;
|
|
return *this;
|
|
}
|
|
|
|
const CBigNum CBigNum::operator--(int)
|
|
{
|
|
// postfix operator
|
|
const CBigNum ret = *this;
|
|
--(*this);
|
|
return ret;
|
|
}
|
|
|
|
void CBigNum::setulong(unsigned long n)
|
|
{
|
|
if (!BN_set_word(this, n))
|
|
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
|
|
}
|
|
|
|
unsigned long CBigNum::getulong() const
|
|
{
|
|
return BN_get_word(this);
|
|
}
|
|
|
|
const CBigNum operator+(const CBigNum& a, const CBigNum& b)
|
|
{
|
|
CBigNum r;
|
|
if (!BN_add(&r, &a, &b))
|
|
throw bignum_error("CBigNum::operator+ : BN_add failed");
|
|
return r;
|
|
}
|
|
|
|
const CBigNum operator-(const CBigNum& a, const CBigNum& b)
|
|
{
|
|
CBigNum r;
|
|
if (!BN_sub(&r, &a, &b))
|
|
throw bignum_error("CBigNum::operator- : BN_sub failed");
|
|
return r;
|
|
}
|
|
|
|
const CBigNum operator-(const CBigNum& a)
|
|
{
|
|
CBigNum r(a);
|
|
BN_set_negative(&r, !BN_is_negative(&r));
|
|
return r;
|
|
}
|
|
|
|
const CBigNum operator*(const CBigNum& a, const CBigNum& b)
|
|
{
|
|
CAutoBN_CTX pctx;
|
|
CBigNum r;
|
|
if (!BN_mul(&r, &a, &b, pctx))
|
|
throw bignum_error("CBigNum::operator* : BN_mul failed");
|
|
return r;
|
|
}
|
|
|
|
const CBigNum operator/(const CBigNum& a, const CBigNum& b)
|
|
{
|
|
CAutoBN_CTX pctx;
|
|
CBigNum r;
|
|
if (!BN_div(&r, NULL, &a, &b, pctx))
|
|
throw bignum_error("CBigNum::operator/ : BN_div failed");
|
|
return r;
|
|
}
|
|
|
|
const CBigNum operator%(const CBigNum& a, const CBigNum& b)
|
|
{
|
|
CAutoBN_CTX pctx;
|
|
CBigNum r;
|
|
if (!BN_mod(&r, &a, &b, pctx))
|
|
throw bignum_error("CBigNum::operator% : BN_div failed");
|
|
return r;
|
|
}
|
|
|
|
const CBigNum operator<<(const CBigNum& a, unsigned int shift)
|
|
{
|
|
CBigNum r;
|
|
if (!BN_lshift(&r, &a, shift))
|
|
throw bignum_error("CBigNum:operator<< : BN_lshift failed");
|
|
return r;
|
|
}
|
|
|
|
const CBigNum operator>>(const CBigNum& a, unsigned int shift)
|
|
{
|
|
CBigNum r = a;
|
|
r >>= shift;
|
|
return r;
|
|
}
|
|
|
|
bool operator== (const CBigNum& a, const CBigNum& b)
|
|
{
|
|
return (BN_cmp(&a, &b) == 0);
|
|
}
|
|
|
|
bool operator!= (const CBigNum& a, const CBigNum& b)
|
|
{
|
|
return (BN_cmp(&a, &b) != 0);
|
|
}
|
|
|
|
bool operator<= (const CBigNum& a, const CBigNum& b)
|
|
{
|
|
return (BN_cmp(&a, &b) <= 0);
|
|
}
|
|
|
|
bool operator>= (const CBigNum& a, const CBigNum& b)
|
|
{
|
|
return (BN_cmp(&a, &b) >= 0);
|
|
}
|
|
|
|
bool operator< (const CBigNum& a, const CBigNum& b)
|
|
{
|
|
return (BN_cmp(&a, &b) < 0);
|
|
}
|
|
|
|
bool operator> (const CBigNum& a, const CBigNum& b)
|
|
{
|
|
return (BN_cmp(&a, &b) > 0);
|
|
}
|
|
|
|
#if (ULONG_MAX > UINT_MAX)
|
|
|
|
int BN_add_word64 (BIGNUM* bn, uint64 word)
|
|
{
|
|
return BN_add_word(bn, word);
|
|
}
|
|
|
|
int BN_sub_word64 (BIGNUM* bn, uint64 word)
|
|
{
|
|
return BN_sub_word(bn, word);
|
|
}
|
|
|
|
int BN_mul_word64 (BIGNUM* bn, uint64 word)
|
|
{
|
|
return BN_mul_word(bn, word);
|
|
}
|
|
|
|
uint64 BN_div_word64 (BIGNUM* bn, uint64 word)
|
|
{
|
|
return BN_div_word(bn, word);
|
|
}
|
|
|
|
#else
|
|
|
|
int BN_add_word64 (BIGNUM *a, uint64 w)
|
|
{
|
|
CBigNum bn(w);
|
|
return BN_add(a, &bn, a);
|
|
}
|
|
|
|
int BN_sub_word64 (BIGNUM *a, uint64 w)
|
|
{
|
|
CBigNum bn(w);
|
|
return BN_sub(a, &bn, a);
|
|
}
|
|
|
|
int BN_mul_word64 (BIGNUM *a, uint64 w)
|
|
{
|
|
CBigNum bn(w);
|
|
CAutoBN_CTX ctx;
|
|
return BN_mul(a, &bn, a, ctx);
|
|
}
|
|
|
|
uint64 BN_div_word64 (BIGNUM *a, uint64 w)
|
|
{
|
|
CBigNum bn(w);
|
|
CAutoBN_CTX ctx;
|
|
return (BN_div(a, NULL, a, &bn, ctx) == 1) ? 0 : ((uint64)-1);
|
|
}
|
|
|
|
#endif
|