Python 在安全加密方面的最佳实践。如:
cryptography:提供了常用的加密方法,名字太长,OUThashlib:【标准库】为不同的安全哈希和信息摘要算法实现的公共接口,如 MD5、SHA1、SHA224、SHA256、SHA384 和 SHA512 等Passlib:安全的密码存储/哈希库,非常高的安全级别hashmac:在基于各种哈希算法/散列算法同时,使和密钥增加安全性。与 hashilib 的 api 基本一致hmac:【标准库】标准的 Hmac 算法pyobfuscate:Python 代码混淆器,通过多种方式改变源码,一些可以被反解,一些不可以。
概述
- cryptography
- hashids
- paramiko
- passlib
- pycrypto
- pyNacl
MD5:Message-Digest Algorithm 5:信息 - 摘要算法 5:计算机广泛使用的散列算法之一(又译摘要算法、哈希算法),用于确保信息传输完整一致
- 广泛用于安全领域:如常用于服务器提供一个 MD5 校验和,用户下载完文件后,可用 MD5 算法计算下载文件的 MD5 校验和,通过对比一致性,判断文件是否正确。
- 数据安全的三个要素:
- 对称加密与非对称加密:
- 对称加密:加密和解密采用相同的密钥。如:DES、RC2、RC4
- 非对称加密:需要两个密钥:公钥和私钥。如果用公钥加密,需要用私钥才能解密。如:RSA
- 区别:对称加密速度更快,通常用于大量数据的加密;非对称加密安全性更高(不需要传送私钥)
字符混淆
- 不能实现真正的加密,只是看到脚本的人无法直接记下密码
1 2 3 4 5 6
| import base64
print(base64.b64encode("password".encode("utf-8")))
print(base64.b64decode("cGFzc3dvcmQ=").decode("utf-8"))
|
secrets
secrets:生成密码
基本使用
1 2 3 4 5 6 7 8
| import secrets
value = secrets.token_bytes(length) print(f"Bytes: {value}")
value = secrets.token_hex(length) print(f"Hex: {value}")
|
cryptography
cryptography:提供了常用的加密方法,常用于二进制文件、图片等的加密
- 支持对称加密算法(如 AES、DES)、非对称加密算法(如 RSA)和哈希算法
1 2 3 4 5
| from cryptography.fernet import Fernet key = Fernet.generate_key() cipher_suite = Fernet(key) cipher_text = cipher_suite.encrypt(b"A really secret message. Not for prying eyes.") plain_text = cipher_suite.decrypt(cipher_text)
|
hashilib
hashlib:【标准库】为不同的安全哈希和信息摘要算法实现的公共接口,常用于字符串、文本文件等的加密。支持多种哈希算法,如 MD5、SHA1、SHA224、SHA256、SHA384 和 SHA512 等
- 摘要/哈希/散列算法:通过一个函数,将任意长度的数据转换为一个长度固定的数据串(常用 16 进制的字符串表示),
- 目的:发现原始数据是否被篡改过。
- 摘要函数为单向函数,计算
f(data) 很容易,但通过得到的 digest 反推 data 却非常困难,而对原始数据改一个 bit,都会导致计算出的 digest 完全不同
- 常用 MD5、SHA1,比 SHA1 更安全的算法是 SHA256 和 SHA512,不过越安全的算法不仅越慢,而且摘要长度更长。
- 碰撞:两个不同的数据通过某个摘要算法得到了相同的摘要
- 用处:保存用户密码:登录时用用户输入的密码对应的 MD5 与数据库存储的 MD5 对比。
- 摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。
- 需要字节形式的字符串
- 存储密码的哈希值而不是密码本身
- 发送文件时同时发送其哈希值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import hashlib m = hashlib.md5() m.update(b"test") m.hexdigest() '05a671c66aefea124cc08b76ea6d30bb' m.digest() b'\x05\xa6q\xc6j\xef\xea\x12L\xc0\x8bv\xeam0\xbb' hash=hashlib.new('ripemd160',b'chen') dics = hashlib.algorithms_guaranteed dics = hashlib.algorithms_available
hash_bytes = hashlib.pbkdf2_hmac('sha256', b'luzhuo.me', b'80', 100000)
num = hash.digest_size num = hash.block_size strs = hash.name hash.update(b"data") hash_bytes = hash.digest() hash_str = hash.hexdigest() hash = hash.copy()
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| import hashlib md5 = hashlib.md5() md5.update('how to use md5 in python hashlib?'.encode('utf-8')) print(md5.hexdigest())
import hashlib md5 = hashlib.md5() md5.update('how to use md5 in '.encode('utf-8')) md5.update('python hashlib?'.encode('utf-8')) print(md5.hexdigest())
|
1 2 3 4 5 6
| import hashlib sha1 = hashlib.sha1() sha1.update('how to use sha1 in '.encode('utf-8')) sha1.update('python hashlib?'.encode('utf-8')) print(sha1.hexdigest())
|
passlib
Passlib:安全的密码存储/哈希库,非常高的安全级别
hashmac
hashmac:在基于各种哈希算法/散列算法同时,使和密钥增加安全性。与 hashilib 的 api 基本一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import hmac def hmac_demo(): h = hmac.new(b"net") h.update(b"luzhuo.me") h_str = h.hexdigest() print(h_str) boolean = hmac.compare_digest(h_str, hmac.new(b"net", b"luzhuo.me").hexdigest()) print(boolean)
def hmac_func(): hc = hmac.new(b"key") hc.update(b"msg") hash_bytes = hc.digest() hash_str = hc.hexdigest() hc = hc.copy() num = hc.digest_size num = hc.block_size strs = hc.name boolean = hmac.compare_digest(hmac.new(b"net", b"luzhuo.me").digest(), hmac.new(b"net", b"luzhuo.me").digest())
|
hmac
hmac:【标准库】标准的 Hmac 算法,常用于验证消息的完整性
- 对在应用程序之间传递或存储的可能受攻击的数据,以实际数据 + 共享密钥结合的形式,生成的哈希检查传输或存储的的完整生
- 利用一个 key 对 message 计算杂凑后得到 hash
- Hmac 算法:Keyed-Hashing for Message Authentication。它通过一个标准算法,在计算哈希的过程中,把 key 混入计算过程中。
- 和我们自定义的加 salt 算法不同,Hmac 算法针对所有哈希算法都通用,无论是 MD5 还是 SHA-1。采用 Hmac 替代我们自己的 salt 算法,可以使程序算法更标准化,也更安全。
1 2 3 4 5 6 7 8
| import hmac message=b'Hello world!' key=b'secret' h=hmac.new(key,message,digestmod='MD5')
h.hexdigest() 'fa4ee7d173f2d97ee79022d1a7355bcf'
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import hmac
digest_maker = hmac.new(b'secret-shared-key-goes-here')
with open('lorem.txt', 'rb') as f: while True: block = f.read(1024) if not block: break digest_maker.update(block)
digest = digest_maker.hexdigest() print(digest)
import base64 import hmac import hashlib
with open('lorem.txt', 'rb') as f: body = f.read()
hash = hmac.new( b'secret-shared-key-goes-here', body, hashlib.sha1, )
digest = hash.digest() print(base64.encodebytes(digest))
|
pyobfuscate
pyobfuscate:Python 代码混淆器,通过多种方式改变源码,一些可以被反解,一些不可以。
- 脚本语言的 pyc 和 pyo 文件能反编译出源码,
- 通过混淆代码可增加破解者阅读代码的成本。
- pyexe、PyInstaller、Py2app 等打包工具:可得到 pyc 文件或源代码
- 目前大部分开源的 Python 代码混淆工具都是可逆的,最安全的不可逆方式是把 Python 代码编译成 C 模块,直接发布编译后的类库即可。但需要编写额外的代码来生成 C 模块,并且生成后的模块不一定可以直接运行。
- Cython:Cython 是属于 PYTHON 的超集,首先会将 PYTHON 代码转化成 C 语言代码,然后通过 c 编译器生成可执行文件。
- 优势:资源丰富,适合快速开发。翻译成 C 后速度比较快。
- 缺点是:无法支持 JIT 技术
- 类似于 C/C++ 的 CXX-OBFUS
jmpy
jmpy:将 .py 文件编译成 .pyd
遇到的问题
- 加密时
error: Unable to find vcvarsall.bat - 解决方案:
- 参考资料
- 参考资料
- 安装最新版本的 Visusl Studio,选择 使用 C++ 的桌面开发,选择 MSVC 相关的可选组件
- mingw 解决一个问题,又来一个新的问题,真是**,我**,**Windows
pyarmor
pyarmor:Python代码保护工具,可以对python脚本进行加密和混淆。
基本使用
1
| pyarmor obfuscate --output dist/obfuscated main.py
|
附 反调试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import sys import os def detect_debugger(): if hasattr(sys, 'gettrace') and sys.gettrace() is not None: return True return False if detect_debugger(): print("检测到调试器,应用退出") os._exit(0) python 运行
|