📄 big_base.cpp
字号:
/************************************************** BigInt Base Source File ** (C) 1999-2002 The Botan Project **************************************************/#include <botan/bigint.h>#include <botan/numthry.h>#include <botan/rng.h>#include <stdio.h>namespace Botan {/************************************************** Construct a BigInt from a regular number **************************************************/BigInt::BigInt(u64bit n) { const u32bit limbs_needed = 8 / sizeof(word); reg.create(limbs_needed + 2); for(u32bit j = 0; j != limbs_needed; j++) reg[j] = (n >> (j*MP_WORD_BITS)) & MP_WORD_MAX; set_sign(Positive); }/************************************************** Construct a BigInt of the specified size **************************************************/BigInt::BigInt(Sign s, u32bit size) { reg.create(size); signedness = s; }/************************************************** Construct a BigInt from a "raw" BigInt **************************************************/BigInt::BigInt(const BigInt& b) { if(b.sig_words()) { reg.set(b.reg.ptr(), b.sig_words()); set_sign(b.sign()); } else { reg.create(2); set_sign(Positive); } }/************************************************** Construct a BigInt from a "raw" BigInt **************************************************/BigInt::BigInt(const word* n, u32bit n_size, Sign s) { printf("WARNING: BigInt(const word*, u32bit, Sign) is deprecated\n"); reg.set(n, n_size); set_sign(s); }/************************************************** Construct a BigInt from a string **************************************************/BigInt::BigInt(const std::string& str) { Encoding code = Decimal; u32bit markers = 0; bool negative = false; if(str.length() > 0 && str[0] == '-') { markers += 1; negative = true; } if(str.length() > markers + 2 && str[markers ] == '0' && str[markers + 1] == 'x') { markers += 2; code = Hexadecimal; } else if(str.length() > markers + 1 && str[markers] == '0') { markers += 1; code = Octal; } *this = decode((byte*)str.data() + markers, str.length() - markers, code); if(negative) set_sign(Negative); else set_sign(Positive); }/************************************************** Construct a BigInt from an encoded BigInt **************************************************/BigInt::BigInt(const SecureVector<byte>& input, Encoding encoding) { printf("WARNING: BigInt(const SecureVector<byte>&, Encoding) is " "deprecated\n"); *this = decode(input, encoding); set_sign(Positive); }/************************************************** Construct a BigInt from an encoded BigInt **************************************************/BigInt::BigInt(const byte input[], u32bit length, Encoding encoding) { *this = decode(input, length, encoding); set_sign(Positive); }/************************************************** Construct a Random BigInt **************************************************/BigInt::BigInt(NumberType type, u32bit bits) { if(type == Random) randomize(bits); else if(type == Prime) *this = random_prime(bits); else if(type == SafePrime) *this = random_safe_prime(bits); }/************************************************** BigInt Destructor **************************************************/BigInt::~BigInt() { }/************************************************** Swap this BigInt with another **************************************************/void BigInt::swap(BigInt& other) { std::swap(reg, other.reg); std::swap(signedness, other.signedness); }/************************************************** Add n to this number **************************************************/void BigInt::add(word n) { if(!n) return; word temp = reg[0]; reg[0] += n; if(reg[0] > temp) return; for(u32bit j = 1; j != size(); j++) if(++reg[j]) return; grow_to(2*size()); reg[size() / 2] = 1; }/************************************************** Subtract n from this number **************************************************/void BigInt::sub(word n) { if(!n) return; word temp = reg[0]; reg[0] -= n; if(reg[0] < temp) return; for(u32bit j = 1; j != size(); j++) if(reg[j]--) return; reg.create(2); flip_sign(); reg[0] = n - temp; }/************************************************** Return word n of this number **************************************************/word BigInt::word_at(u32bit n) const { if(n >= size()) return 0; else return reg[n]; }/************************************************** Return byte n of this number **************************************************/byte BigInt::byte_at(u32bit n) const { const u32bit WORD_BYTES = sizeof(word); u32bit word_num = n / WORD_BYTES, byte_num = n % WORD_BYTES; if(word_num >= size()) return 0; else return get_byte(WORD_BYTES - byte_num - 1, reg[word_num]); }/************************************************** Return bit n of this number **************************************************/bool BigInt::get_bit(u32bit n) const { return ((word_at(n / MP_WORD_BITS) >> (n % MP_WORD_BITS)) & 1); }/************************************************** Set bit number n **************************************************/void BigInt::set_bit(u32bit n) { u32bit word = n / MP_WORD_BITS, mask = 1 << (n % MP_WORD_BITS); if(word >= size()) grow_to(word + 1); reg[word] |= mask; }/************************************************** Clear bit number n **************************************************/void BigInt::clear_bit(u32bit n) { u32bit word = n / MP_WORD_BITS, mask = 1 << (n % MP_WORD_BITS); if(word < size()) reg[word] &= ~mask; }/************************************************** Count how many words are being used **************************************************/u32bit BigInt::sig_words() const { u32bit count = size(); while(count && (reg[count-1] == 0)) count--; return count; }/************************************************** Count how many bytes are being used **************************************************/u32bit BigInt::bytes() const { u32bit bit_count = bits(); return (bit_count / 8) + (bit_count % 8 ? 1 : 0); }/************************************************** Count how many bits are being used **************************************************/u32bit BigInt::bits() const { if(sig_words() == 0) return 0; u32bit full_words = sig_words() - 1, top_bits = MP_WORD_BITS; word top_word = word_at(full_words), mask = MP_WORD_TOP_BIT; while(top_bits && ((top_word & mask) == 0)) { mask >>= 1; top_bits--; } return (full_words * MP_WORD_BITS + top_bits); }/************************************************** Return true if this number is zero **************************************************/bool BigInt::is_zero() const { for(u32bit j = 0; j != size(); j++) if(reg[j]) return false; return true; }/************************************************** Set the sign **************************************************/void BigInt::set_sign(Sign s) { if(is_zero()) signedness = Positive; else signedness = s; }/************************************************** Reverse the value of the sign flag **************************************************/void BigInt::flip_sign() { set_sign(reverse_sign()); }/************************************************** Return the opposite value of the current sign **************************************************/Sign BigInt::reverse_sign() const { if(sign() == Positive) return Negative; return Positive; }/************************************************** Return the negation of this number **************************************************/BigInt BigInt::operator-() const { return (BigInt(reg, reg.size(), reverse_sign())); }/************************************************** Return the absolute value of this number **************************************************/BigInt BigInt::abs() const { BigInt tmp = *this; tmp.set_sign(Positive); return tmp; }/************************************************** Randomize this number **************************************************/void BigInt::randomize(u32bit bitsize) { set_sign(Positive); if(bitsize == 0) bitsize = bits(); SecureVector<byte> array((bitsize / 8) + ((bitsize % 8) ? 1 : 0)); Global_RNG::randomize(array, array.size()); if(bitsize % 8) array[0] &= 0xFF >> (8 - (bitsize % 8)); array[0] |= 0x80 >> ((bitsize % 8) ? (8 - bitsize % 8) : 0); binary_decode(array); }/************************************************** Encode this number into bytes **************************************************/SecureVector<byte> BigInt::binary_encode() const { SecureVector<byte> output(bytes()); binary_encode(output); return output; }/************************************************** Encode this number into bytes **************************************************/void BigInt::binary_encode(byte output[]) const { const u32bit sig_bytes = bytes(); for(u32bit j = 0; j != sig_bytes; j++) output[sig_bytes-j-1] = byte_at(j); }/************************************************** Set this number to the value in buf **************************************************/void BigInt::binary_decode(const SecureVector<byte>& buf) { binary_decode(buf, buf.size()); }/************************************************** Set this number to the value in buf **************************************************/void BigInt::binary_decode(const byte buf[], u32bit length) { const u32bit WORD_BYTES = sizeof(word); reg.create(length / WORD_BYTES + 1); for(u32bit j = 0; j != length / WORD_BYTES; j++) { u32bit top = length - WORD_BYTES*j; for(u32bit k = WORD_BYTES; k > 0; k--) reg[j] = (reg[j] << 8) | buf[top - k]; } for(u32bit j = 0; j != length % WORD_BYTES; j++) reg[length / WORD_BYTES] = (reg[length / WORD_BYTES] << 8) + buf[j]; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -