参考地址:https://www.cnblogs.com/dhcn/p/11077447.html

0 前言

去年11月在PyCon China 2018 杭州站分享了 Python 源码加密,讲述了如何通过修改 Python 解释器达到加解密 Python 代码的目的。然而因为笔者拖延症发作,一直没有及时整理成文字版,现在终于战胜了它,才有了本文。

本系列将首先介绍下现有源码加密方案的思路、方法、优点与不足,进而介绍如何通过定制 Python 解释器来达到更好地加解密源码的目的。

由于 Python 的动态特性和开源特点,导致 Python 代码很难做到很好的加密。社区中的一些声音认为这样的限制是事实,应该通过法律手段而不是加密源码达到商业保护的目的;而还有一些声音则是不论如何都希望能有一种手段来加密。于是乎,人们想出了各种或加密、或混淆的方案,借此来达到保护源码的目的。

常见的源码保护手段有如下几种:

  • 发行 .pyc 文件
  • 代码混淆
  • 使用 py2exe
  • 使用 Cython

下面来简单说说这些方案。

1 发行 .pyc 文件

1.1 思路

大家都知道,Python 解释器在执行代码的过程中会首先生成 .pyc 文件,然后解释执行 .pyc文件中的内容。当然了,Python 解释器也能够直接执行 .pyc 文件。而 .pyc 文件是二进制文件,无法直接看出源码内容。如果发行代码到客户环境时都是 .pyc 而非 .py 文件的话,那岂不是能达到保护 Python 代码的目的?

1.2 方法

把 .py 文件编译为 .pyc 文件,是件非常轻松地事情,可不需要把所有代码跑一遍,然后去捞生成的 .pyc 文件。

事实上,Python 标准库中提供了一个名为 compileall 的库,可以轻松地进行编译。

执行如下命令能够将遍历 <src> 目录下的所有 .py 文件,将之编译为 .pyc 文件:

python -m compileall <src> 然后删除 <src> 目录下所有 .py 文件就可以打包发布了:

$ find <src> -name '*.py' -type f -print -exec rm {} \;

1.3 优点

  • 简单方便,提高了一点源码破解门槛
  • 平台兼容性好,.py 能在哪里运行,.pyc 就能在哪里运行

1.4 不足

  • 解释器兼容性差,.pyc 只能在特定版本的解释器上运行
  • 有现成的反编译工具,破解成本低

python-uncompyle6 就是这样一款反编译工具,效果出众。

执行如下命令,即可将 .pyc 文件反编译为 .py 文件:

$ uncompyle6 *compiled-python-file-pyc-or-pyo*

2 代码混淆

如果代码被混淆到一定程度,连作者看着都费劲的话,是不是也能达到保护源码的目的呢?

2.1 思路

既然我们的目的是混淆,就是通过一系列的转换,让代码逐渐不让人那么容易明白,那就可以这样下手: - 移除注释和文档。没有这些说明,在一些关键逻辑上就没那么容易明白了。 - 改变缩进。完美的缩进看着才舒服,如果缩进忽长忽短,看着也一定闹心。 - 在tokens中间加入一定空格。这就和改变缩进的效果差不多。 - 重命名函数、类、变量。命名直接影响了可读性,乱七八糟的名字可是阅读理解的一大障碍。 - 在空白行插入无效代码。这就是障眼法,用无关代码来打乱阅读节奏。

2.2 方法

方法一:使用 oxyry 进行混淆

http://pyob.oxyry.com/ 是一个在线混淆 Python 代码的网站,使用它可以方便地进行混淆。

假定我们有这样一段 Python 代码,涉及到了类、函数、参数等内容:

# coding: utf-8class A(object):"""Description"""def __init__(self, x, y, default=None):self.z = x + yself.default = defaultdef name(self):return 'No Name'def always():return Truenum = 1
a = A(num, 999, 100)
a.name()
always()

经过 Oxyry 的混淆,得到如下代码:

class A (object ):#line:4""#line:7def __init__ (O0O0O0OO00OO000O0 ,OO0O0OOOO0000O0OO ,OO0OO00O00OO00OOO ,OO000OOO0O000OOO0 =None ):#line:9O0O0O0OO00OO000O0 .z =OO0O0OOOO0000O0OO +OO0OO00O00OO00OOO #line:10O0O0O0OO00OO000O0 .default =OO000OOO0O000OOO0 #line:11def name (O000O0O0O00O0O0OO ):#line:13return 'No Name'#line:14
def always ():#line:17return True #line:18
num =1 #line:21
a =A (num ,999 ,100 )#line:22
a .name ()#line:23
always ()

