我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python代码加密方案

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python代码加密方案

为何要对代码加密? python的解释特性是将py编译为独有的二进制编码pyc 文件,然后对pyc中的指令进行解释执行,但是pyc的反编译却非常简单,可直接反编译为源码,当需要将产品发布到外部环境的时候,源码的保护尤为重要。 常见的源码保护手段有如下几种:
  1. 发行.pyc文件  
  2. 代码混淆
  3. 使用py2exe
  4. 使用Cython

一、发行.pyc文件

pyc文件是一种二进制文件,由原生Python文件经过编译后所生成的,py文件编译成pyc文件后加载速度更快而且提高了代码的安全性。pyc的内容与python的版本相关,不同版本编译的pyc文件不一样。

1.1、编译.pyc文件

编译单个py:
python -m compileall xxx.py  # 把单个.py文件编译为字节码文件

pyc会生成在目录下的__pycache__下(前后有双下划线) 生成的文件名命名方式:源文件名.cpython-python版本.pyc     编译多个
python -m compileall /path/class="lazy" data-src/ # 批量生成字节码文件,/path/class="lazy" data-src/是包含.py文件名的路径
     将.py文件转化为.pyc文件,实现代码隐藏的需要;.pyc文件的使用与.py文件的使用相同。
# 安装pip install compileall2import compileall# compile_file编译单个文件compileall.compile_file('main.py')# compile_dir 函数编译文件夹下的py文件compileall.compile_dir('Lib/', force=True)# 使用多处理器编译compileall.compile_dir('Lib/', workers=2)

1.2、反编译.pyc文件 (.pyc -> .py)

# 安装 uncompylepip install uncompyle# 把 name.pyc 反编译成 name.pyuncompyle6 name.pyc > name.py反编译多个文件:uncompyle6 -o . *.pyc

1.3、优缺点

优点:
  • 简单方便,提高了一点源码破解门槛
  • pyc 文件的加载速度比 py 文件快
  • 平台兼容性好,.py能在哪里运行,.pyc就能在哪里运行
不足:
  • 解释器兼容性差, .pyc只能在特定版本的解释器上运行
  • 有现成的反编译工具, 破解成本低

二、代码混淆

代码混淆是指在不改变代码逻辑的情况下,对代码结构进行变换,通过一些带有混淆性质的命名、注释等,使代码变得晦涩难懂,从而达到保护代码的作用。

可以这样下手:

  • 移除注释和文档。没有这些说明,在一些关键逻辑上就没那么容易明白了。

  • 改变缩进。完美的缩进看着才舒服,如果缩进忽长忽短,看着也一定闹心。

  • 在 tokens 中间加入一定空格。这就和改变缩进的效果差不多。

  • 重命名函数、类、变量。命名直接影响了可读性,乱七八糟的名字可是阅读理解的一大障碍。

  • 在空白行插入无效代码。这就是障眼法,用无关代码来打乱阅读节奏。

实现方法:

  1. 网站混淆:Oxyry Python Obfuscator - The most reliable python obfuscator in the world, 破解: https://www.cnblogs.com/Eeyhan/p/13154217.html

  2. 使用 pyobfuscate 库进行混淆   (2条消息) Python 源码混淆与加密_pyobfuscate_早起的python的博客-CSDN博客

优点:

  • 简单方便,提高了一点源码破解门槛

  • 兼容性好,只要源码逻辑能够做到兼容,混淆代码亦能

不足:

  • 只能对单个文件混淆,无法做到多个互相有联系的源码文件的联动混淆

  • 代码结构未发生变化,也能获取字节码,破解难度不大

三、打包

类似的还有pyinstaller、Nuitka

  • pyinstaller是通过设置key来对源码进行加密的;
  • nuitka则是将python源码转成C++(这里得到的是二进制的pyd文件,防止了反编译),然后再编译成可执行文件。 
  • py2exe 是一款将 Python 脚本转换为 Windows 平台上的可执行文件的工具。其原理是将源码编译为.pyc文件,加之必要的依赖文件,一起打包成一个可执行文件。

