我试图将以下C#方法移植到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);
}
由于某种原因,我无法获得与C#中相同的PHP代码输出。
此外,我知道在PHP 7.1中不推荐使用mcrypt_get_block_size
和其他mcrypt
相关方法,因此不建议使用它。
答案 0 :(得分:2)
tdes.Key = (new UnicodeEncoding()).GetBytes(key);
UnicodeEncoding
构造函数用于UTF-16,little-endian,“with BOM”。 “with BOM”并不重要,因为没有任何名为GetPreamble()
,所以对于所有意图和目的,它都是UTF-16LE。
这意味着您的密钥("1r1ppl3x"
)实际上是:
31 00 72 00 31 00 70 00 70 00 6C 00 33 00 78 00
哪个是带有
的2DEA密钥k1
= { 31 00 72 00 31 00 70 00 }
k2
= { 70 00 6C 00 33 00 78 00 }
哪个是非法的。除了.NET之外,.NET不关心DES奇偶校验位,所以它只是假装每个字节的最低有效位是正确的。无论PHP中的哪个库都可能都这样做。如果没有,您可能需要correct the parity manually。
2DEA密钥的等效3DEA密钥为k3
= k1
。因此,如果您的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,并且(个人意见)从强类型语言转变为脚本语言。
答案 1 :(得分:0)
C#代码使用PKCS#7填充,PHP MCRYPT代码使用空填充。
假设密钥应该使用空值扩展。
使用具有8字节的单个DES密钥的Triple DES是没有意义的。此外,仅使用56位的8位DES密钥。 56位密钥不被认为是安全的。