Syllabus Lesson 81 of 156 · Encryption you can explain
Encryption you can explain

Symmetric and public key

Why it matters Almost every privacy promise you will meet, from the padlock in your address bar to "end-to-end encrypted" chats, is built from two ideas. Once you can explain them in plain words, you can judge those promises yourself instead of taking them on trust.

Imagine passing a note across a classroom. Anyone in between can read it. Encryption is a way of scrambling the note so that only the right person can unscramble it. Everything in this module comes down to one question: who holds the key that unscrambles it?

Encryption: turning readable data (the plaintext) into scrambled data (the ciphertext) using a secret called a key. Decryption turns it back.

Idea 1: symmetric encryption, one shared key

Think of a padlocked box where you and a friend each hold a copy of the same key. You lock the box, post it, and your friend unlocks it with their copy. The same key locks and unlocks. That is symmetric encryption.

Symmetric encryption: encryption where the same secret key is used to encrypt and to decrypt. It is very fast, so it carries almost all real data. The standard one today is AES.

Here is a toy version in Python. The b"..." in front of a string makes it bytes: the text as a row of small numbers from 0 to 255, one per character. The code combines each byte of the message with a byte of the key using XOR, written ^ in Python: it flips the bits of the message wherever the key has a 1, so doing it twice with the same key flips them back. zip walks the two rows side by side, and .hex() prints bytes as hexadecimal digits. Run the same step with the same key and the message comes back.

message = b"hi bob"
key     = b"k3y!9Z"     # shared secret, same length

scrambled = bytes(m ^ k for m, k in zip(message, key))
print(scrambled.hex())     # 035a59435638

unscrambled = bytes(c ^ k for c, k in zip(scrambled, key))
print(unscrambled)         # b'hi bob'

The catch is obvious once you say it aloud: you and your friend must already share the key. How do you get it to them without someone copying it on the way? For two strangers on the internet, such as you and a shop you have never visited, there was no safe way to do that. That is the problem idea 2 solves.

Idea 2: public key, a pair of keys

Now imagine a post box with a slot. Anyone can drop a letter in, but only the owner has the key that opens the back. The slot is the public key: you can hand it to the whole world. The key to the back is the private key: it never leaves the owner.

Public key cryptography: a system where each person has a pair of linked keys. What one key locks, only the other can unlock. You publish one (the public key) and guard the other (the private key). Also called asymmetric cryptography.

A tiny version uses the classic textbook numbers for RSA, one of the first public key systems. The public key is (n, e) = (3233, 17); the private number is d = 2753. These are far too small to be safe and are for learning only.

n, e = 3233, 17   # public: anyone may know these
d = 2753          # private: only the owner

secret = 65                    # a message, written as a number
locked = pow(secret, e, n)     # anyone can do this
print(locked)                  # 2790

print(pow(locked, d, n))       # 65, only the owner can do this

pow(a, b, n) means "a to the power b, then keep only the remainder after dividing by n". Going forward with e is easy for everyone. Going back needs d, and working out d from n and e needs the two secret primes that make up n. With real keys, hundreds of digits long, nobody knows a practical way to do that.

The same pair, run backwards: signatures

Public key systems give a second gift. If the owner uses the private key on a message, anyone can use the public key to check it. Only the owner could have produced it, so it works like a wax seal. This is a digital signature, and you will verify one yourself in lesson 84.

How real systems combine them

You                                        shopa.example
 |  1. public key magic: agree a fresh       |
 |     shared secret, no one in between     |
 |     can work it out                       |
 |-------------------------------------------|
 |  2. symmetric encryption with that        |
 |     secret for every byte after           |
 |==========================================>|

Public key operations are slow, so they are used briefly, to agree a shared secret and to check identities. Then fast symmetric encryption carries the actual data. HTTPS, messaging apps and encrypted backups all follow this pattern.

A common misconception: "the public key is a weak spot because it is public". It is designed to be public. Knowing it lets people lock things for you or check your signatures, never unlock or forge them. The danger is the private key leaking, or someone tricking you into using their public key instead of the real one. That second problem returns in lessons 82 and 83.

In other languages

JavaScript has real, safe encryption built in, called the Web Crypto API. Never write your own for real data; use these.

// JavaScript (browser): a real AES key and encryption
const key = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
const iv = crypto.getRandomValues(new Uint8Array(12));
const data = new TextEncoder().encode("hi bob");
const locked = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, data);
// Go: the toy RSA step with big numbers
locked := new(big.Int).Exp(big.NewInt(65), big.NewInt(17), big.NewInt(3233))
fmt.Println(locked) // 2790

Recap

  • Symmetric encryption: one shared key locks and unlocks. Fast, but the key must be shared safely first.
  • Public key: a public key anyone can use, and a private key only the owner holds.
  • Run backwards, the private key makes signatures that anyone can check with the public key.
  • Real systems use public keys to agree a secret, then symmetric encryption for the data.

Spotted a problem in this lesson? Report it

Code · runs in your browser
Output