9
9
#include < vector>
10
10
11
11
#include < boost/test/unit_test.hpp>
12
- #include < openssl/aes.h>
13
- #include < openssl/evp.h>
14
12
15
13
BOOST_FIXTURE_TEST_SUITE (wallet_crypto, BasicTestingSetup)
16
14
17
- bool OldSetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char >& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod, unsigned char * chKey, unsigned char * chIV)
18
- {
19
- if (nRounds < 1 || chSalt.size () != WALLET_CRYPTO_SALT_SIZE)
20
- return false ;
21
-
22
- int i = 0 ;
23
- if (nDerivationMethod == 0 )
24
- i = EVP_BytesToKey (EVP_aes_256_cbc (), EVP_sha512 (), &chSalt[0 ],
25
- (unsigned char *)&strKeyData[0 ], strKeyData.size (), nRounds, chKey, chIV);
26
-
27
- if (i != (int )WALLET_CRYPTO_KEY_SIZE)
28
- {
29
- memory_cleanse (chKey, WALLET_CRYPTO_KEY_SIZE);
30
- memory_cleanse (chIV, WALLET_CRYPTO_IV_SIZE);
31
- return false ;
32
- }
33
- return true ;
34
- }
35
-
36
- bool OldEncrypt (const CKeyingMaterial& vchPlaintext, std::vector<unsigned char > &vchCiphertext, const unsigned char chKey[32 ], const unsigned char chIV[16 ])
37
- {
38
- // max ciphertext len for a n bytes of plaintext is
39
- // n + AES_BLOCK_SIZE - 1 bytes
40
- int nLen = vchPlaintext.size ();
41
- int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0 ;
42
- vchCiphertext = std::vector<unsigned char > (nCLen);
43
-
44
- EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
45
-
46
- if (!ctx) return false ;
47
-
48
- bool fOk = true ;
49
-
50
- EVP_CIPHER_CTX_init (ctx);
51
- if (fOk ) fOk = EVP_EncryptInit_ex (ctx, EVP_aes_256_cbc (), nullptr , chKey, chIV) != 0 ;
52
- if (fOk ) fOk = EVP_EncryptUpdate (ctx, &vchCiphertext[0 ], &nCLen, &vchPlaintext[0 ], nLen) != 0 ;
53
- if (fOk ) fOk = EVP_EncryptFinal_ex (ctx, (&vchCiphertext[0 ]) + nCLen, &nFLen) != 0 ;
54
- EVP_CIPHER_CTX_cleanup (ctx);
55
-
56
- EVP_CIPHER_CTX_free (ctx);
57
-
58
- if (!fOk ) return false ;
59
-
60
- vchCiphertext.resize (nCLen + nFLen);
61
- return true ;
62
- }
63
-
64
- bool OldDecrypt (const std::vector<unsigned char >& vchCiphertext, CKeyingMaterial& vchPlaintext, const unsigned char chKey[32 ], const unsigned char chIV[16 ])
65
- {
66
- // plaintext will always be equal to or lesser than length of ciphertext
67
- int nLen = vchCiphertext.size ();
68
- int nPLen = nLen, nFLen = 0 ;
69
-
70
- vchPlaintext = CKeyingMaterial (nPLen);
71
-
72
- EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
73
-
74
- if (!ctx) return false ;
75
-
76
- bool fOk = true ;
77
-
78
- EVP_CIPHER_CTX_init (ctx);
79
- if (fOk ) fOk = EVP_DecryptInit_ex (ctx, EVP_aes_256_cbc (), nullptr , chKey, chIV) != 0 ;
80
- if (fOk ) fOk = EVP_DecryptUpdate (ctx, &vchPlaintext[0 ], &nPLen, &vchCiphertext[0 ], nLen) != 0 ;
81
- if (fOk ) fOk = EVP_DecryptFinal_ex (ctx, (&vchPlaintext[0 ]) + nPLen, &nFLen) != 0 ;
82
- EVP_CIPHER_CTX_cleanup (ctx);
83
-
84
- EVP_CIPHER_CTX_free (ctx);
85
-
86
- if (!fOk ) return false ;
87
-
88
- vchPlaintext.resize (nPLen + nFLen);
89
- return true ;
90
- }
91
-
92
15
class TestCrypter
93
16
{
94
17
public:
95
18
static void TestPassphraseSingle (const std::vector<unsigned char >& vchSalt, const SecureString& passphrase, uint32_t rounds,
96
19
const std::vector<unsigned char >& correctKey = std::vector<unsigned char >(),
97
20
const std::vector<unsigned char >& correctIV=std::vector<unsigned char >())
98
21
{
99
- unsigned char chKey[WALLET_CRYPTO_KEY_SIZE];
100
- unsigned char chIV[WALLET_CRYPTO_IV_SIZE];
101
-
102
22
CCrypter crypt;
103
23
crypt.SetKeyFromPassphrase (passphrase, vchSalt, rounds, 0 );
104
24
105
- OldSetKeyFromPassphrase (passphrase, vchSalt, rounds, 0 , chKey, chIV);
106
-
107
- BOOST_CHECK_MESSAGE (memcmp (chKey, crypt.vchKey .data (), crypt.vchKey .size ()) == 0 , \
108
- HexStr (chKey, chKey+sizeof (chKey)) + std::string (" != " ) + HexStr (crypt.vchKey ));
109
- BOOST_CHECK_MESSAGE (memcmp (chIV, crypt.vchIV .data (), crypt.vchIV .size ()) == 0 , \
110
- HexStr (chIV, chIV+sizeof (chIV)) + std::string (" != " ) + HexStr (crypt.vchIV ));
111
-
112
25
if (!correctKey.empty ())
113
- BOOST_CHECK_MESSAGE (memcmp (chKey, & correctKey[ 0 ], sizeof (chKey )) == 0 , \
114
- HexStr (chKey, chKey+ sizeof (chKey )) + std::string (" != " ) + HexStr (correctKey.begin (), correctKey.end ()));
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 ()));
115
28
if (!correctIV.empty ())
116
- BOOST_CHECK_MESSAGE (memcmp (chIV, & correctIV[ 0 ], sizeof (chIV )) == 0 ,
117
- HexStr (chIV, chIV+ sizeof (chIV )) + std::string (" != " ) + HexStr (correctIV.begin (), correctIV.end ()));
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 ()));
118
31
}
119
32
120
33
static void TestPassphrase (const std::vector<unsigned char >& vchSalt, const SecureString& passphrase, uint32_t rounds,
@@ -126,50 +39,26 @@ static void TestPassphrase(const std::vector<unsigned char>& vchSalt, const Secu
126
39
TestPassphraseSingle (vchSalt, SecureString (i, passphrase.end ()), rounds);
127
40
}
128
41
129
-
130
42
static void TestDecrypt (const CCrypter& crypt, const std::vector<unsigned char >& vchCiphertext, \
131
43
const std::vector<unsigned char >& vchPlaintext = std::vector<unsigned char >())
132
44
{
133
- CKeyingMaterial vchDecrypted1;
134
- CKeyingMaterial vchDecrypted2;
135
- int result1, result2;
136
- result1 = crypt.Decrypt (vchCiphertext, vchDecrypted1);
137
- result2 = OldDecrypt (vchCiphertext, vchDecrypted2, crypt.vchKey .data (), crypt.vchIV .data ());
138
- BOOST_CHECK (result1 == result2);
139
-
140
- // These two should be equal. However, OpenSSL 1.0.1j introduced a change
141
- // that would zero all padding except for the last byte for failed decrypts.
142
- // This behavior was reverted for 1.0.1k.
143
- if (vchDecrypted1 != vchDecrypted2 && vchDecrypted1.size () >= AES_BLOCK_SIZE && SSLeay () == 0x100010afL )
144
- {
145
- for (CKeyingMaterial::iterator it = vchDecrypted1.end () - AES_BLOCK_SIZE; it != vchDecrypted1.end () - 1 ; it++)
146
- *it = 0 ;
147
- }
148
-
149
- BOOST_CHECK_MESSAGE (vchDecrypted1 == vchDecrypted2, HexStr (vchDecrypted1.begin (), vchDecrypted1.end ()) + " != " + HexStr (vchDecrypted2.begin (), vchDecrypted2.end ()));
150
-
45
+ CKeyingMaterial vchDecrypted;
46
+ crypt.Decrypt (vchCiphertext, vchDecrypted);
151
47
if (vchPlaintext.size ())
152
- BOOST_CHECK (CKeyingMaterial (vchPlaintext.begin (), vchPlaintext.end ()) == vchDecrypted2 );
48
+ BOOST_CHECK (CKeyingMaterial (vchPlaintext.begin (), vchPlaintext.end ()) == vchDecrypted );
153
49
}
154
50
155
51
static void TestEncryptSingle (const CCrypter& crypt, const CKeyingMaterial& vchPlaintext,
156
52
const std::vector<unsigned char >& vchCiphertextCorrect = std::vector<unsigned char >())
157
53
{
158
- std::vector<unsigned char > vchCiphertext1;
159
- std::vector<unsigned char > vchCiphertext2;
160
- int result1 = crypt.Encrypt (vchPlaintext, vchCiphertext1);
161
-
162
- int result2 = OldEncrypt (vchPlaintext, vchCiphertext2, crypt.vchKey .data (), crypt.vchIV .data ());
163
- BOOST_CHECK (result1 == result2);
164
- BOOST_CHECK (vchCiphertext1 == vchCiphertext2);
54
+ std::vector<unsigned char > vchCiphertext;
55
+ crypt.Encrypt (vchPlaintext, vchCiphertext);
165
56
166
57
if (!vchCiphertextCorrect.empty ())
167
- BOOST_CHECK (vchCiphertext2 == vchCiphertextCorrect);
58
+ BOOST_CHECK (vchCiphertext == vchCiphertextCorrect);
168
59
169
60
const std::vector<unsigned char > vchPlaintext2 (vchPlaintext.begin (), vchPlaintext.end ());
170
-
171
- if (vchCiphertext1 == vchCiphertext2)
172
- TestDecrypt (crypt, vchCiphertext1, vchPlaintext2);
61
+ TestDecrypt (crypt, vchCiphertext, vchPlaintext2);
173
62
}
174
63
175
64
static void TestEncrypt (const CCrypter& crypt, const std::vector<unsigned char >& vchPlaintextIn, \
0 commit comments