Как посчитать имитовставку mac функциями openssl

Продолжая традицию, начатую в статьях 1 и 2 нашего блога, предлагаем обсудить еще одну из атак на протокол TLS. В сегодняшней статье будет рассмотрено, как предпринятые в TLS 1.1 и TLS 1.2 контрмеры, направленные на устранение уязвимости протокола к атакам, основанным на методах Барда-Дэя и Воденея, сами привели к возникновению новых уязвимостей и к появлению новых типов атак.
Для ликвидации уязвимости к атакам, аналогичным атаке Воденея, был принят ряд контрмер, связанных с порядком вычисления имитовставки при некорректном заполнении. В пункте 6.2.3.2 RFC 5246 (описание протокола TLS версии 1.2) присутствует следующая рекомендация: указано, что лучшим методом защиты от временных атак, аналогичных атаке Воденея, является вычисление значения имитовставки даже в случае некорректного заполнения, например, вычисление значения имитовставки по всему полученному после расшифрования фрагменту в предположении отсутствия заполнения.
«For instance, if the pad appears to be incorrect, the implementation might assume a zero-length pad and then compute the MAC. This leaves a small timing channel, since MAC performance depends to some extent on the size of the data fragment, but it is not believed to be large enough to be exploitable, due to the large block size of existing MACs and the small size of the timing signal.»
Таким образом, указано, что предлагаемые меры оставляют временной канал утечки информации, связанный с наличием разницы во времени вычисления имитовставки в случае сообщения с корректным заполнением (время вычисления самого сообщения) и модифицированного сообщения с некорректным заполнением (время вычисления сообщения и соответствующих заполнению байтов). Также сделан вывод, что канал невозможно использовать по причине большого размера блока современных алгоритмов выработки имитовставки. Буквально сказано так: «предполагается, что временной канал недостаточно большой для его использования».
Не странно ли видеть слова «предполагается, что это безопасно» в спецификации криптографического протокола? Так вот, это предположение оказывается неверным.
Атака Аль-Фардана и Патерсона или Число 13 приносит удачу
При наличии низкоинформативного побочного канала возможны два пути его эксплуатации. Первый путь заключается в нахождении относительно реалистичных условий, при которых возможно стабильное долговременное использование данного канала, обеспечивающее достаточный для анализа объём получаемых данных.
Второй путь заключается в построении дополнительных технических и математических механизмов для расширения данного побочного канала.
Успехов на первом пути добились Аль-Фардан (AlFardan) и Патерсон (Paterson) из Лондонского Университета (City University London). Метод Аль-Фардана–Патерсона предполагает модель нарушителя, в которой нарушитель имеет возможность наблюдать и подменять сообщения в канале в точке, близкой к атакуемому клиенту или серверу. Неформально определенное требование «близости» происходит из необходимости работы с крайне слабым побочным каналом по времени.
Опишем построение данного канала утечки и использование этого канала для дешифрования блока Сi (здесь и далее используются обозначения из этой статьи) передаваемого по каналу связи шифртекста С = (С1|С2|С3|. |Cm) = Ek(M1|M2|M3|. |Mm). Будем считать, что для шифрования используется AES (важен не сам алгоритм шифрования, а его длина блока) с длиной блока равной 128 бит, а для выработки кода аутентификации используется HMAC-SHA-1 с длиной блока 160 бит.
Для некоторого случайно выбранного значения Ω сформируем шифртекст C att ( Ω ) = (HDR|IV|C1|C2|Ci‑1⊕ Ω |Ci) , где HDR – заголовок, C0 – произвольный блок. После расшифрования на стороне получателя последний блок P4 будет равен Dk(Ci) ⊕ Ci‑1 ⊕ Ω = Mi. Далее возможны следующие три случая: блок Mi ⊕ Ω в конце содержит корректное заполнение длины 1, длины 2 (или более, с вероятностью в 256 раз меньшей), либо некорректное заполнение.
С учётом указанной выше рекомендации RFC 5246, в случае некорректного заполнения код аутентификации сообщения вычисляется по всему тексту, т.е. до конца блока Mi. По свойствам протокола TLS, в этом случае он вычисляется на 57 или более байт, если заголовок имеет длину 13 байтов (отсюда название атаки «Lucky Thirteen»), а в случае корректного заполнения длины 1 – на 56 байт. В случае же, когда присутствует корректное заполнение длины 2 и более, происходит расчёт кода аутентификации сообщения на 55 или менее байт.
С учетом структуры HMAC-SHA-1, в случае длины аутентифицируемых данных 55 или менее требуется не более 4 вычислений функции сжатия SHA-1, тогда как при длине 56 или более требуется 5 или более вычислений. После этих вычислений происходит возврат ошибки (вероятность появления коллизий при проверке HMAC-SHA-1 пренебрежимо мала), которую наблюдает нарушитель.
Измерение времени до возврата ошибки позволяет использовать побочный канал по времени, связанный с количеством вычислений функции сжатия. В случае быстрого возврата ошибки (4 вычисления функции сжатия) нарушителю известно, что в последних 2 байтах (или более, но вероятность этого меньше в 256 раз) Mi ⊕ Ω содержится корректное заполнение. Зная структуру заполнения и значение Ω, нарушитель однозначно определяет последние два байта Mi. Зная последние два байта Mi, далее возможно тем же способом, модифицируя Ω , восстановить третий с конца байт Mi, и так далее.
Звучит интересно, а что на практике?
Допустим что сервер, клиент и атакующий находятся в одной сети VLAN с пропускной способностью 100 Mbps. Атакующий начинает перехватывать пакеты от клиента к серверу, модифицировать их и отправлять на сервер и собирает статистику по времени получения сообщений TLS alert от сервера. Для повышения скорости атаки сразу после получения ответа от сервера атакующий отсылает клиенту и серверу RST пакет, который приводит к мгновенному закрытию соединения. Для подбора каждого байта в худшем случае нужно L*256 попыток, где L – это количество попыток с одинаковым Ω . Несколько попыток с одинаковым Ω нужно для уменьшения вероятности неправильной трактовки результата. Эксперименты показали что вероятность правильного подбора байта при росте L от 1 до 128 изменяется от 0,756 до 1. Уже при L=8 вероятность удачи равна 0.914. Это говорит о том, что даже при одной попытке на каждое Ω мы имеем достаточно большую вероятность правильно отличить ошибки заполнения от ошибки имитозащиты. На момент публикации статьи практически все известные реализации TLS (OpenSSL, GnuTLS, NSS, Java BC, PolarSSL, yaSSL) были уязвимы к данному варианту временной атаки.
Наша атака или А если нет разницы, зачем заполнять меньше?
Годом ранее на конференции РусКрипто’2012 специалистами ООО «КРИПТО-ПРО» была представлена другая временная атака, направленная на расширение побочного канала.
Заметим, что в пункте 6.2.3.2 RFC 5246 указано, что заполнение может иметь любую длину, не превосходящую 255 байтов, обеспечивающую должное выравнивание. Таким образом, при размере блока алгоритма выработки имитовставки в 16 байтов сообщение длиной, например, 16 байтов, дополненное 240 байтами вида 0xf0, будет считаться дополненным корректно, и при проверке корректности сообщения будет вычисляться имитовставка на 1 блок. В случае же контролируемой модификации конечных блоков данного открытого текста (производимой аналогично методу Воденея) заполнение будет приниматься как некорректное, и имитовставка будет вычисляться на 16 блоков, обеспечивая существенную разницу во времени вычисления, создающую потенциальный канал утечки информации. По сравнению с атакой « Lucky Thirteen » э то позволяет ослабить требование по « близости» нарушителя к атакуемому клиенту или серверу. Наша атака работает в модели нарушителя, аналогичной BEAST , т.е. помимо навязывания шифртекста нарушитель имеет возможность навязывать открытый текст для зашифрования.
Идея атаки состоит в следующем. На расшифрование подается сообщение, после расшифрования которого в конце оказывается несколько блоков, интерпретируемых либо как часть корректного длинного заполнения, либо как часть сообщения с некорректным заполнением. В случае корректного заполнения имитовставка рассчитывается только на предшествующую этим блокам часть сообщения, иначе – на все сообщение. В случае большого числа этих блоков разница во времени вычисления имитовставки окажется значительной.
Благодаря данному временному каналу восстанавливается последний байт блока, предшествующего добавляемой части. После определения данного байта, аналогичным образом восстанавливается предшествующий ему, и так далее.
Описанная в нашей статье атака не может быть осуществлена напрямую из браузера сценарием JavaScript, т.к. этот уровень не управляет дополнением открытого текста для выравнивания границ блоков – это происходит на уровне реализации протокола TLS. Тем не менее, несложно модифицировать данную атаку таким образом, что она будет осуществима с помощью сценария JavaScript. Для этого понадобится, чтобы сценарий нарушителя дополнял отправляемое в канал сообщение в конце до границы блока аналогичным образом, но при этом отбрасывал последний байт. Тогда реализация TLS добавит заполнение в 1 байт вида 0x00, и у атакующего остаётся возможность подбирать открытый текст побайтово с конца в условиях существенной разницы по времени вычисления имитовставки при корректном и некорректном заполнении.
Ранее мы уже писали почему наша реализация TLS и другие, использующие поточные алгоритмы шифрования, неуязвимы к подобным атакам.
Судя по всему, тема атак на протокол TLS неисчерпаема, а значит, нам будет о чём писать в нашем блоге. Не отключайтесь!
Беляев Анатолий
Смирнов Павел
Смышляев Станислав
4 Лекция. Контроль целостности данных. Хеш-функции. Имитовставка. ЭЦП
Целостности данных — при котором отсутствует любое ее изменение либо изменение осуществляется только преднамеренно субъектами, имеющими на него право.
Методы контроля целостности данных:
-
Полная копия данных
Контрольная сумма
Имитовставка
Полная копия данных.
Создаются полные копии данных и потом сверяются.
- простота реализации
- полный контроль данных (до бита)
- большой объем
- копии можно подменить
- копиями можно воспользоваться (например: если данные — пароль)

