Python3.6 AES加密依赖包Crypto的安装,pyinstaller打包exe报错Cannot load native module ‘Crypto.Cipher._raw_ecb的解决方法

所有方法都来自互联网,我做了个全套总结

pycrypto,pycrytodome和crypto是一个东西,在很久以前,crypto在python上面的名字是pycrypto它是一个第三方库,但是已经停止更新三年了,所以不建议安装这个库;但有一个延伸版pycryptodome,用法和pycrypto一模一样的,正常用pip安装就OK:
pip install pycryptodome

安装完之后,去C:\Python36\Lib\site-packages文件夹(python安装目录的第三方库)下找到crypto文件夹,改成Crypto,‘C’改成大写,然后用测试代码验证:我用的CFB模式,不限制明文的长度,比较简单

 
  1. #AES-dome

  2. # -*- coding: utf-8 -*-

  3. import base64

  4. import os

  5. from Crypto.Cipher import AES

  6. '''

  7. 采用AES CFB模式 对称加密算法

  8. CFB模式,对待加密原文长度没有要求

    扫描二维码关注公众号,回复: 13213564 查看本文章
  9. '''

  10. class AES_encrypt_decrypt(object):

  11. def __init__(self, key):

  12. self.key = key.encode('utf-8')

  13. self.mode = AES.MODE_CFB

  14.  
  15. # 加密函数,采用CFB方式,text明文没有长度限制

  16. def encrypt(self, text):

  17. text = text.encode('utf-8')

  18. #注意,这里Python3.6下用AES传递key时必须要转换成2进制,key前面要加'b'

  19. crypto = AES.new(self.key, self.mode, b'woshigongyao6666')

  20. # 这里密钥key 长度必须为16(AES-128),

  21. # 24(AES-192),或者32 (AES-256)Bytes 长度

  22. # 目前AES-128 足够目前使用

  23. self.ciphertext = crypto.encrypt(text)

  24. # 因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题

  25. # 所以这里统一用base64转化为字符串

  26. return str(base64.encodebytes(self.ciphertext), encoding='utf-8')

  27.  
  28. # 解密

  29. def decrypt(self, text):

  30. crypto = AES.new(self.key, self.mode, b'woshigongyao6666')

  31. plain_text = crypto.decrypt(base64.decodebytes(text.encode(encoding='utf-8')))

  32. return bytes.decode(plain_text)

  33.  
  34. if __name__ == '__main__':

  35. # 初始化密钥

  36. sql = AES_encrypt_decrypt('woshisiyao666888')

  37.   text = 'my AES encrypt program!'

  38. e = pc.encrypt(text) # 加密

  39. d = pc.decrypt(e) # 解密

  40. print("原文:"+'\n'+text)

  41. print("加密结果:"+'\n'+ e)

  42. print("解密结果:"+'\n'+d)

 

运行上面的程序,应该可以跑出来这样的结果:

 
  1. 原文:

  2. my AES encrypt program!

  3. 加密结果:

  4. DyMSIDSVV6zp8r2XtcPEHaWlqcNuEOA=

  5.  
  6. 解密结果:

  7. my AES encrypt program!

好,下面开始用Pyinstaller打包,但无奈报错,经过网上一顿找,发现原因大致如下,延续开发的人漏了hook,需要手动加一个hook文件到C:\python36\Lib\site-packages\PyInstaller\hooks,文件名是hook-Crypto.py,内容如下:

 
  1. #-----------------------------------------------------------------------------

  2. # Copyright (c) 2005-2018, PyInstaller Development Team.

  3. #

  4. # Distributed under the terms of the GNU General Public License with exception

  5. # for distributing bootloader.

  6. #

  7. # The full license is in the file COPYING.txt, distributed with this software.

  8. #-----------------------------------------------------------------------------

  9.  
  10. """

  11. Hook for PyCryptodome library: https://pypi.python.org/pypi/pycryptodome

  12.  
  13. PyCryptodome is an almost drop-in replacement for the now unmaintained

  14. PyCrypto library. The two are mutually exclusive as they live under

  15. the same package ("Crypto").

  16.  
  17. PyCryptodome distributes dynamic libraries and builds them as if they were

  18. Python C extensions (even though they are not extensions - as they can't be

  19. imported by Python). It might sound a bit weird, but this decision is rooted

  20. in PyPy and its partial and slow support for C extensions. However, this also

  21. invalidates several of the existing methods used by PyInstaller to decide the

  22. right files to pull in.

  23.  
  24. Even though this hook is meant to help with PyCryptodome only, it will be

  25. triggered also when PyCrypto is installed, so it must be tested with both.

  26.  
  27. Tested with PyCryptodome 3.5.1, PyCrypto 2.6.1, Python 2.7 & 3.6, Fedora & Windows

  28. """

  29.  
  30. import os

  31. import glob

  32.  
  33. from PyInstaller.compat import EXTENSION_SUFFIXES

  34. from PyInstaller.utils.hooks import get_module_file_attribute

  35.  
  36. # Include the modules as binaries in a subfolder named like the package.

  37. # Cryptodome's loader expects to find them inside the package directory for

  38. # the main module. We cannot use hiddenimports because that would add the

  39. # modules outside the package.

  40.  
  41. binaries = []

  42. binary_module_names = [

  43. 'Crypto.Math', # First in the list

  44. 'Crypto.Cipher',

  45. 'Crypto.Util',

  46. 'Crypto.Hash',

  47. 'Crypto.Protocol',

  48. ]

  49.  
  50. try:

  51. for module_name in binary_module_names:

  52. m_dir = os.path.dirname(get_module_file_attribute(module_name))

  53. for ext in EXTENSION_SUFFIXES:

  54. module_bin = glob.glob(os.path.join(m_dir, '_*%s' % ext))

  55. for f in module_bin:

  56. binaries.append((f, module_name.replace('.', os.sep)))

  57. except ImportError:

  58. # Do nothing for PyCrypto (Crypto.Math does not exist there)

  59. pass

保存之后,拷贝到那个目录,重新用Pyinstaller打包,完美生成EXE文件!

猜你喜欢

转载自blog.csdn.net/uiop_uiop_uiop/article/details/111893836