The key to success in life is the ability to recognize a rare opportunity, and the courage to take it. If, for instance, your coworkers are clever, fond of puzzles and easily distractible, and if these same coworkers are all at Defcon, leaving the office deserted, the circumstances demand that you pull the most elaborate office prank you can devise.

Only a few of the engineers on my team skipped Defcon this year, including Marcus and myself. The week before people flew out, I suggested to Marcus that we should pull some sort of prank, and he immediately agreed. We batted around a few ideas - turn the conference room into a ball pit? Replace everyone’s laptops with typewriters? We eventually decided to kidnap the office espresso machine and set up a puzzle for our coworkers to solve in order to liberate it.

Espresso machine in a metal cage with multiple padlocks. A ransom note made of magazine clippings, and a fragment of a QR code, are taped to the front.

The Heist

The first step was taking the machine hostage. It’s a heavy, expensive piece of equipment, so we didn’t want to move it – we just wanted to stop people from using it. So Marcus welded an espresso machine-sized cage and we locked it up.

We liked the visual of putting the machine in a cage, but we thought that wouldn’t be enough for a couple reasons:

  • The bars were pretty far apart, so you could still reach into the cage and use the machine.
  • The padlocks we had weren’t very good, and many people in the office know how to pick locks.

We figured that picking the locks was the first thing they would try. To slow them down, we used five padlocks and confiscated the office lockpick gun. As an extra precaution, in case they still managed to pick all the locks, we took all the portafilters too – they were small and durable enough that we felt comfortable moving them, but the machine wasn’t usable without them.

We rented a storage unit at Belltown Storage, where we stashed the keys to the padlocks, the portafilters, and the lockpick gun.

Espresso machine in a metal cage with five padlocks.
A narrow hallway lined with small tan storage lockers.

As the finishing touch, we created a ransom note, which we signed “The Decaffeinator”. We went the old-school route of cutting and pasting letters from magazines. Gaby, Marcus’s wife, helped out a lot by cutting out and arranging a bunch of the letters.

Posterboard, glue stick and letters cut from magazines on a table.
Ransom note taped to espresso machine cage.

The note reads:

I have taken your espresso machine hostage and stolen your portafilters! I’ve left a series of clues to lead you back to your portafilters and the keys to this cage. Solve them by the end of the month…or you’ll never be able to use your espresso machine again! Good luck, The Decaffeinator.

PS Here is the first puzzle piece to get you started.

The Puzzle

Whiteboard flow chart of puzzle steps.     'Ransom Note' leads to 'This is Fine,' which leads to 'Dog,' which leads to 'Buy blank at SCW,'     which leads to 'coffee can; key to storage unit; ciphertext (book cipher?); give ISBN,'     which leads to 'PASTEBIN,' which then splits into three branches.     First branch: Babbage (QR) leads to 'Look at Joe's records' which leads to 'Message in a Bottle,'     which leads to 'Actual message in bottle,' which leads to 'Address of Belltown Storage.'     Second branch: 'look behind toaster' leads to 'Morse code' which leads to 'haiku'     which leads to 'Unit # & floor'     Third branch: 'alice & bob' leads to 'equation' which leads to 'numbers on whiteboards'     which leads to 'code'

1. QR Code Jigsaw Puzzle

The first clue was a QR code. We cut it into nine pieces, which we hid throughout the office. (Gaby’s XActo knife skills helped here too.) We put one piece on the espresso machine itself so they knew what to look for. We hid a few pieces in plain sight – we didn’t want people to get frustrated before they’d even started. A few others were trickier.

QR piece hidden in a gray shoe
QR piece stuck to fridge with a coffee-themed magnet
QR piece thumbtacked to a board with other papers
QR piece hidden behind a bag of potato chips in a snack box

2. This is Fine

The complete QR code linked to the classic “This Is Fine” comic. We had a couple plush versions of the unlucky dog in the office – Joe (my manager) and I had both backed the Kickstarter campaign to produce them. We hid a message on a strip of paper in the rim of each dog’s hat.

One strip said “Report to Seattle Coffee Works on August 1 at 1300 hours and order the “Keurig Blend”. The other said “See other dog.”

Stuffed dog holding a mug that says 'This is Fine', in a cardboard house with flame pattern

3. Seattle Coffee Works

