6

我正在尝试用 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;
}
4

2 回答 2

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

    }
于 2013-11-16T09:19:22.123 回答
4

您的 C# 代码有两个问题。

  1. 您不应该将您的内容编码MemoryStream为 UTF8。的输出CryptoStream是二进制的,不会正确转换。返回 a byte[],或者如果您真的想要一个字符串,请将输出编码为 Hex 或 Base64。

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

另请注意,您的 PHP 和 C# 方法的签名是不同的。PHP 函数的参数顺序是data, key, ivC# 方法是data, iv, key. 如果在我上面列出的更改之后您仍然遇到问题,则可能是在调用 C# 加密方法时您的 IV 和密钥被颠倒了。

于 2013-09-04T18:30:41.993 回答