Search code examples
c#asp.net-corebouncycastle

Bouncy Castle add extra padding block


I have implemented an AES 128 CBC Encryption using BounyCastle v1.8.6 .net core, the problem when I tried to encrypt data with length of 16 byte it adds another 16 byte that contains data -padding I guess- . I don't know why it adds this. knowing that default c# implementation doesn't do that

data example in hex format as string 6752b87027fc7728fbe4ec2f0d76da75 => EE93F245FCDB928BF8E3012C9E5150EDA1B876A6D790CFC69C2F129215B3C938

this happended also if the data to encrypt was 32, 64 , 128 and so on

Code:

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

Any ideas how to fix this?


Solution

  • The posted code applies 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, last sentence of the Zero padding section. Another difference between the BC and .NET variants is that the BC variant removes the padding during decryption, while the .NET variant does not.

    This ambivalence is a disadvantage of Zero padding. Another disadvantage is that it is not possible to distinguish between terminating plaintext 0x00 bytes and padding 0x00 bytes, because Zero padding does not contain information about the number of padding bytes.

    Because of this unreliability PKCS7 padding is better: It is sharply defined in RFC 2315 (section 10.3, note 2) (i.e. there are no different variants) and it contains the information about the number of padding bytes so that they can be distinguished from the plaintext bytes.

    BouncyCastle offers no option to choose between different Zero padding variants. It only offers the variant described above. Thus, to use BouncyCastle with the .NET variant, this must be implemented by yourself: First, PaddedBufferedBlockCipher must be replaced by BufferedBlockCipher, which simply means that no (BouncyCastle) padding is used. Second, the .NET variant must be implemented in a corresponding method, which is relatively simple: If the length of the plaintext is not an integer multiple of the block length, padding is done with 0x00 values until this condition is met. The method is then applied to the plaintext before encryption. Since the .NET variant does not remove the Zero padding during decryption, only the first part is needed for decryption.