Part I: Secrets · Chapter 1

Symmetric encryption: one shared key

In one sentence

Symmetric encryption scrambles data with one secret key, and only someone who holds that same key can turn the scrambled data back into readable text.

Who is this for

Level: Beginner

On this page
  1. The idea
  2. How it really works
  3. At work
  4. Common mistakes
  5. Why it matters to the business
  6. Check yourself
  7. Go deeper

The idea

  • Beginner

When you send a message over the internet, it does not travel straight to your friend. It passes through many computers on the way: your Wi-Fi router, your internet provider, data centres, and the other person’s provider. Any of them could copy it. You cannot stop people copying it. You can only make the copy useless to them.

That is what encryption does. It takes readable text, called plaintext, and scrambles it into nonsense, called ciphertext. Turning the nonsense back into readable text is called decryption.

The scrambling is controlled by a secret key. A key is not a password you remember. It is a long random number, usually written as a string of letters and digits, for example:

2756673dc44d7e786bd515a25b952597e29c9f4cd9e9a79ccee8cb82f231b28f

In symmetric encryption, the same key does both jobs. You encrypt with key K, and the person you write to decrypts with the same key K. “Symmetric” means the two sides are the same.

Three things follow from that.

  • The method is public. The key is the secret. Everyone knows how the scrambling works. That is fine, because without the key the ciphertext stays scrambled.
  • The key must be long and random. Someone without the key could try every possible key, one after another. This is called brute force. A key with two digits has only 100 possible values, so a computer finds it at once. A 256-bit key has about 10⁷⁷ possible values, far more than the number of atoms in the Earth (about 10⁵⁰). Nobody can try them all.
  • Encryption does not stop copying. A spy can still copy your ciphertext, keep it and pass it on. Encryption only makes sure the copy tells them nothing, as long as the key stays secret.
Symmetric encryption: the same key K encrypts and decrypts Rosa plaintext Three ships sail… The network ciphertext q8Zt1V0m3kQ2… The harbour plaintext ✓ Three ships sail… key K encrypts same key K decrypts Eve copies it ✗ cannot read it
One secret key on both ends. Anyone on the way can copy the ciphertext, but only a holder of key K can read it.

How it really works

  • Developer
  • Expert

What is a symmetric cipher, exactly?

A cipher is the algorithm that encrypts and decrypts. Today almost everything uses the Advanced Encryption Standard (AES), defined by NIST in FIPS 197. AES is a block cipher: it scrambles one block of 128 bits (16 bytes) at a time, under a key of 128, 192 or 256 bits. The three versions are called AES-128, AES-192 and AES-256.

The other common choice is ChaCha20, a stream cipher from RFC 8439. It is fast on phones and small devices that have no AES hardware.

A block cipher alone only scrambles 16 bytes. To encrypt a real message you need a mode of operation that says how to chain the blocks together. The oldest mode, ECB, encrypts each block separately, so identical blocks of plaintext give identical blocks of ciphertext. Patterns leak through. Never use it.

Why is scrambling not enough?

Encryption hides the content, but on its own it does not stop someone changing the ciphertext on the way. With some older modes, an attacker can flip bits in the ciphertext and cause predictable changes in the decrypted text, without ever knowing the key.

Modern systems therefore use authenticated encryption with associated data (AEAD). The interface is defined in RFC 5116:

  • Inputs to encrypt: the key, a nonce (a number used once), the plaintext, and optional “associated data” that is protected but not hidden, such as a header.
  • Output: the ciphertext plus an authentication tag.
  • Decryption: either returns the exact plaintext, or fails with an error. If the key is wrong, or one bit of the ciphertext, tag, nonce or associated data has changed, you get no plaintext at all.

The two AEADs you will meet most are AES-GCM (NIST SP 800-38D) and ChaCha20-Poly1305 (RFC 8439).

What does AES-256-GCM look like in bytes?

Part Size Secret?
Key 32 bytes (256 bits) Yes
Nonce (also called IV) 12 bytes (96 bits) No, but it must never repeat under the same key
Ciphertext Same length as the plaintext No
Authentication tag 16 bytes (128 bits) No

So the 25-byte message “Three ships sail at dawn.” becomes 41 bytes of ciphertext and tag, and the sender also sends the 12-byte nonce.

