Both ends need the same key, but anything sent by radio is public. Each end mixes a private number with public numbers, swaps the mixes, and both arrive at the same key without it ever being sent.
Every time you open a secure web page, your computer and a server agree a key with a stranger, in public, in less than a second. This lesson is the idea behind it, with numbers small enough to follow by hand.
The last lesson needs both micro:bits to hold the same key. How do they get it? If one sends the key by radio, everyone in the group hears it (lesson 1). Meeting in person works for two friends, but not for a phone and a web server.
The trick: agree a key in public without ever sending it.
The function modPow does "base to the power, remainder after dividing by prime" with a loop.
Behind the code: the mix travels with radio send value (in Radio), which sends a short name and a number together: here the name mix and the number. on radio received value gives the receiver both, as name and value, and name == "mix" checks the name; text must match exactly, capital letters included. A name can be 8 characters at most: a longer name is cut short on the way, so it no longer matches.
Make your prediction first. Help opens once you've locked it in.

// Public numbers everyone may know
let P = 23
let G = 5
// This micro:bit's own secret number (the other micro:bit has 15)
let secret = 6
let shared = 0
function modPow(base: number, power: number, prime: number): number {
let result = 1
for (let i = 0; i < power; i++) {
result = (result * base) % prime
}
return result
}
radio.setGroup(5)
input.onButtonPressed(Button.A, function () {
radio.sendValue("mix", modPow(G, secret, P))
})
radio.onReceivedValue(function (name, value) {
if (name == "mix") {
shared = modPow(value, secret, P)
basic.showNumber(shared)
}
})
Each simulated micro:bit picks its own random private number. Press A on both (one after the other) and compare the numbers shown.

let P = 23
let G = 5
let secret = randint(2, 20)
let shared = 0
function modPow(base: number, power: number, prime: number): number {
let result = 1
for (let i = 0; i < power; i++) {
result = (result * base) % prime
}
return result
}
radio.setGroup(5)
input.onButtonPressed(Button.A, function () {
radio.sendValue("mix", modPow(G, secret, P))
})
radio.onReceivedValue(function (name, value) {
if (name == "mix") {
shared = modPow(value, secret, P)
basic.showNumber(shared)
}
})

// Public numbers everyone may know
let P = 23
let G = 5
// This micro:bit's own secret number (the other micro:bit has 15)
let secret = 6
let shared = 0
function modPow(base: number, power: number, prime: number): number {
let result = 1
for (let i = 0; i < power; i++) {
result = (result * base) % prime
}
return result
}
radio.setGroup(5)
input.onButtonPressed(Button.A, function () {
radio.sendValue("mix", modPow(G, secret, P))
})
radio.onReceivedValue(function (name, value) {
if (name == "mix") {
shared = modPow(value, secret, P)
basic.showNumber(shared)
}
})
A micro:bit with private number 3 sends its mix: 5³ mod 23. What number goes out? (5³ = 125.)
Which of these cross the air, and which stay on one micro:bit?
First press A on both micro:bits, so each works out shared. Then let B send the number 7 locked with shared, and show it unlocked on the other.
B sends a secret number locked with shared: radio send number (7 ^ shared). On radio received number, show received number ^ shared.
B sends a number locked with the agreed key; the other micro:bit unlocks it.
This ticks by itself when your blocks do what is asked.
Put it together: A sends your mix and each micro:bit works out the shared key and shows a tick; B sends a PIN locked with it; the other micro:bit unlocks and shows the PIN. The key was never sent.
A sends the mix; when a mix arrives, work out shared and show a tick.
B sends pin ^ shared; a number received is shown after ^ shared.
A key exchange, then a locked PIN: A sends the mix and the key is worked out, B sends the PIN locked with it, and the receiver unlocks it.
This ticks by itself when your blocks do what is asked.
Students agree a key over an open channel with a Diffie–Hellman style exchange using small numbers, then use it as the key for XOR. About 55 minutes.
Open the teacher guide: answers, solutions, slides and a worksheet.
The idea: two ends agree a shared key while everyone listens. Each mixes a private number with public numbers, swaps the mixes, and mixes again with its private number. Both reach the same number, which was never sent. This is the Diffie–Hellman key exchange, the idea behind the padlock in a browser.
Everyday picture: paint. Everyone knows the common colour (yellow). Each person adds a private colour and shares the mixture. Each then adds their private colour to the other's mixture. Both end with the same colour, and nobody can un-mix the shared one to find the private colours. Where it breaks: with numbers there is no real un-mixing for big numbers, but for tiny numbers you can just try them all.
The maths: students need only the pattern "power, then remainder". The check numbers are small. The program does the working (modPow, a loop, as in micro:bit Foundations).
Honest limits: P = 23 can be broken by trying all private numbers (the third Investigate task says so). Also, a key exchange does not say who you are talking to: an unknown micro:bit could do the exchange too. That need, to prove who is who, is the next lessons' job.
Following a key exchange where the shared key never travels. Ask them to trace on paper what each micro:bit sends and what it keeps private.
Stretch: Change P and G. Which private numbers still give a match? (All of them do: the method works for any P and G.)
Support: Give the exchange complete and ask only for the locked PIN.
Next: how does the receiver know a message was not changed on the way?