Hi Friends,

    I have PSKC XML file.. That contains my Salt/Key,IV(Initialization Vector),Encrpted Data,password also. Now, I am trying to Do Password Based Encyption and Decryption Using PBEWITHSHA1AND128BITAES-CBC-BC Algorithm. 
It works,If i generate salt and IV randomly. But,it fails to work,if i dont generate it randomly... Instead of generating Salt and IV randomly.. i am using my own salt,IV,password and everything.. 
Here is my code....

import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.crypto.PBEParametersGenerator;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;

/**
 * parts of this code were copied from the StandardPBEByteEncryptor class from
 * the Jasypt (www.jasypt.org) project
 */

public class AESCrypt
{
    private final String KEY_ALGORITHM = "PBEWITHSHA1AND128BITAES-CBC-BC";
//    private final String KEY_ALGORITHM = "PBEWithSHA256And256BitAES-CBC-BC";
    private final String MODE_PADDING = "/CBC/PKCS5Padding";
    private final int DEFAULT_SALT_SIZE_BYTES = 128;

    private byte[] ivParamSpec1 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    private final SecureRandom rand;

    private final String passwd = "kn4\"bE,W11kewsUd";

    public AESCrypt() throws Exception
    {
        rand = SecureRandom.getInstance("SHA1PRNG");
    }

    private byte[] generateSalt(int size)
    {
        byte[] salt = new byte[size];
        rand.nextBytes(salt);

        return salt;
    }

    private SecretKey generateKey(String algorithm, int keySize, byte[] salt)
            throws NoSuchProviderException, NoSuchAlgorithmException,
            InvalidKeySpecException
     {
//      SecretKeySpec Spec =  new SecretKeySpec(keyBytes, algorithm);
        SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
        PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.toCharArray(), salt,100000);
        SecretKey tmpKey = factory.generateSecret(pbeKeySpec);
        byte[] keyBytes = new byte[keySize / 8];
        SecretKeySpec Spec =  new SecretKeySpec(keyBytes, algorithm);
        System.arraycopy(tmpKey.getEncoded(), 0, keyBytes, 0, keyBytes.length);
        System.out.println("SecretKeySpec(keyBytes, algorithm)---->"+Spec);
        return Spec;
    }

    private byte[] generateIV(Cipher cipher) 
    {
        byte[] iv = new byte[cipher.getBlockSize()];
        rand.nextBytes(iv);

        return iv;
    }

    private byte[] appendArrays(byte[] firstArray, byte[] secondArray) 
    {
        final byte[] result = new byte[firstArray.length + secondArray.length];

        System.arraycopy(firstArray, 0, result, 0, firstArray.length);
        System.arraycopy(secondArray, 0, result, firstArray.length, secondArray.length);

        return result;
    }

    public byte[] encrypt(String algorithm, int keySize, final byte[] message)
            throws Exception
    {
        Cipher cipher = Cipher.getInstance(algorithm + MODE_PADDING);
        // The salt size for the chosen algorithm is set to be equal
        // to the algorithm's block size (if it is a block algorithm).
        int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES;
        int algorithmBlockSize = cipher.getBlockSize();
        if (algorithmBlockSize > 0) 
        {
            saltSizeBytes = algorithmBlockSize;
        }

        // Create salt
//        final byte[] salt = generateSalt(saltSizeBytes);
        final byte[] salt = "EW0h0yUcDX72WU9UiKiCwDpXsJg=".getBytes();

        SecretKey key = generateKey(algorithm, keySize, salt);

        // create a new IV for each encryption
//        final IvParameterSpec ivParamSpec = new IvParameterSpec();
         ivParamSpec1 = "ixYgnjjY58RNacxZHwxgBQ==".getBytes();
        final IvParameterSpec ivParamSpec = new IvParameterSpec(ivParamSpec1);
        // Perform encryption using the Cipher
        cipher.init(Cipher.ENCRYPT_MODE, key, ivParamSpec);
        byte[] encryptedMessage = cipher.doFinal(message);

        // append the IV and salt
        encryptedMessage = appendArrays(ivParamSpec.getIV(), encryptedMessage);
        encryptedMessage = appendArrays(salt, encryptedMessage);

        return encryptedMessage;
    }

    public byte[] decrypt(String algorithm, int keySize, final byte[] encryptedMessage) throws Exception
    {
        Cipher cipher = Cipher.getInstance(algorithm + MODE_PADDING);

        // determine the salt size for the first layer of encryption
        int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES;
        int algorithmBlockSize = cipher.getBlockSize();
        if (algorithmBlockSize > 0)
        {
            saltSizeBytes = algorithmBlockSize;
        }
        System.out.println("saltSizeBytes:" + saltSizeBytes);

        byte[] decryptedMessage = new byte[encryptedMessage.length];
        System.arraycopy(encryptedMessage, 0, decryptedMessage, 0,
                encryptedMessage.length);

        // extract the salt and IV from the incoming message
        byte[] salt = null;
        byte[] iv = null;
        byte[] encryptedMessageKernel = null;
        final int saltStart = 0;
        final int saltSize = (saltSizeBytes < decryptedMessage.length ? saltSizeBytes
                : decryptedMessage.length);
        // final int saltSize = 32;
        // System.out.println("saltSize:"+saltSize);

        final int ivStart = (saltSizeBytes < decryptedMessage.length ? saltSizeBytes
                : decryptedMessage.length);
        final int ivSize = cipher.getBlockSize();
        final int encMesKernelStart = (saltSizeBytes + ivSize < decryptedMessage.length ? saltSizeBytes
                + ivSize
                : decryptedMessage.length);
        final int encMesKernelSize = (saltSizeBytes + ivSize < decryptedMessage.length ? (decryptedMessage.length
                - saltSizeBytes - ivSize)
                : 0);

        salt = new byte[saltSize];
        iv = new byte[ivSize];
        System.out.println("saltSize:" + saltSize);
        System.out.println("ivSize:" + ivSize);

        encryptedMessageKernel = new byte[encMesKernelSize];
        System.out.println("encryptedMessageKernel");

        System.arraycopy(decryptedMessage, saltStart, salt, 0, saltSize);
        System.arraycopy(decryptedMessage, ivStart, iv, 0, ivSize);
        System.arraycopy(decryptedMessage, encMesKernelStart,
                encryptedMessageKernel, 0, encMesKernelSize);

        SecretKey key = generateKey(algorithm, keySize, salt);
        System.out.println("ekey");

        ivParamSpec1 = "ixYgnjjY58RNacxZHwxgBQ==".getBytes();
        IvParameterSpec ivParamSpec = new IvParameterSpec(ivParamSpec1);


        // Perform decryption using the Cipher
        cipher.init(Cipher.DECRYPT_MODE, key, ivParamSpec);
        decryptedMessage = cipher.doFinal(encryptedMessageKernel);

        // Return the results
        return decryptedMessage;
    }

    private byte[] decryptWithLWCrypto(byte[] cipher, String password, byte[] salt, final  int iterationCount)
            throws Exception
    {
        PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(new SHA256Digest());
        char[] passwordChars = password.toCharArray();
        final byte[] pkcs12PasswordBytes = PBEParametersGenerator.PKCS12PasswordToBytes(passwordChars);
        pGen.init(pkcs12PasswordBytes, salt, iterationCount);
        CBCBlockCipher aesCBC = new CBCBlockCipher(new AESEngine());
        ParametersWithIV aesCBCParams = (ParametersWithIV) pGen.generateDerivedParameters(256, 128);
        aesCBC.init(false, aesCBCParams);
        PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(aesCBC,new PKCS7Padding());
        byte[] plainTemp = new byte[aesCipher.getOutputSize(cipher.length)];
        int offset = aesCipher.processBytes(cipher, 0, cipher.length, plainTemp, 0);
        int last = aesCipher.doFinal(plainTemp, offset);
        final byte[] plain = new byte[offset + last];
        System.arraycopy(plainTemp, 0, plain, 0, plain.length);
        System.out.println("Plain--->"+plain);
        return plain;
    }

    public static void main(String[] args) throws Exception 
    {
        Security.addProvider(new BouncyCastleProvider());
        AESCrypt aesCrypt = new AESCrypt();
        String originalText = "6skYngWZxkTgsRIoFPLS1mpI32Q=";
        String toDecrypt = new String(Base64.encode(aesCrypt.encrypt("AES", 128, originalText.getBytes())));
        System.out.println("Original Data----->"+originalText);
        System.out.println("After Encrpytion--->"+toDecrypt);

        byte[] criptata = Base64.decode(toDecrypt); 
        byte[] decriptata = aesCrypt.decrypt("AES", 128, criptata);
        String msgdecriptato = new String(decriptata); 
        System.out.println("After Decrption--->"+msgdecriptato);
        if (!originalText.equals(msgdecriptato)) 
        {
            throw new IllegalStateException("Strings do not match!");
        }
        else
        {
            System.out.println("Matched.....");
        }

//        byte[] cipher = "RVcwaDB5VWNEWDcyV1U5VWlLaUN3RHBYc0pnPWl4WWduampZNThSTmFjeFoJfgJbigcnDs0TJdNu7yEkprlJFdilLrLJT8uoQ3dm/A==".getBytes();
//        String password = "kn4\"bE,W11kewsUd";
//        byte[] salt = "EW0h0yUcDX72WU9UiKiCwDpXsJg=".getBytes();
//        System.out.println(aesCrypt.decryptWithLWCrypto(cipher, password, salt , 128));
    }
}



