diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2011-07-15 16:08:38 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2011-07-15 16:42:44 +0200 |
commit | d4211176208b5e4ae4a699c6ce3239447752cdb2 (patch) | |
tree | 2f1c91d534d1571e3a04c000d66590964bbc213e /src/crypter.cpp | |
parent | a24b23622e504f5134dd8011af5bbe68cb9443f1 (diff) | |
parent | 5b0fc31b1c3d25039262ae2043474b35c14bd30b (diff) |
Merge branch 'master' of https://github.com/bitcoin/bitcoin
Diffstat (limited to 'src/crypter.cpp')
-rw-r--r-- | src/crypter.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/crypter.cpp b/src/crypter.cpp new file mode 100644 index 0000000000..9a8e6ca89a --- /dev/null +++ b/src/crypter.cpp @@ -0,0 +1,132 @@ +// Copyright (c) 2011 The Bitcoin Developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <openssl/aes.h> +#include <openssl/evp.h> +#include <vector> +#include <string> +#include "headers.h" +#ifdef __WXMSW__ +#include <windows.h> +#endif + +#include "crypter.h" +#include "main.h" +#include "util.h" + +bool CCrypter::SetKeyFromPassphrase(const std::string& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod) +{ + if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE) + return false; + + // Try to keep the keydata out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap) + // Note that this does nothing about suspend-to-disk (which will put all our key data on disk) + // 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. + mlock(&chKey[0], sizeof chKey); + mlock(&chIV[0], sizeof chIV); + + int i = 0; + if (nDerivationMethod == 0) + i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], + (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV); + + if (i != WALLET_CRYPTO_KEY_SIZE) + { + memset(&chKey, 0, sizeof chKey); + memset(&chIV, 0, sizeof chIV); + return false; + } + + fKeySet = true; + return true; +} + +bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV) +{ + if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE) + return false; + + // Try to keep the keydata out of swap + // Note that this does nothing about suspend-to-disk (which will put all our key data on disk) + // 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. + mlock(&chKey[0], sizeof chKey); + mlock(&chIV[0], sizeof chIV); + + memcpy(&chKey[0], &chNewKey[0], sizeof chKey); + memcpy(&chIV[0], &chNewIV[0], sizeof chIV); + + fKeySet = true; + return true; +} + +bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext) +{ + if (!fKeySet) + return false; + + // max ciphertext len for a n bytes of plaintext is + // n + AES_BLOCK_SIZE - 1 bytes + int nLen = vchPlaintext.size(); + int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0; + vchCiphertext = std::vector<unsigned char> (nCLen); + + EVP_CIPHER_CTX ctx; + + EVP_CIPHER_CTX_init(&ctx); + EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); + + EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen); + EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen); + + EVP_CIPHER_CTX_cleanup(&ctx); + + vchCiphertext.resize(nCLen + nFLen); + return true; +} + +bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) +{ + if (!fKeySet) + return false; + + // plaintext will always be equal to or lesser than length of ciphertext + int nLen = vchCiphertext.size(); + int nPLen = nLen, nFLen = 0; + + vchPlaintext = CKeyingMaterial(nPLen); + + EVP_CIPHER_CTX ctx; + + EVP_CIPHER_CTX_init(&ctx); + EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); + + EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen); + EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen); + + EVP_CIPHER_CTX_cleanup(&ctx); + + vchPlaintext.resize(nPLen + nFLen); + return true; +} + + +bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext) +{ + CCrypter cKeyCrypter; + std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + if(!cKeyCrypter.SetKey(vMasterKey, chIV)) + return false; + return cKeyCrypter.Encrypt((CKeyingMaterial)vchPlaintext, vchCiphertext); +} + +bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CSecret& vchPlaintext) +{ + CCrypter cKeyCrypter; + std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + if(!cKeyCrypter.SetKey(vMasterKey, chIV)) + return false; + return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext)); +} |