Рис. Контроль целостности с помощью полной копии данных
- контроль целостности файлов
Контрольная сумма.
Контрольная сумма — значение, рассчитанное по входным данным с помощью определённого алгоритма.
- высокая скорость вычисления
- малый размер
- стандартный размер
- можно подменить
- для одного значения существует множество исходных данных
- можно подобрать исходные данные к значению за приемлемое время (например: получить пароль)

Рис. Контроль целостности с помощью контрольной суммы
Примеры контрольных сумм: CRC8, CRC16, CRC32
исходный текст: Контроль целостности данных
crc32 (длина 32 бита)
- контроль целостности файлов
- контроль передаваемых данных по каналам связи
- контроль целостности при считывании данных (например: c HDD)
Хеш.
Хеш (хэш, криптографический хеш) — значение, рассчитанное по входным данным с помощью криптографического алгоритма.
- малый размер
- стандартный размер
- нельзя подобрать исходные данные к значению за приемлемое время (например: получить пароль)
- низкая скорость вычисления (сопоставима с шифрованием)
- можно подменить
- для одного значения существует множество исходных данных

Рис. Основная задача хеш функций
Вычисляют хеш шифрованием данных блочным алгоритмом в режимах CBC, но со стандартным (известным) ключом. Хешем является последний шифрованный блок.
ГОСТ Р 34.11-94
Входное сообщение M разделяется на блоки mn,mn ? 1,mn ? 2. m1 по 256 бит. В случае если размер последнего блока mn меньше 256 бит, то к нему приписываются слева нули для достижения заданной длины блока.
Каждый блок сообщения подаётся на шаговую функцию для вычисления промежуточного значения хеш-функции Hout =f( Hin , mi ) где Hout , Hin , mi — блоки длины 256 бит.
Рис. Вычисление хеш по ГОСТ Р 34.11-94 (сравните с CBC)
h — значение хеш-функции сообщения M
Len(M) — длина сообщения
Ключи для f-функции генерятся стандартным образом, что бы все пользователи могли вычислить одинаковые хеш для одних и тех же файлов.
исходный текст: Контроль целостности данных
md2 (длина 128 бит)
md4 (длина 128 бит)
md5 (длина 128 бит)
sha1 (длина 160 бит)
sha224 (длина 224 бит)
sha256 (длина 256 бит)
sha384 (длина 384 бит)
sha512 (длина 512 бит)
ГОСТ Р 34.11-94 (длина 256 бит)
- контроль целостности файлов
- контроль передаваемых данных по каналам связи
- контроль целостности при считывании данных (например: c HDD)
- хеши паролей
- аутентификация (CRAM-MD5, DIGEST-MD5 и т.д.)
Имитовставка (MAC, message authentication code — код аутентичности сообщения)
Имитовставка — значение, рассчитанное по входным данным с помощью криптографического алгоритма с использованием секретного элемента (ключа), известного только отправителю и получателю.
- малый размер
- стандартный размер
- нельзя подобрать исходные данные к значению за приемлемое время (например: получить пароль)
- нельзя подменить без секретного элемента (ключа)
- низкая скорость вычисления (сопоставима с шифрованием)
- для одного значения существует множество исходных данных
- секретный ключ известен как минимум двоим
Вычисляют имитовставку шифрованием данных блочным алгоритмом в режимах CBC. Имитовставкой является последний шифрованный блок.
Рис. Вычисление имитовставки
Имитовставка по ГОСТ 28147-89
Длина имитовставки от 1 до 32 бит.
Открытый текст TO разбивается на блоки длиной 64 бита. Последний блок в случае необходимости дополняется нулями.

