Скрипти для узгодженого маскування конфіденційних даних у військових документах з можливістю точного відновлення.
data_masking.py— маскування даних з instance trackingunmask_data.py— розмаскування з точним відновленнямdiagnose_mapping.py— діагностика, порівняння маппінгів та верифікація відновлення
rank_data.py— звання ЗСУ (армія, флот, медична/юридична служба) з відмінками
| Модуль | Опис |
|---|---|
config.py |
YAML + ENV + CLI конфігурація з пріоритетами (CLI > ENV > YAML > Default) |
security.py |
AES-256-GCM шифрування/дешифрування mapping файлів |
masking_logger.py |
Структуроване логування (JSON + кольоровий console output) |
selective.py |
--only / --exclude фільтри для вибіркового маскування |
re_mask.py |
Ланцюгове перемаскування (multi-pass) з відстеженням ланцюгів |
tools.py |
Атомарні функції маскування для програмного використання (API) |
password_generator.py |
Генератор паролів (ASCII, кирилиця, кастомні символи) |
config_example.py— приклад конфігурації (dataclasses, без зовнішніх залежностей)
python data_masking.py input.txtРезультат:
output/masked_input_YYYYMMDD_HHMMSS.txt— замаскований текстoutput/mapping_input_YYYYMMDD_HHMMSS.json— mapping для unmaskoutput/report_input_YYYYMMDD_HHMMSS.txt— звіт
Автоматичний режим:
python unmask_data.py masked_file.txtРучний режим:
python unmask_data.py masked_file.txt -m mapping_file.jsonЗ шифрованим mapping файлом (v2.3.0+):
python unmask_data.py masked_file.txt --map mapping.enc --password mypasswordЗ конфігураційним файлом (v2.3.0+):
python unmask_data.py -c config.yamlРезультат:
result/unmasked_file_YYYYMMDD_HHMMSS.txt— відновлений текст
python diagnose_mapping.py mapping1.json mapping2.json # порівняння маппінгів
python diagnose_mapping.py --verify input.txt recovered.txt # верифікація відновлення- ПІБ — з урахуванням відмінків та роду
- По батькові — маскуються зі збереженням гендеру та регістру
- ІПН — 10 цифр
- ID-паспорти — 9 цифр (перші 3 + остання фіксовані, середні 5 — випадкові)
- Паспорти — АА123456, АА №123456
- Військові квитки — МТ123456, мт-123456, мт №123456
- Звання — всі відмінки, чоловічі/жіночі форми, з "у відставці"/"в запасі"
- Бригади — "123 окрема механізована бригада"
- Військові частини — "в/ч А1234"
- Номери наказів — "наказ №123 від 01.01.2025"
- БР номери — 75/25/3400/Р, 818/856, 86319/06/1689/Р, 566
- Дати — DD.MM.YYYY (±30 днів)
- Абревіатури — ЗСУ, МОУ, ВСУ, ДПСУ, НГУ, ДСНС, СБУ, ГУР, ТЦК, СП
Кожне входження відстежується окремо:
Вхід: "Іванов зустрів Петрова, потім Іванов пішов"
Маска: "Сидоров зустрів Коваля, потім Сидоров пішов"
↑ instance 1 ↑ instance 2
Unmask правильно відновить обидва входження
Відмінки звань:
"молодшому сержанту" → "старшому солдату" (давальний)
"молодшого сержанта" → "старшого солдата" (родовий)
"молодшим сержантом" → "старшим солдатом" (орудний)
Відмінки імен:
"Іванову Петру" → "Сидорову Андрію" (давальний)
"Іванова Петра" → "Сидорова Андрія" (родовий)
"Івановим Петром" → "Сидоровим Андрієм" (орудний)
Рід:
"молодшою сержанткою" → "старшою солдаткою" (жіночий)
"капітанці" → "майорці" (жіночий)
Додаткові слова:
"Солдату у відставці" → "Рекруту у відставці" (давальний зберігається!)
"Сержанту в запасі" → "Старшому солдату в запасі" (давальний зберігається!)
"Капітану на пенсії" → "Майору на пенсії" (давальний зберігається!)
"ІВАНОВ" → "ПЕТРЕНКО"
"Іванов" → "Петренко"
"іванов" → "петренко"
Система генерує однакові mapping файли при обробці однакових вхідних даних:
# Запуск 1:
"Іванов" → blake2b hash → seed → "Петренко"
# Запуск 2 (той самий файл):
"Іванов" → blake2b hash → seed → "Петренко" # Той самий результат!Переваги:
- Один оригінал = одна маска (завжди)
- Результат передбачуваний та відтворюваний
- Можна перезапустити на тому самому файлі — отримаєте той самий mapping
- Unmask працює консистентно
Технічні деталі:
- Використовується
hashlib.blake2b()для генерації seed - Faker та random ініціалізуються з детермінованим seed
Mapping файли можна шифрувати AES-256-GCM:
# Маскування з шифруванням
python data_masking.py input.txt --encrypt --password mypassword
# Результат: mapping_*.json.enc
# Розмаскування з шифрованим mapping
python unmask_data.py masked.txt --map mapping.enc --password mypasswordПріоритет: CLI > ENV > config.yaml > Default
# Використання YAML конфігурації
python data_masking.py input.txt -c config.yaml
# Генерація прикладу конфігурації — див. config_example.py# Маскувати тільки ІПН та паспорти
python data_masking.py input.txt --only ipn,passport
# Маскувати все крім дат
python data_masking.py input.txt --exclude datesДля повторного маскування вже замаскованих файлів зі збереженням повного ланцюга маппінгів:
from modules.re_mask import ReMasker, MappingChain
chain = MappingChain()
remasker = ReMasker(chain=chain, mask_function=my_mask_fn)Атомарні функції для інтеграції в зовнішні додатки:
from modules.tools import mask_ipn_direct, mask_rank_direct, mask_pib_force
result = mask_ipn_direct("1234567890", masking_dict, instance_counters)from modules.password_generator import generate_password
# Стандартний пароль (24 символи)
pwd = generate_password()
# З кирилицею
pwd = generate_password(length=32, include_cyrillic_lower=True)
# CLI
# python -m modules.password_generator --length 32 --cyrillicСтруктуроване логування з JSON та кольоровим console output:
from modules.masking_logger import MaskingLogger, setup_logging
logger = MaskingLogger("masking")
setup_logging(level="DEBUG", json_output=True)В data_masking.py можна увімкнути/вимкнути категорії:
# Алгоритм хешування для детермінованої генерації
HASH_ALGORITHM = 'blake2b' # blake2b (рекомендовано), md5 (швидкий), sha256 (популярний)
MASK_IPN = True # ІПН (10 цифр)
MASK_PASSPORT = True # Паспорти (АА123456) та ID-паспорти (9 цифр)
MASK_MILITARY_ID = True # Військові квитки
MASK_NAMES = True # Імена та прізвища
MASK_RANKS = True # Звання
MASK_BRIGADES = True # Бригади
MASK_MILITARY_UNITS = True # Військові частини
MASK_ORDER_NUMBERS = True # Номери наказів
MASK_BR_NUMBERS = True # БР номери
MASK_DATES = True # ДатиПорівняння алгоритмів хешування:
| Алгоритм | Швидкість | Безпека | Використання |
|---|---|---|---|
| blake2b | ⚡⚡⚡⚡⚡ | ✅ Високо | Рекомендовано (за замовчуванням) |
| md5 | ⚡⚡⚡⚡⚡ | Найшвидший, достатній для seed | |
| sha1 | ⚡⚡⚡⚡ | Швидкий, краще ніж md5 | |
| sha256 | ⚡⚡⚡ | ✅ Високо | Популярний, Bitcoin |
| sha512 | ⚡⚡ | ✅ Максимально | Найповільніший |
Вхід:
Молодшому сержанту у відставці СИЧУ Роману Сергійовичу (Житомирський ОТЦКСП),
звільненому 31.05.2025, який є особою з інвалідністю III групи.
Результат:
Старшому солдату у відставці БОЙКО Павлу Сергійовичу (Житомирський ОТЦКСП),
звільненому 15.06.2025, який є особою з інвалідністю III групи.
Вхід:
Капітанці медичної служби Коваленко Марії Іванівні, ІПН 1234567890,
ID-паспорт 123456789, видано наказом №75/25/3400/Р від 26.06.2025.
Результат:
Майорці медичної служби Петренко Оксані Іванівні, ІПН 9876543210,
ID-паспорт 123947568, видано наказом №59/87/4249/Р від 10.07.2025.
Вхід:
Командир 72 окремої механізованої бригади
полковник Сергій ЗАПОРОЖЕЦЬ
Результат:
Командир 85 окремої механізованої бригади
підполковник Павло ЗАВОДСЬКИЙ
Вхід:
Капітан ЗСУ Іванов Петро Миколайович, військовий квиток МТ123456,
проходив службу у МОУ, нагороджений СБУ за заслуги перед ГУР.
Результат:
Майор ЗСУ Сидоров Андрій Миколайович, військовий квиток МТ654321,
проходив службу у МОУ, нагороджений СБУ за заслуги перед ГУР.
Вхід:
Сержанту БОНДАРЕНКО Олегу та молодшому сержанту КОВАЛЕНКО Андрію,
а також рядовому ШЕВЧЕНКО Петру видати по 100 грн.
Результат:
Старшому солдату ЗАВОДСЬКИЙ Павлу та молодшому солдату БОЙКО Станіславу,
а також солдату ПЕТРЕНКО Андрію видати по 100 грн.
{
"version": "2.0",
"mappings": {
"rank": {
"молодшому сержанту": {
"masked_as": "старшому солдату",
"instances": [1, 3]
}
},
"surname": {
"іванов": {
"masked_as": "петренко",
"instances": [1, 2]
}
},
"passport_id": {
"123456789": {
"masked_as": "123947568",
"instances": [1]
}
}
},
"instance_tracking": {
"старшому солдату": 3,
"петренко": 2,
"123947568": 1
}
}Рядові: рекрут, рядовий, солдат, старший солдат
Сержанти: молодший сержант, сержант, старший сержант, головний сержант, штаб-сержант, майстер-сержант, старший майстер-сержант, головний майстер-сержант
Офіцери: молодший лейтенант, лейтенант, старший лейтенант, капітан, майор, підполковник, полковник
Генерали: бригадний генерал, генерал-майор, генерал-лейтенант, генерал
Матроси: матрос, старший матрос
Старшини: головний корабельний старшина, головний старшина, старшина 1/2 статті
Офіцери: молодший лейтенант, лейтенант, старший лейтенант, капітан-лейтенант
Капітани: капітан 3/2/1 рангу
Адмірали: контр-адмірал, віце-адмірал, адмірал
Медична: капітан/майор/підполковник/полковник медичної служби
Юридична: капітан/майор/підполковник/полковник юстиції
- Називний (nominative): хто? що? — "солдат"
- Родовий (genitive): кого? чого? — "солдата"
- Давальний (dative): кому? чому? — "солдату"
- Орудний (instrumental): ким? чим? — "солдатом"
- Зберігайте mapping файли в захищеному місці
- НЕ передавайте mapping разом з замаскованими даними
- Видаляйте mapping після завершення роботи
- Використовуйте різні mapping для різних документів
- Використовуйте шифрування mapping файлів (v2.3.0+):
--encrypt --password - Unmask можливий ТІЛЬКИ при наявності mapping файлу
- Перевірте версію mapping (має бути v2.0)
- Використайте актуальні версії скриптів
- Переконайтесь що
MASK_RANKS = True - Оновіть до актуальної версії
- Оновіть до v2.1.16+ з whitelist підтримкою
- Переконайтесь що
MASK_PASSPORT = True - ID-паспорти = 9 цифр (не 10 як ІПН)
# Додати як submodule
git submodule add https://github.com/click0/data-masking.git
# Оновити submodule
git submodule update --remote data-masking
# Використання в проекті
cd data-masking
python data_masking.py ../documents/input.txt# Клонувати окремо
git clone https://github.com/click0/data-masking.git
cd data-masking
python data_masking.py input.txtBSD 3-Clause "New" or "Revised" License
Vladyslav V. Prodan
- GitHub: @click0
- Phone: +38(099)6053340
v2.3.2 (квітень 2026)
Детальну історію змін див. у CHANGELOG.md