Root/
/*! * 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; } |
Source at commit tip created 12 years 1 month ago. By Nathan Adams, initial commit |
---|