c# - 在 PHP 中从 C# 复制相同的 AES 加密

标签 c# php encryption aes

我正在做一个项目,我有一个 C# 应用程序,它有一个加密类,可以执行字符串值的加密和解密。我现在想制作一个 Web 界面,以使用 PHP 与我的 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 变量使用的 key 与 C# 应用程序中的 rgbIV 变量相同,而 PHP Web 界面中的 CIPHERKEY 使用的 key 与我的 c# 应用程序中的 key 变量相同。

感谢您提供的任何帮助

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

在上面的 PHP 代码中,我将 NHHloywxlybbANIH5dS7SQ== 作为加密字符串。

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

的结果

最佳答案

您得到不同结果的原因是默认情况下 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自动添加padding。

更新 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;
    }
}

关于c# - 在 PHP 中从 C# 复制相同的 AES 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14551332/

相关文章:

c# - 如何将图像转换为字符流

php - 谷歌地图 "but your computer or network may be sending automated queries"错误

java - 您可以将 RSA 公共(public)指数设置为您选择的值吗?

java - Cipher.getInstance 太慢

c# - 传递参数的最佳实践,可以取两个值

c# - "Classes should never perform work involving Dependencies in their constructors."

php - 定义 header 响应在 hiawatha 和 php 中不起作用

c - 编码文本和文件写入读取错误

c# - 动态函数映射

php - 在 PHP 中,我们如何设置 session 的到期日期?