gpt4 book ai didi

c# - C# 和 PHP 上的三重 DES 加密产生不同的结果

转载 作者:可可西里 更新时间:2023-11-01 00:23:05 27 4
gpt4 key购买 nike

我正在编写一个简单的登录加密系统,但我遇到了一个小问题。C# 加密函数:

public static string EncryptString(string Message, string Passphrase)
{
byte[] Results;
System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();

// Step 1. We hash the passphrase using MD5
// We use the MD5 hash generator as the result is a 128 bit byte array
// which is a valid length for the TripleDES encoder we use below

MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));

// Step 2. Create a new TripleDESCryptoServiceProvider object
TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();

// Step 3. Setup the encoder
TDESAlgorithm.Key = TDESKey;
TDESAlgorithm.Mode = CipherMode.ECB;
TDESAlgorithm.Padding = PaddingMode.PKCS7;

// Step 4. Convert the input string to a byte[]
byte[] DataToEncrypt = UTF8.GetBytes(Message);

// Step 5. Attempt to encrypt the string
try
{
ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
}
finally
{
// Clear the TripleDes and Hashprovider services of any sensitive information
TDESAlgorithm.Clear();
HashProvider.Clear();
}

// Step 6. Return the encrypted string as a base64 encoded string
return Convert.ToBase64String(Results);
}

EncryptString("test", "123456") 返回 "Yjaqhc7RFds="

php 中的相同代码:

  <?php
$key = "123456";
function pkcs7_pad($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}

$input = pkcs7_pad("test", 16);
$key = md5(utf8_encode($key), true);
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

echo base64_encode($encrypted_data);
?>

返回 “dybhiZYdKG8pNCgCFkbV6g==”?我做错了什么?

最佳答案

您遇到此问题是因为 Triple DES 的 key 大小为 168 位(21 字节),但 MD5 生成的哈希值仅为 16 字节(128 位)长。

这意味着 key 必须扩展到 168 位,这样三重 DES 才能工作。事实证明,这种从 128 位到 168 位的推导在 C# 中的工作方式与在 PHP 中的工作方式不同,因此有效使用的 key 不同,从而导致不同的加密数据。

现在你有两个选择:


选项 1:选择完全支持 128 位 key 的密码

如果您使用支持 128 位 key 的密码,则可以避免与 key 大小差异相关的所有问题。这将需要对您的代码进行最少的更改。例如,您可以使用 Rijndael (AES)。

C#:将 TripleDESCryptoServiceProvider 更改为 RijndaelManaged
其他一切都可以保持几乎相同。 (Demo)

PHP:使用 MCRYPT_RIJNDAEL_128 而不是 tripledes (Demo) :

function encrypt_pkcs7($str, $key)
{
$key = md5(utf8_encode($key), true);
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
return base64_encode($ciphertext);
}

echo encrypt_pkcs7('test', '123456');

请注意,AES 的有效 key 大小大于三重 DES。虽然 Triple DES 的 key 长度为 168 位,但它仅提供 112 位的安全性。如果我是你,我会选择这个选项。


选项 2:使用 192 位 key 而不是 128 位 key

如果您使用的 key 比 Triple DES 实际使用的 key 大,C# 和 PHP 似乎就如何将其减少到 168 位达成一致。您可以使用像 SHA-256 这样的散列函数来执行此操作,它会生成 256 位散列并将其修整为 192 位(24 字节):

C#:使用 SHA256CryptoServiceProviderArray.Copy 获取 192 位 key ,并将其用于程序的其余部分: (Demo)

SHA256CryptoServiceProvider HashProvider = new SHA256CryptoServiceProvider();
byte[] temp = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
byte[] key = new byte[24];
Array.Copy(temp, key, 24);

PHP:使用带有 SHA-256 的 hash()substr() 获取 192 位 key

function encrypt_pkcs7($str, $key)
{
// derive 192-bit key using SHA-256
$key = substr(hash('sha256', $key, true), 0, 24);
$block = mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_ECB);
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);

$ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $str, MCRYPT_MODE_ECB);
return base64_encode($ciphertext);
}

echo encrypt_pkcs7('test', '123456');

看起来我无法为 TripleDESCryptoServiceProvider 提供 168 位 key ,我不知道为什么。


其他注意事项:

  • 考虑使用 SSL;即使它是自签名证书。它胜过重新发明轮子,这是一项在涉及密码学时特别危险的任务。

  • 考虑使用 ECB 以外的操作模式(例如:CBC)。使用 ECB 会增加安全风险。阅读 Wikipedia article on block cipher modes of operation

  • 除非您绝对需要明文密码(这种情况很少见),否则您应该散列您的密码。阅读 this article on securing passwords.

  • 考虑使用适当的基于密码的 key 派生函数,例如 PBKDF2,而不是 MD5 或 SHA 系列等通用哈希函数。这将使破解 key 变得更加困难。有关详细信息,请阅读上一个要点中的文章。

关于c# - C# 和 PHP 上的三重 DES 加密产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13402856/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com