"расшифровать ошибку" TLS 1.2 change-cipher-spec, но читает MAC правильно
Я пытаюсь обновить старую реализацию TLS 1.0 (которую я не писал), чтобы говорить TLS 1.2.
в качестве первого шага я интегрировал изменение TLS 1.1 ввод вектора инициализации открытого текста в запись. Это не проблема. Казалось, он работал достаточно хорошо, чтобы я мог читать https://example.com
в TLS 1.1, а также SSL Labs viewMyClient.HTML-код.
затем я адаптировался к изменению TLS 1.2 псевдослучайной функции На (для большинство практических целей) P_SHA256 вместо (более сложной и причудливой)половина и половина MD5 / SHA1 rigamarole. Я сделал это неправильно в первый раз и получил недопустимую ошибку MAC, но это была более или менее опечатка с моей стороны, и я исправил ее. Затем недействительная ошибка MAC ушла.
но, несмотря на это, после отправки сообщений ClientKeyExchange - >ChangeCipherSpec я получаю "расшифровать ошибку" с сервера(ов) (то же предупреждение независимо,https://google.com
или все, что я пытаюсь). Я понимаю, что сообщение ChangeCipherSpec шифрует только один байт, помещая его в сообщение с заполнением и MAC и т. д.
если я настраиваю MAC случайным образом на один байт, он возвращается к жалобе на недопустимый MAC. что меня смущает-это то,сам MAC зашифрован как часть GenericBlockCipher:
struct {
opaque IV[SecurityParameters.record_iv_length];
block-ciphered struct {
opaque content[TLSCompressed.length];
opaque MAC[SecurityParameters.mac_length]; // <-- server reads this fine!
uint8 padding[GenericBlockCipher.padding_length];
uint8 padding_length;
};
} GenericBlockCipher;
обновление: FWIW, я добавил Wireshark журнал сбоя 1.2 чтение
https://example.com
, а также журнал функционирующего сеанса 1.1 с тем же кодом, не считая обновления P_SHA256 MAC:http://hostilefork.com/media/shared/stackoverflow/example-com-tls-1.2.pcapng (сбой) http://hostilefork.com/media/shared/stackoverflow/example-com-tls-1.1.pcapng (успешно)
Итак, что именно у него возникли проблемы с расшифровкой? Обивка кажется правильно, как будто добавить или вычесть 1 в байт я получаю недопустимую ошибку MAC. (спецификация говорит: "приемник должен проверить это заполнение и должен использовать предупреждение bad_record_mac для указания ошибок заполнения.- этого следовало ожидать.) если я повреждаю client-iv в сообщении от того, что я использовал для шифрования (просто поместите плохой байт в переданную версию), это также дает мне плохую запись MAC. Я ожидал, что это также разрушит расшифровку.
поэтому я озадачен тем, что может быть проблема:
- сервер демонстрирует различение допустимого MAC против не, так что это должны расшифровали. Как он получает правильный MAC - и-имеющий ошибку дешифрования?
- Cipher suite-старый (TLS_RSA_WITH_AES_256_CBC_SHA), но я просто решаю одну проблему за раз...и если я не ошибаюсь, это не имеет значения.
есть ли у кого-нибудь с соответствующим опытом теория о том, как TLS 1.2 может бросить ключ в код, который иначе работает в TLS 1.1? (возможно, кто-то, кто сделал подобное обновление для кодовой базы, и должен был изменить больше, чем две вещи, которые я изменил, чтобы заставить его работать?) я пропускаю еще одно важное техническое изменение? Какой ресурс у меня есть, чтобы узнать, что делает сервер несчастным?
2 ответов
на самом деле нет ничего плохого в ChangeCipherSpec
сообщение. Это на самом деле Finished
в этом проблема. Он жалуется на расшифровку verify_data
внутри этого сообщения, которое не соответствует ожидаемому хэшу (несмотря на то, что само шифрование/дешифрование является правильным).
но что смущает в журнале Wireshark, так это то, что Finished
сообщение появляется на той же строке журнала, но под именем "EncryptedHandshakeMessage
" это делает это похоже на какой-то тег или ярлык, описывающий ChangeCipherSpec, но это не так. Это сообщение вообще не зашифровано.
- TLS закончил пакет переименован зашифрованное сообщение рукопожатия
- HTTPS через TLS-зашифрованный тип
из второй ссылки:
на практике вы увидите незашифрованный клиент Hello, сервер Hello, сертификат, обмен ключами сервера, сертификат Запрос, проверка сертификата и сообщения обмена ключами клиента. Сообщение о готовом рукопожатии шифруется, поскольку оно возникает после сообщения спецификации шифра изменения.
"надеясь, что у кого-то есть опыт обновления TLS 1.0 или 1.1 до 1.2, и, возможно, видели аналогичную проблему из-за не меняется больше, чем P_SHA256 MAC и натыкаясь на номер версии"
они упоминают только два из трех мест, которые вам нужно обновить MD5 / SHA1 комбинация в " изменения из TLS 1.1 " раздел из RFC 5246:
комбинация MD5/SHA-1 в псевдослучайной функции (PRF) была заменена на PRFs, заданную набором шифров. Все шифров в данном документе P_SHA256.
комбинация MD5/SHA-1 в элементе с цифровой подписью была заменена одним хэшем. Подписанные элементы теперь включают поле, которое явно указывает используется хэш-алгоритм.
(Примечание: второй относится к сертификатам, и если вы еще не получили проверку сертификата, вы еще не были бы в этот момент.)
то, что они не упоминают в этом разделе, это третий поместите изменения комбинации MD5/SHA-1, которая является хэшем, используемым в семени для verify_data
на Finished
сообщение. Однако этот момент также является изменением от TLS 1.1, описанного намного дальше вниз документ в 7.4.9:
"хэш обозначает хэш сообщений рукопожатия. Для PRF, определенного в разделе 5, хэш должен быть хэшем, используемым в качестве основы для PRF. Любой набор шифров, который определяет другой PRF, также должен определить хэш для использования в завершенном вычислении."
для формальной спецификации они немного расплывчаты на "хэше, используемом в качестве основы для PRF "(это HMAC или просто хэш?) Но это обычный гашиш. Так и SHA256, если спекуляции шифра говорит иначе.
(обратите внимание также, что набор шифров может диктовать длину verify_data более 12 байтов, хотя ни один из них не упоминается в спецификации.)
" какой у меня есть способ узнать, что делает сервер несчастным?"
YMMV. Но я просто построил OpenSSL как статическую библиотеку отладки и связал ее с простым сервером. Затем я добавил точки останова и инструменты, чтобы увидеть, что это было расстроено. (GDB не позволял мне войти в общую библиотеку по какой-то причине.)
около 30-Sep-2018, на простой машине linux:
git://git.openssl.org/openssl.git
./config no-shared no-asm -g3 -O0 -fno-omit-frame-pointer -fno-inline-functions no-ssl2 no-ssl3
make
простой сервер я приехал из простой сервер TLS. Сборки статической библиотеки с:
gcc -g -O0 simple.c -o simple -lssl -lcrypto -ldl -lpthread
я следовал инструкциям по созданию сертификатов здесь, но изменил AAs на localhost
openSSL подписать https_client сертификат с CA
затем я изменил cert.pem => rootCA.pem
и key.pem => rootCA.key
в простом коде сервера. Я смог сделать:
wget https://localhost:4433 --no-check-certificate
и успешно вернуться test
в качестве ответа. Тогда оставалось только узнать, где мой клиент. вызвал неудачу.
Я могу думать о 2 различных ситуациях, которые создают эту проблему:
- отправка некорректно
IV
.IV
влияет только на 1-й блок при расшифровкеCBC
режим, поэтому, если ваш контент больше 16 байт (AES
размер блока),MAC
часть ваших данных будет правильно расшифрован. - если вы используете неправильную структуру заполнения, вы можете получить ошибку в расшифровке (потому что проверка заполнения не выполняется), но содержимое будет расшифровано правильно.