You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

crypter.h 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // Copyright (c) 2009-2013 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"
  7. #include "serialize.h"
  8. #include "keystore.h"
  9. class uint256;
  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. ADD_SERIALIZE_METHODS;
  38. template <typename Stream, typename Operation>
  39. inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
  40. READWRITE(vchCryptedKey);
  41. READWRITE(vchSalt);
  42. READWRITE(nDerivationMethod);
  43. READWRITE(nDeriveIterations);
  44. READWRITE(vchOtherDerivationParameters);
  45. }
  46. CMasterKey()
  47. {
  48. // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
  49. // ie slightly lower than the lowest hardware we need bother supporting
  50. nDeriveIterations = 25000;
  51. nDerivationMethod = 0;
  52. vchOtherDerivationParameters = std::vector<unsigned char>(0);
  53. }
  54. };
  55. typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
  56. /** Encryption/decryption context with key information */
  57. class CCrypter
  58. {
  59. private:
  60. unsigned char chKey[WALLET_CRYPTO_KEY_SIZE];
  61. unsigned char chIV[WALLET_CRYPTO_KEY_SIZE];
  62. bool fKeySet;
  63. public:
  64. bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
  65. bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext);
  66. bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext);
  67. bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
  68. void CleanKey()
  69. {
  70. OPENSSL_cleanse(chKey, sizeof(chKey));
  71. OPENSSL_cleanse(chIV, sizeof(chIV));
  72. fKeySet = false;
  73. }
  74. CCrypter()
  75. {
  76. fKeySet = false;
  77. // 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)
  78. // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
  79. // 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.
  80. LockedPageManager::Instance().LockRange(&chKey[0], sizeof chKey);
  81. LockedPageManager::Instance().LockRange(&chIV[0], sizeof chIV);
  82. }
  83. ~CCrypter()
  84. {
  85. CleanKey();
  86. LockedPageManager::Instance().UnlockRange(&chKey[0], sizeof chKey);
  87. LockedPageManager::Instance().UnlockRange(&chIV[0], sizeof chIV);
  88. }
  89. };
  90. bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
  91. bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
  92. /** Keystore which keeps the private keys encrypted.
  93. * It derives from the basic key store, which is used if no encryption is active.
  94. */
  95. class CCryptoKeyStore : public CBasicKeyStore
  96. {
  97. private:
  98. CryptedKeyMap mapCryptedKeys;
  99. CKeyingMaterial vMasterKey;
  100. // if fUseCrypto is true, mapKeys must be empty
  101. // if fUseCrypto is false, vMasterKey must be empty
  102. bool fUseCrypto;
  103. // keeps track of whether Unlock has run a thourough check before
  104. bool fDecryptionThoroughlyChecked;
  105. protected:
  106. bool SetCrypted();
  107. // will encrypt previously unencrypted keys
  108. bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
  109. bool Unlock(const CKeyingMaterial& vMasterKeyIn);
  110. public:
  111. CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
  112. {
  113. }
  114. bool IsCrypted() const
  115. {
  116. return fUseCrypto;
  117. }
  118. bool IsLocked() const
  119. {
  120. if (!IsCrypted())
  121. return false;
  122. bool result;
  123. {
  124. LOCK(cs_KeyStore);
  125. result = vMasterKey.empty();
  126. }
  127. return result;
  128. }
  129. bool Lock();
  130. virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
  131. bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
  132. bool HaveKey(const CKeyID &address) const
  133. {
  134. {
  135. LOCK(cs_KeyStore);
  136. if (!IsCrypted())
  137. return CBasicKeyStore::HaveKey(address);
  138. return mapCryptedKeys.count(address) > 0;
  139. }
  140. return false;
  141. }
  142. bool GetKey(const CKeyID &address, CKey& keyOut) const;
  143. bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
  144. void GetKeys(std::set<CKeyID> &setAddress) const
  145. {
  146. if (!IsCrypted())
  147. {
  148. CBasicKeyStore::GetKeys(setAddress);
  149. return;
  150. }
  151. setAddress.clear();
  152. CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
  153. while (mi != mapCryptedKeys.end())
  154. {
  155. setAddress.insert((*mi).first);
  156. mi++;
  157. }
  158. }
  159. /* Wallet status (encrypted, locked) changed.
  160. * Note: Called without locks held.
  161. */
  162. boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
  163. };
  164. #endif // __CRYPTER_H__