user2638180
user2638180

Reputation: 1023

Android equivalent to AES-256-CBC-HMAC-SHA256 in PHP

I've the following encryption done in PHP:

openssl_encrypt( $data, "AES-256-CBC-HMAC-SHA256", $key, OPENSSL_RAW_DATA, $iv ) );

I get to receive that $data in a JSON in my Android app.

I've to decrypt that $data in the app.

I'm using an structure like the following:

private static final String engine = "AES";
private static final String crypto = "AES/CBC/PKCS5Padding";
[...]

public byte[] cipher(byte[] data, int mode, String key, String iv2) throws NoSuchAlgorithmException,NoSuchPaddingException,InvalidKeyException,IllegalBlockSizeException,BadPaddingException,InvalidAlgorithmParameterException {        
    SecretKeySpec sks = new SecretKeySpec(key.getBytes(), engine);
    IvParameterSpec iv = new IvParameterSpec(iv2.getBytes());
    Cipher c = Cipher.getInstance(crypto);
    c.init(mode, sks, iv);
    return c.doFinal(data);
}

public byte[] decrypt(byte[] data,  String key, String iv) throws InvalidKeyException,
        NoSuchAlgorithmException, NoSuchPaddingException,
        IllegalBlockSizeException, BadPaddingException,
        InvalidAlgorithmParameterException {
    return cipher(data, Cipher.DECRYPT_MODE,key,iv);
}

So I call decrypt with the required key and the required iv.

But defining engine as "AES" and crypto as "AES/CBC/PKCS5Padding" throws an error, because it's not equivalent to the one from the server.

On the other hand, using an encrypt function with that cipher function and later decrypting it does work, as either the encryption and the decryption are done with the same key, iv, engine and crypto.

Which would be the engine and crypto equivalent for that AES-256-CBC-HMAC-SHA256 in PHP?

Upvotes: 0

Views: 2606

Answers (1)

Michael Fehr
Michael Fehr

Reputation: 6414

I'm answering your question but I'm confused... you will see :-).

First I setup a simple PHP program with 2 en-/decryption functions, they are using the following algorithms:

$algorithm = "aes-256-cbc-hmac-sha256";
$algorithm2 = "aes-256-cbc";

code:

<?php
// https://stackoverflow.com/questions/63135041/android-equivalent-to-aes-256-cbc-hmac-sha256-in-php
$key = "!mysecretkey#9^5usdk39d&dlf)03sL";
$iv = "Cfq84/46Qjet3EEQ1HUwSg==";
$plaintext = "The quick brown fox jumps over the lazy dog";

$algorithm = "aes-256-cbc-hmac-sha256";
echo 'encryption with algorithm: ' . $algorithm . PHP_EOL;
// encryption
$ciphertext = openssl_encrypt($plaintext, $algorithm, $key, $options = OPENSSL_RAW_DATA, base64_decode($iv));
echo 'ciphertext : ' . base64_encode($ciphertext) . PHP_EOL;
// decryption
$decryptedtext = openssl_decrypt($ciphertext, $algorithm, $key, $options = OPENSSL_RAW_DATA, base64_decode($iv));
echo 'cbc-256-hmac decrypt : ' . $decryptedtext . PHP_EOL . PHP_EOL;

$algorithm2 = "aes-256-cbc";
echo 'encryption with algorithm: ' . $algorithm2 . PHP_EOL;
$ciphertext2 = openssl_encrypt($plaintext, $algorithm2, $key, $options = OPENSSL_RAW_DATA, base64_decode($iv));
echo 'ciphertext2: ' . base64_encode($ciphertext2) . PHP_EOL;
// decryption
$decryptedtext2 = openssl_decrypt($ciphertext2, $algorithm2, $key, $options = OPENSSL_RAW_DATA, base64_decode($iv));
echo 'cbc-256 decrypt      : ' . $decryptedtext2 . PHP_EOL;
?>

Both do fine but - that's what is confusing me - give the same output (here encoded in Base64):

encryption with algorithm: aes-256-cbc-hmac-sha256
ciphertext : sdFQ/X0YdAlyTe8ICtQSb3aHRGzsAdyXRlUGdocGZS9sckqa2seeYaVD10vYu5wV
cbc-256-hmac decrypt : The quick brown fox jumps over the lazy dog

encryption with algorithm: aes-256-cbc
ciphertext2: sdFQ/X0YdAlyTe8ICtQSb3aHRGzsAdyXRlUGdocGZS9sckqa2seeYaVD10vYu5wV
cbc-256 decrypt      : The quick brown fox jumps over the lazy dog

Using the ciphertext string as input in a simple Java decryption method using the algorithm

AES/CBC/PKCS5Padding

the encrypted message get decrypted successfully. So maybe one of our "crypto-gurus" is been able to "put on the spot" why two different algorithms gave the same output.

Here is the Java-result:

decryptedtext: The quick brown fox jumps over the lazy dog

and the Java code:

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class Main {
    public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        System.out.println("https://stackoverflow.com/questions/63135041/android-equivalent-to-aes-256-cbc-hmac-sha256-in-php");

        String key = "!mysecretkey#9^5usdk39d&dlf)03sL";
        String iv = "Cfq84/46Qjet3EEQ1HUwSg==";
        String ciphertext = "sdFQ/X0YdAlyTe8ICtQSb3aHRGzsAdyXRlUGdocGZS9sckqa2seeYaVD10vYu5wV";

        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(Base64.getDecoder().decode(iv));
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] decryptedtextByte = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
        String decryptedtext = new String(decryptedtextByte);
        System.out.println("decryptedtext: " + decryptedtext);
    }
}

Upvotes: 2

Related Questions