PyArmor ~ Easy way to encrypt and deliver python source code ~

Introduction

When doing contract development, I think there are situations where you have to deliver the deliverables to the client. In such a case, for example, if the function can be provided as SaaS, the client side will hit the API and use the function, so of course it will not be possible to grasp the source code on this side. However, I think there are many situations where that is not realistic. There is a library called PyArmor that is useful in such cases. PyArmor is a library that encrypts the source code, and in theory the source code cannot be restored. It is a very convenient library when you want to deliver the source code quickly. In addition to just encrypting, it is also possible to encrypt after granting various licenses (usability period, execution device, etc.). Regarding PyArmor, other articles will come out if you google, but since the specifications have changed slightly, I tried to summarize it as an article this time including the meaning of the memo. For how to use PyArmor, refer to the official document below.

PyArmor Official Document

The source code of this blog is posted on [GitHub]. Please refer to the local environment of Mac for the environment and Pipfile for the required libraries.

Actually try

Before encryption

Here is the code before encryption. [Single_Module] After reading the image file, the trained VGG16 model is used for image classification and image display.

Single_Module/main.py


import os
import sys
import cv2
import numpy as np
import matplotlib.pyplot as plt
import torch
from torchvision import models, transforms

sys.path.append(os.path.abspath('..'))
import imagenet_class


img = cv2.imread('../baseball.png')
img = cv2.resize(img, (256, 256))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_tensor = transforms.ToTensor()(img)
img_tensor = img_tensor.unsqueeze_(0)

model = models.vgg16(pretrained=True)

output = model(img_tensor)
output = np.argmax(output.detach().numpy())

print(imagenet_class.target[str(output)][1])   # ballplayer

plt.imshow(img)
plt.show()

スクリーンショット 2020-08-26 18.31.36.png

You can see that the result is also correctly classified as ball player.

encryption

Encrypt with the following command.

$ pyarmor obfuscate main.py 

After execution, the dist directory will be created directly underneath. The contents file is as follows.

Licensed encryption

As you can see in the Generating License For Obfuscated Scripts section of the official documentation, first run the following command: (Freely name such as r001)

$ pyarmor licenses --expired 2022-01-01 r001

Then, the licenses directory will be created directly under it, and various files will be created under it. Next, as before, encrypt the main file with the pyarmor obfuscate command, but execute it with the following options.

$ pyarmor obfuscate --with-license licenses/r001/license.lic main.py

Then, it is possible to encrypt in the form of a license with an expiration date. [Single_Module_Obfuscating_pre]

--In addition, if you try --expired 2019-01-01 with the previous command, you will not be able to execute the encrypted main file because it has already expired. ――It is also possible to issue a license that specifies the device in the same way as above. See the official documentation for details.

Executing an encrypted file

The encrypted main file can be executed like a normal python script. The main file encrypted so far exists directly under the dist directory, so the relative path is slightly different from the original. Therefore, in order to align the paths, I made a configuration like [Single_Module_Obfuscating]. I haven't messed with anything other than changing the location of the files. Try executing the following command.

$ python main.py

【result】

[out] ballplayer

スクリーンショット 2020-08-26 18.31.36.png

You can see that the result is exactly the same as before encryption. Also, let's try and see what the main file looks like.

$ cat main.py

