背景
在一些使用python的商業(yè)項(xiàng)目上,開發(fā)人員不想被用戶看到源代碼時(shí),就需要對python代碼進(jìn)行加密;進(jìn)一步地,如果想限制用戶只能在獲得授權(quán)的機(jī)器上運(yùn)行你寫的代碼時(shí)(利益相關(guān)),就需要使用License控制。只有經(jīng)過加密的代碼才能進(jìn)行License控制,試想一下,如果客戶能拿到你的源代碼,那么License控制就成為無稽之談。
這里提供一種代碼加密與License控制的思路。
先說python代碼加密。
代碼加密
眾所周知,python是一種開源的編程語言,在開源的語言上做加密,加密效果肯定不如編譯性語言的加密效果好,其逆向工程的難度會(huì)比編譯性語言的逆向工程簡單,按照這個(gè)思路,既然編譯性語言c/c++的逆向工程難,那么為何不先把python編譯成c/c++代碼,然后再加密呢?根據(jù)經(jīng)驗(yàn)這樣是可行的,且這樣加密的代碼比那些編譯成pyd文件或者打包成exe的方法就安全得多(pyd和exe的逆向工程有專門的包可以實(shí)現(xiàn))。這就是這篇文章介紹的加密方法。
思路是先將py轉(zhuǎn)換為c代碼,然后編譯c為so文件。
準(zhǔn)備工作:
linux安裝:
-
python-dev
-
gcc
sudo apt-get install python-dev gcc
python安裝第三方庫
-
pycrypto
(注意:在win10環(huán)境下安裝這個(gè)包可能會(huì)報(bào)錯(cuò),解決辦法見這里 ) -
Cython
pip install pycrypto Cython
加密腳本``setup.py`的代碼如下
# coding:utf-8
from
distutils
.
core
import
setup
from
Cython
.
Build
import
cythonize
import
os
'''
該文件的執(zhí)行需要的在Terminal中輸入 python setup.py build_ext --inplace
使用Cpython 編譯python文件,關(guān)鍵函數(shù)編譯成pyd文件(相當(dāng)于dll)
'''
# 針對多文件情況設(shè)置,單文件就只寫一個(gè)就行, 文件之間用逗號隔開
key_funs
=
[
'test.py'
]
setup
(
name
=
"XX app"
,
ext_modules
=
cythonize
(
key_funs
)
,
)
'''
1、將編譯后的pyd文件的命名更改成與原py文件一致
2、刪除編譯后得到的c文件和原py文件
'''
print
(
"——————"
,
os
.
getcwd
(
)
,
"——————"
)
files
=
os
.
listdir
(
os
.
getcwd
(
)
)
print
(
files
)
for
fi
in
files
:
if
fi
.
__contains__
(
".pyd"
)
:
re_name
=
fi
.
split
(
"."
)
[
0
]
+
".pyd"
print
(
re_name
)
os
.
rename
(
fi
,
re_name
)
elif
fi
.
__contains__
(
".c"
)
or
fi
in
key_funs
:
os
.
remove
(
fi
)
為了更好的說明,這里舉個(gè)簡單的例子。
另外準(zhǔn)備兩個(gè)py文件,
test.py
和
main.py
,其中
test.py
是需要加密的代碼,
main.py
是調(diào)用加密代碼的腳本,不需要加密。
test.py
的內(nèi)容如下
import
datetime
class
Today
(
)
:
def
get_time
(
self
)
:
print
(
datetime
.
datetime
.
now
(
)
)
def
say
(
self
)
:
print
(
'hello world'
)
main.py
的內(nèi)容如下
from
test
import
Today
t
=
Today
(
)
t
.
get_time
(
)
t
.
say
(
)
加密之前,測試一下運(yùn)行效果,在終端執(zhí)行
python main.py
,輸出
2019-08-30 11:38:38.419308
hello world
使用
setup.py
對
test.py
進(jìn)行加密
方法:將需要加密的代碼放到列表
key_funs
里面,然后在終端運(yùn)行
python setup.py build_ext --inplace
運(yùn)行完加密腳本
setup.py
后,會(huì)將
test.py
刪掉(請備份到其他地方!),得到
test.so
文件和文件夾
build/
,這個(gè)文件夾可以刪掉。至此代碼加密完成。
測試
再次在終端執(zhí)行
python main.py
,輸出
2019-08-30 11:49:17.986503
hello world
成功!
(注意,不能直接在IDE執(zhí)行main.py,會(huì)出現(xiàn)錯(cuò)誤ImportError: cannot import name ‘Today’)
License控制
知道怎么加密代碼之后,就可以用license控制你的代碼,以防被別人濫用。
通過License可以控制你的代碼,控制方式有很多種,包括限制主機(jī)、限制時(shí)間(過期則無法執(zhí)行)、限制使用地點(diǎn)等,這里只介紹如何通過License限制主機(jī),其他方法大同小異,做適當(dāng)修改即可。
物理地址是每臺計(jì)算機(jī)獨(dú)一無二的身份號碼,我們可以利用物理地址作為限制主機(jī)的依據(jù)。
具體思路是,用戶拿到你寫的代碼后,如果用戶的計(jì)算機(jī)未經(jīng)你權(quán)授則不能運(yùn)行你的代碼,這時(shí)候就需要利用物理地址作為權(quán)授的載體進(jìn)行授權(quán)計(jì)算機(jī)。如需要授權(quán)計(jì)算機(jī),用戶要把需權(quán)授的機(jī)器的物理地址發(fā)給你,你使用AES加密算法把這個(gè)物理地址加密后,將得到的加密文件發(fā)給用戶(這個(gè)加密文件就相當(dāng)于一把鑰匙,只有擁有這把鑰匙才能正常運(yùn)行你的代碼)用戶把加密文件放到指定路徑下并執(zhí)行代碼,程序讀取加密文件并解密,得到你加密的物理地址,將此物理地址與當(dāng)前主機(jī)的物理地址做匹配,如果這兩個(gè)物理地址相同則程序能正常運(yùn)行,不同則退出程序。這里將物理地址加密的目的是防止被用戶篡改。
這里涉及到的加密算法不做詳細(xì)介紹,需了解請移步 here
用戶計(jì)算機(jī)申請授權(quán)過程
License控制流程圖
具體代碼及實(shí)現(xiàn)例子請移步github
(別忘了點(diǎn)star哦)
Reference:
- 淺談常見的七種加密算法及實(shí)現(xiàn)
- 加密Python源代碼筆記
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