The next step took them down the street to Seattle Coffee Works, our regular source of coffee beans. These folks take their coffee very seriously – like, they have a slow bar where you can go try Aeropress vs. pour-over vs. vacuum pot coffee and compare how they taste. They definitely do not sell a Keurig Blend. We mostly wanted to poke fun at the people at our office who are way too pretentious to ever drink coffee from a Keurig machine.

The wonderful people at Seattle Coffee Works agreed to help, but told us to bring the can back on the day they were actually going to pick it up. They worried it would get lost in the shuffle over the weekend.

The can contained a page of ciphertext and the key to the storage unit – without any indication of what the key was for. For maximum trolling, we also filled the can with Keurig cups.

Half-page of printed numbers and a key
Coffee can full of Keurig cups
Closed coffee can with printed 'Keurig Blend' label on top

4. The Cuckoo’s Egg

Here’s the ciphertext from the coffee can:

ISBN: 0-671-72688-9

262.1.2 27.21.2 32.14.1 33.26.10 53.12.5:  6.1.8  53.40.8  59.13.5, 6.1.8  11.8.1, 11.3.5 12.19.3  35.35.8  40.246.
56.33.8 27.21.2 57.1.10 38.7.2 6.1.8 41.4.7 77.36.9 93.12.1 78.9.3 79.1.11 80.26.5 81.22.6:

* 77.36.9 81.22.6 118.6.7 6.1.8 127.14.3 173.25.4 175.1.6 174.1.10 192.17.9 192.17.10 192.17.11 12.1.1. 121.29.1 262.35.2 53.40.8 333.13.2.

* 77.36.9 2.3.9 3.12.3 81.22.6 192.17.10 192.17.11 4.2.7 340.36.4-ers, 11.3.5 12.19.3 189.29.5 153.4.3 197.9.1 213.36.7 14.23.7 12.5.1.

* 77.36.9 32.14.1 12.17.7 50.12.9 193.39.6 153.4.3 213.30.5 231.11.10 14.2.5 ... 14.27.7 14.3.8 9.13.10 19.20.2 18.8.3 16.2.4 9.27.4 10.12.5 6.18.2 106.8.3 26.16.2 26.1.6 27.4.5 127.14.3 226.15.3

This is an Arnold Cipher, a type of book cipher. In an Arnold cipher, each word is encoded by a series of three numbers: a page in the key text, a line number on that page, and a word number on that line.

The ISBN at the top indicated our key text, The Cuckoo’s Egg. It had a few things going for it as a key text:

  • It was sort of thematically relevant – the protagonist unravels a mystery step by step.
  • It had all the words we needed.
  • We had a copy lying around the office.

We’d considered a few different types of ciphers, and settled on a book cipher for a few reasons: it was a little unusual, but not so obscure that it would feel arbitrary, and it had to be decoded by hand. Many of our coworkers play in CTFs regularly, and have scripts handy to break Vigenere ciphers and other CTF staples. Because we opted for a book cipher, they would have to find the book and then physically leaf through it to decode the clue.

There are lots of different types of book ciphers; we picked an Arnold cipher so there wouldn’t be any ambiguity about how to decode it. The triplets of numbers were pretty distinctive, and there weren’t a ton of possible variations on an Arnold cipher. We didn’t want people to spend a lot of time using the wrong encoding scheme – that seemed like the not-fun kind of frustrating, which could potentially take people way off track.

Here’s the plaintext:

Here's a key...but where's the lock? You need to discover three more things: a street address, a unit number, and an access code.
You'll need to ask a different person for help with each one:

* Person One made a real difference in the history of the computer. Also hated street musicians a lot.

* Person Two was one of the first debuggers, and an expert on how long a nanosecond is.

* Person Three always stayed current on new scientific discoveries...but is best known for his feud with another prominent scientist and his sweet moustache.

5. The Three People

Our office conference rooms are named after famous figures in computer science and engineering. Every room has a nameplate with the person’s name and picture, a brief bio cribbed from Wikipedia, and a QR code linking to the person’s Wikipedia page. These nameplates are printed out on regular printer paper, and are easily removable.

The last three paragraphs of the plaintext hinted at three of our conference rooms’ namesakes: Grace Hopper, Nikola Tesla, and Charles Babbage. We replaced each nameplate with an exact1 replica, with only the QR code changed. The three new QR codes led to three puzzles which could be solved independently. Each led to one piece of information the solvers would need to get into the storage unit; Babbage led to the address, Tesla led to the storage unit number, and Hopper gave them the PIN they needed to get to the right floor in the elevator.

