Wrong algorithm: Blowfish required

I'm hoping one of you can tell me why when attempting to decrypt an OpenSSL Blowfish encrypted file via the following code (below), the Blowfish Cipher initialization code yields:

java.security.InvalidKeyException: Wrong algorithm: Blowfish required

at com.sun.crypto.provider.SunJCE_u.a(DashoA13*..)

at com.sun.crypto.provider.SunJCE_k.a(DashoA13*..)

at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)

at com.sun.crypto.provider.BlowfishCipher.engineInit(DashoA13*..)

at javax.crypto.Cipher.init(DashoA13*..)

at javax.crypto.Cipher.init(DashoA13*..)

at TestDecryption.main(TestDecryption.java:134)

/****************************************************************************/

/* */

/* @Copyright 2007 by Cast Iron Systems Corporation@*/

/* */

/* TestDecryption.java:*/

/*A program to test decryption of a previously encrypted file.*/

/* */

/****************************************************************************/

import java.io.FileInputStream;

import javax.crypto.Cipher;

import javax.crypto.SecretKey;

import javax.crypto.spec.PBEKeySpec;

import javax.crypto.spec.SecretKeySpec;

import javax.crypto.spec.PBEParameterSpec;

import javax.crypto.spec.IvParameterSpec;

publicclass TestDecryption

{

//-

// Display usage of how to invoke this app/class:

//-

privatestaticvoid usage()

{

System.out.println("Usage: java TestDecryption encryptedFile password salt" );

System.out.println(" encryptedFile- The blowfish encrypted file." );

System.out.println(" password - The password/key for the encrypted file." );

System.out.println(" salt - The hex character salt string for password/key." );

return;

}

//-

// Convert a string of hex chars to a byte array:

//-

privatestaticbyte[] strToHex(String s)

{

int strLen = s.length();

if ((strLen % 2) != 0){

thrownew IllegalArgumentException("hex char string must be an even number of chars." );

}

byte[] hexBytes =newbyte[ strLen >> 1 ];

for (int i = 0; i < strLen; i+=2){

int highNibble = charToNibble( s.charAt(i) );

int lowNibble = charToNibble( s.charAt(i+1) );

hexBytes[i>>1] = (byte)((highNibble << 4) | lowNibble);

}

return hexBytes;

}

privatestaticint charToNibble(char c )

{

if (c >='0' && c <='9'){

return c -'0';

}

if (c >='a' && c <='f'){

return c -'a' + 0xa;

}

if (c >='A' && c <='F'){

return c -'A' + 0xa;

}

thrownew IllegalArgumentException("Invalid hex character: " + c );

}

// Algorithm for decrypting file content (Blowfish).

privatestaticfinal String decryptionAlgorithm ="Blowfish/CBC/PKCS5Padding";

publicstaticvoid main (String[] args)

{

//-

// Check/Validate input args ...

//-

// Ensure required args were supplied.

if (args.length != 3){

usage();

System.exit(-1);

}

// Required args:

String encryptedFile = args[0];// Complete path/name of encrypted file.

String password= args[1];// Password/key used to encrypt/decrypt the file.

String hexsalt= args[2];// Hex salt characters for password/key.

int requiredPasswordLength = 0;// Establish required length for password and salt args.

int requiredSaltLength= 0;

if (decryptionAlgorithm.startsWith("Blowfish" )){

requiredPasswordLength = 16;

requiredSaltLength= 16;

}elseif (decryptionAlgorithm.startsWith("DESede" )){

requiredPasswordLength = 24;

requiredSaltLength= 16;

}

if (password.length() != requiredPasswordLength){

System.out.println("password arg must be " + Integer.toString( requiredPasswordLength ) +" characters for this test: " + decryptionAlgorithm );

System.exit(-1);

}

if (hexsalt.length() != requiredSaltLength){

System.out.println("salt arg must be " + Integer.toString( requiredSaltLength ) +" characters for this test: " + decryptionAlgorithm );

System.exit(-1);

}

// Convert salt hex string to a hex byte array.

byte[] saltBytes =null;

try{

saltBytes = strToHex( hexsalt );

}catch (Exception e){

System.out.println( e.getMessage() );

System.exit(-1);

}

//-

// Read and decrypt specified file.

//-

try{

// Get/Load encrypted file content.

FileInputStream encryptedFileStream =new FileInputStream(encryptedFile);

int encryptedByteCount = encryptedFileStream.available();

byte[] encryptedData =newbyte[encryptedByteCount];

int bytesRead = encryptedFileStream.read(encryptedData, 0, encryptedByteCount);

encryptedFileStream.close();

if (bytesRead != encryptedByteCount){

thrownew Exception("Couldn't read encrypted file content" );

}

// Decrypt file content.

try{

String decryptionKey = password;

byte[] salt = saltBytes;

//PBEParameterSpec ps = new PBEParameterSpec( salt, 20 );

SecretKeySpec keySpec =new SecretKeySpec( decryptionKey.getBytes("UTF-8" ), decryptionAlgorithm );

Cipher decryptCipher = Cipher.getInstance( keySpec.getAlgorithm(),"SunJCE" );

//decryptCipher.init( Cipher.DECRYPT_MODE, keySpec, ps );

decryptCipher.init( Cipher.DECRYPT_MODE, keySpec,new IvParameterSpec( salt ) );

decryptCipher.doFinal( encryptedData );

}catch (Exception e){

e.printStackTrace();

}

}catch (Exception e){

e.printStackTrace();

}

}// main()

}// class TestDecryption

