#include #include #include #include #include #include #include using namespace std; // This is the same as what was given, just added the key string as a parameter // so I could manipulate it in here instead. int do_crypt(FILE *in, FILE *out, string inkey, int do_encrypt) { /* Allow enough space in output buffer for additional block */ unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH]; int inlen, outlen; EVP_CIPHER_CTX *ctx; /* * Bogus key and IV: we'd normally set these from * another source. */ // hardcoding the IV because we already know what it is. unsigned char iv[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // I'm adding the spaces in here. for(int i = inkey.length(); i < 16; ++i) { inkey += ' '; } // Converting the input key into an unsigned char array. unsigned char key[17]; strcpy((char*) key, inkey.c_str()); /* Don't set key or IV right away; we want to check lengths */ ctx = EVP_CIPHER_CTX_new(); EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL, do_encrypt); OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16); OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16); /* Now we can set key and IV */ EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, do_encrypt); for (;;) { inlen = fread(inbuf, 1, 1024, in); if (inlen <= 0) break; if (!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen)) { /* Error */ EVP_CIPHER_CTX_free(ctx); return 0; } fwrite(outbuf, 1, outlen, out); } if (!EVP_CipherFinal_ex(ctx, outbuf, &outlen)) { /* Error */ EVP_CIPHER_CTX_free(ctx); // I added this just in case to make sure thigns cleaned up properly. EVP_CIPHER_CTX_cleanup(ctx); return 0; } fwrite(outbuf, 1, outlen, out); EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_cleanup(ctx); return 1; } int main() { // Initialize files. FILE *input; FILE *output; // Open the needed files. input = fopen("ciphertext.txt", "rb"); output = fopen("testing.txt", "wb"); // I prefer ifstreams when dealing with files, // but I leave the other two as file pointers // so I don't have to change more code. ifstream words("words.txt"); ifstream original("plaintext.txt"); // Just an initial key. It will be overwritten. string key = "0123456789abcdef"; // Variable to storing the goal string. string secret = ""; getline(original, secret); // Variable for storing output when we read // from the file that we wrote to. string templine = ""; while(!words.eof()) { // Get the current key to test with. key = ""; getline(words, key); // Only test it if it's less that 16 characters. if(key.length() > 16) { continue; } // Try to decrypt with this key. do_crypt(input, output, key, 0); // Set the file pointers back to the beginning // of the files. rewind(input); rewind(output); // Read the file and see if it matches the original // message, if it does, then we guessed the key. fclose(output); ifstream tempoutput("testing.txt"); getline(tempoutput, templine); tempoutput.close(); if(templine.compare("This is a top secret.") == 0) { // Output the key and the output text // to prove we know the key and we // successfully decrypted the message. cout << key << endl; cout << templine << endl; break; } else { // We didn't decrypt it, try again, // overwrite whatever was in the file. output = fopen("testing.txt", "wb"); } } fclose(input); words.close(); original.close(); return 0; }