C# 欧洲央行解密问题中的三重DES

C# 欧洲央行解密问题中的三重DES,c#,php,encryption,des,ecb,C#,Php,Encryption,Des,Ecb,我有一个PHP脚本,我们需要将它转换为C#来解码API post请求的结果,但我的C#实现遇到了问题 我们在运行PHP脚本时得到了很好的结果,该脚本是XXXX-XXXX-XXXX,但会出现不同的错误 价值观是: encodedText = "U8Q+m2zpFMLa/3gYILHx5w==" key = "examplesecret" keyHash = "6315046b2c085bbeeab87c65" Php脚本: <?php $secret = 'examplesecret';

我有一个PHP脚本,我们需要将它转换为C#来解码API post请求的结果,但我的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;
?>

我看到了几件事:

  • 通过PHP中的substr派生
    $key
    ;但就拿C#中MD5的输出来说,它们是一样的吗?(例如,如果PHP的值是一个十六进制字符串,那么MD5的16个字节是32个字符,它被转换为24个字符,是一个12字节(96位)的值;在C#中是16个字节)
  • 说到键,如果您使用的是PHP 5.6之前的版本,那么有缺陷的键是0填充的(根据;C#的文档),这不适合您。因此,这是另一件需要检查的事情
  • PHP代码中有一个IV,但ECB没有使用IV。这不会导致您的问题,但它不太理想
  • 当然,在这一点上,我应该警告欧洲央行“过于稳定”,不会在加密数据中隐藏模式,也不会隐藏您再次发送相同的消息
  • TransformFinalBlock需要字节,但您似乎在这里给它一个字符串。因为C#是一种强类型语言,所以这不可能是您正在运行的代码
  • 您应该避免谈论算法的具体实现。
    TripleDES.Create()
    优先于
    new TripleDESCryptoServiceProvider()
    MD5.Create()
    优先于
    new MD5CryptoServiceProvider()
    ;并将变量键入TripleDES和MD5
  • TripleDES对象、MD5对象和CreateDecryptor()的输出都是IDisposable的,因此您应该将它们包装在using语句中,以便更有效地使用本机资源

  • 不过,问题最可能的罪魁祸首是您在两种语言中生成的密钥不相同。

    我看到了以下几点:

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

  • 但是,问题最可能的罪魁祸首是两种语言生成的密钥不相同。

    出现了什么错误?异常错误:“错误数据。\r\n”3DES+ECB模式==不安全。3DES不应在新作品中使用,它被AES取代。不要使用ECB模式,它不安全,请参阅,向下滚动到企鹅。最好不要使用mcrypt,它是弃用软件,多年来未更新,不支持标准PKCS#7(née PKCS#5)填充,只有非标准的空填充,甚至不能用二进制数据。McLIPT有许多优秀的追溯到2003。相反,考虑使用或提供完整的解决方案,并保持正确。这个代码太糟糕了,你应该扔掉它,只使用具有一个PHP库和一个C库的RNIKORT。您得到的错误是什么?异常错误:“坏数据。\r\n”3DES+ECB模式==不安全。3DES不应用于新工作,它被AES取代。不要使用ECB模式,它不安全,请参阅,向下滚动到企鹅。最好不要使用mcrypt,它是弃用软件,多年未更新,不支持标准PKCS#7(née PKCS#5)填充,只有非标准的空填充,甚至不能用二进制数据。McLIPT有许多优秀的追溯到2003。相反,考虑使用或提供完整的解决方案,并保持正确。这个代码太糟糕了,你应该扔掉它,只使用具有一个PHP库和一个C库的RNIKORT。
    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;
    }