Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

IllegalBlockSizeException Issues with javax.crypto

Posted on 2013-02-05
9
Medium Priority
?
422 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
AWS Certified Solutions Architect - Associate

This course has been developed to provide you with the requisite knowledge to not only pass the AWS CSA certification exam but also gain the hands-on experience required to become a qualified AWS Solutions architect working in a real-world environment.

 

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

Build and deliver software with DevOps

A digital transformation requires faster time to market, shorter software development lifecycles, and the ability to adapt rapidly to changing customer demands. DevOps provides the solution.

Question has a verified solution.

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

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…
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
The viewer will learn how to implement Singleton Design Pattern in Java.
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.
Suggested Courses

722 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