C#中的PHP MCRYPT_RIJNDAEL_128加密

时间:2013-09-04 16:52:26

标签: php c#-4.0 encryption

我正在尝试在C#中重写此函数。但是C#输出与php不匹配

PHP版

// Encrypt data using AES128-cbc
function encrypt($data, $key, $iv) {
    $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', '');
    mcrypt_generic_init($cipher, $key, $iv);
    $multipass = mcrypt_generic($cipher, $data);
    mcrypt_generic_deinit($cipher);
    return $multipass;
}

C#版本

public static string encrypt(string encryptionString, string iv, string key)
{
    byte[] clearTextBytes = Encoding.UTF8.GetBytes(encryptionString);
    var rijn = SymmetricAlgorithm.Create();
    rijn.KeySize = 128;
    rijn.Mode = CipherMode.CBC;
    var ms = new MemoryStream();
    var cs = new CryptoStream(ms, rijn.CreateEncryptor(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(iv)), CryptoStreamMode.Write);
    cs.Write(clearTextBytes, 0, clearTextBytes.Length);
    cs.Close();
    var tmp = Encoding.UTF8.GetString(ms.ToArray());
    return tmp;
}

2 个答案:

答案 0 :(得分:6)

使用PHP加密/解密:

class Cipher {
    private $key, $iv;
    function __construct() {
        $this->key = "edrtjfjfjlldldld";
        $this->iv = "56666852251557009888889955123458";
    }
    function encrypt($text) {

        $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
        $padding = $block - (strlen($text) % $block);
        $text .= str_repeat(chr($padding), $padding);
        $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->key, $text, MCRYPT_MODE_CBC, $this->iv);

        return base64_encode($crypttext);
    }

    function decrypt($input) {
        $dectext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->key, base64_decode($input), MCRYPT_MODE_CBC, $this->iv);
        return $dectext;
    }
}

使用C#加密/解密:

public class RijndaelSimple
    {
        const string iv = "56666852251557009888889955123458";
        const string key = "edrtjfjfjlldldld";

        static public String EncryptRJ256(string plainText)
        {
            var encoding = new UTF8Encoding();
            var Key = encoding.GetBytes(key);
            var IV = encoding.GetBytes(iv);
            byte[] encrypted;

            using (var rj = new RijndaelManaged())
            {
                try
                {
                    rj.Padding = PaddingMode.PKCS7;
                    rj.Mode = CipherMode.CBC;
                    rj.KeySize = 256;
                    rj.BlockSize = 256;
                    rj.Key = Key;
                    rj.IV = IV;

                    var ms = new MemoryStream();

                    using (var cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
                    {
                        using (var sr = new StreamWriter(cs))
                        {
                            sr.Write(plainText);
                            sr.Flush();
                            cs.FlushFinalBlock();
                        }
                        encrypted = ms.ToArray();
                    }
                }
                finally
                {
                    rj.Clear();
                }
            }

            return Convert.ToBase64String(encrypted);
        }

        static public String DecryptRJ256(string input)
        {
            byte[] cypher = Convert.FromBase64String(input);

            var sRet = "";

            var encoding = new UTF8Encoding();
            var Key = encoding.GetBytes(key);
            var IV = encoding.GetBytes(iv);

            using (var rj = new RijndaelManaged())
            {
                try
                {
                    rj.Padding = PaddingMode.PKCS7;
                    rj.Mode = CipherMode.CBC;
                    rj.KeySize = 256;
                    rj.BlockSize = 256;
                    rj.Key = Key;
                    rj.IV = IV;
                    var ms = new MemoryStream(cypher);

                    using (var cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
                    {
                        using (var sr = new StreamReader(cs))
                        {
                            sRet = sr.ReadLine();
                        }
                    }
                }
                finally
                {
                    rj.Clear();
                }
            }

            return sRet;
        }

    }

答案 1 :(得分:4)

C#代码存在两个问题。

  1. 您不应将MemoryStream的内容编码为UTF8。 CryptoStream的输出是二进制的,无法正确转换。要么返回byte[],要么确实需要字符串,请将输出编码为Hex或Base64。

  2. 您需要通过rijn.Padding = PaddingMode.Zeros;设置填充模式。虽然没有明确说明,PHP使用0来填充数据块大小。 SymmetricAlgorithm的填充默认值为PKCS7。

  3. 另请注意,PHP和C#方法的签名是不同的。 PHP函数的参数顺序为data, key, iv,而C#方法为data, iv, key。如果您在我上面列出的更改后仍然遇到问题,那么在调用C#加密方法时可能会反转您的IV和密钥。