4

我正在做一个项目,我有一个 C# 应用程序,它有一个加密类,可以执行字符串值的加密和解密。我现在想使用 PHP 制作一个 Web 界面来与我的 C# 应用程序一起工作。

我正在尝试执行与我的 C# 项目在我的 PHP 网站中执行的相同类型的加密,但我无法弄清楚我需要做什么。

下面是我的 C# 应用程序的代码。

public static string encrypt(string encryptionString)
        {
            byte[] clearTextBytes = Encoding.UTF8.GetBytes(encryptionString);

            SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();

            MemoryStream ms = new MemoryStream();
            byte[] rgbIV = Encoding.ASCII.GetBytes("PRIVATE");

            byte[] key = Encoding.ASCII.GetBytes("PRIVATE");
            CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write);

            cs.Write(clearTextBytes, 0, clearTextBytes.Length);

            cs.Close();

            return Convert.ToBase64String(ms.ToArray());
        }

我正在我的 PHP Web 界面中尝试以下代码

define("CIPHERKEY", "PRIVATE");
function encrypt($data) 
    { 
        //$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_ECB, '');
        $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
        //$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($cipher), MCRYPT_RAND);
        $iv = 'PRIVATE';
        //$key = substr(CIPHERKEY, 0, mcrypt_enc_get_key_size($cipher));
        $key =CIPHERKEY;
        if (mcrypt_generic_init($cipher, $key, $iv) != 1) 
        {
            $cipherData = mcrypt_generic($cipher, $data);

            mcrypt_generic_deinit($cipher);
            mcrypt_module_close($cipher);

            $sanitizedCipherData = trim(base64_encode($cipherData)); 

            return $sanitizedCipherData;
        } 
    }

我尝试了各种变体,但找不到正确的方法。

iv 变量使用与 C# 应用程序中的 rgbIV 变量相同的密钥,PHP Web 界面中的 CIPHERKEY 使用与我的 c# 应用程序中的密钥变量相同的密钥。

感谢您的任何帮助,您可以提供

更新 目前我不断得到不同的结果。我通过传入字符串来测试它password

在上面的 PHP 代码中,我得到NHHloywxlybbANIH5dS7SQ==了加密字符串。

但是,使用相同的字符串,我得到的结果是n86Mwc5MRXzhT3v3A/uxEA==

4

2 回答 2

3

您得到不同结果的原因是默认情况下,C# 中的密码模式是 CBC,而在 PHP 中您使用的是 ECB 模式,有关两种不同模式的信息,请参阅Wikipedia

CBC 比 ECB 更安全,因此我建议坚持使用默认的 .NET 实现并更改您的 PHP 代码以使用 CBC,但是您有两种选择。

选项 1 - 更改 .NET 以使用 ECB 模式(如果您有一些遗留代码并且需要使用它)但是请阅读它,ECB 模式会在您的密文中留下伪影,并使攻击者能够了解什么您已加密(请参阅维基百科文章中的企鹅图像)。

要更改 .NET 代码以使用 ECB,只需为模式添加一行:

// Start of your code ...
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
rijn.Mode = CipherMode.ECB;

MemoryStream ms = new MemoryStream();
byte[] rgbIV = Encoding.ASCII.GetBytes("PRIVATE");
// Rest of your code ...

选项 2 - 更改 PHP 脚本以使用 CBC 模式

$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');

更新 我更详细地检查了这一点,发现您还需要在明文中添加填充。以下代码将为您提供匹配项:

PHP代码:

function encrypt($data) 
{ 
    $iv = "AAAAAAAAAAAAAAAA";
    $key = CIPHERKEY;

    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, addpadding($data), MCRYPT_MODE_CBC, $iv));
}

function addpadding($string, $blocksize = 16)
{
    $len = strlen($string);
    $pad = $blocksize - ($len % $blocksize);
    $string .= str_repeat(chr($pad), $pad);
    return $string;
}

C# 代码将自动添加基于 PKCS7 的填充。

更新 2剥离填充:如评论中所述,解密后需要剥离填充。

function strippadding($string)
{
    $slast = ord(substr($string, -1));
    $slastc = chr($slast);
    $pcheck = substr($string, -$slast);
    if(preg_match("/$slastc{".$slast."}/", $string)){
        $string = substr($string, 0, strlen($string)-$slast);
        return $string;
    } else {
        return false;
    }
}
于 2013-01-27T19:43:20.427 回答
1

试试这个:

   function encrypt_str($str) 
    {
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_DEV_URANDOM);
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, "PRIVATE", $str, MCRYPT_MODE_ECB, $iv);
    return rtrim($encrypted);
    }

并将其添加到您的 C#

rijn.Mode = CipherMode.ECB;
于 2013-01-27T19:41:01.523 回答