😊 About the author: Hello, I'm hellobigorange. You can call me big orange
📃 Personal home page: Personal homepage of hellobigorange
📰 If you think the blogger's article is good, please 👍 Three companies support bloggers 🤞
💖 Abstract: This paper mainly realizes the automatic generation of encrypted files and the deletion of all unencrypted files when the container is started py files, and non The py file is moved to the folder with the same name in dist to make the encryption algorithm call normally.
Official Manual: pyarmor official manual
To avoid the risk of code leakage, we often need to encrypt the code. PyArmor is a tool for encrypting and protecting Python scripts. It can protect the binary code of Python script from being leaked at runtime, set the validity period of encrypted Python source code, and bind the encrypted Python source code to hard disk, network card and other hardware devices.
I. Basic Configuration
pip install pyarmor
- Update to the latest version
pip install --upgrade pyarmor
II. Basic grammar
2.1 encrypted Python script
a) Single package, single level directory only
Use the command obfuscate to encrypt python scripts. In the simplest case, the most common case is to switch to the main function script algorithm Py, and then execute:
pyarmor obfuscate algorithm.py
PyArmor encrypts algorithm py and all * py file:
- Create output subdirectory dist
- Generate encrypted main script algorithm Py is saved in the output directory dist
- Encrypt all other * py file, saved to the output directory dist
- Generate all auxiliary files required to run the encryption script and save them to the output directory dist
b) If there are multiple algorithm packages and multi-level directories
By default, only other * py will be encrypted at the same time. If you want to recursively encrypt all * py file, using the following command:
pyarmor obfuscate --recursive algorithm.py
🙇 Note: only encryption is allowed py file, if the algorithm needs to be called csv，. The json file can be directly copied to the package corresponding to the dist folder
2.2 running encryption script
pyarmo does not need to be installed to run the encryption script
2.3 publish encryption script
After this step, you can publish the encryption script. To publish the encryption script, you only need to copy all dist files in the output path.
Because the script encrypted by pyarmo is sensitive to the running environment, we'd better package the entire algorithm into an image, encrypt it when starting the container, delete all unencrypted files, and leave dist files
Note: as mentioned above, pyrmo can only py file encryption, for csv，. json files cannot be encrypted. Naturally, there is no non - non - Encryption in the generated dist package py suffix file, so we need to add Move CSV and other files into dist, otherwise an error will be reported when running the algorithm in dist.
Because my local is a windows system, it is generated dll suffix file. If dist is directly made into an image, an error will be reported because the container needs to run So file, so consider runtime encryption in the container to generate So, and then automatically remove the unencrypted text key, leaving only dist and the required non py suffix file
In fact, you can also use the linux system to directly generate dist locally, but don't forget to set non py suffix files and folders are copied in.
The following will take the algorithm package of myprocessor as an example to describe the whole process:
It can be seen that there are multiple algorithm packages calling each other, and there are many non py file
FROM python:3.6 # Import python3.6 basic environment RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime\ && echo 'Asia/Shanghai'>/etc/timezone # Synchronize system time COPY ./ ./app/ # Copy all files and folders in the algorithm to the image WORKDIR /app/ # Set the app in the image as the main folder RUN pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple \ RUN pyarmor obfuscate --recursive myprocessor.py # Recursively encrypt all algorithms RUN ls # Display all files in the app CMD ["python3","/app/dist/myprocessor.py"] # Run the encrypted main function in dist
# Here are the modules that my algorithm depends on. pyarmor==7.4.2 must be added. Others must be added according to their own algorithm pyarmor==7.4.2 pandas == 1.1.5 numpy == 1.19.5 requests == 2.25.1
3.3 encryption function lock_by_pyarmor.py
# -*- coding: utf-8 -*- # @Time : 2022/4/20 10:10 # @Author : Orange # @File : lock_by_pyarmor.py import shutil import os class File_lock(): def __init__(self): self.root_path = os.getcwd() # Current working path def remove_and_del_unsecret_dir_f(self): '''Remove unencrypted py and pyc Files, copying non py,pyc File to dist''' for root, dir, files in os.walk(self.root_path): if "dist" not in root: for file in files: if os.path.splitext(file)[-1] in ['.py', '.pyc']: # Delete all unencrypted py and pyc file os.remove(os.path.join(root, file)) else: # Since non py files cannot be encrypted, move non py files to a folder with the same name. If a folder with the same name cannot be found, create a folder with the same name if root == self.root_path: dist_same_die_path = os.path.join(self.root_path, 'dist') else: dist_same_die_path = os.path.join(self.root_path, 'dist', os.path.basename(root)) if not os.path.exists(dist_same_die_path): os.mkdir(dist_same_die_path) shutil.move(os.path.join(root, file), dist_same_die_path) temp_list = os.listdir() # Remove all empty folders except dist temp_list.remove('dist') for i in temp_list: os.rmdir(i) def lock_by_pyarmor(self): # print("current working path:", self.root_path) # print("os.listdir", os.listdir()) if (not os.path.exists(os.path.join(self.root_path, "dist"))): # If dist does not exist os.system("pyarmor obfuscate --recursive myprocessor.py") # encryption self.remove_and_del_unsecret_dir_f() else: # print("encrypted folder:", os.listdir()) self.remove_and_del_unsecret_dir_f() # print("after removing unencrypted files:", os.listdir())
3.4 main function myprocessor py
from lock_by_pyarmor import File_lock def call(arg, model, *args, **kwargs): lockf = File_lock() lockf.lock_by_pyarmor() from deviation_algothrim.get_deviation import Deviation from loss_power.get_loss_power import GetPower pass if __name__ == "__main__": print(call(arg=None, model=None))
👴: Note that the required content should be imported from other packages and placed in lockf lock_ by_ After pyarmor (), otherwise, the dist file has not been completely built, and an error may be reported when calling.
3.5 create an image and verify the effect
- docker build _t imag1 .
After the image is created, the directory in the app is
- docker run -d imag1 /bin/bash -c "tail -f /dev/null"
- docker ps \
- docker exec -it 2293ee92f3ca /bin/bash \
- python /app/dist/myprocessor.py \
You can see that only the dist file is left in the app.
Finally, you need to repackage the started container into an image and publish it to harbor: docker commit 2293ee92f3ca7 new_image to discard the original image. Because there are unencrypted files in the original image and they can be accessed.
You can export the encrypted files in the container to the local D disk: docker cp bf5f2e815b64:/app D:/
📢 ps: if there is a problem, or lock_by_pyarmor.py has a better implementation method. I hope you can correct it 🙆.