Address: Belltown Self-Storage
Unit number: M015
PIN: 618352

Nameplate with Babbage bio and photo and a QR code
Nameplate with Hopper bio and photo and a QR code

6a. Babbage - https://pastebin.com/pNgyL2QP

QR code for Babbage pastebin link

Joe has plenty of records, it's true,
But I felt he was missing a few.
So I've added another
for you to discover -
that record will be your next clue.

Joe has a record player and a bunch of records in his office because he’s a dirty hipster. Several years ago he promised to listen to and rank any record he was given - so his collection of vinyl is large, eclectic, and exhaustively documented on the internal wiki. We added Reggatta de Blanc to the collection; they would need to identify it as the only album that wasn’t on the wiki.

We starred “Message in a Bottle” on the track listing. The address of Belltown Storage was on a piece of paper in an empty cider bottle in the office fridge. We hid it behind a bunch of similar-looking bottles to make it harder to spot.

6b. Tesla - https://pastebin.com/7yFAY00v

QR code for Tesla pastebin link

This next clue might be pretty hard;
I hope that you don't mind it.
But at least it should stay nice and warm
and toasty till you find it.

We hid a Diavolino board with a single LED behind the toaster oven. Marcus programmed it to blink a message in Morse code:

    WELL DONE MORSE CODE GURU
    EVEN WITHOUT ESPRESSO
    READY FOR INFO

    SLOWLY NOT QUITE YET
    UNIT NUMBER WILL COME SOON
    HAIKU ALWAYS FIRST

    ELEVATOR SLOW
    UNIT IS ON LEVEL A
    M ZERO ONE FIVE

To be as obnoxious as possible, we created a pretty long message (hence the haiku) and put the important information - the storage unit number - at the very end. Explicitly pointing out that the message was in haiku format also served as a way to insert line breaks, which clarified that “level A” and “M ZERO ONE FIVE” were separate bits of information.

Here’s the code to blink out the message:

/*
 Description: Morse Code Aurduino, blinks message on LED
 Author: Marcus Hodges
 License: MIT License
 Date: July 28, 2017
 */

// configuration
int led = 13;  // LED pin (on most Aurduino boards)
int gap = 500; // Time delay between blinks (3*gap between letters, 7*gap between words)
char message[] = "WELL DONE MORSE CODE GURU EVEN WITHOUT ESPRESSO READY FOR INFO SLOWLY NOT QUITE YET UNIT NUMBER WILL COME SOON HAIKU ALWAYS FIRST ELEVATOR SLOW UNIT IS ON LEVEL A M ZERO ONE FIVE";

// setup runs when you press reset
void setup() {
  // initialize the digital pin as an output
  pinMode(led, OUTPUT);
}

void dit(){
  digitalWrite(led, HIGH);   // turn LED on
  delay(gap);                // time delay
  digitalWrite(led, LOW);    // turn LED off
  delay(gap);
}

void dah(){
  digitalWrite(led, HIGH);
  delay(gap*3);
  digitalWrite(led, LOW);
  delay(gap);
}