[11199 byte] By [cleua] at [2007-11-27 8:55:24]
# 1

> I'm hoping one of you can tell me why when attempting

> to decrypt an OpenSSL Blowfish encrypted file via the

> following code (below), the Blowfish Cipher

> initialization code yields:

You don't show the Java parameters used in your tests, you don't show the openssl command used to perform the encryption. Without this information there is just too much uncertainty.

sabre150a at 2007-7-12 21:16:26 > top of Java-index,Security,Cryptography...
# 2

In response to the prior reply:

1) The OpenSSL command has _nothing_ at all to do with this problem. In fact you don't even need to supply an encrypted file to the program because the code never reaches the point at which the encrypted file content is decrypted (i.e. decryptCipher.doFinal( encryptedData );).

2) The password/decryption key supplied to the app is simply a user entered text string. Most any combination of characters are acceptable. For my testing I entered "1234567890123456".

3) The salt supplied to the app is simply a user entered text string which must be an even number of characters and only legitimate hex digits; the app checks/ensures both such requirements are met.For my testing I entered "1234567890123456".

It'll be appreciated if folks posting replies take time to analyze the problem, and perhaps experiment with the supplied code; it's a complete working app.

Thank you for your time and consideration.

cleua at 2007-7-12 21:16:26 > top of Java-index,Security,Cryptography...
# 3

I have spend a long time working with the interoperability between openssl and the JCE and my experience is that the devil is in the detail. I am pretty sure I know what the problem is but after your response I'm ****** if I'm going to help you.

P.S. Since it does not work, how can you say it is a 'complete working app'?

sabre150a at 2007-7-12 21:16:26 > top of Java-index,Security,Cryptography...
# 4

sabre150, Jeeze, I did say "Thank you for your time and consideration." and I truly meant it. I didn't mean to offend you or anyone else, and I appologize if you felt that my post did so.

That said, the app supplied compiles and runs, albeit it yields an exception; hence the reason for my original post. Again, I wish to point out the issue has _nothing_ to do with OpenSSL (which I've worked with for years); rather it is my lack of understanding of the JCE.

Regards, and thank you for your time and consideration.

cleua at 2007-7-12 21:16:26 > top of Java-index,Security,Cryptography...