PageRenderTime 40ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/src/crypter.h

https://gitlab.com/ppanula/nevacoin
C Header | 210 lines | 143 code | 30 blank | 37 comment | 6 complexity | 6888e432cbeab9ea3f048091588e9fa3 MD5 | raw file
  1. // Copyright (c) 2009-2012 The Bitcoin Developers
  2. // Distributed under the MIT/X11 software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #ifndef __CRYPTER_H__
  5. #define __CRYPTER_H__
  6. #include "allocators.h" /* for SecureString */
  7. #include "key.h"
  8. #include "serialize.h"
  9. #include "keystore.h"
  10. const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
  11. const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
  12. /*
  13. Private key encryption is done based on a CMasterKey,
  14. which holds a salt and random encryption key.
  15. CMasterKeys are encrypted using AES-256-CBC using a key
  16. derived using derivation method nDerivationMethod
  17. (0 == EVP_sha512()) and derivation iterations nDeriveIterations.
  18. vchOtherDerivationParameters is provided for alternative algorithms
  19. which may require more parameters (such as scrypt).
  20. Wallet Private Keys are then encrypted using AES-256-CBC
  21. with the double-sha256 of the public key as the IV, and the
  22. master key's key as the encryption key (see keystore.[ch]).
  23. */
  24. /** Master key for wallet encryption */
  25. class CMasterKey
  26. {
  27. public:
  28. std::vector<unsigned char> vchCryptedKey;
  29. std::vector<unsigned char> vchSalt;
  30. // 0 = EVP_sha512()
  31. // 1 = scrypt()
  32. unsigned int nDerivationMethod;
  33. unsigned int nDeriveIterations;
  34. // Use this for more parameters to key derivation,
  35. // such as the various parameters to scrypt
  36. std::vector<unsigned char> vchOtherDerivationParameters;
  37. IMPLEMENT_SERIALIZE
  38. (
  39. READWRITE(vchCryptedKey);
  40. READWRITE(vchSalt);
  41. READWRITE(nDerivationMethod);
  42. READWRITE(nDeriveIterations);
  43. READWRITE(vchOtherDerivationParameters);
  44. )
  45. CMasterKey()
  46. {
  47. // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
  48. // ie slightly lower than the lowest hardware we need bother supporting
  49. nDeriveIterations = 25000;
  50. nDerivationMethod = 1;
  51. vchOtherDerivationParameters = std::vector<unsigned char>(0);
  52. }
  53. CMasterKey(unsigned int nDerivationMethodIndex)
  54. {
  55. switch (nDerivationMethodIndex)
  56. {
  57. case 0: // sha512
  58. default:
  59. nDeriveIterations = 25000;
  60. nDerivationMethod = 0;
  61. vchOtherDerivationParameters = std::vector<unsigned char>(0);
  62. break;
  63. case 1: // scrypt+sha512
  64. nDeriveIterations = 10000;
  65. nDerivationMethod = 1;
  66. vchOtherDerivationParameters = std::vector<unsigned char>(0);
  67. break;
  68. }
  69. }
  70. };
  71. typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
  72. /** Encryption/decryption context with key information */
  73. class CCrypter
  74. {
  75. private:
  76. unsigned char chKey[WALLET_CRYPTO_KEY_SIZE];
  77. unsigned char chIV[WALLET_CRYPTO_KEY_SIZE];
  78. bool fKeySet;
  79. public:
  80. bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
  81. bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext);
  82. bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext);
  83. bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
  84. void CleanKey()
  85. {
  86. OPENSSL_cleanse(chKey, sizeof(chKey));
  87. OPENSSL_cleanse(chIV, sizeof(chIV));
  88. fKeySet = false;
  89. }
  90. CCrypter()
  91. {
  92. fKeySet = false;
  93. // Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
  94. // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
  95. // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
  96. LockedPageManager::instance.LockRange(&chKey[0], sizeof chKey);
  97. LockedPageManager::instance.LockRange(&chIV[0], sizeof chIV);
  98. }
  99. ~CCrypter()
  100. {
  101. CleanKey();
  102. LockedPageManager::instance.UnlockRange(&chKey[0], sizeof chKey);
  103. LockedPageManager::instance.UnlockRange(&chIV[0], sizeof chIV);
  104. }
  105. };
  106. bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
  107. bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
  108. /** Keystore which keeps the private keys encrypted.
  109. * It derives from the basic key store, which is used if no encryption is active.
  110. */
  111. class CCryptoKeyStore : public CBasicKeyStore
  112. {
  113. private:
  114. CryptedKeyMap mapCryptedKeys;
  115. CKeyingMaterial vMasterKey;
  116. // if fUseCrypto is true, mapKeys must be empty
  117. // if fUseCrypto is false, vMasterKey must be empty
  118. bool fUseCrypto;
  119. protected:
  120. bool SetCrypted();
  121. // will encrypt previously unencrypted keys
  122. bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
  123. bool Unlock(const CKeyingMaterial& vMasterKeyIn);
  124. public:
  125. CCryptoKeyStore() : fUseCrypto(false)
  126. {
  127. }
  128. bool IsCrypted() const
  129. {
  130. return fUseCrypto;
  131. }
  132. bool IsLocked() const
  133. {
  134. if (!IsCrypted())
  135. return false;
  136. bool result;
  137. {
  138. LOCK(cs_KeyStore);
  139. result = vMasterKey.empty();
  140. }
  141. return result;
  142. }
  143. bool Lock();
  144. virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
  145. bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
  146. bool HaveKey(const CKeyID &address) const
  147. {
  148. {
  149. LOCK(cs_KeyStore);
  150. if (!IsCrypted())
  151. return CBasicKeyStore::HaveKey(address);
  152. return mapCryptedKeys.count(address) > 0;
  153. }
  154. return false;
  155. }
  156. bool GetKey(const CKeyID &address, CKey& keyOut) const;
  157. bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
  158. void GetKeys(std::set<CKeyID> &setAddress) const
  159. {
  160. if (!IsCrypted())
  161. {
  162. CBasicKeyStore::GetKeys(setAddress);
  163. return;
  164. }
  165. setAddress.clear();
  166. CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
  167. while (mi != mapCryptedKeys.end())
  168. {
  169. setAddress.insert((*mi).first);
  170. mi++;
  171. }
  172. }
  173. /* Wallet status (encrypted, locked) changed.
  174. * Note: Called without locks held.
  175. */
  176. boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
  177. };
  178. #endif