void blink(char c){

  switch(c){
  case 'A':
    dit();
    dah();
    delay(3*gap);
    break;

  case 'B':
    dah();
    dit();
    dit();
    dit();
    delay(3*gap);
    break;

  case 'C':
    dah();
    dit();
    dah();
    dit();
    delay(3*gap);
    break;

  case 'D':
    dah();
    dit();
    dit();
    delay(3*gap);
    break;

  case 'E':
    dit();
    delay(3*gap);
    break;

  case 'F':
    dit();
    dit();
    dah();
    dit();
    delay(3*gap);
    break;

  case 'G':
    dah();
    dah();
    dit();
    delay(3*gap);
    break;

  case 'H':
    dit();
    dit();
    dit();
    dit();
    delay(3*gap);
    break;

  case 'I':
    dit();
    dit();
    delay(3*gap);
    break;

  case 'J':
    dit();
    dah();
    dah();
    dah();
    delay(3*gap);
    break;

  case 'K':
    dah();
    dit();
    dah();
    delay(3*gap);
    break;

  case 'L':
    dit();
    dah();
    dit();
    dit();
    delay(3*gap);
    break;

  case 'M':
    dah();
    dah();
    delay(3*gap);
    break;

  case 'N':
    dah();
    dit();
    delay(3*gap);
    break;

  case 'O':
    dah();
    dah();
    dah();
    delay(3*gap);
    break;

  case 'P':
    dit();
    dah();
    dah();
    dit();
    delay(3*gap);
    break;

  case 'Q':
    dah();
    dah();
    dit();
    dah();
    delay(3*gap);
    break;

  case 'R':
    dit();
    dah();
    dit();
    delay(3*gap);
    break;

  case 'S':
    dit();
    dit();
    dit();
    delay(3*gap);
    break;

  case 'T':
    dah();
    delay(3*gap);
    break;

  case 'U':
    dit();
    dit();
    dah();
    delay(3*gap);
    break;

  case 'V':
    dit();
    dit();
    dit();
    dah();
    delay(3*gap);
    break;

  case 'W':
    dit();
    dah();
    dah();
    delay(3*gap);
    break;

  case 'X':
    dah();
    dit();
    dit();
    dah();
    delay(3*gap);
    break;

  case 'Y':
    dah();
    dit();
    dah();
    dah();
    delay(3*gap);
    break;

  case 'Z':
    dah();
    dah();
    dit();
    dit();
    delay(3*gap);
    break;

  case '1':
    dit();
    dah();
    dah();
    dah();
    dah();
    delay(3*gap);
    break;

  case '2':
    dit();
    dit();
    dah();
    dah();
    dah();
    delay(3*gap);
    break;

  case '3':
    dit();
    dit();
    dit();
    dah();
    dah();
    delay(3*gap);
    break;

  case '4':
    dit();
    dit();
    dit();
    dit();
    dah();
    delay(3*gap);
    break;

  case '5':
    dit();
    dit();
    dit();
    dit();
    dit();
    delay(3*gap);
    break;

  case '6':
    dah();
    dit();
    dit();
    dit();
    dit();
    delay(3*gap);
    break;

  case '7':
    dah();
    dah();
    dit();
    dit();
    dit();
    delay(3*gap);
    break;

  case '8':
    dah();
    dah();
    dah();
    dit();
    dit();
    delay(3*gap);
    break;

  case '9':
    dah();
    dah();
    dah();
    dah();
    dit();
    delay(3*gap);
    break;

  case '0':
    dah();
    dah();
    dah();
    dah();
    dah();
    delay(3*gap);
    break;

  case ' ':
    delay(7*gap);
    break;
  }
}

// loop forever
void loop() {
  int length = strlen(message);
  for (int i=0; i<length; i++){
    blink(message[i]);
  }
}
Circuit board with flashing LED hidden in a corner behind the toaster oven.
Small Diavolino circuit board with LED

6c. Hopper - https://pastebin.com/4XJpzxEu

QR code for Hopper pastebin link

Dear Bob,

I wanted to send you this access code so you could get up the elevator. My friends Diffie and Hellman showed me how on a whiteboard. Don't forget to enter * on the keypad after the code. Your code is XOR(S,0x91B4F).

Secretly yours,

Alice

For the final puzzle, they had to figure out the 6-digit elevator PIN using a Diffie-Hellman key exchange2. We weren’t really using it as a key exchange protocol - we just treated it as an arbitrary formula to calculate an arbitrary value, S:

Given values a, b, p, g:

    A = ga mod p
    B = gb mod p
    S = Ab mod p = Ba mod p
    Elevator PIN = XOR(S, 0x91B4F)

We knew our coworkers would be familiar with Diffie-Hellman - at least familiar enough to look up the formula on Wikipedia. The hard part was finding a, b, p, and g, which we wrote on whiteboards around the office.

Partial view of an arcade machine
        with a whiteboard of 'Top Scores' in the background. One game listed is 'Alice & Bob',
        with top score 'a=0xcafe'
g = 3' written on the bottom corner a whiteboard,
            partially obscured by a battery.
'p=31337' written on the top corner of a whiteboard

Now, not everyone would describe numbers as playful, but given the circumstances 0xCAFE and 0xDECAF seemed more than a little appropriate. 31337 is another classic choice for a hacker challenge and given that it’s a prime number it was a good choice for p. Of course, in the land of cryptography certain properties must be upheld so we had to calculate the base g such that it was a primitive root modulo p. This either requires a few lines of Python or you can cheat and use the Sage Math’s primitive_root() function like we did. The extra XOR step at the end was a simple way to work backwards from the desired PIN code and was also a one-time pad (presuming the Decaffeinator remembers not to use that key again in the future).

