DevKnightUtils logo
What Is AES Encryption and Why Every Developer Should Know It
securityencryptiontutorial

What Is AES Encryption and Why Every Developer Should Know It

Learn how AES encryption works, the difference between AES-128 and AES-256, operation modes, and how to use it in JavaScript with the Web Crypto API.


Is Your Data Really Protected?

Every time you store a password, send a message, or save a file to the cloud, you're trusting that someone encrypted that data correctly. But what does "encrypted correctly" actually mean? In most cases, the answer involves three letters: AES.

AES (Advanced Encryption Standard) is the most widely used symmetric encryption algorithm in the world. It protects your banking apps, your VPN traffic, your HTTPS connections, and probably the hard drive on your laptop. If you're a developer and you don't know how it works, you're flying blind every time you touch anything security-related.

This article explains AES from the ground up — how it works, which variant to choose, what modes of operation mean, and how to use it in real JavaScript code.

What Is AES?

AES is a symmetric block cipher. "Symmetric" means the same key is used to encrypt and decrypt data. "Block cipher" means it processes data in fixed-size chunks (blocks of 128 bits) rather than one bit at a time.

It was established as a federal standard by NIST in 2001, replacing the older DES algorithm. Unlike DES, AES has never been cracked with a practical attack. When implemented correctly, it's considered unbreakable with today's computing power.

AES-128, AES-192, and AES-256

The number refers to the key length in bits:

  • AES-128: 128-bit key. Fast, secure for almost all use cases.
  • AES-192: 192-bit key. Rarely used in practice.
  • AES-256: 256-bit key. Slightly slower, considered quantum-resistant, required by some compliance standards (HIPAA, PCI-DSS).

For most web applications, AES-256 is the recommended choice — the performance difference is negligible and the extra security margin is worth it.

Operation Modes: This Is Where Developers Make Mistakes

AES encrypts 128-bit blocks. But real data is rarely exactly 128 bits. Operation modes define how AES handles data that spans multiple blocks — and choosing the wrong one can completely break your security.

ECB — Never Use This

ECB (Electronic Codebook) encrypts each block independently with the same key. The result? Identical plaintext blocks produce identical ciphertext blocks. This leaks patterns in your data. The famous ECB penguin illustrates this perfectly: encrypting an image with ECB still reveals the shape of the original.

⚠️ Warning: Never use ECB mode for real data. It is fundamentally insecure.

CBC — Common but Requires Care

CBC (Cipher Block Chaining) XORs each plaintext block with the previous ciphertext block before encrypting. This eliminates the pattern problem. It requires a random IV (Initialization Vector) that must be unique for every encryption operation and stored alongside the ciphertext.

CBC is widely supported but requires you to handle padding (since data must fit into 128-bit blocks) and is vulnerable to padding oracle attacks if error handling is not done carefully.

GCM — The Modern Standard

GCM (Galois/Counter Mode) is the mode you should default to in new projects. It provides:

  • Authenticated encryption: it detects if the ciphertext was tampered with (no separate HMAC needed).
  • No padding required: operates as a stream cipher internally.
  • High performance: parallelizable, hardware-accelerated on modern CPUs.

AES-256-GCM is what TLS 1.3 uses. It's what you should use too.

AES-256-GCM in JavaScript: Real Code Example

The Web Crypto API is built into every modern browser and Node.js. No external libraries needed.

// Encrypt
async function encrypt(plaintext, password) {
  const enc = new TextEncoder();
  const keyMaterial = await crypto.subtle.importKey(
    "raw", enc.encode(password), "PBKDF2", false, ["deriveKey"]
  );
  const salt = crypto.getRandomValues(new Uint8Array(16));
  const key = await crypto.subtle.deriveKey(
    { name: "PBKDF2", salt, iterations: 100000, hash: "SHA-256" },
    keyMaterial,
    { name: "AES-GCM", length: 256 },
    false,
    ["encrypt"]
  );
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const ciphertext = await crypto.subtle.encrypt(
    { name: "AES-GCM", iv },
    key,
    enc.encode(plaintext)
  );
  // Return salt + iv + ciphertext as base64
  const combined = new Uint8Array([...salt, ...iv, ...new Uint8Array(ciphertext)]);
  return btoa(String.fromCharCode(...combined));
}

// Decrypt
async function decrypt(base64Data, password) {
  const enc = new TextEncoder();
  const dec = new TextDecoder();
  const combined = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0));
  const salt = combined.slice(0, 16);
  const iv = combined.slice(16, 28);
  const ciphertext = combined.slice(28);
  const keyMaterial = await crypto.subtle.importKey(
    "raw", enc.encode(password), "PBKDF2", false, ["deriveKey"]
  );
  const key = await crypto.subtle.deriveKey(
    { name: "PBKDF2", salt, iterations: 100000, hash: "SHA-256" },
    keyMaterial,
    { name: "AES-GCM", length: 256 },
    false,
    ["decrypt"]
  );
  const plaintext = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, ciphertext);
  return dec.decode(plaintext);
}

A few things to note in this example:

  • The password is derived into a proper key using PBKDF2 — never use a raw password string as a key.
  • The salt and iv are randomly generated on every encryption and stored with the ciphertext — this is mandatory.
  • The iv for AES-GCM should be 12 bytes (96 bits) — this is the recommended size.

Resources

Other Crypto Tools on DevKnightUtils

While you implement AES in your own code, you can use DevKnightUtils' free Hash Generator to quickly compute SHA-256, SHA-512, MD5 and other cryptographic hashes — all in your browser, nothing sent to a server.

Try the Hash Generator on DevKnightUtils →

Understanding AES is one of those foundational skills that pays dividends every time you touch anything security-related. Choose AES-256-GCM, generate random IVs, derive keys with PBKDF2, and you'll be ahead of the vast majority of developers out there.

We use Google AdSense and Google Analytics cookies to show relevant ads and collect usage statistics. You can accept or reject non-essential cookies. Read our Privacy Policy for more information.