Why is calling Cipher.getInstance("AES") (a bare algorithm name) a security pitfall in Java?
answer
- bare name => provider default => AES/ECB/PKCS5Padding
- ECB: equal blocks -> equal ciphertext (penguin)
- no integrity, no IV in ECB
- default is provider/JDK dependent => not portable
- fix: full transformation, prefer AES/GCM/NoPadding
basics
~20 sBecause Java then lets the provider pick the mode and padding for you. On the default JDK it picks ECB mode, which is insecure: identical plaintext blocks become identical ciphertext, leaking data. Always write the full "AES/mode/padding".
solid answer
~40 sWhen you pass only an algorithm name like "AES", you delegate the choice of mode and padding to the installed security provider. On Oracle/OpenJDK the default resolves to AES/ECB/PKCS5Padding, and ECB (Electronic Codebook) is broken for real data: each block is encrypted independently with the same key, so equal plaintext blocks yield equal ciphertext blocks, exposing structure (the classic 'ECB penguin'). It also provides no integrity. Worse, the default is provider- and JDK-version-dependent, so the same code can behave differently across environments, breaking interoperability and audits. The remedy is to always specify the complete transformation — ideally an authenticated mode, AES/GCM/NoPadding — so the chosen mode and padding are explicit, deterministic, reviewable, and consistent across deployments. Static analysis tools flag bare names precisely because of this hidden, unsafe default.
code
java · 12 lines// Pitfall: resolves to AES/ECB/PKCS5Padding on SunJCE
Cipher insecure = Cipher.getInstance("AES");
// Demonstrates the ECB weakness: identical 16-byte blocks repeat
byte[] block = new byte[16]; // all zeros, one AES block
byte[] twoBlocks = new byte[32]; // two identical zero blocks
insecure.init(Cipher.ENCRYPT_MODE, key);
byte[] ct = insecure.doFinal(twoBlocks);
// In ECB, ct[0..15] == ct[16..31] -> structure leaks
// Fix:
Cipher secure = Cipher.getInstance("AES/GCM/NoPadding");go deeper
Knows you should write the full transformation and that "AES" alone is discouraged.
Can explain that the bare name resolves to ECB by default and why ECB leaks data.
Articulates provider/JDK dependence, interop and audit risks, and recommends AES/GCM/NoPadding plus static-analysis enforcement.
Drives crypto-agility (centralized transformations, approved-algorithm policy), reasons about FIPS/provider portability, and bans bare names in CI.
## The mechanism: what a bare name does `Cipher.getInstance(String)` accepts either a full transformation (`algorithm/mode/padding`) or just an `algorithm`. When only the algorithm is given, the **JCA (Java Cryptography Architecture)** asks the security **provider** to supply its *default* mode and padding for that algorithm. A provider is a pluggable implementation of crypto services (the built-in SunJCE, BouncyCastle, a FIPS module, etc.). Each may define its own defaults. For `AES` on the standard SunJCE provider, that default is **`AES/ECB/PKCS5Padding`**. ## Why ECB is the problem **ECB (Electronic Codebook)** is the simplest block-cipher mode: split the plaintext into 16-byte blocks and encrypt each block independently with the same key, no chaining, no IV. The fatal property is **determinism per block**: the same 16 plaintext bytes always encrypt to the same 16 ciphertext bytes. So: - Repeated structure in the plaintext (headers, fixed fields, images) is visible in the ciphertext — the famous *'ECB penguin'* image, where an encrypted bitmap still shows the penguin outline. - An attacker can detect equality, splice/rearrange blocks, and replay them, because there is no chaining and no authentication tag. ECB provides **confidentiality only in the weakest sense and no integrity at all**. It is essentially never the right choice for application data. ## Why the *default* nature makes it worse Three compounding issues: 1. **Invisible decision.** The dangerous mode never appears in your source, so a reviewer reading `getInstance("AES")` cannot see that ECB was selected. 2. **Provider/version dependence.** Because the default comes from the provider, swapping providers (e.g., installing BouncyCastle, or running on a FIPS-validated provider) or upgrading the JDK can silently change the mode or padding. Code that 'worked' may produce incompatible ciphertext or change its security properties. 3. **Interoperability breakage.** Two services that both say `"AES"` but run different providers may not be able to decrypt each other's data. ## The fix Always write the full transformation. Prefer an **AEAD** mode that also authenticates: ```java Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); ``` If you must use CBC (e.g., interop with a legacy system), specify it explicitly *and* add a separate MAC (HMAC) for integrity — but new code should default to GCM. The general rule: **never let the provider choose your mode or padding.** ## How this is enforced in practice - **Static analysis:** SpotBugs (`CIPHER_INTEGRITY`, `ECB_MODE`), SonarQube rule S5542, and Google error-prone all flag bare algorithm names and explicit ECB. - **Code review checklists** treat `getInstance("AES")` as a blocker. - **Crypto-agility:** centralize transformation strings in one constant/helper so the whole codebase uses the approved, full transformation. With this, anyone can explain *what* happens (provider supplies ECB default), *why it's bad* (block-level determinism, no integrity, environment-dependent), and *how to fix it* (full transformation, prefer AES/GCM/NoPadding).
- If ECB is so bad, why does the JDK still default to it?Largely historical/backward compatibility — ECB was the original 'no mode' behavior. The JDK keeps it for compatibility but documentation and tooling now strongly steer you to always specify a secure full transformation.
- Is CBC an acceptable replacement for the bare-name default?CBC is far better than ECB but still lacks integrity. Use AES/GCM/NoPadding for authenticated encryption; if CBC is required for interop, pair it with a separate HMAC (encrypt-then-MAC).
Saying just "AES" is like handing a contractor 'build me a wall' with no spec — they default to the cheapest method (ECB), and you only find out it's see-through after it's built.
saying these in an interview costs you the question
- Claiming "AES" is safe because the algorithm is strong — the broken default mode (ECB) is the issue
- Thinking the default is the same everywhere — it depends on the provider and JDK
- Assuming ECB just lacks an IV but is otherwise fine — it leaks block equality and has no integrity
- Replacing ECB with CBC and calling it 'secure' without adding integrity