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