AES/GCM/PKCS5Padding giving issues while AES/CBC/PKCS5Padding works fine for my use case

I have a requirement to read-encypt-save plus its reverse i.e. read-decypt-save files through chunk/block mechanism (single operation not feasible because of huge(GBs) file sizes).

So essentially the two functionalities should work as below :

1. loop (read-plain-text-block-from-external-source -> encrypt -> save-encrypted-text-block-to-external-target)
2. loop (read-encrypted-text-block-from-external-source -> decrypt -> save-plain-text-block-to-external-target)

Also requirement is to have flexibility to use different chunk/block sizes while encryption / decryption. so either party (Encrypter or Decrypter) does not know other's size at all.

Now we have successfully implemented this functionality using AES/CBC/PKCS5Padding but we are facing issues while trying the same using AES/GCM/PKCS5Padding. Decryption was returning blank plain chunks and we finally received aggregated plain chunks at loop completion. this stops us from saving individual decrypted-chunks to external target during single iteration of the loop.

Any idea if AES/GCM/PKCS5Padding is even an option for our use case ? what must be causing above issue ?

• Does your problem similar to this? How to securely encrypt/decrypt data with a maximum chunk size? Mar 25, 2021 at 11:49
• Just a question, what do need padding for in GCM mode? Mar 25, 2021 at 11:59
• Manish, As also pointed by Maarten below, padding is in-fact not needed. So i must rather use AES/GCM/NoPadding. Mar 26, 2021 at 12:24
• kelalaka, checked the other thread as suggested by you. But that solution seems to have one limitation, decryption component should always fetch/process the same individual encrypted chucks which were earlier stored by the encryption component ? mixing parts of chunks will fail the decryption , No ? Mar 26, 2021 at 12:32
• @nirmalsingh you should add @ in front of the names to poke. Decryption only chained to the previous block. Only small amount of memory is needed to keep the value. Mar 27, 2021 at 22:25

2 Answers

AES-GCM uses AES-CTR to create confidentiality internally. Counter mode turns AES into a stream cipher, where the plaintext is XOR'ed with a generated key stream. This key stream can be applied bit by bit or - practically speaking - byte by byte (with the leftover key stream bytes after encrypting the last counter simply being discarded). Specifying any padding at all is a waste of effort for a stream cipher. Instead you should be using "AES/GCM/NoPadding" for Java.

I would not bet that other implementations allow GCM with PKCS#5 padding. Furthermore, it is the question if that mode would always be using no padding (as it isn't required), 1 byte of padding (since a stream cipher works with "blocks" of a single byte) or up to 16 bytes of padding (because the block size of AES is 16 bytes).

GMAC, the internal MAC operation of GCM also requires padding as it operates on 128 bit values. But as common with MAC algorithms, only one particular padding is used, so it doesn't need to be specified - it is not a configuration option. It is not something the user should be concerned about; the padding is not visible (like it is in the size ciphertext when used during encryption).

You didn't say but I'm going to guess you're using Java. Although Java Crypto (JCA) in general supports ciphers (and also digests, MACs, and signatures) with a 'streaming' interface (init then any number of update ended by doFinal), the 'standard' (Oracle/OpenJDK) provider that implements AES-GCM (SunJCE) obeys the requirement implicit in SP800-38D and often stated generally for AEAD that when verification fails none of the plaintext (at least some of which is probably wrong) is returned. To do this it cannot return partial decrypted results for an update call but instead must buffer all the ciphertext until doFinal when it verifies and decrypts all of it.

In which case, neardupe Plain text size limits for AES-GCM mode at 2GB with Sun JCE implementation? (which links to several other related Qs).

If you use the BouncyCastle provider instead, it does not obey this requirement and does return partial results as you wish.

This does pose a danger. Consider a situation where Company X (maybe remote working due to COVID) has a procedure where the CFO approves large payments and then sends them, in a standard form created by their business software and GCM-encrypted, to the bookkeeper to be executed, and has a very large contract with Company Y that is nearly complete, and Company Y being very up to date and fashionable wants to be paid in Bitcoin. Company Y submits its payment request for say the equivalent of 100 million dollars, which is is valid and the CFO approves it and puts it first because of its importance. Attacker, knowing the payment is first, can easily change the ciphertext so it decrypts without verification to the attacker's Bitcoin address instead -- this ia called 'malleability' and is the main reason AEAD modes were developed; there are numerous existing Qs about it you should be able to find easily. Bookkeeper decrypts the first, important payment and pays the 100 million to the attacker, then breaks for lunch; after lunch they finish the decryption and discover the MAC mismatch meaning the data has been changed -- but after one hour Bitcoin is irreversibly gone, and if the attacker is careful, untraceable. Company X still owes the 100 million to Y and can't pay it, so they go bankrupt. Some people wouldn't consider this a good system design.