When I try to run this... Am getting following Errors,



Exception in thread "main" java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long
    at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)
    at com.sun.crypto.provider.AESCipher.engineInit(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at AESCrypt.encrypt(AESCrypt.java:113)
    at AESCrypt.main(AESCrypt.java:213)

I cant truncate the salt size or IV size and all..  then there will not be any data integrity and all.. 
I tried with the all possibilities of code change.. I didn't come up with any solutions. 
Plz Help me... Thanks in advance...

InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long

That seems perfecrtly clear!
(The rest of the stack is useless here because the line numbers don't match the code you posted)
What happens when you use an IV that is exactly 16 bytes long?

Thanks for your reply.. It will work..But,it will produces some other results.. I want to get my original text..

OK, so with a correct length IV it runs without Exceptions, but the decrypted String does not match the original string?
Have you tried decrypting the byte array that you get from encryption? That would eliminate the Base64 encode/decode as a possible source of problems.

Thanks for your reply.. when i try with byte array of encrpted data.. It is returning this error.. 
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 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.AESCipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)

    at AESCrypt.decrypt(AESCrypt.java:162)
    at AESCrypt.main(AESCrypt.java:177)

Presumably you can rely on the encryption to produce an array that is valid for decryption, so maybe the problem is in your code where you add/unpack the IV/salt (etc)?
It seems to me that you have a lot going on in this code; too much to debug all in one go. I would break it down into its steps, and test.debug them one at a time.

This article has been dead for over six months. Start a new discussion instead.