1// validat2.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4
5#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
6#include "blumshub.h"
7#include "rsa.h"
8#include "md2.h"
9#include "elgamal.h"
10#include "nr.h"
11#include "dsa.h"
12#include "dh.h"
13#include "mqv.h"
14#include "luc.h"
15#include "xtrcrypt.h"
16#include "rabin.h"
17#include "rw.h"
18#include "eccrypto.h"
19#include "ecp.h"
20#include "ec2n.h"
21#include "asn.h"
22#include "rng.h"
23#include "files.h"
24#include "hex.h"
25#include "oids.h"
26#include "esign.h"
27#include "osrng.h"
28
29#include <iostream>
30#include <iomanip>
31
32#include "validate.h"
33
34USING_NAMESPACE(CryptoPP)
35USING_NAMESPACE(std)
36
37class FixedRNG : public RandomNumberGenerator
38{
39public:
40	FixedRNG(BufferedTransformation &source) : m_source(source) {}
41
42	void GenerateBlock(byte *output, size_t size)
43	{
44		m_source.Get(output, size);
45	}
46
47private:
48	BufferedTransformation &m_source;
49};
50
51bool ValidateBBS()
52{
53	cout << "\nBlumBlumShub validation suite running...\n\n";
54
55	Integer p("212004934506826557583707108431463840565872545889679278744389317666981496005411448865750399674653351");
56	Integer q("100677295735404212434355574418077394581488455772477016953458064183204108039226017738610663984508231");
57	Integer seed("63239752671357255800299643604761065219897634268887145610573595874544114193025997412441121667211431");
58	BlumBlumShub bbs(p, q, seed);
59	bool pass = true, fail;
60	int j;
61
62	const byte output1[] = {
63		0x49,0xEA,0x2C,0xFD,0xB0,0x10,0x64,0xA0,0xBB,0xB9,
64		0x2A,0xF1,0x01,0xDA,0xC1,0x8A,0x94,0xF7,0xB7,0xCE};
65	const byte output2[] = {
66		0x74,0x45,0x48,0xAE,0xAC,0xB7,0x0E,0xDF,0xAF,0xD7,
67		0xD5,0x0E,0x8E,0x29,0x83,0x75,0x6B,0x27,0x46,0xA1};
68
69	byte buf[20];
70
71	bbs.GenerateBlock(buf, 20);
72	fail = memcmp(output1, buf, 20) != 0;
73	pass = pass && !fail;
74
75	cout << (fail ? "FAILED    " : "passed    ");
76	for (j=0;j<20;j++)
77		cout << setw(2) << setfill('0') << hex << (int)buf[j];
78	cout << endl;
79
80	bbs.Seek(10);
81	bbs.GenerateBlock(buf, 10);
82	fail = memcmp(output1+10, buf, 10) != 0;
83	pass = pass && !fail;
84
85	cout << (fail ? "FAILED    " : "passed    ");
86	for (j=0;j<10;j++)
87		cout << setw(2) << setfill('0') << hex << (int)buf[j];
88	cout << endl;
89
90	bbs.Seek(1234567);
91	bbs.GenerateBlock(buf, 20);
92	fail = memcmp(output2, buf, 20) != 0;
93	pass = pass && !fail;
94
95	cout << (fail ? "FAILED    " : "passed    ");
96	for (j=0;j<20;j++)
97		cout << setw(2) << setfill('0') << hex << (int)buf[j];
98	cout << endl;
99
100	return pass;
101}
102
103bool SignatureValidate(PK_Signer &priv, PK_Verifier &pub, bool thorough = false)
104{
105	bool pass = true, fail;
106
107	fail = !pub.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2) || !priv.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2);
108	pass = pass && !fail;
109
110	cout << (fail ? "FAILED    " : "passed    ");
111	cout << "signature key validation\n";
112
113	const byte *message = (byte *)"test message";
114	const int messageLen = 12;
115
116	SecByteBlock signature(priv.MaxSignatureLength());
117	size_t signatureLength = priv.SignMessage(GlobalRNG(), message, messageLen, signature);
118	fail = !pub.VerifyMessage(message, messageLen, signature, signatureLength);
119	pass = pass && !fail;
120
121	cout << (fail ? "FAILED    " : "passed    ");
122	cout << "signature and verification\n";
123
124	++signature[0];
125	fail = pub.VerifyMessage(message, messageLen, signature, signatureLength);
126	pass = pass && !fail;
127
128	cout << (fail ? "FAILED    " : "passed    ");
129	cout << "checking invalid signature" << endl;
130
131	if (priv.MaxRecoverableLength() > 0)
132	{
133		signatureLength = priv.SignMessageWithRecovery(GlobalRNG(), message, messageLen, NULL, 0, signature);
134		SecByteBlock recovered(priv.MaxRecoverableLengthFromSignatureLength(signatureLength));
135		DecodingResult result = pub.RecoverMessage(recovered, NULL, 0, signature, signatureLength);
136		fail = !(result.isValidCoding && result.messageLength == messageLen && memcmp(recovered, message, messageLen) == 0);
137		pass = pass && !fail;
138
139		cout << (fail ? "FAILED    " : "passed    ");
140		cout << "signature and verification with recovery" << endl;
141
142		++signature[0];
143		result = pub.RecoverMessage(recovered, NULL, 0, signature, signatureLength);
144		fail = result.isValidCoding;
145		pass = pass && !fail;
146
147		cout << (fail ? "FAILED    " : "passed    ");
148		cout << "recovery with invalid signature" << endl;
149	}
150
151	return pass;
152}
153
154bool CryptoSystemValidate(PK_Decryptor &priv, PK_Encryptor &pub, bool thorough = false)
155{
156	bool pass = true, fail;
157
158	fail = !pub.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2) || !priv.GetMaterial().Validate(GlobalRNG(), thorough ? 3 : 2);
159	pass = pass && !fail;
160
161	cout << (fail ? "FAILED    " : "passed    ");
162	cout << "cryptosystem key validation\n";
163
164	const byte *message = (byte *)"test message";
165	const int messageLen = 12;
166	SecByteBlock ciphertext(priv.CiphertextLength(messageLen));
167	SecByteBlock plaintext(priv.MaxPlaintextLength(ciphertext.size()));
168
169	pub.Encrypt(GlobalRNG(), message, messageLen, ciphertext);
170	fail = priv.Decrypt(GlobalRNG(), ciphertext, priv.CiphertextLength(messageLen), plaintext) != DecodingResult(messageLen);
171	fail = fail || memcmp(message, plaintext, messageLen);
172	pass = pass && !fail;
173
174	cout << (fail ? "FAILED    " : "passed    ");
175	cout << "encryption and decryption\n";
176
177	return pass;
178}
179
180bool SimpleKeyAgreementValidate(SimpleKeyAgreementDomain &d)
181{
182	if (d.GetCryptoParameters().Validate(GlobalRNG(), 3))
183		cout << "passed    simple key agreement domain parameters validation" << endl;
184	else
185	{
186		cout << "FAILED    simple key agreement domain parameters invalid" << endl;
187		return false;
188	}
189
190	SecByteBlock priv1(d.PrivateKeyLength()), priv2(d.PrivateKeyLength());
191	SecByteBlock pub1(d.PublicKeyLength()), pub2(d.PublicKeyLength());
192	SecByteBlock val1(d.AgreedValueLength()), val2(d.AgreedValueLength());
193
194	d.GenerateKeyPair(GlobalRNG(), priv1, pub1);
195	d.GenerateKeyPair(GlobalRNG(), priv2, pub2);
196
197	memset(val1.begin(), 0x10, val1.size());
198	memset(val2.begin(), 0x11, val2.size());
199
200	if (!(d.Agree(val1, priv1, pub2) && d.Agree(val2, priv2, pub1)))
201	{
202		cout << "FAILED    simple key agreement failed" << endl;
203		return false;
204	}
205
206	if (memcmp(val1.begin(), val2.begin(), d.AgreedValueLength()))
207	{
208		cout << "FAILED    simple agreed values not equal" << endl;
209		return false;
210	}
211
212	cout << "passed    simple key agreement" << endl;
213	return true;
214}
215
216bool AuthenticatedKeyAgreementValidate(AuthenticatedKeyAgreementDomain &d)
217{
218	if (d.GetCryptoParameters().Validate(GlobalRNG(), 3))
219		cout << "passed    authenticated key agreement domain parameters validation" << endl;
220	else
221	{
222		cout << "FAILED    authenticated key agreement domain parameters invalid" << endl;
223		return false;
224	}
225
226	SecByteBlock spriv1(d.StaticPrivateKeyLength()), spriv2(d.StaticPrivateKeyLength());
227	SecByteBlock epriv1(d.EphemeralPrivateKeyLength()), epriv2(d.EphemeralPrivateKeyLength());
228	SecByteBlock spub1(d.StaticPublicKeyLength()), spub2(d.StaticPublicKeyLength());
229	SecByteBlock epub1(d.EphemeralPublicKeyLength()), epub2(d.EphemeralPublicKeyLength());
230	SecByteBlock val1(d.AgreedValueLength()), val2(d.AgreedValueLength());
231
232	d.GenerateStaticKeyPair(GlobalRNG(), spriv1, spub1);
233	d.GenerateStaticKeyPair(GlobalRNG(), spriv2, spub2);
234	d.GenerateEphemeralKeyPair(GlobalRNG(), epriv1, epub1);
235	d.GenerateEphemeralKeyPair(GlobalRNG(), epriv2, epub2);
236
237	memset(val1.begin(), 0x10, val1.size());
238	memset(val2.begin(), 0x11, val2.size());
239
240	if (!(d.Agree(val1, spriv1, epriv1, spub2, epub2) && d.Agree(val2, spriv2, epriv2, spub1, epub1)))
241	{
242		cout << "FAILED    authenticated key agreement failed" << endl;
243		return false;
244	}
245
246	if (memcmp(val1.begin(), val2.begin(), d.AgreedValueLength()))
247	{
248		cout << "FAILED    authenticated agreed values not equal" << endl;
249		return false;
250	}
251
252	cout << "passed    authenticated key agreement" << endl;
253	return true;
254}
255
256bool ValidateRSA()
257{
258	cout << "\nRSA validation suite running...\n\n";
259
260	byte out[100], outPlain[100];
261	bool pass = true, fail;
262
263	{
264		const char *plain = "Everyone gets Friday off.";
265		byte *signature = (byte *)
266			"\x05\xfa\x6a\x81\x2f\xc7\xdf\x8b\xf4\xf2\x54\x25\x09\xe0\x3e\x84"
267			"\x6e\x11\xb9\xc6\x20\xbe\x20\x09\xef\xb4\x40\xef\xbc\xc6\x69\x21"
268			"\x69\x94\xac\x04\xf3\x41\xb5\x7d\x05\x20\x2d\x42\x8f\xb2\xa2\x7b"
269			"\x5c\x77\xdf\xd9\xb1\x5b\xfc\x3d\x55\x93\x53\x50\x34\x10\xc1\xe1";
270
271		FileSource keys("TestData/rsa512a.dat", true, new HexDecoder);
272		Weak::RSASSA_PKCS1v15_MD2_Signer rsaPriv(keys);
273		Weak::RSASSA_PKCS1v15_MD2_Verifier rsaPub(rsaPriv);
274
275		size_t signatureLength = rsaPriv.SignMessage(GlobalRNG(), (byte *)plain, strlen(plain), out);
276		fail = memcmp(signature, out, 64) != 0;
277		pass = pass && !fail;
278
279		cout << (fail ? "FAILED    " : "passed    ");
280		cout << "signature check against test vector\n";
281
282		fail = !rsaPub.VerifyMessage((byte *)plain, strlen(plain), out, signatureLength);
283		pass = pass && !fail;
284
285		cout << (fail ? "FAILED    " : "passed    ");
286		cout << "verification check against test vector\n";
287
288		out[10]++;
289		fail = rsaPub.VerifyMessage((byte *)plain, strlen(plain), out, signatureLength);
290		pass = pass && !fail;
291
292		cout << (fail ? "FAILED    " : "passed    ");
293		cout << "invalid signature verification\n";
294	}
295	{
296		FileSource keys("TestData/rsa1024.dat", true, new HexDecoder);
297		RSAES_PKCS1v15_Decryptor rsaPriv(keys);
298		RSAES_PKCS1v15_Encryptor rsaPub(rsaPriv);
299
300		pass = CryptoSystemValidate(rsaPriv, rsaPub) && pass;
301	}
302	{
303		RSAES<OAEP<SHA> >::Decryptor rsaPriv(GlobalRNG(), 512);
304		RSAES<OAEP<SHA> >::Encryptor rsaPub(rsaPriv);
305
306		pass = CryptoSystemValidate(rsaPriv, rsaPub) && pass;
307	}
308	{
309		byte *plain = (byte *)
310			"\x54\x85\x9b\x34\x2c\x49\xea\x2a";
311		byte *encrypted = (byte *)
312			"\x14\xbd\xdd\x28\xc9\x83\x35\x19\x23\x80\xe8\xe5\x49\xb1\x58\x2a"
313			"\x8b\x40\xb4\x48\x6d\x03\xa6\xa5\x31\x1f\x1f\xd5\xf0\xa1\x80\xe4"
314			"\x17\x53\x03\x29\xa9\x34\x90\x74\xb1\x52\x13\x54\x29\x08\x24\x52"
315			"\x62\x51";
316		byte *oaepSeed = (byte *)
317			"\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2"
318			"\xf0\x6c\xb5\x8f";
319		ByteQueue bq;
320		bq.Put(oaepSeed, 20);
321		FixedRNG rng(bq);
322
323		FileSource privFile("TestData/rsa400pv.dat", true, new HexDecoder);
324		FileSource pubFile("TestData/rsa400pb.dat", true, new HexDecoder);
325		RSAES_OAEP_SHA_Decryptor rsaPriv;
326		rsaPriv.AccessKey().BERDecodePrivateKey(privFile, false, 0);
327		RSAES_OAEP_SHA_Encryptor rsaPub(pubFile);
328
329		memset(out, 0, 50);
330		memset(outPlain, 0, 8);
331		rsaPub.Encrypt(rng, plain, 8, out);
332		DecodingResult result = rsaPriv.FixedLengthDecrypt(GlobalRNG(), encrypted, outPlain);
333		fail = !result.isValidCoding || (result.messageLength!=8) || memcmp(out, encrypted, 50) || memcmp(plain, outPlain, 8);
334		pass = pass && !fail;
335
336		cout << (fail ? "FAILED    " : "passed    ");
337		cout << "PKCS 2.0 encryption and decryption\n";
338	}
339
340	return pass;
341}
342
343bool ValidateDH()
344{
345	cout << "\nDH validation suite running...\n\n";
346
347	FileSource f("TestData/dh1024.dat", true, new HexDecoder());
348	DH dh(f);
349	return SimpleKeyAgreementValidate(dh);
350}
351
352bool ValidateMQV()
353{
354	cout << "\nMQV validation suite running...\n\n";
355
356	FileSource f("TestData/mqv1024.dat", true, new HexDecoder());
357	MQV mqv(f);
358	return AuthenticatedKeyAgreementValidate(mqv);
359}
360
361bool ValidateLUC_DH()
362{
363	cout << "\nLUC-DH validation suite running...\n\n";
364
365	FileSource f("TestData/lucd512.dat", true, new HexDecoder());
366	LUC_DH dh(f);
367	return SimpleKeyAgreementValidate(dh);
368}
369
370bool ValidateXTR_DH()
371{
372	cout << "\nXTR-DH validation suite running...\n\n";
373
374	FileSource f("TestData/xtrdh171.dat", true, new HexDecoder());
375	XTR_DH dh(f);
376	return SimpleKeyAgreementValidate(dh);
377}
378
379bool ValidateElGamal()
380{
381	cout << "\nElGamal validation suite running...\n\n";
382	bool pass = true;
383	{
384		FileSource fc("TestData/elgc1024.dat", true, new HexDecoder);
385		ElGamalDecryptor privC(fc);
386		ElGamalEncryptor pubC(privC);
387		privC.AccessKey().Precompute();
388		ByteQueue queue;
389		privC.AccessKey().SavePrecomputation(queue);
390		privC.AccessKey().LoadPrecomputation(queue);
391
392		pass = CryptoSystemValidate(privC, pubC) && pass;
393	}
394	return pass;
395}
396
397bool ValidateDLIES()
398{
399	cout << "\nDLIES validation suite running...\n\n";
400	bool pass = true;
401	{
402		FileSource fc("TestData/dlie1024.dat", true, new HexDecoder);
403		DLIES<>::Decryptor privC(fc);
404		DLIES<>::Encryptor pubC(privC);
405		pass = CryptoSystemValidate(privC, pubC) && pass;
406	}
407	{
408		cout << "Generating new encryption key..." << endl;
409		DLIES<>::GroupParameters gp;
410		gp.GenerateRandomWithKeySize(GlobalRNG(), 128);
411		DLIES<>::Decryptor decryptor;
412		decryptor.AccessKey().GenerateRandom(GlobalRNG(), gp);
413		DLIES<>::Encryptor encryptor(decryptor);
414
415		pass = CryptoSystemValidate(decryptor, encryptor) && pass;
416	}
417	return pass;
418}
419
420bool ValidateNR()
421{
422	cout << "\nNR validation suite running...\n\n";
423	bool pass = true;
424	{
425		FileSource f("TestData/nr2048.dat", true, new HexDecoder);
426		NR<SHA>::Signer privS(f);
427		privS.AccessKey().Precompute();
428		NR<SHA>::Verifier pubS(privS);
429
430		pass = SignatureValidate(privS, pubS) && pass;
431	}
432	{
433		cout << "Generating new signature key..." << endl;
434		NR<SHA>::Signer privS(GlobalRNG(), 256);
435		NR<SHA>::Verifier pubS(privS);
436
437		pass = SignatureValidate(privS, pubS) && pass;
438	}
439	return pass;
440}
441
442bool ValidateDSA(bool thorough)
443{
444	cout << "\nDSA validation suite running...\n\n";
445
446	bool pass = true, fail;
447	{
448	FileSource fs("TestData/dsa512.dat", true, new HexDecoder());
449	GDSA<SHA>::Signer priv(fs);
450	priv.AccessKey().Precompute(16);
451	GDSA<SHA>::Verifier pub(priv);
452
453	byte seed[]={0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21,
454				 0x1b, 0x40, 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3};
455	Integer k("358dad57 1462710f 50e254cf 1a376b2b deaadfbfh");
456	Integer h("a9993e36 4706816a ba3e2571 7850c26c 9cd0d89dh");
457	byte sig[]={0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, 0x43, 0x5c, 0xb7, 0x18,
458				0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, 0xb3, 0x41, 0xc0,
459				0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, 0xdf, 0x24, 0x58, 0xf4,
460				0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, 0xdc, 0xd8, 0xc8};
461	Integer r(sig, 20);
462	Integer s(sig+20, 20);
463
464	Integer pGen, qGen, rOut, sOut;
465	int c;
466
467	fail = !DSA::GeneratePrimes(seed, 160, c, pGen, 512, qGen);
468	fail = fail || (pGen != pub.GetKey().GetGroupParameters().GetModulus()) || (qGen != pub.GetKey().GetGroupParameters().GetSubgroupOrder());
469	pass = pass && !fail;
470
471	cout << (fail ? "FAILED    " : "passed    ");
472	cout << "prime generation test\n";
473
474	priv.RawSign(k, h, rOut, sOut);
475	fail = (rOut != r) || (sOut != s);
476	pass = pass && !fail;
477
478	cout << (fail ? "FAILED    " : "passed    ");
479	cout << "signature check against test vector\n";
480
481	fail = !pub.VerifyMessage((byte *)"abc", 3, sig, sizeof(sig));
482	pass = pass && !fail;
483
484	cout << (fail ? "FAILED    " : "passed    ");
485	cout << "verification check against test vector\n";
486
487	fail = pub.VerifyMessage((byte *)"xyz", 3, sig, sizeof(sig));
488	pass = pass && !fail;
489	}
490	FileSource fs1("TestData/dsa1024.dat", true, new HexDecoder());
491	DSA::Signer priv(fs1);
492	DSA::Verifier pub(priv);
493	FileSource fs2("TestData/dsa1024b.dat", true, new HexDecoder());
494	DSA::Verifier pub1(fs2);
495	assert(pub.GetKey() == pub1.GetKey());
496	pass = SignatureValidate(priv, pub, thorough) && pass;
497	return pass;
498}
499
500bool ValidateLUC()
501{
502	cout << "\nLUC validation suite running...\n\n";
503	bool pass=true;
504
505	{
506		FileSource f("TestData/luc1024.dat", true, new HexDecoder);
507		LUCSSA_PKCS1v15_SHA_Signer priv(f);
508		LUCSSA_PKCS1v15_SHA_Verifier pub(priv);
509		pass = SignatureValidate(priv, pub) && pass;
510	}
511	{
512		LUCES_OAEP_SHA_Decryptor priv(GlobalRNG(), 512);
513		LUCES_OAEP_SHA_Encryptor pub(priv);
514		pass = CryptoSystemValidate(priv, pub) && pass;
515	}
516	return pass;
517}
518
519bool ValidateLUC_DL()
520{
521	cout << "\nLUC-HMP validation suite running...\n\n";
522
523	FileSource f("TestData/lucs512.dat", true, new HexDecoder);
524	LUC_HMP<SHA>::Signer privS(f);
525	LUC_HMP<SHA>::Verifier pubS(privS);
526	bool pass = SignatureValidate(privS, pubS);
527
528	cout << "\nLUC-IES validation suite running...\n\n";
529
530	FileSource fc("TestData/lucc512.dat", true, new HexDecoder);
531	LUC_IES<>::Decryptor privC(fc);
532	LUC_IES<>::Encryptor pubC(privC);
533	pass = CryptoSystemValidate(privC, pubC) && pass;
534
535	return pass;
536}
537
538bool ValidateRabin()
539{
540	cout << "\nRabin validation suite running...\n\n";
541	bool pass=true;
542
543	{
544		FileSource f("TestData/rabi1024.dat", true, new HexDecoder);
545		RabinSS<PSSR, SHA>::Signer priv(f);
546		RabinSS<PSSR, SHA>::Verifier pub(priv);
547		pass = SignatureValidate(priv, pub) && pass;
548	}
549	{
550		RabinES<OAEP<SHA> >::Decryptor priv(GlobalRNG(), 512);
551		RabinES<OAEP<SHA> >::Encryptor pub(priv);
552		pass = CryptoSystemValidate(priv, pub) && pass;
553	}
554	return pass;
555}
556
557bool ValidateRW()
558{
559	cout << "\nRW validation suite running...\n\n";
560
561	FileSource f("TestData/rw1024.dat", true, new HexDecoder);
562	RWSS<PSSR, SHA>::Signer priv(f);
563	RWSS<PSSR, SHA>::Verifier pub(priv);
564
565	return SignatureValidate(priv, pub);
566}
567
568/*
569bool ValidateBlumGoldwasser()
570{
571	cout << "\nBlumGoldwasser validation suite running...\n\n";
572
573	FileSource f("TestData/blum512.dat", true, new HexDecoder);
574	BlumGoldwasserPrivateKey priv(f);
575	BlumGoldwasserPublicKey pub(priv);
576
577	return CryptoSystemValidate(priv, pub);
578}
579*/
580
581bool ValidateECP()
582{
583	cout << "\nECP validation suite running...\n\n";
584
585	ECIES<ECP>::Decryptor cpriv(GlobalRNG(), ASN1::secp192r1());
586	ECIES<ECP>::Encryptor cpub(cpriv);
587	ByteQueue bq;
588	cpriv.GetKey().DEREncode(bq);
589	cpub.AccessKey().AccessGroupParameters().SetEncodeAsOID(true);
590	cpub.GetKey().DEREncode(bq);
591	ECDSA<ECP, SHA>::Signer spriv(bq);
592	ECDSA<ECP, SHA>::Verifier spub(bq);
593	ECDH<ECP>::Domain ecdhc(ASN1::secp192r1());
594	ECMQV<ECP>::Domain ecmqvc(ASN1::secp192r1());
595
596	spriv.AccessKey().Precompute();
597	ByteQueue queue;
598	spriv.AccessKey().SavePrecomputation(queue);
599	spriv.AccessKey().LoadPrecomputation(queue);
600
601	bool pass = SignatureValidate(spriv, spub);
602	cpub.AccessKey().Precompute();
603	cpriv.AccessKey().Precompute();
604	pass = CryptoSystemValidate(cpriv, cpub) && pass;
605	pass = SimpleKeyAgreementValidate(ecdhc) && pass;
606	pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass;
607
608	cout << "Turning on point compression..." << endl;
609	cpriv.AccessKey().AccessGroupParameters().SetPointCompression(true);
610	cpub.AccessKey().AccessGroupParameters().SetPointCompression(true);
611	ecdhc.AccessGroupParameters().SetPointCompression(true);
612	ecmqvc.AccessGroupParameters().SetPointCompression(true);
613	pass = CryptoSystemValidate(cpriv, cpub) && pass;
614	pass = SimpleKeyAgreementValidate(ecdhc) && pass;
615	pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass;
616
617	cout << "Testing SEC 2, NIST, and Brainpool recommended curves..." << endl;
618	OID oid;
619	while (!(oid = DL_GroupParameters_EC<ECP>::GetNextRecommendedParametersOID(oid)).m_values.empty())
620	{
621		DL_GroupParameters_EC<ECP> params(oid);
622		bool fail = !params.Validate(GlobalRNG(), 2);
623		cout << (fail ? "FAILED" : "passed") << "    " << dec << params.GetCurve().GetField().MaxElementBitLength() << " bits" << endl;
624		pass = pass && !fail;
625	}
626
627	return pass;
628}
629
630bool ValidateEC2N()
631{
632	cout << "\nEC2N validation suite running...\n\n";
633
634	ECIES<EC2N>::Decryptor cpriv(GlobalRNG(), ASN1::sect193r1());
635	ECIES<EC2N>::Encryptor cpub(cpriv);
636	ByteQueue bq;
637	cpriv.DEREncode(bq);
638	cpub.AccessKey().AccessGroupParameters().SetEncodeAsOID(true);
639	cpub.DEREncode(bq);
640	ECDSA<EC2N, SHA>::Signer spriv(bq);
641	ECDSA<EC2N, SHA>::Verifier spub(bq);
642	ECDH<EC2N>::Domain ecdhc(ASN1::sect193r1());
643	ECMQV<EC2N>::Domain ecmqvc(ASN1::sect193r1());
644
645	spriv.AccessKey().Precompute();
646	ByteQueue queue;
647	spriv.AccessKey().SavePrecomputation(queue);
648	spriv.AccessKey().LoadPrecomputation(queue);
649
650	bool pass = SignatureValidate(spriv, spub);
651	pass = CryptoSystemValidate(cpriv, cpub) && pass;
652	pass = SimpleKeyAgreementValidate(ecdhc) && pass;
653	pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass;
654
655	cout << "Turning on point compression..." << endl;
656	cpriv.AccessKey().AccessGroupParameters().SetPointCompression(true);
657	cpub.AccessKey().AccessGroupParameters().SetPointCompression(true);
658	ecdhc.AccessGroupParameters().SetPointCompression(true);
659	ecmqvc.AccessGroupParameters().SetPointCompression(true);
660	pass = CryptoSystemValidate(cpriv, cpub) && pass;
661	pass = SimpleKeyAgreementValidate(ecdhc) && pass;
662	pass = AuthenticatedKeyAgreementValidate(ecmqvc) && pass;
663
664#if 0	// TODO: turn this back on when I make EC2N faster for pentanomial basis
665	cout << "Testing SEC 2 recommended curves..." << endl;
666	OID oid;
667	while (!(oid = DL_GroupParameters_EC<EC2N>::GetNextRecommendedParametersOID(oid)).m_values.empty())
668	{
669		DL_GroupParameters_EC<EC2N> params(oid);
670		bool fail = !params.Validate(GlobalRNG(), 2);
671		cout << (fail ? "FAILED" : "passed") << "    " << params.GetCurve().GetField().MaxElementBitLength() << " bits" << endl;
672		pass = pass && !fail;
673	}
674#endif
675
676	return pass;
677}
678
679bool ValidateECDSA()
680{
681	cout << "\nECDSA validation suite running...\n\n";
682
683	// from Sample Test Vectors for P1363
684	GF2NT gf2n(191, 9, 0);
685	byte a[]="\x28\x66\x53\x7B\x67\x67\x52\x63\x6A\x68\xF5\x65\x54\xE1\x26\x40\x27\x6B\x64\x9E\xF7\x52\x62\x67";
686	byte b[]="\x2E\x45\xEF\x57\x1F\x00\x78\x6F\x67\xB0\x08\x1B\x94\x95\xA3\xD9\x54\x62\xF5\xDE\x0A\xA1\x85\xEC";
687	EC2N ec(gf2n, PolynomialMod2(a,24), PolynomialMod2(b,24));
688
689	EC2N::Point P;
690	ec.DecodePoint(P, (byte *)"\x04\x36\xB3\xDA\xF8\xA2\x32\x06\xF9\xC4\xF2\x99\xD7\xB2\x1A\x9C\x36\x91\x37\xF2\xC8\x4A\xE1\xAA\x0D"
691		"\x76\x5B\xE7\x34\x33\xB3\xF9\x5E\x33\x29\x32\xE7\x0E\xA2\x45\xCA\x24\x18\xEA\x0E\xF9\x80\x18\xFB", ec.EncodedPointSize());
692	Integer n("40000000000000000000000004a20e90c39067c893bbb9a5H");
693	Integer d("340562e1dda332f9d2aec168249b5696ee39d0ed4d03760fH");
694	EC2N::Point Q(ec.Multiply(d, P));
695	ECDSA<EC2N, SHA>::Signer priv(ec, P, n, d);
696	ECDSA<EC2N, SHA>::Verifier pub(priv);
697
698	Integer h("A9993E364706816ABA3E25717850C26C9CD0D89DH");
699	Integer k("3eeace72b4919d991738d521879f787cb590aff8189d2b69H");
700	byte sig[]="\x03\x8e\x5a\x11\xfb\x55\xe4\xc6\x54\x71\xdc\xd4\x99\x84\x52\xb1\xe0\x2d\x8a\xf7\x09\x9b\xb9\x30"
701		"\x0c\x9a\x08\xc3\x44\x68\xc2\x44\xb4\xe5\xd6\xb2\x1b\x3c\x68\x36\x28\x07\x41\x60\x20\x32\x8b\x6e";
702	Integer r(sig, 24);
703	Integer s(sig+24, 24);
704
705	Integer rOut, sOut;
706	bool fail, pass=true;
707
708	priv.RawSign(k, h, rOut, sOut);
709	fail = (rOut != r) || (sOut != s);
710	pass = pass && !fail;
711
712	cout << (fail ? "FAILED    " : "passed    ");
713	cout << "signature check against test vector\n";
714
715	fail = !pub.VerifyMessage((byte *)"abc", 3, sig, sizeof(sig));
716	pass = pass && !fail;
717
718	cout << (fail ? "FAILED    " : "passed    ");
719	cout << "verification check against test vector\n";
720
721	fail = pub.VerifyMessage((byte *)"xyz", 3, sig, sizeof(sig));
722	pass = pass && !fail;
723
724	pass = SignatureValidate(priv, pub) && pass;
725
726	return pass;
727}
728
729bool ValidateESIGN()
730{
731	cout << "\nESIGN validation suite running...\n\n";
732
733	bool pass = true, fail;
734
735	const char *plain = "test";
736	const byte *signature = (byte *)
737		"\xA3\xE3\x20\x65\xDE\xDA\xE7\xEC\x05\xC1\xBF\xCD\x25\x79\x7D\x99\xCD\xD5\x73\x9D\x9D\xF3\xA4\xAA\x9A\xA4\x5A\xC8\x23\x3D\x0D\x37\xFE\xBC\x76\x3F\xF1\x84\xF6\x59"
738		"\x14\x91\x4F\x0C\x34\x1B\xAE\x9A\x5C\x2E\x2E\x38\x08\x78\x77\xCB\xDC\x3C\x7E\xA0\x34\x44\x5B\x0F\x67\xD9\x35\x2A\x79\x47\x1A\x52\x37\x71\xDB\x12\x67\xC1\xB6\xC6"
739		"\x66\x73\xB3\x40\x2E\xD6\xF2\x1A\x84\x0A\xB6\x7B\x0F\xEB\x8B\x88\xAB\x33\xDD\xE4\x83\x21\x90\x63\x2D\x51\x2A\xB1\x6F\xAB\xA7\x5C\xFD\x77\x99\xF2\xE1\xEF\x67\x1A"
740		"\x74\x02\x37\x0E\xED\x0A\x06\xAD\xF4\x15\x65\xB8\xE1\xD1\x45\xAE\x39\x19\xB4\xFF\x5D\xF1\x45\x7B\xE0\xFE\x72\xED\x11\x92\x8F\x61\x41\x4F\x02\x00\xF2\x76\x6F\x7C"
741		"\x79\xA2\xE5\x52\x20\x5D\x97\x5E\xFE\x39\xAE\x21\x10\xFB\x35\xF4\x80\x81\x41\x13\xDD\xE8\x5F\xCA\x1E\x4F\xF8\x9B\xB2\x68\xFB\x28";
742
743	FileSource keys("TestData/esig1536.dat", true, new HexDecoder);
744	ESIGN<SHA>::Signer signer(keys);
745	ESIGN<SHA>::Verifier verifier(signer);
746
747	fail = !SignatureValidate(signer, verifier);
748	pass = pass && !fail;
749
750	fail = !verifier.VerifyMessage((byte *)plain, strlen(plain), signature, verifier.SignatureLength());
751	pass = pass && !fail;
752
753	cout << (fail ? "FAILED    " : "passed    ");
754	cout << "verification check against test vector\n";
755
756	cout << "Generating signature key from seed..." << endl;
757	signer.AccessKey().GenerateRandom(GlobalRNG(), MakeParameters("Seed", ConstByteArrayParameter((const byte *)"test", 4))("KeySize", 3*512));
758	verifier = signer;
759
760	fail = !SignatureValidate(signer, verifier);
761	pass = pass && !fail;
762
763	return pass;
764}
765