Symetric Decryption throws IllegalBlockSizeException? Please help...

Dear all,

I'm new to cryptography in general and I have been modifying the symmetric key examples so that:

a) the application can read data from a file, encrypt it, then overwrite contents of the file with the encrypted bytes. The generated secret key is saved to a different file.

b) the encrypted file can later be read and decrypted, using the stored secret key.

All is fine until the decrypt.doFinal(input_bytes ) method throws an IllegalBlockSizeException.

Does anyone know what's wrong? I suspect it is the encoding of the text when I read it or save it to a file, but I can't be sure. Please help!

Anyway, here are the code components:

Encoding

########

1) Read data from file:

InputStream inputstream = getClass().getResourceAsStream("/" + "Portal.properties");

Properties propInProps = new Properties();

propInProps.load(inputstream);

sOutputString = propInProps.toString();

2) Generate Symmetric Key:

Security.addProvider( new com.sun.crypto.provider.SunJCE() );

KeyGenerator generator = KeyGenerator.getInstance("DES");

generator.init( 56, new SecureRandom() );

key = generator.generateKey();

3) Encrypt it:

Cipher cipher_encrypt = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher_encrypt.init( Cipher.ENCRYPT_MODE, key );

byte[] encode_input_bytes = sInputString.getBytes("UTF8");

byte[] encode_output_bytes = cipher_encrypt.doFinal(encode_input_bytes );

BASE64Encoder encoder = new BASE64Encoder();

String encoded_string = encoder.encode( encode_output_bytes );

4) Save the Key:

FileOutputStream out = new FileOutputStream("SECURE_KEY");

ObjectOutputStream os = new ObjectOutputStream(out);

os.writeObject(sInKey);

os.flush();

5) Save the encoded bytes:

FileOutputStream out = new FileOutputStream("../Data.EN");

ObjectOutputStream os = new ObjectOutputStream(out);

os.writeObject(sOutputString);

os.flush();

Decoding

########

1. Read encrypted data from file:

BufferedReader in = new BufferedReader(new FileReader("../Data.EN"));

String sInReadString = "";

while((in.readLine())!= null)

{

sInReadString = sInReadString + in.readLine();

}

sOutputString = sInReadString;

2. Get the stored symmetric key:

// Reading an object from a stream

FileInputStream in = new FileInputStream("SECURE_KEY");

// Step 2. Create an object input stream

ObjectInputStream ins = new ObjectInputStream(in);

// Step 3. Got to know what you are reading

key = (SecretKey)ins.readObject();

3. Decrypt it:

Security.addProvider( new com.sun.crypto.provider.SunJCE() );

Cipher cipher_decrypt = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher_decrypt.init( Cipher.DECRYPT_MODE, key );

System.out.print("\nsInputString in execute() = "+sInputString);

BASE64Decoder decoder = new BASE64Decoder();

byte[] decode_input_bytes = decoder.decodeBuffer(sInputString );

byte[] decode_output_bytes = cipher_decrypt.doFinal( decode_input_bytes ); > failed!

Any suggestions or comments are much appreciated. Thanks in advance!!!

kenshin0

[3389 byte] By [kenshin0] at [2007-9-26 1:37:22]
# 1
Hi,Changegenerator.init( 56, new SecureRandom() )to generator.init( 64, new SecureRandom() ) Then you will not get the Illegal Block size Exception error.ThanksBakrudeen
bakrudeen_indts at 2007-6-29 2:24:01 > top of Java-index,Security,Cryptography...
# 2

Hello,

Thanks for your reply.

I've tried running "generator.init( 64, new SecureRandom() )" but then it prompted a "java.security.InvalidParameterException: Wrong keysize: must be equal to 56 ".

I also tried to run it as "generator.init(new SecureRandom())" but then it gives me the same "javax.crypto.IllegalBlockSizeException: Input length (with padding) not multiple of 8 byte".

Have you got any other ideas where I have gone wrong? Or have I misunderstood some fundamental concepts?

Though a bit long, I'll post the code here so you can have a go. Thanks a lot!!

Regards,

kenshin0

#####################################

package com.zone.portal.utils;

import java.io.*;

import java.security.*;

import javax.crypto.*;

import sun.misc.*;

import java.util.*;

/*

* ZoneCodec.java

*

* Created on July 22, 2001, 3:52 PM

* NOTE: Input and output filenames are currently hard-coded.

*

*/

/**

*

* @author Administrator

* @version

*/

public class ZoneCodec

