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