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

报告相同问题?

悬赏问题

  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?