pastebin - collaborative debugging

pastebin is a collaborative debugging tool allowing you to share and modify code snippets while chatting on IRC, IM or a message board.

This site is developed to XHTML and CSS2 W3C standards. If you see this paragraph, your browser does not support those standards and you need to upgrade. Visit WaSP for a variety of options.

C++ pastebin - collaborative debugging tool View Help


Posted by swarmapps on Tue 24 Nov 03:15
report abuse | View followups from Aaron Polley and Aaron Polley | download | new post

  1. // BasicCryptoPPWrap.h
  2. // By: Michael R. Rich, 2009
  3. // This code is placed into the public domain by its author
  4. // No warranty or guarantee of applicability or function is granted.
  5.  
  6. // This is a wrapper designed to allow rapid use of the Crypto++ cryptographic library in a multitude of applications.
  7. // It permits a developer with a nominal understanding of C++ to rapidly field apps that use cryptography to provide basic confidentiality.
  8. // I wrote it so that a developer need not use any other variable types than string to encrypt and decrypt at will.
  9. // Encrypting a string is as simple as:
  10. //        string plainText = "I don't want anyone seeing this without my permission!"
  11. //        string key = BasicCryptoPPWrap::BitGen(256);        // Better not lose this key!!
  12. //        bool err;
  13. //                string errMsg;
  14. //        string cipherText = BasicCryptoPPWrap::MREncryptStringAES(plainText, key, &err, &errMsg);
  15. // The returned string is not directly viewable.  In this case the string class is used as a handy data buffer for the crypto work.  If you want to see the
  16. // string, simply do this:
  17. //        cout << BasicCryptoPPWrap::HexEncode(cipherText) << "\n";
  18. // To see the text again:
  19. //        string recoveredText = BasicCryptoPPWrap::MRDecryptStringAES(cipherText, key, &err, &errMsg);
  20. //        cout << recoveredText << "\n";
  21. // A more comprehensive example can be seen in the sample code provided with this header
  22.  
  23. // To use the wrapper, you first need to successfully build and test the Crypto++ library.
  24. // Visit the Crypto++ hompage (www.cryptopp.com) for the latest code, build, and test instructions.
  25. // Then, add the Crypto++ directory to your include directories, link to the cryptopp library and include this header in your code.
  26.  
  27. // The Crypto++ library is a very powerful set of cryptographic tools, but I found the learning curve to get my first apps running with
  28. // it to be very high.  I examined all the sample code I could find, worked through the API documentation, and examined the
  29. // validation and test code before I finally started catching on.  Then I had to "grep" my way through the files to identify which headers I
  30. // needed to include for a given function.  All of this brainache is undoubtedly due to my own lack of skill and formal training.
  31.  
  32. // Nonetheless, once I got the pattern figured out, I didn't want to repeat it all over the place in my code, so I wrote this wrapper.
  33. // I don't want you to go through the same thing, so I'm offering this wrapper to those who can use it.
  34.  
  35. // This simplification comes at a cost of flexibility and performance.  I hope you outgrow this wrapper.  But, until you do, use it well!
  36.  
  37. // WARNINGS!!
  38. // Data encrypted with methods starting with "MREncrypt" implement a custom initialization vector protocol.  Essentially the iv is either prepended to
  39. // the string or the file you are using.  The "MRDecrypt" methods should be used to decrypt them.  Methods without the "MR" prefix are
  40. // designed to work with a separately supplied iv.
  41. //
  42. // The binary "strings" returned by this wrapper do not play well with the formatted input and output functions and operators (i.e. <<, >>, getLine, etc..)
  43. // You should use binary, unformatted functions to move them around.  See the MREncryptFileAES and MRDecryptFileAES methods for examples.
  44. //
  45. // This wrapper currently only uses one mode of AES encryption.  See flexibility and performance warning above!
  46. //
  47. // I am not a Crypto anything.  The word novice hardly even applies to me.  I am using the Crypto++ library in it's most basic form.
  48. // As a result, I wouldn't use this wrapper in anything serious like financial or medical records, or access to critical infrastructure control
  49. // routines.  I'm just saying.
  50.  
  51. // If you get a weird link error like "variable not in vtable" or "virtual thunk", add -DCRYPTOPP_DISABLE_ASM to the build options.
  52. // This apparently happens on Mac OS X from time to time (it happened to me)
  53.  
  54.  
  55. #ifndef __MRCRYPTOWRAP_H
  56. #define __MRCRYPTOWRAP_H
  57.  
  58. #include <iostream>
  59. #include <string>
  60. #include <cstdio>
  61. #include "config.h"
  62. #include "hex.h"
  63. #include "files.h"
  64. #include "cryptlib.h"
  65. #include "modes.h"
  66. #include "osrng.h"
  67. #include "filters.h"
  68. #include "aes.h"
  69.  
  70. using namespace std;
  71. using namespace CryptoPP;
  72.  
  73. class BasicCryptoPPWrap {
  74. public:
  75.        
  76.         static bool isHex(string checkForHex) {
  77.                 size_t found;
  78.                 found = checkForHex.find_first_not_of("0123456789ABCDEF");
  79.                 if (found!=string::npos) {
  80.                         // This string has non-hex characters in it
  81.                         return false;
  82.                 } else {
  83.                         // only hex characters
  84.                         return true;
  85.                 }
  86.         }
  87.        
  88.         static string HexEncode(string binaryString) {
  89.                
  90.                 if (isHex(binaryString)) {
  91.                         // This string is already hex, don't convert it!
  92.                         return binaryString;
  93.                 } else {
  94.                         string hexString;
  95.                         StringSource(binaryString, true, new HexEncoder(new StringSink(hexString)));
  96.                         return hexString;
  97.                 }
  98.         }
  99.        
  100.         static string HexDecode(string hexString) {
  101.                 if (isHex(hexString)) {
  102.                         string binaryString;
  103.                         StringSource(hexString, true, new HexDecoder(new StringSink(binaryString)));
  104.                         return binaryString;
  105.                 } else {
  106.                         // it's already binary!
  107.                         return hexString;
  108.                 }
  109.         }    
  110.    
  111.         static string MREncryptStringAES(string plainText, string key, bool &err, string &errMsg) {
  112.                 // returns an encypted string in binary
  113.                 // This version will generate a random 16 byte initialization vector (iv) and prepend it to the actual encrypted text
  114.                 // Use MRDecryptStringAES to decrypt this string
  115.                 // use EncryptStringAES(plainText, key, iv, err) if you have already have an iv you want to use.
  116.                 // key can be sent as a true binary "string" or a hex encoded string
  117.                 try {
  118.                         // get a random iv
  119.                         string iv = ByteGen(AES::BLOCKSIZE);    // BLOCKSIZE is in bytes
  120.                        
  121.                         // convert the key if it is sent in hex
  122.                         key = HexDecode(key);
  123.                                                
  124.                        
  125.                         string cipherText = EncryptStringAES(plainText, key, iv, err, errMsg);
  126.                         if (err) return "ERROR";
  127.                        
  128.                         return iv+cipherText;
  129.                        
  130.                 } catch (Exception& e) {
  131.                         string errText = "Bad encrypt";
  132.                         errMsg = e.GetWhat();
  133.                         err = true;
  134.                         return errText;
  135.                 }
  136.         }
  137.        
  138.         static string EncryptStringAES(string plainText, string key, string iv, bool &err, string &errMsg) {
  139.                 // returns an encypted string in binary
  140.                 // This version uses the given iv and returns only the cipherText with no prepend
  141.                 // use EncryptStringAES(plainText, key, err) if you want a random iv
  142.                 // key and iv can be sent as a true binary "string" or a hex encoded string
  143.                 try {
  144.                         // convert the iv if it is sent in hex
  145.                         iv = HexDecode(iv);                    
  146.                        
  147.                         // convert the key if it is sent in hex
  148.                         key = HexDecode(key);                  
  149.                        
  150.                         // setup the encyptor
  151.                         CBC_Mode< Rijndael >::Encryption e1( (byte *)key.c_str(), key.length(), (byte *)iv.c_str() );
  152.                         // Encryption
  153.                         string cipherText;
  154.                         StringSource( plainText, true,
  155.                                                  new StreamTransformationFilter( e1, new CryptoPP::StringSink( cipherText )));
  156.                        
  157.                         // return the concatated iv and cipherText
  158.                         err = false;
  159.                         return cipherText;
  160.                 } catch (Exception& e) {
  161.                         string errText = "Bad encrypt";
  162.                         errMsg = e.GetWhat();
  163.                         err = true;
  164.                         return errText;
  165.                 }
  166.                
  167.         }
  168.        
  169.         static string MRDecryptStringAES(string ivAndCipherText, string key, bool &err, string &errMsg){
  170.                 // returns the decrypted string
  171.                 // This version expects a 16-byte initialization vector prepended to the cipherText
  172.                 // This is the output generated by MREncryptStringAES
  173.                 // ivAndCipherText & key can be given as hex or binary
  174.                 try {
  175.                         // convert ivAndCipherText as neccessary
  176.                         ivAndCipherText = HexDecode(ivAndCipherText);
  177.                                                
  178.                         // convert key if necessary
  179.                         key = HexDecode(key);
  180.                                                
  181.                         // recover the bits of the message
  182.                         string iv;
  183.                         iv.assign(ivAndCipherText, 0, 16);
  184.                         string cipherText;
  185.                         cipherText.assign(ivAndCipherText, 16, string::npos);
  186.                        
  187.                         string plainText = DecryptStringAES(cipherText, key, iv, err, errMsg);
  188.                         if (err) return "ERROR";
  189.                        
  190.                         err = false;
  191.                         return plainText;
  192.                 } catch (Exception& e) {
  193.                         string errText = "Bad decrypt";
  194.                         errMsg = e.GetWhat();
  195.                         err = true;
  196.                         return errText;
  197.                 }
  198.         }
  199.        
  200.         static string DecryptStringAES(string cipherText, string key, string iv, bool &err, string &errMsg){
  201.                 // returns the decrypted string
  202.                 // This version uses the given iv
  203.                 // use DecryptStringAES(cipherText, key, err) if the iv is prepended to the cipherText
  204.                 // cipherText, key, and iv can be given as hex or binary
  205.                 try {
  206.                         // convert ivAndCipherText as neccessary
  207.                         cipherText = HexDecode(cipherText);
  208.                                                
  209.                         // convert key if necessary
  210.                         key = HexDecode(key);
  211.                                                
  212.                         // convert iv if necessary
  213.                         if (isHex(iv)) {
  214.                                 iv = HexDecode(iv);
  215.                         }
  216.                        
  217.                         // set up decrypter
  218.                         CBC_Mode< Rijndael >::Decryption d((byte *)key.c_str(), key.length(), (byte *)iv.c_str());
  219.                         // decrypt
  220.                         string plainText;
  221.                         StringSource( cipherText, true, new StreamTransformationFilter( d, new StringSink( plainText)));
  222.                         err = false;
  223.                         return plainText;
  224.                 } catch (Exception& e) {
  225.                         string errText = "Bad decrypt";
  226.                         errMsg = e.GetWhat();
  227.                         err = true;
  228.                         return errText;
  229.                 }
  230.         }
  231.        
  232.         static void EncryptFileAES(istream& inFile, ostream& outFile, string key, string iv, bool &err, string &errMsg) {
  233.                 // will encrypt the file at filenameIn to filenameOut using AES
  234.                 // WARNING: The iv must be known and retained for decryption!!
  235.                 // key and iv can be hex or binary
  236.                
  237.                
  238.                 // convert the key and iv
  239.                 key = HexDecode(key);
  240.                 iv = HexDecode(iv);
  241.                 try {
  242.                         // Set up the encrypter
  243.                         CBC_Mode< Rijndael >::Encryption e1( (byte *)key.c_str(), key.length(), (byte *)iv.c_str() );
  244.                         // encrypt
  245.                         //if (filenameOut == "cout")
  246.                         //      FileSource( filenameIn.c_str(), true, new StreamTransformationFilter( e1, new FileSink(cout)));
  247.                         //else
  248.                                 FileSource( inFile, true, new StreamTransformationFilter( e1, new FileSink(outFile)));
  249.                         err= false;
  250.                         return;
  251.                 } catch (Exception& e) {
  252.                         errMsg = e.GetWhat();
  253.                         err = true;
  254.                         return;
  255.                 }
  256.         }
  257.        
  258.        
  259.         static void MREncryptFileAES(istream& inFile, ostream& outFile, string key, bool &err, string &errMsg) {
  260.                 // will encrypt the file at inFile to outFile using AES
  261.                 // but, adds a random iv to the beginning of the newly encrypted file which is recovered and used to decrypt it later.
  262.                 // Use MRDecryptFileAES to decrypt this file
  263.                 // key can be hex or binary
  264.                 // programmers job to open and close the istream and ostream correctly!
  265.                
  266.                 string iv = ByteGen(AES::BLOCKSIZE);
  267.                
  268.                 // encrypt the file to temp
  269.                 // generate a random file name that is unlikely to conflict with any existing names.
  270.                 string tempName = HexEncode(ByteGen(8));
  271.                 ofstream tempFile(tempName.c_str(), ios::binary);
  272.                 EncryptFileAES(inFile, tempFile, key, iv, err, errMsg);
  273.                 if (err) return;
  274.                 tempFile.close();
  275.                
  276.                 try {
  277.                         // Now open a new file and put the iv in it
  278.                                        
  279.                         if (!outFile.good()) {
  280.                                 err = true;
  281.                                 errMsg = "Couldn't open desired output file";
  282.                                 return;
  283.                         }
  284.                        
  285.                         //write the iv to it
  286.                         outFile.write(iv.c_str(), iv.length());
  287.                        
  288.                         // open the temp file and load into memory..
  289.                         ifstream::pos_type size;
  290.                         char * memblock;
  291.                        
  292.                         ifstream file(tempName.c_str(), ios::binary | ios::ate);
  293.                         if (file.is_open()) {
  294.                                 size = file.tellg();
  295.                                 memblock = new char [size];
  296.                                 file.seekg (0, ios::beg);
  297.                                 file.read (memblock, size);
  298.                                 file.close();
  299.                         } else {
  300.                                 err = true;
  301.                                 errMsg = "Couldn't open encrypted temp file";
  302.                                 return;
  303.                         }
  304.                        
  305.                         // write the data to the finished file
  306.                         outFile.write(memblock, size);
  307.                        
  308.                         delete[] memblock;
  309.                        
  310.                         // delete the temp file
  311.                         remove(tempName.c_str());
  312.                         err = false;
  313.                         return;
  314.                        
  315.                 } catch (std::exception &e) {
  316.                         errMsg = e.what();
  317.                         err = true;
  318.                         return;
  319.                 }
  320.         }
  321.        
  322.                
  323.         static void DecryptFileAES(istream& inFile, ostream& outFile, string key, string iv, bool &err, string &errMsg) {
  324.                 // will encrypt the file at filenameIn to filenameOut using AES
  325.                 // WARNING: The correct iv MUST be provided
  326.                 // key and iv can be hex or binary
  327.                
  328.                 // convert the key and iv
  329.                 key = HexDecode(key);
  330.                 iv = HexDecode(iv);
  331.                
  332.                 try {
  333.                         // Set up the encrypter
  334.                         CBC_Mode< Rijndael >::Decryption d ( (byte *)key.c_str(), key.length(), (byte *)iv.c_str() );
  335.                         // encrypt
  336.                         //if (filenameOut == "cout")
  337.                         //      FileSource( filenameIn.c_str(), true, new StreamTransformationFilter( d, new FileSink(cout)));
  338.                         //else
  339.                                 FileSource( inFile, true, new StreamTransformationFilter( d, new FileSink(outFile)));
  340.                         err= false;
  341.                         return;
  342.                 } catch (Exception& e) {
  343.                         errMsg = e.GetWhat();
  344.                         err = true;
  345.                         return;
  346.                 }
  347.         }
  348.        
  349.         static void MRDecryptFileAES(istream& inFile, ostream& outFile, string key, bool &err, string &errMsg) {
  350.                 // Decrypts a file with a iv stored as the initial 16 bytes;
  351.                 // This type of file is generated by MREncryptFileAES
  352.                
  353.                 // first, open the file and load into memory..
  354.                 ifstream::pos_type size;
  355.                 int datasize;
  356.                 char * ivblock;
  357.                 char * datablock;
  358.                
  359.                 if (inFile.good()) {
  360.                         inFile.seekg(0, ios::end);
  361.                         size = inFile.tellg();
  362.                         inFile.seekg(0, ios::beg);
  363.                         datasize = (int)size-16;
  364.                         ivblock = new char[16];
  365.                         datablock = new char[datasize];
  366.                         inFile.read (ivblock, 16);
  367.                         inFile.read(datablock, datasize);
  368.                        
  369.                 } else {
  370.                         err = true;
  371.                         errMsg = "Couldn't open encrypted input file";
  372.                         return;
  373.                 }
  374.                
  375.                 // Make the iv
  376.                 string iv;
  377.                 iv.assign(ivblock, 16);
  378.                 delete[] ivblock;
  379.                
  380.                 //save the rest of the data as a temp file
  381.                 // generate a random file name that is unlikely to conflict with any existing names.
  382.                 string tempFile = HexEncode(ByteGen(8));
  383.                 ofstream tempOut(tempFile.c_str(), ios::binary);
  384.                 if (tempOut.is_open()) {
  385.                         // save the data here.
  386.                         tempOut.write(datablock, (datasize));
  387.                         tempOut.close();
  388.                         delete[] datablock;
  389.                 } else {
  390.                         err = true;
  391.                         errMsg = "Couldn't create encrypted temporary file";
  392.                         delete[] datablock;
  393.                         return;
  394.                 }
  395.                
  396.                 ifstream tempIn(tempFile.c_str(), ios::binary);
  397.                 // Now decrypt the temp file
  398.                 DecryptFileAES(tempIn, outFile, key, iv, err, errMsg);
  399.                
  400.                 tempIn.close();
  401.                 remove(tempFile.c_str());              
  402.                 if (err) return;
  403.                
  404.                 err = false;
  405.                 return;
  406.         }              
  407.        
  408.         static string BitGen(int howManyBits) {
  409.                 // returns a new random key in binary of the given bit length
  410.                 int byteLength = howManyBits/8; // bitLengths always better be div 8!!
  411.                 return ByteGen(byteLength);
  412.         }
  413.        
  414.         static string ByteGen(int howManyBytes) {
  415.                 // returns a new random key of the given byte length
  416.                 AutoSeededRandomPool rnd;
  417.                 byte block[howManyBytes];
  418.                 rnd.GenerateBlock(block, howManyBytes);
  419.                 string blockString;
  420.                 blockString.assign((char *)block, sizeof(block));
  421.                 return blockString;
  422.         }
  423.  
  424.        
  425.         static string hashSHA256(string inputString) {
  426.                 // returns a SHA-256 encoded hash of the inputString in binary
  427.                 // always returns 256 bits
  428.                 SHA256 hash;
  429.                 byte digest [ SHA256::DIGESTSIZE ];
  430.                
  431.                 hash.CalculateDigest( digest, (byte *)inputString.c_str(), inputString.length() );
  432.                 string hashString;
  433.                 hashString.assign((char *)digest, sizeof(digest));
  434.                
  435.                 return hashString;
  436.         }       
  437.        
  438. };
  439.  
  440. #endif

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with @@


Remember me so that I can delete my post