Cipher ciph = Cipher.getInstance("AES");
SecretKeySpec AESkeySpec = new SecretKeySpec(keyPass, "AES");
ciph.init(ENCRYPT_MODE,AESkeySpec);
//ciph.update(s.getBytes());
byte[] encryptedData = ciph.doFinal(s.getBytes());
return encryptedData;
I will get expected output like: long long long long long long long long long long long string
Why does it happen like that?
–
–
The update
method returns encrypted block. But as I see you take the ciphertext only from doFinal
. You supposed to use all blocks from update
and from the doFinal
for completed encrypted stream of blocks.
Note: you are using ECB mode, it means each block encrypted independently, it is less secure and should be used only if you know what are you doing. That's why you are able to decrypt the last block (16 bytes for AES) and see truncated plaintext. More info: http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
For ECB and CBC modes of operation, each block (128 bits or 16 bytes for AES) of plaintext or will be encrypted once it is available. Furthermore, your example uses PKCS#7 padding (or, in Java, "PKCS5Padding"
) to make sure that the last plaintext is padded to a full block. Otherwise you would not be able to encrypt it.
When you encrypt it is obviously not a good idea to buffer all the resulting ciphertext. So update
will simply return all blocks it can encrypt. Therefore you will always get a multiple of the blocksize back. That means that it may keep part of a block in an internal buffer. Of course, once you add enough bytes for a full block it will encrypt and return the data. All this means that the update may return up to blocksize - 1
bytes more or less than the input. For smaller input it may not return anything at all - everything is buffered until the block is full.
Now PKCS#7 padding is always applied, adding 1 to blocksize bytes. Obviously the cipher must know if more bytes are to be expected, or if the end of the plaintext is reached, before it applies the padding. So doFinal
will return at least one block, even if no data is presented to it. If the previous updates did not return any data, then the doFinal()
method will return the entire ciphertext.
More or less the same reasoning can be performed for decryption. Also note the getOutputSize(int inputLength)
and the getBlockSize()
methods of Cipher
. If you want to receive all the data back at once, you can use a stream cipher mode of operation, such as "AES/CTR/NoPadding"
, which has a block size of 1 byte.
Although this should explain the actual issue, the question you asked was "Does it have some maximum length of data it can update?". The answer is that the update is only limited by the amount of memory available in the JVM and the size of byte arrays in Java.
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.