{

private final static String ENCRYPT_FLAG = "ENCRYPT";

private final static String DECRYPT_FLAG = "DECRYPT";

private final static String SECURE_KEY = "../SECRET_KEY.EN";

private static SecretKey key = null;

private String sInputString = "";

private String sInputFlag = "";

/** Creates new ZoneCodec */

public ZoneCodec()

{ }

public static void main(String[] args)

{

String sInputFlag = "";

String sInputString = "";

String sInputFileName = "";

String sOutputFileName = "";

if(args.length < 1)

{

System.out.print("\nUsage: java ZoneCodec -inputFlag (ENCRYPT/DECRYPT)");

System.exit(1);

}

else

{

sInputFlag = args[0].substring(1, args[0].length());;

sInputFileName = args[1].substring(1, args[1].length());

sOutputFileName = args[2].substring(1, args[2].length());

}

// load input file into String

ZoneCodec zoneCodeoc = new ZoneCodec();

sInputString = zoneCodeoc.readInputFile(sInputFlag, sInputFileName);

if (sInputFlag.equals(ZoneCodec.ENCRYPT_FLAG))

{

System.out.print("\nEncode Input String = "+sInputString);

String sEncryptedString = "";

sEncryptedString = zoneCodeoc.execute(sInputString, ZoneCodec.ENCRYPT_FLAG);

System.out.print("\nEncoded Output String = "+sEncryptedString);

System.out.print("\n");

zoneCodeoc.writeOutputFile(ZoneCodec.ENCRYPT_FLAG, sOutputFileName, sEncryptedString);

// erase key used in this class

key = null;

}

else if (sInputFlag.equals(ZoneCodec.DECRYPT_FLAG))

{

// Now Decrypt the message again

// Retrieve key from serialzed class

key = zoneCodeoc.getKey();

System.out.print("\nRetrieved Key = "+key.toString());

String sRecoveredString = zoneCodeoc.execute(sInputString, ZoneCodec.DECRYPT_FLAG);

System.out.print("\nDecoded Output String = "+sRecoveredString);

}

}

private SecretKey getKey()

{

SecretKey key = null;

try

{

// Reading an object from a stream

FileInputStream in = new FileInputStream(ZoneCodec.SECURE_KEY);

// Step 2. Create an object input stream

ObjectInputStream ins = new ObjectInputStream(in);

// Step 3. Got to know what you are reading

key = (SecretKey)ins.readObject();

}

catch(IOException io){System.out.print(io.toString());}

catch(Exception e){System.out.print(e.toString());}

return key;

}

private void saveKey(SecretKey sInKey)

{

try

{

FileOutputStream out = new FileOutputStream(ZoneCodec.SECURE_KEY);

ObjectOutputStream os = new ObjectOutputStream(out);

os.writeObject(sInKey);

os.flush();

}

catch(IOException io){System.out.print(io.toString());}

catch(Exception e){System.out.print(e.toString());}

}

public String execute(String sInputString, String sCodecFlag)

{

String sOutputString="";

try

{

if( sCodecFlag.equals(ZoneCodec.ENCRYPT_FLAG) )

{

// Create New Secret Key from JCE methods

Security.addProvider( new com.sun.crypto.provider.SunJCE() );

KeyGenerator generator = KeyGenerator.getInstance("DES");

generator.init(56, new SecureRandom() );

key = generator.generateKey();

System.out.print("\n56 Symmetric Key generated: "+key.toString()+"\n");

// Serialze the key and save it to file

this.saveKey(key);

System.out.print("\nKey saved to file '"+ZoneCodec.SECURE_KEY+"'.");

Cipher cipher_encrypt = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher_encrypt.init( Cipher.ENCRYPT_MODE, key );

byte[] encode_input_bytes = sInputString.getBytes("UTF8");

byte[] encode_output_bytes = cipher_encrypt.doFinal(encode_input_bytes );

BASE64Encoder encoder = new BASE64Encoder();

String encoded_string = encoder.encode( encode_output_bytes );

sOutputString = encoded_string;

}

else if (sCodecFlag.equals(ZoneCodec.DECRYPT_FLAG))

{

key = this.getKey();

System.out.print("\nKey retrieved from file '"+ZoneCodec.SECURE_KEY+"'.");

Security.addProvider( new com.sun.crypto.provider.SunJCE() );

Cipher cipher_decrypt = Cipher.getInstance("DES/ECB/PKCS5Padding");

cipher_decrypt.init( Cipher.DECRYPT_MODE, key );

System.out.print("\nsInputString in execute() = "+sInputString);

BASE64Decoder decoder = new BASE64Decoder();

byte[] decode_input_bytes = decoder.decodeBuffer(sInputString );

byte[] decode_output_bytes = cipher_decrypt.doFinal( decode_input_bytes );

String decoded_string = new String( decode_output_bytes, "UTF8" );

sOutputString = decoded_string.trim();

}

}

catch( UnsupportedEncodingException e )

{

System.out.println( "UnsupportedEncodingException" );

return e.toString();

}

catch( NoSuchAlgorithmException e )

{

System.out.println ( "NoSuchAlgorithmException" );

return e.toString();

}

catch( IOException e )

{

System.out.println ( "IOException" );

return e.toString();

}

catch( NoSuchPaddingException e )

{

System.out.println ( "NoSuchPaddingException" );

return e.toString();

}

catch( InvalidKeyException e )

{

System.out.println ( "InvalidKeyException" );

return e.toString();

}

catch( IllegalBlockSizeException e )

{

System.out.println ( "IllegalBlockSizeException" );

return e.toString();

}

catch( BadPaddingException e )

{

System.out.println ( "BadPaddingException" );

return e.toString();

}

/* catch( NoSuchProviderException e )

{

System.out.println ( "NoSuchProviderException" );

return e.toString();

}

*/

return sOutputString;

}

private void writeOutputFile(String sInputFlag, String sOutputFileName, String sOutputString)

{

if (sInputFlag.equals(ZoneCodec.ENCRYPT_FLAG))

{

// write to file

try

{

FileOutputStream out = new FileOutputStream("../Portal.EN");

ObjectOutputStream os = new ObjectOutputStream(out);

os.writeObject(sOutputString);

os.flush();

}

catch(IOException io){System.out.print(io.toString());}

catch(Exception e){System.out.print(e.toString());}

}

}

private String readInputFile(String sInputFlag, String sInputFileName)

{

String sOutputString = "";

try

{

if (sInputFlag.equals(ZoneCodec.ENCRYPT_FLAG))

{

// Reading in an unencrypted properties file

InputStream inputstream = getClass().getResourceAsStream("/" + "Portal.properties");

Properties propInProps = new Properties();

propInProps.load(inputstream);

sOutputString = propInProps.toString();

}

else if (sInputFlag.equals(ZoneCodec.DECRYPT_FLAG))

{

// Read in an encrypted properties file

BufferedReader in = new BufferedReader(new FileReader("../Portal.EN"));

String sInReadString = "";

while((in.readLine())!= null)

{

sInReadString = sInReadString + in.readLine();

}

sOutputString = sInReadString;

}

}

catch(Exception ioe)

{

System.out.print(ioe.toString());

System.exit(0);

}

return sOutputString;

}

}