混淆后的代码主要在注释、参数名称和空格上做了些调整,稍微带来了点阅读上的障碍。

方法二:使用 pyobfuscate 库进行混淆

pyobfuscate 算是一个颇具年头的 Python 代码混淆库了,但却是“老当益壮”了。

对上述同样一段 Python 代码,经 pyobfuscate 混淆后效果如下:

# coding: utf-8
if 64 - 64: i11iIiiIii
if 65 - 65: O0 / iIii1I11I1II1 % OoooooooOO - i1IIi
class o0OO00 ( object ) :if 78 - 78: i11i . oOooOoO0Oo0Oif 10 - 10: IIiI1I11i11if 54 - 54: i11iIi1 - oOo0O0Oooif 2 - 2: o0 * i1 * ii1IiI1i % OOooOOo / I11i / Ii1Idef __init__ ( self , x , y , default = None ) :self . z = x + yself . default = defaultif 48 - 48: iII111i % IiII + I1Ii111 / ooOoO0o * Ii1Idef name ( self ) :return 'No Name'if 46 - 46: ooOoO0o * I11i - OoooooooOOif 30 - 30: o0 - O0 % o0 - OoooooooOO * O0 * OoooooooOO
def Oo0o ( ) :return Trueif 60 - 60: i1 + I1Ii111 - I11i / i1IIiif 40 - 40: oOooOoO0Oo0O / O0 % ooOoO0o + O0 * i1IIi
I1Ii11I1Ii1i = 1
Ooo = o0OO00 ( I1Ii11I1Ii1i , 999 , 100 )
Ooo . name ( )
Oo0o ( ) # dd678faae9ac167bc83abf78e5cb2f3f0688d3a3

相比于方法一,方法二的效果看起来更好些。除了类和函数进行了重命名、加入了一些空格,最明显的是插入了若干段无关的代码,变得更加难读了。

2.3 优点

  • 简单方便,提高了一点源码破解门槛
  • 兼容性好,只要源码逻辑能做到兼容,混淆代码亦能

2.4 不足

  • 只能对单个文件混淆,无法做到多个互相有联系的源码文件的联动混淆
  • 代码结构未发生变化,也能获取字节码,破解难度不大

3 使用 py2exe

3.1 思路

py2exe 是一款将 Python 脚本转换为 Windows 平台上的可执行文件的工具。其原理是将源码编译为 .pyc 文件,加之必要的依赖文件,一起打包成一个可执行文件。

如果最终发行由 py2exe 打包出的二进制文件,那岂不是达到了保护源码的目的?

3.2 方法

使用 py2exe 进行打包的步骤较为简便。

1)编写入口文件。本示例中取名为 hello.py

print 'Hello World'

2)编写 setup.py

from distutils.core import setup
import py2exesetup(console=['hello.py'])

3)生成可执行文件

python setup.py py2exe

生成的可执行文件位于 dist\hello.exe

3.3 优点

  • 能够直接打包成 exe,方便分发和执行
  • 破解门槛比 .pyc 更高一些

3.4 不足

  • 兼容性差,只能运行在 Windows 系统上
  • 生成的可执行文件内的布局是明确、公开的,可以找到源码对应的 .pyc 文件,进而反编译出源码

4 使用 Cython

4.1 思路

虽说 Cython 的主要目的是带来性能的提升,但是基于它的原理:将 .py/.pyx 编译为 .c 文件,再将 .c 文件编译为 .so(Unix) 或 .pyd(Windows),其带来的另一个好处就是难以破解。

4.2 方法

使用 Cython 进行开发的步骤也不复杂。

1)编写文件 hello.pyx 或 hello.py

def hello():print('hello')

2)编写 setup.py

from distutils.core import setup
from Cython.Build import cythonizesetup(name='Hello World app',ext_modules=cythonize('hello.pyx'))

3)编译为 .c,再进一步编译为 .so 或 .pyd

python setup.py build_ext --inplace

执行 python -c "from hello import hello;hello()" 即可直接引用生成的二进制文件中的 hello() 函数。

4.3 优点

  • 生成的二进制 .so 或 .pyd 文件难以破解
  • 同时带来了性能提升

4.4 不足

  • 兼容性稍差,对于不同版本的操作系统,可能需要重新编译
  • 虽然支持大多数 Python 代码,但如果一旦发现部分代码不支持,完善成本较高

