最近在看mangos的源码,发现了一个BigNumber类的封装,在此记录一下:
BigNumber.h文件
其中common.h文件最初定义了uint32这些基础数据类型,去掉自己定义也无妨:
#ifndef _AUTH_BIGNUMBER_H #define _AUTH_BIGNUMBER_H #include "Common.h" struct bignum_st; class BigNumber { public: BigNumber(); BigNumber(const BigNumber& bn); BigNumber(uint32); ~BigNumber(); void SetDword(uint32); void SetQword(uint64); void SetBinary(const uint8* bytes,int len); void SetHexStr(const char* str); void SetRand(int numbits); BigNumber operator=(const BigNumber& bn); BigNumber operator+=(const BigNumber& bn); BigNumber operator+(const BigNumber& bn) { BigNumber t(*this); return t += bn; } BigNumber operator-=(const BigNumber& bn); BigNumber operator-(const BigNumber& bn) { BigNumber t(*this); return t -= bn; } BigNumber operator*=(const BigNumber& bn); BigNumber operator*(const BigNumber& bn) { BigNumber t(*this); return t *= bn; } BigNumber operator/=(const BigNumber& bn); BigNumber operator/(const BigNumber& bn) { BigNumber t(*this); return t /= bn; } BigNumber operator%=(const BigNumber& bn); BigNumber operator%(const BigNumber& bn) { BigNumber t(*this); return t %= bn; } bool isZero() const; BigNumber ModExp(const BigNumber& bn1,const BigNumber& bn2); BigNumber Exp(const BigNumber&); int GetNumBytes(void); struct bignum_st* BN() { return _bn; } uint32 AsDword(); uint8* AsByteArray(int minSize = 0,bool reverse = true); const char* AsHexStr(); const char* AsDecStr(); private: struct bignum_st* _bn; uint8* _array; }; #endif
BigNumber.cpp
#include "Auth/BigNumber.h" #include <openssl/bn.h> #include <algorithm> BigNumber::BigNumber() { _bn = BN_new(); _array = NULL; } BigNumber::BigNumber(const BigNumber& bn) { _bn = BN_dup(bn._bn); _array = NULL; } BigNumber::BigNumber(uint32 val) { _bn = BN_new(); BN_set_word(_bn,val); _array = NULL; } BigNumber::~BigNumber() { BN_free(_bn); if (_array) delete[] _array; } void BigNumber::SetDword(uint32 val) { BN_set_word(_bn,val); } void BigNumber::SetQword(uint64 val) { BN_add_word(_bn,(uint32)(val >> 32)); BN_lshift(_bn,_bn,32); BN_add_word(_bn,(uint32)(val & 0xFFFFFFFF)); } void BigNumber::SetBinary(const uint8* bytes,int len) { uint8 t[1000]; for (int i = 0; i < len; ++i) t[i] = bytes[len - 1 - i]; BN_bin2bn(t,len,_bn); } void BigNumber::SetHexStr(const char* str) { BN_hex2bn(&_bn,str); } void BigNumber::SetRand(int numbits) { BN_rand(_bn,numbits,1); } BigNumber BigNumber::operator=(const BigNumber& bn) { BN_copy(_bn,bn._bn); return *this; } BigNumber BigNumber::operator+=(const BigNumber& bn) { BN_add(_bn,bn._bn); return *this; } BigNumber BigNumber::operator-=(const BigNumber& bn) { BN_sub(_bn,bn._bn); return *this; } BigNumber BigNumber::operator*=(const BigNumber& bn) { BN_CTX* bnctx; bnctx = BN_CTX_new(); BN_mul(_bn,bn._bn,bnctx); BN_CTX_free(bnctx); return *this; } BigNumber BigNumber::operator/=(const BigNumber& bn) { BN_CTX* bnctx; bnctx = BN_CTX_new(); BN_div(_bn,NULL,bnctx); BN_CTX_free(bnctx); return *this; } BigNumber BigNumber::operator%=(const BigNumber& bn) { BN_CTX* bnctx; bnctx = BN_CTX_new(); BN_mod(_bn,bnctx); BN_CTX_free(bnctx); return *this; } BigNumber BigNumber::Exp(const BigNumber& bn) { BigNumber ret; BN_CTX* bnctx; bnctx = BN_CTX_new(); BN_exp(ret._bn,bnctx); BN_CTX_free(bnctx); return ret; } BigNumber BigNumber::ModExp(const BigNumber& bn1,const BigNumber& bn2) { BigNumber ret; BN_CTX* bnctx; bnctx = BN_CTX_new(); BN_mod_exp(ret._bn,bn1._bn,bn2._bn,bnctx); BN_CTX_free(bnctx); return ret; } int BigNumber::GetNumBytes(void) { return BN_num_bytes(_bn); } uint32 BigNumber::AsDword() { return (uint32)BN_get_word(_bn); } bool BigNumber::isZero() const { return BN_is_zero(_bn) != 0; } uint8* BigNumber::AsByteArray(int minSize,bool reverse) { int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes(); delete[] _array; _array = new uint8[length]; // If we need more bytes than length of BigNumber set the rest to 0 if (length > GetNumBytes()) memset((void*)_array,length); BN_bn2bin(_bn,(unsigned char*)_array); if (reverse) std::reverse(_array,_array + length); return _array; } const char* BigNumber::AsHexStr() { return BN_bn2hex(_bn); } const char* BigNumber::AsDecStr() { return BN_bn2dec(_bn); }