skip to content

Cipher API: Symmetric (AES)

Symmetric encryption through Cipher and AES: choosing a transformation, initializing with a SecretKey and an IV or GCM parameter spec, and handling the authentication tag. Interviewers ask about IV uniqueness and why AES/GCM is preferred over AES/CBC.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

How do you create a Cipher for AES in Java, and what does the transformation string passed to Cipher.getInstance mean?

level: juniorimportance: must knowfreq 70%

answer

  1. algorithm/mode/padding
  2. AES/GCM/NoPadding is the safe default
  3. Bare "AES" silently means ECB
  4. ECB leaks repeated blocks — never use
  5. CBC needs PKCS5Padding, GCM needs NoPadding

basics

~10 s

You call Cipher.getInstance with a transformation string like "AES/GCM/NoPadding". It has three parts: the algorithm (AES), the mode (how blocks are chained, e.g. GCM or CBC), and the padding (e.g. PKCS5Padding or NoPadding).

solid answer

~40 s

Cipher.getInstance(transformation) returns a Cipher engine for a given algorithm/mode/padding combination. The string is "algorithm/mode/padding", e.g. "AES/GCM/NoPadding" or "AES/CBC/PKCS5Padding". The algorithm is the block cipher (AES). The mode tells the cipher how to process multiple blocks: ECB encrypts each block independently (insecure, never use), CBC chains blocks with an IV, GCM is authenticated. Padding fills the final partial block to the 16-byte AES block size; CBC needs PKCS5Padding, while stream-like and authenticated modes (CTR, GCM) use NoPadding. If you pass only "AES", the provider silently defaults to the dangerous "AES/ECB/PKCS5Padding", so always specify all three parts explicitly. getInstance can throw NoSuchAlgorithmException / NoSuchPaddingException for unknown combinations.

code

java · 8 lines
java
// Safe: fully specified, authenticated mode
Cipher gcm = Cipher.getInstance("AES/GCM/NoPadding");

// Legacy block mode (no integrity) — needs padding
Cipher cbc = Cipher.getInstance("AES/CBC/PKCS5Padding");

// DANGEROUS: silently becomes AES/ECB/PKCS5Padding
Cipher bad = Cipher.getInstance("AES");

go deeper

for a junior

Knows the transformation is algorithm/mode/padding and that AES/GCM/NoPadding is a good default.

for a middle

Explains why ECB is dangerous, knows which padding each mode needs, and that bare "AES" defaults to ECB.

for a senior

Discusses provider selection, getInstance exceptions, statefulness/thread-safety, and chooses GCM over CBC with justification.

for a principal

Reasons about provider/algorithm policy across a codebase, mandates a hardened helper that forbids ECB, and weighs FIPS/provider constraints.

