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