简体   繁体   English

C#/.NET 和 PHP 之间的 TripleDES 加密

[英]TripleDES Encryption between C#/.NET and PHP

I have to implement some TripleDES encryption in my PHP application to communicate with a C#/.NET application, but I get different results compared to the server-side C#/.NET application.我必须在我的 PHP 应用程序中实现一些 TripleDES 加密才能与 C#/.NET 应用程序通信,但与服务器端 C#/.NET 应用程序相比,我得到了不同的结果。 I already tried to use different encodings and flags, without much success.我已经尝试使用不同的编码和标志,但没有取得多大成功。

I am already able to decrypt the string from C#/.NET and get the desired result in PHP (based on examples on StackOverflow and other sites).我已经能够从 C#/.NET 解密字符串并在 PHP 中获得所需的结果(基于 StackOverflow 和其他站点上的示例)。

The server-side C#/.NET code can be found and executed here:服务器端 C#/.NET 代码可以在这里找到并执行:

https://dotnetfiddle.net/OrwaOl 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();
                }
            }
        }
    }

}

The "cient"-side PHP code can be found and executed here: “古老”端的 PHP 代码可以在这里找到并执行:

http://phpfiddle.org/lite/code/hkgu-n1fe 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 />";

?>

I spent hours to figure out the problem, but haven't been able yet.我花了几个小时来找出问题所在,但还没有解决。

I would really appreciate if anybody can spot the problem or point me into the right direction.如果有人能发现问题或为我指明正确的方向,我将不胜感激。

The PHP code uses the hash_pbkdf2 with the sha1 algo. PHP 代码使用hash_pbkdf2sha1算法。

TripleDES is symmetric encryption, which is very different from sha1 which is a hashing function. TripleDES 是对称加密,它与散列函数 sha1 有很大不同。

you can refer to Using Triple DES(3DES) with PHP 7.1 for TripleDES in PHP您可以参考在PHP 7.1 中使用 Triple DES(3DES) for TripleDES in PHP

I solved the problem by using iconv() instead of mb_convert_encoding() and now I get the expected result in PHP as well as in .NET/C#.我通过使用 iconv() 而不是 mb_convert_encoding() 解决了这个问题,现在我在 PHP 和 .NET/C# 中都得到了预期的结果。 The following code shows my result for reference.以下代码显示了我的结果以供参考。

<?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 />";

?>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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