Solved

IllegalBlockSizeException Issues with javax.crypto

Posted on 2013-02-05
9
410 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
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 

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

The New “Normal” in Modern Enterprise Operations

DevOps for the modern enterprise offers many benefits — increased agility, productivity, and more, but digital transformation isn’t easy, especially if you’re not addressing the right issues. Register for the webinar to dive into the “new normal” for enterprise modern ops.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
expectj telnet failing 5 45
eclipse buid path vs tomcat lib path 10 34
Detect Closed Loops (circles, figure-8s, etc) in PNG Images 6 58
java imports not found 4 30
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 second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

830 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