Bouncy Castle 添加额外的填充块

Bouncy Castle add extra padding block

我已经使用 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 ;
    }

有什么解决办法吗?

发布的代码适用 Zero padding. There are several variants of Zero padding. One pads with a complete block if the plaintext length is already an integer multiple of the block size (e.g. the variant that uses BC), the other does not (e.g. the variant that uses .NET), see also here零填充 部分的最后一句。 BC 和 .NET 变体之间的另一个区别是 BC 变体在解密过程中删除了填充,而 .NET 变体则没有。

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

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

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