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 }