如何给Python代码进行加密


Posted in Python onJanuary 10, 2020

这篇文章主要介绍了如何给Python代码进行加密,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

去年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-8
 
class A(object):
  """
  Description
  """
 
  def __init__(self, x, y, default=None):
    self.z = x + y
    self.default = default
 
  def name(self):
    return 'No Name'
def always():
  return True
num = 1
a = A(num, 999, 100)
a.name()
always()

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

class A (object ):#line:4
  ""#line:7
  def __init__ (O0O0O0OO00OO000O0 ,OO0O0OOOO0000O0OO ,OO0OO00O00OO00OOO ,OO000OOO0O000OOO0 =None ):#line:9
    O0O0O0OO00OO000O0 .z =OO0O0OOOO0000O0OO +OO0OO00O00OO00OOO #line:10
    O0O0O0OO00OO000O0 .default =OO000OOO0O000OOO0 #line:11
  def name (O000O0O0O00O0O0OO ):#line:13
    return 'No Name'#line:14
def always ():#line:17
  return 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 . oOooOoO0Oo0O
 if 10 - 10: IIiI1I11i11
 if 54 - 54: i11iIi1 - oOo0O0Ooo
 if 2 - 2: o0 * i1 * ii1IiI1i % OOooOOo / I11i / Ii1I
 def __init__ ( self , x , y , default = None ) :
 self . z = x + y
 self . default = default
 if 48 - 48: iII111i % IiII + I1Ii111 / ooOoO0o * Ii1I
 def name ( self ) :
 return 'No Name'
 if 46 - 46: ooOoO0o * I11i - OoooooooOO
 if 30 - 30: o0 - O0 % o0 - OoooooooOO * O0 * OoooooooOO
def Oo0o ( ) :
 return True
 if 60 - 60: i1 + I1Ii111 - I11i / i1IIi
 if 40 - 40: oOooOoO0Oo0O / O0 % ooOoO0o + O0 * i1IIi
I1Ii11I1Ii1i = 1
Ooo = o0OO00 ( I1Ii11I1Ii1i , 999 , 100 )
Ooo . name ( )
Oo0o ( ) # dd678faae9ac167bc83abf78e5cb2f3f0688d3a3

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 py2exe
setup(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 cythonize
setup(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 相关文章推荐
Django中实现一个高性能计数器(Counter)实例
Jul 09 Python
python编程嵌套函数实例代码
Feb 11 Python
解决PyCharm的Python.exe已经停止工作的问题
Nov 29 Python
python pexpect ssh 远程登录服务器的方法
Feb 14 Python
python常见字符串处理函数与用法汇总
Oct 30 Python
Django实现简单网页弹出警告代码
Nov 15 Python
django实现web接口 python3模拟Post请求方式
Nov 19 Python
浅谈python中频繁的print到底能浪费多长时间
Feb 21 Python
Pandas对DataFrame单列/多列进行运算(map, apply, transform, agg)
Jun 14 Python
多个版本的python共存时使用pip的正确做法
Oct 26 Python
pycharm debug 断点调试心得分享
Apr 16 Python
Python使用Opencv打开笔记本电脑摄像头报错解问题及解决
Jun 21 Python
pytorch如何冻结某层参数的实现
Jan 10 #Python
python标识符命名规范原理解析
Jan 10 #Python
pytorch1.0中torch.nn.Conv2d用法详解
Jan 10 #Python
pytorch 利用lstm做mnist手写数字识别分类的实例
Jan 10 #Python
Tensorflow Summary用法学习笔记
Jan 10 #Python
TENSORFLOW变量作用域(VARIABLE SCOPE)
Jan 10 #Python
python numpy数组复制使用实例解析
Jan 10 #Python
You might like
神奇的代码 通杀各种网站-可随意修改复制页面内容
2008/07/17 Javascript
jquery1.4 教程二 ajax方法的改进
2010/02/25 Javascript
jQuery.getScript加载同域JS的代码
2012/02/13 Javascript
JQuery中根据属性或属性值获得元素(6种情况获取方法)
2013/01/17 Javascript
Jquery实现点击按钮,连续地向textarea中添加值的实例代码
2014/03/08 Javascript
javascript闭包传参和事件的循环绑定示例探讨
2014/04/17 Javascript
Jquery跳到页面指定位置的方法
2014/05/12 Javascript
jquery实现显示已选用户
2014/07/21 Javascript
jquery显示隐藏input对象
2014/07/21 Javascript
jQuery操作cookie方法实例教程
2014/11/25 Javascript
node.js中的fs.unlinkSync方法使用说明
2014/12/15 Javascript
Jquery异步提交表单代码分享
2015/03/26 Javascript
window.setInterval()方法的定义和用法及offsetLeft与style.left的区别
2015/11/11 Javascript
js实现自动图片轮播代码
2017/03/22 Javascript
JavaScript使用Ajax上传文件的示例代码
2017/08/10 Javascript
Javascript中将变量转换为字符串的三种方法
2017/09/19 Javascript
JS实现多物体运动的方法详解
2018/01/23 Javascript
vue路由导航守卫和请求拦截以及基于node的token认证的方法
2019/04/07 Javascript
你准备好迎接vue3.0了吗
2020/04/28 Javascript
Python之多线程爬虫抓取网页图片的示例代码
2018/01/10 Python
浅谈python中对于json写入txt文件的编码问题
2018/06/07 Python
对Tensorflow中的矩阵运算函数详解
2018/07/27 Python
python3+openCV 获取图片中文本区域的最小外接矩形实例
2020/06/02 Python
Python中logger日志模块详解
2020/08/04 Python
python抢购软件/插件/脚本附完整源码
2021/03/04 Python
CSS3 animation ? steps 函数详解
2019/08/30 HTML / CSS
德购商城:德国进口直邮商城
2017/06/13 全球购物
Opodo意大利:欧洲市场上领先的在线旅行社
2019/10/24 全球购物
《和我们一样享受春天》教学反思
2014/02/07 职场文书
创意广告词
2014/03/17 职场文书
弘扬焦裕禄精神走群众路线思想汇报
2014/09/12 职场文书
教师个人年度总结
2015/02/11 职场文书
2015年清明节演讲稿范文
2015/03/17 职场文书
公司年会开场白
2015/06/01 职场文书
导游词之晋城蟒河
2019/12/12 职场文书
nginx location优先级的深入讲解
2021/03/31 Servers