160 / 163 · C11 · 8 min
Cryptography
An operating system cannot protect data after it leaves the hardware the kernel actually controls. Cryptography uses a key to turn plaintext into ciphertext so that later possession of the bits still yields neither meaning nor useful alteration. This chapter presents the symmetric-encryption model, the decisive role of key secrecy, and how a hash supplies integrity checking.
In this lesson
When the Kernel Cannot Reach the Data
Access-control lists apply only to objects the kernel currently manages. Once a USB stick is stolen, a packet is sniffed, or another host’s memory is dumped, those policies no longer exist. Data must therefore be transformed in advance into a form that remains worthless even when every bit is later obtained; that transformation is the job of cryptography.
Plaintext, Ciphertext and Deterministic Maps
Readable data is called plaintext P. An encryption algorithm E together with a key K yields ciphertext C. The matching decryption algorithm D, given the same key, recovers P. Both maps must be deterministic, and recovering P from C without K must be computationally infeasible. It is conventional to treat P as the message we wish to send and C as the protected copy that travels in the open.
Algorithms May Be Public; Keys Must Stay Secret
Inventing a cipher free of structural weaknesses is extremely hard, so real systems almost always adopt a few thoroughly analysed public standards. Consequently the entire security argument collapses onto the key: anyone who learns K can decrypt. Keeping that key secret in a running system is far harder than writing the encryption formula, and is the most common practical failure.
Integrity: Turning Tampering into Garbage
A strong cipher diffuses changes: altering even one bit of ciphertext produces an unpredictable, usually garbage plaintext, so an attacker cannot steer the result toward a chosen message. Including a hash of the original plaintext lets the receiver recompute and compare after decryption; any modification is then immediately visible.
Pitfalls
- Treating the encryption algorithm itself as the secret rather than protecting the key.
- Re-using one key for many independent messages without a nonce or counter.
- Assuming encryption by itself authenticates the origin of the data.
Run an example
Minimum C11 · complete program · Download .c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void caesar_shift(char *s, int shift)
{
int delta = ((shift % 26) + 26) % 26;
for (int i = 0; s[i] != '\0'; i++) {
unsigned char c = (unsigned char)s[i];
if (isupper(c)) {
s[i] = 'A' + (c - 'A' + delta) % 26;
} else if (islower(c)) {
s[i] = 'a' + (c - 'a' + delta) % 26;
}
}
}
int simple_hash(const char *s)
{
int h = 0;
for (int i = 0; s[i] != '\0'; i++) {
h = (h + (unsigned char)s[i]) % 256;
}
return h;
}
int main(void)
{
char buf[64] = "Transfer funds now";
int h = simple_hash(buf);
printf("plaintext: %s\n", buf);
printf("hash: %d\n", h);
caesar_shift(buf, 3);
printf("ciphertext: %s\n", buf);
caesar_shift(buf, -3);
printf("decrypted: %s hash_match=%s\n", buf, simple_hash(buf) == h ? "yes" : "no");
caesar_shift(buf, 3);
buf[4] = 'X';
caesar_shift(buf, -3);
printf("tampered decrypt: %s hash_match=%s\n", buf, simple_hash(buf) == h ? "yes" : "no");
return 0;
}
Compile locally
gcc -std=c11 -Wall -Wextra -Wpedantic -Werror ostep-56-cryptography.c -o example && ./exampleExpected result
plaintext: Transfer funds now
hash: 249
ciphertext: Wudqvihu ixqgv qrz
decrypted: Transfer funds now hash_match=yes
tampered decrypt: TranUfer funds now hash_match=no
CHECK YOUR UNDERSTANDING
Close the answer. Explain it.
An attacker can rewrite ciphertext at will. Why is it still hard to make decryption produce a plaintext of the attacker’s choosing? How can such rewriting be detected more reliably?
Show a reference answer
A well-designed cipher spreads tiny ciphertext differences into an unrecognisable plaintext, so the attacker cannot know which bits to flip to obtain a target message. Protecting a hash of the plaintext alongside the data, then recomputing and comparing after decryption, makes any change visible.
Check the sources
Drafts and official chapters change. The version mark is only the example’s minimum.