Репликация шифрования Java AES / CBC / PKCS5Padding в PHP

Включили код java и php и результаты ниже. Цель состоит в том, чтобы получить значение контрольной суммы Java в php. Как можно видеть, у меня те же входные данные в php, что и в java, и хотя я пробовал много вариантов аргументов в функции php openssl_encrypt, но не смог получить желаемый результат. Мы будем очень признательны за помощь в решении этой проблемы! Обратите внимание, что код java является авторитетным, любые необходимые изменения будут только в php.

Код Java:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import java.io.ByteArrayOutputStream; 

public class ChecksumGen {

    public static void main(final String[] args) {
        String data = "INPUTDATA";
        String secretKey = "0000000000000000000000000000000000000000000000000000000000000000";
        byte[] iv = new byte[16];
        try {
            byte[] hashedData = getDigest(data);
            byte[] key = hexStringToByteArray(secretKey);
            byte[] checksum = encrypt(key, hashedData, iv);
            showB64("key ", key);
            showB64("iv ", iv);
            showB64("hashedData ", hashedData);
            showB64("checksum ", checksum);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public static byte[] getDigest(String checkSumInput) {
        try {
            MessageDigest localMessageDigest = MessageDigest.getInstance("SHA-256");
            byte[] checkSumInputBytes = checkSumInput.getBytes("UTF-8");
            localMessageDigest.update(checkSumInputBytes);
            byte[] digest = localMessageDigest.digest();
            return digest;
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
            throw new RuntimeException(ex);
        }
    }

    public static byte[] hexStringToByteArray(String s) {
        byte[] b = new byte[s.length() / 2];
        for (int i = 0; i < b.length; i++) {
            int index = i * 2;
            int v = Integer.parseInt(s.substring(index, index + 2), 16);
            b[i] = (byte) v;
        }
        return b;
    }

    public static byte[] encrypt(byte[] key,byte[] data, byte[] iv)throws Exception{
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        Cipher acipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        acipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,ivSpec);
        byte[] arrayOfByte1 = acipher.doFinal(data);
        return arrayOfByte1;
    }

    public static void showB64(String label, byte[] rawData) {
      System.out.println(label + ":" + Base64.getEncoder().encodeToString(rawData));
    }
}

Код PHP:

<?php
$data  = "INPUTDATA"; 
$hashedData = hash("sha256", $data, true);
$secretKey = "0000000000000000000000000000000000000000000000000000000000000000";
$ivStr = "00000000000000000000000000000000";
$key = pack('H*', $secretKey);
$iv = pack('H*', $ivStr);
$inputData = pkcs5_pad($hashedData, 16);
showB64('key', $key);
showB64('iv', $iv);
showB64('hashedData', $hashedData);
showB64('inputData', $inputData);
$checksum = encrypt($key, $inputData, $iv);
showB64('checksum', $checksum);

function encrypt($key,$data,$iv){
  $cipher = 'AES-128-CBC';
  $options = OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING;
  $raw = openssl_encrypt(
  $data,
  $cipher,
  $key,
  $options,
  $iv
  );
  return $raw;
}

function pkcs5_pad($text, $blocksize){ 
  $pad = $blocksize - (strlen($text) % $blocksize); 
  return $text . str_repeat(chr($pad), $pad); 
}     

function showB64($label, $rawData) {
  echo "{$label} :".base64_encode($rawData)."\n";
}

Вывод Java:

key :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
iv :AAAAAAAAAAAAAAAAAAAAAA==
hashedData :ZAgNCUfIbdT9EjdkCb3XDNpMFGV34rXNjcTOQ9cdZ3w=
checksum :9NS/ZKMscpa4V7i2YQQPoycxCwbL1BlK3h9O/1ujoD1iYgjE8tZx+JRGflw5WikH

Вывод PHP:

key :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
iv :AAAAAAAAAAAAAAAAAAAAAA==
hashedData :ZAgNCUfIbdT9EjdkCb3XDNpMFGV34rXNjcTOQ9cdZ3w=
inputData :ZAgNCUfIbdT9EjdkCb3XDNpMFGV34rXNjcTOQ9cdZ3wQEBAQEBAQEBAQEBAQEBAQ
checksum :LtdJzSl9UgEpZrpdg7X5g5CYqE3eXQvijazrvkw0XFNY2bxn8zGp1ea8DrUmw/uu

Оказывается, это дает тот же результат, что и java: mcrypt_encrypt (MCRYPT_RIJNDAEL_128, $ key, $ data, MCRYPT_MODE_CBC, $ iv); Учитывая, что эта функция устарела, как реализовать это в openssl_encrypt?

s1d 13.10.2018 18:19
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
4 516
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Наконец выяснилось решение по следующей ссылке:

https://gist.github.com/odan/c1dc2798ef9cedb9fedd09cdfe6e8e76#gistcomment-2743227

MCRYPT_RIJNDAEL_128 - это не то же самое, что AES-128-CBC.

В MYCRYT_RIJNDAEL_128 128 на самом деле относится к размеру блока, а не к размеру ключа, в AES-128-CBC 128 относится к размеру ключа, то есть они оба являются AES-256 при использовании с действительным 256-битным ключом.

В PHP-коде изменение $ cipher в функции encrypt () на «AES-256-CBC» с «AES-128-CBC» помогает нам получить требуемый вывод с помощью openssl_encrypt.

не могли бы вы поделиться своим окончательным кодом с функцией дешифрования? :)

LittleTiger 26.05.2020 12:33

Привет, @LittleTiger, пришлось поискать мои заметки по этому поводу, так как прошло уже больше года. Не думаю, что я реализовал метод дешифрования, поскольку он не входил в мои рамки (это было для платежного шлюза, поэтому они выполняли дешифрование на своей стороне). Я создал общедоступную суть и добавил некоторые заметки из своих исследований, связанных с заполнением PKCS5 / PKCS7. Расскажи взгляд - gist.github.com/siddharth/b114b4415b6791a23ac8196c5a5ef8be

s1d 27.05.2020 12:25

Я также добавил написанный мной эквивалентный Java-код, чтобы вы могли напрямую сравнить результат.

s1d 27.05.2020 12:33

Другие вопросы по теме