A comprehensive Python code obfuscation engine
Project description
obfus
A comprehensive Python code obfuscation engine.
Features
- String Obfuscation - Multiple encoding methods (XOR, Base64, ROT13, multi-layer)
- Name Mangling - Local variables, arguments, code names, attributes
- Code Object Obfuscation - Bytecode encryption and protection
- Module Protection - Prevent modification and inspection
- Wrap Mode - Dynamic deobfuscation at runtime
- RFT (Refactoring) - Complete identifier renaming
- Import Obfuscation - Hide import statements
- Control Flow Obfuscation - Opaque predicates, dead code injection
- Zero Dependencies - Pure Python, no external packages required
Installation
pip install obfus
Or install from source:
git clone https://github.com/rodmena-limited/obfus.git
cd obfus
pip install -e .
Quick Start
Basic Usage
from obfus import ObfuscationConfig, ObfuscationEngine
# Use preset configurations
config = ObfuscationConfig.minimal() # Light obfuscation
config = ObfuscationConfig.standard() # Balanced obfuscation
config = ObfuscationConfig.aggressive() # Heavy obfuscation
# Create engine and obfuscate
engine = ObfuscationEngine(config)
obfuscated = engine.obfuscate_source('''
def hello(name):
return f"Hello, {name}!"
print(hello("World"))
''')
print(obfuscated)
Convenience Functions
from obfus import obfuscate, obfuscate_file, obfuscate_directory
# Obfuscate a string
result = obfuscate("print('Hello')")
# Obfuscate a file
obfuscate_file("input.py", "output.py")
# Obfuscate entire directory
obfuscate_directory("src/", "dist/")
Command Line
# Obfuscate a single file
obfus input.py -o output.py
# Obfuscate a directory
obfus src/ -o dist/
# With specific preset
obfus input.py -o output.py --preset aggressive
Configuration
Presets
| Preset | Description | Use Case |
|---|---|---|
minimal() |
Light obfuscation, preserves readability | Development, debugging |
standard() |
Balanced protection and performance | General distribution |
aggressive() |
Heavy obfuscation, harder to reverse | Production releases |
maximum() |
Maximum protection, slower execution | High-security applications |
Custom Configuration
from obfus import ObfuscationConfig, ObfuscationEngine, WrapMode
config = ObfuscationConfig(
# Name obfuscation
mix_localnames=True, # Obfuscate local variable names
mix_argnames=False, # Keep argument names (for keyword args)
mix_coname=1, # Hide code object names (0-2)
mix_attr=False, # Obfuscate attribute names
# String obfuscation
mix_str=True, # Obfuscate string constants
mix_str_threshold=8, # Min string length to obfuscate
# Module protection
obf_module=True, # Obfuscate module bytecode
obf_code=1, # Code object obfuscation level (0-2)
wrap_mode=WrapMode.SIMPLE, # Dynamic deobfuscation
# Advanced features
enable_rft=False, # Full identifier renaming
enable_control_flow=False, # Control flow obfuscation
enable_dead_code=False, # Dead code injection
)
engine = ObfuscationEngine(config)
Configuration Options Reference
Name Obfuscation
| Option | Type | Default | Description |
|---|---|---|---|
mix_localnames |
bool | True | Obfuscate local variable names |
mix_argnames |
bool | False | Obfuscate function argument names |
mix_coname |
int | 0 | Hide code object names (0=off, 1=partial, 2=full) |
mix_attr |
bool | False | Obfuscate attribute access names |
String Obfuscation
| Option | Type | Default | Description |
|---|---|---|---|
mix_str |
bool | False | Enable string constant obfuscation |
mix_str_threshold |
int | 8 | Minimum string length to obfuscate |
Module Protection
| Option | Type | Default | Description |
|---|---|---|---|
obf_module |
bool | True | Obfuscate module-level bytecode |
obf_code |
int | 1 | Code object encryption level (0-2) |
wrap_mode |
WrapMode | SIMPLE | Dynamic deobfuscation mode |
restrict_module |
RestrictionLevel | BASIC | Module access restrictions |
readonly_module |
bool | False | Make module attributes read-only |
Advanced Features
| Option | Type | Default | Description |
|---|---|---|---|
enable_rft |
bool | False | Enable full refactoring/renaming |
enable_control_flow |
bool | False | Add control flow obfuscation |
enable_dead_code |
bool | False | Inject dead code blocks |
enable_opaque_predicates |
bool | False | Add opaque predicates |
RFT (Refactoring) Mode
RFT mode performs complete identifier renaming across your codebase:
config = ObfuscationConfig(
enable_rft=True,
rft_excludes={'main', 'setup'}, # Names to preserve
rft_preserve_exports=True, # Keep __all__ names
)
RFT Options
| Option | Type | Default | Description |
|---|---|---|---|
rft_excludes |
Set[str] | {} | Names to exclude from renaming |
rft_auto_exclude |
int | 1 | Auto-exclude behavior (0-2) |
rft_preserve_exports |
bool | True | Preserve names in __all__ |
Limitations and Compatibility
Works With
- Pure Python code
- Standard library usage
- Internal class hierarchies
- Async/await patterns
- Generators and iterators
- Context managers
- Decorators
- Metaclasses
- Dataclasses and enums
May Break
| Scenario | Risk Level | Mitigation |
|---|---|---|
exec()/eval() with string names |
High | Use rft_excludes |
getattr()/setattr() with strings |
High | Use rft_excludes |
| Serialization (pickle, JSON) | High | Use minimal() preset |
| Framework magic (Django, Flask) | High | Use minimal() or skip |
| pytest fixtures | Medium | Don't obfuscate test files |
| CLI tools (Click, argparse) | Medium | Keep argument names |
| External API contracts | Medium | Use rft_excludes |
| Reflection-based libraries | Medium | Test thoroughly |
Safe Usage Guidelines
# For libraries with external interfaces
config = ObfuscationConfig.minimal()
# For standalone scripts
config = ObfuscationConfig.aggressive()
# For maximum protection (internal tools only)
config = ObfuscationConfig.maximum()
Performance
Obfuscation adds minimal runtime overhead:
| Operation | Overhead |
|---|---|
| Import time | ~0-5% |
| Simple operations | ~0-10% |
| String-heavy code | ~10-20% |
| With wrap mode | ~5-15% |
Test suite performance is typically within 5% of original code.
Examples
Obfuscate a Package
from obfus import obfuscate_directory, ObfuscationConfig
config = ObfuscationConfig.standard()
obfuscate_directory(
"mypackage/",
"dist/mypackage/",
config=config,
recursive=True,
)
Preserve Specific Names
config = ObfuscationConfig(
enable_rft=True,
rft_excludes={
'main',
'run',
'setup',
'teardown',
'__init__',
'__call__',
},
)
Skip Certain Files
from pathlib import Path
from obfus import ObfuscationEngine, ObfuscationConfig
config = ObfuscationConfig.standard()
engine = ObfuscationEngine(config)
for py_file in Path("src").rglob("*.py"):
# Skip test files and configs
if "test" in py_file.name or py_file.name == "config.py":
continue
source = py_file.read_text()
obfuscated = engine.obfuscate_source(source)
output = Path("dist") / py_file.relative_to("src")
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(obfuscated)
Testing
# Run all tests
pytest
# Run with coverage
pytest --cov=obfus --cov-report=html
# Run specific test class
pytest tests/test_obfuscator.py::TestAllFeatures -v
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see LICENSE for details.
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 Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file obfus-3.7.2.tar.gz.
File metadata
- Download URL: obfus-3.7.2.tar.gz
- Upload date:
- Size: 39.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2610fe0c288a6f4baf205fc53b9a7069774924a14c028bdb71ae1c70e0e52350
|
|
| MD5 |
fa85668b1cd84a754435130bf73a2c51
|
|
| BLAKE2b-256 |
4bc29271b3141eabb319e314f816f1568b7ea8f2c6268c6697ea56dcb0def285
|
File details
Details for the file obfus-3.7.2-py3-none-any.whl.
File metadata
- Download URL: obfus-3.7.2-py3-none-any.whl
- Upload date:
- Size: 24.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
61def12aa307e74a1d1b2a7decc1d5f24281cd3f7de1354709caef441e8e7c68
|
|
| MD5 |
280b724671ad4f81e6da29948704e7cc
|
|
| BLAKE2b-256 |
4555809498359ed4487b9042ea1ddd8ab6aad7f56e064ff624bdf44679a8e25d
|