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