Solved

IllegalBlockSizeException Issues with javax.crypto

Posted on 2013-02-05
9
404 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 500 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
 

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
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Exception after setting jdbc session management 2 52
create a gui in perl 3 72
difference of if loops 23 41
Way to decrease size of apk file 9 45
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
The viewer will learn how to implement Singleton Design Pattern in Java.

920 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now