Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

IllegalBlockSizeException Issues with javax.crypto

Posted on 2013-02-05
9
Medium Priority
?
427 Views
Last Modified: 2013-02-07
I am trying to create a Java program which reads an encrypted password from a config file, decrypts it, and uses that password to connect to an FTP site.  I want the password in the config file to be encrypted so that the program users will only be able to connect to the FTP site with my Java program.

I am attempting to use the information on this site as an example to help me build my own program:  http://www.mkyong.com/java/jce-encryption-data-encryption-standard-des-tutorial/

The program on that site has only 1 method, and that method performs both the encryption and the decryption.  I am trying to split that method into two separate methods so I can have one that performs the encryption and one that performs the decryption.  I figured I can use the "encrypt" method to encrypt the password and then I can just copy / paste the encrypted password and put it in the config file.  Then at runtime, my program will just read the config file, get the encrypted password and pass it into the decrypt program.  

When I tried to split the method into two separate methods, I now get this error whenever I try to decrypt the password:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher

The code I am using to execute my new methods is:

String startString = "Sample text to be encrypted";

String encryptedString = new String();
String decryptedString = new String();


encryptedString=routines.sampleEncryption.encrypt(startString);

System.out.println("Encrypted String: " + encryptedString);


decryptedString=routines.sampleEncryption.decrypt(encryptedString);

System.out.println("Decrypted String: " + decryptedString);

Open in new window


The class with both methods is below.

package routines;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
 
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;



public class sampleEncryption {
	 
		public static String decrypt(String strInput) {
			String rtnString = new String();
			 
			try{
	 
			    KeyGenerator keygenerator = KeyGenerator.getInstance("DES");
			    SecretKey myDesKey = keygenerator.generateKey();
	 
			    Cipher desCipher;
			    System.out.println("myDesKey: " + myDesKey.toString());
	 
			    // Create the cipher 
			    desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
	 
			    // Initialize the cipher for encryption
			    desCipher.init(Cipher.ENCRYPT_MODE, myDesKey);
	 
			    //sensitive information
			    byte[] text = strInput.getBytes();
			    System.out.println("Pwd bytes: "+ text.length);
	 
	 
			    // Initialize the same cipher for decryption
			    desCipher.init(Cipher.DECRYPT_MODE, myDesKey);
	 
			    // Decrypt the text
			    byte[] textDecrypted = desCipher.doFinal(text);
			    
			    rtnString = textDecrypted.toString();
	 
			    System.out.println("Text Decryted : " + new String(textDecrypted));
	 
			}catch(NoSuchAlgorithmException e){
				e.printStackTrace();
			}catch(NoSuchPaddingException e){
				e.printStackTrace();
			}catch(InvalidKeyException e){
				e.printStackTrace();
			}catch(IllegalBlockSizeException e){
				e.printStackTrace();
			}catch(BadPaddingException e){
				e.printStackTrace();
			}
			return rtnString; 
	 
		}
		
		public static String encrypt(String strInput) {
			String rtnString = new String();
			 
			try{
	 
			    KeyGenerator keygenerator = KeyGenerator.getInstance("DES");
			    SecretKey myDesKey = keygenerator.generateKey();
	 
			    Cipher desCipher;
	 
			    // Create the cipher 
			    desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
	 
			    // Initialize the cipher for encryption
			    desCipher.init(Cipher.ENCRYPT_MODE, myDesKey);
	 
			    //sensitive information
			    byte[] text = strInput.getBytes();
	 
			    // Encrypt the text
			    byte[] textEncrypted = desCipher.doFinal(text);
			    System.out.println("Bytes in string: " + textEncrypted.length);
			    System.out.println("String value: " + new String(textEncrypted));

			    rtnString=textEncrypted.toString();
			    
/*	 
			    // Initialize the same cipher for decryption
			    desCipher.init(Cipher.DECRYPT_MODE, myDesKey);
	 
			    // Decrypt the text
			    byte[] textDecrypted = desCipher.doFinal(textEncrypted);
	 
			    System.out.println("Text Decryted : " + new String(textDecrypted));
	*/ 
			}catch(NoSuchAlgorithmException e){
				e.printStackTrace();
			}catch(NoSuchPaddingException e){
				e.printStackTrace();
			}catch(InvalidKeyException e){
				e.printStackTrace();
			}catch(IllegalBlockSizeException e){
				e.printStackTrace();
			}catch(BadPaddingException e){
				e.printStackTrace();
			}
			return rtnString; 
			

	 
		}
		
	}

Open in new window

0
Comment
Question by:jbaird123
  • 5
  • 4
9 Comments
 
LVL 86

Accepted Solution

by:
CEHJ earned 2000 total points
ID: 38857434
You have a basic misconception here: you cannot move freely between strings and blocks of bytes produced by a block cipher. The cipher produces binary output, which can't properly be encoded as a string. You need to encode the result with Base64 or hex and then move that to a String
0
 

Author Comment

by:jbaird123
ID: 38857524
CEHJ,

Can you provide any examples or references where I can read up on this?  I'm sure you know by now I'm pretty green with most of this stuff.  :)

Thanks.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 38857571
Well before you get into all that, you'd better ensure that the concept of your use case is sound. Where are you going to store the encryption key if you're going to use it across program invocations (which you're going to have to do)?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:jbaird123
ID: 38857624
CEHJ,

I guess I hadn't given it that much thought.  Is the key something I can store in a String variable?  If so, I could just hard-code it into the program code itself.  Otherwise, I would need to store it in a file that would be distributed as part of the application.

On one hand, I would like to make this as secure as possible, but on the other hand no matter how much I try to secure the password, I cannot ever really secure it for one simple reason:  The password needs to be decrypted into plain text before I can use it.  Knowing this, any programmer can simply insert a line of code to output the password to the console window using System.out.println...  There is not any way around this since I am working with Talend and I have to work within their limitations.  

Having said that, I do want to at least secure the password so I am not advertising it to everyone by storing it in plain text.  If someone really wants to hack my program I don't think I can stop them.  But I can at least prevent the password from being stored in plain text where everyone can see it.  I guess I am relying on good will and a lot of ignorance for my security here.  It's not ideal, but it is what I have to work with.

Thanks.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 38858606
Don't forget that ftp is in itself insecure, sending the credentials over a channel that can be sniffed.
Why are you not getting the user to enter the credentials?
0
 

Author Comment

by:jbaird123
ID: 38859189
CEHJ,

All of the programs that the users are creating will eventually be run on a scheduler with no human interaction.  The credentials need to be stored somewhere so the program can get them at runtime.

Thanks.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 38863337
It might be just be easier to arrange the file permissions and ACLs for the apps such that a normal user can never read the credentials file
0
 

Author Closing Comment

by:jbaird123
ID: 38865431
Thanks, CEHJ.

I had never done anything with encoding or decoding Base64, so it took me some time to figure out what you were saying.  I figured it out now, so thanks!
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 38865606
:)
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
The viewer will learn how to implement Singleton Design Pattern in Java.
Suggested Courses

879 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question