pyencode-protector 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. pyencode_protector-0.3.0/PKG-INFO +276 -0
  2. pyencode_protector-0.3.0/README.md +253 -0
  3. pyencode_protector-0.3.0/pyproject.toml +41 -0
  4. pyencode_protector-0.3.0/setup.cfg +4 -0
  5. pyencode_protector-0.3.0/src/pyencode/__init__.py +5 -0
  6. pyencode_protector-0.3.0/src/pyencode/__main__.py +8 -0
  7. pyencode_protector-0.3.0/src/pyencode/builder.py +628 -0
  8. pyencode_protector-0.3.0/src/pyencode/cli.py +136 -0
  9. pyencode_protector-0.3.0/src/pyencode/code_hardening.py +185 -0
  10. pyencode_protector-0.3.0/src/pyencode/container.py +319 -0
  11. pyencode_protector-0.3.0/src/pyencode/crypto.py +319 -0
  12. pyencode_protector-0.3.0/src/pyencode/discovery.py +168 -0
  13. pyencode_protector-0.3.0/src/pyencode/errors.py +59 -0
  14. pyencode_protector-0.3.0/src/pyencode/integrity.py +88 -0
  15. pyencode_protector-0.3.0/src/pyencode/inventory.py +356 -0
  16. pyencode_protector-0.3.0/src/pyencode/manifest.py +196 -0
  17. pyencode_protector-0.3.0/src/pyencode/opaque.py +574 -0
  18. pyencode_protector-0.3.0/src/pyencode/runtime_template/__init__.py +99 -0
  19. pyencode_protector-0.3.0/src/pyencode/runtime_template/_build.py +15 -0
  20. pyencode_protector-0.3.0/src/pyencode/runtime_template/_mp_main.py +7 -0
  21. pyencode_protector-0.3.0/src/pyencode/runtime_template/_runtime.py +1488 -0
  22. pyencode_protector-0.3.0/src/pyencode/source.py +50 -0
  23. pyencode_protector-0.3.0/src/pyencode_protector.egg-info/PKG-INFO +276 -0
  24. pyencode_protector-0.3.0/src/pyencode_protector.egg-info/SOURCES.txt +31 -0
  25. pyencode_protector-0.3.0/src/pyencode_protector.egg-info/dependency_links.txt +1 -0
  26. pyencode_protector-0.3.0/src/pyencode_protector.egg-info/entry_points.txt +2 -0
  27. pyencode_protector-0.3.0/src/pyencode_protector.egg-info/requires.txt +1 -0
  28. pyencode_protector-0.3.0/src/pyencode_protector.egg-info/top_level.txt +1 -0
  29. pyencode_protector-0.3.0/tests/test_code_hardening.py +181 -0
  30. pyencode_protector-0.3.0/tests/test_core.py +153 -0
  31. pyencode_protector-0.3.0/tests/test_integration.py +1086 -0
  32. pyencode_protector-0.3.0/tests/test_inventory.py +191 -0
  33. pyencode_protector-0.3.0/tests/test_opaque.py +311 -0
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyencode-protector
3
+ Version: 0.3.0
4
+ Summary: A small cross-platform Python module protector
5
+ Author: PyEncode contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/VanThanBK/pyencode
8
+ Project-URL: Repository, https://github.com/VanThanBK/pyencode
9
+ Project-URL: Issues, https://github.com/VanThanBK/pyencode/issues
10
+ Keywords: python,code-protection,obfuscation,encryption
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: Microsoft :: Windows
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: Implementation :: CPython
18
+ Classifier: Topic :: Security :: Cryptography
19
+ Classifier: Topic :: Software Development :: Build Tools
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: cryptography>=42
23
+
24
+ # PyEncode
25
+
26
+ PyEncode là công cụ bảo vệ ứng dụng CPython thuần Python, hướng tới Windows và
27
+ Linux. Mỗi module được biên dịch thành code object, tuần tự hóa bằng `marshal`,
28
+ nén rồi mã hóa xác thực bằng AES-256-GCM. Runtime giải mã và thực thi trong bộ
29
+ nhớ; source và bytecode rõ không được ghi ra file tạm.
30
+
31
+ Phiên bản 0.3 dùng định dạng PYE2:
32
+
33
+ - Mỗi artifact có tên ngẫu nhiên 128 bit, ví dụ
34
+ `myapp/7b82a40e9aa14e60db7094f2de3fbc33.pye`.
35
+ - PYE2 không có header JSON rõ; file chỉ chứa magic, nonce và ciphertext/tag.
36
+ - Tên module, entry point và cờ package nằm trong một module index được mã hóa.
37
+ - Manifest format 3 được ký Ed25519 và chứa hash SHA-256 của artifact.
38
+ - Runtime, launcher, resource và support tree do builder sao chép đều được ký,
39
+ key-bind và kiểm tra lại lúc `install()`.
40
+ - Loader chỉ trả một trampoline nhỏ cho `runpy`, không trả code object thật của
41
+ ứng dụng. Khóa module được dẫn xuất theo nhu cầu và không giữ trong finder.
42
+
43
+ Mục tiêu là tăng đáng kể chi phí phân tích so với `.pyc`, không phải tạo cơ chế
44
+ chống reverse tuyệt đối.
45
+
46
+ ## Python được hỗ trợ
47
+
48
+ PyEncode 0.3 yêu cầu **CPython chuẩn 3.10 trở lên**. CI kiểm thử trực tiếp các
49
+ phiên bản 3.10 đến 3.15; các CPython feature release mới hơn được phép cài và
50
+ build theo hướng forward-compatible, rồi được đưa vào ma trận bắt buộc sau khi
51
+ có bản phát hành và dependency wheel tương ứng. PyPy và các interpreter khác
52
+ hiện chưa được hỗ trợ.
53
+
54
+ Runtime là Python thuần nên cùng source runtime dùng được trên Windows và
55
+ Linux. Tuy nhiên artifact đã build gắn với đúng CPython major/minor:
56
+
57
+ - build bằng CPython 3.11 → chạy bằng CPython 3.11;
58
+ - không chạy artifact đó bằng 3.10, 3.12 hoặc 3.14;
59
+ - muốn phát hành cho nhiều minor version, build một output bằng từng interpreter.
60
+
61
+ Nếu bundle có thêm `.pyd`, `.so`, `.dll` hoặc dependency native qua `--support`,
62
+ toàn bundle còn phụ thuộc hệ điều hành, kiến trúc và ABI của các file đó. Phạm
63
+ vi kiểm thử hiện tại là CPython GIL tiêu chuẩn; free-threaded/debug ABI cần build
64
+ và kiểm tra riêng.
65
+
66
+ ## Cài đặt
67
+
68
+ Sau khi package được phát hành trên PyPI, cài bằng:
69
+
70
+ ```powershell
71
+ py -3.11 -m venv .venv
72
+ .venv\Scripts\Activate.ps1
73
+ python -m pip install --upgrade pip
74
+ python -m pip install pyencode-protector
75
+ ```
76
+
77
+ Tên lệnh CLI và import namespace vẫn là `pyencode`.
78
+
79
+ Để phát triển trực tiếp từ source, cài editable trong virtual environment:
80
+
81
+ Windows PowerShell:
82
+
83
+ ```powershell
84
+ py -3.11 -m venv .venv
85
+ .venv\Scripts\Activate.ps1
86
+ python -m pip install --upgrade pip
87
+ python -m pip install -e .
88
+ ```
89
+
90
+ Linux:
91
+
92
+ ```bash
93
+ python3.11 -m venv .venv
94
+ source .venv/bin/activate
95
+ python -m pip install --upgrade pip
96
+ python -m pip install -e .
97
+ ```
98
+
99
+ Dependency runtime duy nhất là `cryptography>=42`.
100
+
101
+ ## Sử dụng
102
+
103
+ Bảo vệ một file:
104
+
105
+ ```bash
106
+ pyencode build hello.py -o dist/hello
107
+ python dist/hello/run.py
108
+ ```
109
+
110
+ Bảo vệ package có `__main__.py`:
111
+
112
+ ```bash
113
+ pyencode build src/myapp -o dist/myapp
114
+ python dist/myapp/run.py
115
+ ```
116
+
117
+ Chỉ định entry module:
118
+
119
+ ```bash
120
+ pyencode build src -o dist/app --entry myapp.__main__
121
+ ```
122
+
123
+ Ký và key-bind thêm dependency/support tree:
124
+
125
+ ```bash
126
+ pyencode build src -o dist/app \
127
+ --entry myapp.main \
128
+ --support build/vendor _vendor \
129
+ --support public/config.json config.json
130
+ ```
131
+
132
+ `--support SOURCE DEST` có thể lặp lại. Nếu `SOURCE` là thư mục, nội dung cây
133
+ được chép dưới `DEST`; nếu là file, `DEST` là đường dẫn file đầu ra. Symlink,
134
+ reparse point, đường dẫn thoát root và va chạm chữ hoa/thường bị từ chối.
135
+
136
+ Đích chính xác `_vendor` được xem là bootstrap dependency path cho host không
137
+ có `cryptography` cài sẵn (như Fusion). Chỉ đúng entry `_vendor` trong
138
+ `sys.path` được giữ lúc verifier nạp; mọi đường dẫn con khác trong bundle bị
139
+ cách ly. Vì thư viện mật mã vendored phải chạy trước khi Ed25519 có thể tự kiểm
140
+ chứng bundle, `_vendor` là một phần bootstrap được tin cậy theo thiết kế của
141
+ runtime Python thuần; chỉ đóng gói wheel lấy từ nguồn tin cậy.
142
+
143
+ Các tùy chọn chính:
144
+
145
+ - `-o`, `--output`: thư mục output; phải chưa tồn tại hoặc hoàn toàn rỗng.
146
+ - `-e`, `--entry`: dotted name của entry module/package.
147
+ - `--exclude GLOB`: loại đường dẫn khớp glob; có thể lặp.
148
+ - `--no-resources`: không sao chép file không phải Python trong source tree.
149
+ - `--keep-docstrings`: giữ docstring.
150
+ - `--optimize {0,1,2}`: mức tối ưu CPython.
151
+ - `--expires YYYY-MM-DD`: từ chối chạy sau ngày UTC đã cho.
152
+ - `--launcher PATH`: dùng launcher `.py` tùy biến.
153
+ - `--support SOURCE DEST`: sao chép, ký và key-bind file/cây hỗ trợ.
154
+ - `--rename-locals`: đổi tên metadata của local không phải tham số.
155
+ - `--allow-extra-data`: cho host tạo thêm file/thư mục dữ liệu không thực thi;
156
+ file đã ký và Python/native artifact lạ vẫn bị kiểm tra.
157
+
158
+ `--rename-locals` là opt-in vì code dùng alias động của `locals()`, đọc
159
+ `frame.f_locals`, debugger hoặc một số framework introspection có thể cần tên
160
+ local gốc. Argument, closure, line table và exception table luôn được giữ.
161
+
162
+ ## Launcher tùy biến và host nhúng
163
+
164
+ Launcher được sao chép nguyên byte, ký và tham gia dẫn xuất khóa. Nó phải đặt:
165
+
166
+ ```python
167
+ import sys
168
+ sys.dont_write_bytecode = True
169
+ ```
170
+
171
+ trước mọi import không phải bootstrap. Builder kiểm tra điều kiện tối thiểu này.
172
+ Một launcher ship an toàn cũng phải kiểm tra `pyencode_runtime` không chứa
173
+ `__pycache__`, `.pyc` hoặc file lạ **trước** khi import package; launcher mặc
174
+ định và pipeline Weldments đã có preflight đầy đủ.
175
+
176
+ Host như Fusion có thể nạp entry mà không ghi tên module rõ trong stub:
177
+
178
+ ```python
179
+ import sys
180
+ sys.dont_write_bytecode = True
181
+
182
+ # Thực hiện preflight pyencode_runtime tại đây.
183
+ from pyencode_runtime import load_entry
184
+
185
+ implementation = load_entry()
186
+ ```
187
+
188
+ `install()` cố ý trả `None`. `load_entry()` trả module entry cho embedding host;
189
+ `run()` thực thi entry với ngữ nghĩa `__main__`.
190
+
191
+ ## Output
192
+
193
+ ```text
194
+ dist/app/
195
+ ├── .pyencode-manifest.json
196
+ ├── myapp/
197
+ │ ├── 14a0...f91c.pye
198
+ │ ├── 7b82...bc33.pye
199
+ │ └── assets/config.json
200
+ ├── pyencode_runtime/
201
+ │ ├── __init__.py
202
+ │ ├── _build.py
203
+ │ ├── _mp_main.py
204
+ │ └── _runtime.py
205
+ ├── requirements.txt
206
+ └── run.py
207
+ ```
208
+
209
+ Resource không được mã hóa, nhưng byte/path của resource build-time được ký và
210
+ key-bind. Mặc định toàn bộ cây output là bất biến: runtime từ chối mọi file hoặc
211
+ thư mục được thêm, xóa hay đổi byte.
212
+
213
+ Với host tự tạo metadata/cache cạnh add-in, `--allow-extra-data` cho phép thêm
214
+ file và thư mục dữ liệu mà không làm bundle chết. Chế độ này không cho sửa/xóa
215
+ file đã ký, không cho thêm `.py`, `.pyc`, native library hoặc `.pye` lạ, và vẫn
216
+ từ chối symlink/reparse point. Không dùng data bổ sung này làm đầu vào tin cậy
217
+ cho license hay quyết định bảo mật. Pipeline Weldments bật chế độ tương thích
218
+ này để Fusion có thể tạo `.vscode`, log hoặc cache khác nhau giữa các máy.
219
+
220
+ `__file__` của protected module là đường dẫn thật tới artifact ngẫu nhiên. Vì
221
+ vậy `Path(__file__).parent`, `pkgutil.get_data()` và `importlib.resources` kể cả
222
+ resource lồng thư mục vẫn hoạt động; code phụ thuộc basename/stem của
223
+ `__file__` sẽ thấy token ngẫu nhiên.
224
+
225
+ Import theo fullname, relative import, circular import, namespace package,
226
+ Unicode module, reload, `runpy.run_module()` và `multiprocessing` spawn của app
227
+ chạy qua launcher mặc định đều có test tích hợp. `pkgutil.iter_modules()` và
228
+ `walk_packages()` không thể tự khám phá tên protected child vì tên đó cố ý nằm
229
+ trong index mã hóa; import theo fullname đã biết vẫn hoạt động.
230
+
231
+ Với embedding host gọi `load_entry()`, spawn hoạt động nếu child cũng chạy lại
232
+ bootstrap của host. Trường hợp host chỉ bootstrap bên trong
233
+ `if __name__ == '__main__'` rồi spawn trực tiếp một target protected cần launcher
234
+ riêng; bootstrap spawn tự động hiện tập trung vào app chạy qua `run()`.
235
+
236
+ Phiên bản 0.3 dùng một namespace runtime cố định trong mỗi process. Không nạp
237
+ hai distribution PyEncode độc lập vào cùng một interpreter; chạy chúng ở hai
238
+ process riêng. Runtime namespace ngẫu nhiên/đa-bundle là hạng mục tương thích
239
+ trước khi công bố API ổn định 1.0.
240
+
241
+ ## Giới hạn bảo mật
242
+
243
+ PyEncode làm khó phân tích tĩnh nhưng không thể giữ bí mật tuyệt đối trên máy do
244
+ người khác toàn quyền kiểm soát:
245
+
246
+ - Chế độ mặc định là offline nên key material vẫn phải nằm trong bundle. Người
247
+ có kinh nghiệm có thể đọc runtime và tái tạo quá trình dẫn xuất khóa.
248
+ - Code object phải xuất hiện trong bộ nhớ khi thực thi. Tracing, debugger,
249
+ monkeypatch hoặc hook native vẫn có thể quan sát code/runtime state.
250
+ - Integrity interlock chặn sửa file, tráo artifact, chèn code và re-sign đơn
251
+ giản; nó không biến Python thuần thành trust anchor native.
252
+ - Tên module/entry được che khi nằm yên, nhưng xuất hiện lúc import trong
253
+ `sys.modules`, traceback và runtime state. Thư mục package/resource vẫn có thể
254
+ tiết lộ một phần cấu trúc.
255
+ - `--expires` dựa trên đồng hồ hệ thống và không thay thế hệ thống license.
256
+
257
+ Đừng đặt API key/private key dài hạn trong client. Bước nâng cấp tạo khác biệt
258
+ bảo mật thực sự cho sản phẩm giá trị cao là external/envelope key lấy từ license
259
+ server hoặc keyring; native runtime chủ yếu tăng thêm chi phí phân tích.
260
+
261
+ ## Kiểm thử
262
+
263
+ ```bash
264
+ python -m unittest discover -v
265
+ ```
266
+
267
+ CI chạy trên Windows và Ubuntu với CPython 3.10–3.15. Bộ test bao phủ PYE2,
268
+ module index mã hóa, KDF vectors, tamper/re-sign, resource/support integrity,
269
+ opaque filenames, import/package/namespace/Unicode, `runpy`, multiprocessing
270
+ spawn, launcher thường không có `-B`, policy hết hạn và output atomic.
271
+
272
+ ## Phát hành
273
+
274
+ Quy trình phát hành production bằng GitHub OIDC được ghi tại
275
+ [RELEASING.md](RELEASING.md). Workflow chỉ upload lên PyPI khi push tag khớp
276
+ chính xác version, ví dụ `v0.3.0`.
@@ -0,0 +1,253 @@
1
+ # PyEncode
2
+
3
+ PyEncode là công cụ bảo vệ ứng dụng CPython thuần Python, hướng tới Windows và
4
+ Linux. Mỗi module được biên dịch thành code object, tuần tự hóa bằng `marshal`,
5
+ nén rồi mã hóa xác thực bằng AES-256-GCM. Runtime giải mã và thực thi trong bộ
6
+ nhớ; source và bytecode rõ không được ghi ra file tạm.
7
+
8
+ Phiên bản 0.3 dùng định dạng PYE2:
9
+
10
+ - Mỗi artifact có tên ngẫu nhiên 128 bit, ví dụ
11
+ `myapp/7b82a40e9aa14e60db7094f2de3fbc33.pye`.
12
+ - PYE2 không có header JSON rõ; file chỉ chứa magic, nonce và ciphertext/tag.
13
+ - Tên module, entry point và cờ package nằm trong một module index được mã hóa.
14
+ - Manifest format 3 được ký Ed25519 và chứa hash SHA-256 của artifact.
15
+ - Runtime, launcher, resource và support tree do builder sao chép đều được ký,
16
+ key-bind và kiểm tra lại lúc `install()`.
17
+ - Loader chỉ trả một trampoline nhỏ cho `runpy`, không trả code object thật của
18
+ ứng dụng. Khóa module được dẫn xuất theo nhu cầu và không giữ trong finder.
19
+
20
+ Mục tiêu là tăng đáng kể chi phí phân tích so với `.pyc`, không phải tạo cơ chế
21
+ chống reverse tuyệt đối.
22
+
23
+ ## Python được hỗ trợ
24
+
25
+ PyEncode 0.3 yêu cầu **CPython chuẩn 3.10 trở lên**. CI kiểm thử trực tiếp các
26
+ phiên bản 3.10 đến 3.15; các CPython feature release mới hơn được phép cài và
27
+ build theo hướng forward-compatible, rồi được đưa vào ma trận bắt buộc sau khi
28
+ có bản phát hành và dependency wheel tương ứng. PyPy và các interpreter khác
29
+ hiện chưa được hỗ trợ.
30
+
31
+ Runtime là Python thuần nên cùng source runtime dùng được trên Windows và
32
+ Linux. Tuy nhiên artifact đã build gắn với đúng CPython major/minor:
33
+
34
+ - build bằng CPython 3.11 → chạy bằng CPython 3.11;
35
+ - không chạy artifact đó bằng 3.10, 3.12 hoặc 3.14;
36
+ - muốn phát hành cho nhiều minor version, build một output bằng từng interpreter.
37
+
38
+ Nếu bundle có thêm `.pyd`, `.so`, `.dll` hoặc dependency native qua `--support`,
39
+ toàn bundle còn phụ thuộc hệ điều hành, kiến trúc và ABI của các file đó. Phạm
40
+ vi kiểm thử hiện tại là CPython GIL tiêu chuẩn; free-threaded/debug ABI cần build
41
+ và kiểm tra riêng.
42
+
43
+ ## Cài đặt
44
+
45
+ Sau khi package được phát hành trên PyPI, cài bằng:
46
+
47
+ ```powershell
48
+ py -3.11 -m venv .venv
49
+ .venv\Scripts\Activate.ps1
50
+ python -m pip install --upgrade pip
51
+ python -m pip install pyencode-protector
52
+ ```
53
+
54
+ Tên lệnh CLI và import namespace vẫn là `pyencode`.
55
+
56
+ Để phát triển trực tiếp từ source, cài editable trong virtual environment:
57
+
58
+ Windows PowerShell:
59
+
60
+ ```powershell
61
+ py -3.11 -m venv .venv
62
+ .venv\Scripts\Activate.ps1
63
+ python -m pip install --upgrade pip
64
+ python -m pip install -e .
65
+ ```
66
+
67
+ Linux:
68
+
69
+ ```bash
70
+ python3.11 -m venv .venv
71
+ source .venv/bin/activate
72
+ python -m pip install --upgrade pip
73
+ python -m pip install -e .
74
+ ```
75
+
76
+ Dependency runtime duy nhất là `cryptography>=42`.
77
+
78
+ ## Sử dụng
79
+
80
+ Bảo vệ một file:
81
+
82
+ ```bash
83
+ pyencode build hello.py -o dist/hello
84
+ python dist/hello/run.py
85
+ ```
86
+
87
+ Bảo vệ package có `__main__.py`:
88
+
89
+ ```bash
90
+ pyencode build src/myapp -o dist/myapp
91
+ python dist/myapp/run.py
92
+ ```
93
+
94
+ Chỉ định entry module:
95
+
96
+ ```bash
97
+ pyencode build src -o dist/app --entry myapp.__main__
98
+ ```
99
+
100
+ Ký và key-bind thêm dependency/support tree:
101
+
102
+ ```bash
103
+ pyencode build src -o dist/app \
104
+ --entry myapp.main \
105
+ --support build/vendor _vendor \
106
+ --support public/config.json config.json
107
+ ```
108
+
109
+ `--support SOURCE DEST` có thể lặp lại. Nếu `SOURCE` là thư mục, nội dung cây
110
+ được chép dưới `DEST`; nếu là file, `DEST` là đường dẫn file đầu ra. Symlink,
111
+ reparse point, đường dẫn thoát root và va chạm chữ hoa/thường bị từ chối.
112
+
113
+ Đích chính xác `_vendor` được xem là bootstrap dependency path cho host không
114
+ có `cryptography` cài sẵn (như Fusion). Chỉ đúng entry `_vendor` trong
115
+ `sys.path` được giữ lúc verifier nạp; mọi đường dẫn con khác trong bundle bị
116
+ cách ly. Vì thư viện mật mã vendored phải chạy trước khi Ed25519 có thể tự kiểm
117
+ chứng bundle, `_vendor` là một phần bootstrap được tin cậy theo thiết kế của
118
+ runtime Python thuần; chỉ đóng gói wheel lấy từ nguồn tin cậy.
119
+
120
+ Các tùy chọn chính:
121
+
122
+ - `-o`, `--output`: thư mục output; phải chưa tồn tại hoặc hoàn toàn rỗng.
123
+ - `-e`, `--entry`: dotted name của entry module/package.
124
+ - `--exclude GLOB`: loại đường dẫn khớp glob; có thể lặp.
125
+ - `--no-resources`: không sao chép file không phải Python trong source tree.
126
+ - `--keep-docstrings`: giữ docstring.
127
+ - `--optimize {0,1,2}`: mức tối ưu CPython.
128
+ - `--expires YYYY-MM-DD`: từ chối chạy sau ngày UTC đã cho.
129
+ - `--launcher PATH`: dùng launcher `.py` tùy biến.
130
+ - `--support SOURCE DEST`: sao chép, ký và key-bind file/cây hỗ trợ.
131
+ - `--rename-locals`: đổi tên metadata của local không phải tham số.
132
+ - `--allow-extra-data`: cho host tạo thêm file/thư mục dữ liệu không thực thi;
133
+ file đã ký và Python/native artifact lạ vẫn bị kiểm tra.
134
+
135
+ `--rename-locals` là opt-in vì code dùng alias động của `locals()`, đọc
136
+ `frame.f_locals`, debugger hoặc một số framework introspection có thể cần tên
137
+ local gốc. Argument, closure, line table và exception table luôn được giữ.
138
+
139
+ ## Launcher tùy biến và host nhúng
140
+
141
+ Launcher được sao chép nguyên byte, ký và tham gia dẫn xuất khóa. Nó phải đặt:
142
+
143
+ ```python
144
+ import sys
145
+ sys.dont_write_bytecode = True
146
+ ```
147
+
148
+ trước mọi import không phải bootstrap. Builder kiểm tra điều kiện tối thiểu này.
149
+ Một launcher ship an toàn cũng phải kiểm tra `pyencode_runtime` không chứa
150
+ `__pycache__`, `.pyc` hoặc file lạ **trước** khi import package; launcher mặc
151
+ định và pipeline Weldments đã có preflight đầy đủ.
152
+
153
+ Host như Fusion có thể nạp entry mà không ghi tên module rõ trong stub:
154
+
155
+ ```python
156
+ import sys
157
+ sys.dont_write_bytecode = True
158
+
159
+ # Thực hiện preflight pyencode_runtime tại đây.
160
+ from pyencode_runtime import load_entry
161
+
162
+ implementation = load_entry()
163
+ ```
164
+
165
+ `install()` cố ý trả `None`. `load_entry()` trả module entry cho embedding host;
166
+ `run()` thực thi entry với ngữ nghĩa `__main__`.
167
+
168
+ ## Output
169
+
170
+ ```text
171
+ dist/app/
172
+ ├── .pyencode-manifest.json
173
+ ├── myapp/
174
+ │ ├── 14a0...f91c.pye
175
+ │ ├── 7b82...bc33.pye
176
+ │ └── assets/config.json
177
+ ├── pyencode_runtime/
178
+ │ ├── __init__.py
179
+ │ ├── _build.py
180
+ │ ├── _mp_main.py
181
+ │ └── _runtime.py
182
+ ├── requirements.txt
183
+ └── run.py
184
+ ```
185
+
186
+ Resource không được mã hóa, nhưng byte/path của resource build-time được ký và
187
+ key-bind. Mặc định toàn bộ cây output là bất biến: runtime từ chối mọi file hoặc
188
+ thư mục được thêm, xóa hay đổi byte.
189
+
190
+ Với host tự tạo metadata/cache cạnh add-in, `--allow-extra-data` cho phép thêm
191
+ file và thư mục dữ liệu mà không làm bundle chết. Chế độ này không cho sửa/xóa
192
+ file đã ký, không cho thêm `.py`, `.pyc`, native library hoặc `.pye` lạ, và vẫn
193
+ từ chối symlink/reparse point. Không dùng data bổ sung này làm đầu vào tin cậy
194
+ cho license hay quyết định bảo mật. Pipeline Weldments bật chế độ tương thích
195
+ này để Fusion có thể tạo `.vscode`, log hoặc cache khác nhau giữa các máy.
196
+
197
+ `__file__` của protected module là đường dẫn thật tới artifact ngẫu nhiên. Vì
198
+ vậy `Path(__file__).parent`, `pkgutil.get_data()` và `importlib.resources` kể cả
199
+ resource lồng thư mục vẫn hoạt động; code phụ thuộc basename/stem của
200
+ `__file__` sẽ thấy token ngẫu nhiên.
201
+
202
+ Import theo fullname, relative import, circular import, namespace package,
203
+ Unicode module, reload, `runpy.run_module()` và `multiprocessing` spawn của app
204
+ chạy qua launcher mặc định đều có test tích hợp. `pkgutil.iter_modules()` và
205
+ `walk_packages()` không thể tự khám phá tên protected child vì tên đó cố ý nằm
206
+ trong index mã hóa; import theo fullname đã biết vẫn hoạt động.
207
+
208
+ Với embedding host gọi `load_entry()`, spawn hoạt động nếu child cũng chạy lại
209
+ bootstrap của host. Trường hợp host chỉ bootstrap bên trong
210
+ `if __name__ == '__main__'` rồi spawn trực tiếp một target protected cần launcher
211
+ riêng; bootstrap spawn tự động hiện tập trung vào app chạy qua `run()`.
212
+
213
+ Phiên bản 0.3 dùng một namespace runtime cố định trong mỗi process. Không nạp
214
+ hai distribution PyEncode độc lập vào cùng một interpreter; chạy chúng ở hai
215
+ process riêng. Runtime namespace ngẫu nhiên/đa-bundle là hạng mục tương thích
216
+ trước khi công bố API ổn định 1.0.
217
+
218
+ ## Giới hạn bảo mật
219
+
220
+ PyEncode làm khó phân tích tĩnh nhưng không thể giữ bí mật tuyệt đối trên máy do
221
+ người khác toàn quyền kiểm soát:
222
+
223
+ - Chế độ mặc định là offline nên key material vẫn phải nằm trong bundle. Người
224
+ có kinh nghiệm có thể đọc runtime và tái tạo quá trình dẫn xuất khóa.
225
+ - Code object phải xuất hiện trong bộ nhớ khi thực thi. Tracing, debugger,
226
+ monkeypatch hoặc hook native vẫn có thể quan sát code/runtime state.
227
+ - Integrity interlock chặn sửa file, tráo artifact, chèn code và re-sign đơn
228
+ giản; nó không biến Python thuần thành trust anchor native.
229
+ - Tên module/entry được che khi nằm yên, nhưng xuất hiện lúc import trong
230
+ `sys.modules`, traceback và runtime state. Thư mục package/resource vẫn có thể
231
+ tiết lộ một phần cấu trúc.
232
+ - `--expires` dựa trên đồng hồ hệ thống và không thay thế hệ thống license.
233
+
234
+ Đừng đặt API key/private key dài hạn trong client. Bước nâng cấp tạo khác biệt
235
+ bảo mật thực sự cho sản phẩm giá trị cao là external/envelope key lấy từ license
236
+ server hoặc keyring; native runtime chủ yếu tăng thêm chi phí phân tích.
237
+
238
+ ## Kiểm thử
239
+
240
+ ```bash
241
+ python -m unittest discover -v
242
+ ```
243
+
244
+ CI chạy trên Windows và Ubuntu với CPython 3.10–3.15. Bộ test bao phủ PYE2,
245
+ module index mã hóa, KDF vectors, tamper/re-sign, resource/support integrity,
246
+ opaque filenames, import/package/namespace/Unicode, `runpy`, multiprocessing
247
+ spawn, launcher thường không có `-B`, policy hết hạn và output atomic.
248
+
249
+ ## Phát hành
250
+
251
+ Quy trình phát hành production bằng GitHub OIDC được ghi tại
252
+ [RELEASING.md](RELEASING.md). Workflow chỉ upload lên PyPI khi push tag khớp
253
+ chính xác version, ví dụ `v0.3.0`.
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["setuptools>=65", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyencode-protector"
7
+ version = "0.3.0"
8
+ description = "A small cross-platform Python module protector"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "PyEncode contributors" }]
13
+ keywords = ["python", "code-protection", "obfuscation", "encryption"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "Operating System :: Microsoft :: Windows",
19
+ "Operating System :: POSIX :: Linux",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: Implementation :: CPython",
22
+ "Topic :: Security :: Cryptography",
23
+ "Topic :: Software Development :: Build Tools",
24
+ ]
25
+ dependencies = [
26
+ "cryptography>=42",
27
+ ]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/VanThanBK/pyencode"
31
+ Repository = "https://github.com/VanThanBK/pyencode"
32
+ Issues = "https://github.com/VanThanBK/pyencode/issues"
33
+
34
+ [project.scripts]
35
+ pyencode = "pyencode.cli:main"
36
+
37
+ [tool.setuptools]
38
+ package-dir = { "" = "src" }
39
+
40
+ [tool.setuptools.packages.find]
41
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ """Build encrypted Python module bundles."""
2
+
3
+ from __future__ import annotations
4
+
5
+ __version__ = "0.3.0"
@@ -0,0 +1,8 @@
1
+ from __future__ import annotations
2
+
3
+ from .cli import main
4
+
5
+
6
+ if __name__ == "__main__":
7
+ raise SystemExit(main())
8
+