介绍
在合同开发过程中,我认为有些情况下您必须将交付的产品交付给客户。在这种情况下,例如,如果该功能可以以SaaS的形式提供,则客户端将访问该API并使用该功能,因此,当然不可能在此端掌握源代码。
但是,我认为在许多情况下这是不现实的。有一个名为PyArmor的库在这种情况下很有用。 PyArmor是一个对源代码进行加密的库,从理论上讲,源代码无法恢复。当您要快速交付源代码时,这是一个非常方便的库。除了加密外,还可以在授予各种许可证(可用期限,执行设备等)之后进行加密。
关于PyArmor,如果您用google搜索,还会有其他文章发表,但是由于规范稍有变化,我这次尝试将其概述为一篇文章,其中包括备忘录的含义。
有关如何使用PyArmor的信息,请参阅以下官方文档。
PyArmor官方文档
该博客的源代码发布在[GitHub]上。有关环境,请参阅Mac的本地环境,有关所需的库,请参阅Pipfile。
其实尝试
加密前
这是加密之前的代码。 [Single_Module]
读取图像文件后,将训练有素的VGG16模型用于图像分类和图像显示。
Single_Module / main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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() |
您可以看到
结果也正确地分类为
加密
使用以下命令执行加密。
1 | $ pyarmor obfuscate main.py |
执行
之后,将直接在
-
pytransform / _pytransform.dylib
- 运行时使用的动态库(在Mac上为.dylib文件,在Linux上为.so文件)
-
dist / main.py
- 混淆文件
许可加密
尽管它在正式文档的
1 | $ pyarmor licenses --expired 2022-01-01 r001 |
然后,将直接在目录下创建
1 | $ pyarmor obfuscate --with-license licenses/r001/license.lic main.py |
然后,可以以具有到期日期的许可证形式进行加密。 [Single_Module_Obfuscating_pre]
-
如果您使用前面的命令尝试
--expired 2019-01-01 ,则将无法执行加密的主文件,因为它已经过期。 - 也可以通过与上述相同的方式颁发指定设备的许可证。有关详细信息,请参见官方文档。
执行加密的文件
加密后的主文件可以用与普通python脚本相同的方式执行。由于到目前为止,加密的主文件直接存在于
1 | $ python main.py |
[结果]
[out]球手
您可以看到结果与加密之前完全相同。另外,让我们尝试看看主文件的外观。
1 2 3 4 5 | $ cat main.py from pytransform import pyarmor_runtime pyarmor_runtime() __pyarmor__(__name__, __file__, b'\x50\x59\x41\x52 ...(以下省略) |
您可以看到它通常以这种方式加密。正如我在前面的项目符号列表中所写的那样,要执行此主文件,总是需要同时生成一个动态库。
混淆包含不同目录下的.py文件时
对于以前的方法,默认情况下,直接加密在其下面的所有
1 | $ pyarmor obfuscate --recursive main.py |
我会尝试的。
[Whole_Module]是加密之前的源代码,但是我们所做的是相同的。 (只需将文件分开)
正下方的
Whole_Module /模型/ model.py
1 2 3 4 5 6 7 8 9 10 11 12 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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() |
在这里,当执行上一条命令时,将创建一个新的