From 1c391a5866e1342617b51041afebee2215e9a30c Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 20 Mar 2015 01:05:47 -0400 Subject: crypter: fix the stored initialization vector size AES IV's are 16bytes, not 32. This was harmless but confusing. Add WALLET_CRYPTO_IV_SIZE to make its usage explicit. --- src/wallet/crypter.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/wallet/crypter.cpp') diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 95aa4c259..8f555579f 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -37,7 +37,7 @@ bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::v bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector& chNewIV) { - if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE) + if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_IV_SIZE) return false; memcpy(&chKey[0], &chNewKey[0], sizeof chKey); @@ -105,8 +105,8 @@ bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingM static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext) { CCrypter cKeyCrypter; - std::vector chIV(WALLET_CRYPTO_KEY_SIZE); - memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + std::vector chIV(WALLET_CRYPTO_IV_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_IV_SIZE); if(!cKeyCrypter.SetKey(vMasterKey, chIV)) return false; return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext); @@ -115,8 +115,8 @@ static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMateri static bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext) { CCrypter cKeyCrypter; - std::vector chIV(WALLET_CRYPTO_KEY_SIZE); - memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + std::vector chIV(WALLET_CRYPTO_IV_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_IV_SIZE); if(!cKeyCrypter.SetKey(vMasterKey, chIV)) return false; return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext)); -- cgit v1.2.3 From fb96831c1ff767cd86099f66127fa4dc1ec6e277 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 26 Mar 2015 17:37:29 -0400 Subject: crypter: constify encrypt/decrypt This makes CCrypter easier to pass aroundf for tests --- src/wallet/crypter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/wallet/crypter.cpp') diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 8f555579f..e37a9c4c8 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -47,7 +47,7 @@ bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector &vchCiphertext) +bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext) const { if (!fKeySet) return false; @@ -74,7 +74,7 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext) +bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext) const { if (!fKeySet) return false; -- cgit v1.2.3 From 9049cde4d962862f507f9ddf1c0dbd49ea04be51 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 20 Mar 2015 01:10:30 -0400 Subject: crypter: hook up the new aes cbc classes --- src/wallet/crypter.cpp | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) (limited to 'src/wallet/crypter.cpp') diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index e37a9c4c8..0a19139a3 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -4,6 +4,7 @@ #include "crypter.h" +#include "crypto/aes.h" #include "script/script.h" #include "script/standard.h" #include "util.h" @@ -53,24 +54,15 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector (nCLen); + // n + AES_BLOCKSIZE bytes + vchCiphertext.resize(vchPlaintext.size() + AES_BLOCKSIZE); - EVP_CIPHER_CTX ctx; - - bool fOk = true; - - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; - if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen) != 0; - if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0]) + nCLen, &nFLen) != 0; - EVP_CIPHER_CTX_cleanup(&ctx); - - if (!fOk) return false; + AES256CBCEncrypt enc(chKey, chIV, true); + size_t nLen = enc.Encrypt(&vchPlaintext[0], vchPlaintext.size(), &vchCiphertext[0]); + if(nLen < vchPlaintext.size()) + return false; + vchCiphertext.resize(nLen); - vchCiphertext.resize(nCLen + nFLen); return true; } @@ -81,23 +73,14 @@ bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingM // 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; + vchPlaintext.resize(nLen); - bool fOk = true; - - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; - if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0; - if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0; - EVP_CIPHER_CTX_cleanup(&ctx); - - if (!fOk) return false; - - vchPlaintext.resize(nPLen + nFLen); + AES256CBCDecrypt dec(chKey, chIV, true); + nLen = dec.Decrypt(&vchCiphertext[0], vchCiphertext.size(), &vchPlaintext[0]); + if(nLen == 0) + return false; + vchPlaintext.resize(nLen); return true; } -- cgit v1.2.3 From 976f9ec2645242032d34ab68a60d963f2ac586d8 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 20 Mar 2015 01:24:12 -0400 Subject: crypter: add a BytesToKey clone to replace the use of openssl BytesToKeySHA512AES should be functionally identical to EVP_BytesToKey, but drops the dependency on openssl. --- src/wallet/crypter.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'src/wallet/crypter.cpp') diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 0a19139a3..190f8ecf2 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -5,6 +5,7 @@ #include "crypter.h" #include "crypto/aes.h" +#include "crypto/sha512.h" #include "script/script.h" #include "script/standard.h" #include "util.h" @@ -12,8 +13,33 @@ #include #include #include -#include -#include + +int CCrypter::BytesToKeySHA512AES(const std::vector& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const +{ + // This mimics the behavior of openssl's EVP_BytesToKey with an aes256cbc + // cipher and sha512 message digest. Because sha512's output size (64b) is + // greater than the aes256 block size (16b) + aes256 key size (32b), + // there's no need to process more than once (D_0). + + if(!count || !key || !iv) + return 0; + + unsigned char buf[CSHA512::OUTPUT_SIZE]; + CSHA512 di; + + di.Write((const unsigned char*)strKeyData.c_str(), strKeyData.size()); + if(chSalt.size()) + di.Write(&chSalt[0], chSalt.size()); + di.Finalize(buf); + + for(int i = 0; i != count - 1; i++) + di.Reset().Write(buf, sizeof(buf)).Finalize(buf); + + memcpy(key, buf, WALLET_CRYPTO_KEY_SIZE); + memcpy(iv, buf + WALLET_CRYPTO_KEY_SIZE, WALLET_CRYPTO_IV_SIZE); + memory_cleanse(buf, sizeof(buf)); + return WALLET_CRYPTO_KEY_SIZE; +} bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod) { @@ -22,8 +48,7 @@ bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::v 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); + i = BytesToKeySHA512AES(chSalt, strKeyData, nRounds, chKey, chIV); if (i != (int)WALLET_CRYPTO_KEY_SIZE) { -- cgit v1.2.3