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条)

报告相同问题?

悬赏问题

  • ¥20 beats蓝牙耳机怎么查看日志
  • ¥15 Fluent齿轮搅油
  • ¥15 八爪鱼爬数据为什么自己停了
  • ¥15 交替优化波束形成和ris反射角使保密速率最大化
  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