Hi Ali, Thus wrote Ali Sydney (asyd...@k-state.edu):
> 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; }