#####################################

kenshin0 at 2007-6-29 2:24:01 > top of Java-index,Security,Cryptography...
# 3

Hi,

I am reviewing your code. Please I need to know further clarification.

As far as I understood from your program, you are reading data from portal.properties and then you are working with encryption and decryption. Am I correct in it.

Anyhow, please give me sometime in reviewing your code.

Meanwhile I have sent a sample code, which does the encryption or decryption.

import com.sun.crypto.provider.SunJCE;

import java.io.*;

import java.security.*;

import javax.crypto.Cipher;

import javax.crypto.KeyGenerator;

import sun.misc.*;

public class SecretWriting

{

public SecretWriting()

{

}

public static void main(String args[])

throws Exception

{

if(args.length < 2)

{

System.out.println("Usage : SecretWriting -e|-d text");

return;

}

Security.addProvider(new SunJCE());

Object obj;

try

{

ObjectInputStream objectinputstream = new ObjectInputStream(new FileInputStream("des.key"));

obj = (Key)objectinputstream.readObject();

objectinputstream.close();

}

catch(FileNotFoundException filenotfoundexception)

{

KeyGenerator keygenerator = KeyGenerator.getInstance("DES");

keygenerator.init(new SecureRandom());

obj = keygenerator.generateKey();

ObjectOutputStream objectoutputstream = new ObjectOutputStream(new FileOutputStream("des.key"));

objectoutputstream.writeObject(obj);

objectoutputstream.close();

}

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

if(args[0].indexOf("e") != -1)

{

cipher.init(1, ((Key) (obj)));

String s = args[1];

for(int i = 2; i < args.length; i++)

s = s + " " + args;

byte abyte1[] = s.getBytes("UTF8");

byte abyte3[] = cipher.doFinal(abyte1);

BASE64Encoder base64encoder = new BASE64Encoder();

String s2 = base64encoder.encode(abyte3);

System.out.println(s2);

} else

if(args[0].indexOf("d") != -1)

{

cipher.init(2, ((Key) (obj)));

BASE64Decoder base64decoder = new BASE64Decoder();

byte abyte0[] = base64decoder.decodeBuffer(args[1]);

byte abyte2[] = cipher.doFinal(abyte0);

String s1 = new String(abyte2, "UTF8");

System.out.println(s1);

}

}

}

I hope this will help you.

Thanks

Bakrudeen

bakrudeen_indts at 2007-6-29 2:24:01 > top of Java-index,Security,Cryptography...
# 4

the key retrieving generation is completely funny. You have to use the .getEncoded()

