Friday, June 27, 2025

Protect your MicroPython sourcecode

For an index to all my stories click this text

I am/was working on a large project. The project consisted of a microcontroller with some sensors. That microcontroller sends it's data to a dedicated app on an Android phone. Both the microcontroller and the app have to do some complicated calculations.
As I want to show the prototype to several people who might be commercially interested I don't want them to have the opportunity to peek at my software.

I am a lazy developer. So to speed up things I wrote the software for the microcontroller in MicroPython. It works flawless but is not hidden for anyone who connects a computer to the microcontroller. So I had to find a way to hide the program. At least to make it unreadable.

Sidenote.
When you write the programs for your microcontroller with the Arduino IDE it is almost impossible for someone to get the code out of the controller to examine it. Next to that the C++ code you wrote is compiled into machine language by the IDE which is unreadable for most. These two properties keeps your code quite safe. So maybe (when there is time) I will rewrite the program in Arduino language.

How MicroPython works.

MicroPython is an interpreted language. So you write your program in MicroPython and send it to the microcontroller. The code is stored on the microcontroller before it runs. The microcontroller has the  MicroPython interpreter on board that converts the code into something the microcontroller understands. So your sourcecode is stored on the Microcontroller ready for anyone to retrieve.

An interpreted language like MicroPython is, is therefore significant slower as the machine language the Arduino IDE produces.
The MicroPython developers found a solution to speed things up.
The MicroPython program is first converted into bytecode. The step between bytecode and machinelanguage is easier and therefore your program will run faster. Still not as fast as pure machinecode, but a lot faster as full MicroPython.

The solution

Bytecode is unreadable by us mere humans. And that offers opportunities for obfuscating the source code.

Here is a simple MicroPython program:



I just wrote this in Thonny and saved it to my computers harddisk.



And this is how the bytecode looks.
I am sure that most people that would get this code in their hands would not have a clue on how to alter this or examine it.

So what we need is a program that takes our MicroPython source code and compiles it into bytecode. And lucky for us this software exists.

Download mpy-cross

The program we need is called mpy-cross and you can get it here:
https://gitlab.com/alelec/mpy_cross/-/packages/7514584

As you can see I used this first when I still was running Windows. You might know that I switched to Linux as my operating system. There is a version of mpy-cross for Linux to and I will discuss how to use that in a future article.

At the time of this writing version V1.20.0 was the latest version. Always check for the latest version and use that.



Click on the latest version and a new window opens.



Scroll down on that page till you find the version for your computer. Mine is:
mpy-cross-v1.20.0-win_x86_64.exe

Download it and install it on your computer in a dedicate directory.
Your computer might give a warning that the software might be unsafe. I tested the package with my virus scanner before installing it and it was totally safe.

My version downloaded and had the name: mpy-cross-v1.20.0-win_x86_64
I altered the name in just mpy-cross

Using mpy-cross

Start with copying your MicroPython program into the directory where the mpy-cross program is.



The program mpy-cross needs to be started from the command line. Just double clicking it will not work.
To achieve this here is a nice trick.



Click on the yellow icon in front of the path to the directory where the mpy-cross program and your python code is.



Now type cmd



And the commandline window opens with the prompt at the right directory.

In my directory there were only two files: mpy-cross and test01.py
And the test01.py file is the file I wanted to compile.

Use the command

mpy-cross test01.py

Just replace the name test01.py with the name your MicroPython source code has.



Press enter and after a (short) while the prompt returns. The time it takes to compile your code depends on the complexity and size of your sourcecode.



And there is the bytecode file. It has the name test01 and looks like a text file but as you have seen in the second picture in this article it is nothing like a text file.

How to use the bytecode file



The file test01.mpy is uploaded to Thonny. Clicking on the name of the file produces an error. MicroPython does not seem to recognise the program code.

This is what you need to do:



Make a program containing just a single line:

import test01

That's all. It will load the file test01 and run it. You can see the result in Thonny's shell.

It does not need to be a program with a single line. The test01.mpy code can be part of a larger program. You just treat it like it is a library.

Concluding

This will not stop people from copying the bootcode file from your MicroPython device. But it will prevent most to analyse your program.

Please be aware that a bytcode file can not be used as main.py to automatically run your program at start-up. So make a one-line file (as discussed above) as your main.py file that calls the bytecode file.

Till next time
have fun

Luc Volders