Encryption Basics in Java

Naveen AnamaneniUpdated · 7 min read

Encryption turns readable data, called plaintext, into unreadable data, called ciphertext, using a key. Only someone with the right key can turn it back, which is decryption. Unlike hashing, encryption is two-way. There are two families. Symmetric encryption uses one secret key for both directions. Asymmetric encryption uses a pair of keys: a public key that anyone may have, and a private key that is kept secret. In Java, both are done with the class javax.crypto.Cipher. In this lesson, you will learn the difference between the two families, encrypt with AES and RSA, and see how real systems combine them.

Symmetric vs Asymmetric

PointSymmetricAsymmetric
KeysOne shared secret keyA public key and a private key
Encrypt withThe secret keyThe receiver's public key
Decrypt withThe same secret keyThe receiver's private key
SpeedVery fastMuch slower
Data sizeAny sizeOnly small amounts
Main problemBoth sides must already share the key safelyNone for sharing: the public key can be published
AlgorithmsAES, ChaCha20RSA, elliptic curves
Used forFiles, databases, network trafficExchanging keys, digital signatures
One shared key, or a public and private pair

The Classes

ClassDescription
CipherIt is used to encrypt and decrypt.
KeyGeneratorIt creates a symmetric key, such as an AES key.
KeyPairGeneratorIt creates a public and private key pair.
SecretKey, PublicKey, PrivateKeyThe key types.
GCMParameterSpecIt carries the initialization vector and tag length for AES-GCM.

A cipher is requested by a transformation string: algorithm/mode/padding, for example AES/GCM/NoPadding.

Example: AES and RSA

Encrypt.java▶ Try it
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import javax.crypto.AEADBadTagException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
 
public class Encrypt {
    public static void main(String[] args) throws Exception {
        byte[] message = "Navika's marks: 91"
            .getBytes(StandardCharsets.UTF_8);
 
        // ---- Symmetric: one secret key, AES in GCM mode ----
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256);
        SecretKey key = keyGen.generateKey();
 
        byte[] iv = new byte[12];
        new SecureRandom().nextBytes(iv);
 
        Cipher aes = Cipher.getInstance("AES/GCM/NoPadding");
        aes.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv));
        byte[] encrypted = aes.doFinal(message);
        System.out.println("AES: " + message.length + " bytes in, "
            + encrypted.length + " bytes out (16 are the tag)");
 
        aes.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv));
        String back = new String(aes.doFinal(encrypted),
            StandardCharsets.UTF_8);
        System.out.println("Decrypted: " + back);
 
        // Change one bit of the encrypted data: decryption refuses it.
        encrypted[0] ^= 1;
        try {
            aes.init(Cipher.DECRYPT_MODE, key,
                new GCMParameterSpec(128, iv));
            aes.doFinal(encrypted);
        } catch (AEADBadTagException e) {
            System.out.println("Tampered data rejected: "
                + e.getClass().getSimpleName());
        }
 
        // ---- Asymmetric: a public key and a private key, RSA ----
        KeyPairGenerator pairGen = KeyPairGenerator.getInstance("RSA");
        pairGen.initialize(2048);
        KeyPair pair = pairGen.generateKeyPair();
 
        Cipher rsa = Cipher.getInstance(
            "RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        rsa.init(Cipher.ENCRYPT_MODE, pair.getPublic());
        byte[] sealed = rsa.doFinal(message);
        System.out.println("RSA: " + sealed.length + " bytes out");
 
        rsa.init(Cipher.DECRYPT_MODE, pair.getPrivate());
        System.out.println("Decrypted with the private key: "
            + new String(rsa.doFinal(sealed), StandardCharsets.UTF_8));
    }
}
Output
AES: 18 bytes in, 34 bytes out (16 are the tag)
Decrypted: Navika's marks: 91
Tampered data rejected: AEADBadTagException
RSA: 256 bytes out
Decrypted with the private key: Navika's marks: 91

