Posts Tagged decryption

Encrypt and decrypt with Java

Encryption is a very important subject in computer science which developers need to deal with quite often. I already wrote a few years ago an article containing some code to encrypt data with PHP and decrypt it with Java.

I will give you this time the code to encrypt and decrypt data with the same language: Java. Once again, I used a secret key and an initialization vector for the encryption and decryption.

And here it is:

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * This class provides methods to encrypt and decrypt data.
 * @author Stephane Moreau
 */
public class Crypto {
    private static String md5(final String input) throws NoSuchAlgorithmException {
        final MessageDigest md = MessageDigest.getInstance("MD5");
        final byte[] messageDigest = md.digest(input.getBytes());
        final BigInteger number = new BigInteger(1, messageDigest);
        return String.format("%032x", number);
    }

    private Cipher initCipher(final int mode, final String initialVectorString, final String secretKey)
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
        final SecretKeySpec skeySpec = new SecretKeySpec(md5(secretKey).getBytes(), "AES");
        final IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes());
        final Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
        cipher.init(mode, skeySpec, initialVector);
        return cipher;
    }

    public String encrypt(final String dataToEncrypt, final String initialVector, final String secretKey) {
        String encryptedData = null;
        try {
            // Initialize the cipher
            final Cipher cipher = initCipher(Cipher.ENCRYPT_MODE, initialVector, secretKey);
            // Encrypt the data
            final byte[] encryptedByteArray = cipher.doFinal(dataToEncrypt.getBytes());
            // Encode using Base64
            encryptedData = (new BASE64Encoder()).encode(encryptedByteArray);
        } catch (Exception e) {
            System.err.println("Problem encrypting the data");
            e.printStackTrace();
        }
        return encryptedData;
    }

    public String decrypt(final String encryptedData, final String initialVector, final String secretKey) {
        String decryptedData = null;
        try {
            // Initialize the cipher
            final Cipher cipher = initCipher(Cipher.DECRYPT_MODE, initialVector, secretKey);
            // Decode using Base64
            final byte[] encryptedByteArray = (new BASE64Decoder()).decodeBuffer(encryptedData);
            // Decrypt the data
            final byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
            decryptedData = new String(decryptedByteArray, "UTF8");
        } catch (Exception e) {
            System.err.println("Problem decrypting the data");
            e.printStackTrace();
        }
        return decryptedData;
    }

    public static void main(final String[] args) {
        final String iv = "0123456789123456"; // This has to be 16 characters
        final String secretKey = "Replace this by your secret key";
        final Crypto crypto = new Crypto();

        final String encryptedData = crypto.encrypt("This is a test message.", iv, secretKey);
        System.out.println(encryptedData);

        final String decryptedData = crypto.decrypt(encryptedData, iv, secretKey);
        System.out.println(decryptedData);
    }
}

, , ,

12 Comments

Illegal Key Size

About a week ago, I wrote an article on how to encrypt with PHP and decrypt with Java. The funny thing is I got an error when I deployed the Java code into the live server! 😐

As a reminder, this is the code I am talking about:

SecretKeySpec skeySpec = new SecretKeySpec("SECRET KEY".getBytes(), "AES");
IvParameterSpec initalVector = new IvParameterSpec("iv_example".getBytes());
Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, initalVector);

This code was working perfectly fine on my local machine but here is the exception I got when I ran it on a Linux server:

java.security.InvalidKeyException: Illegal key size
        at javax.crypto.Cipher.a(DashoA12275)
        at javax.crypto.Cipher.a(DashoA12275)
        at javax.crypto.Cipher.a(DashoA12275)
        at javax.crypto.Cipher.init(DashoA12275)
        at javax.crypto.Cipher.init(DashoA12275)
        ...

Looking on internet for an explanation, I found the following answer on Charitha Kankanamge’s blog (which I slightly updated):

“java.security.InvalidKeyException: Illegal key size” error is a common issue which occurs when you try to invoke a secured web service in an environment where the provision for java unlimited security jurisdiction is not done.
This can be avoided by installing Java Cryptography Extension (JCE) unlimited strength jurisdiction policy files.
1. Go to http://www.oracle.com/technetwork/java/javase/downloads/index.html
2. Go to the Additional Resources section and click on the download button next to “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files X”
3. Download jce_policy-X.zip and extract it into a directory
4. You will find local_policy.jar and US_export_policy.jar files there in the extracted directory. Copy these two files to $JAVA_HOME/jre/lib/security directory (These files might already be there, replace them in this case)
5. Restart the web server and invoke your secured service again. You will not encounter the “invalidkeyException” any more

Please click on the link below to see the original article:
http://charithaka.blogspot.com/2008/08/how-to-avoid-javasecurityinvalidkeyexce.html

, , , ,

1 Comment

Encrypt with PHP – Decrypt with Java

For security reason, I wanted to encrypt the data transferred between PHP web services and a Java application. But the problem was to encrypt the data with PHP in a way that it is possible to decrypt it using Java.

It obviously exists a lot of ways of doing this. But here is the way I choose:

  • Use a secret key and an initialisation vector for the encryption and decryption
  • Use the mcrypt PHP module for the encryption
  • Use the javax.crypto Java package for the decryption

Please find below the PHP code for the encryption:

function encrypt($message, $initialVector, $secretKey) {
    return base64_encode(
        mcrypt_encrypt( 
            MCRYPT_RIJNDAEL_128,
            md5($secretKey),
            $message,  
            MCRYPT_MODE_CFB,
            $initialVector
        )
    );
}

And please see below the Java code for the decryption:

public static String md5(String input) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("MD5");
    byte[] messageDigest = md.digest(input.getBytes());
    BigInteger number = new BigInteger(1, messageDigest);
    return number.toString(16);
}

public String decrypt(String encryptedData, String initialVectorString, String secretKey) {
    String decryptedData = null;
    try {
        SecretKeySpec skeySpec = new SecretKeySpec(md5(secretKey).getBytes(), "AES");
        IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes());
        Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, initialVector);
        byte[] encryptedByteArray = (new org.apache.commons.codec.binary.Base64()).decode(encryptedData.getBytes());
        byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
        decryptedData = new String(decryptedByteArray, "UTF8");
    } catch (Exception e) {
        LOGGER.debug("Problem decrypting the data", e);
    }
    return decryptedData;
}

EDIT: The line number.toString(16) of the md5 method needs to be replaced by String.format("%032x", number). See this article for more details.

, , , , ,

45 Comments