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]

Hi,Changegenerator.init( 56, new SecureRandom() )to generator.init( 64, new SecureRandom() ) Then you will not get the Illegal Block size Exception error.ThanksBakrudeen
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;
}
}
#####################################
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
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
> 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
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.
Hi bakrudeen. I tried the code you pasted but it still shows the IllegalBlockSizeException when decrypting. Any ideas?
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");
}
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