【问题标题】:how to pad data before encryption with Bouncy Castle如何在使用 Bouncy Castle 加密之前填充数据
【发布时间】:2012-11-13 08:47:14
【问题描述】:

我正在尝试使用 CBC 模式的 AES 算法加密我的数据。出于这个原因,我使用 .Net 库“Bouncy Castle”。我没有加密背景,所以我试图以一种简单的方式使用它。这是我的加密代码

public byte[] encrypt(byte[] key, byte[] iv,byte[] data) 
    {
        IBlockCipher engine=new AesFastEngine();
        KeyParameter keyParam = new KeyParameter(key);
        CbcBlockCipher cipher = new CbcBlockCipher(engine);

        ICipherParameters parameters = new ParametersWithIV(keyParam, iv);

        byte[] output=new byte[16+data.Length];
        cipher.Init(true, parameters);
        cipher.ProcessBlock(data, 0, output, data.Length);

        //process output
        byte[] cipherArray = new byte[data.Length];
        /*
        int k=0;
        for (int i = 0; i < output.Length; i++) 
        {
            if (output[i]!= 0) 
            {
                cipherArray[k++] = output[i];
            }
        }
         */
        return cipherArray;

    }

当我尝试输入不是 16 的倍数时,我得到一个异常。当我用左边的零填充数组到右边时,我可以得到一个结果。但结果对我来说也是一个问题。它给了我这样的结果:

[0][0][0][0[111][22][33][44][66][77][33][12][32][23][0][0][0][0][0] 

左右两边都是零。

我认为这可能与我对ProcessBlock(data, 0, output, data.Length) 函数的使用有关。我使用它的假设是输出将是我的密文,但似乎输出应该比输入长度长。由于我没有有关此功能的文档,因此我可能以错误的方式使用它。任何帮助将不胜感激

【问题讨论】:

    标签: c# cryptography aes


    【解决方案1】:

    Bouncy Castle 会为您做填充,首先您需要将密码设置为:

      PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
    

    要使您的其余代码正常工作,您需要使用 cipher.GetOutputSize(data.Length) ProcessBytesDoFinal 以便正确添加填充。

    byte[] output = new byte[cipher.GetOutputSize(data.Length)];
    int len = cipher.ProcessBytes(data, 0, data.Length, output, 0);
    cipher.DoFinal(output, len);
    

    我有一个使用AES-GCM in Bouncy Castle on CodeReview的简单示例

    AES-GCM增加了鉴权加密,但是使用api的基本原理是一样的。

    我还有一个高级加密框架的 C# 端口 Kecyzar,我使用 Bouncy Castle 作为后端,虽然这是一个更难的例子,抽象的加密代码 SymmetricStream 设置为在 @ 中使用 AES-CBC 987654324@

    【讨论】:

    • 谢谢 jbtule,但是当我尝试使用 paddedCipher.DoFinal(output,len);它抛出一个异常“description 中的最后一个块不完整”,processBytes 方法返回一个值,该值是 16 的乘积,小于数据长度,你知道是什么导致了这个问题吗?谢谢
    • @paskalnikov 我添加了更多代码来展示如何使用。 ProcessBytes 将为每个完整的块输出字节并保持其余的缓冲(您也可以多次调用ProcessBytes,一次给它一部分数据),它不会假设您已经完成直到你调用DoFinal,然后DoFinal 将写出最后一个字节(带填充),所以如果你有DoFinal 写入你的最终输出数组,你需要给它它应该写入的索引数组。
    【解决方案2】:

    通常会使用标准填充算法来确保明文数据与密码的块大小对齐。

    您目前正在手动编码zero padding。这不是一个很好的选择,因为它禁止以零字节结尾的原始数据 - 您如何将其与填充区分开来?

    我建议您使用标准填充,例如PKCS #7 padding。请注意,这通常称为“PKCS #5 填充”,因为它们非常相似。

    您可能希望参考这个其他 SO 问题 - Encrypt/Decrypt using Bouncy Castle in C# - 以获取使用标准填充的示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-15
      • 2011-08-20
      • 2011-07-12
      • 2011-01-26
      • 2015-06-13
      • 2012-05-10
      • 1970-01-01
      • 2017-04-30
      相关资源
      最近更新 更多