Первые 32 бита получившегося блока составляют имитовставку. Спецификация шифра предусматривает использование в качестве имитовставки и меньшее количество бит по желанию, но не большее.

Рис. Проблема имитовставки
Получатель должен знать ключ, и этот ключ позволяет ему генерировать сообщения с тем же значением имитовставки, что и у присланного сообщения, таким образом, имитовставка на основе симметричного шифра не дает знания — отправитель или получатель сформировал эту имитовставку.
Отсюда следует, что имитовставка на основе симметричного шифра не может заменять собой электронную подпись!
- контроль целостности файлов
- контроль передаваемых данных по каналам связи
- аутентификации источника данных (не во всех случаях)
Обычные хэш-алгоритмы использовать для вычисления имитовставки нельзя (MD5 и т.д.) т.к. отсутствует секретный ключ. Поэтому создан HMAC .
HMAC (H ash-based Message Authentication Code ) — механизм включения секретного ключа в существующие хэш-алгоритмы.
ЭЦП.
Электронная цифровая подпись — зашифрованное значение вычисленного хеша по входным данным.
- малый размер
- стандартный размер
- нельзя подобрать исходные данные к значению за приемлемое время (например: получить пароль)
- нельзя подменить без секретного элемента (ключа)
- секретный ключ известен одному
- низкая скорость вычисления (сопоставима с шифрованием)
- для одного значения существует множество исходных данных

