在C#和PHP中加密的三倍不同样(PKCS7,ECB)?
-
11-10-2019 - |
题
我已经花了几个小时来弄清楚这一点,但是我只是无法正常工作。我有一个在PHP中需要匹配的C#加密例程。我无法更改C#版本,这不是一个选项(第三方对此很牢固)。
这是C#代码:
//In C#
// Console.WriteLine(ApiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl"));
// Results in:
// XvHbR/CsLTo=
public static string ApiEncode(string data, string secret)
{
byte[] clear;
var encoding = new UTF8Encoding();
var md5 = new MD5CryptoServiceProvider();
byte[] key = md5.ComputeHash(encoding.GetBytes(secret));
TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
des.Key = key;
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.PKCS7;
byte[] input = encoding.GetBytes(data);
try { clear = des.CreateEncryptor().TransformFinalBlock(input, 0, input.Length); }
finally
{
des.Clear();
md5.Clear();
}
return Convert.ToBase64String(clear);
}
这是我在PHP中提出的最好的事情:
//In PHP
// echo apiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl");
// Results in:
// 5aqvY6q1T54=
function apiEncode($data, $secret)
{
//Generate a key from a hash
$key = md5(utf8_encode($secret), true);
//Create init vector
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_ecb), MCRYPT_RAND);
//Pad for PKCS7
$blockSize = mcrypt_get_block_size('tripledes', 'ecb');
$len = strlen($data);
$pad = $blockSize - ($len % $blockSize);
$data .= str_repeat(chr($pad), $pad);
//Encrypt data
$encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb'); //, $iv);
return base64_encode($encData);
}
据我所知,我正在正确处理PHP一侧的PKCS7填充。我不确定还有什么尝试。
需要注意的一件事,C#正在Windows上发生,Linux上的PHP不确定是否会有所作为。
解决方案
PHP版本中的填充长度基于密码的长度。这是不正确的。它应该基于消息的长度。
尝试更换 strlen($password)
和 strlen($data)
.
第二个问题是 mcrypt
图书馆需要24字节键。 Triple DES适用3次,因此您可以调用DES K的每轮使用的8字节键1, ,k2, 和k3. 。有不同的方法可以选择这些密钥。最安全的是选择三个不同的键。另一种方法是设置k3 等于k1. 。最不安全的方法(等效于DES)是使K1 = k2 = k3.
大多数库的“智能”足以将16字节3DES键解释为上述第二个选项:k3 = k1. 。 .NET实现正在为您执行此操作,但是 mcrypt
图书馆不是;相反,它是设置k3 = 0。您需要自己解决此问题,然后通过 mcrypt
一个24字节键。
计算MD5哈希后,以前8个字节的 $key
, ,并将它们附加到结尾 $key
, ,使您有24字节的价值传递给 mcrypt_encrypt()
.
其他提示
我找到了一个解决方案,检查此链接可能会为您提供帮助。 http://sanity-free.com/131/triple_des_between_php_and_csharp.html
这是解密功能,以防万一:
public static string Decrypt(string cypherString)
{
byte[] key = Encoding.ASCII.GetBytes("icatalogDR0wSS@P6660juht");
byte[] iv = Encoding.ASCII.GetBytes("iCatalog");
byte[] data = Convert.FromBase64String(cypherString);
byte[] enc = new byte[0];
TripleDES tdes = TripleDES.Create();
tdes.IV = iv;
tdes.Key = key;
tdes.Mode = CipherMode.CBC;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform ict = tdes.CreateDecryptor();
enc = ict.TransformFinalBlock(data, 0, data.Length);
return UTF8Encoding.UTF8.GetString(enc, 0, enc.Length);
}
看看编码。getBytes,您需要UTF8 ...