I am writing an application that uses OpenSSL 256-bit AES CBC encryption on a Windows system to communicate with a UNIX web application written in Perl using Crypt::CBC with the Crypt::OpenSSL::AES cipher. After a lot of experimentation and testing, it appears that the two AES CBC implementations are not compatible. Technically, the Perl AES implementation is supposed to use the OpenSSL library for encryption and decryption, so I am a little confused on why this is not working.
I have looked at the source for Crypt::CBC and found that the Perl implementation does a conversion of the key into an MD5 hash -- to override this behavior, I pass "-literal-key => 1" when I create the cipher object in Perl. I have also set parameters that override the salt header in Perl and set the padding to null bytes. To analyze the problem, I wrote two command line test apps. The client side app prompts for text input, encrypts the string, converts it to hex, and prints it (it also does some internal validation). The server side app reads the hex encoded input strings, decodes them using Crypt::CBC, and print the decoded result. The Perl side is not able to correctly decode encrypted data from the Windows app. For the encrypting side, I am running OpenSSL version 0.9.8i on Windows Vista Ultimate. The application is written in C using Visual Studio 9.0. On the server (Perl) side, I am using Perl 5.8.8 with Crypt::CBC 2.30, Crypt::OpenSSL::AES 0.02, and FreeBSD 7.0 with OpenSSL 0.9.8e. I have included copies of both the encrypting and decrypting test apps below (these are to be run from the command line). I would really appreciate any pointers or suggestions from the group that would allow me to get these two AES CBC apps to talk to each other. Dave Stoddard ==================================== Client (Encrypting) Test Application Windows Vista OpenSSL 0.9.8i Visual Studio C/C++ 9.0 ==================================== # include <stdio.h> # include <ctype.h> # include <string.h> # include "openssl/aes.h" # define BLOCK_LEN 16 # define MAXBUF 65536 # define KEY "abcdefghijklmnopqrstuvwxyz012345" # define IV "RandomIVRandomIV" // function prototypes int bin2hex (unsigned char *pinp, unsigned char *pout, unsigned int len); int hex2bin (unsigned char *pinp, unsigned char *pout, unsigned int len); int main (int argc, char *argv[]) { unsigned long olen; unsigned char data[MAXBUF]; // command line input unsigned char dbuf[MAXBUF]; // decrypt output unsigned char ibuf[MAXBUF]; // encrypt input unsigned char obuf[MAXBUF]; // encrypt output unsigned char xbuf[MAXBUF]; // hex encrypt output unsigned char ybuf[MAXBUF]; // hex encrypt output unsigned char key[] = KEY; unsigned char iv[] = IV; AES_KEY aeskeyEnc, aeskeyDec; // loop through user input while (1) { // read input printf ("input> "); gets_s (data,MAXBUF); // check for exit if (strcmp (data,"exit") == 0) break; if (strcmp (data,"quit") == 0) break; // printf ("input: %s (len = %d)\n", data, strlen(data)); // prepare the input data with padding memset (ibuf, 0x00, sizeof (ibuf)); memcpy_s (ibuf, sizeof (ibuf), data, strlen (data)); // calc length of aes output block olen = ((int)(strlen (data) / BLOCK_LEN) * BLOCK_LEN) + 32; // init cipher keys AES_set_encrypt_key (key, 256, &aeskeyEnc); AES_set_decrypt_key (key, 256, &aeskeyDec); // encrypt string memcpy_s (iv, sizeof (iv), IV, sizeof (IV)); AES_cbc_encrypt (ibuf, obuf, olen, &aeskeyEnc, iv, AES_ENCRYPT); // convert encoded string to hex and display bin2hex (obuf,xbuf,olen); printf ("encode: %s (len = %d)\n", xbuf, (int) strlen (xbuf)); // convert hex string to binary hex2bin (xbuf, ybuf, (int) strlen(xbuf)); // compare binary values if (memcmp (obuf, ybuf, olen) != 0) { printf ("HEX FAILED!\n"); return (0); } // decrypt string memcpy_s (iv, sizeof (iv), IV, sizeof (IV)); AES_cbc_encrypt (ybuf, dbuf, olen, &aeskeyDec, iv, AES_DECRYPT); printf ("decode: %s (len = %d)\n", dbuf, strlen(dbuf)); // compare binary values if (memcmp (data, dbuf, (unsigned int) strlen (data)) != 0) { printf ("DECODE FAILED!\n"); return (0); } printf ("\n"); } // while (1) return (0); } int bin2hex (unsigned char *pcIbuf, unsigned char *pszObuf, unsigned int ilen) { unsigned int i; // loop iteration counter unsigned int j = (ilen * 2) + 1; // output buffer length unsigned char *p; p = pszObuf; // point to start of output buffer for (i = 0; i < ilen; i++) { sprintf_s (p, j, "%2.2x", (unsigned char) pcIbuf [i]); p += 2; } *p = '\0'; return (0); } int hex2bin (unsigned char *pszIbuf, unsigned char *pcObuf, unsigned int ilen) { unsigned int i; // loop iteration variable unsigned int j; // current character unsigned int by = 0; // byte value for conversion unsigned char ch; // current character // process the list of characters for (i = 0; i < ilen; i++) { ch = toupper(*pszIbuf++); // get next character // do the conversion if(ch >= '0' && ch <= '9') by = (by << 4) + ch - '0'; else if(ch >= 'A' && ch <= 'F') by = (by << 4) + ch - 'A' + 10; else { // error if not hexadecimal memcpy (pcObuf,"ERROR",5); return 0; } // store a byte for each pair of hexadecimal digits if (i & 1) { j = ((i + 1) / 2) - 1; pcObuf [j] = by & 0xff; } } return (j); } // end of client test app ================================ Server Decoding Test App in Perl FreeBSD 7.0 UNIX OpenSSL 0.9.8e Perl 5.8.8 Crypt::CBC 2.30 Crypt::OpenSSL::AES 0.02 ================================ #!/usr/bin/perl use strict; use Crypt::CBC; my $obj = ""; my $len = ""; my $key = "abcdefghijklmnopqrstuvwxyz012345"; my $iv = "RandomIVRandomIV"; my $meth = "Crypt::OpenSSL::AES"; my $decdata = ""; print "coded hex input> "; while (<STDIN>) { chomp; last if ($_ eq "exit"); last if ($_ eq "quit"); $obj = Crypt::CBC->new ( -key => $key, -padding => "null", -header => "none", -literal-key => 1, -iv => $iv, -cipher => $meth ); # decrypt data $decdata = $obj->decrypt_hex ($_); $len = length ($decdata); print "decoded: $decdata (len = $len)\n"; # input prompt print "\ncoded hex input> "; } exit 0; # end of Perl app ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]