将C#中的TripleDESCryptoServiceProvider移植到PHP
我试图将以下C#方法移植到PHP,但无法获得正确的输出。将C#中的TripleDESCryptoServiceProvider移植到PHP
public static string Encrypt()
{
String text = "123456";
String key = "1r1ppl3x";
byte[] arrText = UTF8Encoding.UTF8.GetBytes(text);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = (new UnicodeEncoding()).GetBytes(key);
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(arrText, 0, arrText.Length);
tdes.Clear();
String encrypted = Convert.ToBase64String(resultArray, 0, resultArray.Length);
return encrypted;
}
我在PHP尝试至今:
function encrypt()
{
$key = utf8_encode("1r1ppl3x\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
$data = utf8_encode("123456");
$blocksize = mcrypt_get_block_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_ECB);
$tripleKey = substr($key, 0, mcrypt_get_key_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_ECB));
$paddingSize = $blocksize - (strlen($data) % $blocksize);
$data .= str_repeat(chr($paddingSize), $paddingSize);
$encodedText = mcrypt_encrypt(MCRYPT_TRIPLEDES, $tripleKey, $data, MCRYPT_MODE_ECB);
return base64_encode($encodedText);
}
由于某种原因,我不能让PHP代码相同,一个在C#中的输出。
此外,我知道mcrypt_get_block_size
和其他mcrypt
相关方法在PHP 7.1中已弃用,建议不要使用它。
C#代码使用PKCS#7填充,PHP MCRYPT代码使用null填充。
有一个假设,关键应扩展为空值。
使用Triple DES和8字节的单个DES密钥没有意义。此外,仅使用8位DES密钥的56位。一个56位密钥不被认为是安全的。
tdes.Key = (new UnicodeEncoding()).GetBytes(key);
这UnicodeEncoding
构造是UTF-16,小尾数 “与BOM”。 “带有BOM”并不重要,因为没有任何东西叫做GetPreamble()
,所以对于所有的意图和目的,它都是UTF-16LE。
这意味着你的钥匙("1r1ppl3x"
)居然是:
31 00 72 00 31 00 70 00 70 00 6C 00 33 00 78 00
这与
- =
{ 31 00 72 00 31 00 70 00 }
-
k2
={ 70 00 6C 00 33 00 78 00 }
瓦一2DEA关键这是违法的。除.NET之外,与其他所有内容一样,不关心DES奇偶校验位,所以它只是假设每个字节的最低有效位是正确的。无论在PHP中的图书馆可能会做同样的事情。如果没有,您可能需要correct the parity manually。
2DEA密钥具有等效的3DEA密钥k3
=。因此,如果您的PHP库不支持2DEA密钥,则可以通过将前8个字节复制到最后,从而人为地扩展它(在正确使用UTF-16LE而不是UTF-8之后),从而构建一个24字节的值。
如果utf8_encode
是最好的“在PHP中将文本转换为二进制数据”,那么您希望使用输入字符串"1\0r\01\0p\0p\0l\03\0x\01\0r\01\0p\0"
。
看起来您已经找到How to add/remove PKCS7 padding from an AES encrypted string?,因此更正密钥应该会使您进入“等效功能”状态。
现在你所有的问题是,你使用的是一个56位的密钥(所有这些零都很容易被猜到),就好像它是一个168位密钥,并且使用ECB模式,并且使用一个废弃的库,和(可以说)您使用3DES而不是AES,以及(个人观点)从强类型语言转换为脚本语言。
为什么使用Triple DES和8字节密钥?这只是恢复到不安全的DES。 ] ECB模式不安全,请参阅[ECB模式](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29),向下滚动到企鹅。 – zaph
最好不要使用PHP mcrypt,它是弃用的,多年未更新,不支持标准的PKCS#7(néePKCS#5)填充,只有**非标准的null填充**不能甚至可以用于二进制数据。 mcrypt有很多优秀的[bug](https://sourceforge.net/p/mcrypt/bugs/),可以追溯到2003年.mcrypt-extension已被弃用,将在PHP 7.2中被删除。请考虑使用[defuse](https://github.com/defuse/php-encryption)或[RNCryptor](https://github.com/RNCryptor),他们提供了一个完整的解决方案,并且正在维护和正确。 – zaph
我很欣赏这个建议,但我不能更改C#代码,因为它不是我的。它是我们客户的遗留软件的一部分。我的任务是使现有C#代码的PHP等效。 – xar