├── MANIFEST.in ├── setup.cfg ├── dev-requirements.txt ├── .travis ├── run.sh └── install.sh ├── .gitignore ├── .travis.yml ├── tox.ini ├── tlsenum ├── utils.py ├── hello_constructs.py ├── __init__.py ├── parse_hello.py └── mappings.py ├── tests ├── test_utils.py └── test_parse_hello.py ├── LICENSE ├── setup.py └── README.md /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [wheel] 2 | universal = 1 3 | -------------------------------------------------------------------------------- /dev-requirements.txt: -------------------------------------------------------------------------------- 1 | coverage 2 | flake8 3 | pytest 4 | tox 5 | pretend 6 | -------------------------------------------------------------------------------- /.travis/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | source ~/.venv/bin/activate 7 | tox -e $TOX_ENV -- $TOX_FLAGS 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | _build/ 3 | build/ 4 | dist/ 5 | htmlcov/ 6 | .tox/ 7 | .cache/ 8 | .coverage 9 | *.egg-info/ 10 | *.egg 11 | *.py[co] 12 | .vagrant/ 13 | -------------------------------------------------------------------------------- /.travis/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | sudo add-apt-repository -y ppa:fkrull/deadsnakes 7 | sudo apt-get -y update 8 | 9 | sudo apt-get install python3.3 python3.3-dev 10 | 11 | sudo pip install virtualenv 12 | 13 | virtualenv ~/.venv 14 | source ~/.venv/bin/activate 15 | pip install tox coveralls 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | os: 3 | - linux 4 | 5 | env: 6 | matrix: 7 | - TOX_ENV=py33 8 | - TOX_ENV=py34 9 | - TOX_ENV=pep8 10 | 11 | install: 12 | - ./.travis/install.sh 13 | 14 | script: 15 | - ./.travis/run.sh 16 | 17 | after_success: 18 | - source ~/.venv/bin/activate && coveralls 19 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py27, py33, py34, pep8 3 | 4 | [testenv] 5 | deps = 6 | coverage 7 | pytest 8 | pretend 9 | commands = 10 | coverage run --source=tlsenum -m pytest --capture=no --strict 11 | coverage report -m 12 | 13 | [testenv:pep8] 14 | basepython = python3 15 | deps = 16 | flake8 17 | commands = 18 | flake8 . 19 | 20 | [flake8] 21 | exclude = .tox,*.egg 22 | select = E,W,F,N,I 23 | -------------------------------------------------------------------------------- /tlsenum/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | import construct 4 | 5 | import six 6 | 7 | 8 | class _UBInt24(construct.Adapter): 9 | def _encode(self, obj, context): 10 | return ( 11 | six.int2byte((obj & 0xFF0000) >> 16) + 12 | six.int2byte((obj & 0x00FF00) >> 8) + 13 | six.int2byte(obj & 0x0000FF) 14 | ) 15 | 16 | def _decode(self, obj, context): 17 | obj = bytearray(obj) 18 | return (obj[0] << 16 | obj[1] << 8 | obj[2]) 19 | 20 | 21 | def UBInt24(name): 22 | return _UBInt24(construct.Bytes(name, 3)) 23 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | import pytest 4 | 5 | from construct.core import Construct 6 | from pretend import stub 7 | 8 | from tlsenum.utils import _UBInt24 9 | 10 | 11 | @pytest.mark.parametrize("byte,number", [ 12 | (b"\x00\x00\xFF", 255), 13 | (b"\x00\xFF\xFF", 65535), 14 | (b"\xFF\xFF\xFF", 16777215) 15 | ]) 16 | class TestUBInt24(object): 17 | def test_encode(self, byte, number): 18 | ubint24 = _UBInt24(Construct(name="test")) 19 | assert ubint24._encode(number, context=stub()) == byte 20 | 21 | def test_decode(self, byte, number): 22 | ubint24 = _UBInt24(Construct(name="test")) 23 | assert ubint24._decode(byte, context=stub()) == number 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Terry Chia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | from setuptools import setup, find_packages 4 | 5 | setup( 6 | name="tlsenum", 7 | description="A TLS ciphersuite enumeration tool.", 8 | version="0.3", 9 | install_requires=[ 10 | "Click", 11 | "Construct<2.8", 12 | "enum34", 13 | "idna", 14 | "six" 15 | ], 16 | entry_points=""" 17 | [console_scripts] 18 | tlsenum=tlsenum:cli 19 | """, 20 | packages=find_packages(exclude=["tests*"]), 21 | license="MIT", 22 | url="https://github.com/Ayrx/tlsenum", 23 | author="Terry Chia", 24 | author_email="terrycwk1994@gmail.com", 25 | classifiers=[ 26 | "Intended Audience :: Developers", 27 | "Natural Language :: English", 28 | "License :: OSI Approved :: MIT License", 29 | "Operating System :: OS Independent", 30 | "Programming Language :: Python", 31 | "Programming Language :: Python :: 2", 32 | "Programming Language :: Python :: 2.7", 33 | "Programming Language :: Python :: 3", 34 | "Programming Language :: Python :: 3.3", 35 | "Programming Language :: Python :: 3.4", 36 | "Topic :: Security", 37 | "Topic :: Security :: Cryptography" 38 | ], 39 | ) 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tlsenum 2 | ======= 3 | 4 | [![Build Status](https://travis-ci.org/Ayrx/tlsenum.svg?branch=master)](https://travis-ci.org/Ayrx/tlsenum) 5 | [![Coverage Status](https://coveralls.io/repos/Ayrx/tlsenum/badge.png?branch=master)](https://coveralls.io/r/Ayrx/tlsenum?branch=master) 6 | 7 | tlsenum is a command-line TLS enumeration tool that attempts to enumerate what 8 | TLS cipher suites a server supports and list them in order of priority. 9 | 10 | It works by sending out sending out TLS `ClientHello` messages and parsing the 11 | `ServerHello` responses from the server. 12 | 13 | tlsenum assumes that the server decides the preferred cipher suite, ignoring 14 | the preference indicated by the client. While this is not strictly guaranteed 15 | by the TLS specification, it seems like a fairly common implementation detail. 16 | 17 | Installation 18 | ------------ 19 | 20 | `tlsenum` can be used with Python 2.7, 3.3 or 3.4 and can be installed with 21 | pip. 22 | 23 | $ pip install tlsenum 24 | 25 | Usage 26 | ----- 27 | 28 | Using this tool is fairly simple, here is an example of the tool's results 29 | when scanning twitter.com. 30 | 31 | ``` 32 | [ayrx@division tlsenum]$ tlsenum twitter.com 443 33 | TLS Versions supported by server: 3.0, 1.0, 1.1, 1.2 34 | Deflate compression: no 35 | Supported Cipher suites in order of priority: 36 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 37 | TLS_ECDHE_RSA_WITH_RC4_128_SHA 38 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 39 | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 40 | TLS_RSA_WITH_AES_128_GCM_SHA256 41 | TLS_RSA_WITH_RC4_128_SHA 42 | TLS_RSA_WITH_RC4_128_MD5 43 | TLS_RSA_WITH_AES_128_CBC_SHA 44 | TLS_RSA_WITH_AES_256_CBC_SHA 45 | TLS_RSA_WITH_3DES_EDE_CBC_SHA 46 | ``` 47 | 48 | Do look at `tlsenum -h` for other options. 49 | -------------------------------------------------------------------------------- /tlsenum/hello_constructs.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | from construct import Array, Bytes, Struct, Switch, UBInt16, UBInt32, UBInt8 4 | 5 | from tlsenum.utils import UBInt24 6 | 7 | 8 | ProtocolVersion = Struct( 9 | "version", 10 | UBInt8("major"), 11 | UBInt8("minor") 12 | ) 13 | 14 | Random = Struct( 15 | "random", 16 | UBInt32("gmt_unix_time"), 17 | Bytes("random_bytes", 28) 18 | ) 19 | 20 | SessionID = Struct( 21 | "session_id", 22 | UBInt8("length"), 23 | Bytes("session_id", lambda ctx: ctx.length) 24 | ) 25 | 26 | CipherSuites = Struct( 27 | "cipher_suites", 28 | UBInt16("length"), 29 | Array(lambda ctx: ctx.length // 2, UBInt16("cipher_suites")) 30 | ) 31 | 32 | CompressionMethods = Struct( 33 | "compression_methods", 34 | UBInt8("length"), 35 | Array(lambda ctx: ctx.length, UBInt8("compression_methods")) 36 | ) 37 | 38 | ClientHello = Struct( 39 | "ClientHello", 40 | ProtocolVersion, 41 | Random, 42 | SessionID, 43 | CipherSuites, 44 | CompressionMethods, 45 | UBInt16("extensions_length"), 46 | Bytes("extensions_bytes", lambda ctx: ctx.extensions_length), 47 | ) 48 | 49 | ServerHello = Struct( 50 | "ServerHello", 51 | ProtocolVersion, 52 | Random, 53 | SessionID, 54 | UBInt16("cipher_suite"), 55 | UBInt8("compression_method") 56 | ) 57 | 58 | Handshake = Struct( 59 | "handshake", 60 | UBInt8("handshake_type"), 61 | UBInt24("length"), 62 | Switch("handshake_struct", lambda ctx: ctx.handshake_type, { 63 | 1: ClientHello, 64 | 2: ServerHello 65 | }) 66 | ) 67 | 68 | Alert = Struct( 69 | "alert", 70 | UBInt8("alert_level"), 71 | UBInt8("alert_description") 72 | ) 73 | 74 | TLSPlaintext = Struct( 75 | "TLSPlaintext", 76 | UBInt8("content_type"), 77 | ProtocolVersion, 78 | UBInt16("length"), 79 | Switch("content", lambda ctx: ctx.content_type, { 80 | 21: Alert, 81 | 22: Handshake 82 | }) 83 | ) 84 | 85 | ECPointFormat = Struct( 86 | "ec_point_format", 87 | UBInt8("ec_point_format_length"), 88 | Array(lambda ctx: ctx.ec_point_format_length, UBInt8("ec_point_format")) 89 | ) 90 | 91 | ECCurves = Struct( 92 | "ec_curves", 93 | UBInt16("ec_curves_length"), 94 | Array(lambda ctx: ctx.ec_curves_length // 2, UBInt16("named_curves")) 95 | ) 96 | 97 | ServerName = Struct( 98 | "server_name", 99 | UBInt16("server_name_list_length"), 100 | UBInt8("name_type"), 101 | UBInt16("server_name_length"), 102 | Bytes("server_name", lambda ctx: ctx.server_name_length) 103 | ) 104 | 105 | Extension = Struct( 106 | "extension", 107 | UBInt16("extension_type"), 108 | UBInt16("extension_length"), 109 | Switch("extension_struct", lambda ctx: ctx.extension_type, { 110 | 0: ServerName, 111 | 10: ECCurves, 112 | 11: ECPointFormat 113 | }) 114 | ) 115 | -------------------------------------------------------------------------------- /tlsenum/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | import socket 4 | 5 | import click 6 | 7 | from construct import UBInt16 8 | 9 | from tlsenum.parse_hello import ( 10 | ClientHello, Extensions, HandshakeFailure, ProtocolVersionFailure, 11 | ServerHello, construct_sslv2_client_hello 12 | ) 13 | from tlsenum.mappings import ( 14 | CipherSuites, ECCurves, ECPointFormat, TLSProtocolVersion 15 | ) 16 | 17 | CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"]) 18 | 19 | 20 | def send_client_hello(host, port, data): 21 | """ 22 | Sends a ClientHello message in bytes. 23 | 24 | Returns a ServerHello message in bytes 25 | 26 | """ 27 | try: 28 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 29 | s.connect((host, port)) 30 | s.send(data) 31 | 32 | server_hello = s.recv(5) 33 | 34 | # This is to handle the case where the server fails 35 | # to respond instead of a returning a handshake failure. 36 | if len(server_hello) == 0: 37 | raise HandshakeFailure() 38 | 39 | server_hello += s.recv(UBInt16("length").parse(server_hello[3:5])) 40 | 41 | return server_hello 42 | 43 | except socket.error: 44 | raise HandshakeFailure() 45 | 46 | 47 | def send_sslv2_client_hello(host, port): 48 | """ 49 | Sends a SSLv2 ClientHello message in bytes. 50 | 51 | If server supports SSLv2, returns None. Else raise a HandshakeFailure(). 52 | 53 | """ 54 | data = construct_sslv2_client_hello() 55 | 56 | try: 57 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 58 | s.connect((host, port)) 59 | s.send(data) 60 | 61 | server_hello = s.recv(3) 62 | 63 | if len(server_hello) == 0: 64 | raise HandshakeFailure() 65 | 66 | if server_hello[2] == 4: 67 | pass 68 | else: 69 | raise HandshakeFailure() 70 | 71 | except socket.error: 72 | raise HandshakeFailure() 73 | 74 | 75 | @click.command(context_settings=CONTEXT_SETTINGS) 76 | @click.argument("host", type=click.STRING) 77 | @click.argument("port", type=click.INT) 78 | def cli(host, port): 79 | """ 80 | A command line tool to enumerate TLS cipher-suites supported by a server. 81 | 82 | """ 83 | cipher_suites_list = [i.name for i in CipherSuites] 84 | 85 | extension = Extensions() 86 | extension.sni = host 87 | extension.ec_curves = [i.name for i in ECCurves] 88 | extension.ec_point_format = [i.name for i in ECPointFormat] 89 | 90 | client_hello = ClientHello() 91 | client_hello.deflate = False 92 | client_hello.extensions = extension.build() 93 | client_hello.cipher_suites = cipher_suites_list 94 | 95 | supported_tls_versions = [] 96 | 97 | try: 98 | send_sslv2_client_hello(host, port) 99 | supported_tls_versions.append("2.0") 100 | except HandshakeFailure: 101 | pass 102 | 103 | for i in TLSProtocolVersion: 104 | client_hello.protocol_version = i 105 | try: 106 | server_hello = send_client_hello(host, port, client_hello.build()) 107 | server_hello = ServerHello.parse_server_hello(server_hello) 108 | except HandshakeFailure: 109 | continue 110 | 111 | except ProtocolVersionFailure: 112 | continue 113 | 114 | supported_tls_versions.append(server_hello.protocol_version) 115 | 116 | supported_tls_versions = sorted( 117 | list(set(supported_tls_versions)), 118 | key=lambda x: 0 if x == "2.0" else TLSProtocolVersion.index(x) + 1 119 | ) 120 | 121 | print("TLS Versions supported by server: {0}".format( 122 | ", ".join(supported_tls_versions) 123 | )) 124 | 125 | client_hello.protocol_version = supported_tls_versions[-1] 126 | client_hello.deflate = True 127 | 128 | try: 129 | server_hello = send_client_hello(host, port, client_hello.build()) 130 | server_hello = ServerHello.parse_server_hello(server_hello) 131 | except HandshakeFailure: 132 | pass 133 | 134 | print("Deflate compression: {0}".format( 135 | "Yes" if server_hello.deflate else "No" 136 | )) 137 | 138 | client_hello.deflate = False 139 | 140 | supported_cipher_suites = [] 141 | 142 | print("Supported Cipher suites in order of priority: ") 143 | 144 | while True: 145 | client_hello.cipher_suites = cipher_suites_list 146 | try: 147 | server_hello = send_client_hello(host, port, client_hello.build()) 148 | server_hello = ServerHello.parse_server_hello(server_hello) 149 | except HandshakeFailure: 150 | break 151 | 152 | supported_cipher_suites.append(server_hello.cipher_suite) 153 | cipher_suites_list.remove(server_hello.cipher_suite) 154 | 155 | for i in supported_cipher_suites: 156 | print(i) 157 | -------------------------------------------------------------------------------- /tests/test_parse_hello.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | import pytest 4 | 5 | from tlsenum.parse_hello import ( 6 | ClientHello, Extensions, HandshakeFailure, ServerHello 7 | ) 8 | 9 | 10 | class TestClientHello(object): 11 | @pytest.mark.parametrize("version_string,protocol_minor", [ 12 | ("3.0", 0), ("1.0", 1), ("1.1", 2), ("1.2", 3) 13 | ]) 14 | def test_protocol_version(self, version_string, protocol_minor): 15 | msg = ClientHello() 16 | msg.protocol_version = version_string 17 | assert msg._protocol_minor == protocol_minor 18 | assert msg.protocol_version == version_string 19 | 20 | @pytest.mark.parametrize("deflate,result", [ 21 | (True, [1, 0]), (False, [0]) 22 | ]) 23 | def test_compression_method(self, deflate, result): 24 | msg = ClientHello() 25 | msg.deflate = deflate 26 | assert msg._compression_method == result 27 | assert msg.deflate is deflate 28 | 29 | def test_cipher_suites(self): 30 | msg = ClientHello() 31 | msg.cipher_suites = ["TLS_NULL_WITH_NULL_NULL"] 32 | assert msg.cipher_suites == ["TLS_NULL_WITH_NULL_NULL"] 33 | 34 | def test_get_bytes_from_cipher_suites(self): 35 | msg = ClientHello() 36 | assert msg._get_bytes_from_cipher_suites( 37 | ["TLS_NULL_WITH_NULL_NULL", "TLS_RSA_WITH_NULL_MD5"] 38 | ) == [0, 1] 39 | 40 | def test_extensions(self): 41 | msg = ClientHello() 42 | msg.extensions = b"mock" 43 | assert msg.extensions == b"mock" 44 | 45 | def test_build(self, monkeypatch): 46 | def mock_urandom(len): 47 | return ( 48 | b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 49 | b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 50 | ) 51 | 52 | monkeypatch.setattr("time.time", lambda: 0) 53 | monkeypatch.setattr("os.urandom", mock_urandom) 54 | 55 | msg = ClientHello() 56 | msg.protocol_version = "1.2" 57 | msg.deflate = False 58 | msg.cipher_suites = ["TLS_RSA_WITH_NULL_MD5"] 59 | msg.extensions = b"" 60 | 61 | assert msg.build() == ( 62 | b"\x16" 63 | b"\x03\x03" 64 | b"\x00\x2F" 65 | b"\x01" 66 | b"\x00\x00\x2B" 67 | b"\x03\x03" 68 | b"\x00\x00\x00\x00" 69 | b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 70 | b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 71 | b"\x00" 72 | b"\x00\x02\x00\x01" 73 | b"\x01\x00" 74 | b"\x00\x00" 75 | ) 76 | 77 | 78 | class TestExtensions(object): 79 | def test_ec_point_format(self): 80 | extension = Extensions() 81 | extension.ec_point_format = [ 82 | "ansiX962_compressed_prime", 83 | "uncompressed", 84 | "ansiX962_compressed_char2" 85 | ] 86 | 87 | assert extension.ec_point_format == [ 88 | "ansiX962_compressed_prime", 89 | "uncompressed", 90 | "ansiX962_compressed_char2" 91 | ] 92 | 93 | assert extension.build() == b"\x00\x0B\x00\x04\x03\x01\x00\x02" 94 | 95 | def test_get_bytes_from_ec_point_format(self): 96 | extension = Extensions() 97 | assert extension._get_bytes_from_ec_point_format([ 98 | "ansiX962_compressed_prime", 99 | "uncompressed", 100 | "ansiX962_compressed_char2" 101 | ]) == [1, 0, 2] 102 | 103 | def test_ec_curves(self): 104 | extension = Extensions() 105 | extension.ec_curves = ["sect163k1", "sect163r1", "sect163r2"] 106 | assert extension.ec_curves == ["sect163k1", "sect163r1", "sect163r2"] 107 | assert extension.build() == ( 108 | b"\x00\x0A\x00\x08\x00\x06\x00\x01\x00\x02\x00\x03" 109 | ) 110 | 111 | def test_get_bytes_from_ec_curves(self): 112 | extension = Extensions() 113 | assert extension._get_bytes_from_ec_curves([ 114 | "sect163k1", "sect163r1", "sect163r2" 115 | ]) == [1, 2, 3] 116 | 117 | def test_sni_extension(self): 118 | extension = Extensions() 119 | extension.sni = "ayrx.me" 120 | assert extension.sni == "ayrx.me" 121 | assert extension.build() == ( 122 | b"\x00\x00\x00\x0C\x00\x0A\x00\x00\x07\x61\x79\x72\x78\x2E\x6D\x65" 123 | ) 124 | 125 | 126 | class TestServerHello(object): 127 | def test_parse_server_hello(self): 128 | deflate_no = ( 129 | b"\x16\x03\x03\x00\x2A\x02\x00\x00\x26\x03\x03\xB5\xA4\x22\x01\x18" 130 | b"\xC5\x71\x41\x97\x6D\xC7\x06\x14\xC0\xE5\x78\x7A\xF3\x1D\x4E\x56" 131 | b"\x98\xCC\x7A\x37\xAE\x6F\x1D\xC6\xF0\x78\x68\x00\xC0\x2F\x00" 132 | ) 133 | 134 | server_hello = ServerHello.parse_server_hello(deflate_no) 135 | assert server_hello.protocol_version == "1.2" 136 | assert server_hello.deflate is False 137 | assert server_hello.cipher_suite == ( 138 | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" 139 | ) 140 | 141 | deflate_yes = ( 142 | b"\x16\x03\x03\x00\x2A\x02\x00\x00\x26\x03\x03\xB5\xA4\x22\x01\x18" 143 | b"\xC5\x71\x41\x97\x6D\xC7\x06\x14\xC0\xE5\x78\x7A\xF3\x1D\x4E\x56" 144 | b"\x98\xCC\x7A\x37\xAE\x6F\x1D\xC6\xF0\x78\x68\x00\xC0\x2F\x01" 145 | ) 146 | 147 | server_hello = ServerHello.parse_server_hello(deflate_yes) 148 | assert server_hello.protocol_version == "1.2" 149 | assert server_hello.deflate is True 150 | assert server_hello.cipher_suite == ( 151 | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" 152 | ) 153 | 154 | def test_parse_alert(self): 155 | handshake_failure_alert_msg = b"\x15\x03\x03\x00\x02\x02\x28" 156 | with pytest.raises(HandshakeFailure): 157 | ServerHello.parse_server_hello(handshake_failure_alert_msg) 158 | 159 | close_notify_alert_msg = b"\x15\x03\x03\x00\x02\x02\x00" 160 | with pytest.raises(ValueError): 161 | ServerHello.parse_server_hello(close_notify_alert_msg) 162 | -------------------------------------------------------------------------------- /tlsenum/parse_hello.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | import time 4 | import os 5 | 6 | import construct 7 | import idna 8 | 9 | from tlsenum import hello_constructs 10 | from tlsenum.mappings import ( 11 | CipherSuites, ECCurves, ECPointFormat, TLSProtocolVersion 12 | ) 13 | 14 | 15 | class ClientHello(object): 16 | 17 | @property 18 | def protocol_version(self): 19 | return self._protocol_version 20 | 21 | @protocol_version.setter 22 | def protocol_version(self, protocol_version): 23 | assert protocol_version in ["3.0", "1.0", "1.1", "1.2"] 24 | 25 | self._protocol_version = protocol_version 26 | self._protocol_minor = TLSProtocolVersion.index(protocol_version) 27 | 28 | @property 29 | def cipher_suites(self): 30 | return self._cipher_suites 31 | 32 | @cipher_suites.setter 33 | def cipher_suites(self, cipher_suites): 34 | self._cipher_suites = cipher_suites 35 | 36 | @property 37 | def deflate(self): 38 | return self._deflate 39 | 40 | @deflate.setter 41 | def deflate(self, deflate): 42 | self._deflate = deflate 43 | if deflate: 44 | self._compression_method = [1, 0] 45 | else: 46 | self._compression_method = [0] 47 | 48 | @property 49 | def extensions(self): 50 | return self._extensions 51 | 52 | @extensions.setter 53 | def extensions(self, value): 54 | self._extensions = value 55 | 56 | def build(self): 57 | protocol_version = construct.Container( 58 | major=3, minor=self._protocol_minor 59 | ) 60 | 61 | random = construct.Container( 62 | gmt_unix_time=int(time.time()), random_bytes=os.urandom(28) 63 | ) 64 | 65 | session_id = construct.Container( 66 | length=0, session_id=b"" 67 | ) 68 | 69 | ciphers = construct.Container( 70 | length=len(self._cipher_suites) * 2, 71 | cipher_suites=self._get_bytes_from_cipher_suites( 72 | self._cipher_suites 73 | ) 74 | ) 75 | 76 | compression_method = construct.Container( 77 | length=len(self._compression_method), 78 | compression_methods=self._compression_method 79 | ) 80 | 81 | client_hello = construct.Container( 82 | version=protocol_version, random=random, session_id=session_id, 83 | cipher_suites=ciphers, compression_methods=compression_method, 84 | extensions_length=len(self._extensions), 85 | extensions_bytes=self._extensions 86 | ) 87 | 88 | handshake = construct.Container( 89 | handshake_type=1, 90 | length=len(hello_constructs.ClientHello.build(client_hello)), 91 | handshake_struct=client_hello 92 | ) 93 | 94 | return hello_constructs.TLSPlaintext.build( 95 | construct.Container( 96 | content_type=0x16, version=protocol_version, 97 | length=len(hello_constructs.Handshake.build(handshake)), 98 | content=handshake 99 | ) 100 | ) 101 | 102 | def _get_bytes_from_cipher_suites(self, cipher_suites): 103 | return [CipherSuites[i].value for i in cipher_suites] 104 | 105 | 106 | class Extensions(object): 107 | 108 | def __init__(self): 109 | self._ec_point_format = None 110 | self._ec_curves = None 111 | self._hostname = None 112 | 113 | @property 114 | def ec_point_format(self): 115 | return self._ec_point_format 116 | 117 | @ec_point_format.setter 118 | def ec_point_format(self, formats): 119 | self._ec_point_format = formats 120 | 121 | @property 122 | def ec_curves(self): 123 | return self._ec_curves 124 | 125 | @ec_curves.setter 126 | def ec_curves(self, curves): 127 | self._ec_curves = curves 128 | 129 | @property 130 | def sni(self): 131 | return self._hostname 132 | 133 | @sni.setter 134 | def sni(self, hostname): 135 | self._hostname = hostname 136 | 137 | def build(self): 138 | ret = b"" 139 | 140 | if self._ec_point_format is not None: 141 | ec_point_format_struct = construct.Container( 142 | ec_point_format_length=len(self._ec_point_format), 143 | ec_point_format=self._get_bytes_from_ec_point_format( 144 | self._ec_point_format 145 | ) 146 | ) 147 | ret += hello_constructs.Extension.build( 148 | construct.Container( 149 | extension_type=11, 150 | extension_length=len(hello_constructs.ECPointFormat.build( 151 | ec_point_format_struct 152 | )), 153 | extension_struct=ec_point_format_struct 154 | ) 155 | ) 156 | 157 | if self._ec_curves is not None: 158 | ec_curves_struct = construct.Container( 159 | ec_curves_length=len(self._ec_curves) * 2, 160 | named_curves=self._get_bytes_from_ec_curves( 161 | self._ec_curves 162 | ) 163 | ) 164 | ret += hello_constructs.Extension.build( 165 | construct.Container( 166 | extension_type=10, 167 | extension_length=len(hello_constructs.ECCurves.build( 168 | ec_curves_struct 169 | )), 170 | extension_struct=ec_curves_struct 171 | ) 172 | ) 173 | 174 | if self._hostname is not None: 175 | encoded_hostname = idna.encode(self._hostname) 176 | sni_struct = construct.Container( 177 | server_name_list_length=len(encoded_hostname) + 3, 178 | name_type=0, 179 | server_name_length=len(encoded_hostname), 180 | server_name=encoded_hostname 181 | ) 182 | ret += hello_constructs.Extension.build( 183 | construct.Container( 184 | extension_type=0, 185 | extension_length=len(hello_constructs.ServerName.build( 186 | sni_struct 187 | )), 188 | extension_struct=sni_struct 189 | ) 190 | ) 191 | 192 | return ret 193 | 194 | def _get_bytes_from_ec_point_format(self, ec_point_format): 195 | return [ECPointFormat[i].value for i in ec_point_format] 196 | 197 | def _get_bytes_from_ec_curves(self, ec_curves): 198 | return [ECCurves[i].value for i in ec_curves] 199 | 200 | 201 | class ServerHello(object): 202 | 203 | def __init__(self, protocol_version, cipher_suite, deflate): 204 | self._protocol_version = protocol_version 205 | self._cipher_suite = cipher_suite 206 | self._deflate = deflate 207 | 208 | @property 209 | def protocol_version(self): 210 | return self._protocol_version 211 | 212 | @property 213 | def cipher_suite(self): 214 | return self._cipher_suite 215 | 216 | @property 217 | def deflate(self): 218 | return self._deflate 219 | 220 | @classmethod 221 | def parse_server_hello(cls, data): 222 | server_hello = hello_constructs.TLSPlaintext.parse(data) 223 | 224 | if server_hello.content_type == 21: 225 | if server_hello.content.alert_description == 40: 226 | raise HandshakeFailure() 227 | 228 | elif server_hello.content.alert_description == 70: 229 | raise ProtocolVersionFailure() 230 | 231 | else: 232 | raise ValueError("Unknown TLS Alert, type {0}".format( 233 | server_hello.content.alert_description 234 | )) 235 | 236 | protocol_minor = server_hello.content.handshake_struct.version.minor 237 | 238 | protocol_version = TLSProtocolVersion[protocol_minor] 239 | 240 | cipher_suite = CipherSuites( 241 | server_hello.content.handshake_struct.cipher_suite 242 | ).name 243 | 244 | if server_hello.content.handshake_struct.compression_method == 1: 245 | deflate = True 246 | else: 247 | deflate = False 248 | 249 | return cls(protocol_version, cipher_suite, deflate) 250 | 251 | 252 | class HandshakeFailure(Exception): 253 | pass 254 | 255 | 256 | class ProtocolVersionFailure(Exception): 257 | pass 258 | 259 | 260 | def construct_sslv2_client_hello(): # pragma: no cover 261 | """ 262 | Returns a SSLv2 ClientHello message in bytes. 263 | 264 | This is a quick and dirty function to return a SSLv2 ClientHello with all 265 | 7 specified cipher suites. I don't really want to enumerate the supported 266 | SSLv2 cipher suites so this doesn't have to be flexible... 267 | 268 | This function does not require test coverage because I am simply returning 269 | bytes constructed from a fix list. 270 | 271 | """ 272 | return bytes([ 273 | 0x80, 0x2e, # Length of record 274 | 0x01, # Handshake Type (0x01 for ClientHello) 275 | 0x00, 0x02, # SSL Version Identifier (0x0002 for SSLv2) 276 | 0x00, 0x15, # Length of cipher suites list 277 | 0x00, 0x00, # Session ID Length 278 | 0x00, 0x10, # Challenge Length 279 | # Cipher suites list 280 | 0x01, 0x00, 0x80, 281 | 0x02, 0x00, 0x80, 282 | 0x03, 0x00, 0x80, 283 | 0x04, 0x00, 0x80, 284 | 0x05, 0x00, 0x80, 285 | 0x06, 0x00, 0x40, 286 | 0x07, 0x00, 0xc0, 287 | # Challenge 288 | 0x53, 0x43, 0x5b, 0x90, 0x9d, 0x9b, 0x72, 0x0b, 289 | 0xbc, 0x0c, 0xbc, 0x2b, 0x92, 0xa8, 0x48, 0x97, 290 | ]) 291 | -------------------------------------------------------------------------------- /tlsenum/mappings.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function 2 | 3 | from enum import Enum 4 | 5 | 6 | class CipherSuites(Enum): 7 | TLS_NULL_WITH_NULL_NULL = 0x0000 8 | TLS_RSA_WITH_NULL_MD5 = 0x0001 9 | TLS_RSA_WITH_NULL_SHA = 0x0002 10 | TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003 11 | TLS_RSA_WITH_RC4_128_MD5 = 0x0004 12 | TLS_RSA_WITH_RC4_128_SHA = 0x0005 13 | TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006 14 | TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007 15 | TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008 16 | TLS_RSA_WITH_DES_CBC_SHA = 0x0009 17 | TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A 18 | TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B 19 | TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C 20 | TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D 21 | TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E 22 | TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F 23 | TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010 24 | TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011 25 | TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012 26 | TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013 27 | TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014 28 | TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015 29 | TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016 30 | TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017 31 | TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018 32 | TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019 33 | TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A 34 | TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B 35 | TLS_KRB5_WITH_DES_CBC_SHA = 0x001E 36 | TLS_KRB5_WITH_3DES_EDE_CBC_SHA = 0x001F 37 | TLS_KRB5_WITH_RC4_128_SHA = 0x0020 38 | TLS_KRB5_WITH_IDEA_CBC_SHA = 0x0021 39 | TLS_KRB5_WITH_DES_CBC_MD5 = 0x0022 40 | TLS_KRB5_WITH_3DES_EDE_CBC_MD5 = 0x0023 41 | TLS_KRB5_WITH_RC4_128_MD5 = 0x0024 42 | TLS_KRB5_WITH_IDEA_CBC_MD5 = 0x0025 43 | TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA = 0x0026 44 | TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA = 0x0027 45 | TLS_KRB5_EXPORT_WITH_RC4_40_SHA = 0x0028 46 | TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 = 0x0029 47 | TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 = 0x002A 48 | TLS_KRB5_EXPORT_WITH_RC4_40_MD5 = 0x002B 49 | TLS_PSK_WITH_NULL_SHA = 0x002C 50 | TLS_DHE_PSK_WITH_NULL_SHA = 0x002D 51 | TLS_RSA_PSK_WITH_NULL_SHA = 0x002E 52 | TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F 53 | TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030 54 | TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031 55 | TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032 56 | TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033 57 | TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034 58 | TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035 59 | TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036 60 | TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037 61 | TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038 62 | TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039 63 | TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A 64 | TLS_RSA_WITH_NULL_SHA256 = 0x003B 65 | TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C 66 | TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D 67 | TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E 68 | TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F 69 | TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040 70 | TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041 71 | TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042 72 | TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043 73 | TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044 74 | TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045 75 | TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046 76 | TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067 77 | TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068 78 | TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069 79 | TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A 80 | TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B 81 | TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C 82 | TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D 83 | TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084 84 | TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085 85 | TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086 86 | TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087 87 | TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088 88 | TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089 89 | TLS_PSK_WITH_RC4_128_SHA = 0x008A 90 | TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B 91 | TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C 92 | TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D 93 | TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E 94 | TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F 95 | TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090 96 | TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091 97 | TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092 98 | TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093 99 | TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094 100 | TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095 101 | TLS_RSA_WITH_SEED_CBC_SHA = 0x0096 102 | TLS_DH_DSS_WITH_SEED_CBC_SHA = 0x0097 103 | TLS_DH_RSA_WITH_SEED_CBC_SHA = 0x0098 104 | TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099 105 | TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A 106 | TLS_DH_anon_WITH_SEED_CBC_SHA = 0x009B 107 | TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C 108 | TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D 109 | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E 110 | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F 111 | TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0 112 | TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1 113 | TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2 114 | TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3 115 | TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4 116 | TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5 117 | TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6 118 | TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7 119 | TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8 120 | TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9 121 | TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA 122 | TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB 123 | TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC 124 | TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD 125 | TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE 126 | TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF 127 | TLS_PSK_WITH_NULL_SHA256 = 0x00B0 128 | TLS_PSK_WITH_NULL_SHA384 = 0x00B1 129 | TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2 130 | TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3 131 | TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4 132 | TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5 133 | TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6 134 | TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7 135 | TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8 136 | TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9 137 | TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BA 138 | TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BB 139 | TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BC 140 | TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BD 141 | TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BE 142 | TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BF 143 | TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C0 144 | TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C1 145 | TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C2 146 | TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3 147 | TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4 148 | TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5 149 | TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF 150 | TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001 151 | TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002 152 | TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003 153 | TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004 154 | TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005 155 | TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006 156 | TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007 157 | TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008 158 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009 159 | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A 160 | TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B 161 | TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C 162 | TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D 163 | TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E 164 | TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F 165 | TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010 166 | TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011 167 | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012 168 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013 169 | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014 170 | TLS_ECDH_anon_WITH_NULL_SHA = 0xC015 171 | TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016 172 | TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017 173 | TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018 174 | TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019 175 | TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A 176 | TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B 177 | TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C 178 | TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D 179 | TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E 180 | TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F 181 | TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020 182 | TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021 183 | TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022 184 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023 185 | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024 186 | TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025 187 | TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026 188 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027 189 | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028 190 | TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029 191 | TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A 192 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B 193 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C 194 | TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D 195 | TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E 196 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F 197 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030 198 | TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031 199 | TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032 200 | TLS_ECDHE_PSK_WITH_RC4_128_SHA = 0xC033 201 | TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 0xC034 202 | TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035 203 | TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036 204 | TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0xC037 205 | TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 0xC038 206 | TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039 207 | TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A 208 | TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B 209 | TLS_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC03C 210 | TLS_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC03D 211 | TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 = 0xC03E 212 | TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 = 0xC03F 213 | TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC040 214 | TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC041 215 | TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 = 0xC042 216 | TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 = 0xC043 217 | TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC044 218 | TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC045 219 | TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 = 0xC046 220 | TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 = 0xC047 221 | TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 = 0xC048 222 | TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 = 0xC049 223 | TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 = 0xC04A 224 | TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 = 0xC04B 225 | TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC04C 226 | TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC04D 227 | TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC04E 228 | TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC04F 229 | TLS_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC050 230 | TLS_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC051 231 | TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC052 232 | TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC053 233 | TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC054 234 | TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC055 235 | TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 = 0xC056 236 | TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 = 0xC057 237 | TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 = 0xC058 238 | TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 = 0xC059 239 | TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 = 0xC05A 240 | TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 = 0xC05B 241 | TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 = 0xC05C 242 | TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 = 0xC05D 243 | TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 = 0xC05E 244 | TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 = 0xC05F 245 | TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC060 246 | TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC061 247 | TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC062 248 | TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC063 249 | TLS_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC064 250 | TLS_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC065 251 | TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC066 252 | TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC067 253 | TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC068 254 | TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC069 255 | TLS_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06A 256 | TLS_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06B 257 | TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06C 258 | TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06D 259 | TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06E 260 | TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06F 261 | TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC070 262 | TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC071 263 | TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC072 264 | TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC073 265 | TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC074 266 | TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC075 267 | TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC076 268 | TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC077 269 | TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC078 270 | TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC079 271 | TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07A 272 | TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07B 273 | TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07C 274 | TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07D 275 | TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07E 276 | TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07F 277 | TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC080 278 | TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC081 279 | TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC082 280 | TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC083 281 | TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 = 0xC084 282 | TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 = 0xC085 283 | TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC086 284 | TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC087 285 | TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC088 286 | TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC089 287 | TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08A 288 | TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08B 289 | TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08C 290 | TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08D 291 | TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08E 292 | TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08F 293 | TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC090 294 | TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC091 295 | TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC092 296 | TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC093 297 | TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC094 298 | TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC095 299 | TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC096 300 | TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC097 301 | TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC098 302 | TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC099 303 | TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC09A 304 | TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC09B 305 | TLS_RSA_WITH_AES_128_CCM = 0xC09C 306 | TLS_RSA_WITH_AES_256_CCM = 0xC09D 307 | TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E 308 | TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F 309 | TLS_RSA_WITH_AES_128_CCM_8 = 0xC0A0 310 | TLS_RSA_WITH_AES_256_CCM_8 = 0xC0A1 311 | TLS_DHE_RSA_WITH_AES_128_CCM_8 = 0xC0A2 312 | TLS_DHE_RSA_WITH_AES_256_CCM_8 = 0xC0A3 313 | TLS_PSK_WITH_AES_128_CCM = 0xC0A4 314 | TLS_PSK_WITH_AES_256_CCM = 0xC0A5 315 | TLS_DHE_PSK_WITH_AES_128_CCM = 0xC0A6 316 | TLS_DHE_PSK_WITH_AES_256_CCM = 0xC0A7 317 | TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8 318 | TLS_PSK_WITH_AES_256_CCM_8 = 0xC0A9 319 | TLS_PSK_DHE_WITH_AES_128_CCM_8 = 0xC0AA 320 | TLS_PSK_DHE_WITH_AES_256_CCM_8 = 0xC0AB 321 | TLS_ECDHE_ECDSA_WITH_AES_128_CCM = 0xC0AC 322 | TLS_ECDHE_ECDSA_WITH_AES_256_CCM = 0xC0AD 323 | TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE 324 | TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xC0AF 325 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14 326 | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13 327 | 328 | 329 | class ECPointFormat(Enum): 330 | uncompressed = 0 331 | ansiX962_compressed_prime = 1 332 | ansiX962_compressed_char2 = 2 333 | 334 | 335 | class ECCurves(Enum): 336 | sect163k1 = 1 337 | sect163r1 = 2 338 | sect163r2 = 3 339 | sect193r1 = 4 340 | sect193r2 = 5 341 | sect233k1 = 6 342 | sect233r1 = 7 343 | sect239k1 = 8 344 | sect283k1 = 9 345 | sect283r1 = 10 346 | sect409k1 = 11 347 | sect409r1 = 12 348 | sect571k1 = 13 349 | sect571r1 = 14 350 | secp160k1 = 15 351 | secp160r1 = 16 352 | secp160r2 = 17 353 | secp192k1 = 18 354 | secp192r1 = 19 355 | secp224k1 = 20 356 | secp224r1 = 21 357 | secp256k1 = 22 358 | secp256r1 = 23 359 | secp384r1 = 24 360 | secp521r1 = 25 361 | brainpoolP256r1 = 26 362 | brainpoolP384r1 = 27 363 | brainpoolP512r1 = 28 364 | 365 | 366 | TLSProtocolVersion = ("3.0", "1.0", "1.1", "1.2") 367 | --------------------------------------------------------------------------------