1 /**
2 * BigInt
3 * 
4 * Copyright:
5 * (C) 1999-2008,2012 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *    2007 FlexSecure
8 *
9 * License:
10 * Botan is released under the Simplified BSD License (see LICENSE.md)
11 */
12 module botan.math.bigint.bigint;
13 
14 import botan.constants;
15 public import botan.math.mp.mp_types;
16 public import botan.utils.types;
17 import botan.constants;
18 import botan.rng.rng;
19 import memutils.vector;
20 import botan.utils.charset;
21 import botan.codec.hex;
22 import botan.math.bigint.divide;
23 import botan.math.mp.mp_core;
24 import botan.utils.get_byte;
25 import botan.utils.parsing;
26 import botan.utils.rounding;
27 import botan.utils.parsing;
28 import botan.utils.bit_ops;
29 import std.algorithm;
30 import std.traits : isNumeric;
31 
32 /**
33 * Arbitrary precision integer
34 */
35 struct BigInt
36 {
37 public:
38     /*
39     * Write the BigInt into a vector
40     */
41     Vector!char toVector(Base base = Decimal) const
42     {
43         Vector!ubyte buffer = BigInt.encode(this, base);
44         Vector!char ret;
45         size_t skip = 0;
46         while(skip < buffer.length && buffer[skip] == '0')
47             ++skip;
48         ret[] = cast(char[])(buffer.ptr + skip)[0 .. buffer.length - skip];
49         return ret.move();
50     }
51 
52     /*
53     * Write the BigInt into a string
54     */
55     string toString(Base base = Decimal) const
56     {
57         auto vec = toVector(base);
58         //logTrace("toString: ", vec[]);
59         return (vec[]).idup;
60     }
61     alias Base = int;
62     /**
63     * Base enumerator for encoding and decoding
64     */
65     enum : Base { Decimal = 10, Hexadecimal = 16, Binary = 256 }
66 
67     alias Sign = bool;
68     /**
69     * Sign symbol definitions for positive and negative numbers
70     */
71     enum : Sign { Negative = 0, Positive = 1 }
72 
73     /**
74     * DivideByZero Exception
75     */
76     class DivideByZero : Exception
77     { 
78         this() {
79             super("BigInt divide by zero");
80         }
81     }
82 
83     /**
84     * Create BigInt from any integer
85     * Params:
86     *  n = initial value of this BigInt
87     */
88     this(T)(T n)
89         if (isNumeric!T)
90     {
91         import std.algorithm : max;
92         if (n == 0)
93             return;
94         const size_t limbs_needed = std.algorithm.max(1, T.sizeof / word.sizeof);
95         m_reg.resize(4*limbs_needed);
96         foreach (size_t i; 0 .. limbs_needed)
97             m_reg[i] = ((n >> (i*MP_WORD_BITS)) & MP_WORD_MASK);
98     }
99 
100     @disable this(this);
101 
102     /// Move constructor
103     ref BigInt opAssign(size_t other)
104     {
105         BigInt bigInt = BigInt(other);
106         this.swap(bigInt);
107         
108         return this;
109     }
110 
111 	/// Copy constructor
112 	void load()(auto ref BigInt other) {
113 		m_reg[] = other.m_reg[];
114 		m_signedness = other.m_signedness;
115 		m_sig_words = other.m_sig_words;
116 	}
117 
118     /**
119     * Create BigInt from a string. If the string starts with 0x the
120     * rest of the string will be interpreted as hexadecimal digits.
121     * Otherwise, it will be interpreted as a decimal number.
122     *
123     * Params:
124     *  str = the string to parse for an integer value
125     */
126     this(in string str)
127     {
128         Base base = Decimal;
129         size_t markers = 0;
130         bool negative = false;
131         
132         if (str.length > 0 && str[0] == '-')
133         {
134             markers += 1;
135             negative = true;
136         }
137         
138         if (str.length > markers + 2 && str[markers     ] == '0' &&
139         str[markers + 1] == 'x')
140         {
141             markers += 2;
142             base = Hexadecimal;
143         }
144         auto contents = decode(cast(const(ubyte)*)(str.ptr) + markers, str.length - markers, base);
145         this.swap( contents );
146 
147         if (negative) setSign(Negative);
148         else          setSign(Positive);
149     }
150 
151     /**
152     * Create a BigInt from an integer in a ubyte array
153     * Params:
154     *  input = the ubyte array holding the value
155     *  length = size of buf
156     *  base = is the number base of the integer in buf
157     */
158     this(const(ubyte)* input, size_t length, Base base = Binary)
159     {
160         auto contents = decode(input, length, base);
161         this.swap( contents );
162     }
163 
164     /**
165     * Create a random BigInt of the specified size
166     * Params:
167     *  rng = random number generator
168     *  bits = size in bits
169     *  set_high_bit = if true, the highest bit is always set
170     */
171     this(RandomNumberGenerator rng, size_t bits, bool set_high_bit = true)
172     {
173         randomize(rng, bits, set_high_bit);
174     }
175     /**
176     * Create BigInt of specified size, all zeros
177     * Params:
178     *  s = the sign
179     *  size = of the internal register in words
180     */
181     this(Sign s, size_t size)
182     {
183         m_reg.resize(roundUp!size_t(size, 8));
184         m_signedness = s;
185     }
186 
187     /**
188     * Move constructor
189     */
190     this()(auto ref BigInt other)
191     {
192         this.swap(other);
193     }    
194 
195     this(ALLOC)(auto const ref Vector!(ubyte, ALLOC) payload, in Sign sign, in size_t sig_words = size_t.max) {
196         this(payload.ptr, payload.length, sig_words);
197     }
198 
199     this(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) payload, in Sign sign, in size_t sig_words = size_t.max) {
200         this(payload.ptr, payload.length, sig_words);
201     }
202 
203     this()(auto ref SecureVector!word reg, Sign sign, in size_t sig_words = size_t.max) {
204         import std.algorithm : swap;
205         m_reg.swap(reg);
206         swap(m_signedness, sign);
207         m_sig_words = sig_words;	
208     }
209 
210 	void reserve(size_t n) {
211 		m_reg.reserve(n);
212 	}
213 
214     /**
215     * Move assignment
216     */
217     void opAssign()(auto ref BigInt other)
218     {
219 		this.swap(other);
220     }
221 
222     /**
223     * Copy assignment
224     */
225     // BigInt operator=(const ref BigInt) = default;
226 
227     /**
228     * Swap this value with another
229     * Params:
230     *  other = BigInt to swap values with
231     */
232     void swap()(auto ref BigInt other)
233     {
234 		m_reg.swap(other.m_reg);
235 
236         .swap(m_signedness, other.m_signedness);
237         .swap(m_sig_words, other.m_sig_words);
238     }
239 
240     void swapReg(ref SecureVector!word reg)
241     {
242         m_reg.swap(reg);
243         m_sig_words = size_t.max;
244     }
245 
246     /**
247     * += operator
248     * Params:
249     *  y = the BigInt to add to this
250     */
251     void opOpAssign(string op)(auto const ref BigInt y)
252         if (op == "+")
253     {
254         const size_t x_sw = sigWords(), y_sw = y.sigWords();
255         
256         const size_t reg_size = std.algorithm.max(x_sw, y_sw) + 1;
257         growTo(reg_size);
258         
259         if (sign() == y.sign())
260             bigint_add2(mutablePtr(), reg_size - 1, y.ptr, y_sw);
261         else
262         {
263             int relative_size = bigint_cmp(mutablePtr(), x_sw, y.ptr, y_sw);
264             
265             if (relative_size < 0)
266 			{               
267 				SecureVector!word z = SecureVector!word(reg_size - 1);
268 				bigint_sub3(z.ptr, y.ptr, reg_size - 1, mutablePtr(), x_sw);
269 				m_reg[] = z;
270 				m_sig_words = z.length;
271                 setSign(y.sign());
272             }
273             else if (relative_size == 0)
274             {
275                 zeroise(m_reg);
276 		        setSign(Positive);
277             }
278             else if (relative_size > 0) 
279                 bigint_sub2(mutablePtr(), x_sw, y.ptr, y_sw);
280         }
281         
282     }
283 
284     void opOpAssign(string op)(in word y)
285         if (op == "+")
286     {
287         this += BigInt(y);
288     }
289 
290     /**
291     * -= operator
292     * Params:
293     *  y = the BigInt to subtract from this
294     */
295     void opOpAssign(string op)(auto const ref BigInt y)
296         if (op == "-")
297     {
298         const size_t x_sw = sigWords(), y_sw = y.sigWords();
299         
300         int relative_size = bigint_cmp(mutablePtr(), x_sw, y.ptr, y_sw);
301         
302         const size_t reg_size = std.algorithm.max(x_sw, y_sw) + 1;
303         growTo(reg_size);
304         
305         if (relative_size < 0)
306         {
307             if (sign() == y.sign())
308                 bigint_sub2_rev(mutablePtr(), y.ptr, y_sw);
309             else
310                 bigint_add2(mutablePtr(), reg_size - 1, y.ptr, y_sw);
311             
312             setSign(y.reverseSign());
313         }
314         else if (relative_size == 0)
315         {
316             if (sign() == y.sign())
317             {
318                 clear();
319                 setSign(Positive);
320             }
321             else
322                 bigint_shl1(mutablePtr(), x_sw, 0, 1);
323         }
324         else if (relative_size > 0)
325         {
326             if (sign() == y.sign())
327                 bigint_sub2(mutablePtr(), x_sw, y.ptr, y_sw);
328             else
329                 bigint_add2(mutablePtr(), reg_size - 1, y.ptr, y_sw);
330         }
331     }
332 
333 
334     void opOpAssign(string op)(in word y)
335         if (op == "-")
336     {
337         this -= BigInt(y);
338     }
339 
340 
341     /**
342     * *= operator
343     * Params:
344     *  y = the BigInt to multiply with this
345     */
346     void opOpAssign(string op)(const ref BigInt y)
347         if (op == "*")
348     {
349         const size_t x_sw = sigWords(), y_sw = y.sigWords();
350         setSign((sign() == y.sign()) ? Positive : Negative);
351         
352         if (x_sw == 0 || y_sw == 0)
353         {
354             clear();
355             setSign(Positive);
356         }
357         else if (x_sw == 1 && y_sw)
358         {
359             growTo(y_sw + 2);
360             bigint_linmul3(mutablePtr(), y.ptr, y_sw, wordAt(0));
361         }
362         else if (y_sw == 1 && x_sw)
363         {
364             growTo(x_sw + 2);
365             bigint_linmul2(mutablePtr(), x_sw, y.wordAt(0));
366         }
367         else
368         {
369             growTo(size() + y.length);
370             
371             SecureVector!word z = SecureVector!word(mutablePtr()[0 .. x_sw]);
372             SecureVector!word workspace = SecureVector!word(size());
373             
374             bigint_mul(mutablePtr(), size(), workspace.ptr, z.ptr, z.length, x_sw, y.ptr, y.length, y_sw);
375         }
376     }
377 
378 
379     void opOpAssign(string op)(in word y)
380         if (op == "*")
381     {
382         const BigInt b_y = BigInt(y);
383         this *= b_y;
384     }
385 
386     /**
387     * /= operator
388     * Params:
389     *   y = the BigInt to divide this by
390     */
391     void opOpAssign(string op)(auto const ref BigInt y)
392         if (op == "/")
393     {
394         if (y.sigWords() == 1 && isPowerOf2(y.wordAt(0)))
395             this >>= (y.bits() - 1);
396         else
397             this = this / y;
398     }
399 
400 
401     void opOpAssign(string op)(in word y)
402         if (op == "/")
403     {
404         this /= BigInt(y);
405     }
406 
407 
408     /**
409     * Modulo operator
410     * Params:
411     *  mod = the modulus to reduce this by
412     */
413     void opOpAssign(string op)(auto const ref BigInt mod)
414         if (op == "%")
415     {
416         this = this % mod;
417     }
418 
419     /**
420     * Modulo operator
421     * Params:
422     *  mod = the modulus (word) to reduce this by
423     */
424     void opOpAssign(string op)(word mod)
425         if (op == "%")
426     {
427         if (mod == 0)
428             throw new DivideByZero();
429         if (isPowerOf2(mod))
430         {
431             word result = (wordAt(0) & (mod - 1));
432             clear();
433             growTo(2);
434             m_reg[0] = result;
435 			m_sig_words = size_t.max;
436             return;
437         }
438         
439         word remainder = 0;
440         
441         for (size_t j = sigWords(); j > 0; --j)
442             remainder = bigint_modop(remainder, wordAt(j-1), mod);
443         clear();
444         growTo(2);
445         
446         if (remainder && sign() == Negative)
447             m_reg[0] = mod - remainder;
448         else
449             m_reg[0] = remainder;
450 		m_sig_words = size_t.max;
451         
452         setSign(Positive);
453     }
454 
455 
456     /**
457     * Left shift operator
458     * Params:
459     *  shift = the number of bits to shift this left by
460     */
461     void opOpAssign(string op)(size_t shift)
462         if (op == "<<")
463     {
464         if (shift)
465         {
466             const size_t shift_words = shift / MP_WORD_BITS;
467             const size_t shift_bits  = shift % MP_WORD_BITS;
468             const size_t words = sigWords();
469             
470             growTo(words + shift_words + (shift_bits ? 1 : 0));
471             bigint_shl1(mutablePtr(), words, shift_words, shift_bits);
472         }
473         
474     }
475 
476     /**
477     * Right shift operator
478     * Params:
479     *  shift = the number of bits to shift this right by
480     */
481     void opOpAssign(string op)(size_t shift)
482         if (op == ">>")
483     {
484         if (shift)
485         {
486             const size_t shift_words = shift / MP_WORD_BITS;
487             const size_t shift_bits  = shift % MP_WORD_BITS;
488             
489             bigint_shr1(mutablePtr(), sigWords(), shift_words, shift_bits);
490             m_sig_words = size_t.max;
491             if (isZero())
492                 setSign(Positive);
493         }
494     }
495 
496     /**
497     * Increment operator
498     */
499     ref BigInt opUnary(string op)() if (op == "++") { this += BigInt(1); return this; }
500 
501     /**
502     * Decrement operator
503     */
504     ref BigInt opUnary(string op)() if (op == "--") { this -= BigInt(1); return this; }
505 
506     /**
507     * Unary negation operator
508     * Returns: negative this
509     */
510     BigInt opUnary(string op)() const
511         if (op == "-")
512     {
513         BigInt ret = this.dup;
514         ret.flipSign();
515         return ret;
516     }
517 
518     /**
519     * bool cast
520     * Returns: true iff this is not zero, otherwise false
521     */
522     T opCast(T : bool)() const { return isNonzero(); }
523 
524     T opCast(T : BigInt)() const { return *cast(BigInt*)&this; }
525 
526     /**
527     * Zeroize the BigInt. The size of the underlying register is not
528     * modified.
529     */
530     void clear() 
531     { 
532         import core.stdc.string : memset;
533         if (!m_reg.empty){
534             memset(mutablePtr(), 0, word.sizeof*m_reg.length);
535 			m_sig_words = 0;
536         }
537     }
538 
539     /**
540     * Compare this to another BigInt
541     * Params:
542     *  other = the BigInt value to compare with
543     *  check_signs = include sign in comparison?
544     * Returns: if (this<n) return -1, if (this>n) return 1, if both
545     * values are identical return 0 [like Perl's <=> operator]
546     */
547     int cmp(const ref BigInt other, bool check_signs = true) const
548     {
549         if (check_signs)
550         {
551             if (other.isPositive() && this.isNegative())
552                 return -1;
553             
554             if (other.isNegative() && this.isPositive())
555                 return 1;
556             
557             if (other.isNegative() && this.isNegative())
558                 return (-bigint_cmp(m_reg.ptr, this.sigWords(), other.ptr, other.sigWords()));
559         }
560         
561         return bigint_cmp(m_reg.ptr, this.sigWords(), other.ptr, other.sigWords());
562     }
563     /*
564     * Comparison Operators
565     */
566     bool opEquals()(auto const ref BigInt b) const
567     { return (cmp(b) == 0); }
568 
569     bool opEquals(in size_t n) const
570     { 
571         BigInt b = n;
572         return (cmp(b) == 0); 
573     }
574 
575 
576     int opCmp()(auto const ref BigInt b) const
577     { 
578         return cmp(b);
579     }
580 
581     int opCmp(in size_t n) const
582     { 
583         BigInt b = n; 
584         return cmp(b); 
585     }
586 
587     /**
588     * Test if the integer has an even value
589     * Returns: true if the integer is even, false otherwise
590     */
591     bool isEven() const { return (getBit(0) == 0); }
592 
593     /**
594     * Test if the integer has an odd value
595     * Returns: true if the integer is odd, false otherwise
596     */
597     bool isOdd()  const { return (getBit(0) == 1); }
598 
599     /**
600     * Test if the integer is not zero
601     * Returns: true if the integer is non-zero, false otherwise
602     */
603     bool isNonzero() const { return (!isZero()); }
604 
605     /**
606     * Test if the integer is zero
607     * Returns: true if the integer is zero, false otherwise
608     */
609     bool isZero() const
610     {
611 		return sigWords() == 0;
612     }
613 
614     /**
615     * Set bit at specified position
616     * Params:
617     *  n = bit position to set
618     */
619     void setBit(size_t n)
620     {
621         const size_t which = n / MP_WORD_BITS;
622         const word mask = cast(word)(1) << (n % MP_WORD_BITS);
623         if (which >= size()) growTo(which + 1);
624         m_reg[which] |= mask;
625         if (which >= sigWords() - 1)
626 			m_sig_words = size_t.max;
627     }
628 
629     /**
630     * Clear bit at specified position
631     * Params:
632     *  n = bit position to clear
633     */
634     void clearBit(size_t n)
635     {
636         const size_t which = n / MP_WORD_BITS;
637         const word mask = cast(word)(1) << (n % MP_WORD_BITS);
638         if (which < size())
639             m_reg[which] &= ~mask;
640         m_sig_words = size_t.max;
641     }
642 
643     /**
644     * Clear all but the lowest n bits
645     * Params:
646     *  n = amount of bits to keep
647     */
648     void maskBits(size_t n)
649     {
650         if (n == 0) { clear(); return; }
651         if (n >= bits()) return;
652 
653         const size_t top_word = n / MP_WORD_BITS;
654         const word mask = ((cast(word)1) << (n % MP_WORD_BITS)) - 1;
655         
656         if (top_word < size())
657             clearMem(&m_reg[top_word+1], size() - (top_word + 1));
658         
659         m_reg[top_word] &= mask;
660 		m_sig_words = top_word;
661     }
662 
663     /**
664     * Return bit value at specified position
665     * Params:
666     *  n = the bit offset to test
667     * Returns: true, if the bit at position n is set, false otherwise
668     */
669     bool getBit(size_t n) const
670     {
671         return ((wordAt(n / MP_WORD_BITS) >> (n % MP_WORD_BITS)) & 1);
672     }
673 
674     /**
675     * Return (a maximum of) 32 bits of the complete value
676     * Params:
677     *  offset = the offset to start extracting
678     *  length = amount of bits to extract (starting at offset)
679     * Returns: the integer extracted from the register starting at
680     * offset with specified length
681     */
682     uint getSubstring(size_t offset, size_t length) const
683     {
684         if (length > 32)
685             throw new InvalidArgument("BigInt.getSubstring: Substring size too big");
686         
687         ulong piece = 0;
688         foreach (size_t i; 0 .. 8)
689         {
690             const ubyte part = byteAt((offset / 8) + (7-i));
691             piece = (piece << 8) | part;
692         }
693         
694         const ulong mask = (cast(ulong)(1) << length) - 1;
695         const size_t shift = (offset % 8);
696         
697         return cast(uint)((piece >> shift) & mask);
698     }
699 
700     /**
701     * Convert this value into a uint, if it is in the range
702     * [0 ... 2**32-1], or otherwise throw new an exception.
703     * Returns: the value as a uint if conversion is possible
704     */
705     uint toUint() const
706     {
707         if (isNegative())
708             throw new EncodingError("BigInt.to_uint: Number is negative");
709         if (bits() >= 32)
710             throw new EncodingError("BigInt.to_uint: Number is too big to convert");
711         
712         uint output = 0;
713         for (uint j = 0; j != 4; ++j)
714             output = (output << 8) | byteAt(3-j);
715         return output;
716     }
717 
718     /**
719     * Params:
720     *  n = the offset to get a ubyte from
721     * Returns: ubyte at offset n
722     */
723     ubyte byteAt(size_t n) const
724     {
725         const size_t WORD_BYTES = (word).sizeof;
726         size_t word_num = n / WORD_BYTES;
727         size_t byte_num = n % WORD_BYTES;
728         if (word_num >= size())
729             return 0;
730         else
731             return get_byte(WORD_BYTES - byte_num - 1, m_reg[word_num]);
732     }
733 
734     /**
735     * Return the word at a specified position of the internal register
736     * Params:
737     *  n = position in the register
738     * Returns: value at position n
739     */
740 	pragma(inline, true)
741     word wordAt(size_t n) const
742     { return ((n < size()) ? m_reg[n] : 0); }
743 
744     /**
745     * Tests if the sign of the integer is negative
746     * Returns: true, iff the integer has a negative sign
747     */
748     bool isNegative() const { return (sign() == Negative); }
749 
750     /**
751     * Tests if the sign of the integer is positive
752     * Returns: true, iff the integer has a positive sign
753     */
754     bool isPositive() const { return (sign() == Positive); }
755 
756     /**
757     * Return the sign of the integer
758     * Returns: the sign of the integer
759     */
760 	pragma(inline, true)
761     Sign sign() const { return (m_signedness); }
762 
763     /**
764     * Returns: the opposite sign of the represented integer value
765     */
766     Sign reverseSign() const
767     {
768         if (sign() == Positive)
769             return Negative;
770         return Positive;
771     }
772 
773     /**
774     * Flip the sign of this BigInt
775     */
776     void flipSign()
777     {
778         setSign(reverseSign());
779     }
780 
781     /**
782     * Set sign of the integer
783     * Params:
784     *  s = new Sign to set
785     */
786     void setSign(Sign s)
787     {
788         if (isZero())
789             m_signedness = Positive;
790         else
791             m_signedness = s;
792     }
793 
794     /**
795     * Returns: absolute (positive) value of this
796     */
797     BigInt abs() const
798     {
799         BigInt ret = this.dup;
800         ret.setSign(Positive);
801         return ret;
802     }
803 
804     /**
805     * Give size of internal register
806     * Returns: size of internal register in words
807     */
808 	pragma(inline, true)
809     size_t size() const { return m_reg.length; }
810 
811     // ditto
812 	pragma(inline, true)
813     size_t length() const { return size(); }
814 
815     /**
816     * Return how many words we need to hold this value
817     * Returns: significant words of the represented integer value
818     */
819     size_t sigWords() const
820     {
821         if (m_sig_words != size_t.max) return m_sig_words;
822         const word* x = m_reg.ptr;
823         size_t sig = min(m_max_sig_words, m_reg.length);
824 
825         while (sig && (x[sig-1] == 0))
826             sig--;
827         (cast()this).m_sig_words = sig;
828         return sig;
829     }
830 
831     /**
832     * Give ubyte length of the integer
833     * Returns: ubyte length of the represented integer value
834     */
835 	pragma(inline, true)
836     size_t bytes() const
837     {
838         return (bits() + 7) / 8;
839     }
840 
841     /**
842     * Get the bit length of the integer
843     * Returns: bit length of the represented integer value
844     */
845     size_t bits() const
846     {
847         const size_t words = sigWords();
848         if (words == 0)
849             return 0;
850         
851         const size_t full_words = words - 1;
852         return (full_words * MP_WORD_BITS + highBit(wordAt(full_words)));
853     }
854 
855     /**
856     * Return a mutable pointer to the register
857     * Returns: a pointer to the start of the internal register
858     */
859     word* mutablePtr() { m_sig_words = size_t.max; return m_reg.ptr; }
860 
861     /**
862     * Return a const pointer to the register
863     * Returns: a pointer to the start of the internal register
864     */
865     @property const(word*) ptr() const { return m_reg.ptr; }
866 
867     /**
868     * Increase internal register buffer to at least n words
869     * Params:
870     *  n = new size of register
871     */
872     void growTo(size_t n)
873     {
874 		m_max_sig_words = n;
875         if (n >= size()) {
876 			if (m_reg.capacity < n) m_reg.reserve(n*2);
877             m_reg.resize(roundUp!size_t(n, 8));
878 		}
879     }
880 
881     /**
882     * Fill BigInt with a random number with size of bitsize
883     * If set_high_bit is true, the highest bit will be set, which causes
884     * the entropy to be bits-1. Otherwise the highest bit is randomly choosen
885     * by the rng, causing the entropy to be bits.
886     * 
887     * Params:
888     *  rng = the random number generator to use
889     *  bitsize = number of bits the created random value should have
890     *  set_high_bit = if true, the highest bit is always set
891     */
892     void randomize(RandomNumberGenerator rng, size_t bitsize = 0, bool set_high_bit = true)
893     {
894         setSign(Positive);
895         
896         if (bitsize == 0)
897             clear();
898         else
899         {
900             SecureVector!ubyte array = rng.randomVec((bitsize + 7) / 8);
901 			// Always cut unwanted bits
902             if (bitsize % 8)
903                 array[0] &= 0xFF >> (8 - (bitsize % 8));
904 			// Set the highest bit if wanted
905 			if (set_high_bit)
906 				array[0] |= 0x80 >> ((bitsize % 8) ? (8 - bitsize % 8) : 0);
907             binaryDecode(array.ptr, array.length);
908         }
909     }
910 
911     /**
912     * Store BigInt-value in a given ubyte array
913     * Params:
914     *  output = destination ubyte array for the integer value
915     */
916     void binaryEncode(ubyte* output) const
917     {
918         const size_t sig_bytes = bytes();
919         foreach (size_t i; 0 .. sig_bytes) {
920             output[sig_bytes-i-1] = byteAt(i);
921         }
922     }
923 
924     /**
925     * Read integer value from a ubyte array with given size
926     * Params:
927     *  buf = ubyte array buffer containing the integer
928     *  length = size of buf
929     */
930     void binaryDecode(const(ubyte)* buf, size_t length)
931     {
932         const size_t WORD_BYTES = (word).sizeof;
933         
934         clear();
935         m_reg.resize(roundUp!size_t((length / WORD_BYTES) + 1, 8));
936         foreach (size_t i; 0 .. (length / WORD_BYTES))
937         {
938             const size_t top = length - WORD_BYTES*i;
939             for (size_t j = WORD_BYTES; j > 0; --j)
940                 m_reg[i] = (m_reg[i] << 8) | buf[top - j];
941         }
942         
943         foreach (size_t i; 0 .. (length % WORD_BYTES))
944             m_reg[length / WORD_BYTES] = (m_reg[length / WORD_BYTES] << 8) | buf[i];
945     	m_sig_words = size_t.max;
946     }
947 
948     /**
949     * Read integer value from a ubyte array (SecureVector!ubyte)
950     * Params:
951     *  buf = the array to load from
952     */
953     void binaryDecode(ALLOC)(auto const ref Vector!(ubyte, ALLOC) buf)
954     {
955         binaryDecode(buf.ptr, buf.length);
956     }
957 
958     /// ditto
959     void binaryDecode(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) buf)
960     {
961         binaryDecode(buf.ptr, buf.length);
962     }
963 
964     /**
965     * Params:
966     *  base = the base to measure the size for
967     * Returns: size of this integer in base base
968     */
969     size_t encodedSize(Base base = Binary) const
970     {
971         static const double LOG_2_BASE_10 = 0.30102999566;
972         
973         if (base == Binary)
974             return bytes();
975         else if (base == Hexadecimal)
976             return 2*bytes();
977         else if (base == Decimal)
978             return cast(size_t)((bits() * LOG_2_BASE_10) + 1);
979         else
980             throw new InvalidArgument("Unknown base for BigInt encoding");
981     }
982 
983     /**
984     * Params:
985     *  rng = a random number generator
986     *  min = the minimum value
987     *  max = the maximum value
988     * Returns: random integer in [min,max$(RPAREN)
989     */
990     static BigInt randomInteger()(RandomNumberGenerator rng, auto const ref BigInt min, auto const ref BigInt max)
991     {
992 		BigInt delta_upper_bound = max - min - 1;
993 
994         if (delta_upper_bound <= 0)
995             throw new InvalidArgument("randomInteger: invalid min/max values");
996 		// Choose x in [0, delta_upper_bound]
997 		BigInt x;
998 		do {
999 			auto bitsize = delta_upper_bound.bits();
1000 			x.randomize(rng, bitsize, false);
1001 		} while (x > delta_upper_bound);
1002 
1003 		return min + x;
1004     }
1005 
1006     /**
1007     * Create a power of two
1008     * Params:
1009     *  n = the power of two to create
1010     * Returns: bigint representing 2^n
1011     */
1012     static BigInt powerOf2(size_t n)
1013     {
1014         BigInt b;
1015         b.setBit(n);
1016         return b;
1017     }
1018 
1019     /**
1020     * Encode the integer value from a BigInt to an Array of bytes
1021     * Params:
1022     *  n = the BigInt to use as integer source
1023     *  base = number-base of resulting ubyte array representation
1024     * Returns: SecureVector of bytes containing the integer with given base
1025     */
1026     static Vector!ubyte encode()(auto const ref BigInt n, Base base = Binary)
1027     {
1028         Vector!ubyte output = Vector!ubyte(n.encodedSize(base));
1029         encode(output.ptr, n, base);
1030         if (base != Binary)
1031             for (size_t j = 0; j != output.length; ++j)
1032                 if (output[j] == 0)
1033                     output[j] = '0';
1034         return output.move();
1035     }
1036 
1037     /**
1038     * Encode the integer value from a BigInt to a Secure Array of bytes
1039     * Params:
1040     *  n = the BigInt to use as integer source
1041     *  base = number-base of resulting ubyte array representation
1042     * Returns: SecureVector of bytes containing the integer with given base
1043     */
1044     static SecureVector!ubyte encodeLocked()(auto const ref BigInt n, Base base = Binary)
1045     {
1046         SecureVector!ubyte output = SecureVector!ubyte(n.encodedSize(base));
1047         encode(output.ptr, n, base);
1048         if (base != Binary)
1049             for (size_t j = 0; j != output.length; ++j)
1050                 if (output[j] == 0)
1051                     output[j] = '0';
1052         return output.move();
1053     }
1054 
1055     /**
1056     * Encode the integer value from a BigInt to a ubyte array
1057     * Params:
1058     *  output = destination ubyte array for the encoded integer
1059     * value with given base
1060     *  n = the BigInt to use as integer source
1061     *  base = number-base of resulting ubyte array representation
1062     */
1063     static void encode()(ubyte* output, auto const ref BigInt n, Base base = Binary)
1064     {
1065         if (base == Binary)
1066         {
1067             n.binaryEncode(output);
1068         }
1069         else if (base == Hexadecimal)
1070         {
1071             SecureVector!ubyte binary = SecureVector!ubyte(n.encodedSize(Binary));
1072             n.binaryEncode(binary.ptr);
1073             
1074             hexEncode(cast(char*)(output), binary.ptr, binary.length);
1075         }
1076         else if (base == Decimal)
1077         {
1078             BigInt copy = n.dup();
1079             BigInt remainder;
1080             copy.setSign(Positive);
1081             const size_t output_size = n.encodedSize(Decimal);
1082             foreach (size_t j; 0 .. output_size)
1083             {
1084                 auto bi = BigInt(10);
1085                 divide(copy, bi, copy, remainder);
1086                 output[output_size - 1 - j] = digit2char(cast(ubyte)(remainder.wordAt(0)));
1087                 if (copy.isZero())
1088                     break;
1089             }
1090         }
1091         else
1092             throw new InvalidArgument("Unknown BigInt encoding method");
1093     }
1094 
1095     /**
1096     * Create a BigInt from an integer in a ubyte array
1097     * Params:
1098     *  buf = the binary value to load
1099     *  length = size of buf
1100     *  base = number-base of the integer in buf
1101     * Returns: BigInt representing the integer in the ubyte array
1102     */
1103     static BigInt decode(const(ubyte)* buf, size_t length, Base base = Binary)
1104     {
1105         BigInt r;
1106         if (base == Binary)
1107             r.binaryDecode(buf, length);
1108         else if (base == Hexadecimal)
1109         {
1110             SecureVector!ubyte binary;
1111             if (length % 2)
1112             {
1113                 // Handle lack of leading 0
1114                 const char[2] buf0_with_leading_0 = [ '0', cast(char)(buf[0]) ];
1115                 
1116                 binary = hexDecodeLocked(buf0_with_leading_0.ptr, 2);
1117                 binary.reserve(length);
1118                 binary ~= hexDecodeLocked(cast(const(char)*)&buf[1], length - 1, false);
1119             }
1120             else {
1121                 binary = hexDecodeLocked(cast(const(char)*)buf, length, false);
1122             }
1123             r.binaryDecode(binary.ptr, binary.length);
1124         }
1125         else if (base == Decimal)
1126         {
1127             foreach (size_t i; 0 .. length)
1128             {
1129                 if (isSpace(buf[i]))
1130                     continue;
1131                 
1132                 if (!isDigit(buf[i]))
1133                     throw new InvalidArgument("BigInt.decode: " ~ "Invalid character in decimal input");
1134                 
1135                 const ubyte x = char2digit(buf[i]);
1136                 
1137                 if (x >= 10)
1138                     throw new InvalidArgument("BigInt: Invalid decimal string");
1139                 
1140                 r *= 10;
1141                 r += x;
1142             }
1143         }
1144         else
1145             throw new InvalidArgument("Unknown BigInt decoding method");
1146         return r.move;
1147     }
1148 
1149 
1150     /**
1151     * Create a BigInt from an integer in a ubyte array
1152     * Params:
1153     *  buf = the binary value to load
1154     *  base = number-base of the integer in buf
1155     * Returns: BigInt representing the integer in the ubyte array
1156     */
1157     static BigInt decode(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) buf, Base base = Binary)
1158     {
1159         return BigInt.decode(buf.ptr, buf.length, base);
1160     }
1161 
1162     /**
1163     * Create a BigInt from an integer in a ubyte array
1164     * Params:
1165     *  buf = the binary value to load
1166     *  base = number-base of the integer in buf
1167     * Returns: BigInt representing the integer in the ubyte array
1168     */
1169     static BigInt decode(ALLOC)(auto const ref Vector!(ubyte, ALLOC) buf, Base base = Binary)
1170     {
1171         return BigInt.decode(buf.ptr, buf.length, base);
1172     }
1173 
1174     /**
1175     * Encode a BigInt to a ubyte array according to IEEE 1363
1176     * Params:
1177     *  n = the BigInt to encode
1178     *  bytes = the length of the resulting SecureVector!ubyte
1179     * Returns: a SecureVector!ubyte containing the encoded BigInt
1180     */
1181     static SecureVector!ubyte encode1363()(auto const ref BigInt n, size_t bytes)
1182     {
1183         const size_t n_bytes = n.bytes();
1184         if (n_bytes > bytes)
1185             throw new EncodingError("encode1363: n is too large to encode properly");
1186         const size_t leading_0s = bytes - n_bytes;
1187         SecureVector!ubyte output = SecureVector!ubyte(bytes);
1188         encode(output.ptr + leading_0s, n, Binary);
1189         return output;
1190     }
1191 
1192     /*
1193     * Addition Operator
1194     */
1195     BigInt opBinary(string op)(auto const ref BigInt y) const
1196         if (op == "+")
1197     {
1198         const BigInt* x = &this;
1199         const size_t x_sw = x.sigWords(), y_sw = y.sigWords();
1200         
1201         BigInt z = BigInt(x.sign(), std.algorithm.max(x_sw, y_sw) + 1);
1202         
1203         if ((x.sign() == y.sign()))
1204             bigint_add3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1205         else
1206         {
1207             int relative_size = bigint_cmp(x.ptr, x_sw, y.ptr, y_sw);
1208             
1209             if (relative_size < 0)
1210             {
1211                 bigint_sub3(z.mutablePtr(), y.ptr, y_sw, x.ptr, x_sw);
1212                 z.setSign(y.sign());
1213             }
1214             else if (relative_size == 0)
1215                 z.setSign(BigInt.Positive);
1216             else if (relative_size > 0)
1217                 bigint_sub3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1218         }
1219         return z.move();
1220     }
1221 
1222     BigInt opBinary(string op)(in word y) const
1223         if (op == "+")
1224     {
1225         return this + BigInt(y);
1226     }
1227 
1228     /*
1229     * Subtraction Operator
1230     */
1231     BigInt opBinary(string op)(auto const ref BigInt y) const
1232         if (op == "-")
1233     {
1234         const BigInt* x = &this;
1235         const size_t x_sw = x.sigWords(), y_sw = y.sigWords();
1236         
1237         int relative_size = bigint_cmp(x.ptr, x_sw, y.ptr, y_sw);
1238         
1239         BigInt z = BigInt(BigInt.Positive, std.algorithm.max(x_sw, y_sw) + 1);
1240         
1241         if (relative_size < 0)
1242         {
1243             if (x.sign() == y.sign())
1244                 bigint_sub3(z.mutablePtr(), y.ptr, y_sw, x.ptr, x_sw);
1245             else
1246                 bigint_add3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1247             z.setSign(y.reverseSign());
1248         }
1249         else if (relative_size == 0)
1250         {
1251             if (x.sign() != y.sign())
1252                 bigint_shl2(z.mutablePtr(), x.ptr, x_sw, 0, 1);
1253         }
1254         else if (relative_size > 0)
1255         {
1256             if (x.sign() == y.sign())
1257                 bigint_sub3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1258             else
1259                 bigint_add3(z.mutablePtr(), x.ptr, x_sw, y.ptr, y_sw);
1260             z.setSign(x.sign());
1261         }
1262         return z.move();
1263     }
1264 
1265 
1266     BigInt opBinary(string op)(in word y) const
1267         if (op == "-")
1268     {
1269         return this - BigInt(y);
1270     }
1271 
1272     /*
1273     * Multiplication Operator
1274     */
1275     BigInt opBinary(string op)(auto const ref BigInt y) const
1276         if (op == "*")
1277     {
1278         const BigInt* x = &this;
1279         const size_t x_sw = x.sigWords(), y_sw = y.sigWords();
1280         
1281         BigInt z = BigInt(BigInt.Positive, x.length + y.length);
1282         
1283         if (x_sw == 1 && y_sw)
1284             bigint_linmul3(z.mutablePtr(), y.ptr, y_sw, x.wordAt(0));
1285         else if (y_sw == 1 && x_sw)
1286             bigint_linmul3(z.mutablePtr(), x.ptr, x_sw, y.wordAt(0));
1287         else if (x_sw && y_sw)
1288         {
1289             SecureVector!word workspace = SecureVector!word(z.length);
1290             bigint_mul(z.mutablePtr(), z.length, workspace.ptr,
1291                         x.ptr, x.length, x_sw,
1292                         y.ptr, y.length, y_sw);
1293         }
1294         
1295         if (x_sw && y_sw && x.sign() != y.sign())
1296             z.flipSign();
1297         return z.move();
1298     }
1299 
1300 
1301     BigInt opBinary(string op)(in word y) const
1302         if (op == "*")
1303     {
1304         return this * BigInt(y);
1305     }
1306     
1307     /*
1308     * Division Operator
1309     */
1310     BigInt opBinary(string op)(auto const ref BigInt y) const
1311         if (op == "/")
1312     {
1313         const BigInt* x = &this;
1314         BigInt q, r;
1315         divide(*x, y, q, r);
1316         return q.move();
1317     }
1318 
1319 
1320     BigInt opBinary(string op)(in word y) const
1321         if (op == "/")
1322     {
1323         return this / BigInt(y);
1324     }
1325 
1326     /*
1327     * Modulo Operator
1328     */
1329     BigInt opBinary(string op)(auto const ref BigInt mod) const
1330         if (op == "%")
1331     {
1332         const BigInt* n = &this;
1333         if (mod.isZero())
1334             throw new BigInt.DivideByZero();
1335         if (mod.isNegative())
1336             throw new InvalidArgument("BigInt.operator%: modulus must be > 0");
1337         if (n.isPositive() && mod.isPositive() && *n < mod)
1338             return n.dup;
1339         
1340         BigInt q, r;
1341         divide(*n, mod, q, r);
1342         return r.move();
1343     }
1344 
1345     /*
1346     * Modulo Operator
1347     */
1348     word opBinary(string op)(word mod) const
1349         if (op == "%")
1350     {
1351         const BigInt* n = &this;
1352         if (mod == 0)
1353             throw new BigInt.DivideByZero();
1354         
1355         if (isPowerOf2(mod))
1356             return (n.wordAt(0) & (mod - 1));
1357         
1358         word remainder = 0;
1359         
1360         for (size_t j = n.sigWords(); j > 0; --j)
1361             remainder = bigint_modop(remainder, n.wordAt(j-1), mod);
1362         
1363         if (remainder && n.sign() == BigInt.Negative)
1364             return mod - remainder;
1365         return remainder;
1366     }
1367     
1368     /*
1369     * Left Shift Operator
1370     */
1371     BigInt opBinary(string op)(size_t shift) const
1372         if (op == "<<")
1373     {
1374         const BigInt* x = &this;
1375         if (shift == 0)
1376             return x.dup();
1377         
1378         const size_t shift_words = shift / MP_WORD_BITS,
1379             shift_bits  = shift % MP_WORD_BITS;
1380         
1381         const size_t x_sw = x.sigWords();
1382         
1383         BigInt y = BigInt(x.sign(), x_sw + shift_words + (shift_bits ? 1 : 0));
1384         bigint_shl2(y.mutablePtr(), x.ptr, x_sw, shift_words, shift_bits);
1385         return y.move();
1386     }
1387     
1388     /*
1389     * Right Shift Operator
1390     */
1391     BigInt opBinary(string op)(size_t shift) const
1392         if (op == ">>")
1393     {
1394         if (shift == 0)
1395             return this.dup;
1396         if (bits() <= shift)
1397             return BigInt(0);
1398         
1399         const size_t shift_words = shift / MP_WORD_BITS,
1400             shift_bits  = shift % MP_WORD_BITS,
1401             x_sw = sigWords();
1402         
1403         BigInt y = BigInt(sign(), x_sw - shift_words);
1404         bigint_shr2(y.mutablePtr(), ptr, x_sw, shift_words, shift_bits);
1405         return y.move();
1406     }
1407 
1408     @property BigInt move() {
1409         return BigInt(m_reg, m_signedness, m_sig_words);
1410     }
1411 
1412     @property BigInt dup() const {
1413         return BigInt(m_reg.dup(), m_signedness, m_sig_words);
1414     }
1415 private:
1416 
1417     SecureVector!word m_reg;
1418     Sign m_signedness = Positive;
1419     size_t m_sig_words = size_t.max;
1420 	size_t m_max_sig_words = size_t.max;
1421 }