Python常见的几种代码加密方法相关推荐

  1. python最快的循环方法_【转】【Python效率】五种Pandas循环方法效率对比

    [Python效率]五种Pandas循环方法效率对比 - 文兄的文章 - 知乎 https://zhuanlan.zhihu.com/p/80880493 正文: 如果你使用过Python及Panda ...

  2. 循环下标_【转】【Python效率】五种Pandas循环方法效率对比

    [Python效率]五种Pandas循环方法效率对比 - 文兄的文章 - 知乎 https://zhuanlan.zhihu.com/p/80880493 正文: 如果你使用过Python及Panda ...

  3. 常见的几种身份验证方法

    常见的几种身份验证方法 在做项目时,我们常常会对登陆用户的合法性进行判断,接下来我就给大家介绍几中常见的身份验证的方法. 1.session校验 最先是session校验,这块一般是初学者最先做的一种 ...

  4. 数据科学中常见的9种距离度量方法(包括曼哈顿距离、欧氏距离、半正矢距离等)

    数据科学中常见的9种距离度量方法(包括曼哈顿距离.欧氏距离.半正矢距离等) 1.欧氏距离(Euclidean Distance) 2.余弦相似度(Cosine Similarity) 3.汉明距离(H ...

  5. js常见的几种页面刷新方法

    js常见的几种页面刷新方法如下: 1 history.go(0); 2 location.reload(); 3 location=location; 4 location.assign(locati ...

  6. OpenResty 常见的几种数据共享的方法

    OpenResty 常见的几种数据共享的方法 1. Nginx 中的变量 2. ngx.ctx 3. 模块级别的变量 3.1 关于变量竞争的问题 4. shared dict 4.1 shared d ...

  7. 实战!Python常见的几种数据可视化案例

    大家好,我是辰哥. 利用可视化探索图表 一.数据可视化与探索图 数据可视化是指用图形或表格的方式来呈现数据.图表能够清楚地呈现数据性质, 以及数据间或属性间的关系,可以轻易地让人看图释义.用户通过探索 ...

  8. 【机器学习基础】常见的9种距离度量方法,内含欧氏距离、切比雪夫距离等

    作者|机器之心编译 来源|机器之心 在数据挖掘中,我们经常需要计算样本之间的相似度,通常的做法是计算样本之间的距离.在本文中,数据科学家 Maarten Grootendorst 向我们介绍了 9 种 ...

  9. 数据科学中常见的9种距离度量方法

    选自towardsdatascience 作者:Maarten Grootendorst 机器之心编译 编辑:陈萍 在数据挖掘中,我们经常需要计算样本之间的相似度,通常的做法是计算样本之间的距离.在本 ...

最新文章

  1. 为什么让A.I.“顶天立地”需要6个多月?
  2. 笔记2 自定义文件上传
  3. 使用Active Directory的常见问题2
  4. 飞行模式的开启和关闭
  5. spring 整合quartz
  6. OpenJudge NOI 1.7 10:简单密码
  7. 深度学习(机器学习)模型压缩开源库整理
  8. python中素数怎么求_用python怎么求素数
  9. 使用NodeJS连接到MySQL数据库Client does not support authentication protocol requested by server; consider upg
  10. python 教程 w3 school_Python 模块 | w3cschool菜鸟教程
  11. [Erlang 0075] Bad value on output port 'tcp_inet'
  12. Elasticsearch 安装详细步骤(保姆级安装)
  13. Heidisql中如何解决MySqlServer go away问题
  14. EDI与VMI 的区别
  15. SAP S4 FI后台详细配置教程- PART4 (科目及税费相关配置篇)
  16. C51单片机-2只LED灯循环闪烁
  17. 基于华为鲲鹏云的c语言程序设计,华为DevRun第四讲,华为云鲲鹏云服务移植快速入门与实践...
  18. 【关于ChatGPT的30个问题】26、ChatGPT的开发团队是谁?/ By 禅与计算机程序设计艺术
  19. 顶刊TPAMI!目标检测中的不均衡问题综述!
  20. check的3种用法

热门文章

  1. 美拉德烧烤盛宴,健康美食原理癌症
  2. 模仿英雄选择界面 setvisible的作用不仅仅是JFrame调用
  3. 什么是最大传输单元(MTU)以及注意事项
  4. JavaWeb之【转发与重定向】
  5. DCDC电源芯片供电对射频电路的影响
  6. git rebase 修改备注信息
  7. biee mysql_【Oracle BIEE学习笔记一】Oracle BIEE简介 | 学步园
  8. 文字排版中的设计四原则(二)
  9. 淘宝API item_search_guang - 爱逛街
  10. MATLAB—repmat函数