Advertisement
Guest User

Brendan Long

a guest
Mar 30th, 2010
773
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.84 KB | None | 0 0
  1. /*!
  2.  * Simple AES
  3.  * Brendan Long
  4.  * March 29, 2010
  5.  *
  6.  * Simplified encryption and decryption using OpenSSL's AES library.
  7.  * Remember to compile with -lcrypto and link against the library
  8.  * g++ (your stuff) -lcrypto simpleAes.cpp (or simpleAes.o)
  9.  *
  10.  * Implementation note: Using the default ivec (0) is not secure. For
  11.  *                      the full security that AES offers, use a different
  12.  *                      ivec each time (it does not need to be secret,
  13.  *                      just different.
  14.  *
  15.  * This code is released into the public domain. Yada yada..
  16.  * Read this for details: http://creativecommons.org/licenses/publicdomain/
  17.  *
  18.  * If for some reason public domain isn't good enough, you may use, alter,
  19.  * distribute or do anything else you want with this code with no restrictions.
  20.  */
  21.  
  22. #include <openssl/aes.h>
  23. #include <openssl/evp.h>
  24. #include <iostream>
  25. #include <string.h>
  26.  
  27. // On Linux, we'll seed openssl with /dev/urandom, on others we use the time
  28. #ifdef __unix__
  29. #include <fstream>
  30. #elif _win32
  31. #include <Wincrypt.h>
  32. #endif
  33.  
  34. /*!
  35.  * Generates 16 random numbers for the initialization vector.
  36.  * On Linux, this uses /dev/urandom, on other platforms, it uses c's rand() function
  37.  * \param ivec An unsigned char[16] to fill with random numbers
  38.  * \return True on success, false otherwise
  39.  */
  40. bool getRandomIvec(unsigned char* ivec){
  41.    
  42. #ifdef __unix__
  43.  
  44.     // Read 16 bytes from /dev/urandom
  45.     std::ifstream fin("/dev/urandom", std::ios_base::in | std::ios_base::binary);
  46.     if(!fin.fail()){
  47.         fin.read((char*)ivec, 16);
  48.     }
  49.     else{
  50.         fin.open("/dev/urandom", std::ios_base::in | std::ios_base::binary);
  51.         if(!fin.fail()){
  52.             fin.read((char*)ivec, 16);
  53.         }
  54.         else return false;
  55.     }
  56.     fin.close();
  57.     return true;
  58.  
  59. #elif _win32
  60.    
  61.     // I don't have a clue if this works..
  62.     HCRYPTPROV hCryptProv;
  63.     CryptAcquireContext( &hCryptProv,  NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
  64.     if(CryptGenRandom(hCryptProv, 16, (BYTE*) ivec)){
  65.         printf("Random sequence generated. \n");
  66.     }
  67.     else{
  68.         std::cout << "ERROR: CryptGenRandom failed." << std::endl;
  69.         return NULL;
  70.     }
  71.  
  72. #else
  73.  
  74.     // uhh...
  75.  
  76. #endif
  77. }
  78.  
  79. /*!
  80.  * Encrypts a string using AES 256
  81.  * Note: If the key is less than 32 bytes, it will be null padded.
  82.  *       If the key is greater than 32 bytes, it will be truncated
  83.  * \param in The string to encrypt
  84.  * \param key The key to encrypt with
  85.  * \return The encrypted data
  86.  */
  87. std::string aes_encrypt(std::string in, std::string key){
  88.  
  89.     unsigned char ivec[16];
  90.     getRandomIvec(ivec);
  91.     std::string ivecString((char*) ivec, 16); // Save this for later
  92.  
  93.     // Always pad the key to 32 bits.. because we can
  94.     if(key.length() < 32){
  95.         key.append(32 - key.length(), '\0');
  96.     }
  97.    
  98.     // Get some space ready for the output
  99.     unsigned char *output = new unsigned char[in.length() + AES_BLOCK_SIZE];
  100.    
  101.     // Encrypt the data
  102.     int length, finalLength = 0;
  103.     EVP_CIPHER_CTX *encryptHandle = new EVP_CIPHER_CTX;
  104.     EVP_CIPHER_CTX_init(encryptHandle);
  105.     EVP_EncryptInit_ex(encryptHandle, EVP_aes_256_cbc(), NULL, (unsigned char*) key.c_str(), ivec);
  106.     EVP_EncryptUpdate(encryptHandle, output, &length, (unsigned char*)in.c_str(), in.length());
  107.     finalLength += length;
  108.     EVP_EncryptFinal_ex(encryptHandle, output + length, &length);
  109.     finalLength += length;
  110.  
  111.     // Make the data into a string
  112.     std::string ret((char*) output, finalLength);
  113.    
  114.     // clean up
  115.     delete output;
  116.     EVP_CIPHER_CTX_cleanup(encryptHandle);
  117.     delete encryptHandle;
  118.    
  119.     return ivecString + ret;
  120. }
  121.  
  122. /*!
  123.  * Decrypts a string using AES 256
  124.  * Note: If the key is less than 32 bytes, it will be null padded.
  125.  *       If the key is greater than 32 bytes, it will be truncated
  126.  * \param in The string to decrypt
  127.  * \param key The key to decrypt with
  128.  * \return The decrypted data
  129.  */
  130. std::string aes_decrypt(std::string in, std::string key){
  131.  
  132.     // Get the ivec from the front
  133.     unsigned char ivec[16];
  134.     strncpy((char*)ivec, in.c_str(), 16);
  135.     in = in.substr(16);
  136.  
  137.     // Always pad the key to 32 bits.. because we can
  138.     if(key.length() < 32){
  139.         key.append(32 - key.length(), '\0');
  140.     }
  141.  
  142.     // Create some space for output
  143.     unsigned char *output = new unsigned char[in.length()];
  144.     int length, finalLength = 0;
  145.    
  146.     // Decrypt the string
  147.     EVP_CIPHER_CTX *encryptHandle = new EVP_CIPHER_CTX;
  148.     EVP_CIPHER_CTX_init(encryptHandle);
  149.     EVP_DecryptInit_ex(encryptHandle, EVP_aes_256_cbc(), NULL, (unsigned char*) key.c_str(), ivec);
  150.     EVP_DecryptUpdate(encryptHandle, output, &length, (unsigned char*)in.c_str(), in.length());
  151.     finalLength += length;
  152.     EVP_DecryptFinal_ex(encryptHandle, output + length, &length);
  153.     finalLength += length;
  154.    
  155.     std::cout << finalLength << std::endl;
  156.    
  157.     // Make the output into a string
  158.     std::string ret((char*) output, finalLength);
  159.    
  160.     // Clean up
  161.     delete output;
  162.     EVP_CIPHER_CTX_cleanup(encryptHandle);
  163.     delete encryptHandle;
  164.    
  165.     return ret;
  166. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement