Python源码加密与Pytorch模型加密分别介绍

前言

深度学习领域,常常用python写代码,而且是建立在一些开源框架之上,如pytorch。在实际的项目部署中,也有用conda环境和python代码去部署服务器,在这个时候,又分为两种情况。

部署方式可分为两种,一种是在线部署,算法服务器归公司所有,只开放API给客户,客户通过POST请求访问算法服务器,上传数据并得到返回结果。这种情况客户当然看不到代码。还有一种是离线部署,就是给客户私有化部署,把公司的代码放到客户的服务器上运行,这种情况下客户能够看到代码。如果是python部署的项目,就需要保护两个东西,一个是模型文件,一个是python源代码。

一、python源代码的保护

由于 Python 的动态特性和开源特点,导致 Python 代码很难做到很好的加密。在实际工程部署中,如果不想让客户看到代码,一般使用C++来部署。

可是自己把代码改成c++也太费劲了,还好python提供了转c++代码的工具cpython,代码转成c++之后,编译成.so(linux)的库文件,就完成了加密效果了。整个过程已经有人写好了响应的工具,如jumy,具体参考:GitHub - Boris-code/jmpy: python 代码加密|加固

使用之前先安装jumy

pip install jmpy3

然后找到找到项目目录,在当前打开终端,并执行下面命令就能够完成编译。

jmpy -i "xxx project dir" [-o output dir]

加密后的文件默认存储在 dist/project_name/ 下。注意工程文件夹下,凡是带有if __name__=="__main__"的只要存在都不编译,注释掉一样不编译。其他的py文件才编译。所以在使用时可以把main文件暴露出来,其他的文件都编译成了.so的库文件。

优点:.so文件为二进制文件,无法反编译出源代码,源码可以得到有效保护。

缺点:编译过程会编译一些底层的代码进去,如python版本之类的,所以编译后的工程依旧依赖于环境,不能把其他机器上编译好的文件直接拿过去用。

二、pytorch模型.pth的加密

对于一个文件的加密其实还是容易,这里我们用AES(一种对称加密算法)对模型文件进行加密。

首先要安装一个包,里面包含很多加密算法,ubuntu上安装命令为‘

pip install pycrypto

然后写一个python脚本,实现读取模型文件,加密后保护的功能,和读取加密文件,解密后保存的功能。

from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
# 如果text不足16位的倍数就用空格补足为16位
def add_to_16(text:bytes):
    if len(text) % 16:
        add = 16 - (len(text) % 16)
    else:
        add = 0
    text = text + (b'\0' * add)
    return text
# 加密函数
def encrypt(text:bytes):
    # key = '9999999999999999'.encode('utf-8')
    key = 'tqsktqsktqsktqsk'.encode('utf-8')
    mode = AES.MODE_CBC
    iv = b'qqqqqqqqqqqqqqqq'
    text = add_to_16(text)
    cryptos = AES.new(key, mode, iv)
    cipher_text = cryptos.encrypt(text)
    # 因为AES加密后的字符串不一定是ascii字符集的,输出保存可能存在问题,所以这里转为16进制字符串
    return b2a_hex(cipher_text)
# 解密后,去掉补足的空格用strip() 去掉
def decrypt(text):
    key = 'tqsktqsktqsktqsk'.encode('utf-8')
    iv = b'qqqqqqqqqqqqqqqq'
    mode = AES.MODE_CBC
    cryptos = AES.new(key, mode, iv)
    plain_text = cryptos.decrypt(a2b_hex(text))
    return plain_text
if __name__ == '__main__':
    # encryption model
    with open('detect_model/checkpoints/xxx_ori.pth', 'rb') as f1:
        encrypted = encrypt(f1.read())
        with open('detect_model/checkpoints/xxx_encryp.pth', 'wb') as f2:
            f2.write(encrypted)
    # decryption model
    with open("./detect_model/checkpoints/xxx_decryp.pth", 'wb') as f:
        content = open('detect_model/checkpoints/xxx_encryp.pth', 'rb').read()
        f.write(decrypt(content))

这里用的是Crypto.Cipher模块的AES算法。模型文件加密后会比加密前的内存大一倍左右。

问题出现了。pytorch读取模型的函数torch.load()只能读取文件,并且返回一个FileIO的对象,来对文件进行操作。底层都是封死的,如果我们使用加密文件的时候要先解密成文件,那还怎么保密,可是没有办法,只能这么做。

理论上一个可行的办法是,把加密后的文件读入内存,然后对读取的内容(Bytes指针类型)进行解密,此时解密后的内容在内存中。但torch.load()只能读取文件,所以只能使用C++自己来写一个工具,完成内存解密的内容,加载到pytorch模型的操作,这个流程就比较复杂了,暂时没有实现。

到此这篇关于Python源码加密与Pytorch模型加密分别介绍的文章就介绍到这了,更多相关Python源码加密内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

你可能感兴趣的:(Python源码加密与Pytorch模型加密分别介绍)