Why must a nonce never repeat?

SP 800-38D recommends 96-bit IVs (section 5.2.1.1) and states the rule plainly in section 8: the chance of ever using the same IV twice with the same key must be no greater than 2⁻³². NIST adds that this requirement is “almost as important as the secrecy of the key”. If a nonce repeats under one key, GCM loses its protection against forged messages, and the two ciphertexts leak information about each other.

There are two safe ways to choose nonces:

  • A counter. Never repeats, as long as you never reset it. TLS 1.3 does this: each record’s nonce is the record’s 64-bit sequence number combined (by XOR) with a secret IV that both sides derive during the handshake (RFC 9846, section 5.3).
  • Random 96-bit values. Simple, but section 8.3 of SP 800-38D then limits you to 2³² encryptions per key. After that, change the key.

How long does a key need to be?

Every extra bit doubles the number of possible keys. A 128-bit key has 2¹²⁸ possible values, about 3.4 × 10³⁸. A 256-bit key has about 1.2 × 10⁷⁷. Trying them all is not feasible with any computer we know how to build.

Key lengths only compare within one algorithm. NIST’s SP 800-57 Part 1 (Table 2) rates AES-128 at 128 bits of security, the same as a 3,072-bit RSA key or a 256-bit elliptic-curve key. A “256-bit key” means very different things for AES and for RSA.

Real failures almost never come from guessing a properly random key. They come from:

  • keys made from a password or a timestamp instead of a secure random generator;
  • repeated nonces;
  • keys that leak: in source code, logs, backups or a laptop that was lost.

If you must start from a password, use a key derivation function made for passwords, such as PBKDF2 (NIST SP 800-132) or Argon2 (RFC 9106). They make each guess slow.

Where is symmetric encryption used?

Almost everywhere data is protected in bulk, because it is fast. Most modern processors have AES instructions built in.

  • HTTPS. TLS 1.3 (RFC 9846) protects every record with an AEAD. Every TLS 1.3 implementation must support TLS_AES_128_GCM_SHA256 and should support TLS_AES_256_GCM_SHA384 and TLS_CHACHA20_POLY1305_SHA256 (section 9.1).
  • Disk and file encryption on laptops and phones, and encrypted backups and databases.
  • Wi-Fi, VPNs and messaging apps.

In all of these, the symmetric key itself is set up by a different mechanism first. In HTTPS, a fresh key is agreed for every connection, as the chapter on key exchange explains. Symmetric encryption does the heavy lifting; other tools solve the problem of getting the key to both sides.

At work

  • Developer
  • IT ops

Make a key

A symmetric key is just random bytes from a secure random generator. OpenSSL prints 32 random bytes, the size of an AES-256 key, like this:

openssl rand -hex 32
2756673dc44d7e786bd515a25b952597e29c9f4cd9e9a79ccee8cb82f231b28f

Use openssl rand -base64 32 if a configuration file wants Base64. Treat the output like a password: never paste a real key into a chat, a ticket or a Git repository. Store it in a secrets manager or a key vault.

See the symmetric cipher in a real HTTPS connection

Every HTTPS connection uses a symmetric cipher for the actual data. You can see which one with openssl s_client (output from OpenSSL 3.2 against www.rfc-editor.org):

openssl s_client -connect www.rfc-editor.org:443 -servername www.rfc-editor.org -brief < /dev/null
CONNECTION ESTABLISHED
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Peer certificate: CN=rfc-editor.org
Hash used: SHA256
Signature type: ECDSA
Verification: OK
Server Temp Key: X25519, 253 bits

Read it like this:

  • Ciphersuite: TLS_AES_256_GCM_SHA384 is the symmetric part: AES-256 in GCM mode protects every byte of the page. SHA-384 is used to derive the keys.
  • Server Temp Key: X25519 is how the two sides agreed the secret that the AES keys are derived from, without ever sending it. That is the subject of key exchange.
  • Signature type: ECDSA is how the server proved who it is. See digital signatures.

Use a library, not the enc command, for authenticated encryption

openssl enc looks like the obvious tool, but it does not support authenticated modes:

openssl enc -aes-256-gcm -pbkdf2 -in notes.txt -out notes.enc
enc: AEAD ciphers not supported

