Python code protection
Project description
Stonefish
Industry-grade Python code protection.
Quickstart
Protecting Python packages
If you have a Python package that you'd like to build with Stonefish, make
sure it follows PEP 517 and contains
at least a minimal pyproject.toml
. There, simply replace the your build system
(e.g., setuptools
) with stonefish
:
[build-system]
# requires = ["setuptools"]
# build-backend = "setuptools.build_meta"
requires = ["stonefish"]
build-backend = "stonefish.build_meta"
# ...
# more project metadata if you follow PEP 621
# <https://peps.python.org/pep-0621/>
# (recommended)
# ...
Done! Your project builds are now protected with Stonefish. Try it out with
pip install .
or
(pip install build)
python -m build . --wheel
Protecting standalone Python scripts
If you'd like to project just a single Python file, you
can use the stonefish
command-line utility, e.g.,
stonefish /path/to/file.py
How Stonefish protects your code
Python packages ship their code to all users, and there are different ways for every user to retrieve it. Unless built with Stonefish. Some examples:
Just opening the source files
After installation, users will find the package code in, e.g.,
~/.local/lib/python3.11/site-packages/numpy
. (The path is different for
different operation systems.)
When building with Stonefish, though, a source code like
├── pyproject.toml
└── stonefish_example
└── __init__.py
is installed as
├── _agg
│ ├── __init__.dat
│ ├── __init__.py
│ └── __pycache__
│ └── __init__.cpython-311.pyc
├── __init__.py
└── __pycache__
└── __init__.cpython-311.pyc
where all program logic is encrypted in the binary __init__.dat
. The actual
source code remains protected.
inspect — Inspect live objects
import stonefish_example
import inspect
print(inspect.getsource(stonefish_example.solve))
Without Stonefish | With Stonefish |
|
|
Dill
import stonefish_example
from dill.source import getsource
print(getsource(stonefish_example.solve))
Without Stonefish | With Stonefish |
|
|
IPython's ??
In [1]: import stonefish_example
In [2]: stonefish_example.solve??
Without Stonefish | With Stonefish |
|
|
dis — Disassembler for Python bytecode
import stonefish_example
import dis
dis.dis(stonefish_example.solve)
Without Stonefish | With Stonefish |
|
|
xdis
import stonefish_example
import xdis.std as dis
dis.dis(stonefish_example.solve)
Without Stonefish | With Stonefish |
|
|
decompyle3, uncompyle6 etc.
Those tools are meant to recreated Python code from .pyc
files.
Since Stonefish moves the actual code into an encrypted
decompyle3 ~/path/to/__init__.cpython-38.pyc
Without Stonefish | With Stonefish |
|
|
Limitations
-
Stonefish renames class/function names, so you cannot rely on the
__name__
attribute in your code. -
Users must add
*.dat
files to their package data, e.g.,[tool.setuptools.package-data] "*" = ["*.dat"]
in
pyproject.toml
. This is because the encrypted code must be shipped with the package. -
Local imports must be relative, i.e.,
from . import x
instead ofimport x
ifx/
/x.py
is an internal folder or directory. This is recommended anyway. -
Stonefish will put all data files in a flat directory structure. That's why it cannot yet handle files that are read from two different Python paths, e.g.,
./data.dat ./a.py Path(__file__).parent / "data.dat" ./b/b.py Path(__file__).parent / .. / "data.dat"
-
Stonefish discards private (underscored) names from the API. If you want your users to use these variables or functions, you'll have to rename them.
-
Stonefish cannot yet handle relative
*
imports, e.g.,from .utils import *
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
File details
Details for the file stonefish-0.3.26-py3-none-any.whl
.
File metadata
- Download URL: stonefish-0.3.26-py3-none-any.whl
- Upload date:
- Size: 68.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/4.0.2 CPython/3.11.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d1763b08e4ac094b9c92e15dd5bd7723d7234460197af1ecfe05ac41ad1c8258 |
|
MD5 | 33e70254560f910b634f9caf19793e92 |
|
BLAKE2b-256 | 089cff874d7240e1af75d0fad6571f38cfcd2c30015116d9d18db749dc70a7ad |