Аудитория: ИБ-служба, DPO, аттестатор, суперадминистратор. Закрывает вопросы: №1 («это шифрование? нужна лицензия ФСТЭК?»), частично №7. Сценарий: S1 — аттестатор спрашивает, попадает ли продукт под регулирование СКЗИ.
Нет, «Лицензиар» не является средством криптографической защиты информации (СКЗИ) и не требует лицензии ФСТЭК/ФСБ на криптографию. В продукте применяется отечественный алгоритм ГОСТ Р 34.11-2012 «Стрибог», но исключительно как хеш-функция для обезличивания идентификаторов — не для шифрования, не для электронной подписи и не для имитозащиты.
Обезличивание (псевдонимизация) — это не криптографическая защита канала или данных, а преобразование персональных данных в форму, по которой нельзя определить субъекта без дополнительной информации, хранимой отдельно (ст. 3 п. 9 ФЗ-152). Регулирование СКЗИ (Постановление Правительства №313, приказы ФСБ) к такому применению не относится.
Это первый блокирующий вопрос при внедрении в госорганизации. Если безопасник заказчика решит, что продукт — СКЗИ, он потребует сертификат ФСБ, формуляр, журнал учёта СКЗИ и аттестованное рабочее место. Ничего этого не нужно, и ниже — обоснование, которое можно показать аттестатору дословно.
Обезличивание выполняет одна функция — anonymize(tenant_id, tabel_no) (полный исходник приведён ниже, в разделе «Что показать аттестатору»):
вход: ANON_SALT | tenant_id | табельный_номер
│
▼ ГОСТ Р 34.11-2012 «streebog256» (gosthash.new)
выход: hex(64) — 256-битный непрозрачный идентификатор- Это одностороннее преобразование: из hex(64) нельзя восстановить табельный номер.
У шифрования есть обратная операция (расшифрование) — здесь её нет принципиально.
- Ключа шифрования нет. Есть «соль» (
ANON_SALT) — она домешивается ко входу, чтобы
одинаковые табельные в разных инсталляциях давали разные id (защита от радужных таблиц). Соль — не криптографический ключ: она не позволяет «расшифровать», только меняет пространство значений хеша.
- Соль приходит только из переменной окружения, не хранится в БД и не попадает в логи.
Если соль не задана — обезличивание останавливается (SaltMissingError, fail-closed): система предпочитает не работать, чем записать сырой идентификатор.
| Признак СКЗИ | Есть в «Лицензиаре»? |
|---|---|
| Шифрование/расшифрование данных | ❌ Нет обратной операции |
| Электронная подпись (ГОСТ Р 34.10) | ❌ Не реализуется |
| Имитозащита / выработка ключей | ❌ Нет |
| Защита канала связи (VPN/TLS-крипто) | ❌ Транспорт — обычный HTTPS/nginx, без отеч. крипто |
| Хеширование для обезличивания ПДн | ✅ Только это |
Хеш-функция ГОСТ Р 34.11-2012 сама по себе — стандартизованный алгоритм, а не СКЗИ. СКЗИ — это изделие (программа/устройство), реализующее криптографические функции защиты (шифрование, ЭП, имитозащита). Применение хеша для псевдонимизации к этому классу не относится.
Это гард-рейл проекта (BUILD_SPEC р.5): западные алгоритмы (SHA-256/SHA-1/MD5) в продукте не используются вообще. Для российской госорганизации обезличивание отечественным алгоритмом — аргумент в пользу импортонезависимости, а не требование закона. То есть мы взяли отечественный алгоритм там, где закон вообще не обязывает применять криптографию, — это усиливает позицию при аттестации, а не создаёт обязанность по линии СКЗИ.
Реализация — библиотека gostcrypto (лицензия MIT), а не pygost (GPL-3): выбор продиктован вторым гард-рейлом «ноль копилефта» (см. 05 — Автономность и стек). Корректность сверена с официальным тест-вектором ГОСТ (приёмочный тест приведён ниже).
Пароли операторов хешируются Argon2id (библиотека argon2-cffi, MIT) — это парольный хеш, а не шифрование и не СКЗИ. Важно: Argon2id и Стрибог разведены и не импортируют друг друга — обезличивание ПДн и аутентификация решают разные задачи и не смешиваются.
Все доказательства приведены прямо здесь — раскройте нужный блок.
- Исходник целиком (≈50 строк). Видно, что есть только
digest()— нет
encrypt/decrypt/sign; ключа шифрования нет, есть лишь соль из окружения.
▸Исходник модуля обезличивания (anonymize.py)
"""
Обезличивание идентификаторов по ГОСТ Р 34.11-2012 («Стрибог», 256 бит).
КОНТРАКТНЫЙ ГЕЙТ: западные алгоритмы хеширования (SHA-256/MD5/SHA-1) НЕ используются.
Обезличивание выполняется отечественным «Стрибог».
Соль (ANON_SALT) приходит ТОЛЬКО из переменной окружения — она НЕ хранится в БД и НЕ
попадает в логи. Результат — непрозрачный hex(64) (256 бит), стабильный для одного и того
же (соль, табельный номер): связь id↔человек существует лишь в Identity Vault.
Система НЕ является СКЗИ: Стрибог здесь применяется как функция обезличивания (хеш-функция
по ГОСТ), а не для шифрования/ЭЦП.
"""
import os
# gostcrypto (MIT) — отечественная реализация ГОСТ Р 34.11-2012 «Стрибог».
# Выбрана вместо pygost (GPL-3) ради гардрейла «ноль копилефта».
from gostcrypto import gosthash
class SaltMissingError(RuntimeError):
"""ANON_SALT не задана в окружении — обезличивание невозможно (fail-closed)."""
def _salt() -> bytes:
salt = os.environ.get("ANON_SALT")
if not salt:
raise SaltMissingError(
"ANON_SALT не задана в env. Обезличивание остановлено (соль не хранится в БД)."
)
return salt.encode("utf-8")
def anonymize(tenant_id: str, tabel_no: str) -> str:
"""Вход: арендатор + табельный номер. Выход: hex(64) по ГОСТ Р 34.11-2012 (Стрибог-256)."""
payload = _salt() + b"|" + tenant_id.encode("utf-8") + b"|" + tabel_no.encode("utf-8")
# 'streebog256' = ГОСТ Р 34.11-2012 с длиной выхода 256 бит.
h = gosthash.new("streebog256", data=payload)
digest = h.digest() # 32 байта = 256 бит
return digest.hex() # 64 hex-символа
def algorithm_name() -> str:
return "ГОСТ Р 34.11-2012 (Стрибог-256)"В модуле нет ни одной функции шифрования, расшифрования или подписи — только одностороннее хеширование. Это и есть отличие обезличивания от СКЗИ.
- Приёмочный тест-вектор ГОСТ. Проверяет, что выход — корректный hex(64), что он
не совпадает с SHA-256 того же входа (значит, алгоритм действительно отечественный), и что соль реально влияет на результат.
▸Приёмочный тест: Стрибог ≠ SHA-256, влияние соли, изоляция арендаторов
def test_streebog_outputs_hex64_not_sha256():
os.environ["ANON_SALT"] = "test-salt"
out = anonymize("artek", "T-0001")
assert len(out) == 64
assert all(c in "0123456789abcdef" for c in out)
# НЕ совпадает с SHA-256 того же входа — алгоритм действительно отечественный.
sha = hashlib.sha256(b"test-salt|artek|T-0001").hexdigest()
assert out != sha
def test_streebog_salt_changes_result():
os.environ["ANON_SALT"] = "salt-A"
a = anonymize("artek", "T-0001")
os.environ["ANON_SALT"] = "salt-B"
b = anonymize("artek", "T-0001")
assert a != b # соль реально влияет
def test_streebog_tenant_isolated_ids():
os.environ["ANON_SALT"] = "test-salt"
assert anonymize("artek", "T-0001") != anonymize("demo", "T-0001")- Заготовка заключения о совместимости для аттестатора ИСПДн. Готовый пакет фактов и
доказательств (его подписывает аттестатор/орган заказчика, а не вендор).
▸Фрагмент заключения: обезличивание ПДн — ГОСТ, не западные алгоритмы
| Требование | Реализация | Доказательство |
|---|---|---|
| Алгоритм хеширования идентификаторов | ГОСТ Р 34.11-2012 «Стрибог», 256 бит (gostcrypto, MIT) | модуль обезличивания + сверка с офиц. тест-вектором ГОСТ |
| Отсутствие SHA-256 / западных алгоритмов для ПДн | в коде обезличивания западные алгоритмы не используются | тест test_streebog_outputs_hex64_not_sha256 (выход ≠ SHA-256) |
| Соль обезличивания | из переменной окружения ANON_SALT, не хранится в БД и не пишется в журналы | тест влияния соли test_streebog_salt_changes_result |
| Система не является СКЗИ | обезличивание — программно-математическое, не шифрование | в модуле нет encrypt/decrypt/sign |
Полный пакет (совместимость с Astra Linux / Postgres Pro, RLS-изоляция арендаторов, журнал ФЗ-152, состав зависимостей без копилефта) формируется отдельным приложением к договору.
- Формула применения: «хеш-функция по ГОСТ применяется для обезличивания ПДн (ст. 3 п. 9
ФЗ-152), функции СКЗИ (шифрование, ЭП, имитозащита) не реализуются».
- «Раз есть ГОСТ-крипто — значит СКЗИ». Нет: ГОСТ Р 34.11 — хеш-функция; класс СКЗИ
определяется реализуемой функцией защиты, а не происхождением алгоритма.
- «Соль — это же ключ, верните данные». Соль не обращает хеш. Восстановление невозможно
даже зная соль; связь id↔человек берётся не из хеша, а из отдельного сейфа (Identity Vault, см. статью 02), доступного только роли DPO под запись в аудит.
- Не теряйте `ANON_SALT`. Сменили соль — все ранее посчитанные id перестают совпадать с
новыми (тот же человек получит другой hex). Соль — часть «личности» инсталляции; на стенде для воспроизводимости используется ANON_SALT=test-salt, в проде — секрет, заданный один раз.
- Соль не в БД и не в git. Если её туда положить — теряется весь смысл обезличивания.
Связанные статьи: 02 — ПДн и Vault · 05 — Автономность и стек.