Bitcoin Core  0.18.99
P2P Digital Currency
wallet_crypto_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2019 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <test/setup_common.h>
6 #include <util/strencodings.h>
7 #include <wallet/crypter.h>
8 
9 #include <vector>
10 
11 #include <boost/test/unit_test.hpp>
12 
14 
16 {
17 public:
18 static void TestPassphraseSingle(const std::vector<unsigned char>& vchSalt, const SecureString& passphrase, uint32_t rounds,
19  const std::vector<unsigned char>& correctKey = std::vector<unsigned char>(),
20  const std::vector<unsigned char>& correctIV=std::vector<unsigned char>())
21 {
22  CCrypter crypt;
23  crypt.SetKeyFromPassphrase(passphrase, vchSalt, rounds, 0);
24 
25  if(!correctKey.empty())
26  BOOST_CHECK_MESSAGE(memcmp(crypt.vchKey.data(), correctKey.data(), crypt.vchKey.size()) == 0, \
27  HexStr(crypt.vchKey.begin(), crypt.vchKey.end()) + std::string(" != ") + HexStr(correctKey.begin(), correctKey.end()));
28  if(!correctIV.empty())
29  BOOST_CHECK_MESSAGE(memcmp(crypt.vchIV.data(), correctIV.data(), crypt.vchIV.size()) == 0,
30  HexStr(crypt.vchIV.begin(), crypt.vchIV.end()) + std::string(" != ") + HexStr(correctIV.begin(), correctIV.end()));
31 }
32 
33 static void TestPassphrase(const std::vector<unsigned char>& vchSalt, const SecureString& passphrase, uint32_t rounds,
34  const std::vector<unsigned char>& correctKey = std::vector<unsigned char>(),
35  const std::vector<unsigned char>& correctIV=std::vector<unsigned char>())
36 {
37  TestPassphraseSingle(vchSalt, passphrase, rounds, correctKey, correctIV);
38  for(SecureString::const_iterator i(passphrase.begin()); i != passphrase.end(); ++i)
39  TestPassphraseSingle(vchSalt, SecureString(i, passphrase.end()), rounds);
40 }
41 
42 static void TestDecrypt(const CCrypter& crypt, const std::vector<unsigned char>& vchCiphertext, \
43  const std::vector<unsigned char>& vchPlaintext = std::vector<unsigned char>())
44 {
45  CKeyingMaterial vchDecrypted;
46  crypt.Decrypt(vchCiphertext, vchDecrypted);
47  if (vchPlaintext.size())
48  BOOST_CHECK(CKeyingMaterial(vchPlaintext.begin(), vchPlaintext.end()) == vchDecrypted);
49 }
50 
51 static void TestEncryptSingle(const CCrypter& crypt, const CKeyingMaterial& vchPlaintext,
52  const std::vector<unsigned char>& vchCiphertextCorrect = std::vector<unsigned char>())
53 {
54  std::vector<unsigned char> vchCiphertext;
55  crypt.Encrypt(vchPlaintext, vchCiphertext);
56 
57  if (!vchCiphertextCorrect.empty())
58  BOOST_CHECK(vchCiphertext == vchCiphertextCorrect);
59 
60  const std::vector<unsigned char> vchPlaintext2(vchPlaintext.begin(), vchPlaintext.end());
61  TestDecrypt(crypt, vchCiphertext, vchPlaintext2);
62 }
63 
64 static void TestEncrypt(const CCrypter& crypt, const std::vector<unsigned char>& vchPlaintextIn, \
65  const std::vector<unsigned char>& vchCiphertextCorrect = std::vector<unsigned char>())
66 {
67  TestEncryptSingle(crypt, CKeyingMaterial(vchPlaintextIn.begin(), vchPlaintextIn.end()), vchCiphertextCorrect);
68  for(std::vector<unsigned char>::const_iterator i(vchPlaintextIn.begin()); i != vchPlaintextIn.end(); ++i)
69  TestEncryptSingle(crypt, CKeyingMaterial(i, vchPlaintextIn.end()));
70 }
71 
72 };
73 
74 BOOST_AUTO_TEST_CASE(passphrase) {
75  // These are expensive.
76 
77  TestCrypter::TestPassphrase(ParseHex("0000deadbeef0000"), "test", 25000, \
78  ParseHex("fc7aba077ad5f4c3a0988d8daa4810d0d4a0e3bcb53af662998898f33df0556a"), \
79  ParseHex("cf2f2691526dd1aa220896fb8bf7c369"));
80 
81  std::string hash(GetRandHash().ToString());
82  std::vector<unsigned char> vchSalt(8);
83  GetRandBytes(vchSalt.data(), vchSalt.size());
84  uint32_t rounds = InsecureRand32();
85  if (rounds > 30000)
86  rounds = 30000;
87  TestCrypter::TestPassphrase(vchSalt, SecureString(hash.begin(), hash.end()), rounds);
88 }
89 
91  std::vector<unsigned char> vchSalt = ParseHex("0000deadbeef0000");
92  BOOST_CHECK(vchSalt.size() == WALLET_CRYPTO_SALT_SIZE);
93  CCrypter crypt;
94  crypt.SetKeyFromPassphrase("passphrase", vchSalt, 25000, 0);
95  TestCrypter::TestEncrypt(crypt, ParseHex("22bcade09ac03ff6386914359cfe885cfeb5f77ff0d670f102f619687453b29d"));
96 
97  for (int i = 0; i != 100; i++)
98  {
99  uint256 hash(GetRandHash());
100  TestCrypter::TestEncrypt(crypt, std::vector<unsigned char>(hash.begin(), hash.end()));
101  }
102 
103 }
104 
106  std::vector<unsigned char> vchSalt = ParseHex("0000deadbeef0000");
107  BOOST_CHECK(vchSalt.size() == WALLET_CRYPTO_SALT_SIZE);
108  CCrypter crypt;
109  crypt.SetKeyFromPassphrase("passphrase", vchSalt, 25000, 0);
110 
111  // Some corner cases the came up while testing
112  TestCrypter::TestDecrypt(crypt,ParseHex("795643ce39d736088367822cdc50535ec6f103715e3e48f4f3b1a60a08ef59ca"));
113  TestCrypter::TestDecrypt(crypt,ParseHex("de096f4a8f9bd97db012aa9d90d74de8cdea779c3ee8bc7633d8b5d6da703486"));
114  TestCrypter::TestDecrypt(crypt,ParseHex("32d0a8974e3afd9c6c3ebf4d66aa4e6419f8c173de25947f98cf8b7ace49449c"));
115  TestCrypter::TestDecrypt(crypt,ParseHex("e7c055cca2faa78cb9ac22c9357a90b4778ded9b2cc220a14cea49f931e596ea"));
116  TestCrypter::TestDecrypt(crypt,ParseHex("b88efddd668a6801d19516d6830da4ae9811988ccbaf40df8fbb72f3f4d335fd"));
117  TestCrypter::TestDecrypt(crypt,ParseHex("8cae76aa6a43694e961ebcb28c8ca8f8540b84153d72865e8561ddd93fa7bfa9"));
118 
119  for (int i = 0; i != 100; i++)
120  {
121  uint256 hash(GetRandHash());
122  TestCrypter::TestDecrypt(crypt, std::vector<unsigned char>(hash.begin(), hash.end()));
123  }
124 }
125 
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< unsigned char > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
Definition: crypter.cpp:42
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< unsigned char > &vchCiphertext) const
Definition: crypter.cpp:74
Encryption/decryption context with key information.
Definition: crypter.h:76
static void TestEncrypt(const CCrypter &crypt, const std::vector< unsigned char > &vchPlaintextIn, const std::vector< unsigned char > &vchCiphertextCorrect=std::vector< unsigned char >())
uint256 GetRandHash() noexcept
Definition: random.cpp:675
std::vector< unsigned char > ParseHex(const char *psz)
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:60
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition: crypter.h:68
static void TestPassphrase(const std::vector< unsigned char > &vchSalt, const SecureString &passphrase, uint32_t rounds, const std::vector< unsigned char > &correctKey=std::vector< unsigned char >(), const std::vector< unsigned char > &correctIV=std::vector< unsigned char >())
bool Decrypt(const std::vector< unsigned char > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Definition: crypter.cpp:92
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:659
unsigned char * begin()
Definition: uint256.h:55
unsigned char * end()
Definition: uint256.h:60
std::vector< unsigned char, secure_allocator< unsigned char > > vchKey
Definition: crypter.h:80
std::vector< unsigned char, secure_allocator< unsigned char > > vchIV
Definition: crypter.h:81
static void TestPassphraseSingle(const std::vector< unsigned char > &vchSalt, const SecureString &passphrase, uint32_t rounds, const std::vector< unsigned char > &correctKey=std::vector< unsigned char >(), const std::vector< unsigned char > &correctIV=std::vector< unsigned char >())
256-bit opaque blob.
Definition: uint256.h:121
const unsigned int WALLET_CRYPTO_SALT_SIZE
Definition: crypter.h:15
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
#define BOOST_AUTO_TEST_SUITE_END()
Definition: object.cpp:16
static void TestDecrypt(const CCrypter &crypt, const std::vector< unsigned char > &vchCiphertext, const std::vector< unsigned char > &vchPlaintext=std::vector< unsigned char >())
std::string HexStr(const T itbegin, const T itend)
Definition: strencodings.h:125
BOOST_AUTO_TEST_CASE(passphrase)
static void TestEncryptSingle(const CCrypter &crypt, const CKeyingMaterial &vchPlaintext, const std::vector< unsigned char > &vchCiphertextCorrect=std::vector< unsigned char >())
#define BOOST_CHECK(expr)
Definition: object.cpp:17