The OpenSSL documentation says enc “does not support authenticated encryption modes like CCM and GCM, and will not support such modes in the future”. The modes it does offer, such as CBC and CTR, do not detect tampering. In code, use AES-GCM or ChaCha20-Poly1305 from a well-reviewed library. This is the Web Crypto API, which works the same in browsers and in Node.js:

const key = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
const iv = crypto.getRandomValues(new Uint8Array(12));   // 96-bit nonce, never reused with this key
const data = new TextEncoder().encode("Three ships sail at dawn.");
const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, data);
console.log(data.length, "bytes in,", ct.byteLength, "bytes out (ciphertext + 16-byte tag)");
const pt = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, ct);
console.log(new TextDecoder().decode(pt));
25 bytes in, 41 bytes out (ciphertext + 16-byte tag)
Three ships sail at dawn.

When we changed one bit of the ciphertext, or decrypted with a different key, decrypt threw OperationError and returned nothing. That is AEAD doing its job: a wrong key never gives you “nearly right” text.

How fast is it?

On the laptop used to write this page, one processor core encrypted with AES-256-GCM at about 3.6 GB per second:

openssl speed -evp aes-256-gcm -seconds 1 -bytes 16384
The 'numbers' are in 1000s of bytes per second processed.
type          16384 bytes
AES-256-GCM    3652698.11k

Your numbers will differ, but the point holds: encryption is rarely the reason a system is slow. Turn it on.

What goes wrong in real systems

  • A fixed or reused nonce. A hard-coded IV, or a counter that resets after a restart, breaks AES-GCM. Let the library generate nonces, or use a counter stored safely.
  • Keys in the wrong place. Keys in source code, container images, environment dumps or log files are the most common leak. Keep them in a key vault or an HSM (see guarding the keys).
  • One key for everything, forever. Give each system and each purpose its own key, and plan how to rotate it. If a key leaks, everything it ever protected is exposed, including old copies someone recorded earlier.

Common mistakes

  • “Encrypted means locked away, so nobody can get it.” Encryption does not stop anyone copying the data. It makes the copy unreadable without the key. Access control and encryption are different tools.
  • “If I can decrypt it, it must come from my partner.” Everyone who holds a shared key can encrypt with it. An AEAD tag shows that a key holder made the message, not which one. Proving who wrote something needs a digital signature.
  • “A bigger key number is always stronger.” Only within the same algorithm. AES-128 is far stronger than a 1,024-bit RSA key. Compare security levels, not raw bit counts.
  • “My password is my key.” Human passwords are short and guessable. Turn a password into a key only with a password-based key derivation function such as PBKDF2 or Argon2.
  • “The nonce is public, so it does not matter.” It is public, but it must never repeat under the same key. Reuse breaks AES-GCM.
  • “Hashing is a kind of encryption.” A hash has no key and cannot be reversed. See hashes and fingerprints.

Why it matters to the business

  • Leader

Check yourself

Check yourself

Rosa encrypts her orders with AES-GCM using key K1. The harbour holds a different key, K2, and tries to decrypt. What happens?

  1. The harbour reads the orders, because AES is a public standard
  2. Decryption fails and the harbour gets no plaintext
  3. The harbour sees the orders with a few letters scrambled
Show answer

Answer B Decryption fails and the harbour gets no plaintext

Check yourself

Eve, a spy on the network, copies all of Rosa's encrypted orders and keeps them. Rosa used AES-256-GCM with a random key that only she and the harbour hold. What has Eve gained?

  1. The orders, because she has a full copy
  2. Nothing readable, as long as the key stays secret
  3. The key, because it travels inside the ciphertext
Show answer

Answer B Nothing readable, as long as the key stays secret

Check yourself

A developer encrypts every database row with AES-256-GCM, one key, and the same hard-coded 12-byte nonce for every row. What is the problem?

  1. Nothing; AES-256 is strong enough to cover it
  2. The nonce repeats under the same key, which breaks the protection GCM gives
  3. The key should be 512 bits long
Show answer

Answer B The nonce repeats under the same key, which breaks the protection GCM gives

Go deeper

Play itLevel 1: The secret keyHarbour Post Office, Keystone. Play now

Short on time? The crash course covers this chapter and the next in Lesson 1: Secrets and the sharing problem.

Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.

Last reviewed Edition 0.9