Преобразование функции шифрования C # AES в PHP - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь преобразовать функцию шифрования C # в php, но я подозреваю, что есть проблема с кодировкой или генерация IV не верна.

Это для отправки зашифрованного текста в APIи в настоящее время я пытался форсировать utf8, но строки, закодированные в base64, всегда отличаются от того, что я получаю при запуске функции C #.Я также не могу найти точный способ создания IV в C #.

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

*Функция 1007 * C #

public void EncryptStringToBytes(string plaintext) {
            string key = DateTime.UtcNow.ToShortDateString();
            HashAlgorithm algorithm = SHA256.Create();
            byte[] bytekey = algorithm.ComputeHash(Encoding.UTF8.GetBytes(key));

            using (Aes myAes = Aes.Create()) {
                myAes.Key = bytekey;
                // Encrypt the string to an array of bytes.
                byte[] encrypted = null;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = myAes.CreateEncryptor(myAes.Key, myAes.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream()) {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
                             //Write all data to the stream.
                             swEncrypt.Write(plaintext);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
                 Console.WriteLine(Convert.ToBase64String(encrypted)); 
                 Console.WriteLine(Convert.ToBase64String(myAes.IV));
            }
        }

Функция PHP

date_default_timezone_set("UTC");

function encrypt($string) {
  // Generate key based on current time
  $secret_key = utf8_encode(date('Y-m-d'));
  // Hash the key with SHA256
  $key = hash('sha256', $secret_key);
  // Use AES 128 w/ CBC as encryption method
  $encrypt_method = "AES-128-CBC";
  // Get cipher length based on encryption method
  $cypher_length = openssl_cipher_iv_length($encrypt_method);
  // Generate IV -- possible issue
  $iv = openssl_random_pseudo_bytes($cypher_length);
  // Encrypt input string with the given method, key and IV
  $output = openssl_encrypt($string, $encrypt_method, $key, OPENSSL_RAW_DATA , $iv);

  $debug_info = [ 'date' => $secret_key, 'key' => $key, 'method' => $encrypt_method, 'cypher_len' => $cypher_length, 'iv' => $iv, 'output' => $output];
  return [base64_encode($output), base64_encode($iv), $debug_info];
}

1 Ответ

0 голосов
/ 14 февраля 2019

Я нашел решение благодаря bartonjs, мне пришлось использовать AES-256-CBC вместо 128. Также я не использовал необработанный вывод при хешировании, что также изменило результат, и так как я отправляю зашифрованные данные и IVчерез php-soap с использованием SoapClient мне не нужно использовать base64_encode, так как SoapClient уже делает это для меня.

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

    function encrypt($string, $debug = false) {
        $method = 'aes-256-cbc';
        $secret_key = date('Y-m-d', time());
        $key = hash('SHA256', $secret_key, true);
        $cypher_length = openssl_cipher_iv_length($method);
        $iv = random_bytes($cypher_length);
        $output = openssl_encrypt($string, $method, $key, OPENSSL_RAW_DATA, $iv);
        $debug_info = [ 'date' => $secret_key, 'date_utf8' => utf8_encode($secret_key), 'key' => utf8_encode($key), 'method' => $method, 'cypher_len' => $cypher_length, 'iv' => base64_encode($iv), 'output' => base64_encode($output)];

        if($debug){
            return [$output, $iv, $debug_info];
        }
        return [$output, $iv];
    }
...