bignum.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. // ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #ifndef ECOIN_BIGNUM_H
  3. #define ECOIN_BIGNUM_H
  4. #include <stdexcept>
  5. #include <vector>
  6. #include <openssl/bn.h>
  7. #include "util.h" // for uint64
  8. /** Errors thrown by the bignum class */
  9. class bignum_error : public std::runtime_error
  10. {
  11. public:
  12. explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
  13. };
  14. /** RAII encapsulated BN_CTX (OpenSSL bignum context) */
  15. class CAutoBN_CTX
  16. {
  17. protected:
  18. BN_CTX* pctx;
  19. BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
  20. public:
  21. CAutoBN_CTX()
  22. {
  23. pctx = BN_CTX_new();
  24. if (pctx == NULL)
  25. throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
  26. }
  27. ~CAutoBN_CTX()
  28. {
  29. if (pctx != NULL)
  30. BN_CTX_free(pctx);
  31. }
  32. operator BN_CTX*() { return pctx; }
  33. BN_CTX& operator*() { return *pctx; }
  34. BN_CTX** operator&() { return &pctx; }
  35. bool operator!() { return (pctx == NULL); }
  36. };
  37. /** C++ wrapper for BIGNUM (OpenSSL bignum) */
  38. class CBigNum
  39. {
  40. protected:
  41. BIGNUM *bn;
  42. void init()
  43. {
  44. bn = BN_new();
  45. }
  46. public:
  47. CBigNum()
  48. {
  49. init();
  50. }
  51. CBigNum(const CBigNum& b)
  52. {
  53. init();
  54. if (!BN_copy(bn, &b))
  55. {
  56. BN_clear_free(bn);
  57. throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
  58. }
  59. }
  60. CBigNum& operator=(const CBigNum& b)
  61. {
  62. if (!BN_copy(bn, &b))
  63. throw bignum_error("CBigNum::operator= : BN_copy failed");
  64. return (*this);
  65. }
  66. ~CBigNum()
  67. {
  68. BN_clear_free(bn);
  69. }
  70. BIGNUM *operator &() const
  71. {
  72. return bn;
  73. }
  74. //CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'.
  75. CBigNum(signed char n) { init(); if (n >= 0) setulong(n); else setint64(n); }
  76. CBigNum(short n) { init(); if (n >= 0) setulong(n); else setint64(n); }
  77. CBigNum(int n) { init(); if (n >= 0) setulong(n); else setint64(n); }
  78. CBigNum(long n) { init(); if (n >= 0) setulong(n); else setint64(n); }
  79. CBigNum(int64 n) { init(); setint64(n); }
  80. CBigNum(unsigned char n) { init(); setulong(n); }
  81. CBigNum(unsigned short n) { init(); setulong(n); }
  82. CBigNum(unsigned int n) { init(); setulong(n); }
  83. CBigNum(unsigned long n) { init(); setulong(n); }
  84. CBigNum(uint64 n) { init(); setuint64(n); }
  85. explicit CBigNum(uint256 n) { init(); setuint256(n); }
  86. explicit CBigNum(const std::vector<unsigned char>& vch)
  87. {
  88. init();
  89. setvch(vch);
  90. }
  91. /** Generates a cryptographically secure random number between zero and range exclusive
  92. * i.e. 0 < returned number < range
  93. * @param range The upper bound on the number.
  94. * @return
  95. */
  96. static CBigNum randBignum(const CBigNum& range) {
  97. CBigNum ret;
  98. if(!BN_rand_range(&ret, &range)){
  99. throw bignum_error("CBigNum:rand element : BN_rand_range failed");
  100. }
  101. return ret;
  102. }
  103. /** Generates a cryptographically secure random k-bit number
  104. * @param k The bit length of the number.
  105. * @return
  106. */
  107. static CBigNum RandKBitBigum(const uint32_t k){
  108. CBigNum ret;
  109. if(!BN_rand(&ret, k, -1, 0)){
  110. throw bignum_error("CBigNum:rand element : BN_rand failed");
  111. }
  112. return ret;
  113. }
  114. /**Returns the size in bits of the underlying bignum.
  115. *
  116. * @return the size
  117. */
  118. int bitSize() const{
  119. return BN_num_bits(bn);
  120. }
  121. void setulong(unsigned long n)
  122. {
  123. if (!BN_set_word(bn, n))
  124. throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
  125. }
  126. unsigned long getulong() const
  127. {
  128. return BN_get_word(bn);
  129. }
  130. unsigned int getuint() const
  131. {
  132. return BN_get_word(bn);
  133. }
  134. int getint() const
  135. {
  136. unsigned long n = BN_get_word(bn);
  137. if (!BN_is_negative(bn))
  138. return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n);
  139. else
  140. return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
  141. }
  142. void setint64(int64_t sn)
  143. {
  144. unsigned char pch[sizeof(sn) + 6];
  145. unsigned char* p = pch + 4;
  146. bool fNegative;
  147. uint64_t n;
  148. if (sn < (int64_t)0)
  149. {
  150. // Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate
  151. n = -(sn + 1);
  152. ++n;
  153. fNegative = true;
  154. } else {
  155. n = sn;
  156. fNegative = false;
  157. }
  158. bool fLeadingZeroes = true;
  159. for (int i = 0; i < 8; i++)
  160. {
  161. unsigned char c = (n >> 56) & 0xff;
  162. n <<= 8;
  163. if (fLeadingZeroes)
  164. {
  165. if (c == 0)
  166. continue;
  167. if (c & 0x80)
  168. *p++ = (fNegative ? 0x80 : 0);
  169. else if (fNegative)
  170. c |= 0x80;
  171. fLeadingZeroes = false;
  172. }
  173. *p++ = c;
  174. }
  175. unsigned int nSize = p - (pch + 4);
  176. pch[0] = (nSize >> 24) & 0xff;
  177. pch[1] = (nSize >> 16) & 0xff;
  178. pch[2] = (nSize >> 8) & 0xff;
  179. pch[3] = (nSize) & 0xff;
  180. BN_mpi2bn(pch, p - pch, bn);
  181. }
  182. uint64 getuint64()
  183. {
  184. unsigned int nSize = BN_bn2mpi(bn, NULL);
  185. if (nSize < 4)
  186. return 0;
  187. std::vector<unsigned char> vch(nSize);
  188. BN_bn2mpi(bn, &vch[0]);
  189. if (vch.size() > 4)
  190. vch[4] &= 0x7f;
  191. uint64 n = 0;
  192. for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
  193. ((unsigned char*)&n)[i] = vch[j];
  194. return n;
  195. }
  196. void setuint64(uint64_t n)
  197. {
  198. unsigned char pch[sizeof(n) + 6];
  199. unsigned char* p = pch + 4;
  200. bool fLeadingZeroes = true;
  201. for (int i = 0; i < 8; i++)
  202. {
  203. unsigned char c = (n >> 56) & 0xff;
  204. n <<= 8;
  205. if (fLeadingZeroes)
  206. {
  207. if (c == 0)
  208. continue;
  209. if (c & 0x80)
  210. *p++ = 0;
  211. fLeadingZeroes = false;
  212. }
  213. *p++ = c;
  214. }
  215. unsigned int nSize = p - (pch + 4);
  216. pch[0] = (nSize >> 24) & 0xff;
  217. pch[1] = (nSize >> 16) & 0xff;
  218. pch[2] = (nSize >> 8) & 0xff;
  219. pch[3] = (nSize) & 0xff;
  220. BN_mpi2bn(pch, p - pch, bn);
  221. }
  222. void setuint256(uint256 n)
  223. {
  224. unsigned char pch[sizeof(n) + 6];
  225. unsigned char* p = pch + 4;
  226. bool fLeadingZeroes = true;
  227. unsigned char* pbegin = (unsigned char*)&n;
  228. unsigned char* psrc = pbegin + sizeof(n);
  229. while (psrc != pbegin)
  230. {
  231. unsigned char c = *(--psrc);
  232. if (fLeadingZeroes)
  233. {
  234. if (c == 0)
  235. continue;
  236. if (c & 0x80)
  237. *p++ = 0;
  238. fLeadingZeroes = false;
  239. }
  240. *p++ = c;
  241. }
  242. unsigned int nSize = p - (pch + 4);
  243. pch[0] = (nSize >> 24) & 0xff;
  244. pch[1] = (nSize >> 16) & 0xff;
  245. pch[2] = (nSize >> 8) & 0xff;
  246. pch[3] = (nSize >> 0) & 0xff;
  247. BN_mpi2bn(pch, p - pch, bn);
  248. }
  249. uint256 getuint256() const
  250. {
  251. unsigned int nSize = BN_bn2mpi(bn, NULL);
  252. if (nSize < 4)
  253. return 0;
  254. std::vector<unsigned char> vch(nSize);
  255. BN_bn2mpi(bn, &vch[0]);
  256. if (vch.size() > 4)
  257. vch[4] &= 0x7f;
  258. uint256 n = 0;
  259. for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
  260. ((unsigned char*)&n)[i] = vch[j];
  261. return n;
  262. }
  263. void setvch(const std::vector<unsigned char>& vch)
  264. {
  265. std::vector<unsigned char> vch2(vch.size() + 4);
  266. unsigned int nSize = vch.size();
  267. // BIGNUM's byte stream format expects 4 bytes of
  268. // big endian size data info at the front
  269. vch2[0] = (nSize >> 24) & 0xff;
  270. vch2[1] = (nSize >> 16) & 0xff;
  271. vch2[2] = (nSize >> 8) & 0xff;
  272. vch2[3] = (nSize >> 0) & 0xff;
  273. // swap data to big endian
  274. reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
  275. BN_mpi2bn(&vch2[0], vch2.size(), bn);
  276. }
  277. std::vector<unsigned char> getvch() const
  278. {
  279. unsigned int nSize = BN_bn2mpi(bn, NULL);
  280. if (nSize <= 4)
  281. return std::vector<unsigned char>();
  282. std::vector<unsigned char> vch(nSize);
  283. BN_bn2mpi(bn, &vch[0]);
  284. vch.erase(vch.begin(), vch.begin() + 4);
  285. reverse(vch.begin(), vch.end());
  286. return vch;
  287. }
  288. CBigNum& SetCompact(unsigned int nCompact)
  289. {
  290. unsigned int nSize = nCompact >> 24;
  291. /** std::vector<unsigned char> vch(4 + nSize);
  292. vch[3] = nSize;
  293. if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
  294. if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
  295. if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
  296. BN_mpi2bn(&vch[0], vch.size(), this);*/
  297. bool fNegative =(nCompact & 0x00800000) != 0;
  298. unsigned int nWord = nCompact & 0x007fffff;
  299. if (nSize <= 3)
  300. {
  301. nWord >>= 8*(3-nSize);
  302. BN_set_word(bn, nWord);
  303. }
  304. else
  305. {
  306. BN_set_word(bn, nWord);
  307. BN_lshift(bn, bn, 8*(nSize-3));
  308. }
  309. BN_set_negative(bn, fNegative);
  310. return *this;
  311. }
  312. unsigned int GetCompact() const
  313. {
  314. /** unsigned int nSize = BN_bn2mpi(this, NULL);
  315. std::vector<unsigned char> vch(nSize);
  316. nSize -= 4;
  317. BN_bn2mpi(this, &vch[0]);
  318. unsigned int nCompact = nSize << 24;
  319. if (nSize >= 1) nCompact |= (vch[4] << 16);
  320. if (nSize >= 2) nCompact |= (vch[5] << 8);
  321. if (nSize >= 3) nCompact |= (vch[6] << 0);*/
  322. unsigned int nSize = BN_num_bytes(bn);
  323. unsigned int nCompact = 0;
  324. if (nSize <= 3)
  325. nCompact = BN_get_word(bn) << 8*(3-nSize);
  326. else
  327. {
  328. CBigNum bn1;
  329. BN_rshift(&bn1, bn, 8*(nSize-3));
  330. nCompact = BN_get_word(&bn1);
  331. }
  332. // The 0x00800000 bit denotes the sign.
  333. // Thus, if it is already set, divide the mantissa by 256 and increase the exponent.
  334. if (nCompact & 0x00800000)
  335. {
  336. nCompact >>= 8;
  337. nSize++;
  338. }
  339. nCompact |= nSize << 24;
  340. nCompact |= (BN_is_negative(bn) ? 0x00800000 : 0);
  341. return nCompact;
  342. }
  343. void SetHex(const std::string& str)
  344. {
  345. // skip 0x
  346. const char* psz = str.c_str();
  347. while (isspace(*psz))
  348. psz++;
  349. bool fNegative = false;
  350. if (*psz == '-')
  351. {
  352. fNegative = true;
  353. psz++;
  354. }
  355. if (psz[0] == '0' && tolower(psz[1]) == 'x')
  356. psz += 2;
  357. while (isspace(*psz))
  358. psz++;
  359. // hex string to bignum
  360. static const signed 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 };
  361. *this = 0;
  362. while (isxdigit(*psz))
  363. {
  364. *this <<= 4;
  365. int n = phexdigit[(unsigned char)*psz++];
  366. *this += n;
  367. }
  368. if (fNegative)
  369. *this = 0 - *this;
  370. }
  371. bool SetHexBool(const std::string& str)
  372. {
  373. // skip 0x
  374. const char* psz = str.c_str();
  375. while (isspace(*psz))
  376. psz++;
  377. bool fNegative = false;
  378. if (*psz == '-')
  379. {
  380. fNegative = true;
  381. psz++;
  382. }
  383. if (psz[0] == '0' && tolower(psz[1]) == 'x')
  384. psz += 2;
  385. while (isspace(*psz))
  386. psz++;
  387. // hex string to bignum
  388. static const signed 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 };
  389. *this = 0;
  390. while (isxdigit(*psz))
  391. {
  392. *this <<= 4;
  393. int n = phexdigit[(unsigned char)*psz++];
  394. *this += n;
  395. }
  396. if (fNegative)
  397. *this = 0 - *this;
  398. return true;
  399. }
  400. std::string ToString(int nBase=10) const
  401. {
  402. CAutoBN_CTX pctx;
  403. CBigNum bnBase = nBase;
  404. CBigNum bn0 = 0;
  405. std::string str;
  406. CBigNum bn1 = *this;
  407. BN_set_negative(&bn1, false);
  408. CBigNum dv;
  409. CBigNum rem;
  410. if (BN_cmp(&bn1, &bn0) == 0)
  411. return "0";
  412. while (BN_cmp(&bn1, &bn0) > 0)
  413. {
  414. if (!BN_div(&dv, &rem, &bn1, &bnBase, pctx))
  415. throw bignum_error("CBigNum::ToString() : BN_div failed");
  416. bn1 = dv;
  417. unsigned int c = rem.getulong();
  418. str += "0123456789abcdef"[c];
  419. }
  420. if (BN_is_negative(bn))
  421. str += "-";
  422. reverse(str.begin(), str.end());
  423. return str;
  424. }
  425. std::string GetHex() const
  426. {
  427. return ToString(16);
  428. }
  429. unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const
  430. {
  431. return ::GetSerializeSize(getvch(), nType, nVersion);
  432. }
  433. template<typename Stream>
  434. void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const
  435. {
  436. ::Serialize(s, getvch(), nType, nVersion);
  437. }
  438. template<typename Stream>
  439. void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION)
  440. {
  441. std::vector<unsigned char> vch;
  442. ::Unserialize(s, vch, nType, nVersion);
  443. setvch(vch);
  444. }
  445. /**
  446. * exponentiation with an int. this^e
  447. * @param e the exponent as an int
  448. * @return
  449. */
  450. CBigNum pow(const int e) const {
  451. return this->pow(CBigNum(e));
  452. }
  453. /**
  454. * exponentiation this^e
  455. * @param e the exponent
  456. * @return
  457. */
  458. CBigNum pow(const CBigNum& e) const {
  459. CAutoBN_CTX pctx;
  460. CBigNum ret;
  461. if (!BN_exp(&ret, bn, &e, pctx))
  462. throw bignum_error("CBigNum::pow : BN_exp failed");
  463. return ret;
  464. }
  465. /**
  466. * modular multiplication: (this * b) mod m
  467. * @param b operand
  468. * @param m modulus
  469. */
  470. CBigNum mul_mod(const CBigNum& b, const CBigNum& m) const {
  471. CAutoBN_CTX pctx;
  472. CBigNum ret;
  473. if (!BN_mod_mul(&ret, bn, &b, &m, pctx))
  474. throw bignum_error("CBigNum::mul_mod : BN_mod_mul failed");
  475. return ret;
  476. }
  477. /**
  478. * modular exponentiation: this^e mod n
  479. * @param e exponent
  480. * @param m modulus
  481. */
  482. CBigNum pow_mod(const CBigNum& e, const CBigNum& m) const {
  483. CAutoBN_CTX pctx;
  484. CBigNum ret;
  485. if( e < 0){
  486. // g^-x = (g^-1)^x
  487. CBigNum inv = this->inverse(m);
  488. CBigNum posE = e * -1;
  489. if (!BN_mod_exp(&ret, &inv, &posE, &m, pctx))
  490. throw bignum_error("CBigNum::pow_mod: BN_mod_exp failed on negative exponent");
  491. }else
  492. if (!BN_mod_exp(&ret, bn, &e, &m, pctx))
  493. throw bignum_error("CBigNum::pow_mod : BN_mod_exp failed");
  494. return ret;
  495. }
  496. /**
  497. * Calculates the inverse of this element mod m.
  498. * i.e. i such this*i = 1 mod m
  499. * @param m the modu
  500. * @return the inverse
  501. */
  502. CBigNum inverse(const CBigNum& m) const {
  503. CAutoBN_CTX pctx;
  504. CBigNum ret;
  505. if (!BN_mod_inverse(&ret, bn, &m, pctx))
  506. throw bignum_error("CBigNum::inverse*= :BN_mod_inverse");
  507. return ret;
  508. }
  509. /**
  510. * Generates a random (safe) prime of numBits bits
  511. * @param numBits the number of bits
  512. * @param safe true for a safe prime
  513. * @return the prime
  514. */
  515. static CBigNum generatePrime(const unsigned int numBits, bool safe = false) {
  516. CBigNum ret;
  517. if(!BN_generate_prime_ex(&ret, numBits, (safe == true), NULL, NULL, NULL))
  518. throw bignum_error("CBigNum::generatePrime*= :BN_generate_prime_ex");
  519. return ret;
  520. }
  521. /**
  522. * Calculates the greatest common divisor (GCD) of two numbers.
  523. * @param m the second element
  524. * @return the GCD
  525. */
  526. CBigNum gcd( const CBigNum& b) const{
  527. CAutoBN_CTX pctx;
  528. CBigNum ret;
  529. if (!BN_gcd(&ret, bn, &b, pctx))
  530. throw bignum_error("CBigNum::gcd*= :BN_gcd");
  531. return ret;
  532. }
  533. /**
  534. * Miller-Rabin primality test on this element
  535. * @param checks: optional, the number of Miller-Rabin tests to run
  536. * default causes error rate of 2^-80.
  537. * @return true if prime
  538. */
  539. bool isPrime(const int checks=BN_prime_checks) const {
  540. CAutoBN_CTX pctx;
  541. int ret = BN_is_prime_ex(bn, checks, pctx, NULL);
  542. if(ret < 0){
  543. throw bignum_error("CBigNum::isPrime :BN_is_prime");
  544. }
  545. return ret;
  546. }
  547. bool isOne() const {
  548. return BN_is_one(bn);
  549. }
  550. bool operator!() const
  551. {
  552. return BN_is_zero(bn);
  553. }
  554. CBigNum& operator+=(const CBigNum& b)
  555. {
  556. if (!BN_add(bn, bn, &b))
  557. throw bignum_error("CBigNum::operator+= : BN_add failed");
  558. return *this;
  559. }
  560. CBigNum& operator-=(const CBigNum& b)
  561. {
  562. *this = *this - b;
  563. return *this;
  564. }
  565. CBigNum& operator*=(const CBigNum& b)
  566. {
  567. CAutoBN_CTX pctx;
  568. if (!BN_mul(bn, bn, &b, pctx))
  569. throw bignum_error("CBigNum::operator*= : BN_mul failed");
  570. return *this;
  571. }
  572. CBigNum& operator/=(const CBigNum& b)
  573. {
  574. *this = *this / b;
  575. return *this;
  576. }
  577. CBigNum& operator%=(const CBigNum& b)
  578. {
  579. *this = *this % b;
  580. return *this;
  581. }
  582. CBigNum& operator<<=(unsigned int shift)
  583. {
  584. if (!BN_lshift(bn, bn, shift))
  585. throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
  586. return *this;
  587. }
  588. CBigNum& operator>>=(unsigned int shift)
  589. {
  590. // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
  591. // if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL
  592. CBigNum a = 1;
  593. a <<= shift;
  594. if (BN_cmp(&a, bn) > 0)
  595. {
  596. *this = 0;
  597. return *this;
  598. }
  599. if (!BN_rshift(bn, bn, shift))
  600. throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
  601. return *this;
  602. }
  603. CBigNum& operator++()
  604. {
  605. // prefix operator
  606. if (!BN_add(bn, bn, BN_value_one()))
  607. throw bignum_error("CBigNum::operator++ : BN_add failed");
  608. return *this;
  609. }
  610. const CBigNum operator++(int)
  611. {
  612. // postfix operator
  613. const CBigNum ret = *this;
  614. ++(*this);
  615. return ret;
  616. }
  617. CBigNum& operator--()
  618. {
  619. // prefix operator
  620. CBigNum r;
  621. if (!BN_sub(&r, bn, BN_value_one()))
  622. throw bignum_error("CBigNum::operator-- : BN_sub failed");
  623. *this = r;
  624. return *this;
  625. }
  626. const CBigNum operator--(int)
  627. {
  628. // postfix operator
  629. const CBigNum ret = *this;
  630. --(*this);
  631. return ret;
  632. }
  633. friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
  634. friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
  635. friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
  636. friend inline const CBigNum operator*(const CBigNum& a, const CBigNum& b);
  637. friend inline bool operator<(const CBigNum& a, const CBigNum& b);
  638. };
  639. inline const CBigNum operator+(const CBigNum& a, const CBigNum& b)
  640. {
  641. CBigNum r;
  642. if (!BN_add(&r, &a, &b))
  643. throw bignum_error("CBigNum::operator+ : BN_add failed");
  644. return r;
  645. }
  646. inline const CBigNum operator-(const CBigNum& a, const CBigNum& b)
  647. {
  648. CBigNum r;
  649. if (!BN_sub(&r, &a, &b))
  650. throw bignum_error("CBigNum::operator- : BN_sub failed");
  651. return r;
  652. }
  653. inline const CBigNum operator-(const CBigNum& a)
  654. {
  655. CBigNum r(a);
  656. BN_set_negative(&r, !BN_is_negative(&r));
  657. return r;
  658. }
  659. inline const CBigNum operator*(const CBigNum& a, const CBigNum& b)
  660. {
  661. CAutoBN_CTX pctx;
  662. CBigNum r;
  663. if (!BN_mul(&r, &a, &b, pctx))
  664. throw bignum_error("CBigNum::operator* : BN_mul failed");
  665. return r;
  666. }
  667. inline const CBigNum operator/(const CBigNum& a, const CBigNum& b)
  668. {
  669. CAutoBN_CTX pctx;
  670. CBigNum r;
  671. if (!BN_div(&r, NULL, &a, &b, pctx))
  672. throw bignum_error("CBigNum::operator/ : BN_div failed");
  673. return r;
  674. }
  675. inline const CBigNum operator%(const CBigNum& a, const CBigNum& b)
  676. {
  677. CAutoBN_CTX pctx;
  678. CBigNum r;
  679. if (!BN_nnmod(&r, &a, &b, pctx))
  680. throw bignum_error("CBigNum::operator% : BN_div failed");
  681. return r;
  682. }
  683. inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
  684. {
  685. CBigNum r;
  686. if (!BN_lshift(&r, &a, shift))
  687. throw bignum_error("CBigNum:operator<< : BN_lshift failed");
  688. return r;
  689. }
  690. inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
  691. {
  692. CBigNum r = a;
  693. r >>= shift;
  694. return r;
  695. }
  696. inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); }
  697. inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); }
  698. inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); }
  699. inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); }
  700. inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); }
  701. inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); }
  702. inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { return strm << b.ToString(10); }
  703. //typedef CBigNum Bignum;
  704. #endif