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