from pytransform import pyarmor_runtime
pyarmor_runtime()
__pyarmor__(__name__, __file__, b'\x50\x59\x41\x52 ...(Omitted below)

You can see that it is normally encrypted in this way. As I wrote in a bulleted list earlier, a dynamic library that is generated at the same time is always required for this main file to be executed.

Obfuscation including .py files under different directories

By default, all the .py files directly underneath are encrypted. If you want to recursively encrypt all .py files including subdirectories, execute with the following options.

$ pyarmor obfuscate --recursive main.py

I will try it. [Whole_Module] is the source code before encryption, but it is the same as before. (Just separate the files) The direct main.py is reading the model / model.py under the subdirect.

Whole_Module/model/model.py


from torch import nn
from torchvision import models


class SampleModel(nn.Module):
    def __init__(self):
        super(SampleModel, self).__init__()
        self.backborn = models.vgg16(pretrained=True)

    def forward(self, x):
        x = self.backborn(x)
        return x

Whole_Module/main.py


import os
import sys
import cv2
import numpy as np
import matplotlib.pyplot as plt
import torch
from torchvision import transforms

from model.model import SampleModel
sys.path.append(os.path.abspath('..'))
import imagenet_class


img = cv2.imread('../baseball.png')
img = cv2.resize(img, (256, 256))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_tensor = transforms.ToTensor()(img)
img_tensor = img_tensor.unsqueeze_(0)

model = SampleModel()

output = model(img_tensor)
output = np.argmax(output.detach().numpy())

print(imagenet_class.target[str(output)][1])

plt.imshow(img)
plt.show()

Here, when you execute the above command, a new dist directory will be created, and encrypted main.py, model.py, and dynamic library will be created. [Whole_Module_Obfuscating_pre]. However, since it cannot be executed for the same reason as before (the relative path of the image file is different), the generated file has been moved. This can also be executed without any problems as before. [Whole_Module_Obfuscating]

Recommended Posts

PyArmor ~ Easy way to encrypt and deliver python source code ~
Easy way to check the source of Python modules
Easy way to customize Python import
Easy way to use Wikipedia in Python
Easy way to use Python 2.7 on Cent OS 6
List of Python code to move and remember
An easy way to call Java from Python
Difference in writing method to read external source code between Ruby and Python
Rewrite Python2 code to Python3 (2to3)
Easy way to scrape with python using Google Colab
It's not easy to write Python, it's easy to write numpy and scipy
Easy to use Nifty Cloud API with botocore and python
How to parse Java source code with AST (Abstract Syntax Tree) using ANTLR and Python
Tips for coding short and easy to read in Python
A standard way to develop and distribute packages in Python
[Python] An easy way to visualize energy data interactively [plotly.express]
[Python] Another way to import
Easy way to rename files
Source installation and installation of Python
An easy way to view the time taken in Python and a smarter way to improve it
Convert python 3.x code to python 2.x
An easy way to hit the Amazon Product API in Python
Operate Jupyter with REST API to extract and save Python code
Easy way to round off to the nearest whole number with python3
[PEP8] Take over the Python source code and write it neatly
Code Python to check and graph if it follows Benford's law
How to build Python and Jupyter execution environment with VS Code
How to display bytes in the same way in Java and Python
Python 3.6 on Windows ... and to Xamarin.
[Introduction to Python3 Day 1] Programming and Python
[Code] Module and Python version output
Easy to use Jupyter notebook (Python3.5)
Python logging and dump to json
Selenium and python to open google
Easy Python to learn while writing
[Python] Read the Flask source code
Easy modeling with Blender and Python
[Python Tutorial] An Easy Introduction to Python
Easy way to enter and execute AtCoder test cases in Jupyter Notebook
Sample code to get the Twitter API oauth_token and oauth_token_secret in Python 2.7
Try to write python code to generate go code --Try porting JSON-to-Go and so on
Python code to train and test with Custom Vision of Cognitive Service
Installation of Visual studio code and installation of python
From Python to using MeCab (and CaboCha)
How to install and use pandas_datareader [Python]
python> link> strftime () and strptime () behavior / code
Bind methods to Python classes and instances
Getting Python source code metrics using radon
Fractal to make and play with Python
Porting and modifying doublet-solver from python2 to python3.
Read Python csv and export to txt
python: How to use locals () and globals ()
Flow from source code to creating executable
Encrypt with Ruby (Rails) and decrypt with Python
[Python] How to calculate MAE and RMSE
How to use Python zip and enumerate
Compress python data and write to sqlite
Easy introduction of python3 series and OpenCV3
Easy web scraping with Python and Ruby
A way to understand Python duck typing
How to use is and == in Python