comparison UnitTestsSources/EncryptionTests.cpp @ 1:fc26a8fc54d5

initial release
author Alain Mazy <alain@mazy.be>
date Fri, 03 Jul 2020 10:08:44 +0200
parents
children 84c4ca822a13
comparison
equal deleted inserted replaced
0:d7198e8f0d47 1:fc26a8fc54d5
1 /**
2 * Cloud storage plugins for Orthanc
3 * Copyright (C) 2017-2020 Osimis S.A., Belgium
4 *
5 * This program is free software: you can redistribute it and/or
6 * modify it under the terms of the GNU Affero General Public License
7 * as published by the Free Software Foundation, either version 3 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 **/
18 #include "gtest/gtest.h"
19
20 #include "../Common/EncryptionHelpers.h"
21 #include <boost/chrono/chrono.hpp>
22 #include <boost/date_time.hpp>
23
24 TEST(EncryptionHelpers, GenerateKey)
25 {
26 CryptoPP::SecByteBlock key1, key2;
27 EncryptionHelpers::GenerateKey(key1);
28 EncryptionHelpers::GenerateKey(key2);
29
30 // std::cout << EncryptionHelpers::ToHexString(key1) << std::endl;
31 // std::cout << EncryptionHelpers::ToHexString(key2) << std::endl;
32
33 ASSERT_NE(key1, key2);
34
35 ASSERT_EQ(32, key1.size()); // right now, we work with 256bits key
36 ASSERT_EQ(32*2, EncryptionHelpers::ToHexString(key1).size());
37 }
38
39 TEST(EncryptionHelpers, EncryptDecryptSimpleText)
40 {
41 CryptoPP::SecByteBlock masterKey;
42 EncryptionHelpers::GenerateKey(masterKey);
43
44 EncryptionHelpers crypto;
45 crypto.SetCurrentMasterKey(1, masterKey);
46
47 std::string plainTextMessage = "Plain text message";
48 std::string encryptedMessage;
49
50 crypto.Encrypt(encryptedMessage, plainTextMessage);
51
52 std::string decryptedMessage;
53
54 crypto.Decrypt(decryptedMessage, encryptedMessage);
55
56 ASSERT_EQ(plainTextMessage, decryptedMessage);
57 }
58
59 TEST(EncryptionHelpers, EncryptDecrypt1byteText)
60 {
61 CryptoPP::SecByteBlock masterKey;
62 EncryptionHelpers::GenerateKey(masterKey);
63
64 EncryptionHelpers crypto;
65 crypto.SetCurrentMasterKey(1, masterKey);
66
67 std::string plainTextMessage = "P";
68 std::string encryptedMessage;
69
70 crypto.Encrypt(encryptedMessage, plainTextMessage);
71
72 std::string decryptedMessage;
73
74 crypto.Decrypt(decryptedMessage, encryptedMessage);
75
76 ASSERT_EQ(plainTextMessage, decryptedMessage);
77 }
78
79 TEST(EncryptionHelpers, EncryptDecrypt0byteText)
80 {
81 CryptoPP::SecByteBlock masterKey;
82 EncryptionHelpers::GenerateKey(masterKey);
83
84 EncryptionHelpers crypto;
85 crypto.SetCurrentMasterKey(1, masterKey);
86
87 std::string plainTextMessage = "";
88 std::string encryptedMessage;
89
90 crypto.Encrypt(encryptedMessage, plainTextMessage);
91
92 std::string decryptedMessage;
93
94 crypto.Decrypt(decryptedMessage, encryptedMessage);
95
96 ASSERT_EQ(plainTextMessage, decryptedMessage);
97 }
98
99 TEST(EncryptionHelpers, EncryptDecryptTampering)
100 {
101 CryptoPP::SecByteBlock masterKey;
102 EncryptionHelpers::GenerateKey(masterKey);
103
104 EncryptionHelpers crypto;
105 crypto.SetCurrentMasterKey(1, masterKey);
106
107 std::string plainTextMessage = "Plain text message";
108 std::string encryptedMessage;
109 std::string decryptedMessage;
110
111 crypto.Encrypt(encryptedMessage, plainTextMessage);
112
113 {
114 std::string tamperedEncryptedMessage = encryptedMessage;
115 // change the header
116 tamperedEncryptedMessage[0] = 'B';
117 ASSERT_THROW(crypto.Decrypt(decryptedMessage, tamperedEncryptedMessage), EncryptionException);
118 }
119
120 {
121 std::string tamperedEncryptedMessage = encryptedMessage;
122 // tamper the masterKeyId:
123 tamperedEncryptedMessage[EncryptionHelpers::HEADER_VERSION_SIZE + 2] = 0xAF;
124 ASSERT_THROW(crypto.Decrypt(decryptedMessage, tamperedEncryptedMessage), EncryptionException);
125 }
126
127 {
128 std::string tamperedEncryptedMessage = encryptedMessage;
129 // tamper the iv:
130 tamperedEncryptedMessage[EncryptionHelpers::HEADER_VERSION_SIZE + EncryptionHelpers::MASTER_KEY_ID_SIZE + 2] = 0;
131 ASSERT_THROW(crypto.Decrypt(decryptedMessage, tamperedEncryptedMessage), EncryptionException);
132 }
133
134 {
135 std::string tamperedEncryptedMessage = encryptedMessage;
136 // tamper the encrypted text:
137 tamperedEncryptedMessage[EncryptionHelpers::HEADER_VERSION_SIZE + EncryptionHelpers::MASTER_KEY_ID_SIZE + EncryptionHelpers::IV_SIZE + 2] = 0;
138 ASSERT_THROW(crypto.Decrypt(decryptedMessage, tamperedEncryptedMessage), EncryptionException);
139 }
140
141 {
142 std::string tamperedEncryptedMessage = encryptedMessage;
143 // tamper the mac:
144 tamperedEncryptedMessage[tamperedEncryptedMessage.size() - 2] = 0;
145 ASSERT_THROW(crypto.Decrypt(decryptedMessage, tamperedEncryptedMessage), EncryptionException);
146 }
147
148 {
149 std::string tamperedEncryptedMessage = encryptedMessage;
150 // extend the file content
151 tamperedEncryptedMessage = tamperedEncryptedMessage + "TAMPER";
152 ASSERT_THROW(crypto.Decrypt(decryptedMessage, tamperedEncryptedMessage), EncryptionException);
153 }
154
155 {
156 std::string tamperedEncryptedMessage = encryptedMessage;
157 // reduce the file content
158 tamperedEncryptedMessage = tamperedEncryptedMessage.substr(0, tamperedEncryptedMessage.size() - 5);
159 ASSERT_THROW(crypto.Decrypt(decryptedMessage, tamperedEncryptedMessage), EncryptionException);
160 }
161 }
162
163
164 TEST(EncryptionHelpers, EncryptDecrypt2TimesSameText)
165 {
166 CryptoPP::SecByteBlock masterKey;
167 EncryptionHelpers::GenerateKey(masterKey);
168
169 EncryptionHelpers crypto;
170 crypto.SetCurrentMasterKey(1, masterKey);
171
172 std::string plainTextMessage = "Plain text message";
173 std::string encryptedMessage1;
174 std::string encryptedMessage2;
175
176 crypto.Encrypt(encryptedMessage1, plainTextMessage);
177 crypto.Encrypt(encryptedMessage2, plainTextMessage);
178
179 ASSERT_NE(encryptedMessage1, encryptedMessage2);
180
181 std::string decryptedMessage1;
182 std::string decryptedMessage2;
183
184 crypto.Decrypt(decryptedMessage1, encryptedMessage1);
185 crypto.Decrypt(decryptedMessage2, encryptedMessage2);
186
187 ASSERT_EQ(plainTextMessage, decryptedMessage1);
188 ASSERT_EQ(plainTextMessage, decryptedMessage2);
189 }
190
191 TEST(EncryptionHelpers, RotateMasterKeys)
192 {
193 std::string plainTextMessage = "Plain text message";
194 std::string encryptedMessage1;
195 std::string encryptedMessage2;
196 std::string decryptedMessage;
197
198 CryptoPP::SecByteBlock masterKey1;
199 CryptoPP::SecByteBlock masterKey2;
200 EncryptionHelpers::GenerateKey(masterKey1);
201 EncryptionHelpers::GenerateKey(masterKey2);
202
203 {
204 EncryptionHelpers crypto;
205 crypto.SetCurrentMasterKey(1, masterKey1);
206 crypto.Encrypt(encryptedMessage1, plainTextMessage);
207
208 crypto.SetCurrentMasterKey(2, masterKey2);
209 crypto.AddPreviousMasterKey(1, masterKey1);
210
211 crypto.Encrypt(encryptedMessage2, plainTextMessage);
212
213 // ensure that we can decrypt messages encrypted with both master keys
214 crypto.Decrypt(decryptedMessage, encryptedMessage1);
215 ASSERT_EQ(plainTextMessage, decryptedMessage);
216
217 crypto.Decrypt(decryptedMessage, encryptedMessage2);
218 ASSERT_EQ(plainTextMessage, decryptedMessage);
219 }
220
221 {
222 // if we don't know the old key, check we can not decrypt the old message
223 EncryptionHelpers crypto;
224 crypto.SetCurrentMasterKey(2, masterKey2);
225
226 ASSERT_THROW(crypto.Decrypt(decryptedMessage, encryptedMessage1), EncryptionException);
227 }
228 }
229
230
231 void MeasurePerformance(size_t sizeInMB, EncryptionHelpers& crypto)
232 {
233 std::string largePlainText(sizeInMB * 1024 * 1024, 'A');
234 std::string encryptedMessage;
235 std::string decryptedMessage;
236
237 {
238 auto start = boost::posix_time::microsec_clock::local_time();
239 crypto.Encrypt(encryptedMessage, largePlainText);
240
241 auto end = boost::posix_time::microsec_clock::local_time();
242 boost::posix_time::time_duration diff = end - start;
243 std::cout << "encryption of " << sizeInMB << " MB file took " << diff.total_milliseconds() << " ms" << std::endl;
244 }
245
246 {
247 auto start = boost::posix_time::microsec_clock::local_time();
248 crypto.Decrypt(decryptedMessage, encryptedMessage);
249
250 auto end = boost::posix_time::microsec_clock::local_time();
251 boost::posix_time::time_duration diff = end - start;
252 std::cout << "decryption of " << sizeInMB << " MB file took " << diff.total_milliseconds() << " ms" << std::endl;
253 }
254
255 }
256
257 TEST(EncryptionHelpers, Performance)
258 {
259 CryptoPP::SecByteBlock masterKey;
260 EncryptionHelpers::GenerateKey(masterKey);
261
262 EncryptionHelpers crypto;
263 crypto.SetCurrentMasterKey(1, masterKey);
264
265 MeasurePerformance(1, crypto);
266 MeasurePerformance(10, crypto);
267 // MeasurePerformance(100, crypto);
268 // MeasurePerformance(400, crypto);
269 }