Python 3.6 SSL - использует TLSv1.0 вместо шифра TLSv1.2 - (двухсторонняя аутентификация и самозаверяющий сертификат)

Я использую библиотеку ssl с python 3.6. Я использую самоподписанный сертификат ECDSA, созданный с помощью openssl.

Код сервера / клиента:

# Create a context in TLSv1.2, requiring a certificate (2-way auth)
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.options |= ssl.OP_NO_TLSv1
context.options |= ssl.OP_NO_TLSv1_1
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True # This line ommited in server code

# Set the list of allowed ciphers to those with key length of at least 128
# TODO Figure out why this isn't working
context.set_ciphers('TLSv1.2+HIGH+SHA256+ECDSA')

# Print some info about the connection
for cipher in context.get_ciphers():
    print(cipher)

Вывод:

{'id': 50380835, 'name': 'ECDHE-ECDSA-AES128-SHA256', 'protocol': 'TLSv1/SSLv3', 'description': 'ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AES(128)  Mac=SHA256', 'strength_bits': 128, 'alg_bits': 128}

Текущий шифр:

 connection.cipher()

('ECDHE-ECDSA-AES128-SHA256', 'TLSv1 / SSLv3', 128)

Мой вопрос: почему выбранный шифр не TLSv1.2?

Изменить: запрошенные скриншоты

введите описание изображения здесь

введите описание изображения здесь

Основываясь на другом потоке, я попытался изменить свой код на следующий, но безуспешно.

 # Create a context in TLSv1.2, requiring a certificate (2-way auth)
    self.context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    self.context.options |= ssl.OP_NO_SSLv2
    self.context.options |= ssl.OP_NO_SSLv3
    self.context.options |= ssl.OP_NO_TLSv1
    self.context.options |= ssl.OP_NO_TLSv1_1
    self.context.verify_mode = ssl.CERT_REQUIRED
    # self.context.check_hostname = True

    # Set the list of allowed ciphers to those with high key length
    # I went with  SHA384 because it seemed to have more security
    self.context.set_ciphers('TLSv1.2+ECDSA+HIGH')

person whenitrains    schedule 28.02.2018    source источник


Ответы (2)


Этот шифр совместим с TLS 1.2, это обычный шифр, определенный в RFC 5289.

Я думаю, нам нужно немного интерпретировать документ Python, чтобы знать, что get_ciphers () возвращает точно так, как это не объясняется. Но cipher () может дать нам ответ:

SSLSocket.cipher ()

Возвращает трехзначный кортеж, содержащий имя используемого шифра, версию протокола SSL, определяющую его использование, и количество используемых секретных битов. Если соединение не было установлено, возвращает None.

Сетевой захват подтвердит версию протокола TLS.

person Eugène Adell    schedule 28.02.2018
comment
Добавлены скриншоты. Кажется, использует ssh! В этом нет особого смысла. - person whenitrains; 01.03.2018
comment
SSL-трафик обычно идет на порт 443, вы можете попробовать захватить только через этот порт. Если он работает, откройте захват и перейдите к пакету Client Hello. - person Eugène Adell; 01.03.2018

Вы ищете SSLSocket.version()


Следуя ответу Эжена Аделла о том, почему SSLSocket.cipher() не дает вам того, что вы ожидаете, python вызывает _3 _, документация которого гласит:

... возвращает строку, которая указывает версию протокола SSL / TLS, которая первой определила шифр. В настоящее время это SSLv2 или TLSv1 / SSLv3. В некоторых случаях он, возможно, должен возвращать «TLSv1.2», но этого не происходит; вместо этого используйте SSL_CIPHER_description ().

person Steven Winfield    schedule 10.02.2020