Hi Ali,
Thus wrote Ali Sydney ([email protected]):
> Thanks for the speedy response. I have been attempting to use the EVP
> interface, but the cipher text produced is wrong (and I am fairly new
> to this). As a simple test, I have hard-coded an 8 byte block for the
> key (in hexadecimal), and also an 8 byte block (also in hex) for the
> plaintext. Can you kindly take a look and provide feedback?
> int main()
> {
> EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX));
> EVP_CIPHER_CTX_init(ctx);
> unsigned char key[]={0x01, 0x91, 0xd0, 0xad, 0x79, 0x4c, 0xae, 0x9b};
> //64-bit KEY
> unsigned char plaintext[]={0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63,
> 0x64}; //64-bit Plaintext to be encrypted
> int ret;
> ret = EVP_EncryptInit_ex(ctx, EVP_des_ecb(), NULL, key, NULL); //USE DES
> ECB mode
> assert(ret == 1);
> ret = EVP_CIPHER_CTX_set_padding(ctx, 0); //No padding
> assert(ret == 1);
> int val, num_bytes_in(8),num_bytes_out(8); //8 bytes of plaintext, 8 bytes
> of ciphertext
> unsigned char out[8]; //Store ciphertext in "out"
> val=EVP_EncryptUpdate(ctx, out, &num_bytes_out, plaintext, num_bytes_in );
> //Encrypt plaintext
> for (int i=0; i<8; i++) //Print ciphertext
> {
> printf("%02x",out[i]);
> }
> cout<<endl;
> }
EVP_EncryptFinal() is missing.
The attached example works ok for me
Best regards,
Martin
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
unsigned char K[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 };
int main(void)
{
int ret;
EVP_CIPHER_CTX ctx;
char in[] = "abcdefgh";
int inl;
char out[500];
int outl;
char back[500];
int backl;
int tmp;
inl = strlen(in);
/* ATTENTION: the _ex routines require an initialized context, i.e.
* EVP_CIPHER_CTX_init() must be called before Init_ex,
* it's enough to do this once before encryption, no need to call it a
* second time before decryption */
EVP_CIPHER_CTX_init(&ctx);
/* ----- encryption ----- */
/* EVP_EncryptInit_ex() cleans up the context, it doesn't initialize it */
ret = EVP_EncryptInit_ex(&ctx, EVP_des_ecb(), NULL, K, NULL);
assert(ret == 1);
/* this must be called after EVP_EncryptInit() because EVP_EncryptInit()
* reinitialises the ctx !!!
* 0 turns padding off, i.e. the input string must be exactly N blocks */
ret = EVP_CIPHER_CTX_set_padding(&ctx, 0);
assert(ret == 1);
ret = EVP_EncryptUpdate(&ctx, out, &outl, in, inl);
assert(ret == 1);
assert(outl == inl); /* input must be exactly N blocks */
tmp = outl;
ret = EVP_EncryptFinal_ex(&ctx, &out[outl], &outl);
assert(ret == 1);
assert(outl == 0); /* no remaining incomplete blocks */
outl += tmp;
/* is this really necessary? -> it seems so*/
ret = EVP_CIPHER_CTX_cleanup(&ctx);
assert(ret == 1);
/* ----- decryption ----- */
/* EVP_DecryptInit_ex() cleans up the context, it doesn't initialize it
-> no need to call EVP_CIPHER_CTX_init(&ctx) here,
but padding setting must be renewed */
ret = EVP_DecryptInit_ex(&ctx, EVP_des_ecb(), NULL, K, NULL);
assert(ret == 1);
ret = EVP_CIPHER_CTX_set_padding(&ctx, 0);
assert(ret == 1);
/* out, outl == input data, back, backl == output data */
ret = EVP_DecryptUpdate(&ctx, back, &backl, out, outl);
assert(ret == 1);
assert(backl == outl); /* input to decryption must be exactly N blocks */
tmp = backl;
ret = EVP_DecryptFinal_ex(&ctx, &back[backl], &backl);
assert(ret == 1);
assert(backl == 0); /* no remaining incomplete blocks */
backl += tmp;
ret = EVP_CIPHER_CTX_cleanup(&ctx);
assert(ret == 1);
back[backl+1] = 0x0;
printf("%s\n", back);
return 0;
}