所有方法都来自互联网,我做了个全套总结
pycrypto,pycrytodome和crypto是一个东西,在很久以前,crypto在python上面的名字是pycrypto它是一个第三方库,但是已经停止更新三年了,所以不建议安装这个库;但有一个延伸版pycryptodome,用法和pycrypto一模一样的,正常用pip安装就OK:
pip install pycryptodome
安装完之后,去C:\Python36\Lib\site-packages文件夹(python安装目录的第三方库)下找到crypto文件夹,改成Crypto,‘C’改成大写,然后用测试代码验证:我用的CFB模式,不限制明文的长度,比较简单
#AES-dome
# -*- coding: utf-8 -*-
import base64
import os
from Crypto.Cipher import AES
'''
采用AES CFB模式 对称加密算法
CFB模式,对待加密原文长度没有要求
'''
class AES_encrypt_decrypt(object):
def __init__(self, key):
self.key = key.encode('utf-8')
self.mode = AES.MODE_CFB
# 加密函数,采用CFB方式,text明文没有长度限制
def encrypt(self, text):
text = text.encode('utf-8')
#注意,这里Python3.6下用AES传递key时必须要转换成2进制,key前面要加'b'
crypto = AES.new(self.key, self.mode, b'woshigongyao6666')
# 这里密钥key 长度必须为16(AES-128),
# 24(AES-192),或者32 (AES-256)Bytes 长度
# 目前AES-128 足够目前使用
self.ciphertext = crypto.encrypt(text)
# 因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
# 所以这里统一用base64转化为字符串
return str(base64.encodebytes(self.ciphertext), encoding='utf-8')
# 解密
def decrypt(self, text):
crypto = AES.new(self.key, self.mode, b'woshigongyao6666')
plain_text = crypto.decrypt(base64.decodebytes(text.encode(encoding='utf-8')))
return bytes.decode(plain_text)
if __name__ == '__main__':
# 初始化密钥
sql = AES_encrypt_decrypt('woshisiyao666888')
text = 'my AES encrypt program!'
e = pc.encrypt(text) # 加密
d = pc.decrypt(e) # 解密
print("原文:"+'\n'+text)
print("加密结果:"+'\n'+ e)
print("解密结果:"+'\n'+d)
运行上面的程序,应该可以跑出来这样的结果:
原文:
my AES encrypt program!
加密结果:
DyMSIDSVV6zp8r2XtcPEHaWlqcNuEOA=
解密结果:
my AES encrypt program!
好,下面开始用Pyinstaller打包,但无奈报错,经过网上一顿找,发现原因大致如下,延续开发的人漏了hook,需要手动加一个hook文件到C:\python36\Lib\site-packages\PyInstaller\hooks,文件名是hook-Crypto.py,内容如下:
#-----------------------------------------------------------------------------
# Copyright (c) 2005-2018, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
"""
Hook for PyCryptodome library: https://pypi.python.org/pypi/pycryptodome
PyCryptodome is an almost drop-in replacement for the now unmaintained
PyCrypto library. The two are mutually exclusive as they live under
the same package ("Crypto").
PyCryptodome distributes dynamic libraries and builds them as if they were
Python C extensions (even though they are not extensions - as they can't be
imported by Python). It might sound a bit weird, but this decision is rooted
in PyPy and its partial and slow support for C extensions. However, this also
invalidates several of the existing methods used by PyInstaller to decide the
right files to pull in.
Even though this hook is meant to help with PyCryptodome only, it will be
triggered also when PyCrypto is installed, so it must be tested with both.
Tested with PyCryptodome 3.5.1, PyCrypto 2.6.1, Python 2.7 & 3.6, Fedora & Windows
"""
import os
import glob
from PyInstaller.compat import EXTENSION_SUFFIXES
from PyInstaller.utils.hooks import get_module_file_attribute
# Include the modules as binaries in a subfolder named like the package.
# Cryptodome's loader expects to find them inside the package directory for
# the main module. We cannot use hiddenimports because that would add the
# modules outside the package.
binaries = []
binary_module_names = [
'Crypto.Math', # First in the list
'Crypto.Cipher',
'Crypto.Util',
'Crypto.Hash',
'Crypto.Protocol',
]
try:
for module_name in binary_module_names:
m_dir = os.path.dirname(get_module_file_attribute(module_name))
for ext in EXTENSION_SUFFIXES:
module_bin = glob.glob(os.path.join(m_dir, '_*%s' % ext))
for f in module_bin:
binaries.append((f, module_name.replace('.', os.sep)))
except ImportError:
# Do nothing for PyCrypto (Crypto.Math does not exist there)
pass
保存之后,拷贝到那个目录,重新用Pyinstaller打包,完美生成EXE文件!