In Cybersecurity: Sniffing Attacks & Defenses, the Share Something Personal - Unencrypted? [1] activity involved testing unencrypted transmission of emoji from one micro:bit to another.
In this activity, the application is a little more versatile, allowing you to scroll through the emoji with the micro:bit module’s A button and send it with the B button.
This application also has a routine for sending a malformed packet. In this activity, you will again study how the malformed packet can cause problems, mitigate them, and then also encrypt the communication.
You can either connect each micro:bit to a separate computer, or both to separate USB ports on the same computer.
# radio_send_receive_images_w_buttons from microbit import * import radio radio.on() radio.config(channel=7) n = 0 emoji = [ 'Image.YES', 'Image.NO', 'Image.HEART', 'Image.SKULL' ] image = eval(emoji[n]) display.show(image) while True: if button_a.was_pressed(): n = n + 1 n = n % len(emoji) image = eval(emoji[n]) display.show(image) if button_b.was_pressed(): packet = emoji[n] print('packet:', packet) if image is Image.SKULL: # Sends malformed packet packet = 'malformed packet' # Sends malformed packet radio.send(packet) packet = radio.receive() if packet: print('packet:', packet) n = emoji.index(packet, 0, len(emoji)) image = eval(packet) display.show(image)
Here you will first send correctly formed data by sending the YES, NO, or HEART images. After that, you will send the SKULL to trigger the malformed packet and observe the effect on the receiver micro:bit.
The script starts with its name as a comment, followed by importing the microbit and radio modules. Then, initialization starts by setting the radio to on and the channel to 7.
# radio_send_receive_images_w_buttons from microbit import * import radio radio.on() radio.config(channel=7)
The initialization continues by creating a global variable n and setting it to zero. Then, a list of emoji is created and named emoji. The image = eval(emoji[n]) statement uses eval to convert the string emoji[0] = 'Image.YES' to the object Image.YES, and stores the result in a variable named image. Then, display.show(image) makes the micro:bit modules LED matrix display the Image.YES image, which is a checkmark.
n = 0 emoji = [ 'Image.YES', 'Image.NO', 'Image.HEART', 'Image.SKULL' ] image = eval(emoji[n]) display.show(image)
The main loop starts with a statement checking if the A button has been pressed. If so, it adds 1 to n. The statement n = n % len(emoji) is a trick to keep the value of n cycling through index values of n that never go out of range. With four emoji in the list, repeatedly pressing and releasing the A button result in n incrementing 0, 1, 2, 3, 0, 1, 2, 3,… and so on. After the first press of A, the value of n has been incremented from 0 to 1. So, instead of Image.YES (a checkmark), eval(emoji[n]) returns Image.NO (an X), which is stored in the image variable and then displayed by display.show(image).
while True: if button_a.was_pressed(): n = n + 1 n = n % len(emoji) image = eval(emoji[n]) display.show(image)
If the B button is pressed, the packet variable is set to emoji[n]. For example, if n is 2, packet will be set to 'Image.HEART', or if n is 3, packet will be set to 'Image.SKULL'. Both of those are strings that represent the image to transmit. The print('packet:', packet) statement displays the string that packet stores in the Serial terminal. Back when button A was pressed, the image variable was set to the corresponding Image object. So, when n was 2, image became Image.HEART or when n was 3, image was set to Image.SKULL. Basically, the image variable stores the Image object that is displayed, and packet stores the corresponding string that will be sent to the receiver. The receiver will convert that string to an Image object and display it.
if button_b.was_pressed(): packet = emoji[n] print('packet:', packet) if image is Image.SKULL: # Sends malformed packet packet = 'malformed packet' # Sends malformed packet radio.send(packet)
The if image is Image.SKULL: statement above compares the image the transmitting micro:bit displays to Image.SKULL. If it’s a match, the packet is changed from 'Image.SKULL' to a string that simply says 'malformed packet'. If the string does not contain an image that the receiver recognizes, it will cause a runtime exception, so the string could instead contain something else, like 'abcdefg...', for example, and it would have the same effect.
Every time through the while True: loop, the packet = radio.receive() statement checks for incoming packets. If one is waiting in the radio receiver’s buffer, the if packet: statement processes and displays it. First, it displays it in the Serial terminal with a print statement. Then, it uses n = emoji.index(packet, 0, len(emoji)) to find the index value that matches the incoming string.
For example, if the incoming string is 'Image.HEART', the emoji.index method will return 2, which gets stored in n. Without this statement, you might have received an image and press B to try to send it back since it’s displaying, but without updating the value of n like this, it might send a different image. Then, image = eval(packet) changes a string like 'Image.HEART' to an Image object like Image.HEART, and finally, display.show(image) displays the incoming image on the receiving micro:bit.
packet = radio.receive() if packet: print('packet:', packet) n = emoji.index(packet, 0, len(emoji)) image = eval(packet) display.show(image)
As with the first activity, exception handling can prevent the micro:bit from freezing in response to a malformed packet.
What does a micro:bit terminal now display when it receives a malformed packet?
Neither encryption nor exception handling alone can entirely protect an app, but used together, they improve its chances of not being intercepted AND not halting script execution due to an exception.
Now it is time to implement exception handling + encryption with the Share Something Personal app.
Links
[1] https://learn.parallax.com/tutorials/robot/cyberbot/cybersecurity-sniffing-attacks-and-defenses/share-something-personal
[2] https://python.microbit.org/v/2