| /*!␊ | 
| * Simple AES␊ | 
| * Brendan Long␊ | 
| * March 29, 2010␊ | 
| * ␊ | 
| * Simplified encryption and decryption using OpenSSL's AES library.␊ | 
| * Remember to compile with -lcrypto and link against the library␊ | 
| * g++ (your stuff) -lcrypto simpleAes.cpp (or simpleAes.o)␊ | 
| *␊ | 
| * Implementation note: Using the default ivec (0) is not secure. For␊ | 
| *                      the full security that AES offers, use a different␊ | 
| *                      ivec each time (it does not need to be secret,␊ | 
| *                      just different.␊ | 
| *␊ | 
| * This code is released into the public domain. Yada yada..␊ | 
| * Read this for details: http://creativecommons.org/licenses/publicdomain/␊ | 
| *␊ | 
| * If for some reason public domain isn't good enough, you may use, alter,␊ | 
| * distribute or do anything else you want with this code with no restrictions.␊ | 
| */␊ | 
| ␊ | 
| #include <openssl/aes.h>␊ | 
| #include <openssl/evp.h>␊ | 
| #include <iostream>␊ | 
| #include <string.h>␊ | 
| ␊ | 
| // On Linux, we'll seed openssl with /dev/urandom, on others we use the time␊ | 
| #ifdef __unix__␊ | 
| #include <fstream>␊ | 
| #elif _win32␊ | 
| #include <Wincrypt.h>␊ | 
| #endif␊ | 
| ␊ | 
| /*!␊ | 
| * Generates 16 random numbers for the initialization vector.␊ | 
| * On Linux, this uses /dev/urandom, on other platforms, it uses c's rand() function␊ | 
| * \param ivec An unsigned char[16] to fill with random numbers␊ | 
| * \return True on success, false otherwise␊ | 
| */␊ | 
| bool getRandomIvec(unsigned char* ivec){␊ | 
| ␉␊ | 
| #ifdef __unix__␊ | 
| ␊ | 
| ␉// Read 16 bytes from /dev/urandom␊ | 
| ␉std::ifstream fin("/dev/urandom", std::ios_base::in | std::ios_base::binary);␊ | 
| ␉if(!fin.fail()){␊ | 
| ␉␉fin.read((char*)ivec, 16);␊ | 
| ␉}␊ | 
| ␉else{␊ | 
| ␉␉fin.open("/dev/urandom", std::ios_base::in | std::ios_base::binary);␊ | 
| ␉␉if(!fin.fail()){␊ | 
| ␉␉␉fin.read((char*)ivec, 16);␊ | 
| ␉␉}␊ | 
| ␉␉else return false;␊ | 
| ␉}␊ | 
| ␉fin.close();␊ | 
| ␉return true;␊ | 
| ␊ | 
| #elif _win32␊ | 
| ␉␊ | 
| ␉// I don't have a clue if this works..␊ | 
| ␉HCRYPTPROV hCryptProv;␊ | 
| ␉CryptAcquireContext( &hCryptProv,  NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)␊ | 
| ␉if(CryptGenRandom(hCryptProv, 16, (BYTE*) ivec)){␊ | 
| ␉␉printf("Random sequence generated. \n");␊ | 
| ␉}␊ | 
| ␉else{␊ | 
| ␉␉std::cout << "ERROR: CryptGenRandom failed." << std::endl;␊ | 
| ␉␉return NULL;␊ | 
| ␉}␊ | 
| ␊ | 
| #else␊ | 
| ␊ | 
| ␉// uhh...␊ | 
| ␊ | 
| #endif␊ | 
| }␊ | 
| ␊ | 
| /*!␊ | 
| * Encrypts a string using AES 256␊ | 
| * Note: If the key is less than 32 bytes, it will be null padded.␊ | 
| *       If the key is greater than 32 bytes, it will be truncated␊ | 
| * \param in The string to encrypt␊ | 
| * \param key The key to encrypt with␊ | 
| * \return The encrypted data␊ | 
| */␊ | 
| std::string aes_encrypt(std::string in, std::string key){␊ | 
| ␊ | 
| ␉unsigned char ivec[16];␊ | 
| ␉getRandomIvec(ivec);␊ | 
| ␉std::string ivecString((char*) ivec, 16); // Save this for later␊ | 
| ␊ | 
| ␉// Always pad the key to 32 bits.. because we can␊ | 
| ␉if(key.length() < 32){␊ | 
| ␉␉key.append(32 - key.length(), '\0');␊ | 
| ␉}␊ | 
| ␉␊ | 
| ␉// Get some space ready for the output␊ | 
| ␉unsigned char *output = new unsigned char[in.length() + AES_BLOCK_SIZE];␊ | 
| ␉␊ | 
| ␉// Encrypt the data␊ | 
| ␉int length, finalLength = 0;␊ | 
| ␉EVP_CIPHER_CTX *encryptHandle = new EVP_CIPHER_CTX;␊ | 
| ␉EVP_CIPHER_CTX_init(encryptHandle);␊ | 
| ␉EVP_EncryptInit_ex(encryptHandle, EVP_aes_256_cbc(), NULL, (unsigned char*) key.c_str(), ivec);␊ | 
| ␉EVP_EncryptUpdate(encryptHandle, output, &length, (unsigned char*)in.c_str(), in.length());␊ | 
| ␉finalLength += length;␊ | 
| ␉EVP_EncryptFinal_ex(encryptHandle, output + length, &length);␊ | 
| ␉finalLength += length;␊ | 
| ␊ | 
| ␉// Make the data into a string␊ | 
| ␉std::string ret((char*) output, finalLength);␊ | 
| ␉␊ | 
| ␉// clean up␊ | 
| ␉delete output;␊ | 
| ␉EVP_CIPHER_CTX_cleanup(encryptHandle);␊ | 
| ␉delete encryptHandle;␊ | 
| ␉␊ | 
| ␉return ivecString + ret;␊ | 
| }␊ | 
| ␊ | 
| /*!␊ | 
| * Decrypts a string using AES 256␊ | 
| * Note: If the key is less than 32 bytes, it will be null padded.␊ | 
| *       If the key is greater than 32 bytes, it will be truncated␊ | 
| * \param in The string to decrypt␊ | 
| * \param key The key to decrypt with␊ | 
| * \return The decrypted data␊ | 
| */␊ | 
| std::string aes_decrypt(std::string in, std::string key){␊ | 
| ␊ | 
| ␉// Get the ivec from the front␊ | 
| ␉unsigned char ivec[16];␊ | 
| ␉strncpy((char*)ivec, in.c_str(), 16);␊ | 
| ␉in = in.substr(16);␊ | 
| ␊ | 
| ␉// Always pad the key to 32 bits.. because we can␊ | 
| ␉if(key.length() < 32){␊ | 
| ␉␉key.append(32 - key.length(), '\0');␊ | 
| ␉}␊ | 
| ␊ | 
| ␉// Create some space for output␊ | 
| ␉unsigned char *output = new unsigned char[in.length()];␉␊ | 
| ␉int length, finalLength = 0;␊ | 
| ␉␊ | 
| ␉// Decrypt the string␊ | 
| ␉EVP_CIPHER_CTX *encryptHandle = new EVP_CIPHER_CTX;␊ | 
| ␉EVP_CIPHER_CTX_init(encryptHandle);␊ | 
| ␉EVP_DecryptInit_ex(encryptHandle, EVP_aes_256_cbc(), NULL, (unsigned char*) key.c_str(), ivec);␊ | 
| ␉EVP_DecryptUpdate(encryptHandle, output, &length, (unsigned char*)in.c_str(), in.length());␊ | 
| ␉finalLength += length;␊ | 
| ␉EVP_DecryptFinal_ex(encryptHandle, output + length, &length);␊ | 
| ␉finalLength += length;␊ | 
| ␉␊ | 
| ␉//std::cout << finalLength << std::endl;␊ | 
| ␉␊ | 
| ␉// Make the output into a string␊ | 
| ␉std::string ret((char*) output, finalLength);␊ | 
| ␉␊ | 
| ␉// Clean up␊ | 
| ␉delete output;␊ | 
| ␉EVP_CIPHER_CTX_cleanup(encryptHandle);␊ | 
| ␉delete encryptHandle;␊ | 
| ␉␊ | 
| ␉return ret;␊ | 
| }␊ |