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