Solved

IllegalBlockSizeException Issues with javax.crypto

Posted on 2013-02-05
9
400 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
:)
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
I had a project requirement for a displaying a user workbench .This workbench would consist multiple data grids .In each grid the user will be able to see a large number of data. These data grids should allow the user to 1. Sort 2. Export the …
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:

762 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

10 Experts available now in Live!

Get 1:1 Help Now