Моя проблема в следующем:

У меня есть PHP-скрипт, который отвечает за шифрование строки с использованием шифрования AES-256-CBC. Этот скрипт использует openssl lib и возвращает результат X.

<?php
class AES
{
    const PRIVATE_KEY =  'abcdefghijklmnnoabcdefghijklmnno';
    const ENCRYPT_METHOD = 'aes-256-cbc';
    const VECTOR = 'abcdefghijklmnno';

    public function encryptData($data)
    {
        while(strlen($data) < 16) $data .= "\0";
        return openssl_encrypt($data, self::ENCRYPT_METHOD, self::PRIVATE_KEY, OPENSSL_ZERO_PADDING, self::VECTOR);
    }

  public function encryptDataL($data)
    {
        return openssl_encrypt($data, self::ENCRYPT_METHOD, self::PRIVATE_KEY, 0, self::VECTOR);
    }
    
    public function decryptData($data)
    {
        return openssl_decrypt($data, self::ENCRYPT_METHOD, self::PRIVATE_KEY, OPENSSL_ZERO_PADDING, self::VECTOR);
    }

}

$aes = new AES();
echo $aes->encryptData("abcdefghijkl");
echo "\n";
echo $aes->encryptDataL("{\"REQUEST\": [{\"MSISDN\": \"32156489721\",\"IDPRODUCT\": 123,\"IDOPERATOR\": 12345,\"OUTPUTFORMAT\": \"JSON\"}],\"OUTPUTFORMAT\": \"json\"}");
?>

Когда я запускаю JS-скрипт, отвечающий за то же самое, но с использованием Crypto lib, полученный результат отличается от предыдущего X.

const crypto = require('crypto');
const cipher = crypto.createCipheriv('aes-256-cbc', 'abcdefghijklmnnoabcdefghijklmnno', 'abcdefghijklmnno');
let crypted = cipher.update(data, 'utf8', 'base64');
crypted += cipher.final('base64');

Результаты скриптов различаются, хотя теоретически шифрование должно быть одинаковым.

Пример возврата выглядит следующим образом:

  • Для скрипта php: ввод -> ^ y3Hk3JKGGgA вывод -> eTqD5Op389QS / TOoui5kAQ ==

  • Для сценария js: ввод -> ^ y3Hk3JKGGgA вывод -> HHfskOE1N + QxdGt9MTai5A ==

Желаемый результат - сценарий PHP, но мне нужно запустить код на JS, может ли кто-нибудь объяснить мне, что я делаю неправильно?

Я пробовал разные способы выполнить метод createCipheriv, но все они возвращают один и тот же результат (отличный от того, что мне нужно, то есть результат, полученный с помощью сценария PHP)

Заранее спасибо.

-1
Marcelo Porto 3 Окт 2020 в 01:27

1 ответ

Лучший ответ

Спасибо, ребята, за попытку помочь, действительно, я разместил вопрос без некоторой информации (на самом деле, когда вопрос был задан, у меня не было всей необходимой информации).

Но размещаю здесь некоторые факты и решение, встреченное для моего случая.

Разные результаты в приведенных выше случаях случаются только для первой функции PHP ("encryptData"), ответственной за шифрование небольших текстов. Второй, отвечающий за шифрование больших текстов (более 16 бит), отлично работал как в PHP, так и в JS скриптах.

Решение, с которым я столкнулся, заключалось в том, чтобы самостоятельно сделать отступы, необходимые для алгоритма AES-256. Функция заполнения, предоставляемая Crypto lib, не работала, по крайней мере, в моем случае.

Поэтому я отключил заполнение в моем классе cypher и убедился, что данные, отправленные для шифрования, были заполнены правильно до тех пор, пока длина не станет кратной 16. Конечный код приведен ниже.

encryptWithAES256(data) {
// added padding until data length is multiple of 16
let paddedData = data;
while (paddedData.length % 16 !== 0) {
  paddedData += '\0';
}

// ciphers data
const cipher = crypto.createCipheriv('aes-256-cbc', encodeKey, IV);
cipher.setAutoPadding(false);
let crypted = cipher.update(paddedData, 'utf8', 'base64');
crypted += cipher.final('base64');
return crypted;

}

0
Marcelo Porto 5 Окт 2020 в 17:29