Here’s the math to calculate the elevator PIN:

p = 31337
g = 3
a = 0xcafe
b = 0xdecaf

A = ga mod p
  = 30xcafe mod 31337
  = 30759
B = gb mod p
  = 30xdecaf mod 31337
  = 6811

1st way to find S:
S = Ab mod p
  = 307590xdecaf mod 31337
  = 29759

2nd way to find S:
S = Ba mod p
  = 68110xcafe mod 31337
  = 29759


PIN = XOR(29759, 0x91B4F)
    = 618352

The Games Begin!

On Monday morning, our coworkers returned. Like we’d expected, they tried to pick the locks first, and managed to remove two out of five. They collected the first few QR pieces, but hadn’t found all of them by the end of the day. Lots of folks weren’t back in the office yet.

They were making slower progress than we expected; if they didn’t solve the QR code puzzle by noon on Tuesday, they would miss their rendezvous at Seattle Coffee Works. After everyone else had left the office, I took emergency measures to keep them on track:

  • Created a Google Voice number
  • Replaced the instructions on the “This is Fine” dog with instructions to call the Google Voice Number
  • Put the locks back on the espresso machine
  • Left a message on the cage:

Kermit the Frog meme with caption: NOPE

On Tuesday, with more people back in the office, things started to heat up. Steven, being a bad sport pragmatist, brought his Aeropress from home, so people would have an alternate caffeine supply. David found the Diavolino behind the toaster, earlier than we’d planned, and they noticed a few of the Diffie-Hellman parameters. Solving the Morse code challenge out of the intended order added just enough confusion to keep things entertaining.

They finished the QR code puzzle, and Maxfield, our enterprising intern, texted my Google Voice number:

Picture of Google Voice transcript.
Maxfield: Request for further instructions.
Maxfield: ; rm -rf --no-preserve-root /;
Me: Report to Seattle Coffee Works tomorrow between 10:00 and 15:00. Order the "Keurig Blend."
Maxfield: Roger.
Me: Further attempts at command injection may result in additional padlocks on the espresso machine. Maxfield: Hey, it was worth a shot ;)
Maxfield: Get it, a shot? I miss coffee.

Meanwhile, the lockpicking efforts continued - they got a couple locks off again, and to prevent The Decaffeinator from putting them back on, Ian hung one of them directly in front of the office security camera. I didn’t let this deter me. I snuck back to the office late at night to put the padlocks back on, but donned a disguise in case they checked the security camera footage.

I dropped off the Keurig can at Seattle Coffee Works on Wednesday morning, and they picked it up at lunch. That was my last job - from that point on I was just observing.

Marcus and I were completely wrong about how difficult each step was. We’d expected them to struggle with the book cipher, and be totally stumped by the nameplate switcheroo - instead, they solved both of them almost immediately. But they were completely baffled by “Message in a Bottle,” which we’d expected to be really easy. We realized they might have trouble finding the bottle - we hadn’t anticipated that they’d have trouble figuring out that they should look for a bottle.

Nonetheless, on Friday they found the bottle and retrieved the box from the storage unit. Everyone celebrated with espresso. ☕

They never did check the security camera footage, though:

Me wearing a Mexican wrestler mask and Groucho Marx glasses. I look very cool.

1 Not that exact – we replaced Tesla with a picture of Samuel Morse, to hint that his puzzle would involve Morse code. We also replaced the color picture of Grace Hopper with a black-and-white one because the office doesn’t have a color printer. I spent a lot of time worrying that people would notice the change to Hopper right away – it’s our most used conference room. Marcus convinced me that people weren’t that observant, and we didn’t need to run to FedEx to print out Hopper’s photo in color. He was correct.

2 This is a cryptographic protocol for agreeing on a shared secret over an insecure channel. So, if you need to access a website, your browser and the website can first use Diffie-Hellman to calculate the secret, conventionally named s. Even if someone eavesdrops on all traffic between you and the website, they won’t be able to figure out s, because of math reasons. Then you can use s to encrypt all further traffic between you and the website, which keeps your data confidential. This is part of how TLS works.