3.1、py2exe打包

使用py2exe进行打包的步骤:

1、编写入口文件。本示例中取名为hello.py:print('Hello World') 2、编写setup.pyfrom distutils.core import setupimport py2exe setup(console=['hello.py']) 3、生成可执行文件python setup.py py2exe

 

优点:

  • 能够直接打包成 exe,方便分发和执行

  • 破解门槛比 .pyc 更高一些

不足:

  • 兼容性差,只能运行在 Windows 系统上

  • 生成的可执行文件内的布局是明确、公开的,可以找到源码对应的.pyc文件,进而反编译出源码

3.2、pyinstaller打包

安装pyinstaller

在Terminal下输入:“pyinstaller -F -w *.py” 就可以制作出exe。生成的文件放在同目录dist下。

常用选项​​​

-F(注意大写)是所有库文件打包成一个exe。不加-F参数生成一堆文件,但运行快,压缩后比单个exe文件还小一点点。 加-F参数生成一个exe文件,运行起来慢。-D:默认选项,创建一个目录,包含exe文件以及大量依赖文件;-a,–ascii   不包含 Unicode 字符集支持;-d,–debug   产生 debug 版本的可执行文件;-i: 后接图标文件名,后缀是.ico,表示用自定义图标生成exe程序-c:默认选项,使用控制台(就是类似cmd的黑框);(仅对 Windows 有效);-w: 生成的exe程序不带窗口执行(仅对 Windows 有效);-o DIR,–out=DIR 指定 spec 文件的生成目录。如果没有指定,则默认使用当前目录来生成 spec 文件;-p 表示你自己自定义需要加载的类路径,一般情况下用不到;-n NAME,–name=NAME  指定项目(产生的 spec)名字。如果省略该选项,那么第一个脚本的主文件名将作为 spec 的名字;-i  选择图标

示例:

book.py:

import webbrowserurl="https://blog.csdn.net/leiwuhen92?type=blog"print("hello world")webbrowser.open_new(url)

打包指令:

pyinstaller -F  -i test.ico.ico -w book.py

 

优点:

  • 隐藏源码
  • 方便一用户使用方便,不用再安装什么python啊,第三方包之类的。

缺点:

 3.3、Nuitka打包

使用python打包工具nuitka进行编译打包 - 知乎 (zhihu.com)

nuitka的作用是将python程序转换成C语言的可执行elf文件。这样在运行时就可以享受到C语言处理过程中的优化,提高速度。经测试,Nuitka打包后的exe比Pyinstaller打包后的exe运行速度提升30%

对于第三方依赖包较多的项目(比如需要import torch,tensorflow,cv2,numpy,pandas,geopy等等)而言,这里最好打包的方式是只将属于自己的代码转成C++,不管这些大型的第三方包!

指令:

python -m nuitka --standalone --show-memory --show-progress --nofollow-imports --plugin-enable=qt-plugins --follow-import-to=utils,class="lazy" data-src --output-dir=out --windows-icon-from-ico=./logo.ico demo.py参数:--standalone:方便移植到其他机器,不用再安装python--show-memory --show-progress:展示整个安装的进度过程--nofollow-imports:不编译代码中所有的import,比如keras,numpy之类的。--plugin-enable=qt-plugins:我这里用到pyqt5来做界面的,这里nuitka有其对应的插件。--follow-import-to=utils,class="lazy" data-src:需要编译成C++代码的指定的2个包含源码的文件夹,这里用,来进行分隔。--output-dir=out:指定输出的结果路径为out。--windows-icon-from-ico=./logo.ico:指定生成的exe的图标为logo.ico这个图标,这里推荐一个将图片转成ico格式文件的网站(比特虫)。--windows-disable-console:运行exe取消弹框。这里没有放上去是因为我们还需要调试,可能哪里还有问题之类的。

 四、使用Cython

原理:先用cython将python语言代码转换为c语言代码,然后用c编译器(gcc)生成可执行文件或动态链接库。

4.1、Cpython介绍

Cython是一个编程语言,它通过类似Python的语法来编写C扩展并可以被Python调用,既具备了Python快速开发的特点,又可以让代码运行起来像C一样快,同时还可以方便地调用C library。
Cython是属于python的超集,用于编写python的c扩展语言。
  
pyx文件由 Cython 编译为.c文件,包含 python 扩展模块的代码。.c文件由 C 编译器编译为.so文件(或 Windows 上的.pyd)。
生成的.so文件或pyd文件是D语言(C/C++综合进化版本)生成的二进制文件,理论上很难反编译。

Note: 纯python源码被cython编译后,因为没有使用类型标注等cython语法,故编译后的动态链接库和可执行文件,主要依赖python的运行时,并不依赖C/C++运行时,主要由python解释器执行,多线程GIL的问题同样存在,性能提升有限,但对for循环、大的列表对象遍历性能有明显优化效果。

4.2、安装

# 安装cythonpip3 install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple cython # 安装c编译器(linux需安装python-devel, gcc)centos: yum install python-devel  gccubuntu: apt-get install build-essential

4.3、使用

先用cython将python语言代码转换为c语言代码,然后用c编译器(gcc)生成可执行文件或动态链接库。
  
通过shell 或 python脚本的方式,将项目启动的入口py编译成可执行文件,将项目的其他.py文件编译成.so(__init__.py除外)

Note: __init__.py文件定义了python的包结构,为了使cython编译后的.so能按照正常路径import,__init__.py不能被编译,故为了保护代码,整个项目的所有__init__.py文件不建议放业务相关代码。

4.3.1、单个文件的编译示例-linux

目录结构如下:
test/
├── test.py
├── main.py

test.py:

def hello():    print('hello!')

main.py:文件头的#!/usr/bin/python3.8标记是否程序启动文件

#!/usr/bin/python3.8from test import hello if __name__ == "__main__":    hello()

4.3.1.1、将启动main.py编译成二进制可执行文件main

 main.py ---> main.c ---> main.o ---> main :

# step1: 将python代码翻译成c代码(main.py -> main.c)cython -D -3 --directive always_allow_keywords=true --embed main.py # step2: 将c代码编译为目标文件(main.c -> main.o)gcc -c main.c -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o main.o # step3: 将目标文件编译为二进制可执行文件(main.o -> main)gcc main.o -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o main

 main.py ---> main.c ---> main:

# step1: 将python代码翻译成c代码(main.py -> main.c)cython -D -3 --directive always_allow_keywords=true --embed main.py # step2: 将c代码编译为二进制可执行文件(main.c -> main)gcc main.c -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o main

4.3.1.2、将test.py编译为动态链接库test.so

test.py ---> test.c ---> test.so

# step1: 将python代码翻译成c代码(test.py -> test.c)cython -D -3 --directive always_allow_keywords=true test.py # step2: 将c代码编译为linux动态链接库文件(test.c -> test.so)gcc test.c -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o test.so

 cython参数说明:

-D, --no-docstrings, Strip docstrings from the compiled module.-o, --output-file    Specify name of generated C file-2                             Compile based on Python-2 syntax and code semantics.-3                             Compile based on Python-3 syntax and code semantics.

gcc参数说明:

-shared:编译动态库时要用到-pthread:在Linux中要用到多线程时,需要链接pthread库-fPIC:作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。-fwrapv:它定义了溢出时候编译器的行为——采用二补码的方式进行操作-O参数这是一个程序优化参数,一般用-O2就是,用来优化程序用的-O2:会尝试更多的寄存器级的优化以及指令级的优化,它会在编译期间占用更多的内存和编译时间。-O3: 在O2的基础上进行更多的优化-Wall:编译时 显示Warning警告,但只会显示编译器认为会出现错误的警告-fno-strict-aliasing:“-fstrict-aliasing”表示启用严格别名规则,“-fno-strict-aliasing”表示禁用严格别名规则,当gcc的编译优化参数为“-O2”、“-O3”和“-Os”时,默认会打开“-fstrict-aliasing”。-I (大写的i):是用来指定头文件目录-I /home/hello/include表示将/home/hello/include目录作为第一个寻找头文件的目录,寻找的顺序是:/home/hello/include-->/usr/include-->/usr/local/include-l:-l(小写的 L)参数就是用来指定程序要链接的库,-l参数紧接着就是库名,把库文件名的头lib和尾.so去掉就是库名了,例如我们要用libtest.so库库,编译时加上-ltest参数就能用上了

4.3.2、单个文件的编译示例-windows

windows系统使用cython需要确保已安装C/C++编译器且环境变量正确配置,cython能找到编译器。windows系统可使用MSVC(Microsoft Visual C/C++)或者clang编译器。 

将test.py编译为动态链接库test.pyd:
test.py ---> test.c ---> test.pyd:

# step1: 将python代码翻译成c代码(test.py -> test.c)cython -D -3 --directive always_allow_keywords=true test.py # step2: 将c代码编译为windows动态链接库文件(test.c -> test.pyd)cythonize -i test.c

最后得到windows下的动态链接库文件test.cp39-win_amd64.pyd,还需要将文件名重命名为test.pyd。

cythonize参数说明:

-b, --build     build extension modules using distutils-i, --inplace   build extension modules in place using distutils(implies -b),即将编译后的扩展模块直接放在与test.py同级的目录中。

 4.3.3、python编译可执行文件与动态链接库

 https://github.com/leiwuhen92/cython_test  

main.py:主函数入口

#!/usr/bin/python3.8from test import hellofrom compute import compute if __name__ == "__main__":    hello()    compute.is_leap_year(1992)

test.py:

def hello():    print('hello!')

compute/compute.py:

def is_leap_year(year):    if year%4==0 and year%100!=0 or year%400==0:        print(year,"是闰年")    else:        print(year,"不是闰年")  if __name__ == "__main__":    is_leap_year(1992)

setup.py:

import pathlibimport shutilfrom subprocess import Popen, PIPE, STDOUT  # python编译sodef py_to_so(py_to_so_list):    """    :param py_to_so_list:  py文件列表,例如[test.py,]    :return:    """    for py_to_so_item in py_to_so_list:        # 将python代码翻译成c代码        basename = py_to_so_item[:-3]        py_to_c = "cython -D -3 --directive always_allow_keywords=true --embed {}".format(py_to_so_item)        pl = Popen(py_to_c, shell=True, stdout=PIPE, stderr=STDOUT)        pl.communicate()[0].decode('utf-8', errors='ignore')         # 将c代码编译为linux动态链接库文件(        c_to_so = "gcc {} -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o {}".format(basename + ".c", basename + ".so")        p2 = Popen(c_to_so, shell=True, stdout=PIPE, stderr=STDOUT)        p2.communicate()[0].decode('utf-8', errors='ignore')  def py_to_bin(py_to_bin_list):    """    :param py_to_bin_list: py文件列表,例如[main.py,]    :return:    """    for py_to_bin_item in py_to_bin_list:        basename = py_to_bin_item[:-3]        # 将python代码翻译成c代码        py_to_c = "cython -D -3 --directive always_allow_keywords=true --embed {}".format(py_to_bin_item)        p1 = Popen(py_to_c, shell=True, stdout=PIPE, stderr=STDOUT)        p1.communicate()[0].decode('utf-8', errors='ignore')         # 将c代码编译为二进制可执行文件        c_to_bin = "gcc {} -I /usr/include/python3.8 -L /usr/bin -lpython3.8 -o {}".format(basename + ".c", basename)        p2 = Popen(c_to_bin, shell=True, stdout=PIPE, stderr=STDOUT)        p2.communicate()[0].decode('utf-8', errors='ignore')  def clean_build(project):    """    清理编译文件夹中的文件    :param project:    :return:    """    # 清理py文件    for i in project.glob("***.c"):        j.unlink()     # 清理__pycache__文件夹    for k in project.glob("**/__pycache__"):        shutil.rmtree(k)  if __name__ == "__main__":    # 源文件夹    project_pathlib = pathlib.Path.cwd()     py_to_bin_list = ["main.py"]    py_to_bin(py_to_bin_list)     py_to_so_list = ["test.py"]    for py in project_pathlib.glob("**/*.py"):        if py.name != "__init__.py" and py.name != "setup.py" and py.name != "main.py":            py_to_so_list.append(str(py))    py_to_so(py_to_so_list)     clean_build(project_pathlib)

 4.4、优缺点

优点

  • 生成的二进制so(linux)或.pyd(windows)文件难以破解

  • 性能会提升

不足

  • 兼容性稍差,对于不同版本的操作系统,可能需要重新编译

  • 虽然支持大多数Python代码,但如果一旦发现部分代码不支持,完善成本较高

来源地址:https://blog.csdn.net/leiwuhen92/article/details/131307265

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

python代码加密方案

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python代码部署的三种加密方案

本文主要介绍了Python代码部署的三种加密方案,主要介绍了代码混淆、代码编译、代码打包这三种,具有一定的参考价值,感兴趣的可以了解一下
2023-02-06

Python源代码保密、加密、混淆

有时候用Python开发一些功能但不希望用户得到源代码,就希望对Python代码加一些保密措施。目前可行的方案可能是将核心代码用cython编译成os文件。分析如下:生成方式看这里。Python作为脚本语言,基本上只要是能得到pyc或pyo
2023-01-31

怎么给python代码加密

要给Python代码加密,可以使用以下方法之一:1. 使用编译器或打包工具:将Python代码编译成字节码或将其打包成可执行文件。这样,代码将被转换为机器语言或二进制文件,使其难以被逆向工程或修改。常用的工具有Nuitka、PyInstal
2023-10-18

python实现希尔密码加密的示例代码

目录原理实现原理 希尔密码是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明。 每个字母当作26进制数字:A=0, B=1, C=2… 一串字母当成n维向量,跟一个n×n的矩阵相乘,再将得出的结果模26。(注意用
2022-06-02

如何加密Lua代码

要加密Lua代码,可以使用Lua的加密工具或编码器来实现。以下是一些常见的方法:1. 使用luac:Lua提供了一个名为luac的编译器,可以将Lua代码编译为字节码文件,这样代码就无法直接阅读。使用命令`luac -o encrypted
2023-09-27

Python中怎么加密密码

今天就跟大家聊聊有关Python中怎么加密密码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。如何在Python中加密密码加密密码会将密码编码为随机字符序列。使用base64.b64e
2023-06-16

android md5加密与rsa加解密实现代码

代码如下: import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgori
2022-06-06

Python编程密码学文件加密与解密的方法

本文小编为大家详细介绍“Python编程密码学文件加密与解密的方法”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python编程密码学文件加密与解密的方法”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。本章要点o
2023-06-30

Python3代码工程化加密

这几天公司的Python3需要加密,网上的文章要么提供思路不提供代码,要么加密之后自己都没法用了。。没办法只能自己写了文章整体思路   1、修改python源码opcode为随机值   修改下载后的Python源码包中opcode值(opc
2023-01-31

shiro编码和加密代码详解

涉及到密码存储问题上,应该加密/生成密码摘要存储,而不是存储明文密码。比如之前的600w csdn账号泄露对用户可能造成很大损失,因此应加密/生成不可逆的摘要方式存储。编码/解码 Shiro提供了base64和16进制字符串编码/解码的AP
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录