使用 openssl_encrypt/openssl_decrypt 将 C# TripleDES ECB decrypt/encrypt 转换为 PHP
Convert C# TripleDES ECB decrypt/encrypt into PHP with openssl_encrypt/openssl_decrypt
我正在尝试使用 openssl_encrypt 和 openssl_decrypt 在 PHP 中使用 PKCS7 填充重新创建 TripleDES ECB 的以下 C# 实现。
private static string Key = "<some random key with umlauts and special characters length of 24>";
public static string Decrypt(string cypherText)
{
using(var des = CreateDes(Key))
{
var ct = des.CreateDecryptor();
var input = Convert.FromBase64String(cypherText);
var output = ct.TransformFinalBlock(input, 0, input.Length);
return Encoding.UTF8.GetString(output);
}
}
public static string Encrypt(string plainText)
{
using(var des = CreateDes(Key))
{
var ct = des.CreateEncryptor();
var input = Encoding.UTF8.GetBytes(plainText);
var output = ct.TransformFinalBlock(input, 0, input.Length);
return Convert.ToBase64String(output);
}
}
private static TripleDES CreateDes(string key)
{
MD5 md5 = new MD5CryptoServiceProvider();
TripleDES des = new TripleDESCryptoServiceProvider();
var desKey = md5.ComputeHash(Encoding.UTF8.GetBytes(key));
des.Key = desKey;
des.IV = new byte[des.BlockSize / 8];
des.Padding = PaddingMode.PKCS7;
des.Mode = CipherMode.ECB;
return des;
}
到目前为止,我已经设法弄清楚我必须使用 PHP 中 md5 函数的 raw_output 参数来获得完全相同的密钥(与 C# 和中的断点相比PHP) 中的 getByteFromString 函数和 encryption/decryption 基本上在双方都有效。除了在 C# 中加密的值无法在 PHP 中解密,反之亦然,因为加密结果不同。
到目前为止,我在 PHP 中获得的内容:
function getByteFromString( $value )
{
$ret = '';
for($i = 0; $i < strlen($value); $i++)
{
$ret .= '[' . $i . '] => ' . ord($value[$i])."<br/>";
}
return $ret;
}
function encrypt( $key, $value )
{
if( function_exists( 'openssl_encrypt' ) )
{
return base64_encode( openssl_encrypt( $value, 'DES-EDE3', $key, OPENSSL_RAW_DATA ) );
}
return 'openssl missing';
}
function decrypt( $key, $value )
{
if( function_exists( 'openssl_decrypt' ) )
{
return openssl_decrypt( base64_decode( $value ), 'DES-EDE3', $key, OPENSSL_RAW_DATA );
}
return 'openssl missing';
}
$sKey = md5("<the same random key with umlauts and special characters length of 24 as in c#>", true);
$number = '1234567890';
$encrypted = encrypt( $sKey, $number );
$decrypted = decrypt( $sKey, $encrypted );
// For key debugging only:
echo 'key:<br>' . getByteFromString($sKey) . '<br>';
echo 'encrypted: ' . var_export($encrypted, true) . '<br>';
echo 'decrypted: ' . var_export($decrypted, true). '<br>';
我知道不应再使用 TripleDES,尤其是 ECB 模式,但我无法更改 C# 代码,因此 PHP 代码必须创建与 C# 相同的结果并且必须能够解密在 C# 中加密的值以及加密值,以便 C# 可以解密它们 - 使用 TripleDES 和 ECB。我只是想不通我在 PHP 方面遗漏了什么。
好的,我通过阅读相关问题找到了解决方案。我在一个有 7 年历史的问题中找到了它,尽管它被要求提供已弃用的 mcrypt 函数,但不知何故,即使使用 openssl 函数,它仍然可以工作。
所要做的就是像这样将原始密钥的前 8 个字节附加到自身:
$sKey = md5("<the same random key with umlauts and special characters length of 24 as in c#>", true);
$sKey .= substr( $sKey, 0, 8 );
在PHP中给出了以下工作示例:
function encrypt( $key, $value )
{
if( function_exists( 'openssl_encrypt' ) )
{
return base64_encode( openssl_encrypt( $value, 'DES-EDE3', $key, OPENSSL_RAW_DATA ) );
}
return 'openssl missing';
}
function decrypt( $key, $value )
{
if( function_exists( 'openssl_decrypt' ) )
{
return openssl_decrypt( base64_decode( $value ), 'DES-EDE3', $key, OPENSSL_RAW_DATA );
}
return 'openssl missing';
}
$sKey = md5("<the same random key with umlauts and special characters length of 24 as in c#>", true);
$sKey .= substr( $sKey, 0, 8 ); //Added this line to fix it
$number = '1234567890';
$encrypted = encrypt( $sKey, $number );
$decrypted = decrypt( $sKey, $encrypted );
echo 'encrypted: ' . var_export($encrypted, true) . '<br>';
echo 'decrypted: ' . var_export($decrypted, true). '<br>';
如果有人可以评论为什么这是解决方案,请发表评论。虽然我对它的工作感到满意,但我真的很想了解 为什么 它能工作。我在 C# 中看不到这样的事情发生,所以为什么我必须在 PHP 中这样做?
我正在尝试使用 openssl_encrypt 和 openssl_decrypt 在 PHP 中使用 PKCS7 填充重新创建 TripleDES ECB 的以下 C# 实现。
private static string Key = "<some random key with umlauts and special characters length of 24>";
public static string Decrypt(string cypherText)
{
using(var des = CreateDes(Key))
{
var ct = des.CreateDecryptor();
var input = Convert.FromBase64String(cypherText);
var output = ct.TransformFinalBlock(input, 0, input.Length);
return Encoding.UTF8.GetString(output);
}
}
public static string Encrypt(string plainText)
{
using(var des = CreateDes(Key))
{
var ct = des.CreateEncryptor();
var input = Encoding.UTF8.GetBytes(plainText);
var output = ct.TransformFinalBlock(input, 0, input.Length);
return Convert.ToBase64String(output);
}
}
private static TripleDES CreateDes(string key)
{
MD5 md5 = new MD5CryptoServiceProvider();
TripleDES des = new TripleDESCryptoServiceProvider();
var desKey = md5.ComputeHash(Encoding.UTF8.GetBytes(key));
des.Key = desKey;
des.IV = new byte[des.BlockSize / 8];
des.Padding = PaddingMode.PKCS7;
des.Mode = CipherMode.ECB;
return des;
}
到目前为止,我已经设法弄清楚我必须使用 PHP 中 md5 函数的 raw_output 参数来获得完全相同的密钥(与 C# 和中的断点相比PHP) 中的 getByteFromString 函数和 encryption/decryption 基本上在双方都有效。除了在 C# 中加密的值无法在 PHP 中解密,反之亦然,因为加密结果不同。
到目前为止,我在 PHP 中获得的内容:
function getByteFromString( $value )
{
$ret = '';
for($i = 0; $i < strlen($value); $i++)
{
$ret .= '[' . $i . '] => ' . ord($value[$i])."<br/>";
}
return $ret;
}
function encrypt( $key, $value )
{
if( function_exists( 'openssl_encrypt' ) )
{
return base64_encode( openssl_encrypt( $value, 'DES-EDE3', $key, OPENSSL_RAW_DATA ) );
}
return 'openssl missing';
}
function decrypt( $key, $value )
{
if( function_exists( 'openssl_decrypt' ) )
{
return openssl_decrypt( base64_decode( $value ), 'DES-EDE3', $key, OPENSSL_RAW_DATA );
}
return 'openssl missing';
}
$sKey = md5("<the same random key with umlauts and special characters length of 24 as in c#>", true);
$number = '1234567890';
$encrypted = encrypt( $sKey, $number );
$decrypted = decrypt( $sKey, $encrypted );
// For key debugging only:
echo 'key:<br>' . getByteFromString($sKey) . '<br>';
echo 'encrypted: ' . var_export($encrypted, true) . '<br>';
echo 'decrypted: ' . var_export($decrypted, true). '<br>';
我知道不应再使用 TripleDES,尤其是 ECB 模式,但我无法更改 C# 代码,因此 PHP 代码必须创建与 C# 相同的结果并且必须能够解密在 C# 中加密的值以及加密值,以便 C# 可以解密它们 - 使用 TripleDES 和 ECB。我只是想不通我在 PHP 方面遗漏了什么。
好的,我通过阅读相关问题找到了解决方案。我在一个有 7 年历史的问题中找到了它,尽管它被要求提供已弃用的 mcrypt 函数,但不知何故,即使使用 openssl 函数,它仍然可以工作。
所要做的就是像这样将原始密钥的前 8 个字节附加到自身:
$sKey = md5("<the same random key with umlauts and special characters length of 24 as in c#>", true);
$sKey .= substr( $sKey, 0, 8 );
在PHP中给出了以下工作示例:
function encrypt( $key, $value )
{
if( function_exists( 'openssl_encrypt' ) )
{
return base64_encode( openssl_encrypt( $value, 'DES-EDE3', $key, OPENSSL_RAW_DATA ) );
}
return 'openssl missing';
}
function decrypt( $key, $value )
{
if( function_exists( 'openssl_decrypt' ) )
{
return openssl_decrypt( base64_decode( $value ), 'DES-EDE3', $key, OPENSSL_RAW_DATA );
}
return 'openssl missing';
}
$sKey = md5("<the same random key with umlauts and special characters length of 24 as in c#>", true);
$sKey .= substr( $sKey, 0, 8 ); //Added this line to fix it
$number = '1234567890';
$encrypted = encrypt( $sKey, $number );
$decrypted = decrypt( $sKey, $encrypted );
echo 'encrypted: ' . var_export($encrypted, true) . '<br>';
echo 'decrypted: ' . var_export($decrypted, true). '<br>';
如果有人可以评论为什么这是解决方案,请发表评论。虽然我对它的工作感到满意,但我真的很想了解 为什么 它能工作。我在 C# 中看不到这样的事情发生,所以为什么我必须在 PHP 中这样做?