简体   繁体   中英

256-bit AES decryption in PHP

I have a working example in Java how to decrypt (256-bit AES) a string using a key. I need to replicate the decrypt algorithm in PHP and almost got it to work.

This is the decrypted message in Java:

CSM(MCL/KEX RCV/10001031 ORG/Comdata KYN/dsNAX6hFtKvfceT KEY/C062E276949D83554D7B5198C52C4C55ED1C65370FA71F8220538A0C3BA23172)

Yet when I call the PHP method it gives

10001031 ORG/Comdata KYN/dsNAX6hFtKvfceT KEY/C062E276949D83554D7B5198C52C4C55ED1C65370FA71F8220538A0C3BA23172)

As you can see it's not far off but the PHP method doesn't give back the first 17 characters (ie the "CSM(MCL/KEX RCV/" bit).

Am I missing something trivial here?

This is the PHP class:

class OpensslAES
{
    const METHOD = 'aes-256-cbc';

    public static function encrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = openssl_random_pseudo_bytes($ivsize);

        $ciphertext = openssl_encrypt(
            $message,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        return $iv.$ciphertext;
    }

    public static function decrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = mb_substr($message, 0, $ivsize, '8bit');
        $ciphertext = mb_substr($message, $ivsize, null, '8bit');

        return openssl_decrypt(
            $ciphertext,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );
    }
}

$class = new OpensslAES();

var_dump($class->decrypt(base64_decode("cBVlMjBttr7DKW8fhHtqJOLyMBNrgxpIJsgFFPjkA/4MWxMIudOnYzS4WuxIhUjtgGgk4CzrkJ1G60R4OWBljNTMA9ATPKh9PXe7wXAwJfE9zc698bQv4lDkXRME+q4xCb3bK/UGQ/BPVIkmRYdHcBvIHXNzGd36Nn40giigY/g="), hex2bin("SECRET_KEY_GOES_HERE")));

This is the Java class:

package javaapplication1;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
import org.apache.commons.codec.binary.Hex;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import javax.xml.bind.DatatypeConverter;

public class JavaApplication1 {

    public static void main(String[] args) {
        byte[] ENCRYPTION_KEY = JavaApplication1.toByteArray("SECRET_KEY_GOES_HERE");
        String INPUT = new String("cBVlMjBttr7DKW8fhHtqJOLyMBNrgxpIJsgFFPjkA/4MWxMIudOnYzS4WuxIhUjtgGgk4CzrkJ1G60R4OWBljNTMA9ATPKh9PXe7wXAwJfE9zc698bQv4lDkXRME+q4xCb3bK/UGQ/BPVIkmRYdHcBvIHXNzGd36Nn40giigY/g=");

        try {
            System.out.println(JavaApplication1.decryptStringAES(INPUT, ENCRYPTION_KEY));
        } catch (Exception exception) {
            System.out.println("Error occured: " + exception);
        }
    }

    public static byte[] toByteArray(String s) {
        return DatatypeConverter.parseHexBinary(s);
    }

    public static String decryptStringAES(String input, byte[] key) throws Exception {
        byte[] IV = JavaApplication1.toByteArray("00000000000000000000000000000000");

        byte[] inputBytes = Base64.decodeBase64(input.getBytes());
        Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        decryptCipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new
        IvParameterSpec(IV));
        byte[] decrypt = decryptCipher.doFinal(inputBytes);
        return new String(decrypt);
    }
}

Your Java implementation expects the IV to always be zeros, whereas your PHP implementation expects the IV to be prepended to the message.

If you want your PHP implementation to be compatible with your Java code, then you could change it like this:

class OpensslAES
{
    const METHOD = 'aes-256-cbc';

    public static function encrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = hex2bin('00000000000000000000000000000000');

        return openssl_encrypt(
            $message,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );
    }

    public static function decrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = hex2bin('00000000000000000000000000000000');

        return openssl_decrypt(
            $message,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );
    }
}

$class = new OpensslAES();

var_dump($class->decrypt(base64_decode("cBVlMjBttr7DKW8fhHtqJOLyMBNrgxpIJsgFFPjkA/4MWxMIudOnYzS4WuxIhUjtgGgk4CzrkJ1G60R4OWBljNTMA9ATPKh9PXe7wXAwJfE9zc698bQv4lDkXRME+q4xCb3bK/UGQ/BPVIkmRYdHcBvIHXNzGd36Nn40giigY/g="), hex2bin("SECRET_KEY_GOES_HERE")));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM