pythonencryptionpyinstallerblock-cipher

What is cipher option in pyinstaller spec file and how to use it?


Note: I am using pycharm and have virtual environment. Python version is 3.11.1. PyInstaller version is 5.7.0. OS is Mac Ventura 13.2.

I want to build one-folder bundle using pyinstaller with encryption. I am thinking of writing .spec file. I read the documentation of Spec File Operation here.

This is the example from there.

block_cipher = None
a = Analysis(['minimal.py'],
         pathex=['/Developer/PItests/minimal'],
         binaries=None,
         datas=None,
         hiddenimports=[],
         hookspath=None,
         runtime_hooks=None,
         excludes=None,
         cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
         cipher=block_cipher)
exe = EXE(pyz,... )
coll = COLLECT(...)

In this example, I see cipher option in Analysis. I assume this option does something about encryption.

I know nothing about how to set block_cipher. If I put "str" or "bytes" I get this error.

(venv) ******@*********** engine % pyinstaller ****.spec
110 INFO: PyInstaller: 5.7.0
110 INFO: Python: 3.11.1
163 INFO: Platform: macOS-13.2-x86_64-i386-64bit
169 INFO: UPX is not available.
171 INFO: Extending PYTHONPATH with paths
['/Users/******/PycharmProjects/*********']
529 INFO: Will encrypt Python bytecode with provided cipher key
Traceback (most recent call last):
  File "/Users/******/PycharmProjects/*********/venv/bin/pyinstaller", line 8, in <module>
    sys.exit(_console_script_run())
             ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/******/PycharmProjects/*********/venv/lib/python3.11/site-packages/PyInstaller/__main__.py", line 194, in _console_script_run
    run()
  File "/Users/******/PycharmProjects/*********/venv/lib/python3.11/site-packages/PyInstaller/__main__.py", line 180, in run
    run_build(pyi_config, spec_file, **vars(args))
  File "/Users/******/PycharmProjects/*********/venv/lib/python3.11/site-packages/PyInstaller/__main__.py", line 61, in run_build
    PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
  File "/Users/******/PycharmProjects/*********/venv/lib/python3.11/site-packages/PyInstaller/building/build_main.py", line 971, in main
    build(specfile, distpath, workpath, clean_build)
  File "/Users/******/PycharmProjects/*********/venv/lib/python3.11/site-packages/PyInstaller/building/build_main.py", line 893, in build
    exec(code, spec_namespace)
  File "****.spec", line 15, in <module>
    a = Analysis(
        ^^^^^^^^^
  File "/Users/******/PycharmProjects/*********/venv/lib/python3.11/site-packages/PyInstaller/building/build_main.py", line 393, in __init__
    f.write('# -*- coding: utf-8 -*-\nkey = %r\n' % cipher.key)
                                                    ^^^^^^^^^^
AttributeError: 'bytes' object has no attribute 'key'
  1. What does cipher option do?
  2. How to encrypt python code using pyinstaller?

Thank you!


Solution

  • I received this answer from pyinstaller maintainer.

    The cipher option expects an instance of pyi_crypto.PyiBlockCipher:

    block_cipher = pyi_crypto.PyiBlockCipher(key='password123')
    
    a = Analysis(
        ...
       cipher=block_cipher,
    )
    

    Usually you'd get that in your initial .spec file if you ran PyInstaller or pyi-makespec with --key=password123 command-line switch.

    That said, this built-in bytecode encryption offers no real protection and slated for removal (#6999), so I would advise against using it.

    Answer: https://github.com/orgs/pyinstaller/discussions/7460#discussioncomment-5085798

    About the --key/cipher bytecode encryption: https://github.com/pyinstaller/pyinstaller/pull/6999

    I am thinking of searching some kind of a minifier or an obfuscator.