C#/.NET 和 PHP 之间的 TripleDES 加密
TripleDES Encryption between C#/.NET and PHP
我必须在我的 PHP 应用程序中实施一些 TripleDES 加密才能与 C#/.NET 应用程序通信,但与服务器端 C#/.NET 应用程序相比,我得到的结果不同。我已经尝试使用不同的编码和标志,但没有成功。
我已经能够从 C#/.NET 中解密字符串并在 PHP 中获得所需的结果(基于 Whosebug 和其他站点上的示例)。
可在此处找到并执行服务器端 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();
}
}
}
}
}
"cient"端的PHP代码可以在这里找到并执行:
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 />";
?>
我花了几个小时来找出问题,但还没能解决。
如果有人能发现问题或指出正确的方向,我将不胜感激。
PHP 代码使用 hash_pbkdf2
和 sha1
算法。
TripleDES是对称加密,和sha1是哈希函数有很大区别
TripleDES可以参考Using Triple DES(3DES) with PHP 7.1PHP
我使用 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 />";
?>
我必须在我的 PHP 应用程序中实施一些 TripleDES 加密才能与 C#/.NET 应用程序通信,但与服务器端 C#/.NET 应用程序相比,我得到的结果不同。我已经尝试使用不同的编码和标志,但没有成功。
我已经能够从 C#/.NET 中解密字符串并在 PHP 中获得所需的结果(基于 Whosebug 和其他站点上的示例)。
可在此处找到并执行服务器端 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();
}
}
}
}
}
"cient"端的PHP代码可以在这里找到并执行:
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 />";
?>
我花了几个小时来找出问题,但还没能解决。
如果有人能发现问题或指出正确的方向,我将不胜感激。
PHP 代码使用 hash_pbkdf2
和 sha1
算法。
TripleDES是对称加密,和sha1是哈希函数有很大区别
TripleDES可以参考Using Triple DES(3DES) with PHP 7.1PHP
我使用 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 />";
?>