| 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 | |