How to Hide/ Encrypt/ Obfuscate any Python Program

Balakrishna V

2 min read

Hello everyone. Wondering what this blog post is all about? It is about obfuscating any python program. Now you all must be thinking what does this term “Obfuscate” must mean right!

Obfuscate/ Obfuscation is a process in software development where the developer intentionally/ purposefully makes the source code of the software not easily understandable to humans or in other words not understandable to the layman.

This is done mostly to protect any intellectual property or trade secrets making it difficult to understand and prevent the code from being attacked by external factors.

Here in this blog, I will be explaining how we proceed with this process for any program written in Python. We might sometimes face a situation where we need to provide code directly to a client for obvious reasons, but by doing so, we will lose control of the code. In such cases, we might encrypt the codes to protect them, retain control and add some fallback conditions to control our dependency, just like if we provided code for use only for a certain amount of time.

To address the above issues, I will be demonstrating a simple function with the above capabilities. For the purpose of obfuscation, we will be using a python package called PyArmor.

Table of Contents:

  1. Creating a simple function
  2. Using PyArmor to encrypt it
  3. Importing our function / Inference

1. Creating a simple function

For our implementation, I will be using utils.py with inference function definition and will be encrypting it later.

import os, json, sys
from datetime import datetime
def inference(name="", tag = True):
'''
if the current year is 2021, then inference function will run successfully, otherwise fails.
Here the attribute variable holds the string version of the date in MM-DD-YYYY format
'''
print("Hello {}, the inference function has been successfully started".format(name))
attribute = str(datetime.now().strftime('%m-%d-%Y'))
response = "You license has been expired, please contact us."
year_to_expire = int(2022)
try:
assert int(attribute.split('-')[-1]) == year_to_expire, response
except AssertionError as e:
print(response)
sys.exit()
# Replace your main code to operate here.
# if the above assertion is True, it will reach until this point, otherwise it will stop in the previous line.
if tag:
print("inference function has been completed successfully")
return True
else:
return False
if __name__ == "__main__":
_ = inference(name="Bala")
'''
Function outputs,
Case 1: if year_to_expire = int(2021)
Hello Bala, the inference function has been successfully started
inference function has been completed successfully
[Finished in 0.2s]
Case 2: if year_to_expire = int(2022)
Hello Bala, the inference function has been successfully started
You license has been expired, please contact us.
[Finished in 0.2s]
'''
view raw utils.py hosted with ❤ by GitHub

The inference function is pretty straightforward and doesn’t need any explanation. Save the utils.py file in a folder.

2. Using PyArmor to encrypt it

Now we will encrypt the utils.py file by running the two below-mentioned commands.

pip3 install pyarmor # pip/pip3
# Syntax : pyarmor obfuscate --restrict=0 <filename>
pyarmor obfuscate --restrict=0 utils.py
1. Install-Package
2. Encrypt the utils.py function

Now if you see the folder containing our actual utils.py file, a new subfolder will be created called dist.

utils.py (original file)
Inside the dist folder where we have the (encrypted) utils.py file

The below image shows the content inside the dist folder.

Encrypted utils.py file inside dist subfolder

3. Importing our function / Inference

Once we are done, until this point, now let’s try to import this encrypted utils.py in a new python file called main.py, which is created inside the dist folder.

The necessary keys for decrypting the utils.py at run-time are taken care of by PyArmor and are present in the pytransform folder, thus making our code completely non-readable to others’ eyes.

But if you wish to modify the original utils.py code, then you have to start from step 1 and follow the same steps.

Contents inside main.py file,

# Import the inference function definition inside the utils.py file
from utils import inference
_ = inference(name="Balakrishna")

And upon running the above line, we get the output based on our utils.py file’s configuration.

The final output.

Conclusion:

This is merely the beginning. If you want to really protect and sell your code, consider adding an actual license with an embedded virtual date on it. Upon passing the date, it will no longer run the program and throws a license expiry error. Luckily PyArmor has that too.

I have added the license-related documentation in the references below. You can even set up a provision to email automatically once the license is expired and you can get in touch with your clients using the SMTP services in python.

Also if you have a lot of .py files to import or as dependencies, you must use the — recursive command line instead of the — restrict command for your code to work.

Also, this implementation can be done in both Windows and Ubuntu-based OS.

Hope I have explained the process of obfuscation in a very simple manner. It is the python program you need to make it difficult to read and understand and not my blog😁.

References:

Complete Code Implementation is available at,

https://github.com/bala-codes/Code-Encryption-Obfuscation—Python

For PyArmor:

  1. https://pypi.org/project/pyarmor/
  2. https://github.com/dashingsoft/pyarmor
  3. https://pyarmor.readthedocs.io/en/latest/
  4. https://pyarmor.readthedocs.io/en/latest/usage.html#generating-license-for-obfuscated-scripts
  5. https://docs.python.org/3/library/smtplib.html
Related posts:

Leave a Reply

Your email address will not be published. Required fields are marked *