## What a Cipher is A **cipher** is an algorithm that turns readable data (**plaintext**) into scrambled data (**ciphertext**) and back, using a **key** (a secret value). In Java, `javax.crypto.Cipher` is the single class that performs both directions for many algorithms; it is part of the **JCA/JCE** (Java Cryptography Architecture / Extension), the standard crypto framework. **Symmetric** crypto means the *same* key both encrypts and decrypts (contrast with asymmetric/public-key, which uses a key pair). **AES** (Advanced Encryption Standard) is the dominant symmetric cipher, with key sizes of 128, 192, or 256 bits. ## The transformation string You don't construct a `Cipher` directly; you ask a factory: ```java Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); ``` The argument is a **transformation** of the form `"algorithm/mode/padding"` (or just `"algorithm"`). Three parts: 1. **Algorithm** — the cipher itself, here `AES`. AES is a **block cipher**: it transforms a fixed 16-byte (128-bit) block at a time. 2. **Mode of operation** — how the cipher applies that one-block transformation across a message longer than 16 bytes: - **ECB** (Electronic Codebook): each block encrypted independently. Identical plaintext blocks produce identical ciphertext blocks, leaking structure. **Never use it.** - **CBC** (Cipher Block Chaining): each block is XORed with the previous ciphertext block before encryption, seeded by an **IV** (initialization vector, a random per-message value). Hides patterns but provides no integrity. - **CTR** (Counter): turns the block cipher into a stream cipher by encrypting a counter; needs no padding. - **GCM** (Galois/Counter Mode): CTR plus an **authentication tag** — it both encrypts *and* detects tampering (**authenticated encryption**). The modern default. 3. **Padding** — block modes need the final partial block filled to 16 bytes. `PKCS5Padding` is the standard scheme for CBC/ECB. Stream-like modes (CTR, GCM) need `NoPadding` because they don't operate on whole blocks. ## The dangerous default If you write `Cipher.getInstance("AES")`, the JDK does **not** error — it silently picks `"AES/ECB/PKCS5Padding"`. ECB is insecure, so always pass the full three-part string. Prefer `"AES/GCM/NoPadding"` unless you have a specific reason for CBC. ## Exceptions `getInstance` throws **`NoSuchAlgorithmException`** if no installed **provider** supplies the algorithm/mode, and **`NoSuchPaddingException`** for an unknown padding. A `Cipher` instance is **not thread-safe** and is **stateful** (you reuse it only after re-`init`).

  • Why is ECB mode insecure?
    ECB encrypts each 16-byte block independently with no IV, so identical plaintext blocks produce identical ciphertext. This leaks the data's structure (the classic 'ECB penguin' image stays recognizable) and reveals repetition to an attacker.
  • What's the difference between NoSuchAlgorithmException and NoSuchPaddingException?
    NoSuchAlgorithmException means no installed provider supplies the requested algorithm/mode; NoSuchPaddingException means the algorithm exists but the named padding scheme isn't available for it.

saying these in an interview costs you the question

  • Calling Cipher.getInstance("AES") and assuming it's safe — it defaults to ECB
  • Thinking the mode is optional or cosmetic
  • Reusing one Cipher instance across threads (it is stateful and not thread-safe)

context

open as a page

How do you initialize a Cipher for encryption with a raw AES key, and what is SecretKeySpec used for?

level: middleimportance: must knowfreq 65%

basics

~20 s

After getInstance you call cipher.init(Cipher.ENCRYPT_MODE, key, params). The key is a SecretKey; SecretKeySpec wraps raw bytes (like a 16- or 32-byte array) into a SecretKey for AES. For decryption you use Cipher.DECRYPT_MODE with the same key.

open as a page

How do you perform authenticated encryption with AES-GCM in Java, and how is the authentication tag handled on encrypt and decrypt?

level: seniorimportance: must knowfreq 60%

basics

~20 s

Use "AES/GCM/NoPadding" with a GCMParameterSpec that sets the tag length (usually 128 bits) and a unique 12-byte nonce. On encrypt, doFinal appends the authentication tag to the ciphertext automatically. On decrypt, doFinal verifies the tag and throws AEADBadTagException if the data was tampered with.

open as a page

What is the difference between Cipher.update and Cipher.doFinal, and when do you use each?

level: middleimportance: should knowfreq 45%

basics

~20 s

update feeds part of the data into the cipher and may return some processed bytes, but it doesn't finish the operation. doFinal processes the last chunk, applies padding (or the GCM tag), and completes. For small data you just call doFinal once.

open as a page

When choosing between AES-CBC and AES-GCM in Java, what are the trade-offs, and what must you add to CBC to make it safe?

level: seniorimportance: should knowfreq 40%

basics

~20 s

GCM gives encryption plus built-in integrity in one step and is the default choice. CBC only encrypts — it has no integrity check — so by itself it is vulnerable to tampering and padding-oracle attacks. If you must use CBC, you have to add a separate MAC (encrypt-then-MAC). Both need a unique IV per message.

open as a page