Using PyArmor

The syntax of the pyarmor command is:

pyarmor [command] [options]

Obfuscating Python Scripts

Use command obfuscate to obfuscate python scripts. In the most simple case, set the current directory to the location of your program myscript.py and execute:

pyarmor obfuscate myscript.py

PyArmor obfuscates myscript.py and all the *.py in the same folder:

  • Create .pyarmor_capsule.zip in the HOME folder if it doesn’t exists.
  • Creates a folder dist in the same folder as the script if it does not exist.
  • Writes the obfuscated myscript.py in the dist folder.
  • Writes all the obfuscated *.py in the same folder as the script in the dist folder.
  • Copy runtime files used to run obfuscated scripts to the dist folder.

In the dist folder you find the obfuscated scripts you distribute to your users:

myscript.py

_pytransform.so, or _pytransform.dll in Windows, _pytransform.dylib in MacOS
pytransform.py
pytransform.key
license.lic

The rest files called Runtime Files, all of them are required to run the obfuscated script.

Normally you name one script on the command line. It’s entry script. The content of myscript.py would be like this:

from pytransform import pyarmor_runtime
pyarmor_runtime()

__pyarmor__(__name__, __file__, b'\x06\x0f...')

The first 2 lines called Bootstrap Code, are only in the entry script. They must be run before using any obfuscated file. For all the other obfuscated *.py, there is only last line:

__pyarmor__(__name__, __file__, b'\x0a\x02...')

Run the obfuscated script:

cd dist
python myscript.py

By default, only the *.py in the same path as the entry script are obfuscated. To obfuscate all the *.py in the sub-folder recursively, execute this command:

pyarmor obfuscate --recursive myscript.py

Distributing Obfuscated Scripts

Just copy all the files in the output path dist to end users. Note that except the obfuscated scripts, all the Runtime Files need to be distributed to end users too.

About the security of obfuscated scripts, refer to The Security of PyArmor

Generating License For Obfuscated Scripts

Use command licenses to generate new license.lic for obfuscated scripts.

By default there is dist/license.lic generated by command obfuscate. It allows obfuscated scripts run in any machine and never expired.

Generate an expired license for obfuscated script:

pyarmor licenses --expired 2019-01-01 code-001

PyArmor generates new license file:

  • Read data from .pyarmor_capsule.zip in the HOME folder
  • Create license.lic in the licenses/code-001 folder
  • Create license.lic.txt in the licenses/code-001 folder

Overwrite default license with new one:

cp licenses/code-001/license.lic dist/

Run obfuscated script with new license, It will report error after Jan. 1, 2019:

cd dist
python myscript.py

Generate license to bind obfuscated scripts to fixed machine, first get hardware information:

pyarmor hdinfo

Then generate new license bind to harddisk serial number and mac address:

pyarmor licenses --bind-disk '100304PBN2081SF3NJ5T' --bind-mac '20:c1:d2:2f:a0:96' code-002

Run obfuscated script with new license:

cp licenses/code-002/license.lic dist/

cd dist/
python myscript.py

Extending License Type

It’s easy to extend any other licese type for obfuscated scripts: just add authentication code in the entry script. The script can’t be changed any more after it is obfuscated, so write what ever you want by Python. For example, check expired date by NTP server other than local time:

import ntplib
from time import mktime, strptime
c = ntplib.NTPClient()
response = c.request('europe.pool.ntp.org', version=3)
if response.tx_time > mktime(strptime('20190202', '%Y%m%d')):
    sys.exit(1)

Packing Obfuscated Scripts

Use command pack to pack obfuscated scripts into the bundle.

First install PyInstaller:

pip install pyinstaller

Set the current directory to the location of your program myscript.py and execute:

pyarmor pack myscript.py

PyArmor packs myscript.py:

  • Execute pyarmor obfuscate to obfuscate myscript.py
  • Execute pyinstaller myscipt.py to create myscript.spec
  • Update myscript.spec, replace original scripts with obfuscated ones
  • Execute pyinstaller myscript.spec to bundle the obfuscated scripts

In the dist/myscript folder you find the bundled app you distribute to your users.

Run the final executeable file:

dist/myscript/myscript

Check the scripts have been obfuscated. It should return error:

rm dist/myscript/license.lic
dist/myscript/myscript

Generate an expired license for the bundle:

pyarmor licenses --expired 2019-01-01 code-003
cp licenses/code-003/license.lic dist/myscript

dist/myscript/myscript

Note that command pack maybe doesn’t work if .spec file of PyInstaller has been customed. You need edit .spec file to pack obfuscated scripts, See How To Pack Obfuscated Scripts.