method of the SecretKey class in order to store the key in a file, and use the SecretKeySpec method to get back the SecretKey. It is a wonder you arrive to generate back the key like this.

I will see if i can find back the exact code lines, but take a look at theses methods, they are the "key" to your problems.

Bugsman

marc_huhardeaux at 2007-6-29 2:24:01 > top of Java-index,Security,Cryptography...
# 5

> the key retrieving generation is completely funny. You

> have to use the .getEncoded()

> method of the SecretKey class in order to store the

> key in a file, and use the SecretKeySpec method to get

> back the SecretKey. It is a wonder you arrive to

> generate back the key like this.

>

> I will see if i can find back the exact code lines,

> but take a look at theses methods, they are the "key"

> to your problems.

>

> Bugsman

Hi,

Oops -- that was embarrasing. Forgive me for harshly putting together some code without fully understanding how things should be done!

Thanks for pointing out. I hope you'll be able to spare some of your precious time reviewing my poor code.

I'd also be grateful if anyone can tell me links to JCE/Encryption/Decryption tutorials.

Thanks,

kenshin0

kenshin0 at 2007-6-29 2:24:01 > top of Java-index,Security,Cryptography...
# 6

well i've taken a look at some old testing code where i put and retrieve a SecretKey from a file.

Here the bit code for retrieving the key from the file:

try

{

SecretKeySpec desKeySpec = new SecretKeySpec(decodedKeyC, "DES");

desKey = (javax.crypto.SecretKey) desKeySpec;

}

catch(Exception e)

{

e.printStackTrace();

}

note that the decodedKeyC is the byte[] readen from the file.

And here is the code for writing the key into a file :

byte[] encodedKey = desKey.getEncoded();

fos.write(encodedKey);

Where deskey is the Secret key of your program and fos is a FileOutputStream pointing to your key file.

I spotted the second code you posted and using the CipherInputStream

and CipherOutputStream

is a better choice. If i have some free time, i will try to correct your code. Meanwhile, you should search the site for any help about JCE.

Hope this will enlight a little your knowledge in cryptology.

marc_huhardeaux at 2007-6-29 2:24:01 > top of Java-index,Security,Cryptography...
# 7
Hi bakrudeen. I tried the code you pasted but it still shows the IllegalBlockSizeException when decrypting. Any ideas?
ricky_artigas at 2007-6-29 2:24:01 > top of Java-index,Security,Cryptography...
# 8

I got it to work as so, hope it helps:

//KEY GENERATION:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

public static void main (String args[]) throws Exception{

System.out.println("Generating DES key.....");

KeyGenerator generator = KeyGenerator.getInstance("DES");

String filepath = "D:\\des.key";

generator.init(new SecureRandom());

Key key = generator.generateKey();

System.out.println("Generating DES key.....done");

try{

ObjectOutputStream out = new ObjectOutputStream(

new FileOutputStream(filepath));

out.writeObject(key);

out.close();

}

catch(Exception ex){

System.out.println("Could nat save DES key to file "+filepath);

System.out.println(ex);

}

}

//STRING ECRYPTION:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

public String encrypt (String filePath, String data) throws Exception{

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

Key key;

System.out.println("Reading private key from file DSAprivate.key...");

try{

ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));

Object object = in.readObject();

key = (javax.crypto.SecretKey) object;

in.close();

}

catch(Exception ex){

System.out.println("Could not read the private key from "+filePath);

System.out.println(ex);

return null;

}

cipher.init(Cipher.ENCRYPT_MODE, key);

//convert the inptu the utf8 format

byte[] inputBytes = data.getBytes("UTF8");

byte[] outputBytes = cipher.doFinal(inputBytes);

BASE64Encoder encoder = new BASE64Encoder();

return encoder.encode(outputBytes);

}

//STRING DECRYPTION::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

public String decrypt (String filePath, String data) throws Exception{

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

Key key;

System.out.println("Reading private key from file DSAprivate.key...");

try{

ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));

Object object = in.readObject();

key = (javax.crypto.SecretKey) object;

in.close();

}

catch(Exception ex){

System.out.println("Could not read the private key from "+filePath);

System.out.println(ex);

return null;

}

cipher.init(Cipher.DECRYPT_MODE, key);

BASE64Decoder decoder = new BASE64Decoder();

//convert the input the utf8 format

byte[] inputBytes = decoder.decodeBuffer(data);

byte[] outputBytes = cipher.doFinal(inputBytes);

return new String(outputBytes, "UTF8");

}

javatraveler at 2007-6-29 2:24:01 > top of Java-index,Security,Cryptography...
# 9
The Zombie Waaaalllllllks....I suspect the original poster figured out his problem - he's had four years to do so since last posting, after all.Grant
ggainey at 2007-6-29 2:24:01 > top of Java-index,Security,Cryptography...