Students audit a radio door lock, match each weakness to a tool from the course, and harden it in three milestones: a cipher, a keyed checksum and a challenge and response.
Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.
Predict and Run 8 min · Audit 10 min · Milestone 1 10 min · Milestones 2 and 3 25 min · Report 5 min
The idea: the course's three tools answer three different questions: who can read it (a cipher), was it changed (a checksum with a key) and is this a fresh message from someone who has the key (challenge and response). A secure system usually needs all three.
Framing: this is the defender's job. Students audit and harden their own system. The lesson does not have them attack each other's locks. If students want to test each other, run it as 'pass the pair': swap pairs' final locks, and try the real key against the lock; the lock should open for the key and refuse everything else.
The final system: the key micro:bit knocks with a keyed checksum; the lock checks it, sends a random challenge, the key answers using the secret key, and the lock opens only on the right answer. The secret key never crosses the air.
Limits to say aloud: these are classroom versions. The XOR step reveals the key if someone knows both a locked and an unlocked value; the answer function is not a one-way function; keys have to be shared safely first (the key exchange lesson). Real systems use proven tools, not ones we invented.
Challenge milestones: Milestone 1 has most of the code; milestone 2 outlines; milestone 3 gives goals only. Students who finish quickly can add the lockout from the Challenge–response lesson.
Matching each weakness to its tool and keeping the keys the same on both sides. When the lock fails, ask them to name the weakness each milestone fixes.
| What you will see | A question to ask | The fix |
|---|---|---|
| The lock never opens. | Do both micro:bits have the same secretKey? Is the answer function the same? | Use one secretKey and one answer function in the same program on both. |
| The lock opens for the wrong key. | Do you compare the answer with answer(challenge) on the lock? | Compare value with answer(challenge); keep challenge in a variable on the lock. |
| Milestone 3 and the checksum work separately but not together. | Which block handles each name (KNOCK, CHALL, ANSWER)? | One on radio received value block with if, else if on the name. |
One possible solution for each task. Other correct programs are fine.

let secretKey = 7
radio.setGroup(5)
input.onButtonPressed(Button.A, function () {
radio.sendNumber(4271 ^ secretKey)
})
radio.onReceivedNumber(function (receivedNumber) {
if ((receivedNumber ^ secretKey) == 4271) {
basic.showIcon(IconNames.Yes)
} else {
basic.showIcon(IconNames.No)
}
})

let ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
let secretKey = 7
let challenge = 0
function checksum(message: string): number {
let total = secretKey
for (let i = 0; i < message.length; i++) {
total += ALPHABET.indexOf(message.charAt(i))
}
return total % 10
}
function answer(n: number): number {
return (n * secretKey + 3) % 100
}
radio.setGroup(5)
input.onButtonPressed(Button.A, function () {
radio.sendValue("KNOCK", checksum("KNOCK"))
})
radio.onReceivedValue(function (name, value) {
if (name == "KNOCK") {
if (checksum("KNOCK") == value) {
basic.showIcon(IconNames.Yes)
} else {
basic.showIcon(IconNames.No)
}
}
})

let ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
let secretKey = 7
let challenge = 0
function checksum(message: string): number {
let total = secretKey
for (let i = 0; i < message.length; i++) {
total += ALPHABET.indexOf(message.charAt(i))
}
return total % 10
}
function answer(n: number): number {
return (n * secretKey + 3) % 100
}
radio.setGroup(5)
input.onButtonPressed(Button.A, function () {
radio.sendValue("KNOCK", checksum("KNOCK"))
})
radio.onReceivedValue(function (name, value) {
if (name == "KNOCK") {
if (checksum("KNOCK") == value) {
challenge = randint(10, 99)
radio.sendValue("CHALL", challenge)
} else {
basic.showIcon(IconNames.No)
}
} else if (name == "CHALL") {
radio.sendValue("ANSWER", answer(value))
} else if (name == "ANSWER") {
if (value == answer(challenge)) {
basic.showIcon(IconNames.Yes)
} else {
basic.showIcon(IconNames.No)
}
}
})
Stretch: Add the lockout after three wrong answers from the Challenge–response lesson.
Support: Share the milestone 2 code and ask students to explain it before they build milestone 3.
Name the three weaknesses of the starting lock and the fix for each.
Readable by the group: encrypt with a shared key. A changed message can't be told: a keyed checksum. A heard message works again: challenge and response.
Where this leads: real systems use proven libraries, long keys, hash functions and certificates. The ideas here are the same.