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