Camouflage library, reversible data anonymization
Project description
Camouflage 🛡️
Anonymize. Protect. Restore.
Flexible and reversible anonymization for modern Python workflows.
Ready to get started?
Install Camouflage with pip:
pip install camouflage
✨ What is Camouflage?
Camouflage lets you easily anonymize sensitive data, store reversible mappings, and restore the original dataset when needed — all while being fast, lightweight, and fully customizable.
- 🔥 Anonymize large datasets quickly.
- 🛠️ Add your own plugins easily (your data, your rules).
- 🔄 Reversible by design — restore original values without headaches.
- 🧪 100% test coverage for maximum trust.
- 🏎️ Tested on datasets with over 100,000 rows across 6 columns — handles big data smoothly.
📈 How it Works
Camouflage uses a one-to-one mapping to anonymize data. It generates a unique, consistent, and reversible mapping for each value. See Bijection on Wikipedia.
Camouflage guarantees that every anonymized value is unique, consistent, and traceable back — only when you need it.
🚀 Quick Start
1️⃣ One-Time Anonymization
from camouflage import anonymize
original_value = "192.168.1.1"
anonymized_value = anonymize("ipv4", original_value)
2️⃣ Reversible Anonymization
from camouflage import anonymize, deanonymize, Transform
original_value = "192.168.1.1"
transform = Transform()
# Anonymize
anonymized_value = anonymize("ipv4", original_value, transform)
# Do something with the anonymized value
# ...
# De-anonymize
deanonymized_value = deanonymize("ipv4", anonymized_value, transform)
3️⃣ Anonymizing a Pandas DataFrame
import pandas as pd
from camouflage import PandasAdapter
df = pd.DataFrame({
"ip": ["192.168.1.1", "10.0.0.1"],
"joined_at": [pd.Timestamp("2023-01-01"), pd.Timestamp("2023-02-01")],
"revenue": [1234.56, 7890.12],
})
# | ip | joined_at | revenue |
# |:------------|:--------------------|----------:|
# | 192.168.1.1 | 2023-01-01 00:00:00 | 1234.56 |
# | 10.0.0.1 | 2023-02-01 00:00:00 | 7890.12 |
mapper = {
"ip": "ipv4",
"joined_at": "datetime",
"revenue": "amount",
}
pd_adapter = PandasAdapter(mapper)
df_safe = pd_adapter.anonymize(df)
# | ip | joined_at | revenue |
# |:---------------|:--------------------|----------:|
# | 137.224.91.30 | 2024-12-05 00:00:00 | 1279.97 |
# | 213.209.12.210 | 2023-06-27 00:00:00 | 5506.58 |
# Do something with the anonymized DataFrame
# ...
# When you want to restore:
original_df = pd_adapter.deanonymize(df_safe)
# | ip | joined_at | revenue |
# |:------------|:--------------------|----------:|
# | 192.168.1.1 | 2023-01-01 00:00:00 | 1234.56 |
# | 10.0.0.1 | 2023-02-01 00:00:00 | 7890.12 |
🧩 Extending with Custom Anonymizers
Want to anonymize new types of data? Super easy:
1️⃣ Create your Custom Anonymizers
import random
def anonymize_color(_): # It is crucial for the anonymizer to accept a single argument.
return random.choice(['red', 'green', 'blue'])
def anonymize_red_channel(original_hex):
hex_color = original_hex.lstrip('#')
green = hex_color[2:4]
blue = hex_color[4:6]
random_red = random.randint(0, 255)
return "#{:02X}{}{}".format(random_red, green, blue)
2️⃣ Register the Anonymizers
from camouflage import register_anonymizer
register_anonymizer('color', anonymize_color)
register_anonymizer('red_channel', anonymize_red_channel)
3️⃣ Use the Custom Anonymizers
from camouflage import anonymize
original_value = "cyan"
anonymized_value = anonymize("color", original_value)
original_hex = "#00FF00"
anonymized_hex = anonymize("red_channel", original_hex)
4️⃣ Or Use the Custom Anonymizers for Pandas
import pandas as pd
from camouflage import PandasAdapter
df = pd.DataFrame({
"color": ["cyan", "magenta", "yellow"],
"hex": ["#FF0000", "#00FF00", "#0000FF"],
})
# | color | hex |
# |:--------|:--------|
# | cyan | #FF0000 |
# | magenta | #00FF00 |
# | yellow | #0000FF |
mapper = {
"color": "color",
"hex": "red_channel",
}
pd_adapter = PandasAdapter(mapper)
df_safe = pd_adapter.anonymize(df)
# | color | hex |
# |:--------|:--------|
# | green | #B90000 |
# | blue | #96FF00 |
# | red | #FD00FF |
✅ That's it — now you can anonymize columns as "color" or "red_channel" either one-time or in adapters!
✅ Quality You Can Trust
- ✅ 100% code coverage (Pytest + Coverage)
- ✅ PEP8 compliant, linted
- ✅ Fast anonymization for datasets of 100,000+ rows
- ✅ Extensible plugin system
- ✅ Tested and battle-ready
🧪 Testing
Run tests on your setup with:
pip install pytest
pytest
📜 License
MIT License — do whatever you want, but be cool. ✌️
👨💻 Made with ❤️ by Developers, for Developers.
Camouflage is built to empower privacy-first applications without slowing you down.
🔗 Links
Source Code: https://github.com/NazarNintendo/camouflage
PyPI: https://pypi.org/project/camouflage/
Project details
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 camouflage-1.0.3.tar.gz.
File metadata
- Download URL: camouflage-1.0.3.tar.gz
- Upload date:
- Size: 14.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25ea5215b75c7674828e415f7c6ba54171c79977221fd0eca7a66399415ebc92
|
|
| MD5 |
f7c2c7c78379d258544f60b4353bed45
|
|
| BLAKE2b-256 |
6b8fd65c004c30c6dabaad75a8d876ec795bdf6d75fc08cee8d38f74ae5d2e7c
|
File details
Details for the file camouflage-1.0.3-py3-none-any.whl.
File metadata
- Download URL: camouflage-1.0.3-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3042deafa140fc2197f9f454723c86aff90d8a20fae005a8abdf386949bf290c
|
|
| MD5 |
6f8e7e04445b171a4af594ceccf60793
|
|
| BLAKE2b-256 |
4c79f14609457698146d43a7417c1d7249ae17fa734193b387ba24d1cfc92de2
|