1
votes

I have recently used the AES CBC 128 algorithm in Java in order to cipher data. Now I need to rebuild that algorithm in PHP, but I have no idea how, because PHP algorithms on the internet return different results. Maybe you can help me.

This is the Java-code to encrypt:

private SecretKeySpec secretKey;
private IvParameterSpec ivSpec;

public void setKey(String myKey) {
    MessageDigest sha = null;
    try {
        byte[] key = myKey.getBytes("UTF-8");
        sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16);
        secretKey = new SecretKeySpec(key, "AES");

        byte[] iv = new String("1010101010101010").getBytes("UTF-8");
        ivSpec = new IvParameterSpec(iv);

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

public String encrypt(String strToEncrypt) {
    try {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
        return Base64.encode(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public String decrypt(String strToDecrypt) {
    try {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        return new String(cipher.doFinal(Base64.decode(strToDecrypt)));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public static void main(String[] args) {

    AESText aes = new AESText();
    final String secretKey = "com.secure.test.projectjasdS/FjkGkGhkGjhG786Vjfg=tjGFGH";
    aes.setKey(secretKey);

    String originalString = "test set se ts et set s et se";
    String encryptedString = aes.encrypt(originalString);
    String decryptedString = aes.decrypt(encryptedString);

    System.out.println("origin: " + originalString);
    System.out.println("encrypted: " + encryptedString);
    System.out.println("decrypted: " + decryptedString);
}

This is my php code:

    protected $key;
    protected $method = 'AES-128-CBC';
    protected $iv = '1010101010101010';
    protected $option = OPENSSL_CIPHER_AES_128_CBC;

    function __construct($key)
    {
        $this->key = $key;
    }

    public function encrypt($data) {
        if (is_null($data)) {
            return "Error " . INVALID_PARAMS_ENCRYPTIONS . ": Data is null ";
        }
        $enc = openssl_encrypt($data, $this->method, $this->key, $this->option, $this->iv);
        return base64_encode($enc);
    }

    public function decrypt($data) {
        if (is_null($data)) {
            return "Error " . INVALID_PARAMS_ENCRYPTIONS . ": Data is null ";
        }
        $data = base64_decode($data);
        $dec = openssl_decrypt($data, $this->method, $this->key, $this->option, $this->iv);
        return $dec;
    }

When I encrypted data from java encryption, This result cannot decrypt on Php decryption.

Can you guys possibly help me with building a PHP script, that returns the same results with java encryption?

1

1 Answers

-1
votes

At first glance I see three issues here:

First: you are not using the same mode: in java you have AES/ECB/PKCS5Padding whereas your php uses AES-128-CBC.

Second: you probably aren't using the same IV's in the Java and PHP code (IV's are irrelevant for ECB, but once you switch your java to CBC you will need it):

You have $iv = '1010101010101010' (which is then passed to openssl) in your php but nothing like that in your java.

At the very least, you will probably need something like that in your Java part as well:

cipher.init(Cipher.DECRYPT_MODE/ENCRYPT_MODE, secretKey, new IvParameterSpec(iv))

with iv being a byte[] containing your IV bytes.

Third: once the problems above are addressed, padding may be the next breaking thing: your java cipher specification mentions PKCS5Padding. You need to make sure that both of your counterparts use the same.

edit: Fourth: One more issue is the way you derive the key bits to be used. In java you take the first 16 bytes of a sha1-hash, and in php you just pass $key to openssl. openssl might be deriving the encryption key in a different way.


When building cryptography-related tools using block ciphers, it's always nice to revisit classics like Block cipher mode of operation and Padding on Wikipedia, to get a sense of what is going on under the hood.