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