Learn more about Russian war crimes in Ukraine.

Making a stream cipher

Symmetric cryptography lets Alice talk privately to Bob, as long as they have a shared secret. A “stream cipher” is one way to do symmetric crypto. It’s surprisingly easy to make a (probably bad) stream cipher. Here’s one implementation in Go:

package main

import "os"
import "bufio"
import "crypto/sha256"

func main() {
	keystream := make(chan byte)
	key := []byte(os.Args[1])
	state := sha256.Sum256(key)
	go func() {
		for {
			state := sha256.Sum256(state[:])
			for i := 0; i < 4; i++ {
				keystream <- state[i]
	stdin := bufio.NewReader(os.Stdin)
	for {
		b, err := stdin.ReadByte()
		if err != nil {
		os.Stdout.Write([]byte{b ^ <-keystream})

And here’s the system in action, sending a message over TCP:

$ nc -l 15000 | go run cipher.go secretpass  # Bob awaits Alice's message
I love you Bob
# Alice runs this
echo 'I love you Bob' | go run cipher.go secretpass | nc bob.com 15000

A stream cipher is a bit like the “one-time pad” system. In the one-time pad system, Alice and Bob share a pad filled with random bytes. To encrypt the plaintext, Alice XORs it with some bytes from the pad. To decrypt the ciphertext, Bob XORs it with the same bytes from the pad. Notice that the encryption and decryption algorithms are identical, or “symmetric”.

Sharing this pad is impractical for a couple of reasons. The pad is big, making it impractical to carry. But the pad is finite, meaning you can run out of key material. Stream ciphers fix this by generating an infinite pad, called a “keystream”, from a finite starting key. In the example above, Alice and Bob agreed on the key secretpass. Notice again that encryption and decryption are symmetric, using the same file cipher.go.

My stream cipher generates the keystream by repeatedly applying SHA-256 to the initial key. After each application of SHA-256, it takes some bytes from the state as keystream bytes. There are many other ways you could generate the keystream.

This stream cipher suffers from some of the weaknesses of the one-time pad. The keystream must not be reused! If Alice and Bob were to exchange another message using the same key, Eve could XOR the two ciphertexts together to get the XOR of the two plaintexts.

Another weakness: while the stream cipher provides privacy, it does not provide integrity! An man-in-the-middle could muddle with the ciphertext, and Bob would have no way to know.

And there are probably other flaws I haven’t foreseen. IANAC (I am not a cryptographer).

What can computers do? What are the limits of mathematics? And just how busy can a busy beaver be? This year, I’m writing Busy Beavers, a unique interactive book on computability theory. You and I will take a practical and modern approach to answering these questions — or at least learning why some questions are unanswerable!

It’s only $19, and you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

After months of secret toil, I and Andrew Carr released Everyday Data Science, a unique interactive online course! You’ll make the perfect glass of lemonade using Thompson sampling. You’ll lose weight with differential equations. And you might just qualify for the Olympics with a bit of statistics!

It’s $29, but you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

More by Jim

Tagged #programming, #go, #crypto. All content copyright James Fisher 2018. This post is not associated with my employer. Found an error? Edit this page.