NingSun | 0c89b3c | 2018-02-08 08:34:03 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2010 SURFnet bv |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that the following conditions |
| 7 | * are met: |
| 8 | * 1. Redistributions of source code must retain the above copyright |
| 9 | * notice, this list of conditions and the following disclaimer. |
| 10 | * 2. Redistributions in binary form must reproduce the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer in the |
| 12 | * documentation and/or other materials provided with the distribution. |
| 13 | * |
| 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 20 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
| 22 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| 24 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 | */ |
| 26 | |
| 27 | /***************************************************************************** |
| 28 | DSATests.cpp |
| 29 | |
| 30 | Contains test cases to test the RNG class |
| 31 | *****************************************************************************/ |
| 32 | |
| 33 | #include <stdlib.h> |
| 34 | #include <vector> |
| 35 | #include <cppunit/extensions/HelperMacros.h> |
| 36 | #include "DSATests.h" |
| 37 | #include "CryptoFactory.h" |
| 38 | #include "RNG.h" |
| 39 | #include "AsymmetricKeyPair.h" |
| 40 | #include "AsymmetricAlgorithm.h" |
| 41 | #include "DSAParameters.h" |
| 42 | #include "DSAPublicKey.h" |
| 43 | #include "DSAPrivateKey.h" |
| 44 | |
| 45 | CPPUNIT_TEST_SUITE_REGISTRATION(DSATests); |
| 46 | |
| 47 | void DSATests::setUp() |
| 48 | { |
| 49 | dsa = NULL; |
| 50 | |
| 51 | dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA); |
| 52 | |
| 53 | // Check the DSA object |
| 54 | CPPUNIT_ASSERT(dsa != NULL); |
| 55 | } |
| 56 | |
| 57 | void DSATests::tearDown() |
| 58 | { |
| 59 | if (dsa != NULL) |
| 60 | { |
| 61 | CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa); |
| 62 | } |
| 63 | |
| 64 | fflush(stdout); |
| 65 | } |
| 66 | |
| 67 | void DSATests::testKeyGeneration() |
| 68 | { |
| 69 | AsymmetricKeyPair* kp; |
| 70 | |
| 71 | // Key sizes to test |
| 72 | std::vector<size_t> keySizes; |
| 73 | #ifndef WITH_FIPS |
| 74 | keySizes.push_back(1024); |
| 75 | keySizes.push_back(1536); |
| 76 | #else |
| 77 | keySizes.push_back(1024); |
| 78 | #endif |
| 79 | #ifndef WITH_BOTAN |
| 80 | keySizes.push_back(2048); |
| 81 | #endif |
| 82 | |
| 83 | for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) |
| 84 | { |
| 85 | // Generate parameters |
| 86 | DSAParameters* p; |
| 87 | AsymmetricParameters** ap = (AsymmetricParameters**) &p; |
| 88 | |
| 89 | CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) *k)); |
| 90 | |
| 91 | // Generate key-pair |
| 92 | CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p)); |
| 93 | |
| 94 | DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey(); |
| 95 | DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey(); |
| 96 | |
| 97 | CPPUNIT_ASSERT(pub->getBitLength() == *k); |
| 98 | CPPUNIT_ASSERT(priv->getBitLength() == *k); |
| 99 | |
| 100 | dsa->recycleParameters(p); |
| 101 | dsa->recycleKeyPair(kp); |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | void DSATests::testSerialisation() |
| 106 | { |
| 107 | // Generate 1024-bit parameters for testing |
| 108 | DSAParameters* p; |
| 109 | AsymmetricParameters** ap = (AsymmetricParameters**) &p; |
| 110 | |
| 111 | CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) 1024)); |
| 112 | |
| 113 | // Serialise the parameters |
| 114 | ByteString serialisedParams = p->serialise(); |
| 115 | |
| 116 | // Deserialise the parameters |
| 117 | AsymmetricParameters* dP; |
| 118 | |
| 119 | CPPUNIT_ASSERT(dsa->reconstructParameters(&dP, serialisedParams)); |
| 120 | |
| 121 | CPPUNIT_ASSERT(dP->areOfType(DSAParameters::type)); |
| 122 | |
| 123 | DSAParameters* ddP = (DSAParameters*) dP; |
| 124 | |
| 125 | CPPUNIT_ASSERT(p->getP() == ddP->getP()); |
| 126 | CPPUNIT_ASSERT(p->getQ() == ddP->getQ()); |
| 127 | CPPUNIT_ASSERT(p->getG() == ddP->getG()); |
| 128 | |
| 129 | // Generate a key-pair |
| 130 | AsymmetricKeyPair* kp; |
| 131 | |
| 132 | CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, dP)); |
| 133 | |
| 134 | // Serialise the key-pair |
| 135 | ByteString serialisedKP = kp->serialise(); |
| 136 | |
| 137 | // Deserialise the key-pair |
| 138 | AsymmetricKeyPair* dKP; |
| 139 | |
| 140 | CPPUNIT_ASSERT(dsa->reconstructKeyPair(&dKP, serialisedKP)); |
| 141 | |
| 142 | // Check the deserialised key-pair |
| 143 | DSAPrivateKey* privKey = (DSAPrivateKey*) kp->getPrivateKey(); |
| 144 | DSAPublicKey* pubKey = (DSAPublicKey*) kp->getPublicKey(); |
| 145 | |
| 146 | DSAPrivateKey* dPrivKey = (DSAPrivateKey*) dKP->getPrivateKey(); |
| 147 | DSAPublicKey* dPubKey = (DSAPublicKey*) dKP->getPublicKey(); |
| 148 | |
| 149 | CPPUNIT_ASSERT(privKey->getP() == dPrivKey->getP()); |
| 150 | CPPUNIT_ASSERT(privKey->getQ() == dPrivKey->getQ()); |
| 151 | CPPUNIT_ASSERT(privKey->getG() == dPrivKey->getG()); |
| 152 | CPPUNIT_ASSERT(privKey->getX() == dPrivKey->getX()); |
| 153 | |
| 154 | CPPUNIT_ASSERT(pubKey->getP() == dPubKey->getP()); |
| 155 | CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ()); |
| 156 | CPPUNIT_ASSERT(pubKey->getG() == dPubKey->getG()); |
| 157 | CPPUNIT_ASSERT(pubKey->getY() == dPubKey->getY()); |
| 158 | |
| 159 | dsa->recycleParameters(p); |
| 160 | dsa->recycleParameters(dP); |
| 161 | dsa->recycleKeyPair(kp); |
| 162 | dsa->recycleKeyPair(dKP); |
| 163 | } |
| 164 | |
| 165 | void DSATests::testPKCS8() |
| 166 | { |
| 167 | // Generate 1024-bit parameters for testing |
| 168 | AsymmetricParameters* p; |
| 169 | |
| 170 | CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) 1024)); |
| 171 | |
| 172 | // Generate a key-pair |
| 173 | AsymmetricKeyPair* kp; |
| 174 | |
| 175 | CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p)); |
| 176 | CPPUNIT_ASSERT(kp != NULL); |
| 177 | |
| 178 | DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey(); |
| 179 | CPPUNIT_ASSERT(priv != NULL); |
| 180 | |
| 181 | // Encode and decode the private key |
| 182 | ByteString pkcs8 = priv->PKCS8Encode(); |
| 183 | CPPUNIT_ASSERT(pkcs8.size() != 0); |
| 184 | |
| 185 | DSAPrivateKey* dPriv = (DSAPrivateKey*) dsa->newPrivateKey(); |
| 186 | CPPUNIT_ASSERT(dPriv != NULL); |
| 187 | |
| 188 | CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); |
| 189 | |
| 190 | CPPUNIT_ASSERT(priv->getP() == dPriv->getP()); |
| 191 | CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ()); |
| 192 | CPPUNIT_ASSERT(priv->getG() == dPriv->getG()); |
| 193 | CPPUNIT_ASSERT(priv->getX() == dPriv->getX()); |
| 194 | |
| 195 | dsa->recycleParameters(p); |
| 196 | dsa->recycleKeyPair(kp); |
| 197 | dsa->recyclePrivateKey(dPriv); |
| 198 | } |
| 199 | |
| 200 | void DSATests::testSigningVerifying() |
| 201 | { |
| 202 | AsymmetricKeyPair* kp; |
| 203 | |
| 204 | // Key sizes to test |
| 205 | std::vector<size_t> keySizes; |
| 206 | #ifndef WITH_FIPS |
| 207 | keySizes.push_back(1024); |
| 208 | keySizes.push_back(1536); |
| 209 | #else |
| 210 | keySizes.push_back(1024); |
| 211 | #endif |
| 212 | #ifndef WITH_BOTAN |
| 213 | keySizes.push_back(2048); |
| 214 | #endif |
| 215 | |
| 216 | // Mechanisms to test |
| 217 | std::vector<AsymMech::Type> mechanisms; |
| 218 | mechanisms.push_back(AsymMech::DSA_SHA1); |
| 219 | mechanisms.push_back(AsymMech::DSA_SHA224); |
| 220 | mechanisms.push_back(AsymMech::DSA_SHA256); |
| 221 | |
| 222 | for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) |
| 223 | { |
| 224 | // Generate parameters |
| 225 | AsymmetricParameters* p; |
| 226 | |
| 227 | CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) *k)); |
| 228 | |
| 229 | // Generate key-pair |
| 230 | CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p)); |
| 231 | |
| 232 | // Generate some data to sign |
| 233 | ByteString dataToSign; |
| 234 | |
| 235 | RNG* rng = CryptoFactory::i()->getRNG(); |
| 236 | |
| 237 | CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567)); |
| 238 | |
| 239 | // Test mechanisms that perform internal hashing |
| 240 | for (std::vector<AsymMech::Type>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++) |
| 241 | { |
| 242 | ByteString blockSignature, singlePartSignature; |
| 243 | |
| 244 | // Sign the data in blocks |
| 245 | CPPUNIT_ASSERT(dsa->signInit(kp->getPrivateKey(), *m)); |
| 246 | CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(0, 134))); |
| 247 | CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134, 289))); |
| 248 | CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134 + 289))); |
| 249 | CPPUNIT_ASSERT(dsa->signFinal(blockSignature)); |
| 250 | |
| 251 | // Sign the data in one pass |
| 252 | CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m)); |
| 253 | |
| 254 | // Now perform multi-pass verification |
| 255 | CPPUNIT_ASSERT(dsa->verifyInit(kp->getPublicKey(), *m)); |
| 256 | CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(0, 125))); |
| 257 | CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125, 247))); |
| 258 | CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125 + 247))); |
| 259 | CPPUNIT_ASSERT(dsa->verifyFinal(blockSignature)); |
| 260 | |
| 261 | // And single-pass verification |
| 262 | CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m)); |
| 263 | } |
| 264 | |
| 265 | // Test mechanisms that do not perform internal hashing |
| 266 | CPPUNIT_ASSERT(rng->generateRandom(dataToSign, *k >= 2048 ? 32 : 20)); |
| 267 | |
| 268 | // Sign the data |
| 269 | ByteString signature; |
| 270 | CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::DSA)); |
| 271 | |
| 272 | // Verify the signature |
| 273 | CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::DSA)); |
| 274 | |
| 275 | dsa->recycleKeyPair(kp); |
| 276 | dsa->recycleParameters(p); |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | void DSATests::testSignVerifyKnownVector() |
| 281 | { |
| 282 | DSAPublicKey* pubKey1 = (DSAPublicKey*) dsa->newPublicKey(); |
| 283 | DSAPublicKey* pubKey2 = (DSAPublicKey*) dsa->newPublicKey(); |
| 284 | DSAPrivateKey* privKey1 = (DSAPrivateKey*) dsa->newPrivateKey(); |
| 285 | DSAPrivateKey* privKey2 = (DSAPrivateKey*) dsa->newPrivateKey(); |
| 286 | |
| 287 | // Reconstruct public and private key #1 |
| 288 | ByteString p1 = "e0a67598cd1b763bc98c8abb333e5dda0cd3aa0e5e1fb5ba8a7b4eabc10ba338fae06dd4b90fda70d7cf0cb0c638be3341bec0af8a7330a3307ded2299a0ee606df035177a239c34a912c202aa5f83b9c4a7cf0235b5316bfc6efb9a248411258b30b839af172440f32563056cb67a861158ddd90e6a894c72a5bbef9e286c6b"; |
| 289 | ByteString q1 = "e950511eab424b9a19a2aeb4e159b7844c589c4f"; |
| 290 | ByteString g1 = "d29d5121b0423c2769ab21843e5a3240ff19cacc792264e3bb6be4f78edd1b15c4dff7f1d905431f0ab16790e1f773b5ce01c804e509066a9919f5195f4abc58189fd9ff987389cb5bedf21b4dab4f8b76a055ffe2770988fe2ec2de11ad92219f0b351869ac24da3d7ba87011a701ce8ee7bfe49486ed4527b7186ca4610a75"; |
| 291 | ByteString x1 = "d0ec4e50bb290a42e9e355c73d8809345de2e139"; |
| 292 | ByteString y1 = "25282217f5730501dd8dba3edfcf349aaffec20921128d70fac44110332201bba3f10986140cbb97c726938060473c8ec97b4731db004293b5e730363609df9780f8d883d8c4d41ded6a2f1e1bbbdc979e1b9d6d3c940301f4e978d65b19041fcf1e8b518f5c0576c770fe5a7a485d8329ee2914a2de1b5da4a6128ceab70f79"; |
| 293 | |
| 294 | pubKey1->setP(p1); |
| 295 | pubKey1->setQ(q1); |
| 296 | pubKey1->setG(g1); |
| 297 | pubKey1->setY(y1); |
| 298 | privKey1->setP(p1); |
| 299 | privKey1->setQ(q1); |
| 300 | privKey1->setG(g1); |
| 301 | privKey1->setX(x1); |
| 302 | |
| 303 | // Test with key #1 |
| 304 | ByteString data1 = "616263"; // "abc" |
| 305 | ByteString goodSignature1 = "636155ac9a4633b4665d179f9e4117df68601f346c540b02d9d4852f89df8cfc99963204f4347704"; |
| 306 | ByteString badSignature1 = "636155ac9a4633b4665d179f9e4117df68601f346c540b02d9d4852f89df8cfc99963204f4347705"; |
| 307 | |
| 308 | // Reconstruct public and private key #2 |
| 309 | ByteString p2 = "f56c2a7d366e3ebdeaa1891fd2a0d099436438a673fed4d75f594959cffebca7be0fc72e4fe67d91d801cba0693ac4ed9e411b41d19e2fd1699c4390ad27d94c69c0b143f1dc88932cfe2310c886412047bd9b1c7a67f8a25909132627f51a0c866877e672e555342bdf9355347dbd43b47156b2c20bad9d2b071bc2fdcf9757f75c168c5d9fc43131be162a0756d1bdec2ca0eb0e3b018a8b38d3ef2487782aeb9fbf99d8b30499c55e4f61e5c7dcee2a2bb55bd7f75fcdf00e48f2e8356bdb59d86114028f67b8e07b127744778aff1cf1399a4d679d92fde7d941c5c85c5d7bff91ba69f9489d531d1ebfa727cfda651390f8021719fa9f7216ceb177bd75"; |
| 310 | ByteString q2 = "c24ed361870b61e0d367f008f99f8a1f75525889c89db1b673c45af5867cb467"; |
| 311 | ByteString g2 = "8dc6cc814cae4a1c05a3e186a6fe27eaba8cdb133fdce14a963a92e809790cba096eaa26140550c129fa2b98c16e84236aa33bf919cd6f587e048c52666576db6e925c6cbe9b9ec5c16020f9a44c9f1c8f7a8e611c1f6ec2513ea6aa0b8d0f72fed73ca37df240db57bbb27431d618697b9e771b0b301d5df05955425061a30dc6d33bb6d2a32bd0a75a0a71d2184f506372abf84a56aeeea8eb693bf29a640345fa1298a16e85421b2208d00068a5a42915f82cf0b858c8fa39d43d704b6927e0b2f916304e86fb6a1b487f07d8139e428bb096c6d67a76ec0b8d4ef274b8a2cf556d279ad267ccef5af477afed029f485b5597739f5d0240f67c2d948a6279"; |
| 312 | ByteString x2 = "0caf2ef547ec49c4f3a6fe6df4223a174d01f2c115d49a6f73437c29a2a8458c"; |
| 313 | ByteString y2 = "2828003d7c747199143c370fdd07a2861524514acc57f63f80c38c2087c6b795b62de1c224bf8d1d1424e60ce3f5ae3f76c754a2464af292286d873a7a30b7eacbbc75aafde7191d9157598cdb0b60e0c5aa3f6ebe425500c611957dbf5ed35490714a42811fdcdeb19af2ab30beadff2907931cee7f3b55532cffaeb371f84f01347630eb227a419b1f3f558bc8a509d64a765d8987d493b007c4412c297caf41566e26faee475137ec781a0dc088a26c8804a98c23140e7c936281864b99571ee95c416aa38ceebb41fdbff1eb1d1dc97b63ce1355257627c8b0fd840ddb20ed35be92f08c49aea5613957d7e5c7a6d5a5834b4cb069e0831753ecf65ba02b"; |
| 314 | |
| 315 | pubKey2->setP(p2); |
| 316 | pubKey2->setQ(q2); |
| 317 | pubKey2->setG(g2); |
| 318 | pubKey2->setY(y2); |
| 319 | privKey2->setP(p2); |
| 320 | privKey2->setQ(q2); |
| 321 | privKey2->setG(g2); |
| 322 | privKey2->setX(x2); |
| 323 | |
| 324 | // Test with key #2 |
| 325 | ByteString data2 = "616263"; // "abc" |
| 326 | ByteString goodSignature2 = "315c875dcd4850e948b8ac42824e9483a32d5ba5abe0681b9b9448d444f2be3c89718d12e54a8d9ed066e4a55f7ed5a2229cd23b9a3cee78f83ed6aa61f6bcb9"; |
| 327 | ByteString badSignature2 = "315c875dcd4850e948b8ac42824e9483a32d5ba5abe0681b9b9448d444f2be3c89718d12e54a8d9ed066e4a55f7ed5a2229cd23b9a3cee78f83ed6aa61f6bcb8"; |
| 328 | |
| 329 | CPPUNIT_ASSERT(dsa->verify(pubKey1, data1, goodSignature1, AsymMech::DSA_SHA1)); |
| 330 | CPPUNIT_ASSERT(!dsa->verify(pubKey1, data1, badSignature1, AsymMech::DSA_SHA1)); |
| 331 | CPPUNIT_ASSERT(dsa->verify(pubKey2, data2, goodSignature2, AsymMech::DSA_SHA256)); |
| 332 | CPPUNIT_ASSERT(!dsa->verify(pubKey2, data2, badSignature2, AsymMech::DSA_SHA256)); |
| 333 | |
| 334 | dsa->recyclePublicKey(pubKey1); |
| 335 | dsa->recyclePublicKey(pubKey2); |
| 336 | dsa->recyclePrivateKey(privKey1); |
| 337 | dsa->recyclePrivateKey(privKey2); |
| 338 | } |