【问题标题】:Bouncy Castle add extra padding block充气城堡添加额外的填充块
【发布时间】:2020-09-03 18:15:43
【问题描述】:

我已经使用 BounyCastle v1.8.6 .net 核心实现了 AES 128 CBC 加密,当我尝试加密长度为 16 字节的数据时,它会添加另一个包含数据的 16 字节 - 我猜是填充 - 。我不知道为什么它会添加这个。知道默认的 c# 实现不会这样做

以十六进制格式作为字符串的数据示例 6752b87027fc7728fbe4ec2f0d76da75 => EE93F245FCDB928BF8E3012C9E5150EDA1B876A6D790CFC69C2F129215B3C938

如果要加密的数据是 32、64、128 等,也会发生这种情况

代码:

    int DefaultBlockSize = 16;
    public byte[] Encrypt(byte[] plainBytes, byte[] key, byte[] iv = null)
    {
        iv ??= new byte[DefaultBlockSize] ;
        
        AesEngine engine = new AesEngine();
        CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
        IBlockCipherPadding padding = new ZeroBytePadding();
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher, padding);

        KeyParameter keyParam = new KeyParameter(key);
        ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, DefaultBlockSize);

        // Encrypt
        cipher.Init(true, keyParamWithIV);
        byte[] outputBytes = new byte[cipher.GetOutputSize(plainBytes.Length)];
        int length = cipher.ProcessBytes(plainBytes, outputBytes, 0);
        cipher.DoFinal(outputBytes, length);
        return outputBytes ;
    }

任何想法如何解决这个问题?

【问题讨论】:

    标签: c# asp.net-core bouncycastle


    【解决方案1】:

    发布的代码适用于Zero padding。零填充有几种变体。如果明文长度是 already 块大小的整数倍(例如使用 BC 的变体),则一个填充完整的块,另一个不填充(例如使用 .NET 的变体),另见here零填充部分的最后一句。 BC 和 .NET 变体之间的另一个区别是 BC 变体在解密期间会删除填充,而 .NET 变体则不会。

    这种矛盾是零填充的一个缺点。另一个缺点是无法区分终止明文 0x00 字节和填充 0x00 字节,因为零填充不包含有关填充字节数的信息。

    由于这种不可靠性,PKCS7 填充更好:它在RFC 2315(第 10.3 节,注 2)中有明确定义(即没有不同的变体),它包含有关填充字节数的信息,以便它们可以与明文字节区分开来。

    BouncyCastle 不提供在不同的零填充变体之间进行选择的选项。它仅提供上述变体。因此,要将 BouncyCastle 与 .NET 变体一起使用,必须由您自己实现:首先,必须将 PaddedBufferedBlockCipher 替换为 BufferedBlockCipher,这意味着不使用 (BouncyCastle) 填充。其次,.NET 变种必须用相应的方法实现,比较简单:如果明文长度不是块长度的整数倍,则用 0x00 值进行填充,直到满足这个条件。然后在加密之前将该方法应用于明文。由于 .NET 变体在解密过程中不会删除零填充,因此仅需要第一部分进行解密。

    【讨论】: