padded cypher, converting output correctly to hex and back.

I'm using the code below to encrypt string and get a hex representation from the encrypted string.

This way I can save that hex representation in a properties file.

Later I have to decrypt the hex representation back to the original string.

It works, but only when using certain values.

When using :

privatefinalstaticchar[] pwd ="m001uasterpasswocvgcr".toCharArray();

it works.

When using:

privatefinalstaticchar[] pwd ="m001uasterpasswocvgcrg".toCharArray();

It gives me the following error:

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

at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)

at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)

at com.sun.crypto.provider.SunJCE_ab.b(DashoA13*..)

at com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineDoFinal(DashoA13*..)

at javax.crypto.Cipher.doFinal(DashoA13*..)

at foldersync.dataAccess.clsStringEncryption.decrypt(clsStringEncryption.java:121)

at foldersync.dataAccess.clsStringEncryption.main(clsStringEncryption.java:85)

Where am I going wrong? you can give feedback on the rest of the code 2. because I'm lost in Java's way of handling encryption.

Full test code below: (please don't mind the half baked singleton design)

import java.math.BigInteger;

import java.security.InvalidAlgorithmParameterException;

import java.security.InvalidKeyException;

import java.security.NoSuchAlgorithmException;

import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;

import javax.crypto.Cipher;

import javax.crypto.IllegalBlockSizeException;

import javax.crypto.NoSuchPaddingException;

import javax.crypto.SecretKey;

import javax.crypto.SecretKeyFactory;

import javax.crypto.spec.PBEKeySpec;

import javax.crypto.spec.PBEParameterSpec;

/**

*

* @author finalbeta

*/

publicclass clsStringEncryption{

privatestatic PBEParameterSpec algorithm;

privatestatic PBEKeySpec pbeKeySpec;

privatestatic SecretKeyFactory keyBuilder;

privatestatic SecretKey key;

privatestatic Cipher pbeCipher;

publicstaticint iteration = 128;

publicstaticbyte[] salt ={(byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c, (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99};

privatefinalstaticchar[] pwd ="m001uasterpasswocvgcr".toCharArray();

/**

* Singleton to create key and cipher, but keep it private since everything can be static anyway.

*/

privatestaticfinal clsStringEncryption instance =new clsStringEncryption();

private clsStringEncryption(){

algorithm =new PBEParameterSpec(salt, iteration);

pbeKeySpec =new PBEKeySpec(pwd);

try{

//create key

keyBuilder = SecretKeyFactory.getInstance("PBEWithMD5AndDES");

key = keyBuilder.generateSecret(pbeKeySpec);

}catch (NoSuchAlgorithmException ex){

ex.printStackTrace();

}catch (InvalidKeySpecException ex){

ex.printStackTrace();

}

try{

//create cipher

pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

}catch (NoSuchAlgorithmException ex){

ex.printStackTrace();

}catch (NoSuchPaddingException ex){

ex.printStackTrace();

}

}

privatestatic String asHex (byte buf[]){

StringBuffer strbuf =new StringBuffer(buf.length * 2);

int i;

for (i = 0; i < buf.length; i++){

if (((int) buf[i] & 0xff) < 0x10)

strbuf.append("0");

strbuf.append(Long.toString((int) buf[i] & 0xff, 16));

}

return strbuf.toString();

}

privatestaticbyte[] fromHex (String buff){

returnnew BigInteger(buff, 16).toByteArray();

}

publicstaticvoid main(String[] args)throws Exception{

String mypass ="passwordtoencrypt";

System.out.println(encrypt(mypass));

System.out.println(decrypt(encrypt(mypass)));

}

/**

* @return Hex representation of the encrypted String

*/

publicstatic String encrypt(String text){

algorithm =new PBEParameterSpec(salt, iteration);

try{

//init cipher

pbeCipher.init(Cipher.ENCRYPT_MODE, key, algorithm);

//encrypt

byte[] textTranslated = pbeCipher.doFinal(text.getBytes());

//convert byte to String and return

return asHex(textTranslated);

}catch(Exception e){

e.printStackTrace();

}

returnnull;

}

/**

* @return Decripted String from a Hex representation.

*/

publicstatic String decrypt(String text){

try{

//init cipher

pbeCipher.init(Cipher.DECRYPT_MODE, key, algorithm);

}catch (InvalidKeyException ex){

ex.printStackTrace();

}catch (InvalidAlgorithmParameterException ex){

ex.printStackTrace();

}

try{

byte buffer[] = fromHex(text);

returnnew String(pbeCipher.doFinal(buffer));

}catch (IllegalBlockSizeException ex){

ex.printStackTrace();

returnnull;

}catch (BadPaddingException ex){

ex.printStackTrace();

returnnull;

}

}

}

[10562 byte] By [finalbetaa] at [2007-11-26 18:37:30]
# 1

This may not be the whole problem but what will happen if your byte array you encode as hex has a leading zero byte? The BigInteger created when decoding will drop the leading zero so your decoded byte array will be a byte short.

Use a proper Hex encoder/decoder. Google for 'Jakarta commons codec' for a free one.

sabre150a at 2007-7-9 6:11:35 > top of Java-index,Security,Cryptography...
# 2
String is not a holder for binary data. Use the encrypted byte[] directly, or base-64 encode it if you must have a String.
ejpa at 2007-7-9 6:11:35 > top of Java-index,Security,Cryptography...
# 3

> String is not a holder for binary data. Use the

> encrypted byte[] directly, or base-64 encode it if

> you must have a String.

I don't think the OP is trying to convert encrypted bytes to a String directly. He is HEX encoding them but I think his HEX decoder is not working because it is discarding leading zeros. Try running

BigInteger value = new BigInteger("00112233445566778899AABBCCDDEEFF", 16);

System.out.println(Arrays.toString(value.toByteArray()));

sabre150a at 2007-7-9 6:11:35 > top of Java-index,Security,Cryptography...
# 4
Yup, careless of me, I agree with your diagnosis.
ejpa at 2007-7-9 6:11:35 > top of Java-index,Security,Cryptography...