Crypto++  5.6.3
Free C++ class library of cryptographic schemes
test.cpp
1 // test.cpp - written and placed in the public domain by Wei Dai
2 
3 #define CRYPTOPP_DEFAULT_NO_DLL
4 #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
5 
6 #include "dll.h"
7 #include "aes.h"
8 #include "cryptlib.h"
9 #include "filters.h"
10 #include "md5.h"
11 #include "ripemd.h"
12 #include "rng.h"
13 #include "gzip.h"
14 #include "default.h"
15 #include "randpool.h"
16 #include "ida.h"
17 #include "base64.h"
18 #include "socketft.h"
19 #include "wait.h"
20 #include "factory.h"
21 #include "whrlpool.h"
22 #include "tiger.h"
23 #include "smartptr.h"
24 
25 #include "validate.h"
26 #include "bench.h"
27 
28 #include <algorithm>
29 #include <iostream>
30 #include <sstream>
31 #include <string>
32 #include <locale>
33 #include <time.h>
34 
35 #ifdef CRYPTOPP_WIN32_AVAILABLE
36 #include <windows.h>
37 #endif
38 
39 #if defined(USE_BERKELEY_STYLE_SOCKETS) && !defined(macintosh)
40 #include <netinet/in.h>
41 #include <netinet/tcp.h>
42 #endif
43 
44 #if (_MSC_VER >= 1000)
45 #include <crtdbg.h> // for the debug heap
46 #endif
47 
48 #if defined(__MWERKS__) && defined(macintosh)
49 #include <console.h>
50 #endif
51 
52 #ifdef _OPENMP
53 # include <omp.h>
54 #endif
55 
56 #ifdef __BORLANDC__
57 #pragma comment(lib, "cryptlib_bds.lib")
58 #pragma comment(lib, "ws2_32.lib")
59 #endif
60 
61 // Aggressive stack checking with VS2005 SP1 and above.
62 #if (CRYPTOPP_MSC_VERSION >= 1410)
63 # pragma strict_gs_check (on)
64 #endif
65 
66 USING_NAMESPACE(CryptoPP)
67 USING_NAMESPACE(std)
68 
69 const int MAX_PHRASE_LENGTH=250;
70 
71 void RegisterFactories();
72 void PrintSeedAndThreads(const std::string& seed);
73 
74 void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed);
75 string RSAEncryptString(const char *pubFilename, const char *seed, const char *message);
76 string RSADecryptString(const char *privFilename, const char *ciphertext);
77 void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename);
78 bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename);
79 
80 void DigestFile(const char *file);
81 void HmacFile(const char *hexKey, const char *file);
82 
83 void AES_CTR_Encrypt(const char *hexKey, const char *hexIV, const char *infile, const char *outfile);
84 
85 string EncryptString(const char *plaintext, const char *passPhrase);
86 string DecryptString(const char *ciphertext, const char *passPhrase);
87 
88 void EncryptFile(const char *in, const char *out, const char *passPhrase);
89 void DecryptFile(const char *in, const char *out, const char *passPhrase);
90 
91 void SecretShareFile(int threshold, int nShares, const char *filename, const char *seed);
92 void SecretRecoverFile(int threshold, const char *outFilename, char *const *inFilenames);
93 
94 void InformationDisperseFile(int threshold, int nShares, const char *filename);
95 void InformationRecoverFile(int threshold, const char *outFilename, char *const *inFilenames);
96 
97 void GzipFile(const char *in, const char *out, int deflate_level);
98 void GunzipFile(const char *in, const char *out);
99 
100 void Base64Encode(const char *infile, const char *outfile);
101 void Base64Decode(const char *infile, const char *outfile);
102 void HexEncode(const char *infile, const char *outfile);
103 void HexDecode(const char *infile, const char *outfile);
104 
105 void ForwardTcpPort(const char *sourcePort, const char *destinationHost, const char *destinationPort);
106 
107 void FIPS140_SampleApplication();
108 void FIPS140_GenerateRandomFiles();
109 
110 bool Validate(int, bool, const char *);
111 void PrintSeedAndThreads(const std::string& seed);
112 
113 int (*AdhocTest)(int argc, char *argv[]) = NULL;
114 
115 RandomNumberGenerator & GlobalRNG()
116 {
117  static OFB_Mode<AES>::Encryption s_globalRNG;
118  return dynamic_cast<RandomNumberGenerator&>(s_globalRNG);
119 }
120 
121 int CRYPTOPP_API main(int argc, char *argv[])
122 {
123 #ifdef _CRTDBG_LEAK_CHECK_DF
124  // Turn on leak-checking
125  int tempflag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
126  tempflag |= _CRTDBG_LEAK_CHECK_DF;
127  _CrtSetDbgFlag( tempflag );
128 #endif
129 
130 #if defined(__MWERKS__) && defined(macintosh)
131  argc = ccommand(&argv);
132 #endif
133 
134  try
135  {
136  RegisterFactories();
137 
138  // Some editors have problems with the '\0' character when redirecting output.
139  std::string seed = IntToString(time(NULL));
140  seed.resize(16, ' ');
141 
142  OFB_Mode<AES>::Encryption& prng = dynamic_cast<OFB_Mode<AES>::Encryption&>(GlobalRNG());
143  prng.SetKeyWithIV((byte *)seed.data(), 16, (byte *)seed.data());
144 
145  std::string command, executableName, macFilename;
146 
147  if (argc < 2)
148  command = 'h';
149  else
150  command = argv[1];
151 
152  if (command == "g")
153  {
154  char thisSeed[1024], privFilename[128], pubFilename[128];
155  unsigned int keyLength;
156 
157  cout << "Key length in bits: ";
158  cin >> keyLength;
159 
160  cout << "\nSave private key to file: ";
161  cin >> privFilename;
162 
163  cout << "\nSave public key to file: ";
164  cin >> pubFilename;
165 
166  cout << "\nRandom Seed: ";
167  ws(cin);
168  cin.getline(thisSeed, 1024);
169 
170  GenerateRSAKey(keyLength, privFilename, pubFilename, thisSeed);
171  }
172  else if (command == "rs")
173  RSASignFile(argv[2], argv[3], argv[4]);
174  else if (command == "rv")
175  {
176  bool verified = RSAVerifyFile(argv[2], argv[3], argv[4]);
177  cout << (verified ? "valid signature" : "invalid signature") << endl;
178  }
179  else if (command == "r")
180  {
181  char privFilename[128], pubFilename[128];
182  char thisSeed[1024], message[1024];
183 
184  cout << "Private key file: ";
185  cin >> privFilename;
186 
187  cout << "\nPublic key file: ";
188  cin >> pubFilename;
189 
190  cout << "\nRandom Seed: ";
191  ws(cin);
192  cin.getline(thisSeed, 1024);
193 
194  cout << "\nMessage: ";
195  cin.getline(message, 1024);
196 
197  string ciphertext = RSAEncryptString(pubFilename, thisSeed, message);
198  cout << "\nCiphertext: " << ciphertext << endl;
199 
200  string decrypted = RSADecryptString(privFilename, ciphertext.c_str());
201  cout << "\nDecrypted: " << decrypted << endl;
202  }
203  else if (command == "mt")
204  {
206  FileStore fs(argv[2]);
207  fs.TransferAllTo(mt);
208  cout << "Maurer Test Value: " << mt.GetTestValue() << endl;
209  }
210  else if (command == "mac_dll")
211  {
212  std::string fname(argv[2] ? argv[2] : "");
213 
214  // sanity check on file size
215  std::fstream dllFile(fname.c_str(), ios::in | ios::out | ios::binary);
216  if (!dllFile.good())
217  {
218  cerr << "Failed to open file \"" << fname << "\"\n";
219  return 1;
220  }
221 
222  std::ifstream::pos_type fileEnd = dllFile.seekg(0, std::ios_base::end).tellg();
223  if (fileEnd > 20*1000*1000)
224  {
225  cerr << "Input file " << fname << " is too large";
226  cerr << "(size is " << fileEnd << ").\n";
227  return 1;
228  }
229 
230  // read file into memory
231  unsigned int fileSize = (unsigned int)fileEnd;
232  SecByteBlock buf(fileSize);
233  dllFile.seekg(0, std::ios_base::beg);
234  dllFile.read((char *)buf.begin(), fileSize);
235 
236  // find positions of relevant sections in the file, based on version 8 of documentation from http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
237  word32 coffPos = *(word16 *)(buf+0x3c);
238  word32 optionalHeaderPos = coffPos + 24;
239  word16 optionalHeaderMagic = *(word16 *)(buf+optionalHeaderPos);
240  if (optionalHeaderMagic != 0x10b && optionalHeaderMagic != 0x20b)
241  {
242  cerr << "Target file is not a PE32 or PE32+ image.\n";
243  return 3;
244  }
245  word32 checksumPos = optionalHeaderPos + 64;
246  word32 certificateTableDirectoryPos = optionalHeaderPos + (optionalHeaderMagic == 0x10b ? 128 : 144);
247  word32 certificateTablePos = *(word32 *)(buf+certificateTableDirectoryPos);
248  word32 certificateTableSize = *(word32 *)(buf+certificateTableDirectoryPos+4);
249  if (certificateTableSize != 0)
250  cerr << "Warning: certificate table (IMAGE_DIRECTORY_ENTRY_SECURITY) of target image is not empty.\n";
251 
252  // find where to place computed MAC
253  byte mac[] = CRYPTOPP_DUMMY_DLL_MAC;
254  byte *found = std::search(buf.begin(), buf.end(), mac+0, mac+sizeof(mac));
255  if (found == buf.end())
256  {
257  cerr << "MAC placeholder not found. The MAC may already be placed.\n";
258  return 2;
259  }
260  word32 macPos = (unsigned int)(found-buf.begin());
261 
262  // compute MAC
264  assert(pMac->DigestSize() == sizeof(mac));
265  MeterFilter f(new HashFilter(*pMac, new ArraySink(mac, sizeof(mac))));
266  f.AddRangeToSkip(0, checksumPos, 4);
267  f.AddRangeToSkip(0, certificateTableDirectoryPos, 8);
268  f.AddRangeToSkip(0, macPos, sizeof(mac));
269  f.AddRangeToSkip(0, certificateTablePos, certificateTableSize);
270  f.PutMessageEnd(buf.begin(), buf.size());
271 
272  // place MAC
273  cout << "Placing MAC in file " << fname << ", location " << macPos;
274  cout << " (0x" << std::hex << macPos << std::dec << ").\n";
275  dllFile.seekg(macPos, std::ios_base::beg);
276  dllFile.write((char *)mac, sizeof(mac));
277  }
278  else if (command == "m")
279  DigestFile(argv[2]);
280  else if (command == "tv")
281  {
282  std::string fname = (argv[2] ? argv[2] : "all");
283  if (fname.find(".txt") == std::string::npos)
284  fname = PACKAGE_DATA_DIR "TestVectors/" + fname + ".txt";
285 
286  PrintSeedAndThreads(seed);
287  return !RunTestDataFile(fname.c_str());
288  }
289  else if (command == "t")
290  {
291  // VC60 workaround: use char array instead of std::string to workaround MSVC's getline bug
292  char passPhrase[MAX_PHRASE_LENGTH], plaintext[1024];
293 
294  cout << "Passphrase: ";
295  cin.getline(passPhrase, MAX_PHRASE_LENGTH);
296 
297  cout << "\nPlaintext: ";
298  cin.getline(plaintext, 1024);
299 
300  string ciphertext = EncryptString(plaintext, passPhrase);
301  cout << "\nCiphertext: " << ciphertext << endl;
302 
303  string decrypted = DecryptString(ciphertext.c_str(), passPhrase);
304  cout << "\nDecrypted: " << decrypted << endl;
305 
306  return 0;
307  }
308  else if (command == "e64")
309  Base64Encode(argv[2], argv[3]);
310  else if (command == "d64")
311  Base64Decode(argv[2], argv[3]);
312  else if (command == "e16")
313  HexEncode(argv[2], argv[3]);
314  else if (command == "d16")
315  HexDecode(argv[2], argv[3]);
316  else if (command == "e" || command == "d")
317  {
318  char passPhrase[MAX_PHRASE_LENGTH];
319  cout << "Passphrase: ";
320  cin.getline(passPhrase, MAX_PHRASE_LENGTH);
321  if (command == "e")
322  EncryptFile(argv[2], argv[3], passPhrase);
323  else
324  DecryptFile(argv[2], argv[3], passPhrase);
325  }
326  else if (command == "ss")
327  {
328  char thisSeed[1024];
329  cout << "\nRandom Seed: ";
330  ws(cin);
331  cin.getline(thisSeed, 1024);
332  SecretShareFile(StringToValue<int, true>(argv[2]), StringToValue<int, true>(argv[3]), argv[4], thisSeed);
333  }
334  else if (command == "sr")
335  SecretRecoverFile(argc-3, argv[2], argv+3);
336  else if (command == "id")
337  InformationDisperseFile(StringToValue<int, true>(argv[2]), StringToValue<int, true>(argv[3]), argv[4]);
338  else if (command == "ir")
339  InformationRecoverFile(argc-3, argv[2], argv+3);
340  else if (command == "v" || command == "vv")
341  return !Validate(argc>2 ? StringToValue<int, true>(argv[2]) : 0, argv[1][1] == 'v', argc>3 ? argv[3] : NULL);
342  else if (command == "b")
343  BenchmarkAll(argc<3 ? 1 : StringToValue<float, true>(argv[2]), argc<4 ? 0 : StringToValue<float, true>(argv[3])*1e9);
344  else if (command == "b2")
345  BenchmarkAll2(argc<3 ? 1 : StringToValue<float, true>(argv[2]), argc<4 ? 0 : StringToValue<float, true>(argv[3])*1e9);
346  else if (command == "z")
347  GzipFile(argv[3], argv[4], argv[2][0]-'0');
348  else if (command == "u")
349  GunzipFile(argv[2], argv[3]);
350  else if (command == "fips")
351  FIPS140_SampleApplication();
352  else if (command == "fips-rand")
353  FIPS140_GenerateRandomFiles();
354  else if (command == "ft")
355  ForwardTcpPort(argv[2], argv[3], argv[4]);
356  else if (command == "a")
357  {
358  if (AdhocTest)
359  return (*AdhocTest)(argc, argv);
360  else
361  {
362  cerr << "AdhocTest not defined.\n";
363  return 1;
364  }
365  }
366  else if (command == "hmac")
367  HmacFile(argv[2], argv[3]);
368  else if (command == "ae")
369  AES_CTR_Encrypt(argv[2], argv[3], argv[4], argv[5]);
370  else if (command == "h")
371  {
372  FileSource usage(PACKAGE_DATA_DIR "TestData/usage.dat", true, new FileSink(cout));
373  return 1;
374  }
375  else if (command == "V")
376  {
377  cout << CRYPTOPP_VERSION / 100 << '.' << (CRYPTOPP_VERSION % 100) / 10 << '.' << CRYPTOPP_VERSION % 10 << endl;
378  }
379  else
380  {
381  cerr << "Unrecognized command. Run \"cryptest h\" to obtain usage information.\n";
382  return 1;
383  }
384  return 0;
385  }
386  catch(const CryptoPP::Exception &e)
387  {
388  cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
389  return -1;
390  }
391  catch(const std::exception &e)
392  {
393  cout << "\nstd::exception caught: " << e.what() << endl;
394  return -2;
395  }
396 } // End main()
397 
398 void FIPS140_GenerateRandomFiles()
399 {
400 #ifdef OS_RNG_AVAILABLE
402  RandomNumberStore store(rng, ULONG_MAX);
403 
404  for (unsigned int i=0; i<100000; i++)
405  store.TransferTo(FileSink((IntToString(i) + ".rnd").c_str()).Ref(), 20000);
406 #else
407  cout << "OS provided RNG not available.\n";
408  exit(-1);
409 #endif
410 }
411 
412 template <class T, bool NON_NEGATIVE>
413 T StringToValue(const std::string& str) {
414  std::istringstream iss(str);
415  T value;
416  iss >> value;
417 
418  // Use fail(), not bad()
419  if (iss.fail())
420  throw InvalidArgument("cryptest.exe: '" + str +"' is not a value");
421 
422 #if NON_NEGATIVE
423  if (value < 0)
424  throw InvalidArgument("cryptest.exe: '" + str +"' is negative");
425 #endif
426 
427  return value;
428 }
429 
430 template<>
431 int StringToValue<int, true>(const std::string& str)
432 {
433  Integer n(str.c_str());
434  long l = n.ConvertToLong();
435 
436  int r;
437  if(!SafeConvert(l, r))
438  throw InvalidArgument("cryptest.exe: '" + str +"' is not an integer value");
439 
440  return r;
441 }
442 
443 void PrintSeedAndThreads(const std::string& seed)
444 {
445  cout << "Using seed: " << seed << endl;
446 
447 #ifdef _OPENMP
448  int tc = 0;
449  #pragma omp parallel
450  {
451  tc = omp_get_num_threads();
452  }
453 
454  std::cout << "Using " << tc << " OMP " << (tc == 1 ? "thread" : "threads") << std::endl;
455 #endif
456 }
457 
458 SecByteBlock HexDecodeString(const char *hex)
459 {
460  StringSource ss(hex, true, new HexDecoder);
461  SecByteBlock result((size_t)ss.MaxRetrievable());
462  ss.Get(result, result.size());
463  return result;
464 }
465 
466 void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed)
467 {
468  RandomPool randPool;
469  randPool.IncorporateEntropy((byte *)seed, strlen(seed));
470 
471  RSAES_OAEP_SHA_Decryptor priv(randPool, keyLength);
472  HexEncoder privFile(new FileSink(privFilename));
473  priv.DEREncode(privFile);
474  privFile.MessageEnd();
475 
476  RSAES_OAEP_SHA_Encryptor pub(priv);
477  HexEncoder pubFile(new FileSink(pubFilename));
478  pub.DEREncode(pubFile);
479  pubFile.MessageEnd();
480 }
481 
482 string RSAEncryptString(const char *pubFilename, const char *seed, const char *message)
483 {
484  FileSource pubFile(pubFilename, true, new HexDecoder);
485  RSAES_OAEP_SHA_Encryptor pub(pubFile);
486 
487  RandomPool randPool;
488  randPool.IncorporateEntropy((byte *)seed, strlen(seed));
489 
490  string result;
491  StringSource(message, true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))));
492  return result;
493 }
494 
495 string RSADecryptString(const char *privFilename, const char *ciphertext)
496 {
497  FileSource privFile(privFilename, true, new HexDecoder);
498  RSAES_OAEP_SHA_Decryptor priv(privFile);
499 
500  string result;
501  StringSource(ciphertext, true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))));
502  return result;
503 }
504 
505 void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename)
506 {
507  FileSource privFile(privFilename, true, new HexDecoder);
508  RSASS<PKCS1v15, SHA>::Signer priv(privFile);
509  FileSource f(messageFilename, true, new SignerFilter(GlobalRNG(), priv, new HexEncoder(new FileSink(signatureFilename))));
510 }
511 
512 bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename)
513 {
514  FileSource pubFile(pubFilename, true, new HexDecoder);
515  RSASS<PKCS1v15, SHA>::Verifier pub(pubFile);
516 
517  FileSource signatureFile(signatureFilename, true, new HexDecoder);
518  if (signatureFile.MaxRetrievable() != pub.SignatureLength())
519  return false;
520  SecByteBlock signature(pub.SignatureLength());
521  signatureFile.Get(signature, signature.size());
522 
523  VerifierFilter *verifierFilter = new VerifierFilter(pub);
524  verifierFilter->Put(signature, pub.SignatureLength());
525  FileSource f(messageFilename, true, verifierFilter);
526 
527  return verifierFilter->GetLastResult();
528 }
529 
530 void DigestFile(const char *filename)
531 {
532  SHA1 sha;
533  RIPEMD160 ripemd;
534  SHA256 sha256;
535  Tiger tiger;
536  SHA512 sha512;
537  Whirlpool whirlpool;
539  filters[0].reset(new HashFilter(sha));
540  filters[1].reset(new HashFilter(ripemd));
541  filters[2].reset(new HashFilter(tiger));
542  filters[3].reset(new HashFilter(sha256));
543  filters[4].reset(new HashFilter(sha512));
544  filters[5].reset(new HashFilter(whirlpool));
545 
546  member_ptr<ChannelSwitch> channelSwitch(new ChannelSwitch);
547  size_t i;
548  for (i=0; i<filters.size(); i++)
549  channelSwitch->AddDefaultRoute(*filters[i]);
550  FileSource(filename, true, channelSwitch.release());
551 
552  HexEncoder encoder(new FileSink(cout), false);
553  for (i=0; i<filters.size(); i++)
554  {
555  cout << filters[i]->AlgorithmName() << ": ";
556  filters[i]->TransferTo(encoder);
557  cout << "\n";
558  }
559 }
560 
561 void HmacFile(const char *hexKey, const char *file)
562 {
564  if (strcmp(hexKey, "selftest") == 0)
565  {
566  cerr << "Computing HMAC/SHA1 value for self test.\n";
567  mac.reset(NewIntegrityCheckingMAC());
568  }
569  else
570  {
571  std::string decodedKey;
572  StringSource(hexKey, true, new HexDecoder(new StringSink(decodedKey)));
573  mac.reset(new HMAC<SHA1>((const byte *)decodedKey.data(), decodedKey.size()));
574  }
575  FileSource(file, true, new HashFilter(*mac, new HexEncoder(new FileSink(cout))));
576 }
577 
578 void AES_CTR_Encrypt(const char *hexKey, const char *hexIV, const char *infile, const char *outfile)
579 {
580  SecByteBlock key = HexDecodeString(hexKey);
581  SecByteBlock iv = HexDecodeString(hexIV);
582  CTR_Mode<AES>::Encryption aes(key, key.size(), iv);
583  FileSource(infile, true, new StreamTransformationFilter(aes, new FileSink(outfile)));
584 }
585 
586 string EncryptString(const char *instr, const char *passPhrase)
587 {
588  string outstr;
589 
590  DefaultEncryptorWithMAC encryptor(passPhrase, new HexEncoder(new StringSink(outstr)));
591  encryptor.Put((byte *)instr, strlen(instr));
592  encryptor.MessageEnd();
593 
594  return outstr;
595 }
596 
597 string DecryptString(const char *instr, const char *passPhrase)
598 {
599  string outstr;
600 
601  HexDecoder decryptor(new DefaultDecryptorWithMAC(passPhrase, new StringSink(outstr)));
602  decryptor.Put((byte *)instr, strlen(instr));
603  decryptor.MessageEnd();
604 
605  return outstr;
606 }
607 
608 void EncryptFile(const char *in, const char *out, const char *passPhrase)
609 {
610  FileSource f(in, true, new DefaultEncryptorWithMAC(passPhrase, new FileSink(out)));
611 }
612 
613 void DecryptFile(const char *in, const char *out, const char *passPhrase)
614 {
615  FileSource f(in, true, new DefaultDecryptorWithMAC(passPhrase, new FileSink(out)));
616 }
617 
618 void SecretShareFile(int threshold, int nShares, const char *filename, const char *seed)
619 {
620  assert(nShares >= 1 && nShares<=1000);
621  if (nShares < 1 || nShares > 1000)
622  throw InvalidArgument("SecretShareFile: " + IntToString(nShares) + " is not in range [1, 1000]");
623 
624  RandomPool rng;
625  rng.IncorporateEntropy((byte *)seed, strlen(seed));
626 
627  ChannelSwitch *channelSwitch;
628  FileSource source(filename, false, new SecretSharing(rng, threshold, nShares, channelSwitch = new ChannelSwitch));
629 
630  vector_member_ptrs<FileSink> fileSinks(nShares);
631  string channel;
632  for (int i=0; i<nShares; i++)
633  {
634  char extension[5] = ".000";
635  extension[1]='0'+byte(i/100);
636  extension[2]='0'+byte((i/10)%10);
637  extension[3]='0'+byte(i%10);
638  fileSinks[i].reset(new FileSink((string(filename)+extension).c_str()));
639 
640  channel = WordToString<word32>(i);
641  fileSinks[i]->Put((const byte *)channel.data(), 4);
642  channelSwitch->AddRoute(channel, *fileSinks[i], DEFAULT_CHANNEL);
643  }
644 
645  source.PumpAll();
646 }
647 
648 void SecretRecoverFile(int threshold, const char *outFilename, char *const *inFilenames)
649 {
650  assert(threshold >= 1 && threshold <=1000);
651  if (threshold < 1 || threshold > 1000)
652  throw InvalidArgument("SecretRecoverFile: " + IntToString(threshold) + " is not in range [1, 1000]");
653 
654  SecretRecovery recovery(threshold, new FileSink(outFilename));
655 
656  vector_member_ptrs<FileSource> fileSources(threshold);
657  SecByteBlock channel(4);
658  int i;
659  for (i=0; i<threshold; i++)
660  {
661  fileSources[i].reset(new FileSource(inFilenames[i], false));
662  fileSources[i]->Pump(4);
663  fileSources[i]->Get(channel, 4);
664  fileSources[i]->Attach(new ChannelSwitch(recovery, string((char *)channel.begin(), 4)));
665  }
666 
667  while (fileSources[0]->Pump(256))
668  for (i=1; i<threshold; i++)
669  fileSources[i]->Pump(256);
670 
671  for (i=0; i<threshold; i++)
672  fileSources[i]->PumpAll();
673 }
674 
675 void InformationDisperseFile(int threshold, int nShares, const char *filename)
676 {
677  assert(threshold >= 1 && threshold <=1000);
678  if (threshold < 1 || threshold > 1000)
679  throw InvalidArgument("InformationDisperseFile: " + IntToString(nShares) + " is not in range [1, 1000]");
680 
681  ChannelSwitch *channelSwitch;
682  FileSource source(filename, false, new InformationDispersal(threshold, nShares, channelSwitch = new ChannelSwitch));
683 
684  vector_member_ptrs<FileSink> fileSinks(nShares);
685  string channel;
686  for (int i=0; i<nShares; i++)
687  {
688  char extension[5] = ".000";
689  extension[1]='0'+byte(i/100);
690  extension[2]='0'+byte((i/10)%10);
691  extension[3]='0'+byte(i%10);
692  fileSinks[i].reset(new FileSink((string(filename)+extension).c_str()));
693 
694  channel = WordToString<word32>(i);
695  fileSinks[i]->Put((const byte *)channel.data(), 4);
696  channelSwitch->AddRoute(channel, *fileSinks[i], DEFAULT_CHANNEL);
697  }
698 
699  source.PumpAll();
700 }
701 
702 void InformationRecoverFile(int threshold, const char *outFilename, char *const *inFilenames)
703 {
704  assert(threshold<=1000);
705  if (threshold < 1 || threshold > 1000)
706  throw InvalidArgument("InformationRecoverFile: " + IntToString(threshold) + " is not in range [1, 1000]");
707 
708  InformationRecovery recovery(threshold, new FileSink(outFilename));
709 
710  vector_member_ptrs<FileSource> fileSources(threshold);
711  SecByteBlock channel(4);
712  int i;
713  for (i=0; i<threshold; i++)
714  {
715  fileSources[i].reset(new FileSource(inFilenames[i], false));
716  fileSources[i]->Pump(4);
717  fileSources[i]->Get(channel, 4);
718  fileSources[i]->Attach(new ChannelSwitch(recovery, string((char *)channel.begin(), 4)));
719  }
720 
721  while (fileSources[0]->Pump(256))
722  for (i=1; i<threshold; i++)
723  fileSources[i]->Pump(256);
724 
725  for (i=0; i<threshold; i++)
726  fileSources[i]->PumpAll();
727 }
728 
729 void GzipFile(const char *in, const char *out, int deflate_level)
730 {
731 // FileSource(in, true, new Gzip(new FileSink(out), deflate_level));
732 
733  // use a filter graph to compare decompressed data with original
734  //
735  // Source ----> Gzip ------> Sink
736  // \ |
737  // \ Gunzip
738  // \ |
739  // \ v
740  // > ComparisonFilter
741 
742  EqualityComparisonFilter comparison;
743 
744  Gunzip gunzip(new ChannelSwitch(comparison, "0"));
745  gunzip.SetAutoSignalPropagation(0);
746 
747  FileSink sink(out);
748 
749  ChannelSwitch *cs;
750  Gzip gzip(cs = new ChannelSwitch(sink), deflate_level);
751  cs->AddDefaultRoute(gunzip);
752 
753  cs = new ChannelSwitch(gzip);
754  cs->AddDefaultRoute(comparison, "1");
755  FileSource source(in, true, cs);
756 
757  comparison.ChannelMessageSeriesEnd("0");
758  comparison.ChannelMessageSeriesEnd("1");
759 }
760 
761 void GunzipFile(const char *in, const char *out)
762 {
763  FileSource(in, true, new Gunzip(new FileSink(out)));
764 }
765 
766 void Base64Encode(const char *in, const char *out)
767 {
768  FileSource(in, true, new Base64Encoder(new FileSink(out)));
769 }
770 
771 void Base64Decode(const char *in, const char *out)
772 {
773  FileSource(in, true, new Base64Decoder(new FileSink(out)));
774 }
775 
776 void HexEncode(const char *in, const char *out)
777 {
778  FileSource(in, true, new HexEncoder(new FileSink(out)));
779 }
780 
781 void HexDecode(const char *in, const char *out)
782 {
783  FileSource(in, true, new HexDecoder(new FileSink(out)));
784 }
785 
786 void ForwardTcpPort(const char *sourcePortName, const char *destinationHost, const char *destinationPortName)
787 {
788 #ifdef SOCKETS_AVAILABLE
789  SocketsInitializer sockInit;
790 
791  Socket sockListen, sockSource, sockDestination;
792 
793  int sourcePort = Socket::PortNameToNumber(sourcePortName);
794  int destinationPort = Socket::PortNameToNumber(destinationPortName);
795 
796  sockListen.Create();
797  sockListen.Bind(sourcePort);
798 
799  int err = setsockopt(sockListen, IPPROTO_TCP, TCP_NODELAY, "\x01", 1);
800  assert(err == 0);
801  if(err != 0)
802  throw Socket::Err(sockListen, "setsockopt", sockListen.GetLastError());
803 
804  cout << "Listing on port " << sourcePort << ".\n";
805  sockListen.Listen();
806 
807  sockListen.Accept(sockSource);
808  cout << "Connection accepted on port " << sourcePort << ".\n";
809  sockListen.CloseSocket();
810 
811  cout << "Making connection to " << destinationHost << ", port " << destinationPort << ".\n";
812  sockDestination.Create();
813  sockDestination.Connect(destinationHost, destinationPort);
814 
815  cout << "Connection made to " << destinationHost << ", starting to forward.\n";
816 
817  SocketSource out(sockSource, false, new SocketSink(sockDestination));
818  SocketSource in(sockDestination, false, new SocketSink(sockSource));
819 
820  WaitObjectContainer waitObjects;
821 
822  while (!(in.SourceExhausted() && out.SourceExhausted()))
823  {
824  waitObjects.Clear();
825 
826  out.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - out", NULL));
827  in.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - in", NULL));
828 
829  waitObjects.Wait(INFINITE_TIME);
830 
831  if (!out.SourceExhausted())
832  {
833  cout << "o" << flush;
834  out.PumpAll2(false);
835  if (out.SourceExhausted())
836  cout << "EOF received on source socket.\n";
837  }
838 
839  if (!in.SourceExhausted())
840  {
841  cout << "i" << flush;
842  in.PumpAll2(false);
843  if (in.SourceExhausted())
844  cout << "EOF received on destination socket.\n";
845  }
846  }
847 #else
848  cout << "Socket support was not enabled at compile time.\n";
849  exit(-1);
850 #endif
851 }
852 
853 bool Validate(int alg, bool thorough, const char *seedInput)
854 {
855  bool result;
856 
857  // Some editors have problems with the '\0' character when redirecting output.
858  // seedInput is argv[3] when issuing 'cryptest.exe v all <seed>'
859  std::string seed = (seedInput ? seedInput : IntToString(time(NULL)));
860  seed.resize(16, ' ');
861 
862  OFB_Mode<AES>::Encryption& prng = dynamic_cast<OFB_Mode<AES>::Encryption&>(GlobalRNG());
863  prng.SetKeyWithIV((byte *)seed.data(), 16, (byte *)seed.data());
864 
865  PrintSeedAndThreads(seed);
866 
867  switch (alg)
868  {
869  case 0: result = ValidateAll(thorough); break;
870  case 1: result = TestSettings(); break;
871  case 2: result = TestOS_RNG(); break;
872  case 3: result = ValidateMD5(); break;
873  case 4: result = ValidateSHA(); break;
874  case 5: result = ValidateDES(); break;
875  case 6: result = ValidateIDEA(); break;
876  case 7: result = ValidateARC4(); break;
877  case 8: result = ValidateRC5(); break;
878  case 9: result = ValidateBlowfish(); break;
879 // case 10: result = ValidateDiamond2(); break;
880  case 11: result = ValidateThreeWay(); break;
881  case 12: result = ValidateBBS(); break;
882  case 13: result = ValidateDH(); break;
883  case 14: result = ValidateRSA(); break;
884  case 15: result = ValidateElGamal(); break;
885  case 16: result = ValidateDSA(thorough); break;
886 // case 17: result = ValidateHAVAL(); break;
887  case 18: result = ValidateSAFER(); break;
888  case 19: result = ValidateLUC(); break;
889  case 20: result = ValidateRabin(); break;
890 // case 21: result = ValidateBlumGoldwasser(); break;
891  case 22: result = ValidateECP(); break;
892  case 23: result = ValidateEC2N(); break;
893 // case 24: result = ValidateMD5MAC(); break;
894  case 25: result = ValidateGOST(); break;
895  case 26: result = ValidateTiger(); break;
896  case 27: result = ValidateRIPEMD(); break;
897  case 28: result = ValidateHMAC(); break;
898 // case 29: result = ValidateXMACC(); break;
899  case 30: result = ValidateSHARK(); break;
900  case 32: result = ValidateLUC_DH(); break;
901  case 33: result = ValidateLUC_DL(); break;
902  case 34: result = ValidateSEAL(); break;
903  case 35: result = ValidateCAST(); break;
904  case 36: result = ValidateSquare(); break;
905  case 37: result = ValidateRC2(); break;
906  case 38: result = ValidateRC6(); break;
907  case 39: result = ValidateMARS(); break;
908  case 40: result = ValidateRW(); break;
909  case 41: result = ValidateMD2(); break;
910  case 42: result = ValidateNR(); break;
911  case 43: result = ValidateMQV(); break;
912  case 44: result = ValidateRijndael(); break;
913  case 45: result = ValidateTwofish(); break;
914  case 46: result = ValidateSerpent(); break;
915  case 47: result = ValidateCipherModes(); break;
916  case 48: result = ValidateCRC32(); break;
917  case 49: result = ValidateECDSA(); break;
918  case 50: result = ValidateXTR_DH(); break;
919  case 51: result = ValidateSKIPJACK(); break;
920  case 52: result = ValidateSHA2(); break;
921  case 53: result = ValidatePanama(); break;
922  case 54: result = ValidateAdler32(); break;
923  case 55: result = ValidateMD4(); break;
924  case 56: result = ValidatePBKDF(); break;
925  case 57: result = ValidateESIGN(); break;
926  case 58: result = ValidateDLIES(); break;
927  case 59: result = ValidateBaseCode(); break;
928  case 60: result = ValidateSHACAL2(); break;
929  case 61: result = ValidateCamellia(); break;
930  case 62: result = ValidateWhirlpool(); break;
931  case 63: result = ValidateTTMAC(); break;
932  case 64: result = ValidateSalsa(); break;
933  case 65: result = ValidateSosemanuk(); break;
934  case 66: result = ValidateVMAC(); break;
935  case 67: result = ValidateCCM(); break;
936  case 68: result = ValidateGCM(); break;
937  case 69: result = ValidateCMAC(); break;
938  case 70: result = ValidateHKDF(); break;
939  default: return false;
940  }
941 
942 // Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55
943 #if defined(CRYPTOPP_MSC_VERSION)
944  tm localTime = {};
945  char timeBuf[64];
946  errno_t err;
947 
948  const time_t endTime = time(NULL);
949  err = localtime_s(&localTime, &endTime);
950  assert(err == 0);
951  err = asctime_s(timeBuf, sizeof(timeBuf), &localTime);
952  assert(err == 0);
953 
954  cout << "\nTest ended at " << timeBuf;
955 #else
956  const time_t endTime = time(NULL);
957  cout << "\nTest ended at " << asctime(localtime(&endTime));
958 #endif
959 
960  cout << "Seed used was: " << seed << endl;
961 
962  return result;
963 }
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
Definition: randpool.cpp:26
An invalid argument was detected.
Definition: cryptlib.h:166
container of wait objects
Definition: wait.h:151
Randomness Pool.
Definition: randpool.h:15
Filter Wrapper for PK_Verifier.
Definition: filters.h:540
bool SafeConvert(T1 from, T2 &to)
Tests whether a conversion from → to is safe to perform.
Definition: misc.h:436
implements the SHA-256 standard
Definition: sha.h:27
Classes for RIPEMD message digest.
file-based implementation of Source interface
Definition: files.h:55
Converts given data to base 16.
Definition: hex.h:15
Tiger
Definition: tiger.h:10
GZIP Decompression (RFC 1952)
Definition: gzip.h:34
Base64 decodes data.
Definition: base64.h:52
Decode base 16 data back to bytes.
Definition: hex.h:28
Abstract base classes that provide a uniform interface to this library.
RIPEMD-160
Definition: ripemd.h:15
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:509
Classes for automatic resource management.
Filter Wrapper for PK_Signer.
Definition: filters.h:520
Classes for DefaultEncryptor, DefaultDecryptor, DefaultEncryptorWithMAC and DefaultDecryptorWithMAC.
STL namespace.
Interface for random number generators.
Definition: cryptlib.h:1085
Append input to a string object.
Definition: filters.h:724
SecByteBlock is a SecBlock<byte> typedef.
Definition: secblock.h:719
Route input to different and/or multiple channels based on channel ID.
Definition: channels.h:92
Pointer that overloads operator→
Definition: smartptr.h:39
Base64 encodes data.
Definition: base64.h:18
Copy input to a memory buffer.
Definition: filters.h:775
Filter Wrapper for HashTransformation.
Definition: filters.h:424
RNG-based implementation of Source interface.
Definition: filters.h:829
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1268
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition: cryptlib.cpp:41
signed long ConvertToLong() const
return equivalent signed long if possible, otherwise undefined
Definition: integer.cpp:2875
Whirlpool
Definition: whrlpool.h:10
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
Marks the end of a series of messages on a channel.
Definition: mqueue.cpp:135
Maurer&#39;s Universal Statistical Test for Random Bit Generators.
Definition: rng.h:80
implements the SHA-512 standard
Definition: sha.h:51
Class file for the AES cipher (Rijndael)
Manages resources for an array of objects.
Definition: smartptr.h:284
Multiple precision integer with arithmetic operations.
Definition: integer.h:31
SHA-1
Definition: sha.h:16
proxy for the filter created by PK_Decryptor::CreateDecryptionFilter
Definition: filters.h:715
MessageAuthenticationCode * NewIntegrityCheckingMAC()
Class object that calculates the MAC on the module.
Definition: fipstest.cpp:254
Password-Based encryptor using TripleDES and HMAC/SHA-1.
Definition: default.h:121
Miscellaneous classes for RNGs.
const unsigned long INFINITE_TIME
Represents infinite time.
Definition: cryptlib.h:105
Implementation of BufferedTransformation&#39;s attachment interface in cryptlib.h.
file-based implementation of Store interface
Definition: files.h:15
proxy for the filter created by PK_Encryptor::CreateEncryptionFilter
Definition: filters.h:706
Classes for the Base64Encoder, Base64Decoder, Base64URLEncoder and Base64URLDecoder.
Filter Wrapper for StreamTransformation, optionally handling padding/unpadding when needed...
Definition: filters.h:398
#define CRYPTOPP_DUMMY_DLL_MAC
The placeholder used prior to embedding the actual MAC in the module.
Definition: fips140.h:109
HMAC
Definition: hmac.h:43
a variant of Rabin&#39;s Information Dispersal Algorithm
Definition: ida.h:124
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:449
measure how many byte and messages pass through, also serves as valve
Definition: filters.h:187
Password-Based decryptor using TripleDES and HMAC/SHA-1.
Definition: default.h:159
A filter that checks messages on two channels for equality.
Definition: mqueue.h:71
Crypto++ library namespace.
GZIP Compression (RFC 1952)
Definition: gzip.h:12
a variant of Shamir&#39;s Secret Sharing Algorithm
Definition: ida.h:86
file-based implementation of Sink interface
Definition: files.h:78
Functions and definitions required for building the FIPS-140 DLL on Windows.
a variant of Rabin&#39;s Information Dispersal Algorithm
Definition: ida.h:103
a variant of Shamir&#39;s Secret Sharing Algorithm
Definition: ida.h:65
Classes for Information Dispersal Algorithm (IDA)
A template implementing constructors for public key algorithm classes.
Definition: pubkey.h:1770
A typedef providing a default generator.
Definition: osrng.h:242