Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

test.cpp

00001 // test.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "md5.h"
00005 #include "sha.h"
00006 #include "ripemd.h"
00007 #include "files.h"
00008 #include "rng.h"
00009 #include "hex.h"
00010 #include "gzip.h"
00011 #include "default.h"
00012 #include "rsa.h"
00013 #include "randpool.h"
00014 #include "ida.h"
00015 #include "base64.h"
00016 #include "socketft.h"
00017 #include "dsa.h"
00018 #include "rsa.h"
00019 #include "osrng.h"
00020 #include "wait.h"
00021 #include "fips140.h"
00022 #include "factory.h"
00023 
00024 #include "validate.h"
00025 #include "bench.h"
00026 
00027 #include <iostream>
00028 #include <time.h>
00029 
00030 #ifdef CRYPTOPP_WIN32_AVAILABLE
00031 #include <windows.h>
00032 #endif
00033 
00034 #if (_MSC_VER >= 1000)
00035 #include <crtdbg.h>             // for the debug heap
00036 #endif
00037 
00038 #if defined(__MWERKS__) && defined(macintosh)
00039 #include <console.h>
00040 #endif
00041 
00042 USING_NAMESPACE(CryptoPP)
00043 USING_NAMESPACE(std)
00044 
00045 const int MAX_PHRASE_LENGTH=250;
00046 
00047 void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed);
00048 string RSAEncryptString(const char *pubFilename, const char *seed, const char *message);
00049 string RSADecryptString(const char *privFilename, const char *ciphertext);
00050 void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename);
00051 bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename);
00052 
00053 void DigestFile(const char *file);
00054 
00055 string EncryptString(const char *plaintext, const char *passPhrase);
00056 string DecryptString(const char *ciphertext, const char *passPhrase);
00057 
00058 void EncryptFile(const char *in, const char *out, const char *passPhrase);
00059 void DecryptFile(const char *in, const char *out, const char *passPhrase);
00060 
00061 void SecretShareFile(int threshold, int nShares, const char *filename, const char *seed);
00062 void SecretRecoverFile(int threshold, const char *outFilename, char *const *inFilenames);
00063 
00064 void InformationDisperseFile(int threshold, int nShares, const char *filename);
00065 void InformationRecoverFile(int threshold, const char *outFilename, char *const *inFilenames);
00066 
00067 void GzipFile(const char *in, const char *out, int deflate_level);
00068 void GunzipFile(const char *in, const char *out);
00069 
00070 void Base64Encode(const char *in, const char *out);
00071 void Base64Decode(const char *in, const char *out);
00072 void HexEncode(const char *in, const char *out);
00073 void HexDecode(const char *in, const char *out);
00074 
00075 void ForwardTcpPort(const char *sourcePort, const char *destinationHost, const char *destinationPort);
00076 
00077 void FIPS140_SampleApplication(const char *moduleFilename, const char *edcFilename);
00078 void FIPS140_GenerateRandomFiles();
00079 
00080 bool Validate(int, bool, const char *);
00081 
00082 void RegisterFactories();
00083 bool RunTestDataFile(const char *filename);
00084 
00085 int (*AdhocTest)(int argc, char *argv[]) = NULL;
00086 
00087 #ifdef __BCPLUSPLUS__
00088 int cmain(int argc, char *argv[])
00089 #elif defined(_MSC_VER)
00090 int __cdecl main(int argc, char *argv[])
00091 #else
00092 int main(int argc, char *argv[])
00093 #endif
00094 {
00095 #ifdef _CRTDBG_LEAK_CHECK_DF
00096         // Turn on leak-checking
00097         int tempflag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
00098         tempflag |= _CRTDBG_LEAK_CHECK_DF;
00099         _CrtSetDbgFlag( tempflag );
00100 #endif
00101 
00102 #if defined(__MWERKS__) && defined(macintosh)
00103         argc = ccommand(&argv);
00104 #endif
00105 
00106         try
00107         {
00108                 std::string command, executableName, edcFilename;
00109 
00110                 if (argc < 2)
00111                         command = 'h';
00112                 else
00113                         command = argv[1];
00114 
00115                 if (FIPS_140_2_ComplianceEnabled())
00116                 {
00117                         edcFilename = PKGDATADIR "edc.dat";
00118 
00119 #ifdef CRYPTOPP_WIN32_AVAILABLE
00120                         TCHAR filename[MAX_PATH];
00121                         GetModuleFileName(GetModuleHandle(NULL), filename, sizeof(filename));
00122                         executableName = filename;
00123                         std::string::size_type pos = executableName.rfind('\\');
00124                         if (pos != std::string::npos)
00125                                 edcFilename = executableName.substr(0, pos+1) + edcFilename;
00126 #else
00127                         executableName = argv[0];
00128 #endif
00129 
00130                         if (command.substr(0, 4) != "fips")
00131                         {
00132                                 byte expectedModuleDigest[SHA1::DIGESTSIZE];
00133                                 FileSource(edcFilename.c_str(), true, new HexDecoder(new ArraySink(expectedModuleDigest, sizeof(expectedModuleDigest))));
00134 
00135                                 DoPowerUpSelfTest(executableName.c_str(), expectedModuleDigest);
00136                         }
00137                 }
00138 
00139                 switch (command[0])
00140                 {
00141                 case 'g':
00142                   {
00143                         char seed[1024], privFilename[128], pubFilename[128];
00144                         unsigned int keyLength;
00145 
00146                         cout << "Key length in bits: ";
00147                         cin >> keyLength;
00148 
00149                         cout << "\nSave private key to file: ";
00150                         cin >> privFilename;
00151 
00152                         cout << "\nSave public key to file: ";
00153                         cin >> pubFilename;
00154 
00155                         cout << "\nRandom Seed: ";
00156                         ws(cin);
00157                         cin.getline(seed, 1024);
00158 
00159                         GenerateRSAKey(keyLength, privFilename, pubFilename, seed);
00160                         return 0;
00161                   }
00162                 case 'r':
00163                   {
00164                         switch (argv[1][1])
00165                         {
00166                         case 's':
00167                                 RSASignFile(argv[2], argv[3], argv[4]);
00168                                 return 0;
00169                         case 'v':
00170                           {
00171                                 bool verified = RSAVerifyFile(argv[2], argv[3], argv[4]);
00172                                 cout << (verified ? "valid signature" : "invalid signature") << endl;
00173                                 return 0;
00174                           }
00175                         default:
00176                           {
00177                                 char privFilename[128], pubFilename[128];
00178                                 char seed[1024], message[1024];
00179 
00180                                 cout << "Private key file: ";
00181                                 cin >> privFilename;
00182 
00183                                 cout << "\nPublic key file: ";
00184                                 cin >> pubFilename;
00185 
00186                                 cout << "\nRandom Seed: ";
00187                                 ws(cin);
00188                                 cin.getline(seed, 1024);
00189 
00190                                 cout << "\nMessage: ";
00191                                 cin.getline(message, 1024);
00192 
00193                                 string ciphertext = RSAEncryptString(pubFilename, seed, message);
00194                                 cout << "\nCiphertext: " << ciphertext << endl;
00195 
00196                                 string decrypted = RSADecryptString(privFilename, ciphertext.c_str());
00197                                 cout << "\nDecrypted: " << decrypted << endl;
00198 
00199                                 return 0;
00200                           }
00201                         }
00202                   }
00203                 case 'm':
00204                         DigestFile(argv[2]);
00205                         return 0;
00206                 case 't':
00207                   {
00208                         if (command == "tv")
00209                         {
00210                                 return !RunTestDataFile(argv[2]);
00211                         }
00212                         // VC60 workaround: use char array instead of std::string to workaround MSVC's getline bug
00213                         char passPhrase[MAX_PHRASE_LENGTH], plaintext[1024];
00214 
00215                         cout << "Passphrase: ";
00216                         cin.getline(passPhrase, MAX_PHRASE_LENGTH);
00217 
00218                         cout << "\nPlaintext: ";
00219                         cin.getline(plaintext, 1024);
00220 
00221                         string ciphertext = EncryptString(plaintext, passPhrase);
00222                         cout << "\nCiphertext: " << ciphertext << endl;
00223 
00224                         string decrypted = DecryptString(ciphertext.c_str(), passPhrase);
00225                         cout << "\nDecrypted: " << decrypted << endl;
00226 
00227                         return 0;
00228                   }
00229                 case 'e':
00230                 case 'd':
00231                         if (command == "e64")
00232                                 Base64Encode(argv[2], argv[3]);
00233                         else if (command == "d64")
00234                                 Base64Decode(argv[2], argv[3]);
00235                         else if (command == "e16")
00236                                 HexEncode(argv[2], argv[3]);
00237                         else if (command == "d16")
00238                                 HexDecode(argv[2], argv[3]);
00239                         else
00240                         {
00241                                 char passPhrase[MAX_PHRASE_LENGTH];
00242                                 cout << "Passphrase: ";
00243                                 cin.getline(passPhrase, MAX_PHRASE_LENGTH);
00244                                 if (command == "e")
00245                                         EncryptFile(argv[2], argv[3], passPhrase);
00246                                 else
00247                                         DecryptFile(argv[2], argv[3], passPhrase);
00248                         }
00249                         return 0;
00250                 case 's':
00251                         if (argv[1][1] == 's')
00252                         {
00253                                 char seed[1024];
00254                                 cout << "\nRandom Seed: ";
00255                                 ws(cin);
00256                                 cin.getline(seed, 1024);
00257                                 SecretShareFile(atoi(argv[2]), atoi(argv[3]), argv[4], seed);
00258                         }
00259                         else
00260                                 SecretRecoverFile(argc-3, argv[2], argv+3);
00261                         return 0;
00262                 case 'i':
00263                         if (argv[1][1] == 'd')
00264                                 InformationDisperseFile(atoi(argv[2]), atoi(argv[3]), argv[4]);
00265                         else
00266                                 InformationRecoverFile(argc-3, argv[2], argv+3);
00267                         return 0;
00268                 case 'v':
00269                         return !Validate(argc>2 ? atoi(argv[2]) : 0, argv[1][1] == 'v', argc>3 ? argv[3] : NULL);
00270                 case 'b':
00271                         if (argc<3)
00272                                 BenchMarkAll();
00273                         else
00274                                 BenchMarkAll((float)atof(argv[2]));
00275                         return 0;
00276                 case 'z':
00277                         GzipFile(argv[3], argv[4], argv[2][0]-'0');
00278                         return 0;
00279                 case 'u':
00280                         GunzipFile(argv[2], argv[3]);
00281                         return 0;
00282                 case 'f':
00283                         if (command == "fips")
00284                                 FIPS140_SampleApplication(executableName.c_str(), edcFilename.c_str());
00285                         else if (command == "fips-rand")
00286                                 FIPS140_GenerateRandomFiles();
00287                         else if (command == "ft")
00288                                 ForwardTcpPort(argv[2], argv[3], argv[4]);
00289                         return 0;
00290                 case 'a':
00291                         if (AdhocTest)
00292                                 return (*AdhocTest)(argc, argv);
00293                         else
00294                                 return 0;
00295                 default:
00296                         FileSource usage(PKGDATADIR "usage.dat", true, new FileSink(cout));
00297                         return 1;
00298                 }
00299         }
00300         catch(CryptoPP::Exception &e)
00301         {
00302                 cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
00303                 return -1;
00304         }
00305         catch(std::exception &e)
00306         {
00307                 cout << "\nstd::exception caught: " << e.what() << endl;
00308                 return -2;
00309         }
00310 }
00311 
00312 void FIPS140_SampleApplication(const char *moduleFilename, const char *edcFilename)
00313 {
00314         if (!FIPS_140_2_ComplianceEnabled())
00315         {
00316                 cerr << "FIPS-140-2 compliance was turned off at compile time.\n";
00317                 abort();
00318         }
00319 
00320         // try to use a crypto algorithm before doing a self test
00321         try
00322         {
00323                 // trying to use a crypto algorithm before power-up self test will result in an exception
00324                 DES::Encryption des;
00325 
00326                 // should not be here
00327                 cerr << "Use of DES before power-up test failed to cause an exception.\n";
00328                 abort();
00329         }
00330         catch (SelfTestFailure &e)
00331         {
00332                 cout << "0. Caught expected exception. Exception message follows: ";
00333                 cout << e.what() << endl;
00334         }
00335 
00336         // simulate a power-up self test error
00337         SimulatePowerUpSelfTestFailure();
00338         try
00339         {
00340                 // trying to use a crypto algorithm after power-up self test error will result in an exception
00341                 DES::Encryption des;
00342 
00343                 // should not be here
00344                 cerr << "Use of DES failed to cause an exception after power-up self test error.\n";
00345                 abort();
00346         }
00347         catch (SelfTestFailure &e)
00348         {
00349                 cout << "1. Caught expected exception when simulating self test failure. Exception message follows: ";
00350                 cout << e.what() << endl;
00351         }
00352 
00353         // clear the self test error state and do power-up self test
00354         byte expectedModuleDigest[SHA1::DIGESTSIZE];
00355         FileSource(edcFilename, true, new HexDecoder(new ArraySink(expectedModuleDigest, sizeof(expectedModuleDigest))));
00356 
00357         DoPowerUpSelfTest(moduleFilename, expectedModuleDigest);
00358         if (GetPowerUpSelfTestStatus() != POWER_UP_SELF_TEST_PASSED)
00359         {
00360                 cerr << "Power-up self test failed.\n";
00361                 abort();
00362         }
00363         cout << "2. Power-up self test passed.\n";
00364 
00365         // encrypt and decrypt
00366         const byte key[] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
00367         const byte iv[] = {0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef};
00368         const byte plaintext[] = {      // "Now is the time for all " without tailing 0
00369                 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
00370                 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
00371                 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20};
00372         byte ciphertext[24];
00373         byte decrypted[24];
00374 
00375         CBC_Mode<DES>::Encryption encryption_DES_CBC;
00376         encryption_DES_CBC.SetKeyWithIV(key, 8, iv);
00377         encryption_DES_CBC.ProcessString(ciphertext, plaintext, 24);
00378 
00379         CBC_Mode<DES>::Decryption decryption_DES_CBC;
00380         decryption_DES_CBC.SetKeyWithIV(key, 8, iv);
00381         decryption_DES_CBC.ProcessString(decrypted, ciphertext, 24);
00382 
00383         if (memcmp(plaintext, decrypted, 24) != 0)
00384         {
00385                 cerr << "DES-CBC Encryption/decryption failed.\n";
00386                 abort();
00387         }
00388         cout << "3. DES-CBC Encryption/decryption succeeded.\n";
00389 
00390         // hash
00391         const byte message[] = {'a', 'b', 'c'};
00392         const byte expectedDigest[] = {0xA9,0x99,0x3E,0x36,0x47,0x06,0x81,0x6A,0xBA,0x3E,0x25,0x71,0x78,0x50,0xC2,0x6C,0x9C,0xD0,0xD8,0x9D};
00393         byte digest[20];
00394         
00395         SHA1 sha;
00396         sha.Update(message, 3);
00397         sha.Final(digest);
00398 
00399         if (memcmp(digest, expectedDigest, 20) != 0)
00400         {
00401                 cerr << "SHA-1 hash failed.\n";
00402                 abort();
00403         }
00404         cout << "4. SHA-1 hash succeeded.\n";
00405 
00406         // create auto-seeded X9.17 RNG object, if available
00407 #ifdef OS_RNG_AVAILABLE
00408         AutoSeededX917RNG<DES_EDE3> rng;
00409 #else
00410         // this is used to allow this function to compile on platforms that don't have auto-seeded RNGs
00411         RandomNumberGenerator &rng(NullRNG());
00412 #endif
00413 
00414         // generate DSA key
00415         DSA::PrivateKey dsaPrivateKey;
00416         dsaPrivateKey.GenerateRandomWithKeySize(rng, 1024);
00417         DSA::PublicKey dsaPublicKey;
00418         dsaPublicKey.AssignFrom(dsaPrivateKey);
00419         if (!dsaPrivateKey.Validate(rng, 3) || !dsaPublicKey.Validate(rng, 3))
00420         {
00421                 cerr << "DSA key generation failed.\n";
00422                 abort();
00423         }
00424         cout << "5. DSA key generation succeeded.\n";
00425 
00426         // encode DSA key
00427         std::string encodedDsaPublicKey, encodedDsaPrivateKey;
00428         dsaPublicKey.DEREncode(StringSink(encodedDsaPublicKey).Ref());
00429         dsaPrivateKey.DEREncode(StringSink(encodedDsaPrivateKey).Ref());
00430 
00431         // decode DSA key
00432         DSA::PrivateKey decodedDsaPrivateKey;
00433         decodedDsaPrivateKey.BERDecode(StringStore(encodedDsaPrivateKey).Ref());
00434         DSA::PublicKey decodedDsaPublicKey;
00435         decodedDsaPublicKey.BERDecode(StringStore(encodedDsaPublicKey).Ref());
00436 
00437         if (!decodedDsaPrivateKey.Validate(rng, 3) || !decodedDsaPublicKey.Validate(rng, 3))
00438         {
00439                 cerr << "DSA key encode/decode failed.\n";
00440                 abort();
00441         }
00442         cout << "6. DSA key encode/decode succeeded.\n";
00443 
00444         // sign and verify
00445         byte signature[40];
00446         DSA::Signer signer(dsaPrivateKey);
00447         assert(signer.SignatureLength() == 40);
00448         signer.SignMessage(rng, message, 3, signature);
00449 
00450         DSA::Verifier verifier(dsaPublicKey);
00451         if (!verifier.VerifyMessage(message, 3, signature, 40))
00452         {
00453                 cerr << "DSA signature and verification failed.\n";
00454                 abort();
00455         }
00456         cout << "7. DSA signature and verification succeeded.\n";
00457 
00458 
00459         // try to verify an invalid signature
00460         signature[0] ^= 1;
00461         if (verifier.VerifyMessage(message, 3, signature, 40))
00462         {
00463                 cerr << "DSA signature verification failed to detect bad signature.\n";
00464                 abort();
00465         }
00466         cout << "8. DSA signature verification successfully detected bad signature.\n";
00467 
00468         // try to use an invalid key length
00469         try
00470         {
00471                 encryption_DES_CBC.SetKey(key, 5);
00472 
00473                 // should not be here
00474                 cerr << "DES implementation did not detect use of invalid key length.\n";
00475                 abort();
00476         }
00477         catch (InvalidArgument &e)
00478         {
00479                 cout << "9. Caught expected exception when using invalid key length. Exception message follows: ";
00480                 cout << e.what() << endl;
00481         }
00482 
00483         cout << "\nFIPS 140-2 Sample Application completed normally.\n";
00484 }
00485 
00486 void FIPS140_GenerateRandomFiles()
00487 {
00488 #ifdef OS_RNG_AVAILABLE
00489         AutoSeededX917RNG<DES_EDE3> rng;
00490         RandomNumberStore store(rng, ULONG_MAX);
00491 
00492         for (unsigned int i=0; i<100000; i++)
00493                 store.TransferTo(FileSink((IntToString(i) + ".rnd").c_str()).Ref(), 20000);
00494 #else
00495         cout << "OS provided RNG not available.\n";
00496         exit(-1);
00497 #endif
00498 }
00499 
00500 RandomPool & GlobalRNG()
00501 {
00502         static RandomPool randomPool;
00503         return randomPool;
00504 }
00505 
00506 void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed)
00507 {
00508         RandomPool randPool;
00509         randPool.Put((byte *)seed, strlen(seed));
00510 
00511         RSAES_OAEP_SHA_Decryptor priv(randPool, keyLength);
00512         HexEncoder privFile(new FileSink(privFilename));
00513         priv.DEREncode(privFile);
00514         privFile.MessageEnd();
00515 
00516         RSAES_OAEP_SHA_Encryptor pub(priv);
00517         HexEncoder pubFile(new FileSink(pubFilename));
00518         pub.DEREncode(pubFile);
00519         pubFile.MessageEnd();
00520 }
00521 
00522 string RSAEncryptString(const char *pubFilename, const char *seed, const char *message)
00523 {
00524         FileSource pubFile(pubFilename, true, new HexDecoder);
00525         RSAES_OAEP_SHA_Encryptor pub(pubFile);
00526 
00527         RandomPool randPool;
00528         randPool.Put((byte *)seed, strlen(seed));
00529 
00530         string result;
00531         StringSource(message, true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))));
00532         return result;
00533 }
00534 
00535 string RSADecryptString(const char *privFilename, const char *ciphertext)
00536 {
00537         FileSource privFile(privFilename, true, new HexDecoder);
00538         RSAES_OAEP_SHA_Decryptor priv(privFile);
00539 
00540         string result;
00541         StringSource(ciphertext, true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))));
00542         return result;
00543 }
00544 
00545 void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename)
00546 {
00547         FileSource privFile(privFilename, true, new HexDecoder);
00548         RSASSA_PKCS1v15_SHA_Signer priv(privFile);
00549         // RSASSA_PKCS1v15_SHA_Signer ignores the rng. Use a real RNG for other signature schemes!
00550         FileSource f(messageFilename, true, new SignerFilter(NullRNG(), priv, new HexEncoder(new FileSink(signatureFilename))));
00551 }
00552 
00553 bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename)
00554 {
00555         FileSource pubFile(pubFilename, true, new HexDecoder);
00556         RSASSA_PKCS1v15_SHA_Verifier pub(pubFile);
00557 
00558         FileSource signatureFile(signatureFilename, true, new HexDecoder);
00559         if (signatureFile.MaxRetrievable() != pub.SignatureLength())
00560                 return false;
00561         SecByteBlock signature(pub.SignatureLength());
00562         signatureFile.Get(signature, signature.size());
00563 
00564         VerifierFilter *verifierFilter = new VerifierFilter(pub);
00565         verifierFilter->Put(signature, pub.SignatureLength());
00566         FileSource f(messageFilename, true, verifierFilter);
00567 
00568         return verifierFilter->GetLastResult();
00569 }
00570 
00571 void DigestFile(const char *filename)
00572 {
00573         MD5 md5;
00574         SHA sha;
00575         RIPEMD160 ripemd;
00576         SHA256 sha256;
00577         HashFilter md5Filter(md5), shaFilter(sha), ripemdFilter(ripemd), sha256Filter(sha256);
00578 
00579         auto_ptr<ChannelSwitch> channelSwitch(new ChannelSwitch);
00580         channelSwitch->AddDefaultRoute(md5Filter);
00581         channelSwitch->AddDefaultRoute(shaFilter);
00582         channelSwitch->AddDefaultRoute(ripemdFilter);
00583         channelSwitch->AddDefaultRoute(sha256Filter);
00584         FileSource(filename, true, channelSwitch.release());
00585 
00586         HexEncoder encoder(new FileSink(cout), false);
00587         cout << "\nMD5: ";
00588         md5Filter.TransferTo(encoder);
00589         cout << "\nSHA-1: ";
00590         shaFilter.TransferTo(encoder);
00591         cout << "\nRIPEMD-160: ";
00592         ripemdFilter.TransferTo(encoder);
00593         cout << "\nSHA-256: ";
00594         sha256Filter.TransferTo(encoder);
00595 }
00596 
00597 string EncryptString(const char *instr, const char *passPhrase)
00598 {
00599         string outstr;
00600 
00601         DefaultEncryptorWithMAC encryptor(passPhrase, new HexEncoder(new StringSink(outstr)));
00602         encryptor.Put((byte *)instr, strlen(instr));
00603         encryptor.MessageEnd();
00604 
00605         return outstr;
00606 }
00607 
00608 string DecryptString(const char *instr, const char *passPhrase)
00609 {
00610         string outstr;
00611 
00612         HexDecoder decryptor(new DefaultDecryptorWithMAC(passPhrase, new StringSink(outstr)));
00613         decryptor.Put((byte *)instr, strlen(instr));
00614         decryptor.MessageEnd();
00615 
00616         return outstr;
00617 }
00618 
00619 void EncryptFile(const char *in, const char *out, const char *passPhrase)
00620 {
00621         FileSource f(in, true, new DefaultEncryptorWithMAC(passPhrase, new FileSink(out)));
00622 }
00623 
00624 void DecryptFile(const char *in, const char *out, const char *passPhrase)
00625 {
00626         FileSource f(in, true, new DefaultDecryptorWithMAC(passPhrase, new FileSink(out)));
00627 }
00628 
00629 void SecretShareFile(int threshold, int nShares, const char *filename, const char *seed)
00630 {
00631         assert(nShares<=1000);
00632 
00633         RandomPool rng;
00634         rng.Put((byte *)seed, strlen(seed));
00635 
00636         ChannelSwitch *channelSwitch;
00637         FileSource source(filename, false, new SecretSharing(rng, threshold, nShares, channelSwitch = new ChannelSwitch));
00638 
00639         vector_member_ptrs<FileSink> fileSinks(nShares);
00640         string channel;
00641         for (int i=0; i<nShares; i++)
00642         {
00643                 char extension[5] = ".000";
00644                 extension[1]='0'+byte(i/100);
00645                 extension[2]='0'+byte((i/10)%10);
00646                 extension[3]='0'+byte(i%10);
00647                 fileSinks[i].reset(new FileSink((string(filename)+extension).c_str()));
00648 
00649                 channel = WordToString<word32>(i);
00650                 fileSinks[i]->Put((byte *)channel.data(), 4);
00651                 channelSwitch->AddRoute(channel, *fileSinks[i], BufferedTransformation::NULL_CHANNEL);
00652         }
00653 
00654         source.PumpAll();
00655 }
00656 
00657 void SecretRecoverFile(int threshold, const char *outFilename, char *const *inFilenames)
00658 {
00659         assert(threshold<=1000);
00660 
00661         SecretRecovery recovery(threshold, new FileSink(outFilename));
00662 
00663         vector_member_ptrs<FileSource> fileSources(threshold);
00664         SecByteBlock channel(4);
00665         int i;
00666         for (i=0; i<threshold; i++)
00667         {
00668                 fileSources[i].reset(new FileSource(inFilenames[i], false));
00669                 fileSources[i]->Pump(4);
00670                 fileSources[i]->Get(channel, 4);
00671                 fileSources[i]->Attach(new ChannelSwitch(recovery, string((char *)channel.begin(), 4)));
00672         }
00673 
00674         while (fileSources[0]->Pump(256))
00675                 for (i=1; i<threshold; i++)
00676                         fileSources[i]->Pump(256);
00677 
00678         for (i=0; i<threshold; i++)
00679                 fileSources[i]->PumpAll();
00680 }
00681 
00682 void InformationDisperseFile(int threshold, int nShares, const char *filename)
00683 {
00684         assert(nShares<=1000);
00685 
00686         ChannelSwitch *channelSwitch;
00687         FileSource source(filename, false, new InformationDispersal(threshold, nShares, channelSwitch = new ChannelSwitch));
00688 
00689         vector_member_ptrs<FileSink> fileSinks(nShares);
00690         string channel;
00691         for (unsigned int i=0; i<nShares; i++)
00692         {
00693                 char extension[5] = ".000";
00694                 extension[1]='0'+byte(i/100);
00695                 extension[2]='0'+byte((i/10)%10);
00696                 extension[3]='0'+byte(i%10);
00697                 fileSinks[i].reset(new FileSink((string(filename)+extension).c_str()));
00698 
00699                 channel = WordToString<word32>(i);
00700                 fileSinks[i]->Put((byte *)channel.data(), 4);
00701                 channelSwitch->AddRoute(channel, *fileSinks[i], BufferedTransformation::NULL_CHANNEL);
00702         }
00703 
00704         source.PumpAll();
00705 }
00706 
00707 void InformationRecoverFile(int threshold, const char *outFilename, char *const *inFilenames)
00708 {
00709         assert(threshold<=1000);
00710 
00711         InformationRecovery recovery(threshold, new FileSink(outFilename));
00712 
00713         vector_member_ptrs<FileSource> fileSources(threshold);
00714         SecByteBlock channel(4);
00715         unsigned int i;
00716         for (i=0; i<threshold; i++)
00717         {
00718                 fileSources[i].reset(new FileSource(inFilenames[i], false));
00719                 fileSources[i]->Pump(4);
00720                 fileSources[i]->Get(channel, 4);
00721                 fileSources[i]->Attach(new ChannelSwitch(recovery, string((char *)channel.begin(), 4)));
00722         }
00723 
00724         while (fileSources[0]->Pump(256))
00725                 for (i=1; i<threshold; i++)
00726                         fileSources[i]->Pump(256);
00727 
00728         for (i=0; i<threshold; i++)
00729                 fileSources[i]->PumpAll();
00730 }
00731 
00732 void GzipFile(const char *in, const char *out, int deflate_level)
00733 {
00734 //      FileSource(in, true, new Gzip(new FileSink(out), deflate_level));
00735 
00736         // use a filter graph to compare decompressed data with original
00737         //
00738         // Source ----> Gzip ------> Sink
00739         //    \           |
00740         //          \       Gunzip
00741         //                \       |
00742         //                  \     v
00743         //                    > ComparisonFilter 
00744                            
00745         EqualityComparisonFilter comparison;
00746 
00747         Gunzip gunzip(new ChannelSwitch(comparison, "0"));
00748         gunzip.SetAutoSignalPropagation(0);
00749 
00750         FileSink sink(out);
00751 
00752         ChannelSwitch *cs;
00753         Gzip gzip(cs = new ChannelSwitch(sink), deflate_level);
00754         cs->AddDefaultRoute(gunzip);
00755 
00756         cs = new ChannelSwitch(gzip);
00757         cs->AddDefaultRoute(comparison, "1");
00758         FileSource source(in, true, cs);
00759 
00760         comparison.ChannelMessageSeriesEnd("0");
00761         comparison.ChannelMessageSeriesEnd("1");
00762 }
00763 
00764 void GunzipFile(const char *in, const char *out)
00765 {
00766         FileSource(in, true, new Gunzip(new FileSink(out)));
00767 }
00768 
00769 void Base64Encode(const char *in, const char *out)
00770 {
00771         FileSource(in, true, new Base64Encoder(new FileSink(out)));
00772 }
00773 
00774 void Base64Decode(const char *in, const char *out)
00775 {
00776         FileSource(in, true, new Base64Decoder(new FileSink(out)));
00777 }
00778 
00779 void HexEncode(const char *in, const char *out)
00780 {
00781         FileSource(in, true, new HexEncoder(new FileSink(out)));
00782 }
00783 
00784 void HexDecode(const char *in, const char *out)
00785 {
00786         FileSource(in, true, new HexDecoder(new FileSink(out)));
00787 }
00788 
00789 void ForwardTcpPort(const char *sourcePortName, const char *destinationHost, const char *destinationPortName)
00790 {
00791 #ifdef SOCKETS_AVAILABLE
00792         SocketsInitializer sockInit;
00793 
00794         Socket sockListen, sockSource, sockDestination;
00795 
00796         int sourcePort = Socket::PortNameToNumber(sourcePortName);
00797         int destinationPort = Socket::PortNameToNumber(destinationPortName);
00798 
00799         sockListen.Create();
00800         sockListen.Bind(sourcePort);
00801 
00802         cout << "Listing on port " << sourcePort << ".\n";
00803         sockListen.Listen();
00804 
00805         sockListen.Accept(sockSource);
00806         cout << "Connection accepted on port " << sourcePort << ".\n";
00807         sockListen.CloseSocket();
00808 
00809         cout << "Making connection to " << destinationHost << ", port " << destinationPort << ".\n";
00810         sockDestination.Create();
00811         sockDestination.Connect(destinationHost, destinationPort);
00812 
00813         cout << "Connection made to " << destinationHost << ", starting to forward.\n";
00814 
00815         SocketSource out(sockSource, false, new SocketSink(sockDestination));
00816         SocketSource in(sockDestination, false, new SocketSink(sockSource));
00817 
00818         WaitObjectContainer waitObjects;
00819 
00820         while (!(in.SourceExhausted() && out.SourceExhausted()))
00821         {
00822                 waitObjects.Clear();
00823 
00824                 out.GetWaitObjects(waitObjects);
00825                 in.GetWaitObjects(waitObjects);
00826 
00827                 waitObjects.Wait(INFINITE_TIME);
00828 
00829                 if (!out.SourceExhausted())
00830                 {
00831                         cout << "o" << flush;
00832                         out.PumpAll2(false);
00833                         if (out.SourceExhausted())
00834                                 cout << "EOF received on source socket.\n";
00835                 }
00836 
00837                 if (!in.SourceExhausted())
00838                 {
00839                         cout << "i" << flush;
00840                         in.PumpAll2(false);
00841                         if (in.SourceExhausted())
00842                                 cout << "EOF received on destination socket.\n";
00843                 }
00844         }
00845 #else
00846         cout << "Socket support was not enabled at compile time.\n";
00847         exit(-1);
00848 #endif
00849 }
00850 
00851 bool Validate(int alg, bool thorough, const char *seed)
00852 {
00853         bool result;
00854 
00855         std::string timeSeed;
00856         if (!seed)
00857         {
00858                 timeSeed = IntToString(time(NULL));
00859                 seed = timeSeed.c_str();
00860         }
00861 
00862         cout << "Using seed: " << seed << endl << endl;
00863         GlobalRNG().Put((const byte *)seed, strlen(seed));
00864 
00865         switch (alg)
00866         {
00867         case 1: result = TestSettings(); break;
00868         case 2: result = TestOS_RNG(); break;
00869         case 3: result = ValidateMD5(); break;
00870         case 4: result = ValidateSHA(); break;
00871         case 5: result = ValidateDES(); break;
00872         case 6: result = ValidateIDEA(); break;
00873         case 7: result = ValidateARC4(); break;
00874         case 8: result = ValidateRC5(); break;
00875         case 9: result = ValidateBlowfish(); break;
00876         case 10: result = ValidateDiamond2(); break;
00877         case 11: result = ValidateThreeWay(); break;
00878         case 12: result = ValidateBBS(); break;
00879         case 13: result = ValidateDH(); break;
00880         case 14: result = ValidateRSA(); break;
00881         case 15: result = ValidateElGamal(); break;
00882         case 16: result = ValidateDSA(thorough); break;
00883         case 17: result = ValidateHAVAL(); break;
00884         case 18: result = ValidateSAFER(); break;
00885         case 19: result = ValidateLUC(); break;
00886         case 20: result = ValidateRabin(); break;
00887 //      case 21: result = ValidateBlumGoldwasser(); break;
00888         case 22: result = ValidateECP(); break;
00889         case 23: result = ValidateEC2N(); break;
00890         case 24: result = ValidateMD5MAC(); break;
00891         case 25: result = ValidateGOST(); break;
00892         case 26: result = ValidateTiger(); break;
00893         case 27: result = ValidateRIPEMD(); break;
00894         case 28: result = ValidateHMAC(); break;
00895         case 29: result = ValidateXMACC(); break;
00896         case 30: result = ValidateSHARK(); break;
00897         case 32: result = ValidateLUC_DH(); break;
00898         case 33: result = ValidateLUC_DL(); break;
00899         case 34: result = ValidateSEAL(); break;
00900         case 35: result = ValidateCAST(); break;
00901         case 36: result = ValidateSquare(); break;
00902         case 37: result = ValidateRC2(); break;
00903         case 38: result = ValidateRC6(); break;
00904         case 39: result = ValidateMARS(); break;
00905         case 40: result = ValidateRW(); break;
00906         case 41: result = ValidateMD2(); break;
00907         case 42: result = ValidateNR(); break;
00908         case 43: result = ValidateMQV(); break;
00909         case 44: result = ValidateRijndael(); break;
00910         case 45: result = ValidateTwofish(); break;
00911         case 46: result = ValidateSerpent(); break;
00912         case 47: result = ValidateCipherModes(); break;
00913         case 48: result = ValidateCRC32(); break;
00914         case 49: result = ValidateECDSA(); break;
00915         case 50: result = ValidateXTR_DH(); break;
00916         case 51: result = ValidateSKIPJACK(); break;
00917         case 52: result = ValidateSHA2(); break;
00918         case 53: result = ValidatePanama(); break;
00919         case 54: result = ValidateAdler32(); break;
00920         case 55: result = ValidateMD4(); break;
00921         case 56: result = ValidatePBKDF(); break;
00922         case 57: result = ValidateESIGN(); break;
00923         case 58: result = ValidateDLIES(); break;
00924         case 59: result = ValidateBaseCode(); break;
00925         default: result = ValidateAll(thorough); break;
00926         }
00927 
00928         time_t endTime = time(NULL);
00929         cout << "\nTest ended at " << asctime(localtime(&endTime));
00930         cout << "Seed used was: " << seed << endl;
00931 
00932         return result;
00933 }

Generated on Sun Mar 14 20:44:29 2004 for Crypto++ by doxygen 1.3.6-20040222