1//
2// EVPTest.cpp
3//
4// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "EVPTest.h"
12#include "Poco/Crypto/RSAKey.h"
13#include "Poco/Crypto/ECKey.h"
14#include "Poco/Crypto/EVPPKey.h"
15#include "Poco/TemporaryFile.h"
16#include "Poco/StreamCopier.h"
17#include "Poco/CppUnit/TestCaller.h"
18#include "Poco/CppUnit/TestSuite.h"
19#include <sstream>
20#include <fstream>
21#include <iostream>
22#include <cstring>
23
24
25using namespace Poco::Crypto;
26using Poco::TemporaryFile;
27using Poco::StreamCopier;
28
29
30EVPTest::EVPTest(const std::string& name): CppUnit::TestCase(name)
31{
32}
33
34
35EVPTest::~EVPTest()
36{
37}
38
39
40void EVPTest::testRSAEVPPKey()
41{
42 try
43 {
44 RSAKey* key = new RSAKey(RSAKey::KL_1024, RSAKey::EXP_SMALL);
45 assertTrue (key->type() == Poco::Crypto::KeyPair::KT_RSA);
46 // construct EVPPKey from RSAKey*
47 EVPPKey* pKey = new EVPPKey(key);
48 // EVPPKey increments reference count, so freeing the original must be ok
49 delete key;
50
51 assertTrue (!pKey->isSupported(0));
52 assertTrue (!pKey->isSupported(-1));
53 assertTrue (pKey->isSupported(pKey->type()));
54 assertTrue (pKey->type() == EVP_PKEY_RSA);
55
56 // construct RSAKey from const EVPPKey&
57 key = new RSAKey(*pKey);
58 delete pKey;
59 assertTrue (key->type() == Poco::Crypto::KeyPair::KT_RSA);
60 // construct EVPPKey from RSAKey*
61 pKey = new EVPPKey(key);
62 assertTrue (pKey->type() == EVP_PKEY_RSA);
63
64 BIO* bioPriv1 = BIO_new(BIO_s_mem());
65 BIO* bioPub1 = BIO_new(BIO_s_mem());
66 assertTrue (0 != PEM_write_bio_PrivateKey(bioPriv1, *pKey, NULL, NULL, 0, 0, NULL));
67 assertTrue (0 != PEM_write_bio_PUBKEY(bioPub1, *pKey));
68 char* pPrivData1;
69 long sizePriv1 = BIO_get_mem_data(bioPriv1, &pPrivData1);
70 char* pPubData1;
71 long sizePub1 = BIO_get_mem_data(bioPub1, &pPubData1);
72
73 // construct EVPPKey from EVP_PKEY*
74 EVPPKey evpPKey(pKey->operator EVP_PKEY*());
75 // EVPPKey makes duplicate, so freeing the original must be ok
76 delete pKey;
77 assertTrue (evpPKey.type() == EVP_PKEY_RSA);
78
79 BIO* bioPriv2 = BIO_new(BIO_s_mem());
80 BIO* bioPub2 = BIO_new(BIO_s_mem());
81 assertTrue (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey, NULL, NULL, 0, 0, NULL));
82 assertTrue (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey));
83 char* pPrivData2;
84 long sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2);
85 char* pPubData2;
86 long sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2);
87
88 assertTrue (sizePriv1 && (sizePriv1 == sizePriv2));
89 assertTrue (0 == memcmp(pPrivData1, pPrivData2, sizePriv1));
90 assertTrue (sizePub1 && (sizePub1 == sizePub2));
91 assertTrue (0 == memcmp(pPubData1, pPubData2, sizePub1));
92
93 BIO_free(bioPub2);
94 BIO_free(bioPriv2);
95
96 // copy
97 EVPPKey evpPKey2(evpPKey);
98 assertTrue (evpPKey2.type() == EVP_PKEY_RSA);
99 bioPriv2 = BIO_new(BIO_s_mem());
100 bioPub2 = BIO_new(BIO_s_mem());
101 assertTrue (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey2, NULL, NULL, 0, 0, NULL));
102 assertTrue (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey2));
103 sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2);
104 sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2);
105
106 assertTrue (sizePriv1 && (sizePriv1 == sizePriv2));
107 assertTrue (0 == memcmp(pPrivData1, pPrivData2, sizePriv1));
108 assertTrue (sizePub1 && (sizePub1 == sizePub2));
109 assertTrue (0 == memcmp(pPubData1, pPubData2, sizePub1));
110
111 BIO_free(bioPub2);
112 BIO_free(bioPriv2);
113
114 // move
115 EVPPKey evpPKey3(std::move(evpPKey2));
116 assertTrue (evpPKey3.type() == EVP_PKEY_RSA);
117 bioPriv2 = BIO_new(BIO_s_mem());
118 bioPub2 = BIO_new(BIO_s_mem());
119 assertTrue (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey3, NULL, NULL, 0, 0, NULL));
120 assertTrue (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey3));
121 sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2);
122 sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2);
123
124 assertTrue (sizePriv1 && (sizePriv1 == sizePriv2));
125 assertTrue (0 == memcmp(pPrivData1, pPrivData2, sizePriv1));
126 assertTrue (sizePub1 && (sizePub1 == sizePub2));
127 assertTrue (0 == memcmp(pPubData1, pPubData2, sizePub1));
128
129 BIO_free(bioPub2);
130 BIO_free(bioPriv2);
131 BIO_free(bioPub1);
132 BIO_free(bioPriv1);
133 }
134 catch (Poco::Exception& ex)
135 {
136 std::cerr << ex.displayText() << std::endl;
137 throw;
138 }
139}
140
141
142void EVPTest::testRSAEVPSaveLoadStream()
143{
144 RSAKey rsaKey(RSAKey::KL_1024, RSAKey::EXP_SMALL);
145 EVPPKey key(&rsaKey);
146 std::ostringstream strPub;
147 std::ostringstream strPriv;
148 key.save(&strPub, &strPriv, "testpwd");
149 std::string pubKey = strPub.str();
150 std::string privKey = strPriv.str();
151
152 // now do the round trip
153 std::istringstream iPub(pubKey);
154 std::istringstream iPriv(privKey);
155 EVPPKey key2(&iPub, &iPriv, "testpwd");
156
157 assertTrue (key == key2);
158 assertTrue (!(key != key2));
159 RSAKey rsaKeyNE(RSAKey::KL_1024, RSAKey::EXP_LARGE);
160 EVPPKey keyNE(&rsaKeyNE);
161 assertTrue (key != keyNE);
162 assertTrue (!(key == keyNE));
163 assertTrue (key2 != keyNE);;
164 assertTrue (!(key2 == keyNE));
165
166 std::ostringstream strPub2;
167 std::ostringstream strPriv2;
168 key2.save(&strPub2, &strPriv2, "testpwd");
169 assertTrue (strPub2.str() == pubKey);
170
171 std::istringstream iPriv2(strPriv2.str());
172 EVPPKey key3(0, &iPriv2, "testpwd");
173 std::ostringstream strPub3;
174 key3.save(&strPub3);
175 assertTrue (strPub3.str() == pubKey);
176}
177
178
179void EVPTest::testRSAEVPSaveLoadStreamNoPass()
180{
181 RSAKey rsaKey(RSAKey::KL_1024, RSAKey::EXP_SMALL);
182 EVPPKey key(&rsaKey);
183 std::ostringstream strPub;
184 std::ostringstream strPriv;
185 key.save(&strPub, &strPriv);
186 std::string pubKey = strPub.str();
187 std::string privKey = strPriv.str();
188
189 // now do the round trip
190 std::istringstream iPub(pubKey);
191 std::istringstream iPriv(privKey);
192 EVPPKey key2(&iPub, &iPriv);
193
194 assertTrue (key == key2);
195 assertTrue (!(key != key2));
196 RSAKey rsaKeyNE(RSAKey::KL_1024, RSAKey::EXP_LARGE);
197 EVPPKey keyNE(&rsaKeyNE);
198 assertTrue (key != keyNE);
199 assertTrue (!(key == keyNE));
200 assertTrue (key2 != keyNE);;
201 assertTrue (!(key2 == keyNE));
202
203 std::istringstream iPriv2(privKey);
204 EVPPKey key3(0, &iPriv2);
205 std::ostringstream strPub3;
206 key3.save(&strPub3);
207 std::string pubFromPrivate = strPub3.str();
208 assertTrue (pubFromPrivate == pubKey);
209}
210
211
212void EVPTest::testECEVPPKey()
213{
214 try
215 {
216 std::string curveName = ECKey::getCurveName();
217 if (!curveName.empty())
218 {
219 EVPPKey*pKey = new EVPPKey(curveName);
220 assertTrue (pKey != 0);
221 assertTrue (!pKey->isSupported(0));
222 assertTrue (!pKey->isSupported(-1));
223 assertTrue (pKey->isSupported(pKey->type()));
224 assertTrue (pKey->type() == EVP_PKEY_EC);
225
226 BIO*bioPriv1 = BIO_new(BIO_s_mem());
227 BIO*bioPub1 = BIO_new(BIO_s_mem());
228 assertTrue (0 != PEM_write_bio_PrivateKey(bioPriv1, *pKey, NULL, NULL, 0, 0, NULL));
229 assertTrue (0 != PEM_write_bio_PUBKEY(bioPub1, *pKey));
230 char*pPrivData1;
231 long sizePriv1 = BIO_get_mem_data(bioPriv1, &pPrivData1);
232 char*pPubData1;
233 long sizePub1 = BIO_get_mem_data(bioPub1, &pPubData1);
234
235 // construct EVPPKey from EVP_PKEY*
236 EVPPKey evpPKey(pKey->operator EVP_PKEY*());
237 assertTrue (evpPKey.type() == EVP_PKEY_EC);
238 // EVPPKey makes duplicate, so freeing the original must be ok
239 delete pKey;
240
241 BIO*bioPriv2 = BIO_new(BIO_s_mem());
242 BIO*bioPub2 = BIO_new(BIO_s_mem());
243 assertTrue (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey, NULL, NULL, 0, 0, NULL));
244 assertTrue (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey));
245 char*pPrivData2;
246 long sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2);
247 char*pPubData2;
248 long sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2);
249
250 assertTrue (sizePriv1 && (sizePriv1 == sizePriv2));
251 assertTrue (0 == memcmp(pPrivData1, pPrivData2, sizePriv1));
252 assertTrue (sizePub1 && (sizePub1 == sizePub2));
253 assertTrue (0 == memcmp(pPubData1, pPubData2, sizePub1));
254
255 BIO_free(bioPub2);
256 BIO_free(bioPriv2);
257
258 // copy
259 EVPPKey evpPKey2(evpPKey);
260 assertTrue (evpPKey2.type() == EVP_PKEY_EC);
261 bioPriv2 = BIO_new(BIO_s_mem());
262 bioPub2 = BIO_new(BIO_s_mem());
263 assertTrue (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey2, NULL, NULL, 0, 0, NULL));
264 assertTrue (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey2));
265 sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2);
266 sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2);
267
268 assertTrue (sizePriv1 && (sizePriv1 == sizePriv2));
269 assertTrue (0 == memcmp(pPrivData1, pPrivData2, sizePriv1));
270 assertTrue (sizePub1 && (sizePub1 == sizePub2));
271 assertTrue (0 == memcmp(pPubData1, pPubData2, sizePub1));
272
273 BIO_free(bioPub2);
274 BIO_free(bioPriv2);
275
276 // move
277 EVPPKey evpPKey3(std::move(evpPKey2));
278 assertTrue (evpPKey3.type() == EVP_PKEY_EC);
279 bioPriv2 = BIO_new(BIO_s_mem());
280 bioPub2 = BIO_new(BIO_s_mem());
281 assertTrue (0 != PEM_write_bio_PrivateKey(bioPriv2, evpPKey3, NULL, NULL, 0, 0, NULL));
282 assertTrue (0 != PEM_write_bio_PUBKEY(bioPub2, evpPKey3));
283 sizePriv2 = BIO_get_mem_data(bioPriv2, &pPrivData2);
284 sizePub2 = BIO_get_mem_data(bioPub2, &pPubData2);
285
286 assertTrue (sizePriv1 && (sizePriv1 == sizePriv2));
287 assertTrue (0 == memcmp(pPrivData1, pPrivData2, sizePriv1));
288 assertTrue (sizePub1 && (sizePub1 == sizePub2));
289 assertTrue (0 == memcmp(pPubData1, pPubData2, sizePub1));
290
291 BIO_free(bioPub2);
292 BIO_free(bioPriv2);
293 BIO_free(bioPub1);
294 BIO_free(bioPriv1);
295 }
296 else
297 std::cerr << "No elliptic curves found!" << std::endl;
298 }
299 catch (Poco::Exception& ex)
300 {
301 std::cerr << ex.displayText() << std::endl;
302 throw;
303 }
304}
305
306
307void EVPTest::testECEVPSaveLoadStream()
308{
309 try
310 {
311 std::string curveName = ECKey::getCurveName();
312 if (!curveName.empty())
313 {
314 EVPPKey key(curveName);
315 std::ostringstream strPub;
316 std::ostringstream strPriv;
317 key.save(&strPub, &strPriv, "testpwd");
318 std::string pubKey = strPub.str();
319 std::string privKey = strPriv.str();
320
321 // now do the round trip
322 std::istringstream iPub(pubKey);
323 std::istringstream iPriv(privKey);
324 EVPPKey key2(&iPub, &iPriv, "testpwd");
325
326 std::ostringstream strPubE;
327 std::ostringstream strPrivE;
328 key2.save(&strPubE, &strPrivE, "testpwd");
329 assertTrue (strPubE.str() == pubKey);
330 /*TODO: figure out why EVP_PKEY_cmp() fails for identical public keys
331 assertTrue (key == key2);
332 assertTrue (!(key != key2));*/
333 ECKey ecKeyNE(curveName);
334 EVPPKey keyNE(&ecKeyNE);
335 assertTrue (key != keyNE);
336 assertTrue (!(key == keyNE));
337 assertTrue (key2 != keyNE);
338 assertTrue (!(key2 == keyNE));
339
340 std::ostringstream strPub2;
341 std::ostringstream strPriv2;
342 key2.save(&strPub2, &strPriv2, "testpwd");
343 assertTrue (strPub2.str() == pubKey);
344
345 std::istringstream iPriv2(strPriv2.str());
346 EVPPKey key3(0, &iPriv2, "testpwd");
347 std::ostringstream strPub3;
348 key3.save(&strPub3);
349 std::string pubFromPrivate = strPub3.str();
350 assertTrue (pubFromPrivate == pubKey);
351 }
352 else
353 std::cerr << "No elliptic curves found!" << std::endl;
354 }
355 catch (Poco::Exception& ex)
356 {
357 std::cerr << ex.displayText() << std::endl;
358 throw;
359 }
360}
361
362
363void EVPTest::testECEVPSaveLoadStreamNoPass()
364{
365 try
366 {
367 std::string curveName = ECKey::getCurveName();
368 if (!curveName.empty())
369 {
370 EVPPKey key(curveName);
371 std::ostringstream strPub;
372 std::ostringstream strPriv;
373 key.save(&strPub, &strPriv);
374 std::string pubKey = strPub.str();
375 std::string privKey = strPriv.str();
376
377 // now do the round trip
378 std::istringstream iPub(pubKey);
379 std::istringstream iPriv(privKey);
380 EVPPKey key2(&iPub, &iPriv);
381
382 std::ostringstream strPubE;
383 std::ostringstream strPrivE;
384 key2.save(&strPubE, &strPrivE);
385 assertTrue (strPubE.str() == pubKey);
386 /*TODO: figure out why EVP_PKEY_cmp() fails for identical public keys
387 assertTrue (key == key2);
388 assertTrue (!(key != key2));*/
389 ECKey ecKeyNE(curveName);
390 EVPPKey keyNE(&ecKeyNE);
391 assertTrue (key != keyNE);
392 assertTrue (!(key == keyNE));
393 assertTrue (key2 != keyNE);
394 assertTrue (!(key2 == keyNE));
395
396 std::ostringstream strPub2;
397 std::ostringstream strPriv2;
398 key2.save(&strPub2, &strPriv2);
399 assertTrue (strPub2.str() == pubKey);
400 assertTrue (strPriv2.str() == privKey);
401
402 std::istringstream iPriv2(privKey);
403 EVPPKey key3(0, &iPriv2);
404 std::ostringstream strPub3;
405 key3.save(&strPub3);
406 std::string pubFromPrivate = strPub3.str();
407 assertTrue (pubFromPrivate == pubKey);
408 }
409 else
410 std::cerr << "No elliptic curves found!" << std::endl;
411 }
412 catch (Poco::Exception& ex)
413 {
414 std::cerr << ex.displayText() << std::endl;
415 throw;
416 }
417}
418
419
420void EVPTest::testECEVPSaveLoadFile()
421{
422 try
423 {
424 std::string curveName = ECKey::getCurveName();
425 if (!curveName.empty())
426 {
427 EVPPKey key(curveName);
428 TemporaryFile filePub;
429 TemporaryFile filePriv;
430 key.save(filePub.path(), filePriv.path(), "testpwd");
431 std::ifstream ifPub(filePub.path());
432 std::ifstream ifPriv(filePriv.path());
433 std::string pubKey;
434 std::string privKey;
435 StreamCopier::copyToString(ifPub, pubKey);
436 StreamCopier::copyToString(ifPriv, privKey);
437
438 EVPPKey key2(filePub.path(), filePriv.path(), "testpwd");
439
440 std::ostringstream strPubE;
441 std::ostringstream strPrivE;
442 key2.save(&strPubE, &strPrivE, "testpwd");
443 assertTrue (strPubE.str() == pubKey);
444 /*TODO: figure out why EVP_PKEY_cmp() fails for identical public keys
445 assertTrue (key == key2);
446 assertTrue (!(key != key2));*/
447 ECKey ecKeyNE(curveName);
448 EVPPKey keyNE(&ecKeyNE);
449 assertTrue (key != keyNE);
450 assertTrue (!(key == keyNE));
451 assertTrue (key2 != keyNE);
452 assertTrue (!(key2 == keyNE));
453
454 std::ostringstream strPub2;
455 std::ostringstream strPriv2;
456 key2.save(&strPub2, &strPriv2, "testpwd");
457 assertTrue (strPub2.str() == pubKey);
458
459 EVPPKey key3("", filePriv.path(), "testpwd");
460 std::ostringstream strPub3;
461 key3.save(&strPub3);
462 std::string pubFromPrivate = strPub3.str();
463 assertTrue (pubFromPrivate == pubKey);
464 }
465 else
466 std::cerr << "No elliptic curves found!" << std::endl;
467 }
468 catch (Poco::Exception& ex)
469 {
470 std::cerr << ex.displayText() << std::endl;
471 throw;
472 }
473}
474
475
476void EVPTest::testECEVPSaveLoadFileNoPass()
477{
478 try
479 {
480 std::string curveName = ECKey::getCurveName();
481 if (!curveName.empty())
482 {
483 EVPPKey key(curveName);
484 TemporaryFile filePub;
485 TemporaryFile filePriv;
486 key.save(filePub.path(), filePriv.path());
487 std::ifstream ifPub(filePub.path());
488 std::ifstream ifPriv(filePriv.path());
489 std::string pubKey;
490 std::string privKey;
491 StreamCopier::copyToString(ifPub, pubKey);
492 StreamCopier::copyToString(ifPriv, privKey);
493
494 EVPPKey key2(filePub.path(), filePriv.path());
495 std::ostringstream strPub2;
496 std::ostringstream strPriv2;
497 key2.save(&strPub2, &strPriv2);
498 assertTrue (strPub2.str() == pubKey);
499
500 EVPPKey key3("", filePriv.path());
501 std::ostringstream strPub3;
502 key3.save(&strPub3);
503 std::string pubFromPrivate = strPub3.str();
504 assertTrue (pubFromPrivate == pubKey);
505 }
506 else
507 std::cerr << "No elliptic curves found!" << std::endl;
508 }
509 catch (Poco::Exception& ex)
510 {
511 std::cerr << ex.displayText() << std::endl;
512 throw;
513 }
514}
515
516
517void EVPTest::setUp()
518{
519}
520
521
522void EVPTest::tearDown()
523{
524}
525
526
527CppUnit::Test* EVPTest::suite()
528{
529 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("EVPTest");
530
531 CppUnit_addTest(pSuite, EVPTest, testRSAEVPPKey);
532 CppUnit_addTest(pSuite, EVPTest, testRSAEVPSaveLoadStream);
533 CppUnit_addTest(pSuite, EVPTest, testRSAEVPSaveLoadStreamNoPass);
534 CppUnit_addTest(pSuite, EVPTest, testECEVPPKey);
535 CppUnit_addTest(pSuite, EVPTest, testECEVPSaveLoadStream);
536 CppUnit_addTest(pSuite, EVPTest, testECEVPSaveLoadStreamNoPass);
537 CppUnit_addTest(pSuite, EVPTest, testECEVPSaveLoadFile);
538 CppUnit_addTest(pSuite, EVPTest, testECEVPSaveLoadFileNoPass);
539
540 return pSuite;
541}
542