Explanation:

  1. A 256-bit AES key is generated with KeyGenerator.
  2. The IV (initialization vector) is 12 random bytes. It makes the same message encrypt differently each time. It isn't secret, and it is stored or sent along with the ciphertext, but it must never be reused with the same key.
  3. AES/GCM/NoPadding is AES in GCM mode. GCM is authenticated encryption: besides hiding the data, it adds a 16-byte tag that detects any change. That is why 18 bytes became 34.
  4. Decryption needs the same key and the same IV.
  5. Tampering: one bit of the ciphertext is flipped. Decryption throws AEADBadTagException instead of returning damaged data. Modes without authentication would silently return garbage.
  6. RSA: a 2048-bit key pair is generated. The message is encrypted with the public key and decrypted with the private key. The output is 256 bytes, the size of the key, however short the message is. OAEP is the secure padding scheme for RSA.

How They Work Together

RSA can only encrypt a small message, and it is slow. AES needs both sides to share a key. Real systems use each for what it does well. This is called hybrid encryption, and it is how HTTPS works:

  1. Generate a random AES key for this message or session.
  2. Encrypt the data with that AES key.
  3. Encrypt the AES key with the receiver's public key (or agree on it with a key exchange).
  4. Send both. The receiver uses the private key to recover the AES key, then decrypts the data.

Choices That Matter

ChoiceUseAvoid
Symmetric algorithmAES with 128 or 256-bit keysDES, 3DES, RC4
AES modeGCMECB, which reveals patterns: equal blocks encrypt to equal blocks
RSA key size2048 bits or more1024 bits
RSA paddingOAEPPKCS#1 v1.5 for new designs, and "no padding"
Keys and IVsFrom SecureRandomFrom Random, from passwords directly, or hard-coded

Cipher.getInstance("AES") alone means AES/ECB/PKCS5Padding, the insecure mode. Always write the full transformation.

Common Mistakes

Using ECB mode, often by writing just "AES". It leaks patterns in the data.

Reusing an IV with the same key in GCM. That breaks its security completely. Generate a fresh random IV for every message.

Hard-coding keys in source code. Anyone with the code has the key. Keep keys in a key store or a secrets manager.

Confusing encoding with encryption. Base64 is not encryption; anyone can decode it.

Encrypting passwords. Passwords should be hashed with a slow function, not encrypted (see "Storing Passwords Safely in Java").

Interview Corner

What is the difference between symmetric and asymmetric encryption?

Symmetric encryption uses the same secret key to encrypt and decrypt; it is fast and suited to large data, but the key must be shared securely. AES is the standard. Asymmetric encryption uses a key pair: data encrypted with the public key can only be decrypted with the private key; it is much slower and limited to small data, but solves key distribution and enables digital signatures. RSA and elliptic-curve algorithms are examples. Systems such as TLS combine both: asymmetric cryptography to establish a shared key, then symmetric encryption for the data.

How do you encrypt data in Java?

With javax.crypto.Cipher. For AES-GCM: create a key with KeyGenerator, generate a random 12-byte IV with SecureRandom, call Cipher.getInstance("AES/GCM/NoPadding"), init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv)) and doFinal(plaintext). Store the IV with the ciphertext. Decryption uses DECRYPT_MODE with the same key and IV and throws AEADBadTagException if the data was altered.

Practice

  1. Easy: Encrypt the same message twice with the same key but two different IVs, and show that the two ciphertexts differ.
  2. Harder: Write encrypt(key, text) that returns the IV followed by the ciphertext in one byte array, and decrypt(key, bytes) that splits them again.

Quick check: Encryption

4 questions
1How many keys does symmetric encryption use?
2In asymmetric encryption, which key decrypts a message sent to you?
3Which AES mode should you choose?
4What must never be reused with the same key in AES-GCM?

Key Takeaways

Was this tutorial helpful?

Lesson 510 of 578