Lab 09: Secret Message

This part of the lab will give you some practice using the debugger and setting breakpoints. We covered these topics in an earlier lab, now it's important to use these tools to help you figure out what your code is doing.

Partner A
Partner B

Among the starter files for today's lab are secrets.pyc, messageDecoder.py, and encrypted.txt. The code in messageDecoder.py is the focus of this unusual task: in theory, if a specific file is created and a secret password is written into that file, the code will read encrypted.txt and decrypt it, writing the results to a new file named message.txt. Your goal is to work together with your partner to figure out the correct name of the password file, and the correct password to put in the file, so that you can read the encrypted message. Your goal is to figure out things indicated with green question marks in the image below.

A diagram of the task at hand. It shows a box representing messageDecoder.py and
another box representing the provided secrets.pyc. Arrows extend from the messageDecoder box to indicate that a file should be read and the file contains a password. Green question marks indicate parts the user must figure out or generate. There is also an orange box labeled message.txt, which is generated if the right file and the right password are created.

The Debugger

We first introduced the debugger back in lab 02. To briefly review how it works: When running in debug mode, you can step through things one operation at a time, and Thonny will show you each value that gets created, plus the values of all active variables. To speed things up, you can double-click in the margin to set a 'breakpoint', which will cause Thonny to fast-forward to that point in the code when you run the debugger, and each time you hit the resume button. This screenshot shows how breakpoints are set:

A screenshot of the Thonny window with a `hasCGBlock` function displayed; the left-margin has line numbers and is highlighted to indicate that clicking on it will set or remove a breakpoint. In the example, a red dot in the margin after the line number '20' indicates a breakpoint has been set on that line.

This picture shows the debugger in action:

Another screenshot showing a pop-up window for a function call frame, with the body of a loop highlighted in yellow to indicate that's what will run next. The bottom of the pop-up window shows the local variables in that function call frame and their values.

Hidden code

You can read through and even edit the code in messageDecoder.py. But we have not given you the code for secrets.py; instead we gave you secrets.pyc, which lets Python use the code but is a bit harder for you to read (the solutions will include the full secrets.py file).

To figure out what the mysterious secret functions are doing, you'll have to observe their behavior. You could do this in the shell, but you can also use the debugger to see what they do when they're used within messageDecoder.py.

Be careful

The messageDecoder.py file was designed to delete the encrypted message if the wrong password is entered. You should be able to use the debugger to prevent this from happening (just stop the program before that part runs). To start with, set a breakpoint on line 53 of messageDecoder.py so that the debugger will pause (and you'll have a chance to stop it) before actually erasing the file.

Note that in case you do accidentally erase the file, you can always use the encrypted.txt.backup file we've provided to restore it.

The password file

The mystery program won't do anything if there's no password file present. But what file is it looking for?

Your first task is to figure out the correct filename for the password file. The easiest way to do this is to step through the code one operation at a time in the part where it computes the password file name, and then see what result it comes up with. See below if you need an extra hint.

Show me a hint The password filename is decided by a function, and line 22 is where the actual value is computed. You could set a breakpoint here and then step through one step at a time to see the final value. You could also see the value on line 38 when it gets returned and the file is opened.

Once you know what the password filename is, create that file, in Thonny or using a text editor (Notepad or Wordpad for Windows and TextEdit for Macs will work). But you'll also need to know what should go in it...

The password

Once the password file exists, the messageDecoder program will check the password, and it will delete the encrypted message if the password is wrong. For this part, it's important that you only run in debug mode and stop the program before it reaches the code to delete the file encrypted.txt, although you can always restore the message by copying the supplied backup file (encrypted.txt.backup).

To figure out what the correct password is, use the debugger. See below for some hints.

Show me hints Line 46 is the key: this is where it compares the password read from the file against the password encoded in the program. It seems simple, but the `b` function does something complicated. You'll want to set a breakpoint on line 46 and then advance one step at a time to see the result of that function. Once you've seen the result, try to write it into the password file. But come back and step through this line again to check for any differences between the password in the file and the one in the program: it's hard to get it right your first try.

Once you figure out the correct password and write it into the password file, you can run the program (still in debug mode just in case) and let it decrypt the message, to figure out what the hidden message was.

Other approaches

If you're getting stuck with the password filename or the password itself, consider other approaches. Can you edit the messageDecoder.py code to force it to decode the file for you even if you don't know what the password is?

As usual, feel free to ask for help working through this part of the lab! We're happy to help with or without spoiling things :)

Table of Contents