Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how to decrypt a binary file which is encryptes by aes 256 cbc mode

792 views
Skip to first unread message

NaGaGo

unread,
Nov 17, 2009, 5:34:40 AM11/17/09
to

Can any one help me out with the code below I dont understand properly what
is the error problem in this .
I'm using AES API's to decrypt.
Here is my code :
I need to decrypt a binary file...i only have key and iv and i was given the
mode of encryption asked to decrypt the binary file..so this was procedure i
followed..can any one correct me where is wrogong in my code...
#include
#inclide
#incldue
int main()
{

unsigned long lSize;
FILE * inFile;
FILE * outFile;
size_t n,m;
char * pTemp;
char * buffer;
const AES_KEY *key;
inFile = fopen("SB2.bin", "rb");
outFile = fopen("finalPackResult", "wb+");

unsigned char uKey[]=
"3834373532303435333730323834383132373330393233343531323330383839";
unsigned char iv[] = "36363333383630393433313132323031";

int keyLength = sizeof(uKey);
int ivLength = sizeof(iv);
printf("key length:%d.\n",keyLength);
printf("Initialisation vector length:%d.\n",ivLength);

/* get file size and allocate memory to buffer */
fseek (inFile , 0,SEEK_END);
lSize = ftell (inFile);
rewind (inFile);
printf("File size is: %ld.\n",lSize);
unsigned char pInBuff[lSize];
unsigned char pOutBuff[lSize];

/* Allocate memory */
memset(pInBuff,0,lSize * sizeof(char));
memset(pOutBuff,0,lSize * sizeof(char));
buffer = (char *)malloc(sizeof(char)*lSize);

/* Read the input signature package which contains
* encrypted data. The AES encryption technique
* with CBC mode is followed
*/
if ((n = fread (pInBuff, 1, lSize, inFile)) == -1)
{
printf ("read error");
return -1;
}
printf("Data read from input binary is :%d\n", n);
if (n == 0)
{
printf ("Data read error from input file.\n");
return -1;
}
printf("LINE :%d.\n",__LINE__);


/* The AES_cbc_encrypt() function implements the Cipher Block Chaining
(CBC)
* mode of operation. It encrypts or decrypts B<in> using the key
schedule
* B<schedule> and places the result in B<out>. The value of B<length>
is
* the length of B<in> in bytes
*/
AES_set_decrypt_key(uKey, 256, &key);
printf("LINE :%d.\n",__LINE__);

AES_cbc_encrypt(pInBuff, pOutBuff, lSize, key, iv, AES_DECRYPT);---here
i'm getting segfault
printf("LINE :%d.\n",__LINE__);
pTemp = AES_options();
printf("AES function to which pointed:%s.\n", pTemp);

/* Write decrypted data into a file */
if((m=fwrite(pOutBuff, 1, lSize, outFile)) == -1)
{
printf ("Write error.\n");
}
if(m != n)
{
printf("Didn't write the data properly.%dbytes info missed",n-m);
}
printf("size of data written is:%d.\n",m);
return 0;
}
Thanks in Advance.
--
View this message in context: http://old.nabble.com/AES-cbc--How-to-Init-Openssl--tp12475822p26387613.html
Sent from the OpenSSL - User mailing list archive at Nabble.com.
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openss...@openssl.org
Automated List Manager majo...@openssl.org

Dave Thompson

unread,
Nov 18, 2009, 7:32:02 PM11/18/09
to
> From: owner-ope...@openssl.org On Behalf Of NaGaGo
> Sent: Tuesday, 17 November, 2009 05:35

> #include
> #inclide
> #incldue

I assume these were just a hint that the real code
has correct #include's.

