Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
The Caesar cipher is the oldest encryption scheme we still teach, and it earns that spot not because it works but because of how spectacularly it fails. A shift cipher has exactly 25 non-trivial keys, so an attacker can try them all by hand in under a minute. The lesson modern cryptography takes from this is Kerckhoffs's principle: security must rest on the secrecy of the key, not the algorithm, and the key space must be so large that brute force is infeasible. Generalising Caesar to an arbitrary substitution gives a 26! key space (about 4 x 10^26), which seems strong until you realise that the cipher leaks the structure of the language — a lesson that returns in every cipher we will study. Understanding why both small key spaces and structure-preserving ciphers fail is the foundation for understanding what AES, RSA, and elliptic curves are designed to defend against.
A Caesar shift maps each letter to the letter k positions later in the alphabet, modulo 26. The encryption and decryption are inverse functions of the same family.
// main.go
package main
import (
"fmt"
"strings"
"unicode"
)
func caesarEncrypt(plaintext string, k int) string {
var out strings.Builder
for _, ch := range strings.ToUpper(plaintext) {
if unicode.IsLetter(ch) {
shifted := rune((int(ch-'A')+k%26+26)%26) + 'A'
out.WriteRune(shifted)
} else {
out.WriteRune(ch)
}
}
return out.String()
}
func caesarDecrypt(ciphertext string, k int) string {
return caesarEncrypt(ciphertext, -k)
}
func caesarBruteForce(ciphertext string) [][2]string {
results := make([][2]string, 26)
for k := 0; k < 26; k++ {
results[k] = [2]string{fmt.Sprintf("%d", k), caesarDecrypt(ciphertext, k)}
}
return results
}
func main() {
ct := caesarEncrypt("ATTACK AT DAWN", 3)
fmt.Println(ct) // DWWDFN DW GDZQ
for k, pair := range caesarBruteForce(ct) {
fmt.Printf("k=%2d: %s\n", k, pair[1])
}
}
go run main.go