Ошибка шифрования останавливает сервис раньше, чем вы успеваете открыть логи: расшифровка не проходит, HTTPS-сессия рвётся, бэкап не читается. Почти все такие сбои укладываются в четыре причины: неверный или отозванный ключ, повреждение зашифрованных данных, несовместимость версий ПО и ошибки конфигурации TLS.
Два сообщения закрывают большую часть инцидентов. bad decrypt означает, что ключ, пароль или алгоритм не совпали с теми, которыми данные шифровали. certificate verify failed говорит о провале проверки сертификата: истёк срок, сертификат отозван, в цепочке нет промежуточного звена или корневой сертификат отсутствует в доверенных.
Рабочий порядок действий: собрать логи, проверить сертификат и ключ, прогнать тестовый handshake, сверить версии библиотек. Ниже разобраны причины с примерами сообщений, готовые команды для Linux и Windows, сценарии исправления и чек-лист, который не даёт потерять данные по ходу разбирательства.
Почему возникают ошибки шифрования: основные причины
Неверный или отозванный ключ
Сертификат выглядит рабочим: файл на месте, срок действия не истёк. При этом он может быть отозван, и тогда handshake падает с certificate verify failed, если клиент не обновил локальную копию списка отозванных сертификатов (CRL).
В системах с ГОСТ-шифрованием проверка по CRL обязательна. В «Континент TLS VPN» аутентификация выполняется по сертификатам открытых ключей x.509v3 (ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2012), а сами сертификаты выпускает внешний удостоверяющий центр; сервис проверяет их по спискам отозванных сертификатов. Отзыв в УЦ без обновления CRL на стороне сервиса даёт ровно тот же симптом, что и просроченный сертификат.
Проверка на Linux:
openssl x509 -noout -dates -subject -issuer -in cert.pem openssl x509 -noout -serial -in cert.pem openssl crl -in crl.pem -noout -text | head -n 20
На Windows те же данные достаёт certutil. Ключ -urlfetch заставляет утилиту реально сходить за CRL и OCSP, а не доверять локальному кэшу:
certutil -verify -urlfetch cert.cer certutil -store My certutil -dump crl.pem
Серийный номер из вывода команды с ключом -serial сравните со списком в CRL. Совпадение означает отзыв, и сертификат нужно перевыпускать, а не «лечить» настройками сервера.
Повреждение зашифрованных данных
Обрыв передачи, сбойный сектор или неполная запись меняют шифротекст, и расшифровка проваливается с bad decrypt или decryption failed or bad record mac. Блочный шифр проверяет MAC и не прощает искажений: одного изменённого байта достаточно, чтобы операция завершилась ошибкой целиком.
openssl enc -d -aes-256-cbc -pbkdf2 -in data.enc -out data.txt # bad decrypt # error:1C800064:Provider routines:ossl_cipher_unpadblock:bad decrypt
Три причины повреждения встречаются чаще остальных: файл скачан не полностью, размер шифротекста не кратен 16 байтам, передача оборвалась на середине. Размер проверяется одной командой:
stat -c %s data.enc Get-FileHash -Algorithm SHA256 .\data.enc
Целостность подтверждают хэшем: сверяют контрольную сумму исходного файла с суммой после расшифровки, а для подписанных данных проверяют саму подпись.
sha256sum data.txt openssl dgst -sha256 -verify pub.pem -signature data.sig data.enc
В ГОСТ-системах для контроля целостности используют хэш-функции ГОСТ Р 34.11-94 и ГОСТ Р 34.11-2012, а подпись проверяют по ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2012. Расхождение хэшей означает повреждение, и восстанавливать данные нужно из резервной копии: расшифровать испорченный блок без исходного файла нельзя.
Несовместимость версий ПО
Сервер принимает TLS 1.0, клиент требует TLS 1.2 и выше, и соединение падает с unsupported protocol или unknown protocol. Вторая частая пара: файл зашифрован в OpenSSL 1.0.x без ключа -pbkdf2, а расшифровывают его в OpenSSL 3.0, где вывод ключа по умолчанию другой.
Ветки 1.1.1 и 3.0 отличаются наборами шифров и провайдерами: устаревшие алгоритмы в 3.0 вынесены в отдельный провайдер и без него недоступны. В ГОСТ-среде КриптоПро CSP 4.0 и 5.0 поддерживают разные наборы алгоритмов, поэтому клиент и сервер обязаны работать на согласованных версиях.
openssl version -a openssl ciphers -v 'HIGH:!aNULL:!MD5' openssl s_client -connect example.com:443 -tls1
Первая команда показывает сборку и дату выпуска, вторая выводит доступные наборы шифров, третья проверяет handshake на конкретной версии протокола и падает с unsupported protocol, если сервер её не принимает. «Континент TLS VPN» поддерживает протоколы TLS v.1 и TLS v.2, поэтому клиент с одной лишь поддержкой SSLv3 к нему не подключится.
Ошибки конфигурации TLS
Опечатка в пути к сертификату, отсутствие промежуточного сертификата в файле, ключ в формате PKCS#1 вместо PKCS#8, закрытый ключ с правами, недоступными процессу. Симптомы: unable to load certificate, key values mismatch, а на стороне клиента всё тот же certificate verify failed.
openssl s_client -connect example.com:443 -servername example.com -showcerts nginx -t apachectl configtest
В выводе s_client смотрите строку Verify return code. Значение 0 (ok) означает успешную проверку цепочки, любое другое указывает на проблему с промежуточным или корневым сертификатом. Проверка конфигурации Nginx и Apache ловит ошибки путей до перезапуска сервиса, поэтому выполнять её стоит первым делом.
В «Континент TLS VPN» ошибки конфигурации часто лежат не в TLS, а в правилах фильтрации и трансляции адресов запросов к веб-серверам корпоративной сети: неверное правило даёт 403 или 502 без ошибок handshake в логе. Проверяйте оба слоя сразу.
Готовая инструкция по настройке HTTPS с полной цепочкой и современными протоколами собрана в материале ручная установка SSL-сертификата на Nginx и Apache.
| Симптом | Вероятная причина |
|---|---|
| bad decrypt | Неверный пароль, ключ или алгоритм; повреждённый шифротекст |
| decryption failed or bad record mac | Искажение данных: обрыв канала, сбойный сектор, неполная запись |
| certificate verify failed | Истёк срок, отзыв по CRL, неполная цепочка, корневой сертификат не в доверенных |
| unknown protocol / unsupported protocol | Версии TLS у клиента и сервера не пересекаются |
| unable to load certificate | Неверный путь, права доступа или формат файла |
| wrong version number | Клиент идёт по TLS на порт с открытым текстом |
| key values mismatch | Ключ не соответствует сертификату |
Диагностика ошибок шифрования: пошаговый подход
Порядок разбора: логи, затем сертификаты и ключи, затем тестовое соединение, затем версии ПО. Так вы отсекаете три причины из четырёх за несколько минут и не трогаете рабочие конфиги вслепую.
Сбор и анализ логов
journalctl -xe | grep -iE 'ssl|tls|decrypt|handshake' journalctl -u nginx --since "-30 min" tail -n 200 /var/log/nginx/error.log
Строка SSL_CTX_use_PrivateKey_file с пометкой bad decrypt означает неверный пароль к закрытому ключу. Сообщение no such file or directory в том же контексте указывает на путь, который процесс открыть не смог.
Windows пишет ошибки TLS в системный журнал через провайдер Schannel. Событие 36871 связано с ошибкой создания защищённого канала, 36874 и 36888 с отклонёнными протоколами и наборами шифров:
Get-WinEvent -LogName System -MaxEvents 300 |
Where-Object { $_.ProviderName -eq 'Schannel' } |
Format-List TimeCreated, Id, Message
В «Континент TLS VPN» на сервере ведётся журналирование событий информационной безопасности, и все события можно пересылать по syslog на отдельный сервер для разбора в SIEM. При инциденте с ГОСТ-шифрованием этот журнал смотрят первым: в нём видно и отказ аутентификации по сертификату, и отказ в трансляции адресов.
Проверка сертификатов и ключей
openssl x509 -in cert.pem -text -noout openssl rsa -in key.pem -check -noout openssl verify -CAfile ca.pem -untrusted chain.pem cert.pem openssl x509 -noout -modulus -in cert.pem | openssl md5 openssl rsa -noout -modulus -in key.pem | openssl md5
Последние две команды выдают одинаковый отпечаток, если ключ и сертификат образуют пару. Разные значения означают key values mismatch: сертификат выпущен под другой закрытый ключ. Проверка отзыва отдельно, по локальной копии CRL:
openssl crl -in crl.pem -noout -text
В выводе видны серийные номера отозванных сертификатов и дата следующего обновления списка. Если дата в прошлом, копия CRL устарела, и клиент может пропустить отзыв. На Windows те же шаги выполняет certutil:
certutil -verify cert.cer certutil -verifystore My certutil -dump chain.pem
Тестирование TLS-соединения
openssl s_client -connect example.com:443 -servername example.com -showcerts -tls1_2 curl -v https://example.com 2>&1 | grep -E 'SSL|TLS|subject|issuer'
В выводе важны три поля: Protocol, Cipher и Verify return code. Код 0 означает успешную проверку, 20 указывает на отсутствующий корневой сертификат, 10 на истёкший срок. Если процесс не находит файл ключа, strace показывает, какой именно путь открывался:
strace -f -e trace=openat nginx -t 2>&1 | grep -i pem
Для ГОСТ-алгоритмов берите сборку OpenSSL с ГОСТ-движком или консольные утилиты КриптоПро: стандартный s_client не умеет работать с ГОСТ 28147-89.
Когда ошибки шифрования идут рука об руку с падением туннеля, помогает разбор диагностика и устранение неисправностей VPN с готовыми командами для сервера и клиента.
Устранение ошибок шифрования: конкретные сценарии
Исправление ошибки 'bad decrypt'
- Сверьте ключ и алгоритм. Для OpenSSL это флаги -aes-256-cbc, -pbkdf2 и -md sha256: их значения должны совпадать с теми, что применялись при шифровании.
- Убедитесь, что пароль читается корректно. Файл с паролем не должен содержать лишнего перевода строки, иначе последний байт попадёт в ключ.
- Проверьте целостность зашифрованного файла по хэшу и по кратности размера блоку в 16 байт.
- Если файл повреждён, восстанавливайте его из резервной копии: расшифровка испорченного шифротекста невозможна.
- Для ГОСТ-данных используйте КриптоПро CSP или OpenSSL с ГОСТ-движком, AES к ним неприменим.
openssl enc -d -aes-256-cbc -pbkdf2 -md sha256 -in data.enc -out data.txt -pass file:key.txt
Отдельная ловушка: файлы, созданные до OpenSSL 1.1.1, шифровали без -pbkdf2, и вывод ключа шёл через EVP_BytesToKey с MD5. Расшифровка такого файла в OpenSSL 3.0 с ключом -pbkdf2 заканчивается bad decrypt, хотя пароль верный. Уберите флаг или добавьте -md md5, и данные прочитаются.
Исправление ошибки 'certificate verify failed'
- Проверьте срок действия: openssl x509 -noout -dates -in cert.pem.
- Проверьте цепочку: openssl verify -CAfile ca.pem -untrusted chain.pem cert.pem.
- Проверьте отзыв: openssl crl -in crl.pem -noout -text.
- Обновите корневые сертификаты в системном хранилище.
- Для самоподписанного сертификата добавьте его в доверенные либо выпустите новый от внутреннего удостоверяющего центра.
Частая причина на сервере: в файле сертификата лежит только листовой сертификат без промежуточного. Цепочку собирают в правильном порядке, от листового к корневому:
cat server.crt intermediate.crt root.crt > fullchain.pem
Конфигурация Nginx со собранной цепочкой выглядит так:
ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3;
На Windows корневые сертификаты обновляют из хранилища обновлений, а затем добавляют в доверенные:
certutil -generateSSTFromWU roots.sst certutil -addstore -f Root roots.sst
В «Континент TLS VPN» просроченный или отозванный сертификат пользователя лечится перевыпуском во внешнем удостоверяющем центре и обновлением CRL на сервере. Правки на клиенте проблему не снимут.
Полный набор причин и решений по SSL/TLS собран в статье исправление ошибок SSL/TLS сертификата: браузер, сервер и API в одном разборе.
Предотвращение потери данных при ошибках шифрования
Резервную копию делают до первого запуска диагностики, а не после. Данные и ключи копируют раздельно: архив, где рядом лежат шифротекст и ключ, обесценивает саму идею шифрования.
tar -czf keys_backup_$(date +%F).tar.gz /etc/ssl/private /etc/letsencrypt cryptsetup luksHeaderBackup /dev/sda2 --header-backup-file luks-header-$(date +%F).img
Копия заголовка LUKS важна не меньше копии данных: при повреждении заголовка том не открывается, даже когда ключевая фраза известна. На Windows сертификат с закрытым ключом экспортируют через certmgr.msc в файл PFX под сильным паролем и держат его на офлайн-носителе, а не на том же сервере.
Восстановление проверяют на изолированном стенде, а не на рабочем узле. Развернуть отдельный VDS под такие тесты дешевле, чем разбираться с последствиями неудачного эксперимента на продакшене: Timeweb Cloud даёт виртуальные серверы и хранилище, которые поднимаются за минуты и удаляются сразу после проверки.
В ГОСТ-системах ключи и сертификаты экспортируют из КриптоПро CSP отдельными контейнерами и хранят с той же дисциплиной. В «Континент TLS VPN» копия конфигурации и ключей входит в обязательные процедуры обслуживания.
Схемы шифрования на хранении и при передаче, управление ключами и ротация разобраны в статье шифрование данных при передаче и хранении.
Если данные повреждены не сбоем, а атакой шифровальщика, порядок другой: сначала изоляция, потом анализ. Готовый алгоритм собран в практическом плане действий при ransomware-атаке.
Чек-лист для Linux и Windows
Linux:
- Логи: journalctl -xe | grep -i ssl, /var/log/nginx/error.log, /var/log/syslog.
- Сертификат: openssl x509 -noout -dates -subject -issuer -in cert.pem.
- Цепочка: openssl verify -CAfile ca.pem -untrusted chain.pem cert.pem.
- Ключ: openssl rsa -in key.pem -check -noout и сверка modulus с сертификатом.
- Соединение: openssl s_client -connect host:443 -showcerts.
- Версии: openssl version -a, openssl ciphers -v.
- Резервная копия ключей и данных до любых изменений.
Windows:
- Event Viewer, источник Schannel, события 36871, 36874, 36888.
- certutil -verify -urlfetch cert.cer.
- certutil -store My и certutil -store Root для проверки хранилищ.
- Test-NetConnection host -Port 443 для проверки доступности порта.
- Версии Schannel в ветке реестра HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols.
- Экспорт сертификата с закрытым ключом в PFX.
- Обновление корневых: certutil -generateSSTFromWU.
Для ГОСТ-систем добавьте пункты: проверить актуальность CRL, посмотреть журнал событий информационной безопасности и его выгрузку по syslog, убедиться, что клиент и сервер согласовали TLS v.1 или TLS v.2, сверить версии КриптоПро CSP.
Как избежать повторных ошибок шифрования
Проверку срока действия сертификатов ставят в мониторинг: Zabbix, Prometheus с blackbox_exporter или обычный скрипт с openssl x509 и отправкой письма. Оповещение за 30 дней до истечения закрывает самую частую причину внезапных сбоев.
Обновление CRL настраивают по расписанию с запасом по времени: если копия списка отстаёт, отозванный сертификат продолжает работать, и это уже вопрос безопасности, а не доступности. Для выпущенных сертификатов полезно включать OCSP stapling.
Версии ПО на всех узлах приводят к единому виду: одна ветка OpenSSL, один набор шифров, согласованные версии КриптоПро CSP и «Континент TLS VPN». Разъезд версий между тестовым и рабочим контуром даёт ошибки, которые невозможно воспроизвести на стенде.
Плановые проверки конфигураций TLS проводят перед каждым обновлением сервиса, а регламент резервного копирования ключей фиксируют письменно, с указанием ответственного и места хранения копий. Интеграция журналов с SIEM помогает заметить аномалии: всплеск отказов аутентификации по сертификатам виден в системе раньше, чем пользователи начнут писать в поддержку.
Начните с одного действия: добавьте в мониторинг проверку срока действия каждого сертификата и оповещение за 30 дней до истечения. Этот шаг снимает самую частую причину ошибок шифрования в продакшене и не требует изменений в рабочей конфигурации сервисов.