Шифрование TripleDES между C#/.NET и PHP

Мне нужно реализовать шифрование TripleDES в моем PHP-приложении для связи с приложением C#/.NET, но я получаю другие результаты по сравнению с серверным приложением C#/.NET. Я уже пытался использовать разные кодировки и флаги, но без особого успеха.

Я уже могу расшифровать строку из C#/.NET и получить желаемый результат в PHP (на основе примеров на StackOverflow и других сайтах).

Серверный код C#/.NET можно найти и выполнить здесь:

https://dotnetfiddle.net/OrwaOl

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(Encrypt("SourceString123", "fsgerh", "Dataehaeh"));
        Console.WriteLine(Decrypt("Vql0pOr7ouxfUScI3H8exeFbfmcfE5uM3TBtAZXAq0zwkJmqEe13EA==", "fsgerh", "Dataehaeh"));
    }

    public static string Encrypt(string value, string password, string salt)
    {
        DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
        SymmetricAlgorithm algorithm = new TripleDESCryptoServiceProvider();
        byte[] rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
        byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);
        ICryptoTransform transform = algorithm.CreateEncryptor(rgbKey, rgbIV);
        using (MemoryStream buffer = new MemoryStream())
        {
            using (CryptoStream stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write))
            {
                using (StreamWriter writer = new StreamWriter(stream, Encoding.Unicode))
                {
                    writer.Write(value);
                }
            }
            return Convert.ToBase64String(buffer.ToArray());
        }
    }

    public static string Decrypt(string text, string password, string salt)
    {
        DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
        SymmetricAlgorithm algorithm = new TripleDESCryptoServiceProvider();
        byte[] rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
        byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);
        ICryptoTransform transform = algorithm.CreateDecryptor(rgbKey, rgbIV);
        using (MemoryStream buffer = new MemoryStream(Convert.FromBase64String(text)))
        {
            using (CryptoStream stream = new CryptoStream(buffer, transform, CryptoStreamMode.Read))
            {
                using (StreamReader reader = new StreamReader(stream, Encoding.Unicode))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }

}

PHP-код "cient" можно найти и выполнить здесь:

http://phpfiddle.org/lite/code/hkgu-n1fe

<?php

$decrypted = 'SourceString123';
$encrypted = 'Vql0pOr7ouxfUScI3H8exeFbfmcfE5uM3TBtAZXAq0zwkJmqEe13EA==';

$password = 'fsgerh';
$salt = 'Dataehaeh';

$hash = hash_pbkdf2("sha1", $password, mb_convert_encoding($salt, 'UTF-16LE'), 1000, 32, true); 

$key = substr($hash, 0, 24);
$iv = substr($hash, 24, 8);

echo base64_encode($key) . "<br />";
echo base64_encode($iv) . "<br /><br />";

$result = mb_convert_encoding(openssl_decrypt($encrypted, 'des-ede3-cbc', $key, 0, $iv), 'UTF-8', 'UTF-16');
echo $result;
echo "<br /><br />";

$result = openssl_encrypt(mb_convert_encoding($decrypted, 'UTF-8'), 'des-ede3-cbc', $key, 0, $iv);
echo $result;
echo "<br /><br />";

$result = openssl_encrypt(mb_convert_encoding($decrypted, 'UTF-16'), 'des-ede3-cbc', $key, 0, $iv);
echo $result;
echo "<br /><br />";

?>

Я потратил часы, чтобы выяснить проблему, но пока не смог.

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


person visotom    schedule 13.10.2017    source источник
comment
Пожалуйста, введите код, чтобы мы могли вам помочь   -  person A.Rashad    schedule 13.10.2017


Ответы (2)


Код PHP использует hash_pbkdf2 с алгоритмом sha1.

TripleDES — это симметричное шифрование, которое сильно отличается от sha1, функции хеширования.

вы можете обратиться к Использование Triple DES(3DES) с PHP 7.1 для Тройной DES в PHP

person Gilles Gouaillardet    schedule 13.10.2017
comment
Я должен использовать хэш-функцию для получения необходимого IV и ключа. Тот же метод используется в примере .NET (см. ниже). $hash = hash_pbkdf2("sha1", $password, mb_convert_encoding($salt, 'UTF-16LE'), 1000, 32, true); DeriveBytes rgb = new Rfc2898DeriveBytes (пароль, Encoding.Unicode.GetBytes (соль)); Я попробовал несколько примеров, но не смог получить тот же результат. Я могу шифровать и расшифровывать в PHP, но строка в кодировке base64 отличается. - person visotom; 13.10.2017

Я решил проблему, используя iconv() вместо mb_convert_encoding(), и теперь я получаю ожидаемый результат как в PHP, так и в .NET/C#. Следующий код показывает мой результат для справки.

<?php

$decrypted = 'SourceString123';
$encrypted = 'Vql0pOr7ouxfUScI3H8exeFbfmcfE5uM3TBtAZXAq0zwkJmqEe13EA==';

$password = 'fsgerh';
$salt = 'Dataehaeh';

$hash = hash_pbkdf2("sha1", $password, mb_convert_encoding($salt, 'UTF-16LE'), 1000, 32, true); 

$key = substr($hash, 0, 24);
$iv = substr($hash, 24, 8);

echo base64_encode($key) . "<br />";
echo base64_encode($iv) . "<br /><br />";

$result = iconv('UTF-16', 'UTF-8', openssl_decrypt($encrypted, 'des-ede3-cbc', $key, 0, $iv));
echo $result;
echo "<br /><br />";

$result = openssl_encrypt(iconv('UTF-8', 'UTF-16', $decrypted), 'des-ede3-cbc', $key, 0, $iv);
echo $result;
echo "<br />";

?>
person visotom    schedule 18.10.2017