From: alex Date: Sun, 8 Sep 2013 13:28:46 +0000 (+0400) Subject: Crypter.h security improvement, start working on ZeroCoin support X-Git-Tag: v0.4.4.5~21 X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=commitdiff_plain;h=57c556df79e2b413da4715e3867922933083b513 Crypter.h security improvement, start working on ZeroCoin support * Use OPENSSL_cleanse instead of memset for keys cleanup; * Merge CBigNum prime operations from ZeroCoin. --- diff --git a/src/bignum.h b/src/bignum.h index 9d93b00..6b2bada 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -97,6 +97,40 @@ public: setvch(vch); } + /** Generates a cryptographically secure random number between zero and range exclusive + * i.e. 0 < returned number < range + * @param range The upper bound on the number. + * @return + */ + static CBigNum randBignum(const CBigNum& range) { + CBigNum ret; + if(!BN_rand_range(&ret, &range)){ + throw bignum_error("CBigNum:rand element : BN_rand_range failed"); + } + return ret; + } + + /** Generates a cryptographically secure random k-bit number + * @param k The bit length of the number. + * @return + */ + static CBigNum RandKBitBigum(const uint32_t k){ + CBigNum ret; + if(!BN_rand(&ret, k, -1, 0)){ + throw bignum_error("CBigNum:rand element : BN_rand failed"); + } + return ret; + } + + /**Returns the size in bits of the underlying bignum. + * + * @return the size + */ + int bitSize() const{ + return BN_num_bits(this); + } + + void setulong(unsigned long n) { if (!BN_set_word(this, n)) @@ -383,6 +417,122 @@ public: setvch(vch); } + /** + * exponentiation with an int. this^e + * @param e the exponent as an int + * @return + */ + CBigNum pow(const int e) const { + return this->pow(CBigNum(e)); + } + + /** + * exponentiation this^e + * @param e the exponent + * @return + */ + CBigNum pow(const CBigNum& e) const { + CAutoBN_CTX pctx; + CBigNum ret; + if (!BN_exp(&ret, this, &e, pctx)) + throw bignum_error("CBigNum::pow : BN_exp failed"); + return ret; + } + + /** + * modular multiplication: (this * b) mod m + * @param b operand + * @param m modulus + */ + CBigNum mul_mod(const CBigNum& b, const CBigNum& m) const { + CAutoBN_CTX pctx; + CBigNum ret; + if (!BN_mod_mul(&ret, this, &b, &m, pctx)) + throw bignum_error("CBigNum::mul_mod : BN_mod_mul failed"); + + return ret; + } + + /** + * modular exponentiation: this^e mod n + * @param e exponent + * @param m modulus + */ + CBigNum pow_mod(const CBigNum& e, const CBigNum& m) const { + CAutoBN_CTX pctx; + CBigNum ret; + if( e < 0){ + // g^-x = (g^-1)^x + CBigNum inv = this->inverse(m); + CBigNum posE = e * -1; + if (!BN_mod_exp(&ret, &inv, &posE, &m, pctx)) + throw bignum_error("CBigNum::pow_mod: BN_mod_exp failed on negative exponent"); + }else + if (!BN_mod_exp(&ret, this, &e, &m, pctx)) + throw bignum_error("CBigNum::pow_mod : BN_mod_exp failed"); + + return ret; + } + + /** + * Calculates the inverse of this element mod m. + * i.e. i such this*i = 1 mod m + * @param m the modu + * @return the inverse + */ + CBigNum inverse(const CBigNum& m) const { + CAutoBN_CTX pctx; + CBigNum ret; + if (!BN_mod_inverse(&ret, this, &m, pctx)) + throw bignum_error("CBigNum::inverse*= :BN_mod_inverse"); + return ret; + } + + /** + * Generates a random (safe) prime of numBits bits + * @param numBits the number of bits + * @param safe true for a safe prime + * @return the prime + */ + static CBigNum generatePrime(const unsigned int numBits, bool safe = false) { + CBigNum ret; + if(!BN_generate_prime_ex(&ret, numBits, (safe == true), NULL, NULL, NULL)) + throw bignum_error("CBigNum::generatePrime*= :BN_generate_prime_ex"); + return ret; + } + + /** + * Calculates the greatest common divisor (GCD) of two numbers. + * @param m the second element + * @return the GCD + */ + CBigNum gcd( const CBigNum& b) const{ + CAutoBN_CTX pctx; + CBigNum ret; + if (!BN_gcd(&ret, this, &b, pctx)) + throw bignum_error("CBigNum::gcd*= :BN_gcd"); + return ret; + } + + /** + * Miller-Rabin primality test on this element + * @param checks: optional, the number of Miller-Rabin tests to run + * default causes error rate of 2^-80. + * @return true if prime + */ + bool isPrime(const int checks=BN_prime_checks) const { + CAutoBN_CTX pctx; + int ret = BN_is_prime(this, checks, NULL, pctx, NULL); + if(ret < 0){ + throw bignum_error("CBigNum::isPrime :BN_is_prime"); + } + return ret; + } + + bool isOne() const { + return BN_is_one(this); + } + bool operator!() const { @@ -485,6 +635,8 @@ public: friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b); friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b); friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b); + friend inline const CBigNum operator*(const CBigNum& a, const CBigNum& b); + friend inline bool operator<(const CBigNum& a, const CBigNum& b); }; @@ -534,7 +686,7 @@ inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) { CAutoBN_CTX pctx; CBigNum r; - if (!BN_mod(&r, &a, &b, pctx)) + if (!BN_nnmod(&r, &a, &b, pctx)) throw bignum_error("CBigNum::operator% : BN_div failed"); return r; } @@ -561,4 +713,8 @@ inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); } inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); } +inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { return strm << b.ToString(10); } + +typedef CBigNum Bignum; + #endif diff --git a/src/crypter.cpp b/src/crypter.cpp index 6deab04..2b3ff27 100644 --- a/src/crypter.cpp +++ b/src/crypter.cpp @@ -4,6 +4,7 @@ #include #include +//#include // for OPENSSL_cleanse() #include #include #ifdef WIN32 @@ -32,14 +33,14 @@ bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::v i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], (unsigned char *)&scryptHash, sizeof scryptHash, nRounds, chKey, chIV); - memset(&scryptHash, 0, sizeof scryptHash); + OPENSSL_cleanse(&scryptHash, sizeof scryptHash); } if (i != (int)WALLET_CRYPTO_KEY_SIZE) { - memset(&chKey, 0, sizeof chKey); - memset(&chIV, 0, sizeof chIV); + OPENSSL_cleanse(&chKey, sizeof chKey); + OPENSSL_cleanse(&chIV, sizeof chIV); return false; } diff --git a/src/crypter.h b/src/crypter.h index dd5d506..849116c 100644 --- a/src/crypter.h +++ b/src/crypter.h @@ -7,6 +7,7 @@ #include "allocators.h" /* for SecureString */ #include "key.h" #include "serialize.h" +//#include // for OPENSSL_cleanse() const unsigned int WALLET_CRYPTO_KEY_SIZE = 32; const unsigned int WALLET_CRYPTO_SALT_SIZE = 8; @@ -96,8 +97,8 @@ public: void CleanKey() { - memset(&chKey, 0, sizeof chKey); - memset(&chIV, 0, sizeof chIV); + OPENSSL_cleanse(&chKey, sizeof chKey); + OPENSSL_cleanse(&chIV, sizeof chIV); fKeySet = false; }