dongtang1966 2013-01-27 19:33
浏览 89
已采纳

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

I am working on a project where I have a C# application which has an encryption class which can perform encryption and decryption of a string value. I now want to make a web interface to work alongside my C# application using PHP.

I am trying to do the same sort of encryption that my C# project is doing in my PHP web site but I can't work out what I need to do.

Below is the code for my C# application.

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());
        }

I am trying the following code in my PHP web interface

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

I've tried various variations but can't find the correct way to do it.

The iv variable is using the same key as in the rgbIV variable within the C# app and the CIPHERKEY in the PHP web interface is using the same key as in the key variable within my c# app.

Thanks for any help you can provide

UPDATE At the moment I keep on getting different results. I am testing it by passing in the string password.

In the current code above in PHP I get NHHloywxlybbANIH5dS7SQ== as the encrypted string.

However, with the same string I get the result of n86Mwc5MRXzhT3v3A/uxEA==

  • 写回答

2条回答 默认 最新

  • duanhuilao0787 2013-01-27 19:43
    关注

    The reason you're getting different results is that by default the Cipher Mode in C# is CBC whereas in PHP you are using ECB Mode See Wikipedia for information on the two different modes.

    CBC is more secure than ECB so I recommend sticking with the default .NET implementation and changing your PHP code to use CBC however you do have two options.

    Option 1 - Change .NET to use ECB mode (if you have some legacy code and you need to use it) But please read about it, ECB mode will leave artifacts behind in your cipher text and will enable attackers to have some knowledge of what you've encrypted (see the Penguin image on the Wikipedia article).

    To change the .NET code to use ECB just add a line for the mode:

    // 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 ...
    

    Option 2 - Change the PHP script to use CBC mode

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

    Update I checked this out in more detail and found that you also need to add padding to your plaintext as well. The following code will give you a match:

    PHP Code:

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

    The C# code will automatically add padding based on PKCS7.

    Update 2 Strip Padding: As stated in the comments, the padding would need to be stripped after decryption.

    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;
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码