blob: 80f25149266eb80e3142a82a485724a72f308232 [file] [log] [blame]
NingSun0c89b3c2018-02-08 08:34:03 -08001/*
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
45CPPUNIT_TEST_SUITE_REGISTRATION(DSATests);
46
47void 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
57void DSATests::tearDown()
58{
59 if (dsa != NULL)
60 {
61 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
62 }
63
64 fflush(stdout);
65}
66
67void 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
105void 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
165void 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
200void 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
280void 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}