0

我有这个 PHP 脚本,我们需要将其转换为 C# 以解码来自 API 发布请求的结果,但是我的 C# 实现遇到了问题。

我们在运行 PHP 脚本时得到了很好的结果,XXXX-XXXX-XXXX但得到了不同的错误。

值为:

encodedText = "U8Q+m2zpFMLa/3gYILHx5w=="
key = "examplesecret"
keyHash = "6315046b2c085bbeeab87c65"

php脚本:

<?php
$secret = 'examplesecret';
$encrypted_code = 'U8Q+m2zpFMLa/3gYILHx5w==';
// Base64
// Decode
$encrypted_code = base64_decode( $encrypted_code );
// Create decryption module
$cipher = mcrypt_module_open( 'tripledes', '', 'ecb', '' );
$keysize = mcrypt_enc_get_key_size( $cipher ); // = 24
// Generate key
$hash = md5( $secret );
$key = substr( $hash, 0, $keysize );
// Initialise decrypter
$iv = mcrypt_create_iv( mcrypt_enc_get_iv_size( $cipher ),
MCRYPT_DEV_RANDOM );
mcrypt_generic_init( $cipher, $key, $iv );
// Decrypt code
$decrypted = mdecrypt_generic( $cipher, $encrypted_code );
// Output decrypted code
echo $decrypted;
?>

C# 脚本

public static string Decrypt(string encodedText, string key)
{
    TripleDESCryptoServiceProvider desCryptoProvider = new TripleDESCryptoServiceProvider();
    MD5CryptoServiceProvider hashMD5Provider = new MD5CryptoServiceProvider();

    byte[] byteHash;
    byte[] byteBuff;

    byteHash = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(key));
    desCryptoProvider.Key = byteHash;
    desCryptoProvider.Padding = PaddingMode.None;
    desCryptoProvider.Mode = CipherMode.ECB; //CBC, CFB
    byteBuff = Convert.FromBase64String(encodedText);

    var byteHex = BitConverter.ToString(byteBuff).Replace("-", " ");

    string plaintext = Encoding.UTF8.GetString(desCryptoProvider.CreateDecryptor().TransformFinalBlock(byteHex, 0, byteHex.Length));
    return plaintext;
}
4

1 回答 1

2

我看到的几件事:

  1. 您通过 PHP 中的 substr 派生$key;但只需在 C# 中获取 MD5 的输出,它们是否相同?(例如,如果 PHP 的值是一个十六进制字符串,那么 MD5 的 16 个字节是 32 个字符,它被截断为 24 个字符,是一个 12 字节(96 位)的值;在 C# 中它是 16 个字节)
  2. 说到密钥,如果您在 5.6 之前使用 PHP,则会用 0 填充有缺陷的密钥(根据mcrypt_encrypt的文档;C# 不会为您这样做。所以这是另一件事要检查。
  3. 您在 PHP 代码中有 IV,但 ECB 不使用 IV。这不会在这里引起您的问题,但它并不理想。
  4. 当然,此时我应该警告欧洲央行“太稳定”并且不会隐藏加密数据中的模式,也不会隐藏您再次发送相同的消息。
  5. TransformFinalBlock 需要字节,但您似乎在这里给它一个字符串。由于 C# 是一种强类型语言,因此它实际上并不是您正在运行的代码。
  6. 你应该避免谈论算法的具体实现。 TripleDES.Create()优于new TripleDESCryptoServiceProvider(), MD5.Create()over new MD5CryptoServiceProvider(); 并将变量键入为 TripleDES 和 MD5。
  7. TripleDES 对象、MD5 对象和 CreateDecryptor() 的输出都是 IDisposable,因此您应该真正将它们包装在 using 语句中以更有效地使用您的本地资源。

但是,最可能导致您的问题的罪魁祸首是您没有在两种语言中生成相同的密钥。

于 2016-08-12T16:19:24.233 回答