将加密从 AesCryptoServiceProvider 转换为 BouncyCastle

Convert encryption from AesCryptoServiceProvider to BouncyCastle

我在磁盘上使用 AesCryptoServiceProvider 加密了文件。 我需要将代码转换为 PCL(没有 class AesCryptoServiceProvider)。所以我想使用 Bouncy Castle ( https://www.nuget.org/packages/Portable.BouncyCastle/ ) 在不更改加密的情况下读取和保存文件。并防止需要转换所有文件..

Key 是 32 个字节长。 IV 是 16 个字节长。

原代码如下:

private static byte[] Encrypt(string plainText, byte[] Key, byte[] IV)
{
    using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
    {
        aesAlg.Key = Key;
        aesAlg.IV = IV;

        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
        using (MemoryStream outputStream = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                {
                    swEncrypt.Write(plainText);
                }
            }

            return outputStream.ToArray();
        }
    }
}

AesCryptoServiceProvider 的默认模式是 CBC,填充类型为 PKCS7,然后我尝试使用 classes CbcBlockCipherPkcs7Padding.这是我最后一次尝试:

private static byte[] Encrypt(byte[] input, byte[] key, byte[] IV)
{
    var keyParameter = new KeyParameter(key);
    var parameters = new ParametersWithIV(keyParameter, IV);

    var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new AesEngine()), new Pkcs7Padding());

    cipher.Init(true, parameters);

    var rsl = new byte[cipher.GetOutputSize(input.Length)];
    var outOff = cipher.ProcessBytes(input, 0, input.Length, rsl, 0);

    cipher.DoFinal(rsl, outOff);
    return rsl;
}

文本 "test" 的原始结果是 8jykPv2OSILKjJwvgLRr1w==,但新代码是 BaYeiuWSnRiHXBpwt19Dag==

那我想念什么?

感谢您的帮助!

更新#1: 这是 Key 和 IV 的值:

private static byte[] KEY = {98, 193, 95, 78, 211, 151, 118, 57, 179, 5, 85, 181, 133, 20, 94, 101, 184, 175, 94, 164, 150, 119, 75, 207, 189, 178, 21, 213, 13, 217, 174, 44};
private static byte[] IV = {1, 199, 179, 189, 160, 220, 229, 238, 179, 14, 255, 147, 187, 49, 179, 134 };

更新#2: 对于 Bouncy Castle,我将我的 plainText 转换为 input 并使用以下行:

var input = Encoding.Unicode.GetBytes(plainText);

差异来自那里...

问题是streamwriter的编码问题。当写入加密流时,它会带来相同的结果:

    [TestMethod]
    public void windows()
    {

        byte[] KEY = { 98, 193, 95, 78, 211, 151, 118, 57, 179, 5, 85, 181, 133, 20, 94, 101, 184, 175, 94, 164, 150, 119, 75, 207, 189, 178, 21, 213, 13, 217, 174, 44 };
        byte[] IV = { 1, 199, 179, 189, 160, 220, 229, 238, 179, 14, 255, 147, 187, 49, 179, 134 };

        byte[] input = System.Text.Encoding.UTF8.GetBytes("test");

        string win = Convert.ToBase64String(Encrypt_win(input, KEY, IV));

        string bc = Convert.ToBase64String(Encrypt_bc(input, KEY, IV));



        Assert.AreEqual(win, "8jykPv2OSILKjJwvgLRr1w==");
        Assert.AreEqual(bc, "8jykPv2OSILKjJwvgLRr1w==");

    }


    //private static byte[] Encrypt(string plainText, byte[] Key, byte[] IV)
    private static byte[] Encrypt_win(byte[] input, byte[] Key, byte[] IV)
    {
        using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
        {
            aesAlg.Key = Key;
            aesAlg.IV = IV;


            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
            using (MemoryStream outputStream = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
                {
                    csEncrypt.Write(input, 0, input.Length);

                    /*
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        //swEncrypt.Write(plainText);
                        swEncrypt.Write(input);
                    }
                    */
                }

                return outputStream.ToArray();
            }
        }
    }



    private static byte[] Encrypt_bc(byte[] input, byte[] key, byte[] IV)
    {
        var keyParameter = new KeyParameter(key);
        var parameters = new ParametersWithIV(keyParameter, IV);

        var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new AesEngine()), new Pkcs7Padding());

        cipher.Init(true, parameters);

        var rsl = new byte[cipher.GetOutputSize(input.Length)];
        var outOff = cipher.ProcessBytes(input, 0, input.Length, rsl, 0);

        cipher.DoFinal(rsl, outOff);
        return rsl;
    }

在使用 BouncyCastle 调用 Encrypt() 方法之前,我将字符串转换为 Encoding.Unicode.GetBytes(plainText); 而不是 Encoding.UTF8.GetBytes(plainText);

通过此修复,两种方法给出相同的结果!