java <--> openssl interop

Hello.

I have a problem when trying to decrypt data in java, which was encrypted using openssl.

I keep getting a BadPaddingException("Given final block not properly padded").

After trying to come up with a simple test case, i found the following strange fact;

when encrypting a string in openssl using blowfish in ECB mode (I know, not secure, but bare with me) using a simple key, the encrypted text is different than when I use the same key in java and a "Blowfish/CBC/PKCS5Padding" cipher.

I have no clue as to what the problem might be, and an ready to give up.....

Can someone please please help? I can post relevant code if necessary.

Cheers ;)

[701 byte] By [tzachara] at [2007-11-27 4:49:34]
# 1
In your openssl, the chances are you used the -k option to define the key as a passphrase when you should have used the -K option to define the key as a hex string.Message was edited by: sabre150
sabre150a at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 2
I wish it was that simple. I do not use openssl from the command line, but as a library in C. I use the EVP_Encrypt (and palls) directly, and i pass the same key bytes on both sides(java and C).
tzachara at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 3

But there will be an equivalent to the -K mode for the C library. The important point is that one does not use a passphrase as key as this is processed by openssl to form the real key bytes. Start with the real key bytes.

My standard AES test example using the command line is

import javax.crypto.spec.*;

import javax.crypto.*;

import me.sabre150.research.howto.runtime.*;

import java.io.*;

public class EncryptOpenSSLDecryptJava

{

private static String toHex(byte[] bites)

{

char[] hexChars = new char[bites.length*2];

for (int charIndex = 0, startIndex = 0; charIndex < hexChars.length;)

{

int bite = bites[startIndex++] & 0xff;

hexChars[charIndex++] = HEX_CHARS[bite >> 4];

hexChars[charIndex++] = HEX_CHARS[bite & 0xf];

}

return new String(hexChars);

}

private static final char[] HEX_CHARS =

{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};

public static void encryptOrDecryptFile(File ifile, Cipher cipher, File ofile) throws Exception

{

InputStream istrm = new FileInputStream(ifile);

istrm = new javax.crypto.CipherInputStream(istrm, cipher);

OutputStream ostrm = new FileOutputStream(ofile);

byte[] buffer = new byte[65536];

for (int len = 0; (len = istrm.read(buffer)) >= 0;)

{

ostrm.write(buffer, 0, len);

}

ostrm.close();

istrm.close();

}

public static void main(String[] args1) throws Exception

{

final String iFile = System.getProperty("user.home") + "/user.sql";

final String eFile = iFile + ".enc";

final String oFile = iFile + ".x";

final String provider = "SunJCE";

final String algorithm = "AES";

final byte[] iv = {1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1};

final byte[] keyBytes =

{

0,1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf,

10,11,12,13,14,15,16,17,18,19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,

};

{

final String[] command = {"sh","-c","openssl enc -e -aes-256-cbc -K " + toHex(keyBytes) + " -iv " + toHex(iv) + " -in " + iFile + " -out " + eFile};

final Process process = Runtime.getRuntime().exec(command);

new Thread(new SyncPipe(process.getErrorStream(), System.err)).start();

new Thread(new SyncPipe(process.getInputStream(), System.out)).start();

final int returnCode = process.waitFor();

System.out.println("'openssl' return code = " + returnCode);

}

{

final Cipher cipher = Cipher.getInstance(algorithm + "/CBC/PKCS5Padding",provider);

final SecretKey key = new SecretKeySpec(keyBytes, algorithm);

cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));

encryptOrDecryptFile(new File(eFile), cipher, new File(oFile));

}

{

String[] command = {"sh","-c","diff " + iFile + " " + oFile};

final Process process = Runtime.getRuntime().exec(command);

new Thread(new SyncPipe(process.getErrorStream(), System.err)).start();

new Thread(new SyncPipe(process.getInputStream(), System.out)).start();

final int returnCode = process.waitFor();

System.out.println("'diff' return code = " + returnCode);

}

}

}

sabre150a at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 4
I just noticed that you say you encrypt using ECB mode but decrypt using CBC mode!
sabre150a at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 5

>> I just noticed that you say you encrypt using ECB mode but decrypt using CBC mode!

This is just a typo.

here is the code i use in java:

public static byte[] encryptBF(byte[] text, byte[] key)

{

KeyGenerator kgen = KeyGenerator.getInstance("Blowfish");

kgen.init(key.length * 8);

SecretKey skey = kgen.generateKey();

Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");

byte [] biv= new byte[8];

Arrays.fill(biv, (byte)0);

IvParameterSpec iv = new IvParameterSpec(biv);

cipher.init(Cipher.ENCRYPT_MODE, skey, iv);

return cipher.doFinal(text, 0, text.length);

}

and in C:

void my_enc_init(EVP_CIPHER_CTX *ctx,

unsigned char *key,

int key_len)

{

static unsigned char iv[] = {0,0,0,0,0,0,0,0};

if (ctx == NULL){

TRACE(1, "ctx is null \n");

return;

}

EVP_CIPHER_CTX_init(ctx);

EVP_EncryptInit_ex(ctx, EVP_bf_ecb(), NULL, NULL, NULL);

EVP_CIPHER_CTX_set_key_length(ctx, key_len);

EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);

EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv);

return ;

}

int enc(

unsigned char *key,

int key_len,

const unsigned char *data,

int data_len,

unsigned char *out)

{

EVP_CIPHER_CTX ctx;

int outlen = 0;

int tmp = 0;

my_enc_init(&ctx, key, key_len);

if (EVP_EncryptUpdate(&ctx, out, &outlen, data, data_len) != 1){

TRACE(1, "cannot encrypt \n");

ERR_print_errors_fp(stderr);

return -1;

}

if (EVP_EncryptFinal_ex(&ctx, out+outlen, &tmp) != 1){

TRACE(1, "enc not finished correctly. \n");

ERR_print_errors_fp(stderr);

return -1;

}

EVP_CIPHER_CTX_cleanup(&ctx);

return tmp+outlen;

}

using the same key, data and iv results in different cipher text.

they are also different when using CBC.

tzachara at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 6
Why are you using an IV with ECB? I expect this to throw an exception.And why are you not using the key bytes in the Java? You just ignore them.Message was edited by: sabre150
sabre150a at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 7
it does. the wonders of cut-n-paste...in the code example it should be cbc, also in the openssl code.
tzachara at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 8

> it does. the wonders of cut-n-paste...

>

I don't understand! What does?

> in the code example it should be cbc, also in the openssl code.

You have lost me. Until you are at least consistent your code will never work!

Message was edited by:

sabre150

sabre150a at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 9
sorry, I'm half asleep...Let me rephrase: the code should read CBC, not ECB.And the cipher text from java and openssl differs when using the same data.I hope this is more clear.
tzachara at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 10
> sorry, I'm half asleep...> > Let me rephrase: the code should read CBC, not ECB.> And the cipher text from java and openssl differs> when using the same data.But your Java code does not use your key!
sabre150a at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...
# 11
> But your Java code does not use your key!duh !!!!!(spank on the forehead)Thanks ;)This is what happens when you are awake for too long ;)all works now, this was a life saver ;)thanks again ;)
tzachara at 2007-7-12 10:02:43 > top of Java-index,Security,Cryptography...