> int main()
> {
>
> unsigned long lSize;
> FILE * inFile;
> FILE * outFile;
> size_t n,m;
> char * pTemp;
> char * buffer;
> const AES_KEY *key;
> inFile = fopen("SB2.bin", "rb");
> outFile = fopen("finalPackResult", "wb+");

You don't check for fopen() failure.


>
> unsigned char uKey[]=
> "3834373532303435333730323834383132373330393233343531323330383839";
> unsigned char iv[] = "36363333383630393433313132323031";
>

As already said, these are apparently the hex 'armoring' of the
key and iv, which is needed on a command line (because shell
etc. generally can't handle binary) but not used in code.

> int keyLength = sizeof(uKey);
> int ivLength = sizeof(iv);

Even after you change to the correct values, these lengths are one
too high. sizeof gives you the size of the whole array, which
includes the null terminator. strlen() gives you the length
of the valid content *before* the null terminator, and (thus)
only works on things that are null-terminated strings (which
ciphertext usually isn't, and keys and ivs often aren't).
But you don't really use them anyway.

> printf("key length:%d.\n",keyLength);
> printf("Initialisation vector length:%d.\n",ivLength);
>
> /* get file size and allocate memory to buffer */
> fseek (inFile , 0,SEEK_END);
> lSize = ftell (inFile);
> rewind (inFile);

It is a FGA on comp.lang.c that this isn't guaranteed to work
on all systems -- but *no* method is guaranteed to work on all
systems, so this is among the less bad alternatives.

> printf("File size is: %ld.\n",lSize);

Technically an unsigned long should use %lu not %ld.
In practice this will usually work except that values
greater than usually 2147483647 will display wrong.

> unsigned char pInBuff[lSize];
> unsigned char pOutBuff[lSize];
>

This (Variable Length Arrays, also mixed-code-decl) only
works in C99, or GNU89 which added it as an extension.
The portable way is malloc, as below.



> /* Allocate memory */
> memset(pInBuff,0,lSize * sizeof(char));
> memset(pOutBuff,0,lSize * sizeof(char));
> buffer = (char *)malloc(sizeof(char)*lSize);
>

sizeof(char) is *always* 1 per the standard.
There's no point in zeroing these buffers since
you proceed to (try to) fully overwrite them.
You don't check for malloc failure, but you don't
use buffer for anything anyway.

> /* Read the input signature package which contains
> * encrypted data. The AES encryption technique
> * with CBC mode is followed
> */
> if ((n = fread (pInBuff, 1, lSize, inFile)) == -1)
> {
> printf ("read error");
> return -1;
> }

fread doesn't return -1 for error; any value less than
the third (count) argument is error or EOF. (The Unix-level
read and write, and send and recv etc., do return -1.
Some *other* stdio routines return EOF which is defined by
the standard only as negative, but conventionally is -1.)

On some systems size_t is not large (wide) enough to
represent all possible file sizes; on such systems
this will process only a (small) part of the data.
Solutions are more complicated than you need now.

> printf("Data read from input binary is :%d\n", n);
> if (n == 0)
> {
> printf ("Data read error from input file.\n");
> return -1;
> }
> printf("LINE :%d.\n",__LINE__);
>
>
> /* The AES_cbc_encrypt() function implements the Cipher
> Block Chaining
> (CBC)
> * mode of operation. It encrypts or decrypts B<in> using the key
> schedule
> * B<schedule> and places the result in B<out>. The
> value of B<length>
> is
> * the length of B<in> in bytes
> */
> AES_set_decrypt_key(uKey, 256, &key);
> printf("LINE :%d.\n",__LINE__);
>

You need to give this routine, and the next, a pointer
to a AES_KEY object. Instead you give it a pointer to
a pointer. Your compiler should have warned you about
the type mismatch. Either set a pointer validly e.g.
/*not const!*/ AES_KEY * pkey = malloc (sizeof(AES_KEY));
if( pkey == NULL ) some_error_handling;
and pass pkey in both places, or just declare an object
/*not const!*/ AES_KEY key;
and pass &key to both set__key and _encrypt .

> AES_cbc_encrypt(pInBuff, pOutBuff, lSize, key, iv,
> AES_DECRYPT);---here
> i'm getting segfault

This is now trying to deref the totally garbage pointer
value in key created by the bad call above.

> printf("LINE :%d.\n",__LINE__);
> pTemp = AES_options();
> printf("AES function to which pointed:%s.\n", pTemp);
>
> /* Write decrypted data into a file */
> if((m=fwrite(pOutBuff, 1, lSize, outFile)) == -1)
> {
> printf ("Write error.\n");
> }
> if(m != n)
> {
> printf("Didn't write the data properly.%dbytes info
> missed",n-m);
> }

This one you got correct; fwrite also returns m < n not -1.
If size_t is wider than int, which is pretty rare, %d is
wrong and can screw up. The safest C89 way is to cast to
or just use unsigned long and %lu; GNU unsigned long long
and %llu; C99 uintmax_t and I forget I think %zu .

> printf("size of data written is:%d.\n",m);
> return 0;
> }
>

NaGaGo

unread,
Nov 19, 2009, 2:01:32 AM11/19/09
to

Hi
Thank you very much for a complete review on code....I resolved all the
problems and found the issue is in key...
can you tell me now what is problem..the code below run into error at set
decrypt key

the shell command for decryption of my file is o
penssl enc -d -K
3834373532303435333730323834383132373330393233343531323330383839 -iv
36363333383630393433313132323031 -aes-256-cbc -in finalSigPackage.bin -out
x.zip

so what is the key I need to give in my code...??please help me!!
some error checking is removed as their file pointers are ready in the
code...and modification done to earlier is the file is read completely at
once not by chunks..
Here is my modified code :

INCLUDE FILES:
*/
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <openssl/aes.h>
#define AES_BLOCK_SIZE 16

int main()
{

unsigned long size;


FILE * inFile;
FILE * outFile;

char * pInBuff;
char * pOutBuff;
size_t n,m;
AES_KEY *key = malloc (sizeof(AES_KEY));

if (key == NULL)
{
printf ("Error in AES_KEY.\n");
return -1;
}
if((inFile = fopen("gout.bin", "rb")) == NULL)
{
printf ("Error in open input file.\n");
return -1;
}

if((outFile = fopen("finalPackResult", "wb")) == NULL)
{
printf ("Error in opening ouput file.\n");
return -1;
}

unsigned char uKey[] = "84752045370284812730923451230889";
unsigned char iv[] = "6633860943112201";

/* get file size */
struct stat st;
fstat(fileno(inFile), &st);
size = st.st_size;
printf("File size is:%lu.\n",size);

pInBuff = (char *)malloc(size * sizeof(char));
pOutBuff = (char *)malloc(size * sizeof(char));

/* Read the input signature package which contains
* encrypted data. The AES encryption technique
* with CBC mode is followed
*/

/* file is read in chunks
* and is written into file
* decrypt final uses the buffer which has decrypted data
*/
if(!AES_set_decrypt_key(uKey, 256, &key))
{
printf ("Error in set decrypt key.\n");
return -1;
}

if ((n = fread (pInBuff, 1, size, inFile)) < size)
{
printf ("read error\n");
return -1;
}


printf("Data read from input binary is :%d \n", n);

/* The AES_cbc_encrypt() function implements the Cipher Block Chaining
(CBC)
* mode of operation. It encrypts or decrypts B<in> using the key
schedule
* B<schedule> and places the result in B<out>. The value of B<length>
is
* the length of B<in> in bytes
*/

AES_cbc_encrypt((const unsigned char *)pInBuff,
(unsigned char *)pOutBuff,
size,
&key,
iv,
AES_DECRYPT);



/* Write decrypted data into a file */

fwrite(pOutBuff, 1, size, outFile);

printf("size of data written is:%lu.\n", m);
fclose (inFile);
fclose (outFile);
return 0;
}

--
View this message in context: http://old.nabble.com/AES-cbc--How-to-Init-Openssl--tp12475822p26421214.html


Sent from the OpenSSL - User mailing list archive at Nabble.com.

Dave Thompson

unread,
Nov 20, 2009, 8:43:10 PM11/20/09
to
> From: owner-ope...@openssl.org On Behalf Of NaGaGo
> Sent: Thursday, 19 November, 2009 02:02

> #include <sys/types.h>
> #include <unistd.h>
> #include <stdlib.h>
> #include <string.h>
> #include <stdio.h>
> #include <openssl/aes.h>
> #define AES_BLOCK_SIZE 16

This is already in aes.h, you don't need to define it yourself.

>
> int main()
> {
>
> unsigned long size;
> FILE * inFile;
> FILE * outFile;
> char * pInBuff;
> char * pOutBuff;

I would make these pointer to unsigned char, since
that's how you want to use them; see below.

> size_t n,m;
> AES_KEY *key = malloc (sizeof(AES_KEY));
>
> if (key == NULL)
> {
> printf ("Error in AES_KEY.\n");
> return -1;
> }

Okay, key points to suitable memory for a key object.

<snip file opens and allocs>

> if(!AES_set_decrypt_key(uKey, 256, &key))
> {
> printf ("Error in set decrypt key.\n");
> return -1;
> }
>

key is a pointer, so pass its value, not &key.
&key here causes OpenSSL to clobber your stack frame.
key causes it to use the memory you correctly allocated.

As I said, the other approach is to declare an actual object
AES_KEY /*not pointer!*/ key;
and pass &key in both places. Experienced C programmers
(IMO) consider it better style to use this form for small
fixed-size objects (as opposed to things like your data
buffers, which apparently depend on the file you are given).
It's not illegal or unsafe to use malloc for such things,
just more work and clutter, less efficient and less common.

In general, whenever you get an error return from an OpenSSL
routine, you should look at OpenSSL's error info. Either
call ERR_get_error() to get the number, preferably decode it
with ERR_error_string assuming you have loaded error strings,
display, and repeat until you get 0; or if you have a suitable
outfile, which stderr usually is, just call ERR_print_errors.
But in this particular case, of an *invalid* pointer,
it appears to me OpenSSL won't detect it and thus can't
give you good error information here.

<snip read>


> AES_cbc_encrypt((const unsigned char *)pInBuff,
> (unsigned char *)pOutBuff,
> size,
> &key,
> iv,
> AES_DECRYPT);
>

Again key not &key, unless key is an actual object.

And if the pointers are to unsigned char, no casts.

<snip write>

0 new messages