1//
2// RSATest.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 "RSATest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/Crypto/RSADigestEngine.h"
15#include "Poco/Crypto/CipherFactory.h"
16#include "Poco/Crypto/Cipher.h"
17#include "Poco/Crypto/X509Certificate.h"
18#include <iostream>
19#include <sstream>
20
21
22using namespace Poco::Crypto;
23
24
25static const std::string anyPem(
26 "-----BEGIN CERTIFICATE-----\r\n"
27 "MIICaDCCAdECCQCzfxSsk7yaLjANBgkqhkiG9w0BAQUFADBzMQswCQYDVQQGEwJB\r\n"
28 "VDESMBAGA1UECBMJQ2FyaW50aGlhMRIwEAYDVQQHEwlTdC4gSmFrb2IxDzANBgNV\r\n"
29 "BAoTBkFwcEluZjEPMA0GA1UEAxMGQXBwSW5mMRowGAYJKoZIhvcNAQkBFgthcHBA\r\n"
30 "aW5mLmNvbTAeFw0wNjAzMDExMzA3MzFaFw0wNjAzMzExMzA3MzFaMH4xCzAJBgNV\r\n"
31 "BAYTAkFUMRIwEAYDVQQIEwlDYXJpbnRoaWExETAPBgNVBAcTCFN0IEpha29iMRww\r\n"
32 "GgYDVQQKExNBcHBsaWVkIEluZm9ybWF0aWNzMQowCAYDVQQDFAEqMR4wHAYJKoZI\r\n"
33 "hvcNAQkBFg9pbmZvQGFwcGluZi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ\r\n"
34 "AoGBAJHGyXDHyCYoWz+65ltNwwZbhwOGnxr9P1WMATuFJh0bPBZxKbZRdbTm9KhZ\r\n"
35 "OlvsEIsfgiYdsxURYIqXfEgISYLZcZY0pQwGEOmB+0NeC/+ENSfOlNSthx6zSVlc\r\n"
36 "zhJ7+dJOGwepHAiLr1fRuc5jogYLraE+lKTnqAAFfzwvti77AgMBAAEwDQYJKoZI\r\n"
37 "hvcNAQEFBQADgYEAY/ZoeY1ukkEJX7259NeoVM0oahlulWV0rlCqyaeosOiDORPT\r\n"
38 "m6X1w/5MTCf9VyaD1zukoSZ4QqNVjHFXcXidbB7Tgt3yRuZ5PC5LIFCDPv9mgPne\r\n"
39 "mUA70yfctNfza2z3ZiQ6NDkW3mZX+1tmxYIrJQIrkVeYeqf1Gh2nyZrUMcE=\r\n"
40 "-----END CERTIFICATE-----\r\n"
41 "-----BEGIN RSA PRIVATE KEY-----\r\n"
42 "Proc-Type: 4,ENCRYPTED\r\n"
43 "DEK-Info: DES-EDE3-CBC,E7AE93C9E49184EA\r\n"
44 "\r\n"
45 "A2IqzNcWs+I5vzV+i+woDk56+yr58eU0Onw8eEvXkLjnSc58JU4327IF7yUbKWdW\r\n"
46 "Q7BYGGOkVFiZ7ANOwviDg5SUhxRDWCcW8dS6/p1vfdQ1C3qj2OwJjkpg0aDBIzJn\r\n"
47 "FzgguT3MF3ama77vxv0S3kOfmCj62MLqPGpj5pQ0/1hefRFbL8oAX8bXUN7/rmGM\r\n"
48 "Zc0QyzFZv2iQ04dY/6TNclwKPB4H0On4K+8BMs3PRkWA0clCaQaFO2+iwnk3XZfe\r\n"
49 "+MsKUEbLCpAQeYspYv1cw38dCdWq1KTP5aJk+oXgwjfX5cAaPTz74NTqTIsCcaTD\r\n"
50 "3vy7ukJYFlDR9Kyo7z8rMazYrKJslhnuRH0BhK9st9McwL957j5tZmrKyraCcmCx\r\n"
51 "dMAGcsis1va3ayYZpIpFqA4EhYrTM+6N8ZRfUap20+b5IQwHfTQDejUhL6rBwy7j\r\n"
52 "Ti5yD83/itoOMyXq2sV/XWfVD5zk/P5iv22O1EAQMhhnPB9K/I/JhuSGQJfn3cNh\r\n"
53 "ykOUYT0+vDeSeEVa+FVEP1W35G0alTbKbNs5Tb8KxJ3iDJUxokM//SvPXZy9hOVX\r\n"
54 "Y05imB04J15DaGbAHlNzunhuJi7121WV/JRXZRW9diE6hwpD8rwqi3FMuRUmy7U9\r\n"
55 "aFA5poKRAYlo9YtZ3YpFyjGKB6MfCQcB2opuSnQ/gbugV41m67uQ4CDwWLaNRkTb\r\n"
56 "GlsMBNcHnidg15Bsat5HaB7l250ukrI13Uw1MYdDUzaS3gPfw9aC4F2w0p3U+DPH\r\n"
57 "80/zePxtroR7T4/+rI136Rl+aMXDMOEGCX1TVP8rjuZzuRyUSUKC8Q==\r\n"
58 "-----END RSA PRIVATE KEY-----\r\n"
59 "-----BEGIN CERTIFICATE-----\r\n"
60 "MIICXTCCAcYCCQC1Vk/N8qR4AjANBgkqhkiG9w0BAQUFADBzMQswCQYDVQQGEwJB\r\n"
61 "VDESMBAGA1UECBMJQ2FyaW50aGlhMRIwEAYDVQQHEwlTdC4gSmFrb2IxDzANBgNV\r\n"
62 "BAoTBkFwcEluZjEPMA0GA1UEAxMGQXBwSW5mMRowGAYJKoZIhvcNAQkBFgthcHBA\r\n"
63 "aW5mLmNvbTAeFw0wNjAyMjcxMzI3MThaFw0wNjAzMjkxMzI3MThaMHMxCzAJBgNV\r\n"
64 "BAYTAkFUMRIwEAYDVQQIEwlDYXJpbnRoaWExEjAQBgNVBAcTCVN0LiBKYWtvYjEP\r\n"
65 "MA0GA1UEChMGQXBwSW5mMQ8wDQYDVQQDEwZBcHBJbmYxGjAYBgkqhkiG9w0BCQEW\r\n"
66 "C2FwcEBpbmYuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsFXiPuicN\r\n"
67 "Im4oJwF8NuaFN+lgYwcZ6dAO3ILIR3kLA2PxF8HSQLfF8J8a4odZhLhctIMAKTxm\r\n"
68 "k0w8TW5qhL8QLdGzY9vzvkgdKOkan2t3sMeXJAfrM1AphTsmgntAQazGZjOj5p4W\r\n"
69 "jDnxQ+VXAylqwjHh49eSBxM3wgoscF4iLQIDAQABMA0GCSqGSIb3DQEBBQUAA4GB\r\n"
70 "AIpfLdXiKchPvFMhQS8xTtXvrw5dVL3yImUMYs4GQi8RrjGmfGB3yMAR7B/b8v4a\r\n"
71 "+ztfusgWAWiUKuSGTk4S8YB0fsFlmOv0WDr+PyZ4Lui/a8opbyzGE7rqpnF/s0GO\r\n"
72 "M7uLCNNwIN7WhmxcWV0KZU1wTppoSWPJda1yTbBzF9XP\r\n"
73 "-----END CERTIFICATE-----\r\n"
74);
75
76
77RSATest::RSATest(const std::string& name): CppUnit::TestCase(name)
78{
79}
80
81
82RSATest::~RSATest()
83{
84}
85
86
87void RSATest::testRSANewKeys()
88{
89 RSAKey key(RSAKey::KL_1024, RSAKey::EXP_SMALL);
90 std::ostringstream strPub;
91 std::ostringstream strPriv;
92 key.save(&strPub, &strPriv, "testpwd");
93 std::string pubKey = strPub.str();
94 std::string privKey = strPriv.str();
95
96 // now do the round trip
97 std::istringstream iPub(pubKey);
98 std::istringstream iPriv(privKey);
99 RSAKey key2(&iPub, &iPriv, "testpwd");
100
101 std::istringstream iPriv2(privKey);
102 RSAKey key3(0, &iPriv2, "testpwd");
103 std::ostringstream strPub3;
104 key3.save(&strPub3);
105 std::string pubFromPrivate = strPub3.str();
106 assertTrue (pubFromPrivate == pubKey);
107}
108
109
110void RSATest::testRSANewKeysNoPassphrase()
111{
112 RSAKey key(RSAKey::KL_1024, RSAKey::EXP_SMALL);
113 std::ostringstream strPub;
114 std::ostringstream strPriv;
115 key.save(&strPub, &strPriv);
116 std::string pubKey = strPub.str();
117 std::string privKey = strPriv.str();
118
119 // now do the round trip
120 std::istringstream iPub(pubKey);
121 std::istringstream iPriv(privKey);
122 RSAKey key2(&iPub, &iPriv);
123
124 std::istringstream iPriv2(privKey);
125 RSAKey key3(0, &iPriv2);
126 std::ostringstream strPub3;
127 key3.save(&strPub3);
128 std::string pubFromPrivate = strPub3.str();
129 assertTrue (pubFromPrivate == pubKey);
130}
131
132
133void RSATest::testRSASign()
134{
135 std::string msg("Test this sign message");
136 RSAKey key(RSAKey::KL_2048, RSAKey::EXP_LARGE);
137 RSADigestEngine eng(key);
138 eng.update(msg.c_str(), static_cast<unsigned>(msg.length()));
139 const Poco::DigestEngine::Digest& sig = eng.signature();
140 std::string hexDig = Poco::DigestEngine::digestToHex(sig);
141
142 // verify
143 std::ostringstream strPub;
144 key.save(&strPub);
145 std::string pubKey = strPub.str();
146 std::istringstream iPub(pubKey);
147 RSAKey keyPub(&iPub);
148 RSADigestEngine eng2(keyPub);
149 eng2.update(msg.c_str(), static_cast<unsigned>(msg.length()));
150 assertTrue (eng2.verify(sig));
151}
152
153
154void RSATest::testRSASignSha256()
155{
156 std::string msg("Test this sign message");
157 RSAKey key(RSAKey::KL_2048, RSAKey::EXP_LARGE);
158 RSADigestEngine eng(key, "SHA256");
159 eng.update(msg.c_str(), static_cast<unsigned>(msg.length()));
160 const Poco::DigestEngine::Digest& sig = eng.signature();
161 std::string hexDig = Poco::DigestEngine::digestToHex(sig);
162
163 // verify
164 std::ostringstream strPub;
165 key.save(&strPub);
166 std::string pubKey = strPub.str();
167 std::istringstream iPub(pubKey);
168 RSAKey keyPub(&iPub);
169 RSADigestEngine eng2(keyPub, "SHA256");
170 eng2.update(msg.c_str(), static_cast<unsigned>(msg.length()));
171 assertTrue (eng2.verify(sig));
172}
173
174
175void RSATest::testRSASignManipulated()
176{
177 std::string msg("Test this sign message");
178 std::string msgManip("Test that sign message");
179 RSAKey key(RSAKey::KL_2048, RSAKey::EXP_LARGE);
180 RSADigestEngine eng(key);
181 eng.update(msg.c_str(), static_cast<unsigned>(msg.length()));
182 const Poco::DigestEngine::Digest& sig = eng.signature();
183 std::string hexDig = Poco::DigestEngine::digestToHex(sig);
184
185 // verify
186 std::ostringstream strPub;
187 key.save(&strPub);
188 std::string pubKey = strPub.str();
189 std::istringstream iPub(pubKey);
190 RSAKey keyPub(&iPub);
191 RSADigestEngine eng2(keyPub);
192 eng2.update(msgManip.c_str(), static_cast<unsigned>(msgManip.length()));
193 assertTrue (!eng2.verify(sig));
194}
195
196
197void RSATest::testRSACipher()
198{
199 Cipher::Ptr pCipher = CipherFactory::defaultFactory().createCipher(RSAKey(RSAKey::KL_1024, RSAKey::EXP_SMALL));
200 for (std::size_t n = 1; n <= 1200; n++)
201 {
202 std::string val(n, 'x');
203 std::string enc = pCipher->encryptString(val);
204 std::string dec = pCipher->decryptString(enc);
205 assertTrue (dec == val);
206 }
207}
208
209
210void RSATest::testRSACipherLarge()
211{
212 std::vector<std::size_t> sizes;
213 sizes.push_back (2047);
214 sizes.push_back (2048);
215 sizes.push_back (2049);
216 sizes.push_back (4095);
217 sizes.push_back (4096);
218 sizes.push_back (4097);
219 sizes.push_back (8191);
220 sizes.push_back (8192);
221 sizes.push_back (8193);
222 sizes.push_back (16383);
223 sizes.push_back (16384);
224 sizes.push_back (16385);
225
226 Cipher::Ptr pCipher = CipherFactory::defaultFactory().createCipher(RSAKey(RSAKey::KL_1024, RSAKey::EXP_SMALL));
227 for (std::vector<std::size_t>::const_iterator it = sizes.begin(); it != sizes.end(); ++it)
228 {
229 std::string val(*it, 'x');
230 std::string enc = pCipher->encryptString(val);
231 std::string dec = pCipher->decryptString(enc);
232 assertTrue (dec == val);
233 }
234}
235
236
237void RSATest::testRSACertificate()
238{
239 std::istringstream str(anyPem);
240 X509Certificate cert(str);
241 RSAKey publicKey(cert);
242 std::istringstream str2(anyPem);
243 RSAKey privateKey(0, &str2, "test");
244 Cipher::Ptr pCipher = CipherFactory::defaultFactory().createCipher(publicKey);
245 Cipher::Ptr pCipher2 = CipherFactory::defaultFactory().createCipher(privateKey);
246 std::string val("lets do some encryption");
247
248 std::string enc = pCipher->encryptString(val);
249 std::string dec = pCipher2->decryptString(enc);
250 assertTrue (dec == val);
251}
252
253
254void RSATest::setUp()
255{
256}
257
258
259void RSATest::tearDown()
260{
261}
262
263
264CppUnit::Test* RSATest::suite()
265{
266 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RSATest");
267
268 CppUnit_addTest(pSuite, RSATest, testRSANewKeys);
269 CppUnit_addTest(pSuite, RSATest, testRSANewKeysNoPassphrase);
270 CppUnit_addTest(pSuite, RSATest, testRSASign);
271 CppUnit_addTest(pSuite, RSATest, testRSASignSha256);
272 CppUnit_addTest(pSuite, RSATest, testRSASignManipulated);
273 CppUnit_addTest(pSuite, RSATest, testRSACipher);
274 CppUnit_addTest(pSuite, RSATest, testRSACipherLarge);
275 CppUnit_addTest(pSuite, RSATest, testRSACertificate);
276
277 return pSuite;
278}
279