archive/pyz_crypto.py | 51 +++++++++++++-------------
building/api.py | 11 ++++++
building/build_main.py | 5 ++-
building/makespec.py | 22 +++++++-----
loader/pyimod02_archive.py | 89 ++++++++++++++++++++++++----------------------
5 files changed, 102 insertions(+), 76 deletions(-)
diff --git a/archive/pyz_crypto.py b/archive/pyz_crypto.py
index 47d2f1c..7003fd3 100644
--- a/archive/pyz_crypto.py
+++ b/archive/pyz_crypto.py
@@ -14,30 +14,30 @@ import os
BLOCK_SIZE = 16
-def import_aes(module_name):
- """
- Tries to import the AES module from PyCrypto.
+# def import_aes(module_name):
+# """
+# Tries to import the AES module from PyCrypto.
- PyCrypto 2.4 and 2.6 uses different name of the AES extension.
- """
- return __import__(module_name, fromlist=[module_name.split('.')[-1]])
+# PyCrypto 2.4 and 2.6 uses different name of the AES extension.
+# """
+# return __import__(module_name, fromlist=[module_name.split('.')[-1]])
-def get_crypto_hiddenimports():
- """
- These module names are appended to the PyInstaller analysis phase.
- :return: Name of the AES module.
- """
- try:
- # The _AES.so module exists only in PyCrypto 2.6 and later. Try to import
- # that first.
- modname = 'Crypto.Cipher._AES'
- import_aes(modname)
- except ImportError:
- # Fallback to AES.so, which should be there in PyCrypto 2.4 and earlier.
- modname = 'Crypto.Cipher.AES'
- import_aes(modname)
- return modname
+# def get_crypto_hiddenimports():
+# """
+# These module names are appended to the PyInstaller analysis phase.
+# :return: Name of the AES module.
+# """
+# try:
+# # The _AES.so module exists only in PyCrypto 2.6 and later. Try to import
+# # that first.
+# modname = 'Crypto.Cipher._AES'
+# import_aes(modname)
+# except ImportError:
+# # Fallback to AES.so, which should be there in PyCrypto 2.4 and earlier.
+# modname = 'Crypto.Cipher.AES'
+# import_aes(modname)
+# return modname
class PyiBlockCipher(object):
@@ -45,6 +45,8 @@ class PyiBlockCipher(object):
This class is used only to encrypt Python modules.
"""
def __init__(self, key=None):
+ import pyaes
+ self._aes = pyaes
assert type(key) is str
if len(key) > BLOCK_SIZE:
self.key = key[0:BLOCK_SIZE]
@@ -52,8 +54,8 @@ class PyiBlockCipher(object):
self.key = key.zfill(BLOCK_SIZE)
assert len(self.key) == BLOCK_SIZE
- # Import the right AES module.
- self._aesmod = import_aes(get_crypto_hiddenimports())
+ # # Import the right AES module.
+ # self._aesmod = import_aes(get_crypto_hiddenimports())
def encrypt(self, data):
iv = os.urandom(BLOCK_SIZE)
@@ -63,4 +65,5 @@ class PyiBlockCipher(object):
# The 'BlockAlgo' class is stateful, this factory method is used to
# re-initialize the block cipher class with each call to encrypt() and
# decrypt().
- return self._aesmod.new(self.key.encode(), self._aesmod.MODE_CFB, iv)
+ # return self._aesmod.new(self.key.encode(), self._aesmod.MODE_CFB, iv)
+ return self._aes.AESModeOfOperationCFB(self.key.encode(), iv=iv)
diff --git a/building/api.py b/building/api.py
index 8c62749..62957ef 100644
--- a/building/api.py
+++ b/building/api.py
@@ -94,6 +94,17 @@ class PYZ(Target):
# Insert the key as the first module in the list. The key module contains
# just variables and does not depend on other modules.
self.dependencies.insert(0, key_file)
+ import copy
+ copy_file = ('copy',
+ copy.__file__,
+ 'PYMODULE')
+
+ pyaes_file = ('pyimod00_pyaes',
+ os.path.join(CONF['workpath'], 'pyimod00_pyaes.pyc'),
+ 'PYMODULE')
+
+ self.dependencies.insert(2, copy_file)
+ self.dependencies.insert(3, pyaes_file)
# Compile the top-level modules so that they end up in the CArchive and can be
# imported by the bootstrap script.
self.dependencies = misc.compile_py_files(self.dependencies, CONF['workpath'])
diff --git a/building/build_main.py b/building/build_main.py
index d1cab2c..25d9a27 100644
--- a/building/build_main.py
+++ b/building/build_main.py
@@ -225,7 +225,10 @@ class Analysis(Target):
f.write(text_type('# -*- coding: utf-8 -*-\n'
'key = %r\n' % cipher.key))
logger.info('Adding dependencies on pyi_crypto.py module')
- self.hiddenimports.append(pyz_crypto.get_crypto_hiddenimports())
+ # self.hiddenimports.append(pyz_crypto.get_crypto_hiddenimports())
+ pyaes_path = os.path.join(CONF['workpath'], 'pyimod00_pyaes.py')
+ import pyaes.aes
+ shutil.copy(pyaes.aes.__file__, pyaes_path)
self.excludes = excludes or []
self.scripts = TOC()
diff --git a/building/makespec.py b/building/makespec.py
index fc0cc1d..bd69b37 100644
--- a/building/makespec.py
+++ b/building/makespec.py
@@ -396,15 +396,21 @@ def main(scripts, name=None, onefile=None,
# Tries to import PyCrypto since we need it for bytecode obfuscation. Also make sure its
# version is >= 2.4.
try:
- import Crypto
- is_version_acceptable = LooseVersion(Crypto.__version__) >= LooseVersion('2.4')
- if not is_version_acceptable:
- logger.error('PyCrypto version must be >= 2.4, older versions are not supported.')
- sys.exit(1)
+ import pyaes # noqa: F401
+ # import PyCrypto
+ # is_version_acceptable = LooseVersion(Crypto.__version__) >= LooseVersion('2.4')
+ # if not is_version_acceptable:
+ # logger.error('PyCrypto version must be >= 2.4, older versions are not supported.')
+ # sys.exit(1)
except ImportError:
- logger.error('We need PyCrypto >= 2.4 to use byte-code obfuscation but we could not')
- logger.error('find it. You can install it with pip by running:')
- logger.error(' pip install PyCrypto')
+ logger.error('We need pyaes to use byte-code obfuscation but ')
+ logger.error('we could not find it. ')
+ logger.error('You can install it with pip by running:')
+ logger.error(' pip install pyaes')
+ # logger.error('We need PyCrypto >= 2.4 to use byte-code obfuscation but we could not')
+ # logger.error('find it. You can install it with pip by running:')
+ # logger.error(' pip install PyCrypto')
+
sys.exit(1)
cipher_init = cipher_init_template % {'key': key}
else:
diff --git a/loader/pyimod02_archive.py b/loader/pyimod02_archive.py
index 2f372d9..781b81a 100644
--- a/loader/pyimod02_archive.py
+++ b/loader/pyimod02_archive.py
@@ -249,7 +249,9 @@ class Cipher(object):
# the generated 'pyi_crypto_key' module.
import pyimod00_crypto_key
key = pyimod00_crypto_key.key
+ import pyimod00_pyaes
+ self._aes = pyimod00_pyaes
assert type(key) is str
if len(key) > CRYPT_BLOCK_SIZE:
self.key = key[0:CRYPT_BLOCK_SIZE]
@@ -257,53 +259,54 @@ class Cipher(object):
self.key = key.zfill(CRYPT_BLOCK_SIZE)
assert len(self.key) == CRYPT_BLOCK_SIZE
- # Import the right AES module.
- self._aes = self._import_aesmod()
-
- def _import_aesmod(self):
- """
- Tries to import the AES module from PyCrypto.
-
- PyCrypto 2.4 and 2.6 uses different name of the AES extension.
- """
- # The _AES.so module exists only in PyCrypto 2.6 and later. Try to import
- # that first.
- modname = 'Crypto.Cipher._AES'
-
- if sys.version_info[0] == 2:
- # Not-so-easy way: at bootstrap time we have to load the module from the
- # temporary directory in a manner similar to pyi_importers.CExtensionImporter.
- from pyimod03_importers import CExtensionImporter
- importer = CExtensionImporter()
- # NOTE: We _must_ call find_module first.
- mod = importer.find_module(modname)
- # Fallback to AES.so, which should be there in PyCrypto 2.4 and earlier.
- if not mod:
- modname = 'Crypto.Cipher.AES'
- mod = importer.find_module(modname)
- if not mod:
- # Raise import error if none of the AES modules is found.
- raise ImportError(modname)
- mod = mod.load_module(modname)
- else:
- kwargs = dict(fromlist=['Crypto', 'Cipher'])
- try:
- mod = __import__(modname, **kwargs)
- except ImportError:
- modname = 'Crypto.Cipher.AES'
- mod = __import__(modname, **kwargs)
-
- # Issue #1663: Remove the AES module from sys.modules list. Otherwise
- # it interferes with using 'Crypto.Cipher' module in users' code.
- if modname in sys.modules:
- del sys.modules[modname]
- return mod
+ # # Import the right AES module.
+ # self._aes = self._import_aesmod()
+
+ # def _import_aesmod(self):
+ # """
+ # Tries to import the AES module from PyCrypto.
+
+ # PyCrypto 2.4 and 2.6 uses different name of the AES extension.
+ # """
+ # # The _AES.so module exists only in PyCrypto 2.6 and later. Try to import
+ # # that first.
+ # modname = 'Crypto.Cipher._AES'
+
+ # if sys.version_info[0] == 2:
+ # # Not-so-easy way: at bootstrap time we have to load the module from the
+ # # temporary directory in a manner similar to pyi_importers.CExtensionImporter.
+ # from pyimod03_importers import CExtensionImporter
+ # importer = CExtensionImporter()
+ # # NOTE: We _must_ call find_module first.
+ # mod = importer.find_module(modname)
+ # # Fallback to AES.so, which should be there in PyCrypto 2.4 and earlier.
+ # if not mod:
+ # modname = 'Crypto.Cipher.AES'
+ # mod = importer.find_module(modname)
+ # if not mod:
+ # # Raise import error if none of the AES modules is found.
+ # raise ImportError(modname)
+ # mod = mod.load_module(modname)
+ # else:
+ # kwargs = dict(fromlist=['Crypto', 'Cipher'])
+ # try:
+ # mod = __import__(modname, **kwargs)
+ # except ImportError:
+ # modname = 'Crypto.Cipher.AES'
+ # mod = __import__(modname, **kwargs)
+
+ # # Issue #1663: Remove the AES module from sys.modules list. Otherwise
+ # # it interferes with using 'Crypto.Cipher' module in users' code.
+ # if modname in sys.modules:
+ # del sys.modules[modname]
+ # return mod
def __create_cipher(self, iv):
# The 'BlockAlgo' class is stateful, this factory method is used to
# re-initialize the block cipher class with each call to encrypt() and
# decrypt().
- return self._aes.new(self.key, self._aes.MODE_CFB, iv)
+ # return self._aes.new(self.key, self._aes.MODE_CFB, iv)
+ return self._aes.AESModeOfOperationCFB(self.key.encode(), iv=iv)
def decrypt(self, data):
return self.__create_cipher(data[:CRYPT_BLOCK_SIZE]).decrypt(data[CRYPT_BLOCK_SIZE:])
@@ -345,7 +348,7 @@ class ZlibArchiveReader(ArchiveReader):
# Try to import the key module. If the key module is not available
# then it means that encryption is disabled.
try:
- import pyimod00_crypto_key
+ # import pyimod00_crypto_key
self.cipher = Cipher()
except ImportError:
self.cipher = None