#include #include #include #include void handleOpenSSLErrors(void) { ERR_print_errors_fp(stderr); abort(); } unsigned char* decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv ){ EVP_CIPHER_CTX *ctx; unsigned char *plaintexts; int len; int plaintext_len; //unsigned char* plaintext = new unsigned char[ciphertext_len]; unsigned char* plaintext = malloc(ciphertext_len); bzero(plaintext,ciphertext_len); /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) handleOpenSSLErrors(); /* Initialise the decryption operation. IMPORTANT - ensure you use a key * and IV size appropriate for your cipher * In this example we are using 256 bit AES (i.e. a 256 bit key). The * IV size for *most* modes is the same as the block size. For AES this * is 128 bits */ if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) handleOpenSSLErrors(); EVP_CIPHER_CTX_set_key_length(ctx, EVP_MAX_KEY_LENGTH); /* Provide the message to be decrypted, and obtain the plaintext output. * EVP_DecryptUpdate can be called multiple times if necessary */ if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) handleOpenSSLErrors(); plaintext_len = len; /* Finalise the decryption. Further plaintext bytes may be written at * this stage. */ if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleOpenSSLErrors(); plaintext_len += len; /* Add the null terminator */ plaintext[plaintext_len] = 0; /* Clean up */ EVP_CIPHER_CTX_free(ctx); //string ret = (char*)plaintext; //delete [] plaintext; return plaintext; } size_t calcDecodeLength(char* b64input) { size_t len = strlen(b64input), padding = 0; if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are = padding = 2; else if (b64input[len-1] == '=') //last char is = padding = 1; return (len*3)/4 - padding; } void Base64Decode( char* b64message, unsigned char** buffer, size_t* length) { BIO *bio, *b64; // A BIO is an I/O strean abstraction int decodeLen = calcDecodeLength(b64message); *buffer = (unsigned char*)malloc(decodeLen + 1); (*buffer)[decodeLen] = '\0'; bio = BIO_new_mem_buf(b64message, -1); b64 = BIO_new(BIO_f_base64()); bio = BIO_push(b64, bio); //BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer *length = BIO_read(bio, *buffer, strlen(b64message)); BIO_free_all(bio); } void initAES(const unsigned char *pass, unsigned char* salt, unsigned char* key, unsigned char* iv ) { //initialisatio of key and iv with 0 bzero(key,sizeof(key)); bzero(iv,sizeof(iv)); EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(), salt, pass, strlen(pass), 1, key, iv); } int main (void) { // pasword 12345 char* ciphertext_base64 = (char*) "U2FsdGVkX18TOeNk3KGtI3IWTa/sCMEpAWzzMYmSjD/viW5HmNsEFhf69YVe49jr\n"; int decryptedtext_len, ciphertext_len; // cipher (binary) pointer and length size_t cipher_len; // size_t is sizeof(type) unsigned char* ciphertext; unsigned char salt[8]; ERR_load_crypto_strings(); Base64Decode(ciphertext_base64, &ciphertext, &cipher_len); unsigned char key[16]; unsigned char iv[16]; // retrive the slater from ciphertext (binary) if (strncmp((const char*)ciphertext,"Salted__",8) == 0) { memcpy(salt,&ciphertext[8],8); ciphertext += 16; cipher_len -= 16; } // generate key and iv initAES("12345", salt, key, iv); unsigned char* result = decrypt(ciphertext, cipher_len, key, iv); printf("%s\n", result); return 0; }