Рис. Создание и проверка ЭЦП
- вычисляется хеш
- шифруется хеш
- контроль целостности файлов
- контроль передаваемых данных по каналам связи
- аутентификации источника данных (кто создал подпись)
Настройка ГОСТ в OpenSSL
В состав дистрибутива РЕД ОС входит пакет библиотек, поддерживающих методы защитного преобразования по алгоритмам ГОСТ, — openssl-gost-engine.
Пакет openssl-gost-engine включает в себя реализацию следующих алгоритмов ГОСТ:
- ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2012 — алгоритмы электронной цифровой подписи.
- ГОСТ Р 34.11-94 — Алгоритм хэширования. 256-битное значение хэша.
- ГОСТ Р 34.11-2012 — Алгоритм хэширования. 256- и 512-битные значения хеша.
- ГОСТ 28147-89 — Симметричное шифрование с 256-битным ключом. Доступны режимы CBC, CFB и CNT. Для усложнения статистического анализа поддерживается «key meshing» (подробнее см. RFC 4357).
- ГОСТ 28147-89 в режиме выработки имитовставки (MAC). Основан на алгоритме хэширования с использованием алгоритмов симметричного шифрования. Он имеет 256-битный симметричный ключ и разрядность от 8 до 64 (по умолчанию 32) бит.
- ГОСТ Р 34.13–2015 — Симметричное шифрование «Кузнечик» («Grasshopper»).
Установка поддержки алгоритмов ГОСТ
Для установки пакета openssl-gost-engine перейдите в сеанс пользователя root:
и выполните команду:
dnf install openssl-gost-engine
Здесь и далее команды будут выполняться с правами пользователя root, если не указано иное.
Первый способ переключения на ГОСТ
После установки openssl поддержку алгоритмов ГОСТ можно включить следующей командой:
openssl-switch-config
При указании аргумента gost поддержка алгоритмов ГОСТ включается, при указании аргумента default — возвращаются настройки по умолчанию.
Второй способ переключения на ГОСТ
Отредактируйте файл настроек /etc/pki/tls/openssl.cnf:
1. В начало файла поместите строку:
openssl_conf = openssl_def
2. Закомментируйте настройки по умолчанию:
#openssl_conf = default_modules
#[ default_modules ]
#ssl_conf = ssl_module
#[ ssl_module ]
#system_default = crypto_policy
#[ crypto_policy ]
#.include = /etc/crypto-policies/back-ends/opensslcnf.config
3. В конец файла добавьте следующие строки:
[openssl_def]
engines = engine_section
[engine_section]
gost = gost_section
[gost_section]
engine_id = gost dynamic_path = /usr/lib64/engines-1.1/gost.so
default_algorithms = ALL
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
4. Затем необходимо явно указать Cipher Strings в файле конфигурации /etc/crypto-policies/back-ends/openssl.config:
Проверка, что OpenSSL может использовать алгоритмы ГОСТ
После проведения настройки проверьте, видит ли OpenSSL алгоритмы ГОСТ, командой:
openssl ciphers | tr ":" "\n" | grep GOST GOST2012-GOST8912-GOST8912 GOST2001-GOST89-GOST89
Пример генерации ключей
Генерация закрытого ключа и создание сертификата с подписью ГОСТ производится следующей командой:
openssl req -x509 -newkey gost2012_256 -pkeyopt paramset:A -nodes -keyout key.pem -out cert.pem -md_gost12_256
Для проверки сертификата выполните команду:
openssl x509 -in cert.pem -text -noout Certificate: Dat a: Version: 3 (0x2) Serial Number: 17:86:3c:c0:8c:62:36:af:88:3c:19:01:34:bb:19:92:61:38:5a:37 Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit) Issuer: C = ru, ST = Russia, L = Moscow, O = red-soft, OU = drsp, CN = root, emailAddress = root Validity Not Before: Mar 15 11:24:48 2022 GMT Not After : Apr 14 11:24:48 2022 GMT Subject: C = ru, ST = Russia, L = Moscow, O = red-soft, OU = drsp, CN = root, emailAddress = root Subject Public Key Info: Public Key Algorithm: GOST R 34.10-2012 with 256 bit modulus Public key: X:27F4547D48EFAAE904FDCDCD190EB702858B77A796600E175FDEDA8BA35E3C1A Y:35D4E769099EDBC4461A8E67510897D98FD59C4F4D34F08F722899EAD7ABEF81 Parameter set: id-GostR3410-2001-CryptoPro-A-ParamSet X509v3 extensions: X509v3 Subject Key Identifier: 4B:E5:69:DE:B5:00:AE:01:71:56:97:C8:C5:30:8C:B1:5F:5E:AF:AF X509v3 Authority Key Identifier: keyid:4B:E5:69:DE:B5:00:AE:01:71:56:97:C8:C5:30:8C:B1:5F:5E:AF:AF X509v3 Basic Constraints: critical CA:TRUE Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit) 3e:94:02:7d:82:7a:52:5c:4d:09:8b:ae:c9:51:c1:19:2a:0f: c9:ce:39:39:89:27:89:87:e2:e7:bf:f7:9a:b3:be:bd:56:ea: 27:bf:56:d8:99:a9:96:09:62:a5:49:04:69:d1:ea:b3:0f:fa: 92:04:6a:da:27:79:49:ac:79:bd
Эта информация оказалась полезной? ДА НЕТ
Дата последнего изменения: 16.06.2023
Если вы нашли ошибку, пожалуйста, выделите текст и нажмите Ctrl+Enter.
Как посчитать имитовставку mac функциями openssl
Модуль pgcrypto предоставляет криптографические функции для Postgres Pro .
Данный модуль считается « доверенным » , то есть его могут устанавливать обычные пользователи, имеющие право CREATE в текущей базе данных.
F.34.1. Стандартные функции хеширования
F.34.1.1. digest()
digest(data text, type text) returns bytea digest(data bytea, type text) returns bytea
Вычисляет двоичный хеш данных ( data ). Параметр type выбирает используемый алгоритм. Поддерживаются стандартные алгоритмы: md5 , sha1 , sha224 , sha256 , sha384 и sha512 . Если модуль pgcrypto собирался с OpenSSL , становятся доступны и другие алгоритмы, как описано в Таблице F.24.
Если вы хотите получить дайджест в виде шестнадцатеричной строки, примените encode() к результату. Например:
CREATE OR REPLACE FUNCTION sha1(bytea) returns text AS $$ SELECT encode(digest($1, 'sha1'), 'hex') $$ LANGUAGE SQL STRICT IMMUTABLE;
F.34.1.2. hmac()
hmac(data text, key text, type text) returns bytea hmac(data bytea, key bytea, type text) returns bytea
Вычисляет имитовставку на основе хеша для данных data с ключом key . Параметр type имеет то же значение, что и для digest() .
Эта функция похожа на digest() , но вычислить хеш с ней можно, только зная ключ. Это защищает от сценария подмены данных и хеша вместе с ними.
Если размер ключа больше размера блока хеша, он сначала хешируется, а затем используется в качестве ключа хеширования данных.
F.34.2. Функции хеширования пароля
Функции crypt() и gen_salt() разработаны специально для хеширования паролей. Функция crypt() выполняет хеширование, а gen_salt() подготавливает параметры алгоритма для неё.
Алгоритмы в crypt() отличаются от обычных алгоритмов хеширования MD5 и SHA1 в следующих аспектах:
Они медленные. Так как объём данных невелик, это единственный способ усложнить перебор паролей.
Они используют случайное значение, называемое солью, чтобы у пользователей с одинаковыми паролями зашифрованные пароли оказывались разными. Это также обеспечивает дополнительную защиту от получения обратного алгоритма.
Они включают в результат тип алгоритма, что допускает сосуществование паролей, хешированных разными алгоритмами.
В Таблице F.21 перечислены алгоритмы, поддерживаемые функцией crypt() .
Таблица F.21. Алгоритмы, которые поддерживает crypt()
| Алгоритм | Макс. длина пароля | Адаптивный? | Размер соли (бит) | Размер результата | Описание |
|---|---|---|---|---|---|
| bf | 72 | да | 128 | 60 | На базе Blowfish, вариация 2a |
| md5 | без ограничений | нет | 48 | 34 | crypt на базе MD5 |
| xdes | 8 | да | 24 | 20 | Расширенный DES |
| des | 8 | нет | 12 | 13 | Изначальный crypt из UNIX |
F.34.2.1. crypt()
crypt(password text, salt text) returns text
Вычисляет хеш пароля ( password ) в стиле crypt(3). Для сохранения нового пароля необходимо вызвать gen_salt() , чтобы сгенерировать новое значение соли ( salt ). Для проверки пароля нужно передать сохранённое значение хеша в параметре salt и проверить, соответствует ли результат сохранённому значению.
Пример установки нового пароля:
UPDATE . SET pswhash = crypt('new password', gen_salt('md5'));
Пример проверки пароля:
SELECT (pswhash = crypt('entered password', pswhash)) AS pswmatch FROM . ;
Этот запрос возвращает true , если введённый пароль правильный.
F.34.2.2. gen_salt()
gen_salt(type text [, iter_count integer ]) returns text
Вычисляет новое случайное значение соли для функции crypt() . Строка соли также говорит crypt() , какой алгоритм использовать.
Параметр type задаёт алгоритм хеширования. Принимаются следующие варианты: des , xdes , md5 и bf .
Параметр iter_count позволяет пользователю указать счётчик итераций для алгоритма, который его принимает. Чем больше это число, тем больше времени уйдёт на вычисление хеша пароля, а значит, тем больше времени понадобится, чтобы взломать его. Хотя со слишком большим значением время вычисления хеша может вырасти до нескольких лет — это вряд ли практично. Когда параметр iter_count опускается, применяется количество итераций по умолчанию. Множество допустимых значений для iter_count зависит от алгоритма, как показано в Таблице F.22.
Таблица F.22. Счётчики итераций для crypt()
| Алгоритм | По умолчанию | Мин. | Макс. |
|---|---|---|---|
| xdes | 725 | 1 | 16777215 |
| bf | 6 | 4 | 31 |
Для xdes есть дополнительное ограничение: счётчик итераций должен быть нечётным.
При выборе подходящего числа итераций учтите, что оригинальный алгоритм DES crypt был рассчитан так, чтобы выдавать 4 хеша в секунду на компьютерах того времени. Если за секунду будет вычисляться меньше 4 хешей, скорее всего, возникнут определённые неудобства при пользовании. С другой стороны, скорость больше, чем 100 хешей в секунду, вероятно, будет слишком высокой.
В Таблице F.23 дана сводка относительной скорости различных алгоритмов хеширования. В таблице показано, сколько времени уйдёт на перебор всех комбинацией символов в восьмисимвольном пароле, в предположении, что пароль содержит только буквы в нижнем регистре, либо буквы в верхнем и нижнем регистре, а также цифры. В строках crypt-bf числа после косой черты показывают значение параметра iter_count функции gen_salt .
Таблица F.23. Скорости алгоритмов хеширования
| Алгоритм | Хешей/сек. | Для [a-z] | Для [A-Za-z0-9] | Длительность относительно md5 |
|---|---|---|---|---|
| crypt-bf/8 | 1792 | 4 года | 3927 лет | 100k |
| crypt-bf/7 | 3648 | 2 года | 1929 лет | 50k |
| crypt-bf/6 | 7168 | 1 год | 982 лет | 25k |
| crypt-bf/5 | 13504 | 188 дней | 521 лет | 12.5k |
| crypt-md5 | 171584 | 15 дней | 41 год | 1k |
| crypt-des | 23221568 | 157.5 минут | 108 дней | 7 |
| sha1 | 37774272 | 90 минут | 68 дней | 4 |
| md5 (хеш) | 150085504 | 22.5 минут | 17 дней | 1 |
Для расчётов использовался процессор Intel Mobile Core i3.
Показатели алгоритмов crypt-des и crypt-md5 взяты из вывода теста программы John the Ripper v1.6.38.
Показатели md5 получены программой mdcrack 1.2.
Показатели sha1 получены программой lcrack-20031130-beta.
Заметьте, что вариант « перепробовать все комбинации » не вполне реалистичен. Обычно перебор паролей производится с применением словарей, которые содержат и обычные слова, и их различные видоизменения. Поэтому даже похожие на слова пароли обычно можно подобрать быстрее, чем за указанное время, тогда как 6-символьный несловесный пароль может избежать взлома. А может и не избежать.
F.34.3. Функции шифрования на базе PGP
Функции, описанные здесь, реализуют часть стандарта OpenPGP (RFC 4880), относящуюся к шифрованию. Они поддерживают шифрование как с симметричным, так и с закрытым ключом.
Зашифрованное PGP сообщение состоит из 2 частей или пакетов:
Пакет, содержащий сеансовый ключ — либо симметричный, либо открытый (в зашифрованном виде).
При шифровании с симметричным ключом (то есть, паролем):
Заданный пароль хешируется по алгоритму String2Key (S2K). Этот алгоритм подобен алгоритмам crypt() — специально замедлен и добавляет случайную соль — но на выход выдаёт двоичный ключ полной длины.
Если требуется отдельный сеансовый ключ, генерируется новый случайный ключ. В противном случае в качестве сеансового будет использоваться непосредственно ключ S2K.
При шифровании с открытым ключом:
Генерируется новый случайный сеансовый ключ.
В любом случае данные, которые должны быть зашифрованы, обрабатываются так:
Необязательная подготовка данных: сжатие, перекодировка в UTF-8 и/или преобразование концов строк.
Перед данными добавляется блок случайных байт. Это равносильно использованию случайного вектора инициализации.
В конце добавляется хеш SHA1 случайного префикса и данных.
F.34.3.1. pgp_sym_encrypt()
pgp_sym_encrypt(data text, psw text [, options text ]) returns bytea pgp_sym_encrypt_bytea(data bytea, psw text [, options text ]) returns bytea
Шифрует данные ( data ) симметричным ключом PGP psw . В options могут передаваться криптографические параметры, описанные ниже.
F.34.3.2. pgp_sym_decrypt()
pgp_sym_decrypt(msg bytea, psw text [, options text ]) returns text pgp_sym_decrypt_bytea(msg bytea, psw text [, options text ]) returns bytea
Расшифровывает сообщение, зашифрованное симметричным ключом PGP.
Расшифровывать данные bytea функцией pgp_sym_decrypt запрещено. Это ограничение введено, чтобы не допустить вывода некорректных символьных данных. Расшифровывать изначально текстовые данные с помощью pgp_sym_decrypt_bytea можно без ограничений.
Аргумент options может содержать криптографические параметры, описанные ниже.
F.34.3.3. pgp_pub_encrypt()
pgp_pub_encrypt(data text, key bytea [, options text ]) returns bytea pgp_pub_encrypt_bytea(data bytea, key bytea [, options text ]) returns bytea
Зашифровывает данные ( data ) открытым ключом PGP ( key ). Если передать этой функции закрытый ключ, она выдаст ошибку.
Аргумент options может содержать криптографические параметры, описанные ниже.
F.34.3.4. pgp_pub_decrypt()
pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text ]]) returns text pgp_pub_decrypt_bytea(msg bytea, key bytea [, psw text [, options text ]]) returns bytea
Расшифровывает сообщение, зашифрованное открытым ключом. В key должен передаваться закрытый ключ, соответствующий открытому ключу, применяющемуся при шифровании. Если секретный ключ защищён паролем, этот пароль нужно передать в параметре psw . Если пароля нет, но необходимо передать криптографические параметры, вы должны передать пустой пароль.
Расшифровывать данные bytea функцией pgp_pub_decrypt запрещено. Это ограничение введено, чтобы не допустить вывода недопустимых символьных данных. Расшифровывать изначально текстовые данные с помощью pgp_pub_decrypt_bytea можно без ограничений.
Аргумент options может содержать криптографические параметры, описанные ниже.
F.34.3.5. pgp_key_id()
pgp_key_id(bytea) returns text
pgp_key_id извлекает идентификатор ключа из открытого или закрытого ключа PGP. Она также может выдать идентификатор ключа, которым были зашифрованы данные, если ей передаётся зашифрованное сообщение.
Она может выдать два специальных идентификатора ключа:
Сообщение зашифровано симметричным ключом.
Заметьте, что разные ключи могут иметь одинаковый идентификатор. Это редкое, но не невероятное явление. В таком случае клиентское приложение должно пытаться расшифровать данные с каждым ключом, пока не найдёт подходящий — примерно так же, как и с ANYKEY .
F.34.3.6. armor() , dearmor()
armor(data bytea [ , keys text[], values text[] ]) returns text dearmor(data text) returns bytea
Эти функции переводят двоичные данные в/из формата PGP «ASCII Armor», по сути представляющий собой кодировку Base64 с контрольными суммами и дополнительным форматированием.
Если задаются массивы keys и values , для каждой пары ключ/значения в формат Armor добавляется заголовок Armor. Оба массива должны быть одномерными и иметь одинаковую длину. Задаваемые ключи и значения могут содержать только символы ASCII.
F.34.3.7. pgp_armor_headers
pgp_armor_headers(data text, key out text, value out text) returns setof record
Функция pgp_armor_headers() извлекает заголовки Armor из параметра data . Она возвращает набор строк с двумя столбцами, key и value. Если в ключах или значениях оказываются символы не ASCII, они воспринимаются как UTF-8.
F.34.3.8. Параметры функций PGP
Имена параметров подобны принятым в GnuPG. Значение параметра должно задаваться после знака равно; друг от друга параметры отделяются запятыми. Например:
pgp_sym_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256')
Все эти параметры, кроме convert-crlf , применяются только к функциям шифрования. Функции расшифровывания получают параметры из данных PGP.
Вероятно, самые интересные параметры — это compress-algo и unicode-mode . Остальные должны иметь достаточно адекватные значения по умолчанию.
F.34.3.8.1. cipher-algo
Выбирает алгоритм шифрования.
Значения: bf, aes128, aes192, aes256 (только OpenSSL: 3des , cast5 )
По умолчанию: aes128
Применим к: pgp_sym_encrypt, pgp_pub_encrypt
F.34.3.8.2. compress-algo
Выбирает алгоритм сжатия. Принимается, только если Postgres Pro собран с zlib.
Значения:
0 — без сжатия
1 — сжатие ZIP
2 — сжатие ZLIB (= ZIP плюс метаданные и CRC блоков)
По умолчанию: 0
Применим к: pgp_sym_encrypt, pgp_pub_encrypt
F.34.3.8.3. compress-level
Определяет уровень сжатия. Чем больше уровень, тем меньшего объёма результат, но длительнее процесс. Значение 0 отключает сжатие.
Значения: 0, 1-9
По умолчанию: 6
Применим к: pgp_sym_encrypt, pgp_pub_encrypt
F.34.3.8.4. convert-crlf
Определяет, преобразовывать ли \n в \r\n при шифровании и \r\n в \n при дешифровании. В RFC 4880 требуется, чтобы текстовые данные хранились с переводами строк в виде \r\n . Воспользуйтесь этим параметром, чтобы поведение полностью соответствовало RFC.
Значения: 0, 1
По умолчанию: 0
Применим к: pgp_sym_encrypt, pgp_pub_encrypt, pgp_sym_decrypt, pgp_pub_decrypt
F.34.3.8.5. disable-mdc
Не защищать данные хешем SHA-1. Единственная разумная причина использовать этот параметр — добиться совместимости с древними программами PGP, вышедшими до того, как в RFC 4880 была предусмотрена защита пакетов с SHA-1. Все последние реализации с gnupg.org и pgp.com прекрасно поддерживают это.
Значения: 0, 1
По умолчанию: 0
Применим к: pgp_sym_encrypt, pgp_pub_encrypt
F.34.3.8.6. sess-key
Использовать отдельный сеансовый ключ. Для шифрования с открытым ключом всегда используется отдельный сеансовый ключ; этот параметр предназначен для шифрования с симметричным ключом, которое по умолчанию использует непосредственно ключ S2K.
Значения: 0, 1
По умолчанию: 0
Применим к: pgp_sym_encrypt
F.34.3.8.7. s2k-mode
Режим алгоритма S2K.
Значения:
0 — Без соли. Опасно!
1 — С солью, но с фиксированным числом итераций.
3 — С переменным числом итераций.
По умолчанию: 3
Применим к: pgp_sym_encrypt
F.34.3.8.8. s2k-count
Число итераций для алгоритма S2K. Оно должно быть не меньше 1024 и не больше 65011712.
По умолчанию: случайное значение между 65536 и 253952
Применим к: pgp_sym_encrypt, только с s2k-mode=3
F.34.3.8.9. s2k-digest-algo
Выбирает алгоритм хеширования, который будет использоваться для вычисления S2K.
Значения: md5, sha1
По умолчанию: sha1
Применим к: pgp_sym_encrypt
F.34.3.8.10. s2k-cipher-algo
Выбирает шифр, который будет использоваться для шифрования отдельного сеансового ключа.
Значения: bf, aes, aes128, aes192, aes256
По умолчанию: используется cipher-algo
Применим к: pgp_sym_encrypt
F.34.3.8.11. unicode-mode
Определяет, преобразовывать ли текстовые данные из внутренней кодировки базы данных в UTF-8 и обратно. Если кодировка базы уже UTF-8, перекодировка не производится, но сообщение помечается как UTF-8. Без данного параметра этого не происходит.
Значения: 0, 1
По умолчанию: 0
Применим к: pgp_sym_encrypt, pgp_pub_encrypt
F.34.3.9. Формирование ключей PGP с применением GnuPG
Формирование нового ключа:
gpg --gen-key
Предпочитаемый тип ключей: « DSA and Elgamal » .
Для шифрования RSA вы должны создать главный ключ либо DSA, либо RSA только для подписания, а затем добавить подключ для шифрования, выполнив команду gpg —edit-key .
Просмотр списка ключей:
gpg --list-secret-keys
Экспорт открытого ключа в формате «ASCII Armor»:
gpg -a --export KEYID > public.key
Экспорт закрытого ключа в формате «ASCII Armor»:
gpg -a --export-secret-keys KEYID > secret.key
Прежде чем передавать эти ключи функциям PGP, вы должны применить функцию dearmor() к этим ключам. Либо, если вы можете обработать двоичные данные, уберите -a из команды.
Дополнительную информацию вы можете получить в руководстве man gpg , The GNU Privacy Handbook (Руководство GNU по обеспечению конфиденциальности) и другой документации на сайте https://www.gnupg.org/.
F.34.3.10. Ограничения кода PGP
Не поддерживается подписывание. Это также означает, что принадлежность подключа шифрования главному ключу не проверяется.
Не поддерживается использование ключа шифрования в качестве главного ключа. Так как подобная практика обычно не приветствуется, это не должно быть проблемой.
F.34.4. Низкоуровневые функции шифрования
Эти функции выполняют только шифрование данных; они не предоставляют расширенные возможности шифрования PGP. Таким образом, с ними связаны следующие проблемы:
Они используют ключ пользователя непосредственно в качестве ключа шифрования.
Они не обеспечивают проверку целостности, которая должна выявлять модификацию зашифрованных данных.
Они рассчитаны на то, что пользователи будут управлять всеми параметрами шифрования самостоятельно, даже вектором инициализации.
Поэтому с появлением поддержки шифрования PGP использовать низкоуровневые функции шифрования не рекомендуется.
encrypt(data bytea, key bytea, type text) returns bytea decrypt(data bytea, key bytea, type text) returns bytea encrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea decrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea
Эти функции зашифровывают/расшифровывают данные, применяя метод шифрования, заданный параметром type . Строка type имеет следующий формат:
алгоритм[-режим] [/pad:дозаполнение]
где допустимый алгоритм :
cbc — следующий блок зависит от предыдущего (по умолчанию)
и допустимое дозаполнение :
pkcs — данные могут быть любой длины (по умолчанию)
Так что, например, эти вызовы равнозначны:
encrypt(data, 'fooz', 'bf') encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')
Для функций encrypt_iv и decrypt_iv параметр iv задаёт начальное значение для режима CBC; для ECB он игнорируется. Оно обрезается или дополняется нулями, если его размер не равен ровно размеру блока. В функциях без этого параметра оно по умолчанию заполняется нулями.
F.34.5. Функции получения случайных данных
gen_random_bytes(count integer) returns bytea
Возвращает криптографически стойкие случайные байты в количестве count . За один вызов можно получить максимум 1024 байт. Это ограничение предотвращает исчерпание пула энтропии.
gen_random_uuid() returns uuid
Возвращает UUID версии 4 (случайный). (Эта функция в данном модуле считается устаревшей, она вызывает одноимённую функцию ядра.)
