How to Encrypt and Decrypt Data using AES in Java
1. Overview
Advanced Encryption Standard (AES) is a symmetric algorithm for encrypting data to improve the security of a system. It is a “symmetric” algorithm because it uses the same key to encrypt and decrypt data.
One of the advantages of using AES is that it is fast to execute with small resource footprint. This means it can be used in systems with high throughput requirements.
For example, a banking application that processes millions of transactions per minute can use AES to encrypt customer data in transit and at rest.
Because AES uses a single key for decryption and encryption, the key should be handled with utmost care and shared via a secure channel.
2. AES Data Encryption
Encrypting data using AES in Java requires the creation of a SecretKey
object to encapsulate the secret key
and the construction of a suitable Cipher
to use in the encryption.
Listing 2.1 AesService.java
|
|
In snippet above, we constructed an instance of the Cipher
class with the following param: AES/GCM/NoPadding
.
AES
is the encryption algorithm of choice and GCM
(Galois/counter) is the mode of operation we preferred.
AES has many modes of operation, and depending on the preferred mode, there is a need for an Initialization Vector (IV).
In cryptography, an Initialization Vector refers to the bits that are used to randomize the encryption process.
This ensures that each encryption operation results in a different cipher text—even if the plain data is the same. Using an IV serves as an additional layer of security that protects against ciphertext pattern attacks.
Because our preferred mode of operation is GCM
, we are required to generate unique, non-repeating, secure bits
for every encryption operation.
This is why we are generating secure random bytes in lines 7–9 and passing it to the GCMParameterSpec
constructor.
We also configure the spec to use a 128-bit authentication tag length.
Authentication tag is used to verify that the resulting ciphertext has not been tampered with during the decryption process.
128-bit is the recommended configuration when using the GCM
mode for AES encryption.
We will need the IV bytes again when we want to decrypt the data, that’s why we prepend it to the actual bytes of the ciphertext, and encode the result to Base64.
The Base64 format choice is simply because it’s easier to transport (especially on the web) and store a String
data type in applications
as opposed to raw bytes.
3. AES Data Decryption
Decrypting data in AES requires using the same cryptographic parameters used in the encryption process and the same key.
Therefore, we will use the same cipher params AES/GCM/NoPadding
to build a Cipher
object. To produce the ciphertext in bytes,
we will decode the data Base64 String data.
Remember that we prepend the IV to the actual cipher text when encrypting?
We will reconstruct the IV by extracting the first 12 bytes of the decoded Base64 data and use it
to construct the GCMParameterSpec
.
Finally, we will extract the actual ciphertext from the decoded base64 data and decrypt it.
The resulting bytes are used to construct a new String
instance - which is the plain data.
Listing 3.1 AesService.java
|
|
We can test the two functions together using a simple JUnit test:
|
|
4. Conclusion
In today’s tutorial, we have learnt about the foundation of encrypting and decrypting sensitive data in Java.
This knowledge provides the right foundation for applying AES encryption in other aspects of software Engineering like encrypting customers’ data or request and responses for a web application.
The complete source code is available on GitHub
Further reading: https://proandroiddev.com/security-best-practices-symmetric-encryption-with-aes-in-java-7616beaaade9
Happy Coding!