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 | |
22 | using namespace Poco::Crypto; |
23 | |
24 | |
25 | static 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 | |
77 | RSATest::RSATest(const std::string& name): CppUnit::TestCase(name) |
78 | { |
79 | } |
80 | |
81 | |
82 | RSATest::~RSATest() |
83 | { |
84 | } |
85 | |
86 | |
87 | void 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 | |
110 | void 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 | |
133 | void 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 | |
154 | void 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 | |
175 | void 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 | |
197 | void 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 | |
210 | void 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 | |
237 | void 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 | |
254 | void RSATest::setUp() |
255 | { |
256 | } |
257 | |
258 | |
259 | void RSATest::tearDown() |
260 | { |
261 | } |
262 | |
263 | |
264 | CppUnit::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 | |