Compare commits

...

8 Commits

30 changed files with 2910 additions and 1411 deletions

2
.gitignore vendored
View File

@ -1,3 +1 @@
/build/
/TODO
/tmux.sh

20
.reuse/dep5 Normal file
View File

@ -0,0 +1,20 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: TLS Client Hello Mirror
Upstream-Contact: nervuri <https://nervuri.net/contact>
Source: https://tlsprivacy.nervuri.net/
Files: go.sum
Copyright: 2022-2023 nervuri <https://nervuri.net/contact>
License: BSD-3-Clause
Files: .gitignore
Copyright: 2022-2023 nervuri <https://nervuri.net/contact>
License: BSD-3-Clause
Files: *.gmi
Copyright: 2022-2023 nervuri <https://nervuri.net/contact>
License: BSD-3-Clause
Files: clienthello/*.csv
Copyright: IANA and IETF
License: CC0-1.0

82
DOC.md Normal file
View File

@ -0,0 +1,82 @@
<!--
SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
SPDX-License-Identifier: BSD-3-Clause
-->
# API Documentation
The API is largely stable - fields may be added, but existing fields will not be modified or removed.
There are two JSON endpoints:
* [/json/v1](https://tlsprivacy.nervuri.net/json/v1) - basic
* [/json/v2](https://tlsprivacy.nervuri.net/json/v2) - detailed
The `v2` endpoint expands numeric identifiers (of TLS versions, cipher suites, signature algorithms, etc) into objects containing more information. The `name` field in these objects is taken from [the IANA registries](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml); note that these names may differ from those used in TLS libraries ([example](https://ciphersuite.info/cs/TLS_DHE_DSS_WITH_AES_256_CBC_SHA256/)).
The `v1` endpoint is not deprecated, it is a lighter version of `v2`. `v1` is a better fit for CI tests, while `v2` might be preferable on the user-facing side, where you would rather use names instead of numeric identifiers.
The outline of the `v1` output is:
```
{
"client_hello": {
"raw": "...",
"record_header_tls_version": 769,
"client_tls_version": 771,
"random": "...",
"session_id": "...",
"cipher_suites": [
...
],
"compression_methods": [
0
],
"extensions": [
...
],
"highlights": {
"gmt_unix_time": 3563154493,
"secure_renegotiation_support": true,
"ocsp_stapling_support": false,
"sct_support": false,
"ja3": "...",
"ja3_md5": "..."
}
},
"connection_info": {
"tls_version": 772,
"cipher_suite": 4867,
"session_resumed": false,
"alpn_negotiated_protocol": "http/1.1"
}
}
```
The `client_hello` object contains a `highlights` object, which includes:
* the deprecated `gmt_unix_time` value extracted from the client random, which [should NOT](https://datatracker.ietf.org/doc/html/draft-mathewson-no-gmtunixtime) represent the current timestamp anymore;
* boolean values that show whether the client supports secure renegotiation, OCSP stapling and SCTs (Signed Certificate Timestamps);
* the JA3 fingerprint, both its expanded form and its MD5 hash.
Aside from `client_hello`, there is a `connection_info` object containing the TLS version, cipher suite and ALPN protocol that were negotiated for the connection, as well as a boolean value that shows whether the TLS session was resumed.
In `v2` numeric identifiers are expanded, for example `"cipher_suite": 4867` becomes:
```
"cipher_suite": {
"code": 4867,
"hex_code": "1303",
"name": "TLS_CHACHA20_POLY1305_SHA256"
},
```
More info (such as whether a cipher suite is recommended or not) may be added later.
In both JSON endpoints, raw byte values are represented as hexadecimal strings.
IANA-assigned codes for TLS parameters and extensions are documented at:
* [TLS parameters](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml)
* [TLS extensions](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml)

View File

@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
SPDX-License-Identifier: BSD-3-Clause
-->
# Setup
## Install
@ -26,7 +32,7 @@ Generate TLS certificate:
# CA-signed:
certbot certonly --webroot -w /var/www/example.com -d example.com
# or self-signed:
openssl req -new -subj "/CN=example.com" -x509 -days 36500 -nodes -out cert.pem -keyout privkey.pem
openssl req -new -subj "/CN=example.com" -addext "subjectAltName = DNS:example.com" -x509 -days 36500 -nodes -out cert.pem -keyout privkey.pem
```
Run on port 1965:
@ -49,7 +55,7 @@ After=network.target
[Service]
Type=simple
Restart=always
ExecStart=client-hello-mirror -u www-data -c /etc/letsencrypt/live/example.org/fullchain.pem -k /etc/letsencrypt/live/example.org/privkey.pem :443 2>/var/log/client-hello-mirror-error.log
ExecStart=client-hello-mirror -u www-data -c /etc/letsencrypt/live/example.com/fullchain.pem -k /etc/letsencrypt/live/example.com/privkey.pem :443 2>/var/log/client-hello-mirror-error.log
[Install]
WantedBy=multi-user.target

View File

@ -1,661 +1,28 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.
Copyright (c) 2022-2023 nervuri <https://nervuri.net/contact>.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

11
LICENSES/BSD-3-Clause.txt Normal file
View File

@ -0,0 +1,11 @@
Copyright (c) <year> <owner>.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

121
LICENSES/CC0-1.0.txt Normal file
View File

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View File

@ -1,2 +1,19 @@
dev:
mkdir -p build && go build -o build/client-hello-mirror
# SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
#
# SPDX-License-Identifier: BSD-3-Clause
dev: check
mkdir -p build
go build -o build/client-hello-mirror
check:
golangci-lint run
#go vet
#go test
find . -name '*.html' -exec xmllint --noout {} \;
find . -name '*.html' -exec sh -c 'tidy -q -errors -access "{}" || ls "{}"' \;
reuse lint -q
run:
killall -9 client-hello-mirror || :
ls *.go */*.go | entr -nsr "make dev && build/client-hello-mirror -c build/cert.pem -k build/privkey.pem :4444"

View File

@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
SPDX-License-Identifier: BSD-3-Clause
-->
# TLS Client Hello Mirror
This test:
@ -7,28 +13,20 @@ This test:
* supports both HTTP and [Gemini](https://gemini.circumlunar.space/) on the same port;
* is [free as in freedom](https://www.gnu.org/philosophy/free-sw.en.html) and trivial to self-host.
The API is largely stable - fields may be added, but existing fields will not be modified or removed. IANA-assigned codes for TLS parameters and extensions are documented at:
* [TLS parameters](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml)
* [TLS extensions](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml)
Note that these lists do not include draft extensions and [GREASE](https://datatracker.ietf.org/doc/html/rfc8701) values. Missing values will be documented here as the project evolves.
## Installation
See [INSTALL.md](INSTALL.md).
## API documentation
This test exposes two JSON endpoints: [/json/v1 (basic)](https://tlsprivacy.nervuri.net/json/v1) and [/json/v2 (detailed)](https://tlsprivacy.nervuri.net/json/v2). See [DOC.md](DOC.md) for details.
## Roadmap
* HTML & gemtext front-end
* documentation
* detect client vulnerability to session [prolongation attacks](https://svs.informatik.uni-hamburg.de/publications/2018/2018-12-06-Sy-ACSAC-Tracking_Users_across_the_Web_via_TLS_Session_Resumption.pdf#page=3)
* support sessionID-based resumption (Go's `crypto/tls` library currently does not)
* support early data / 0-RTT (Go's `crypto/tls` library currently does not)
## License
[AGPL v3.0 or later](https://www.gnu.org/licenses/agpl-3.0.en.html). If you host a modified version, you must provide users access to its source code under the same license.
* support sessionID-based resumption (Go's `crypto/tls` library currently does not)
## Contributing

View File

@ -1,590 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Based on Go's crypto/tls library:
// https://github.com/golang/go/blob/master/src/crypto/tls/handshake_messages.go#L69
// https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/crypto/tls/handshake_messages.go;l=69
package main
import (
"crypto/md5"
"encoding/binary"
"encoding/hex"
"encoding/json"
"golang.org/x/crypto/cryptobyte"
"log"
"strconv"
"strings"
)
// TLS versions
const (
versionSSL30 = 0x0300 // 768
versionTLS10 = 0x0301 // 769
versionTLS11 = 0x0302 // 770
versionTLS12 = 0x0303 // 771
versionTLS13 = 0x0304 // 772
)
// TLS compression types
const (
compressionNone uint8 = 0
)
// TLS extension numbers
const (
extensionServerName uint16 = 0
extensionStatusRequest uint16 = 5
extensionSupportedGroups uint16 = 10 // elliptic_curves in TLS versions prior to 1.3, see RFC 8446, Section 4.2.7
extensionSupportedPointFormats uint16 = 11
extensionSignatureAlgorithms uint16 = 13
extensionALPN uint16 = 16
extensionSCT uint16 = 18
extensionPadding uint16 = 21
extensionEncryptThenMac uint16 = 22
extensionExtendedMasterSecret uint16 = 23
extensionCompressCertificate uint16 = 27
extensionSessionTicket uint16 = 35
extensionPreSharedKey uint16 = 41
extensionEarlyData uint16 = 42
extensionSupportedVersions uint16 = 43
extensionCookie uint16 = 44
extensionPSKModes uint16 = 45
extensionCertificateAuthorities uint16 = 47
extensionPostHandshakeAuth uint16 = 49
extensionSignatureAlgorithmsCert uint16 = 50
extensionKeyShare uint16 = 51
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionApplicationSettings uint16 = 17513 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
)
// TLS signaling cipher suite values
const (
scsvRenegotiation uint16 = 0x00ff
)
// TLS CertificateStatusType (RFC 3546)
const (
statusTypeOCSP uint8 = 1
)
// curveID is the type of a TLS identifier for an elliptic curve. See
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8.
//
// In TLS 1.3, this type is called NamedGroup, but at this time this library
// only supports Elliptic Curve based groups. See RFC 8446, Section 4.2.7.
type curveID uint16
const (
curveP256 curveID = 23
curveP384 curveID = 24
curveP521 curveID = 25
x25519 curveID = 29
)
// TLS 1.3 Key Share. See RFC 8446, Section 4.2.8.
type keyShare struct {
Group curveID `json:"group"`
Data byteSlice `json:"data"`
}
// TLS 1.3 PSK Identity. Can be a Session Ticket, or a reference to a saved
// session. See RFC 8446, Section 4.2.11.
type pskIdentity struct {
Identity byteSlice `json:"identity"`
ObfuscatedTicketAge uint32 `json:"obfuscated_ticket_age"`
}
// signatureScheme identifies a signature algorithm supported by TLS. See
// RFC 8446, Section 4.2.3.
type signatureScheme uint16
const (
// RSASSA-PKCS1-v1_5 algorithms.
PKCS1WithSHA256 signatureScheme = 0x0401
PKCS1WithSHA384 signatureScheme = 0x0501
PKCS1WithSHA512 signatureScheme = 0x0601
// RSASSA-PSS algorithms with public key OID rsaEncryption.
PSSWithSHA256 signatureScheme = 0x0804
PSSWithSHA384 signatureScheme = 0x0805
PSSWithSHA512 signatureScheme = 0x0806
// ECDSA algorithms. Only constrained to a specific curve in TLS 1.3.
ECDSAWithP256AndSHA256 signatureScheme = 0x0403
ECDSAWithP384AndSHA384 signatureScheme = 0x0503
ECDSAWithP521AndSHA512 signatureScheme = 0x0603
// Legacy signature and hash algorithms for TLS 1.2.
PKCS1WithSHA1 signatureScheme = 0x0201
ECDSAWithSHA1 signatureScheme = 0x0203
)
// Check if this is a GREASE value (RFC 8701)
func isGREASE(value uint16) bool {
// Values for: cipher suites, ALPN,
// extensions, named groups, signature algorithms and TLS versions:
greaseValues := [16]uint16{
0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a, 0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a,
0x8a8a, 0x9a9a, 0xaaaa, 0xbaba, 0xcaca, 0xdada, 0xeaea, 0xfafa,
}
// Values for PSK key exchange modes:
//greasePSKModes := [8]uint8{
// 0x0b, 0x2a, 0x49, 0x68, 0x87, 0xa6, 0xc5, 0xe4,
//}
// Run the check
for _, greaseValue := range greaseValues {
if value == greaseValue {
return true
}
}
return false
}
// readUint8LengthPrefixed acts like s.ReadUint8LengthPrefixed, but targets a
// []byte instead of a cryptobyte.String.
func readUint8LengthPrefixed(s *cryptobyte.String, out *[]byte) bool {
return s.ReadUint8LengthPrefixed((*cryptobyte.String)(out))
}
// readUint16LengthPrefixed acts like s.ReadUint16LengthPrefixed, but targets a
// []byte instead of a cryptobyte.String.
func readUint16LengthPrefixed(s *cryptobyte.String, out *[]byte) bool {
return s.ReadUint16LengthPrefixed((*cryptobyte.String)(out))
}
type byteSlice []byte
func (bs byteSlice) MarshalText() ([]byte, error) {
// Used in json.Marshal() to convert []byte to hex string.
return []byte(hex.EncodeToString(bs)), nil
}
type uint8Slice []uint8
func (numbers uint8Slice) MarshalJSON() ([]byte, error) {
// Used in json.Marshal() to convert []uint8 to array.
newSlice := make([]uint, len(numbers))
for i, n := range numbers {
newSlice[i] = uint(n)
}
return json.Marshal(newSlice)
}
type extensionData struct {
Raw byteSlice `json:"raw"`
ServerName string `json:"server_name,omitempty"`
StatusType uint8 `json:"status_type,omitempty"`
SupportedGroups []curveID `json:"supported_groups,omitempty"`
SupportedPointFormats uint8Slice `json:"supported_point_formats,omitempty"`
SupportedSignatureAlgorithms []signatureScheme `json:"supported_signature_algorithms,omitempty"`
RenegotiationInfo []byte `json:"renegotiation_info,omitempty"`
AlpnProtocols []string `json:"alpn_protocols,omitempty"`
SupportedVersions []uint16 `json:"supported_tls_versions,omitempty"`
Cookie byteSlice `json:"cookie,omitempty"`
KeyShares []keyShare `json:"key_shares,omitempty"`
PskModes uint8Slice `json:"psk_modes,omitempty"`
PskIdentities []pskIdentity `json:"psk_identities,omitempty"`
PskBinders []byteSlice `json:"psk_binders,omitempty"`
Length uint16 `json:"length,omitempty"` // padding
}
type extension struct {
Code uint16 `json:"code"`
Name string `json:"name"`
Data extensionData `json:"data"`
}
type highlights struct {
//SupportedTLSVersions []uint16
GmtUnixTime uint32 `json:"gmt_unix_time"` // first 4 bytes of client random
SecureRenegotiationSupport bool `json:"secure_renegotiation_support"`
OcspStaplingSupport bool `json:"ocsp_stapling_support"`
SctSupport bool `json:"sct_support"`
// Go's crypto/tls server does not support early data.
EarlyData bool `json:"-"` // don't include in JSON
JA3 string `json:"ja3"`
JA3MD5 byteSlice `json:"ja3_md5"`
}
type clientHelloMsg struct {
Raw byteSlice `json:"raw"`
RecordHeaderTLSVersion uint16 `json:"record_header_tls_version"` // TLSv1.0 (769)
TLSVersion uint16 `json:"client_tls_version"` // TLSv1.2 (771)
Random byteSlice `json:"random"`
SessionID byteSlice `json:"session_id"`
CipherSuites []uint16 `json:"cipher_suites"`
CompressionMethods uint8Slice `json:"compression_methods"`
Extensions []extension `json:"extensions"`
Highlights highlights `json:"highlights"`
}
func (m *clientHelloMsg) unmarshal(data []byte) bool {
*m = clientHelloMsg{Raw: data}
s := cryptobyte.String(data)
var random []byte
var sessionID []byte
if !s.Skip(1) || !s.ReadUint16(&m.RecordHeaderTLSVersion) || !s.Skip(2) ||
!s.Skip(4) || // message type and uint24 length field
!s.ReadUint16(&m.TLSVersion) || !s.ReadBytes(&random, 32) ||
!readUint8LengthPrefixed(&s, &sessionID) {
return false
}
m.Random = random
m.Highlights.GmtUnixTime = binary.BigEndian.Uint32(random[0:4])
m.SessionID = sessionID
var cipherSuites cryptobyte.String
if !s.ReadUint16LengthPrefixed(&cipherSuites) {
return false
}
m.CipherSuites = []uint16{}
m.Highlights.SecureRenegotiationSupport = false
for !cipherSuites.Empty() {
var suite uint16
if !cipherSuites.ReadUint16(&suite) {
return false
}
if suite == scsvRenegotiation {
m.Highlights.SecureRenegotiationSupport = true
}
m.CipherSuites = append(m.CipherSuites, suite)
}
var compressionMethods []uint8
if !readUint8LengthPrefixed(&s, &compressionMethods) {
return false
}
m.CompressionMethods = compressionMethods
if s.Empty() {
// ClientHello is optionally followed by extension data
return true
}
var extensions cryptobyte.String
if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() {
return false
}
for !extensions.Empty() {
var extension extension
var extData cryptobyte.String
if !extensions.ReadUint16(&extension.Code) ||
!extensions.ReadUint16LengthPrefixed(&extData) {
return false
}
extension.Data.Raw = []byte(extData)
switch extension.Code {
case extensionServerName:
// RFC 6066, Section 3
extension.Name = "server_name" // Server Name Indication
var nameList cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&nameList) || nameList.Empty() {
return false
}
for !nameList.Empty() {
var nameType uint8
var serverName cryptobyte.String
if !nameList.ReadUint8(&nameType) ||
!nameList.ReadUint16LengthPrefixed(&serverName) ||
serverName.Empty() {
return false
}
if nameType != 0 {
continue
}
if len(extension.Data.ServerName) != 0 {
// Multiple names of the same name_type are prohibited.
return false
}
sn := string(serverName)
extension.Data.ServerName = sn
// An SNI value may not include a trailing dot.
if strings.HasSuffix(sn, ".") {
return false
}
}
case extensionNextProtoNeg:
// draft-agl-tls-nextprotoneg-04
extension.Name = "next_protocol_negotiation" // Next Protocol Negotiation
case extensionStatusRequest:
// RFC 4366, Section 3.6
extension.Name = "status_request" // Certificate Status Request
var ignored cryptobyte.String
if !extData.ReadUint8(&extension.Data.StatusType) ||
!extData.ReadUint16LengthPrefixed(&ignored) || // responder_id_list
!extData.ReadUint16LengthPrefixed(&ignored) { // request_extensions
return false
}
m.Highlights.OcspStaplingSupport = extension.Data.StatusType == statusTypeOCSP
case extensionSupportedGroups:
// RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7
extension.Name = "supported_groups" // Supported Groups
//extension.Name = "elliptic_curves" // old name
var curves cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&curves) || curves.Empty() {
return false
}
extension.Data.SupportedGroups = make([]curveID, 0)
for !curves.Empty() {
var curve uint16
if !curves.ReadUint16(&curve) {
return false
}
extension.Data.SupportedGroups = append(
extension.Data.SupportedGroups, curveID(curve))
}
case extensionSupportedPointFormats:
// RFC 4492, Section 5.1.2
extension.Name = "ec_point_formats" // Supported Point Formats
var supportedPointFormats []uint8
if !readUint8LengthPrefixed(&extData, &supportedPointFormats) ||
len(supportedPointFormats) == 0 {
return false
}
extension.Data.SupportedPointFormats = supportedPointFormats
case extensionSessionTicket:
// RFC 5077, Section 3.2
extension.Name = "session_ticket" // Session Ticket
case extensionSignatureAlgorithms:
// RFC 5246, Section 7.4.1.4.1
extension.Name = "signature_algorithms" // Signature Algorithms
var sigAndAlgs cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() {
return false
}
for !sigAndAlgs.Empty() {
var sigAndAlg uint16
if !sigAndAlgs.ReadUint16(&sigAndAlg) {
return false
}
extension.Data.SupportedSignatureAlgorithms = append(
extension.Data.SupportedSignatureAlgorithms,
signatureScheme(sigAndAlg))
}
case extensionSignatureAlgorithmsCert:
// RFC 8446, Section 4.2.3
extension.Name = "signature_algorithms_cert" // Signature Algorithms Cert
var sigAndAlgs cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() {
return false
}
for !sigAndAlgs.Empty() {
var sigAndAlg uint16
if !sigAndAlgs.ReadUint16(&sigAndAlg) {
return false
}
extension.Data.SupportedSignatureAlgorithms = append(
extension.Data.SupportedSignatureAlgorithms,
signatureScheme(sigAndAlg))
}
case extensionRenegotiationInfo:
// RFC 5746, Section 3.2
extension.Name = "renegotiation_info" // Renegotiation Indication
if !readUint8LengthPrefixed(
&extData,
&extension.Data.RenegotiationInfo) {
return false
}
m.Highlights.SecureRenegotiationSupport = true
case extensionALPN:
// RFC 7301, Section 3.1
extension.Name = "application_layer_protocol_negotiation" // Application-Layer Protocol Negotiation
var protoList cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() {
return false
}
for !protoList.Empty() {
var proto cryptobyte.String
if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() {
return false
}
extension.Data.AlpnProtocols = append(extension.Data.AlpnProtocols, string(proto))
}
case extensionSCT:
// RFC 6962, Section 3.3.1
extension.Name = "signed_certificate_timestamp" // Signed Certificate Timestamp
m.Highlights.SctSupport = true
case extensionSupportedVersions:
// RFC 8446, Section 4.2.1
extension.Name = "supported_versions" // Supported Versions
var versList cryptobyte.String
if !extData.ReadUint8LengthPrefixed(&versList) || versList.Empty() {
return false
}
for !versList.Empty() {
var vers uint16
if !versList.ReadUint16(&vers) {
return false
}
extension.Data.SupportedVersions = append(extension.Data.SupportedVersions, vers)
}
case extensionCookie:
// RFC 8446, Section 4.2.2
extension.Name = "cookie" // Cookie
var cookie []byte
if !readUint16LengthPrefixed(&extData, &cookie) ||
len(extension.Data.Cookie) == 0 {
return false
}
extension.Data.Cookie = cookie
case extensionKeyShare:
// RFC 8446, Section 4.2.8
extension.Name = "key_share" // Key Share
var clientShares cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&clientShares) {
return false
}
for !clientShares.Empty() {
var ks keyShare
var ksData []byte
if !clientShares.ReadUint16((*uint16)(&ks.Group)) ||
!readUint16LengthPrefixed(&clientShares, &ksData) ||
len(ksData) == 0 {
return false
}
ks.Data = ksData
extension.Data.KeyShares = append(extension.Data.KeyShares, ks)
}
case extensionEarlyData:
// RFC 8446, Section 4.2.10
extension.Name = "early_data" // Early Data Indication
m.Highlights.EarlyData = true
case extensionPSKModes:
// RFC 8446, Section 4.2.9
extension.Name = "psk_key_exchange_modes" // Pre-Shared Key Exchange Modes
var pskModes []uint8
if !readUint8LengthPrefixed(&extData, &pskModes) {
return false
}
extension.Data.PskModes = pskModes
case extensionPreSharedKey:
// RFC 8446, Section 4.2.11
extension.Name = "pre_shared_key" // Pre-Shared Key
if !extensions.Empty() {
return false // pre_shared_key must be the last extension
}
var identities cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&identities) || identities.Empty() {
return false
}
for !identities.Empty() {
var psk pskIdentity
var identity []byte
if !readUint16LengthPrefixed(&identities, &identity) ||
!identities.ReadUint32(&psk.ObfuscatedTicketAge) ||
len(identity) == 0 {
return false
}
psk.Identity = identity
extension.Data.PskIdentities = append(extension.Data.PskIdentities, psk)
}
var binders cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&binders) || binders.Empty() {
return false
}
for !binders.Empty() {
var binder []byte
if !readUint8LengthPrefixed(&binders, &binder) ||
len(binder) == 0 {
return false
}
extension.Data.PskBinders = append(extension.Data.PskBinders, binder)
}
case extensionPadding:
// RFC 7685
extension.Name = "padding" // Padding
extension.Data.Length = uint16(len(extData))
case extensionEncryptThenMac:
// RFC 7366
extension.Name = "encrypt_then_mac" // Encrypt-then-MAC"
case extensionExtendedMasterSecret:
// RFC 7627
extension.Name = "extended_master_secret" // Extended Master Secret
case extensionPostHandshakeAuth:
// RFC 8446, Section 4.2.6
extension.Name = "post_handshake_auth" // Post-Handshake Client Authentication
case extensionCompressCertificate:
// RFC 8879
extension.Name = "compress_certificate" // Certificate Compression
// TODO: parse - https://www.rfc-editor.org/rfc/rfc8879.html
case extensionApplicationSettings:
// draft-vvv-tls-alps
// Application-Layer Protocol Settings
extension.Name = " application_settings"
// TODO: parse - https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps
default:
// Check if this is a GREASE extension (RFC 8701)
if isGREASE(extension.Code) {
extension.Name = "GREASE"
} else {
log.Println("Unknown extension:", extension.Code)
}
}
m.Extensions = append(m.Extensions, extension)
if !extData.Empty() &&
extension.Name != "GREASE" &&
extension.Code != extensionPadding {
log.Printf("Extension %d data not read.\n", extension.Code)
}
}
// JA3
var ja3 strings.Builder
var supportedGroups []curveID
var supportedPointFormats uint8Slice
ja3.WriteString(strconv.FormatUint(uint64(m.TLSVersion), 10) + ",")
for i, cs := range m.CipherSuites {
if !isGREASE(cs) { // ignore GREASE values
ja3.WriteString(strconv.FormatUint(uint64(cs), 10))
if i+1 != len(m.CipherSuites) {
ja3.WriteString("-")
}
}
}
ja3.WriteString(",")
for i, e := range m.Extensions {
if !isGREASE(e.Code) { // ignore GREASE values
ja3.WriteString(strconv.FormatUint(uint64(e.Code), 10))
if i+1 != len(m.Extensions) {
ja3.WriteString("-")
}
if e.Code == extensionSupportedGroups {
supportedGroups = e.Data.SupportedGroups
} else if e.Code == extensionSupportedPointFormats {
supportedPointFormats = e.Data.SupportedPointFormats
}
}
}
ja3.WriteString(",")
for i, g := range supportedGroups {
if !isGREASE(uint16(g)) { // ignore GREASE values
ja3.WriteString(strconv.FormatUint(uint64(g), 10))
if i+1 != len(supportedGroups) {
ja3.WriteString("-")
}
}
}
ja3.WriteString(",")
for i, pf := range supportedPointFormats {
if !isGREASE(uint16(pf)) { // ignore GREASE values
ja3.WriteString(strconv.FormatUint(uint64(pf), 10))
if i+1 != len(supportedPointFormats) {
ja3.WriteString("-")
}
}
}
m.Highlights.JA3 = ja3.String()
hash := md5.Sum([]byte(m.Highlights.JA3))
m.Highlights.JA3MD5 = hash[:]
return true
}

View File

@ -0,0 +1,449 @@
Value,Description,DTLS-OK,Recommended,Reference
"0x00,0x00",TLS_NULL_WITH_NULL_NULL,Y,N,[RFC5246]
"0x00,0x01",TLS_RSA_WITH_NULL_MD5,Y,N,[RFC5246]
"0x00,0x02",TLS_RSA_WITH_NULL_SHA,Y,N,[RFC5246]
"0x00,0x03",TLS_RSA_EXPORT_WITH_RC4_40_MD5,N,N,[RFC4346][RFC6347]
"0x00,0x04",TLS_RSA_WITH_RC4_128_MD5,N,N,[RFC5246][RFC6347]
"0x00,0x05",TLS_RSA_WITH_RC4_128_SHA,N,N,[RFC5246][RFC6347]
"0x00,0x06",TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,Y,N,[RFC4346]
"0x00,0x07",TLS_RSA_WITH_IDEA_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
"0x00,0x08",TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
"0x00,0x09",TLS_RSA_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
"0x00,0x0A",TLS_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
"0x00,0x0B",TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
"0x00,0x0C",TLS_DH_DSS_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
"0x00,0x0D",TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
"0x00,0x0E",TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
"0x00,0x0F",TLS_DH_RSA_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
"0x00,0x10",TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
"0x00,0x11",TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
"0x00,0x12",TLS_DHE_DSS_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
"0x00,0x13",TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
"0x00,0x14",TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
"0x00,0x15",TLS_DHE_RSA_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
"0x00,0x16",TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
"0x00,0x17",TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,N,N,[RFC4346][RFC6347]
"0x00,0x18",TLS_DH_anon_WITH_RC4_128_MD5,N,N,[RFC5246][RFC6347]
"0x00,0x19",TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,Y,N,[RFC4346]
"0x00,0x1A",TLS_DH_anon_WITH_DES_CBC_SHA,Y,N,[RFC5469][status-change-tls-des-idea-ciphers-to-historic]
"0x00,0x1B",TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5246]
"0x00,0x1C-1D",Reserved to avoid conflicts with SSLv3,,,[RFC5246]
"0x00,0x1E",TLS_KRB5_WITH_DES_CBC_SHA,Y,N,[RFC2712]
"0x00,0x1F",TLS_KRB5_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC2712]
"0x00,0x20",TLS_KRB5_WITH_RC4_128_SHA,N,N,[RFC2712][RFC6347]
"0x00,0x21",TLS_KRB5_WITH_IDEA_CBC_SHA,Y,N,[RFC2712]
"0x00,0x22",TLS_KRB5_WITH_DES_CBC_MD5,Y,N,[RFC2712]
"0x00,0x23",TLS_KRB5_WITH_3DES_EDE_CBC_MD5,Y,N,[RFC2712]
"0x00,0x24",TLS_KRB5_WITH_RC4_128_MD5,N,N,[RFC2712][RFC6347]
"0x00,0x25",TLS_KRB5_WITH_IDEA_CBC_MD5,Y,N,[RFC2712]
"0x00,0x26",TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,Y,N,[RFC2712]
"0x00,0x27",TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,Y,N,[RFC2712]
"0x00,0x28",TLS_KRB5_EXPORT_WITH_RC4_40_SHA,N,N,[RFC2712][RFC6347]
"0x00,0x29",TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,Y,N,[RFC2712]
"0x00,0x2A",TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,Y,N,[RFC2712]
"0x00,0x2B",TLS_KRB5_EXPORT_WITH_RC4_40_MD5,N,N,[RFC2712][RFC6347]
"0x00,0x2C",TLS_PSK_WITH_NULL_SHA,Y,N,[RFC4785]
"0x00,0x2D",TLS_DHE_PSK_WITH_NULL_SHA,Y,N,[RFC4785]
"0x00,0x2E",TLS_RSA_PSK_WITH_NULL_SHA,Y,N,[RFC4785]
"0x00,0x2F",TLS_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
"0x00,0x30",TLS_DH_DSS_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
"0x00,0x31",TLS_DH_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
"0x00,0x32",TLS_DHE_DSS_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
"0x00,0x33",TLS_DHE_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
"0x00,0x34",TLS_DH_anon_WITH_AES_128_CBC_SHA,Y,N,[RFC5246]
"0x00,0x35",TLS_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
"0x00,0x36",TLS_DH_DSS_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
"0x00,0x37",TLS_DH_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
"0x00,0x38",TLS_DHE_DSS_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
"0x00,0x39",TLS_DHE_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
"0x00,0x3A",TLS_DH_anon_WITH_AES_256_CBC_SHA,Y,N,[RFC5246]
"0x00,0x3B",TLS_RSA_WITH_NULL_SHA256,Y,N,[RFC5246]
"0x00,0x3C",TLS_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x3D",TLS_RSA_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x3E",TLS_DH_DSS_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x3F",TLS_DH_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x40",TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x41",TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
"0x00,0x42",TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
"0x00,0x43",TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
"0x00,0x44",TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
"0x00,0x45",TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
"0x00,0x46",TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,Y,N,[RFC5932]
"0x00,0x47-4F","Reserved to avoid conflicts with
deployed implementations",,,[Pasi_Eronen]
"0x00,0x50-58",Reserved to avoid conflicts,,,"[Pasi Eronen, <pasi.eronen&nokia.com>, 2008-04-04. 2008-04-04]"
"0x00,0x59-5C","Reserved to avoid conflicts with
deployed implementations",,,[Pasi_Eronen]
"0x00,0x5D-5F",Unassigned,,,
"0x00,0x60-66","Reserved to avoid conflicts with
widely deployed implementations",,,[Pasi_Eronen]
"0x00,0x67",TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x68",TLS_DH_DSS_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x69",TLS_DH_RSA_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x6A",TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x6B",TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x6C",TLS_DH_anon_WITH_AES_128_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x6D",TLS_DH_anon_WITH_AES_256_CBC_SHA256,Y,N,[RFC5246]
"0x00,0x6E-83",Unassigned,,,
"0x00,0x84",TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
"0x00,0x85",TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
"0x00,0x86",TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
"0x00,0x87",TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
"0x00,0x88",TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
"0x00,0x89",TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,Y,N,[RFC5932]
"0x00,0x8A",TLS_PSK_WITH_RC4_128_SHA,N,N,[RFC4279][RFC6347]
"0x00,0x8B",TLS_PSK_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC4279]
"0x00,0x8C",TLS_PSK_WITH_AES_128_CBC_SHA,Y,N,[RFC4279]
"0x00,0x8D",TLS_PSK_WITH_AES_256_CBC_SHA,Y,N,[RFC4279]
"0x00,0x8E",TLS_DHE_PSK_WITH_RC4_128_SHA,N,N,[RFC4279][RFC6347]
"0x00,0x8F",TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC4279]
"0x00,0x90",TLS_DHE_PSK_WITH_AES_128_CBC_SHA,Y,N,[RFC4279]
"0x00,0x91",TLS_DHE_PSK_WITH_AES_256_CBC_SHA,Y,N,[RFC4279]
"0x00,0x92",TLS_RSA_PSK_WITH_RC4_128_SHA,N,N,[RFC4279][RFC6347]
"0x00,0x93",TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC4279]
"0x00,0x94",TLS_RSA_PSK_WITH_AES_128_CBC_SHA,Y,N,[RFC4279]
"0x00,0x95",TLS_RSA_PSK_WITH_AES_256_CBC_SHA,Y,N,[RFC4279]
"0x00,0x96",TLS_RSA_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
"0x00,0x97",TLS_DH_DSS_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
"0x00,0x98",TLS_DH_RSA_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
"0x00,0x99",TLS_DHE_DSS_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
"0x00,0x9A",TLS_DHE_RSA_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
"0x00,0x9B",TLS_DH_anon_WITH_SEED_CBC_SHA,Y,N,[RFC4162]
"0x00,0x9C",TLS_RSA_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
"0x00,0x9D",TLS_RSA_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
"0x00,0x9E",TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,Y,Y,[RFC5288]
"0x00,0x9F",TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,Y,Y,[RFC5288]
"0x00,0xA0",TLS_DH_RSA_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
"0x00,0xA1",TLS_DH_RSA_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
"0x00,0xA2",TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
"0x00,0xA3",TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
"0x00,0xA4",TLS_DH_DSS_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
"0x00,0xA5",TLS_DH_DSS_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
"0x00,0xA6",TLS_DH_anon_WITH_AES_128_GCM_SHA256,Y,N,[RFC5288]
"0x00,0xA7",TLS_DH_anon_WITH_AES_256_GCM_SHA384,Y,N,[RFC5288]
"0x00,0xA8",TLS_PSK_WITH_AES_128_GCM_SHA256,Y,N,[RFC5487]
"0x00,0xA9",TLS_PSK_WITH_AES_256_GCM_SHA384,Y,N,[RFC5487]
"0x00,0xAA",TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,Y,Y,[RFC5487]
"0x00,0xAB",TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,Y,Y,[RFC5487]
"0x00,0xAC",TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,Y,N,[RFC5487]
"0x00,0xAD",TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,Y,N,[RFC5487]
"0x00,0xAE",TLS_PSK_WITH_AES_128_CBC_SHA256,Y,N,[RFC5487]
"0x00,0xAF",TLS_PSK_WITH_AES_256_CBC_SHA384,Y,N,[RFC5487]
"0x00,0xB0",TLS_PSK_WITH_NULL_SHA256,Y,N,[RFC5487]
"0x00,0xB1",TLS_PSK_WITH_NULL_SHA384,Y,N,[RFC5487]
"0x00,0xB2",TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,Y,N,[RFC5487]
"0x00,0xB3",TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,Y,N,[RFC5487]
"0x00,0xB4",TLS_DHE_PSK_WITH_NULL_SHA256,Y,N,[RFC5487]
"0x00,0xB5",TLS_DHE_PSK_WITH_NULL_SHA384,Y,N,[RFC5487]
"0x00,0xB6",TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,Y,N,[RFC5487]
"0x00,0xB7",TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,Y,N,[RFC5487]
"0x00,0xB8",TLS_RSA_PSK_WITH_NULL_SHA256,Y,N,[RFC5487]
"0x00,0xB9",TLS_RSA_PSK_WITH_NULL_SHA384,Y,N,[RFC5487]
"0x00,0xBA",TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xBB",TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xBC",TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xBD",TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xBE",TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xBF",TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xC0",TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xC1",TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xC2",TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xC3",TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xC4",TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xC5",TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,Y,N,[RFC5932]
"0x00,0xC6",TLS_SM4_GCM_SM3,N,N,[RFC8998]
"0x00,0xC7",TLS_SM4_CCM_SM3,N,N,[RFC8998]
"0x00,0xC8-FE",Unassigned,,,
"0x00,0xFF",TLS_EMPTY_RENEGOTIATION_INFO_SCSV,Y,N,[RFC5746]
"0x01-09,*",Unassigned,,,
"0x0A,0x00-09",Unassigned,,,
"0x0A,0x0A",Reserved,Y,N,[RFC8701]
"0x0A,0x0B-FF",Unassigned,,,
"0x0B-12,*",Unassigned,,,
"0x13,0x00",Unassigned,,,
"0x13,0x01",TLS_AES_128_GCM_SHA256,Y,Y,[RFC8446]
"0x13,0x02",TLS_AES_256_GCM_SHA384,Y,Y,[RFC8446]
"0x13,0x03",TLS_CHACHA20_POLY1305_SHA256,Y,Y,[RFC8446]
"0x13,0x04",TLS_AES_128_CCM_SHA256,Y,Y,[RFC8446]
"0x13,0x05",TLS_AES_128_CCM_8_SHA256,Y,N,[RFC8446][IESG Action 2018-08-16]
"0x13,0x06",TLS_AEGIS_256_SHA384,Y,N,[draft-irtf-cfrg-aegis-aead-00]
"0x13,0x07",TLS_AEGIS_128L_SHA256,Y,N,[draft-irtf-cfrg-aegis-aead-00]
"0x13,0x08-FF",Unassigned,,,
"0x14-19,*",Unassigned,,,
"0x1A,0x00-19",Unassigned,,,
"0x1A,0x1A",Reserved,Y,N,[RFC8701]
"0x1A,0x1B-FF",Unassigned,,,
"0x1B-29,*",Unassigned,,,
"0x2A,0x00-29",Unassigned,,,
"0x2A,0x2A",Reserved,Y,N,[RFC8701]
"0x2A,0x2B-FF",Unassigned,,,
"0x2B-39,*",Unassigned,,,
"0x3A,0x00-39",Unassigned,,,
"0x3A,0x3A",Reserved,Y,N,[RFC8701]
"0x3A,0x3B-FF",Unassigned,,,
"0x3B-49,*",Unassigned,,,
"0x4A,0x00-49",Unassigned,,,
"0x4A,0x4A",Reserved,Y,N,[RFC8701]
"0x4A,0x4B-FF",Unassigned,,,
"0x4B-55,*",Unassigned,,,
"0x56,0x00",TLS_FALLBACK_SCSV,Y,N,[RFC7507]
"0x56,0x01-FF",Unassigned,,,
"0x57-59,*",Unassigned,,,
"0x5A,0x00-59",Unassigned,,,
"0x5A,0x5A",Reserved,Y,N,[RFC8701]
"0x5A,0x5B-FF",Unassigned,,,
"0x5B-69,*",Unassigned,,,
"0x6A,0x00-69",Unassigned,,,
"0x6A,0x6A",Reserved,Y,N,[RFC8701]
"0x6A,0x6B-FF",Unassigned,,,
"0x6B-79,*",Unassigned,,,
"0x7A,0x00-79",Unassigned,,,
"0x7A,0x7A",Reserved,Y,N,[RFC8701]
"0x7A,0x7B-FF",Unassigned,,,
"0x7B-89,*",Unassigned,,,
"0x8A,0x00-89",Unassigned,,,
"0x8A,0x8A",Reserved,Y,N,[RFC8701]
"0x8A,0x8B-FF",Unassigned,,,
"0x8B-99,*",Unassigned,,,
"0x9A,0x00-99",Unassigned,,,
"0x9A,0x9A",Reserved,Y,N,[RFC8701]
"0x9A,0x9B-FF",Unassigned,,,
"0x9B-A9,*",Unassigned,,,
"0xAA,0x00-A9",Unassigned,,,
"0xAA,0xAA",Reserved,Y,N,[RFC8701]
"0xAA,0xAB-FF",Unassigned,,,
"0xAB-B9,*",Unassigned,,,
"0xBA,0x00-B9",Unassigned,,,
"0xBA,0xBA",Reserved,Y,N,[RFC8701]
"0xBA,0xBB-FF",Unassigned,,,
"0xBB-BF,*",Unassigned,,,
"0xC0,0x00",Unassigned,,,
"0xC0,0x01",TLS_ECDH_ECDSA_WITH_NULL_SHA,Y,N,[RFC8422]
"0xC0,0x02",TLS_ECDH_ECDSA_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
"0xC0,0x03",TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x04",TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x05",TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x06",TLS_ECDHE_ECDSA_WITH_NULL_SHA,Y,N,[RFC8422]
"0xC0,0x07",TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
"0xC0,0x08",TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x09",TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x0A",TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x0B",TLS_ECDH_RSA_WITH_NULL_SHA,Y,N,[RFC8422]
"0xC0,0x0C",TLS_ECDH_RSA_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
"0xC0,0x0D",TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x0E",TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x0F",TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x10",TLS_ECDHE_RSA_WITH_NULL_SHA,Y,N,[RFC8422]
"0xC0,0x11",TLS_ECDHE_RSA_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
"0xC0,0x12",TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x13",TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x14",TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x15",TLS_ECDH_anon_WITH_NULL_SHA,Y,N,[RFC8422]
"0xC0,0x16",TLS_ECDH_anon_WITH_RC4_128_SHA,N,N,[RFC8422][RFC6347]
"0xC0,0x17",TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x18",TLS_ECDH_anon_WITH_AES_128_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x19",TLS_ECDH_anon_WITH_AES_256_CBC_SHA,Y,N,[RFC8422]
"0xC0,0x1A",TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5054]
"0xC0,0x1B",TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5054]
"0xC0,0x1C",TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5054]
"0xC0,0x1D",TLS_SRP_SHA_WITH_AES_128_CBC_SHA,Y,N,[RFC5054]
"0xC0,0x1E",TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,Y,N,[RFC5054]
"0xC0,0x1F",TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,Y,N,[RFC5054]
"0xC0,0x20",TLS_SRP_SHA_WITH_AES_256_CBC_SHA,Y,N,[RFC5054]
"0xC0,0x21",TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,Y,N,[RFC5054]
"0xC0,0x22",TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,Y,N,[RFC5054]
"0xC0,0x23",TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5289]
"0xC0,0x24",TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,Y,N,[RFC5289]
"0xC0,0x25",TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5289]
"0xC0,0x26",TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,Y,N,[RFC5289]
"0xC0,0x27",TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5289]
"0xC0,0x28",TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,Y,N,[RFC5289]
"0xC0,0x29",TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,Y,N,[RFC5289]
"0xC0,0x2A",TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,Y,N,[RFC5289]
"0xC0,0x2B",TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,Y,Y,[RFC5289]
"0xC0,0x2C",TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,Y,Y,[RFC5289]
"0xC0,0x2D",TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,Y,N,[RFC5289]
"0xC0,0x2E",TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,Y,N,[RFC5289]
"0xC0,0x2F",TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,Y,Y,[RFC5289]
"0xC0,0x30",TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,Y,Y,[RFC5289]
"0xC0,0x31",TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,Y,N,[RFC5289]
"0xC0,0x32",TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,Y,N,[RFC5289]
"0xC0,0x33",TLS_ECDHE_PSK_WITH_RC4_128_SHA,N,N,[RFC5489][RFC6347]
"0xC0,0x34",TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,Y,N,[RFC5489]
"0xC0,0x35",TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,Y,N,[RFC5489]
"0xC0,0x36",TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,Y,N,[RFC5489]
"0xC0,0x37",TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,Y,N,[RFC5489]
"0xC0,0x38",TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,Y,N,[RFC5489]
"0xC0,0x39",TLS_ECDHE_PSK_WITH_NULL_SHA,Y,N,[RFC5489]
"0xC0,0x3A",TLS_ECDHE_PSK_WITH_NULL_SHA256,Y,N,[RFC5489]
"0xC0,0x3B",TLS_ECDHE_PSK_WITH_NULL_SHA384,Y,N,[RFC5489]
"0xC0,0x3C",TLS_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x3D",TLS_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x3E",TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x3F",TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x40",TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x41",TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x42",TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x43",TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x44",TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x45",TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x46",TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x47",TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x48",TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x49",TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x4A",TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x4B",TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x4C",TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x4D",TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x4E",TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x4F",TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x50",TLS_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x51",TLS_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x52",TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x53",TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x54",TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x55",TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x56",TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x57",TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x58",TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x59",TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x5A",TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x5B",TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x5C",TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x5D",TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x5E",TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x5F",TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x60",TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x61",TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x62",TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x63",TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x64",TLS_PSK_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x65",TLS_PSK_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x66",TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x67",TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x68",TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x69",TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x6A",TLS_PSK_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x6B",TLS_PSK_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x6C",TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x6D",TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x6E",TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,Y,N,[RFC6209]
"0xC0,0x6F",TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,Y,N,[RFC6209]
"0xC0,0x70",TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,Y,N,[RFC6209]
"0xC0,0x71",TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,Y,N,[RFC6209]
"0xC0,0x72",TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
"0xC0,0x73",TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
"0xC0,0x74",TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
"0xC0,0x75",TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
"0xC0,0x76",TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
"0xC0,0x77",TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
"0xC0,0x78",TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
"0xC0,0x79",TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
"0xC0,0x7A",TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x7B",TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x7C",TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x7D",TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x7E",TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x7F",TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x80",TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x81",TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x82",TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x83",TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x84",TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x85",TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x86",TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x87",TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x88",TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x89",TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x8A",TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x8B",TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x8C",TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x8D",TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x8E",TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x8F",TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x90",TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x91",TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x92",TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,Y,N,[RFC6367]
"0xC0,0x93",TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,Y,N,[RFC6367]
"0xC0,0x94",TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
"0xC0,0x95",TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
"0xC0,0x96",TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
"0xC0,0x97",TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
"0xC0,0x98",TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
"0xC0,0x99",TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
"0xC0,0x9A",TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,Y,N,[RFC6367]
"0xC0,0x9B",TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,Y,N,[RFC6367]
"0xC0,0x9C",TLS_RSA_WITH_AES_128_CCM,Y,N,[RFC6655]
"0xC0,0x9D",TLS_RSA_WITH_AES_256_CCM,Y,N,[RFC6655]
"0xC0,0x9E",TLS_DHE_RSA_WITH_AES_128_CCM,Y,Y,[RFC6655]
"0xC0,0x9F",TLS_DHE_RSA_WITH_AES_256_CCM,Y,Y,[RFC6655]
"0xC0,0xA0",TLS_RSA_WITH_AES_128_CCM_8,Y,N,[RFC6655]
"0xC0,0xA1",TLS_RSA_WITH_AES_256_CCM_8,Y,N,[RFC6655]
"0xC0,0xA2",TLS_DHE_RSA_WITH_AES_128_CCM_8,Y,N,[RFC6655]
"0xC0,0xA3",TLS_DHE_RSA_WITH_AES_256_CCM_8,N,N,[RFC6655]
"0xC0,0xA4",TLS_PSK_WITH_AES_128_CCM,Y,N,[RFC6655]
"0xC0,0xA5",TLS_PSK_WITH_AES_256_CCM,Y,N,[RFC6655]
"0xC0,0xA6",TLS_DHE_PSK_WITH_AES_128_CCM,Y,Y,[RFC6655]
"0xC0,0xA7",TLS_DHE_PSK_WITH_AES_256_CCM,Y,Y,[RFC6655]
"0xC0,0xA8",TLS_PSK_WITH_AES_128_CCM_8,Y,N,[RFC6655]
"0xC0,0xA9",TLS_PSK_WITH_AES_256_CCM_8,Y,N,[RFC6655]
"0xC0,0xAA",TLS_PSK_DHE_WITH_AES_128_CCM_8,Y,N,[RFC6655]
"0xC0,0xAB",TLS_PSK_DHE_WITH_AES_256_CCM_8,Y,N,[RFC6655]
"0xC0,0xAC",TLS_ECDHE_ECDSA_WITH_AES_128_CCM,Y,N,[RFC7251]
"0xC0,0xAD",TLS_ECDHE_ECDSA_WITH_AES_256_CCM,Y,N,[RFC7251]
"0xC0,0xAE",TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,Y,N,[RFC7251]
"0xC0,0xAF",TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,Y,N,[RFC7251]
"0xC0,0xB0",TLS_ECCPWD_WITH_AES_128_GCM_SHA256,Y,N,[RFC8492]
"0xC0,0xB1",TLS_ECCPWD_WITH_AES_256_GCM_SHA384,Y,N,[RFC8492]
"0xC0,0xB2",TLS_ECCPWD_WITH_AES_128_CCM_SHA256,Y,N,[RFC8492]
"0xC0,0xB3",TLS_ECCPWD_WITH_AES_256_CCM_SHA384,Y,N,[RFC8492]
"0xC0,0xB4",TLS_SHA256_SHA256,Y,N,[RFC9150]
"0xC0,0xB5",TLS_SHA384_SHA384,Y,N,[RFC9150]
"0xC0,0xB6-FF",Unassigned,,,
"0xC1,0x00",TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC,N,N,[RFC9189]
"0xC1,0x01",TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC,N,N,[RFC9189]
"0xC1,0x02",TLS_GOSTR341112_256_WITH_28147_CNT_IMIT,N,N,[RFC9189]
"0xC1,0x03",TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L,N,N,[RFC9367]
"0xC1,0x04",TLS_GOSTR341112_256_WITH_MAGMA_MGM_L,N,N,[RFC9367]
"0xC1,0x05",TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S,N,N,[RFC9367]
"0xC1,0x06",TLS_GOSTR341112_256_WITH_MAGMA_MGM_S,N,N,[RFC9367]
"0xC1,0x07-FF",Unassigned,,,
"0xC2-C9,*",Unassigned,,,
"0xCA,0x00-C9",Unassigned,,,
"0xCA,0xCA",Reserved,Y,N,[RFC8701]
"0xCA,0xCB-FF",Unassigned,,,
"0xCB,*",Unassigned,,,
"0xCC,0x00-A7",Unassigned,,,
"0xCC,0xA8",TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
"0xCC,0xA9",TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
"0xCC,0xAA",TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
"0xCC,0xAB",TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,Y,N,[RFC7905]
"0xCC,0xAC",TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
"0xCC,0xAD",TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,Y,Y,[RFC7905]
"0xCC,0xAE",TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,Y,N,[RFC7905]
"0xCC,0xAF-FF",Unassigned,,,
"0xCD-CF,*",Unassigned,,,
"0xD0,0x00",Unassigned,,,
"0xD0,0x01",TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,Y,Y,[RFC8442]
"0xD0,0x02",TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384,Y,Y,[RFC8442]
"0xD0,0x03",TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256,Y,N,[RFC8442]
"0xD0,0x04",Unassigned,,,
"0xD0,0x05",TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256,Y,Y,[RFC8442]
"0xD0,0x06-FF",Unassigned,,,
"0xD1-D9,*",Unassigned,,,
"0xDA,0x00-D9",Unassigned,,,
"0xDA,0xDA",Reserved,Y,N,[RFC8701]
"0xDA,0xDB-FF",Unassigned,,,
"0xDB-E9,*",Unassigned,,,
"0xEA,0x00-E9",Unassigned,,,
"0xEA,0xEA",Reserved,Y,N,[RFC8701]
"0xEA,0xEB-FF",Unassigned,,,
"0xEB-F9,*",Unassigned,,,
"0xFA,0x00-C9",Unassigned,,,
"0xFA,0xFA",Reserved,Y,N,[RFC8701]
"0xFA,0xFB-FF",Unassigned,,,
"0xFB-FD,*",Unassigned,,,
"0xFE,0x00-FD",Unassigned,,,
"0xFE,0xFE-FF","Reserved to avoid conflicts with
widely deployed implementations",,,[Pasi_Eronen]
"0xFF,0x00-FF",Reserved for Private Use,,,[RFC8446]
1 Value Description DTLS-OK Recommended Reference
2 0x00,0x00 TLS_NULL_WITH_NULL_NULL Y N [RFC5246]
3 0x00,0x01 TLS_RSA_WITH_NULL_MD5 Y N [RFC5246]
4 0x00,0x02 TLS_RSA_WITH_NULL_SHA Y N [RFC5246]
5 0x00,0x03 TLS_RSA_EXPORT_WITH_RC4_40_MD5 N N [RFC4346][RFC6347]
6 0x00,0x04 TLS_RSA_WITH_RC4_128_MD5 N N [RFC5246][RFC6347]
7 0x00,0x05 TLS_RSA_WITH_RC4_128_SHA N N [RFC5246][RFC6347]
8 0x00,0x06 TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 Y N [RFC4346]
9 0x00,0x07 TLS_RSA_WITH_IDEA_CBC_SHA Y N [RFC5469][status-change-tls-des-idea-ciphers-to-historic]
10 0x00,0x08 TLS_RSA_EXPORT_WITH_DES40_CBC_SHA Y N [RFC4346]
11 0x00,0x09 TLS_RSA_WITH_DES_CBC_SHA Y N [RFC5469][status-change-tls-des-idea-ciphers-to-historic]
12 0x00,0x0A TLS_RSA_WITH_3DES_EDE_CBC_SHA Y N [RFC5246]
13 0x00,0x0B TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA Y N [RFC4346]
14 0x00,0x0C TLS_DH_DSS_WITH_DES_CBC_SHA Y N [RFC5469][status-change-tls-des-idea-ciphers-to-historic]
15 0x00,0x0D TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA Y N [RFC5246]
16 0x00,0x0E TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA Y N [RFC4346]
17 0x00,0x0F TLS_DH_RSA_WITH_DES_CBC_SHA Y N [RFC5469][status-change-tls-des-idea-ciphers-to-historic]
18 0x00,0x10 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA Y N [RFC5246]
19 0x00,0x11 TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA Y N [RFC4346]
20 0x00,0x12 TLS_DHE_DSS_WITH_DES_CBC_SHA Y N [RFC5469][status-change-tls-des-idea-ciphers-to-historic]
21 0x00,0x13 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA Y N [RFC5246]
22 0x00,0x14 TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA Y N [RFC4346]
23 0x00,0x15 TLS_DHE_RSA_WITH_DES_CBC_SHA Y N [RFC5469][status-change-tls-des-idea-ciphers-to-historic]
24 0x00,0x16 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA Y N [RFC5246]
25 0x00,0x17 TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 N N [RFC4346][RFC6347]
26 0x00,0x18 TLS_DH_anon_WITH_RC4_128_MD5 N N [RFC5246][RFC6347]
27 0x00,0x19 TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA Y N [RFC4346]
28 0x00,0x1A TLS_DH_anon_WITH_DES_CBC_SHA Y N [RFC5469][status-change-tls-des-idea-ciphers-to-historic]
29 0x00,0x1B TLS_DH_anon_WITH_3DES_EDE_CBC_SHA Y N [RFC5246]
30 0x00,0x1C-1D Reserved to avoid conflicts with SSLv3 [RFC5246]
31 0x00,0x1E TLS_KRB5_WITH_DES_CBC_SHA Y N [RFC2712]
32 0x00,0x1F TLS_KRB5_WITH_3DES_EDE_CBC_SHA Y N [RFC2712]
33 0x00,0x20 TLS_KRB5_WITH_RC4_128_SHA N N [RFC2712][RFC6347]
34 0x00,0x21 TLS_KRB5_WITH_IDEA_CBC_SHA Y N [RFC2712]
35 0x00,0x22 TLS_KRB5_WITH_DES_CBC_MD5 Y N [RFC2712]
36 0x00,0x23 TLS_KRB5_WITH_3DES_EDE_CBC_MD5 Y N [RFC2712]
37 0x00,0x24 TLS_KRB5_WITH_RC4_128_MD5 N N [RFC2712][RFC6347]
38 0x00,0x25 TLS_KRB5_WITH_IDEA_CBC_MD5 Y N [RFC2712]
39 0x00,0x26 TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA Y N [RFC2712]
40 0x00,0x27 TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA Y N [RFC2712]
41 0x00,0x28 TLS_KRB5_EXPORT_WITH_RC4_40_SHA N N [RFC2712][RFC6347]
42 0x00,0x29 TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 Y N [RFC2712]
43 0x00,0x2A TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 Y N [RFC2712]
44 0x00,0x2B TLS_KRB5_EXPORT_WITH_RC4_40_MD5 N N [RFC2712][RFC6347]
45 0x00,0x2C TLS_PSK_WITH_NULL_SHA Y N [RFC4785]
46 0x00,0x2D TLS_DHE_PSK_WITH_NULL_SHA Y N [RFC4785]
47 0x00,0x2E TLS_RSA_PSK_WITH_NULL_SHA Y N [RFC4785]
48 0x00,0x2F TLS_RSA_WITH_AES_128_CBC_SHA Y N [RFC5246]
49 0x00,0x30 TLS_DH_DSS_WITH_AES_128_CBC_SHA Y N [RFC5246]
50 0x00,0x31 TLS_DH_RSA_WITH_AES_128_CBC_SHA Y N [RFC5246]
51 0x00,0x32 TLS_DHE_DSS_WITH_AES_128_CBC_SHA Y N [RFC5246]
52 0x00,0x33 TLS_DHE_RSA_WITH_AES_128_CBC_SHA Y N [RFC5246]
53 0x00,0x34 TLS_DH_anon_WITH_AES_128_CBC_SHA Y N [RFC5246]
54 0x00,0x35 TLS_RSA_WITH_AES_256_CBC_SHA Y N [RFC5246]
55 0x00,0x36 TLS_DH_DSS_WITH_AES_256_CBC_SHA Y N [RFC5246]
56 0x00,0x37 TLS_DH_RSA_WITH_AES_256_CBC_SHA Y N [RFC5246]
57 0x00,0x38 TLS_DHE_DSS_WITH_AES_256_CBC_SHA Y N [RFC5246]
58 0x00,0x39 TLS_DHE_RSA_WITH_AES_256_CBC_SHA Y N [RFC5246]
59 0x00,0x3A TLS_DH_anon_WITH_AES_256_CBC_SHA Y N [RFC5246]
60 0x00,0x3B TLS_RSA_WITH_NULL_SHA256 Y N [RFC5246]
61 0x00,0x3C TLS_RSA_WITH_AES_128_CBC_SHA256 Y N [RFC5246]
62 0x00,0x3D TLS_RSA_WITH_AES_256_CBC_SHA256 Y N [RFC5246]
63 0x00,0x3E TLS_DH_DSS_WITH_AES_128_CBC_SHA256 Y N [RFC5246]
64 0x00,0x3F TLS_DH_RSA_WITH_AES_128_CBC_SHA256 Y N [RFC5246]
65 0x00,0x40 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 Y N [RFC5246]
66 0x00,0x41 TLS_RSA_WITH_CAMELLIA_128_CBC_SHA Y N [RFC5932]
67 0x00,0x42 TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA Y N [RFC5932]
68 0x00,0x43 TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA Y N [RFC5932]
69 0x00,0x44 TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA Y N [RFC5932]
70 0x00,0x45 TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA Y N [RFC5932]
71 0x00,0x46 TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA Y N [RFC5932]
72 0x00,0x47-4F Reserved to avoid conflicts with deployed implementations [Pasi_Eronen]
73 0x00,0x50-58 Reserved to avoid conflicts [Pasi Eronen, <pasi.eronen&nokia.com>, 2008-04-04. 2008-04-04]
74 0x00,0x59-5C Reserved to avoid conflicts with deployed implementations [Pasi_Eronen]
75 0x00,0x5D-5F Unassigned
76 0x00,0x60-66 Reserved to avoid conflicts with widely deployed implementations [Pasi_Eronen]
77 0x00,0x67 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 Y N [RFC5246]
78 0x00,0x68 TLS_DH_DSS_WITH_AES_256_CBC_SHA256 Y N [RFC5246]
79 0x00,0x69 TLS_DH_RSA_WITH_AES_256_CBC_SHA256 Y N [RFC5246]
80 0x00,0x6A TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 Y N [RFC5246]
81 0x00,0x6B TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 Y N [RFC5246]
82 0x00,0x6C TLS_DH_anon_WITH_AES_128_CBC_SHA256 Y N [RFC5246]
83 0x00,0x6D TLS_DH_anon_WITH_AES_256_CBC_SHA256 Y N [RFC5246]
84 0x00,0x6E-83 Unassigned
85 0x00,0x84 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA Y N [RFC5932]
86 0x00,0x85 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA Y N [RFC5932]
87 0x00,0x86 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA Y N [RFC5932]
88 0x00,0x87 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA Y N [RFC5932]
89 0x00,0x88 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA Y N [RFC5932]
90 0x00,0x89 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA Y N [RFC5932]
91 0x00,0x8A TLS_PSK_WITH_RC4_128_SHA N N [RFC4279][RFC6347]
92 0x00,0x8B TLS_PSK_WITH_3DES_EDE_CBC_SHA Y N [RFC4279]
93 0x00,0x8C TLS_PSK_WITH_AES_128_CBC_SHA Y N [RFC4279]
94 0x00,0x8D TLS_PSK_WITH_AES_256_CBC_SHA Y N [RFC4279]
95 0x00,0x8E TLS_DHE_PSK_WITH_RC4_128_SHA N N [RFC4279][RFC6347]
96 0x00,0x8F TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA Y N [RFC4279]
97 0x00,0x90 TLS_DHE_PSK_WITH_AES_128_CBC_SHA Y N [RFC4279]
98 0x00,0x91 TLS_DHE_PSK_WITH_AES_256_CBC_SHA Y N [RFC4279]
99 0x00,0x92 TLS_RSA_PSK_WITH_RC4_128_SHA N N [RFC4279][RFC6347]
100 0x00,0x93 TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA Y N [RFC4279]
101 0x00,0x94 TLS_RSA_PSK_WITH_AES_128_CBC_SHA Y N [RFC4279]
102 0x00,0x95 TLS_RSA_PSK_WITH_AES_256_CBC_SHA Y N [RFC4279]
103 0x00,0x96 TLS_RSA_WITH_SEED_CBC_SHA Y N [RFC4162]
104 0x00,0x97 TLS_DH_DSS_WITH_SEED_CBC_SHA Y N [RFC4162]
105 0x00,0x98 TLS_DH_RSA_WITH_SEED_CBC_SHA Y N [RFC4162]
106 0x00,0x99 TLS_DHE_DSS_WITH_SEED_CBC_SHA Y N [RFC4162]
107 0x00,0x9A TLS_DHE_RSA_WITH_SEED_CBC_SHA Y N [RFC4162]
108 0x00,0x9B TLS_DH_anon_WITH_SEED_CBC_SHA Y N [RFC4162]
109 0x00,0x9C TLS_RSA_WITH_AES_128_GCM_SHA256 Y N [RFC5288]
110 0x00,0x9D TLS_RSA_WITH_AES_256_GCM_SHA384 Y N [RFC5288]
111 0x00,0x9E TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 Y Y [RFC5288]
112 0x00,0x9F TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 Y Y [RFC5288]
113 0x00,0xA0 TLS_DH_RSA_WITH_AES_128_GCM_SHA256 Y N [RFC5288]
114 0x00,0xA1 TLS_DH_RSA_WITH_AES_256_GCM_SHA384 Y N [RFC5288]
115 0x00,0xA2 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 Y N [RFC5288]
116 0x00,0xA3 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 Y N [RFC5288]
117 0x00,0xA4 TLS_DH_DSS_WITH_AES_128_GCM_SHA256 Y N [RFC5288]
118 0x00,0xA5 TLS_DH_DSS_WITH_AES_256_GCM_SHA384 Y N [RFC5288]
119 0x00,0xA6 TLS_DH_anon_WITH_AES_128_GCM_SHA256 Y N [RFC5288]
120 0x00,0xA7 TLS_DH_anon_WITH_AES_256_GCM_SHA384 Y N [RFC5288]
121 0x00,0xA8 TLS_PSK_WITH_AES_128_GCM_SHA256 Y N [RFC5487]
122 0x00,0xA9 TLS_PSK_WITH_AES_256_GCM_SHA384 Y N [RFC5487]
123 0x00,0xAA TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 Y Y [RFC5487]
124 0x00,0xAB TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 Y Y [RFC5487]
125 0x00,0xAC TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 Y N [RFC5487]
126 0x00,0xAD TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 Y N [RFC5487]
127 0x00,0xAE TLS_PSK_WITH_AES_128_CBC_SHA256 Y N [RFC5487]
128 0x00,0xAF TLS_PSK_WITH_AES_256_CBC_SHA384 Y N [RFC5487]
129 0x00,0xB0 TLS_PSK_WITH_NULL_SHA256 Y N [RFC5487]
130 0x00,0xB1 TLS_PSK_WITH_NULL_SHA384 Y N [RFC5487]
131 0x00,0xB2 TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 Y N [RFC5487]
132 0x00,0xB3 TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 Y N [RFC5487]
133 0x00,0xB4 TLS_DHE_PSK_WITH_NULL_SHA256 Y N [RFC5487]
134 0x00,0xB5 TLS_DHE_PSK_WITH_NULL_SHA384 Y N [RFC5487]
135 0x00,0xB6 TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 Y N [RFC5487]
136 0x00,0xB7 TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 Y N [RFC5487]
137 0x00,0xB8 TLS_RSA_PSK_WITH_NULL_SHA256 Y N [RFC5487]
138 0x00,0xB9 TLS_RSA_PSK_WITH_NULL_SHA384 Y N [RFC5487]
139 0x00,0xBA TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC5932]
140 0x00,0xBB TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC5932]
141 0x00,0xBC TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC5932]
142 0x00,0xBD TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC5932]
143 0x00,0xBE TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC5932]
144 0x00,0xBF TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC5932]
145 0x00,0xC0 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 Y N [RFC5932]
146 0x00,0xC1 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 Y N [RFC5932]
147 0x00,0xC2 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 Y N [RFC5932]
148 0x00,0xC3 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 Y N [RFC5932]
149 0x00,0xC4 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 Y N [RFC5932]
150 0x00,0xC5 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 Y N [RFC5932]
151 0x00,0xC6 TLS_SM4_GCM_SM3 N N [RFC8998]
152 0x00,0xC7 TLS_SM4_CCM_SM3 N N [RFC8998]
153 0x00,0xC8-FE Unassigned
154 0x00,0xFF TLS_EMPTY_RENEGOTIATION_INFO_SCSV Y N [RFC5746]
155 0x01-09,* Unassigned
156 0x0A,0x00-09 Unassigned
157 0x0A,0x0A Reserved Y N [RFC8701]
158 0x0A,0x0B-FF Unassigned
159 0x0B-12,* Unassigned
160 0x13,0x00 Unassigned
161 0x13,0x01 TLS_AES_128_GCM_SHA256 Y Y [RFC8446]
162 0x13,0x02 TLS_AES_256_GCM_SHA384 Y Y [RFC8446]
163 0x13,0x03 TLS_CHACHA20_POLY1305_SHA256 Y Y [RFC8446]
164 0x13,0x04 TLS_AES_128_CCM_SHA256 Y Y [RFC8446]
165 0x13,0x05 TLS_AES_128_CCM_8_SHA256 Y N [RFC8446][IESG Action 2018-08-16]
166 0x13,0x06 TLS_AEGIS_256_SHA384 Y N [draft-irtf-cfrg-aegis-aead-00]
167 0x13,0x07 TLS_AEGIS_128L_SHA256 Y N [draft-irtf-cfrg-aegis-aead-00]
168 0x13,0x08-FF Unassigned
169 0x14-19,* Unassigned
170 0x1A,0x00-19 Unassigned
171 0x1A,0x1A Reserved Y N [RFC8701]
172 0x1A,0x1B-FF Unassigned
173 0x1B-29,* Unassigned
174 0x2A,0x00-29 Unassigned
175 0x2A,0x2A Reserved Y N [RFC8701]
176 0x2A,0x2B-FF Unassigned
177 0x2B-39,* Unassigned
178 0x3A,0x00-39 Unassigned
179 0x3A,0x3A Reserved Y N [RFC8701]
180 0x3A,0x3B-FF Unassigned
181 0x3B-49,* Unassigned
182 0x4A,0x00-49 Unassigned
183 0x4A,0x4A Reserved Y N [RFC8701]
184 0x4A,0x4B-FF Unassigned
185 0x4B-55,* Unassigned
186 0x56,0x00 TLS_FALLBACK_SCSV Y N [RFC7507]
187 0x56,0x01-FF Unassigned
188 0x57-59,* Unassigned
189 0x5A,0x00-59 Unassigned
190 0x5A,0x5A Reserved Y N [RFC8701]
191 0x5A,0x5B-FF Unassigned
192 0x5B-69,* Unassigned
193 0x6A,0x00-69 Unassigned
194 0x6A,0x6A Reserved Y N [RFC8701]
195 0x6A,0x6B-FF Unassigned
196 0x6B-79,* Unassigned
197 0x7A,0x00-79 Unassigned
198 0x7A,0x7A Reserved Y N [RFC8701]
199 0x7A,0x7B-FF Unassigned
200 0x7B-89,* Unassigned
201 0x8A,0x00-89 Unassigned
202 0x8A,0x8A Reserved Y N [RFC8701]
203 0x8A,0x8B-FF Unassigned
204 0x8B-99,* Unassigned
205 0x9A,0x00-99 Unassigned
206 0x9A,0x9A Reserved Y N [RFC8701]
207 0x9A,0x9B-FF Unassigned
208 0x9B-A9,* Unassigned
209 0xAA,0x00-A9 Unassigned
210 0xAA,0xAA Reserved Y N [RFC8701]
211 0xAA,0xAB-FF Unassigned
212 0xAB-B9,* Unassigned
213 0xBA,0x00-B9 Unassigned
214 0xBA,0xBA Reserved Y N [RFC8701]
215 0xBA,0xBB-FF Unassigned
216 0xBB-BF,* Unassigned
217 0xC0,0x00 Unassigned
218 0xC0,0x01 TLS_ECDH_ECDSA_WITH_NULL_SHA Y N [RFC8422]
219 0xC0,0x02 TLS_ECDH_ECDSA_WITH_RC4_128_SHA N N [RFC8422][RFC6347]
220 0xC0,0x03 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA Y N [RFC8422]
221 0xC0,0x04 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA Y N [RFC8422]
222 0xC0,0x05 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA Y N [RFC8422]
223 0xC0,0x06 TLS_ECDHE_ECDSA_WITH_NULL_SHA Y N [RFC8422]
224 0xC0,0x07 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA N N [RFC8422][RFC6347]
225 0xC0,0x08 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA Y N [RFC8422]
226 0xC0,0x09 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA Y N [RFC8422]
227 0xC0,0x0A TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA Y N [RFC8422]
228 0xC0,0x0B TLS_ECDH_RSA_WITH_NULL_SHA Y N [RFC8422]
229 0xC0,0x0C TLS_ECDH_RSA_WITH_RC4_128_SHA N N [RFC8422][RFC6347]
230 0xC0,0x0D TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA Y N [RFC8422]
231 0xC0,0x0E TLS_ECDH_RSA_WITH_AES_128_CBC_SHA Y N [RFC8422]
232 0xC0,0x0F TLS_ECDH_RSA_WITH_AES_256_CBC_SHA Y N [RFC8422]
233 0xC0,0x10 TLS_ECDHE_RSA_WITH_NULL_SHA Y N [RFC8422]
234 0xC0,0x11 TLS_ECDHE_RSA_WITH_RC4_128_SHA N N [RFC8422][RFC6347]
235 0xC0,0x12 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA Y N [RFC8422]
236 0xC0,0x13 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA Y N [RFC8422]
237 0xC0,0x14 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA Y N [RFC8422]
238 0xC0,0x15 TLS_ECDH_anon_WITH_NULL_SHA Y N [RFC8422]
239 0xC0,0x16 TLS_ECDH_anon_WITH_RC4_128_SHA N N [RFC8422][RFC6347]
240 0xC0,0x17 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA Y N [RFC8422]
241 0xC0,0x18 TLS_ECDH_anon_WITH_AES_128_CBC_SHA Y N [RFC8422]
242 0xC0,0x19 TLS_ECDH_anon_WITH_AES_256_CBC_SHA Y N [RFC8422]
243 0xC0,0x1A TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA Y N [RFC5054]
244 0xC0,0x1B TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA Y N [RFC5054]
245 0xC0,0x1C TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA Y N [RFC5054]
246 0xC0,0x1D TLS_SRP_SHA_WITH_AES_128_CBC_SHA Y N [RFC5054]
247 0xC0,0x1E TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA Y N [RFC5054]
248 0xC0,0x1F TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA Y N [RFC5054]
249 0xC0,0x20 TLS_SRP_SHA_WITH_AES_256_CBC_SHA Y N [RFC5054]
250 0xC0,0x21 TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA Y N [RFC5054]
251 0xC0,0x22 TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA Y N [RFC5054]
252 0xC0,0x23 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 Y N [RFC5289]
253 0xC0,0x24 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 Y N [RFC5289]
254 0xC0,0x25 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 Y N [RFC5289]
255 0xC0,0x26 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 Y N [RFC5289]
256 0xC0,0x27 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 Y N [RFC5289]
257 0xC0,0x28 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 Y N [RFC5289]
258 0xC0,0x29 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 Y N [RFC5289]
259 0xC0,0x2A TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 Y N [RFC5289]
260 0xC0,0x2B TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 Y Y [RFC5289]
261 0xC0,0x2C TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 Y Y [RFC5289]
262 0xC0,0x2D TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 Y N [RFC5289]
263 0xC0,0x2E TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 Y N [RFC5289]
264 0xC0,0x2F TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 Y Y [RFC5289]
265 0xC0,0x30 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 Y Y [RFC5289]
266 0xC0,0x31 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 Y N [RFC5289]
267 0xC0,0x32 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 Y N [RFC5289]
268 0xC0,0x33 TLS_ECDHE_PSK_WITH_RC4_128_SHA N N [RFC5489][RFC6347]
269 0xC0,0x34 TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA Y N [RFC5489]
270 0xC0,0x35 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA Y N [RFC5489]
271 0xC0,0x36 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA Y N [RFC5489]
272 0xC0,0x37 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 Y N [RFC5489]
273 0xC0,0x38 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 Y N [RFC5489]
274 0xC0,0x39 TLS_ECDHE_PSK_WITH_NULL_SHA Y N [RFC5489]
275 0xC0,0x3A TLS_ECDHE_PSK_WITH_NULL_SHA256 Y N [RFC5489]
276 0xC0,0x3B TLS_ECDHE_PSK_WITH_NULL_SHA384 Y N [RFC5489]
277 0xC0,0x3C TLS_RSA_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
278 0xC0,0x3D TLS_RSA_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
279 0xC0,0x3E TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
280 0xC0,0x3F TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
281 0xC0,0x40 TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
282 0xC0,0x41 TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
283 0xC0,0x42 TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
284 0xC0,0x43 TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
285 0xC0,0x44 TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
286 0xC0,0x45 TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
287 0xC0,0x46 TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
288 0xC0,0x47 TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
289 0xC0,0x48 TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
290 0xC0,0x49 TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
291 0xC0,0x4A TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
292 0xC0,0x4B TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
293 0xC0,0x4C TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
294 0xC0,0x4D TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
295 0xC0,0x4E TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
296 0xC0,0x4F TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
297 0xC0,0x50 TLS_RSA_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
298 0xC0,0x51 TLS_RSA_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
299 0xC0,0x52 TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
300 0xC0,0x53 TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
301 0xC0,0x54 TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
302 0xC0,0x55 TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
303 0xC0,0x56 TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
304 0xC0,0x57 TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
305 0xC0,0x58 TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
306 0xC0,0x59 TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
307 0xC0,0x5A TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
308 0xC0,0x5B TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
309 0xC0,0x5C TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
310 0xC0,0x5D TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
311 0xC0,0x5E TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
312 0xC0,0x5F TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
313 0xC0,0x60 TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
314 0xC0,0x61 TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
315 0xC0,0x62 TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
316 0xC0,0x63 TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
317 0xC0,0x64 TLS_PSK_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
318 0xC0,0x65 TLS_PSK_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
319 0xC0,0x66 TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
320 0xC0,0x67 TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
321 0xC0,0x68 TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
322 0xC0,0x69 TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
323 0xC0,0x6A TLS_PSK_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
324 0xC0,0x6B TLS_PSK_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
325 0xC0,0x6C TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
326 0xC0,0x6D TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
327 0xC0,0x6E TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 Y N [RFC6209]
328 0xC0,0x6F TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 Y N [RFC6209]
329 0xC0,0x70 TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 Y N [RFC6209]
330 0xC0,0x71 TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 Y N [RFC6209]
331 0xC0,0x72 TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC6367]
332 0xC0,0x73 TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 Y N [RFC6367]
333 0xC0,0x74 TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC6367]
334 0xC0,0x75 TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 Y N [RFC6367]
335 0xC0,0x76 TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC6367]
336 0xC0,0x77 TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 Y N [RFC6367]
337 0xC0,0x78 TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC6367]
338 0xC0,0x79 TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 Y N [RFC6367]
339 0xC0,0x7A TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
340 0xC0,0x7B TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
341 0xC0,0x7C TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
342 0xC0,0x7D TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
343 0xC0,0x7E TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
344 0xC0,0x7F TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
345 0xC0,0x80 TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
346 0xC0,0x81 TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
347 0xC0,0x82 TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
348 0xC0,0x83 TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
349 0xC0,0x84 TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
350 0xC0,0x85 TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
351 0xC0,0x86 TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
352 0xC0,0x87 TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
353 0xC0,0x88 TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
354 0xC0,0x89 TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
355 0xC0,0x8A TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
356 0xC0,0x8B TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
357 0xC0,0x8C TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
358 0xC0,0x8D TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
359 0xC0,0x8E TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
360 0xC0,0x8F TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
361 0xC0,0x90 TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
362 0xC0,0x91 TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
363 0xC0,0x92 TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 Y N [RFC6367]
364 0xC0,0x93 TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 Y N [RFC6367]
365 0xC0,0x94 TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC6367]
366 0xC0,0x95 TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 Y N [RFC6367]
367 0xC0,0x96 TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC6367]
368 0xC0,0x97 TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 Y N [RFC6367]
369 0xC0,0x98 TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC6367]
370 0xC0,0x99 TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 Y N [RFC6367]
371 0xC0,0x9A TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 Y N [RFC6367]
372 0xC0,0x9B TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 Y N [RFC6367]
373 0xC0,0x9C TLS_RSA_WITH_AES_128_CCM Y N [RFC6655]
374 0xC0,0x9D TLS_RSA_WITH_AES_256_CCM Y N [RFC6655]
375 0xC0,0x9E TLS_DHE_RSA_WITH_AES_128_CCM Y Y [RFC6655]
376 0xC0,0x9F TLS_DHE_RSA_WITH_AES_256_CCM Y Y [RFC6655]
377 0xC0,0xA0 TLS_RSA_WITH_AES_128_CCM_8 Y N [RFC6655]
378 0xC0,0xA1 TLS_RSA_WITH_AES_256_CCM_8 Y N [RFC6655]
379 0xC0,0xA2 TLS_DHE_RSA_WITH_AES_128_CCM_8 Y N [RFC6655]
380 0xC0,0xA3 TLS_DHE_RSA_WITH_AES_256_CCM_8 N N [RFC6655]
381 0xC0,0xA4 TLS_PSK_WITH_AES_128_CCM Y N [RFC6655]
382 0xC0,0xA5 TLS_PSK_WITH_AES_256_CCM Y N [RFC6655]
383 0xC0,0xA6 TLS_DHE_PSK_WITH_AES_128_CCM Y Y [RFC6655]
384 0xC0,0xA7 TLS_DHE_PSK_WITH_AES_256_CCM Y Y [RFC6655]
385 0xC0,0xA8 TLS_PSK_WITH_AES_128_CCM_8 Y N [RFC6655]
386 0xC0,0xA9 TLS_PSK_WITH_AES_256_CCM_8 Y N [RFC6655]
387 0xC0,0xAA TLS_PSK_DHE_WITH_AES_128_CCM_8 Y N [RFC6655]
388 0xC0,0xAB TLS_PSK_DHE_WITH_AES_256_CCM_8 Y N [RFC6655]
389 0xC0,0xAC TLS_ECDHE_ECDSA_WITH_AES_128_CCM Y N [RFC7251]
390 0xC0,0xAD TLS_ECDHE_ECDSA_WITH_AES_256_CCM Y N [RFC7251]
391 0xC0,0xAE TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 Y N [RFC7251]
392 0xC0,0xAF TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 Y N [RFC7251]
393 0xC0,0xB0 TLS_ECCPWD_WITH_AES_128_GCM_SHA256 Y N [RFC8492]
394 0xC0,0xB1 TLS_ECCPWD_WITH_AES_256_GCM_SHA384 Y N [RFC8492]
395 0xC0,0xB2 TLS_ECCPWD_WITH_AES_128_CCM_SHA256 Y N [RFC8492]
396 0xC0,0xB3 TLS_ECCPWD_WITH_AES_256_CCM_SHA384 Y N [RFC8492]
397 0xC0,0xB4 TLS_SHA256_SHA256 Y N [RFC9150]
398 0xC0,0xB5 TLS_SHA384_SHA384 Y N [RFC9150]
399 0xC0,0xB6-FF Unassigned
400 0xC1,0x00 TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC N N [RFC9189]
401 0xC1,0x01 TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC N N [RFC9189]
402 0xC1,0x02 TLS_GOSTR341112_256_WITH_28147_CNT_IMIT N N [RFC9189]
403 0xC1,0x03 TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L N N [RFC9367]
404 0xC1,0x04 TLS_GOSTR341112_256_WITH_MAGMA_MGM_L N N [RFC9367]
405 0xC1,0x05 TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S N N [RFC9367]
406 0xC1,0x06 TLS_GOSTR341112_256_WITH_MAGMA_MGM_S N N [RFC9367]
407 0xC1,0x07-FF Unassigned
408 0xC2-C9,* Unassigned
409 0xCA,0x00-C9 Unassigned
410 0xCA,0xCA Reserved Y N [RFC8701]
411 0xCA,0xCB-FF Unassigned
412 0xCB,* Unassigned
413 0xCC,0x00-A7 Unassigned
414 0xCC,0xA8 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 Y Y [RFC7905]
415 0xCC,0xA9 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 Y Y [RFC7905]
416 0xCC,0xAA TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 Y Y [RFC7905]
417 0xCC,0xAB TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 Y N [RFC7905]
418 0xCC,0xAC TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 Y Y [RFC7905]
419 0xCC,0xAD TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 Y Y [RFC7905]
420 0xCC,0xAE TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 Y N [RFC7905]
421 0xCC,0xAF-FF Unassigned
422 0xCD-CF,* Unassigned
423 0xD0,0x00 Unassigned
424 0xD0,0x01 TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 Y Y [RFC8442]
425 0xD0,0x02 TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 Y Y [RFC8442]
426 0xD0,0x03 TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256 Y N [RFC8442]
427 0xD0,0x04 Unassigned
428 0xD0,0x05 TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 Y Y [RFC8442]
429 0xD0,0x06-FF Unassigned
430 0xD1-D9,* Unassigned
431 0xDA,0x00-D9 Unassigned
432 0xDA,0xDA Reserved Y N [RFC8701]
433 0xDA,0xDB-FF Unassigned
434 0xDB-E9,* Unassigned
435 0xEA,0x00-E9 Unassigned
436 0xEA,0xEA Reserved Y N [RFC8701]
437 0xEA,0xEB-FF Unassigned
438 0xEB-F9,* Unassigned
439 0xFA,0x00-C9 Unassigned
440 0xFA,0xFA Reserved Y N [RFC8701]
441 0xFA,0xFB-FF Unassigned
442 0xFB-FD,* Unassigned
443 0xFE,0x00-FD Unassigned
444 0xFE,0xFE-FF Reserved to avoid conflicts with widely deployed implementations [Pasi_Eronen]
445 0xFF,0x00-FF Reserved for Private Use [RFC8446]

View File

@ -0,0 +1,110 @@
// SPDX-FileCopyrightText: 2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
// Inspired by Andrew Ayer's tlshacks:
// https://github.com/AGWA/tlshacks/blob/main/generate_ciphersuites.go
package clienthello
import (
_ "embed"
"encoding/csv"
"fmt"
"io"
"log"
"strconv"
"strings"
)
// https://www.iana.org/assignments/tls-parameters/tls-parameters-4.csv
//
//go:embed cipher-suites.csv
var cipherSuitesCSV string
var CipherSuiteList = parseCipherSuitesCSV()
type CipherSuite any // (uint16 | CipherSuiteInfo)
type CipherSuiteInfo = struct {
Code uint16 `json:"code"`
HexCode string `json:"hex_code"`
Name string `json:"name"`
Recommended bool `json:"-"`
Reference string `json:"-"`
}
// TLS signaling cipher suite values
const (
scsvRenegotiation uint16 = 0x00ff
)
func parseCipherSuitesCSV() map[uint16]CipherSuiteInfo {
cipherSuites := map[uint16]CipherSuiteInfo{}
r := csv.NewReader(strings.NewReader(cipherSuitesCSV))
// Skip CSV header.
_, err := r.Read()
if err != nil {
log.Fatal(err)
}
for {
row, err := r.Read()
if err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
var (
val = row[0]
desc = row[1]
rec = row[3]
ref = row[4]
)
if desc == "Unassigned" {
continue
}
if strings.HasPrefix(desc, "Reserved") && ref != "[RFC8701]" {
continue
}
val = strings.Replace(val, ",", "", 1)
val = strings.Replace(val, "0x", "", 2)
code, err := strconv.ParseUint(val, 16, 16)
if err != nil {
log.Println(err)
}
suite := CipherSuiteInfo{
Code: uint16(code),
HexCode: val,
Name: desc,
Reference: ref,
}
if rec == "Y" {
suite.Recommended = true
}
if ref == "[RFC8701]" {
suite.Name = "GREASE"
}
cipherSuites[suite.Code] = suite
}
return cipherSuites
}
func GetCipherSuiteInfo(cipherSuiteCode uint16) CipherSuiteInfo {
info, found := CipherSuiteList[cipherSuiteCode]
if !found {
info = CipherSuiteInfo{
Code: cipherSuiteCode,
HexCode: fmt.Sprintf("%04X", cipherSuiteCode),
}
}
return info
}
func (m *ClientHelloMsg) AddCipherSuiteInfo() {
for i, suite := range m.CipherSuites {
m.CipherSuites[i] = GetCipherSuiteInfo(suite.(uint16))
}
}

View File

@ -0,0 +1,463 @@
// SPDX-FileCopyrightText: 2009 The Go Authors
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
// Based on Go's crypto/tls library:
// https://github.com/golang/go/blob/master/src/crypto/tls/handshake_messages.go#L69
// https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/crypto/tls/handshake_messages.go;l=69
package clienthello
import (
"crypto/md5"
"encoding/binary"
"encoding/hex"
"golang.org/x/crypto/cryptobyte"
"log"
"strconv"
"strings"
)
// Check if this is a GREASE value (RFC 8701).
func isGREASE(value uint16) bool {
// Values for: cipher suites, ALPN,
// extensions, named groups, signature algorithms and TLS versions:
greaseValues := [16]uint16{
0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a, 0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a,
0x8a8a, 0x9a9a, 0xaaaa, 0xbaba, 0xcaca, 0xdada, 0xeaea, 0xfafa,
}
// Run the check
for _, greaseValue := range greaseValues {
if value == greaseValue {
return true
}
}
return false
}
// readUint8LengthPrefixed acts like s.ReadUint8LengthPrefixed, but targets a
// []byte instead of a cryptobyte.String.
func readUint8LengthPrefixed(s *cryptobyte.String, out *[]byte) bool {
return s.ReadUint8LengthPrefixed((*cryptobyte.String)(out))
}
// readUint16LengthPrefixed acts like s.ReadUint16LengthPrefixed, but targets a
// []byte instead of a cryptobyte.String.
func readUint16LengthPrefixed(s *cryptobyte.String, out *[]byte) bool {
return s.ReadUint16LengthPrefixed((*cryptobyte.String)(out))
}
type byteSlice []byte
func (bs byteSlice) MarshalText() ([]byte, error) {
// Used in json.Marshal() to convert []byte to hex string.
return []byte(hex.EncodeToString(bs)), nil
}
type highlights struct {
//SupportedTLSVersions []uint16
GMTUnixTime uint32 `json:"gmt_unix_time"` // first 4 bytes of client random
SecureRenegotiationSupport bool `json:"secure_renegotiation_support"`
OCSPStaplingSupport bool `json:"ocsp_stapling_support"`
SCTSupport bool `json:"sct_support"`
// Go's crypto/tls server does not support early data.
EarlyData bool `json:"-"` // don't include in JSON
JA3 string `json:"ja3"`
JA3MD5 byteSlice `json:"ja3_md5"`
}
type ClientHelloMsg struct {
Raw byteSlice `json:"raw"`
RecordHeaderTLSVersion TLSVersion `json:"record_header_tls_version"` // TLSv1.0 (769)
TLSVersion TLSVersion `json:"client_tls_version"` // TLSv1.2 (771)
Random byteSlice `json:"random"`
SessionID byteSlice `json:"session_id"`
CipherSuites []CipherSuite `json:"cipher_suites"`
CompressionMethods []CompressionMethod `json:"compression_methods"`
Extensions []Extension `json:"extensions"`
Highlights highlights `json:"highlights"`
}
func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
*m = ClientHelloMsg{Raw: data}
s := cryptobyte.String(data)
var recordHeaderTLSVersion uint16
var tlsVersion uint16
var random []byte
var sessionID []byte
if !s.Skip(1) || !s.ReadUint16(&recordHeaderTLSVersion) || !s.Skip(2) ||
!s.Skip(4) || // message type and uint24 length field
!s.ReadUint16(&tlsVersion) || !s.ReadBytes(&random, 32) ||
!readUint8LengthPrefixed(&s, &sessionID) {
return false
}
m.RecordHeaderTLSVersion = recordHeaderTLSVersion
m.TLSVersion = tlsVersion
m.Random = random
m.Highlights.GMTUnixTime = binary.BigEndian.Uint32(random[0:4])
m.SessionID = sessionID
m.CipherSuites = []CipherSuite{}
var cipherSuites cryptobyte.String
if !s.ReadUint16LengthPrefixed(&cipherSuites) {
return false
}
m.Highlights.SecureRenegotiationSupport = false
for !cipherSuites.Empty() {
var suite uint16
if !cipherSuites.ReadUint16(&suite) {
return false
}
if suite == scsvRenegotiation {
m.Highlights.SecureRenegotiationSupport = true
}
m.CipherSuites = append(m.CipherSuites, suite)
}
var compressionMethods []uint8
if !readUint8LengthPrefixed(&s, &compressionMethods) {
return false
}
for _, cm := range compressionMethods {
m.CompressionMethods = append(m.CompressionMethods, cm)
}
if s.Empty() {
// ClientHello is optionally followed by extension data
return true
}
var extensions cryptobyte.String
if !s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() {
return false
}
for !extensions.Empty() {
var extCode uint16
var extData cryptobyte.String
if !extensions.ReadUint16(&extCode) ||
!extensions.ReadUint16LengthPrefixed(&extData) {
return false
}
var extension = GetExtensionInfo(extCode)
extension.Data.Raw = []byte(extData)
switch extension.Code {
case extensionServerName:
// Server Name Indication
// RFC 6066, Section 3
var nameList cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&nameList) || nameList.Empty() {
return false
}
for !nameList.Empty() {
var nameType uint8
var serverName cryptobyte.String
if !nameList.ReadUint8(&nameType) ||
!nameList.ReadUint16LengthPrefixed(&serverName) ||
serverName.Empty() {
return false
}
if nameType != 0 {
continue
}
if len(extension.Data.ServerName) != 0 {
// Multiple names of the same name_type are prohibited.
return false
}
sn := string(serverName)
extension.Data.ServerName = sn
// An SNI value may not include a trailing dot.
if strings.HasSuffix(sn, ".") {
return false
}
}
case extensionNextProtoNeg:
// Next Protocol Negotiation
// draft-agl-tls-nextprotoneg-04 (not IANA assiged)
extension.Name = "next_protocol_negotiation"
case extensionStatusRequest:
// Certificate Status Request
// RFC 4366, Section 3.6
var ignored cryptobyte.String
if !extData.ReadUint8(&extension.Data.StatusType) ||
!extData.ReadUint16LengthPrefixed(&ignored) || // responder_id_list
!extData.ReadUint16LengthPrefixed(&ignored) { // request_extensions
return false
}
m.Highlights.OCSPStaplingSupport = extension.Data.StatusType == statusTypeOCSP
case extensionSupportedGroups:
// Supported Groups (former name: elliptic_curves)
// RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7
var groups cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&groups) || groups.Empty() {
return false
}
extension.Data.SupportedGroups = make([]NamedGroup, 0)
for !groups.Empty() {
var group uint16
if !groups.ReadUint16(&group) {
return false
}
extension.Data.SupportedGroups = append(
extension.Data.SupportedGroups, group)
}
case extensionSupportedPointFormats:
// Supported Point Formats
// RFC 4492, Section 5.1.2
var supportedPointFormats []uint8
if !readUint8LengthPrefixed(&extData, &supportedPointFormats) ||
len(supportedPointFormats) == 0 {
return false
}
extension.Data.SupportedPointFormats = make(
[]ECPointFormat, len(supportedPointFormats))
for i, pointFormatCode := range supportedPointFormats {
extension.Data.SupportedPointFormats[i] = pointFormatCode
}
case extensionSessionTicket:
// Session Ticket
// RFC 5077, Section 3.2
case extensionSignatureAlgorithms:
// Signature Algorithms
// RFC 5246, Section 7.4.1.4.1
extension.Data.SupportedSignatureAlgorithms = []SignatureScheme{}
var sigAndAlgs cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() {
return false
}
for !sigAndAlgs.Empty() {
var sigAndAlg uint16
if !sigAndAlgs.ReadUint16(&sigAndAlg) {
return false
}
extension.Data.SupportedSignatureAlgorithms = append(
extension.Data.SupportedSignatureAlgorithms, sigAndAlg)
}
case extensionSignatureAlgorithmsCert:
// Signature Algorithms Cert
// RFC 8446, Section 4.2.3
extension.Data.SupportedSignatureAlgorithms = []SignatureScheme{}
var sigAndAlgs cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&sigAndAlgs) || sigAndAlgs.Empty() {
return false
}
for !sigAndAlgs.Empty() {
var sigAndAlg uint16
if !sigAndAlgs.ReadUint16(&sigAndAlg) {
return false
}
extension.Data.SupportedSignatureAlgorithms = append(
extension.Data.SupportedSignatureAlgorithms, sigAndAlg)
}
case extensionRenegotiationInfo:
// Renegotiation Indication
// RFC 5746, Section 3.2
if !readUint8LengthPrefixed(
&extData,
&extension.Data.RenegotiationInfo) {
return false
}
m.Highlights.SecureRenegotiationSupport = true
case extensionALPN:
// Application-Layer Protocol Negotiation
// RFC 7301, Section 3.1
var protoList cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() {
return false
}
for !protoList.Empty() {
var proto cryptobyte.String
if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() {
return false
}
extension.Data.ALPNProtocols = append(
extension.Data.ALPNProtocols, string(proto))
}
case extensionSCT:
// Signed Certificate Timestamp
// RFC 6962, Section 3.3.1
m.Highlights.SCTSupport = true
case extensionSupportedVersions:
// Supported Versions
// RFC 8446, Section 4.2.1
var versList cryptobyte.String
extension.Data.SupportedVersions = []TLSVersion{}
if !extData.ReadUint8LengthPrefixed(&versList) || versList.Empty() {
return false
}
for !versList.Empty() {
var vers uint16
if !versList.ReadUint16(&vers) {
return false
}
extension.Data.SupportedVersions = append(
extension.Data.SupportedVersions, vers)
}
case extensionCookie:
// Cookie
// RFC 8446, Section 4.2.2
var cookie []byte
if !readUint16LengthPrefixed(&extData, &cookie) ||
len(extension.Data.Cookie) == 0 {
return false
}
extension.Data.Cookie = cookie
case extensionKeyShare:
// Key Share
// RFC 8446, Section 4.2.8
var clientShares cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&clientShares) {
return false
}
for !clientShares.Empty() {
var ks KeyShare
var ksGroup uint16
var ksData []byte
if !clientShares.ReadUint16(&ksGroup) ||
!readUint16LengthPrefixed(&clientShares, &ksData) ||
len(ksData) == 0 {
return false
}
ks.Group = ksGroup
ks.Data = ksData
extension.Data.KeyShares = append(extension.Data.KeyShares, ks)
}
case extensionEarlyData:
// Early Data Indication
// RFC 8446, Section 4.2.10
m.Highlights.EarlyData = true
case extensionPSKModes:
// Pre-Shared Key Exchange Modes
// RFC 8446, Section 4.2.9
var pskModes []uint8
if !readUint8LengthPrefixed(&extData, &pskModes) {
return false
}
for _, pskMode := range pskModes {
extension.Data.PSKModes = append(extension.Data.PSKModes, pskMode)
}
case extensionPreSharedKey:
// Pre-Shared Key
// RFC 8446, Section 4.2.11
if !extensions.Empty() {
return false // pre_shared_key must be the last extension
}
var identities cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&identities) || identities.Empty() {
return false
}
for !identities.Empty() {
var psk PSKIdentity
var identity []byte
if !readUint16LengthPrefixed(&identities, &identity) ||
!identities.ReadUint32(&psk.ObfuscatedTicketAge) ||
len(identity) == 0 {
return false
}
psk.Identity = identity
extension.Data.PSKIdentities = append(extension.Data.PSKIdentities, psk)
}
var binders cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&binders) || binders.Empty() {
return false
}
for !binders.Empty() {
var binder []byte
if !readUint8LengthPrefixed(&binders, &binder) ||
len(binder) == 0 {
return false
}
extension.Data.PSKBinders = append(extension.Data.PSKBinders, binder)
}
case extensionPadding:
// Padding
// RFC 7685
extension.Data.Length = uint16(len(extData))
case extensionCompressCertificate:
// Certificate Compression
// RFC 8879
// TODO: parse - https://www.rfc-editor.org/rfc/rfc8879.html
case extensionApplicationSettings:
// Application-Layer Protocol Settings
// draft-vvv-tls-alps (not IANA assiged)
extension.Name = " application_settings"
// TODO: parse - https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps
}
m.Extensions = append(m.Extensions, extension)
if extension.Name == "" {
log.Println("Unknown extension:", extension.Code)
}
if !extData.Empty() &&
extension.Name != "GREASE" &&
extension.Code != extensionPadding {
log.Printf("Extension %d data not read.\n", extension.Code)
}
}
// JA3
var ja3 strings.Builder
var supportedGroups []NamedGroup
var supportedPointFormats []ECPointFormat
ja3.WriteString(strconv.FormatUint(uint64(m.TLSVersion.(uint16)), 10) + ",")
for i, cs := range m.CipherSuites {
if !isGREASE(cs.(uint16)) { // ignore GREASE values
ja3.WriteString(strconv.FormatUint(uint64(cs.(uint16)), 10))
if i+1 != len(m.CipherSuites) { // if not last element, add "-"
ja3.WriteString("-")
}
}
}
ja3.WriteString(",")
for i, e := range m.Extensions {
if !isGREASE(e.Code) { // ignore GREASE values
ja3.WriteString(strconv.FormatUint(uint64(e.Code), 10))
if i+1 != len(m.Extensions) { // if not last element, add "-"
ja3.WriteString("-")
}
if e.Code == extensionSupportedGroups {
supportedGroups = e.Data.SupportedGroups
} else if e.Code == extensionSupportedPointFormats {
supportedPointFormats = e.Data.SupportedPointFormats
}
}
}
ja3.WriteString(",")
for i, g := range supportedGroups {
if !isGREASE(g.(uint16)) { // ignore GREASE values
ja3.WriteString(strconv.FormatUint(uint64(g.(uint16)), 10))
if i+1 != len(supportedGroups) { // if not last element, add "-"
ja3.WriteString("-")
}
}
}
ja3.WriteString(",")
for i, pf := range supportedPointFormats {
ja3.WriteString(strconv.FormatUint(uint64(pf.(uint8)), 10))
if i+1 != len(supportedPointFormats) { // if not last element, add "-"
ja3.WriteString("-")
}
}
m.Highlights.JA3 = ja3.String()
hash := md5.Sum([]byte(m.Highlights.JA3))
m.Highlights.JA3MD5 = hash[:]
return true
}
// Add information about TLS versions, cipher suites, etc.
func (m *ClientHelloMsg) AddInfo() {
m.AddTLSVersionInfo()
m.AddCipherSuiteInfo()
m.AddSignatureSchemeInfo()
m.AddNamedGroupInfo() // supported_groups
m.AddECPointFormatInfo()
m.AddCompressionMethodInfo()
m.AddPSKModeInfo()
}

View File

@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
package clienthello
// https://www.rfc-editor.org/rfc/rfc3749#section-2
var CompressionMethodList = map[uint8]CompressionMethodInfo{
0: {Code: 0, Name: "null"},
1: {Code: 1, Name: "DEFLATE"},
}
type CompressionMethod any // (uint8 | CompressionMethodInfo)
type CompressionMethodInfo struct {
Code uint8 `json:"code"`
Name string `json:"name"`
}
func GetCompressionMethodInfo(compressionMethodCode uint8) CompressionMethodInfo {
info, found := CompressionMethodList[compressionMethodCode]
if !found {
info = CompressionMethodInfo{
Code: compressionMethodCode,
}
}
return info
}
func (m *ClientHelloMsg) AddCompressionMethodInfo() {
for i, code := range m.CompressionMethods {
m.CompressionMethods[i] = GetCompressionMethodInfo(code.(uint8))
}
}

View File

@ -0,0 +1,97 @@
Value,Extension Name,TLS 1.3,DTLS-Only,Recommended,Reference
0,server_name,"CH, EE, CR",N,Y,[RFC6066][RFC9261]
1,max_fragment_length,"CH, EE",N,N,[RFC6066][RFC8449]
2,client_certificate_url,-,N,Y,[RFC6066]
3,trusted_ca_keys,-,N,Y,[RFC6066]
4,truncated_hmac,-,N,N,[RFC6066][IESG Action 2018-08-16]
5,status_request,"CH, CR, CT",N,Y,[RFC6066]
6,user_mapping,-,N,Y,[RFC4681]
7,client_authz,-,N,N,[RFC5878]
8,server_authz,-,N,N,[RFC5878]
9,cert_type,-,N,N,[RFC6091]
10,"supported_groups (renamed from ""elliptic_curves"")","CH, EE",N,Y,[RFC8422][RFC7919]
11,ec_point_formats,-,N,Y,[RFC8422]
12,srp,-,N,N,[RFC5054]
13,signature_algorithms,"CH, CR",N,Y,[RFC8446]
14,use_srtp,"CH, EE",N,Y,[RFC5764]
15,heartbeat,"CH, EE",N,Y,[RFC6520]
16,application_layer_protocol_negotiation,"CH, EE",N,Y,[RFC7301]
17,status_request_v2,-,N,Y,[RFC6961]
18,signed_certificate_timestamp,"CH, CR, CT",N,N,[RFC6962]
19,client_certificate_type,"CH, EE",N,Y,[RFC7250]
20,server_certificate_type,"CH, EE",N,Y,[RFC7250]
21,padding,CH,N,Y,[RFC7685]
22,encrypt_then_mac,-,N,Y,[RFC7366]
23,extended_master_secret,-,N,Y,[RFC7627]
24,token_binding,-,N,Y,[RFC8472]
25,cached_info,-,N,Y,[RFC7924]
26,tls_lts,-,N,N,[draft-gutmann-tls-lts]
27,compress_certificate,"CH, CR",N,Y,[RFC8879]
28,record_size_limit,"CH, EE",N,Y,[RFC8449]
29,pwd_protect,CH,N,N,[RFC8492]
30,pwd_clear,CH,N,N,[RFC8492]
31,password_salt,"CH, SH, HRR",N,N,[RFC8492]
32,ticket_pinning,"CH, EE",N,N,[RFC8672]
33,tls_cert_with_extern_psk,"CH, SH",N,N,[RFC8773]
34,delegated_credential,"CH, CR, CT",N,Y,[RFC-ietf-tls-subcerts-15]
35,"session_ticket (renamed from ""SessionTicket TLS"")",-,N,Y,[RFC5077][RFC8447]
36,TLMSP,-,N,N,[ETSI TS 103 523-2]
37,TLMSP_proxying,-,N,N,[ETSI TS 103 523-2]
38,TLMSP_delegate,-,N,N,[ETSI TS 103 523-2]
39,supported_ekt_ciphers,"CH, EE",N,Y,[RFC8870]
40,Reserved,,,,[tls-reg-review mailing list]
41,pre_shared_key,"CH, SH",N,Y,[RFC8446]
42,early_data,"CH, EE, NST",N,Y,[RFC8446]
43,supported_versions,"CH, SH, HRR",N,Y,[RFC8446]
44,cookie,"CH, HRR",N,Y,[RFC8446]
45,psk_key_exchange_modes,CH,N,Y,[RFC8446]
46,Reserved,,,,[tls-reg-review mailing list]
47,certificate_authorities,"CH, CR",N,Y,[RFC8446]
48,oid_filters,CR,N,Y,[RFC8446]
49,post_handshake_auth,CH,N,Y,[RFC8446]
50,signature_algorithms_cert,"CH, CR",N,Y,[RFC8446]
51,key_share,"CH, SH, HRR",N,Y,[RFC8446]
52,transparency_info,"CH, CR, CT",N,Y,[RFC9162]
53,connection_id (deprecated),-,Y,N,[RFC9146]
54,connection_id,"CH, SH",Y,N,[RFC9146]
55,external_id_hash,"CH, EE",N,Y,[RFC8844]
56,external_session_id,"CH, EE",N,Y,[RFC8844]
57,quic_transport_parameters,"CH, EE",N,Y,[RFC9001]
58,ticket_request,"CH, EE",N,Y,[RFC9149]
59,dnssec_chain,"CH, CT",N,N,[RFC9102][RFC Errata 6860]
60-2569,Unassigned,,,,
2570,Reserved,"CH, CR, NST",N,N,[RFC8701]
2571-6681,Unassigned,,,,
6682,Reserved,"CH, CR, NST",N,N,[RFC8701]
6683-10793,Unassigned,,,,
10794,Reserved,"CH, CR, NST",N,N,[RFC8701]
10795-14905,Unassigned,,,,
14906,Reserved,"CH, CR, NST",N,N,[RFC8701]
14907-19017,Unassigned,,,,
19018,Reserved,"CH, CR, NST",N,N,[RFC8701]
19019-23129,Unassigned,,,,
23130,Reserved,"CH, CR, NST",N,N,[RFC8701]
23131-27241,Unassigned,,,,
27242,Reserved,"CH, CR, NST",N,N,[RFC8701]
27243-31353,Unassigned,,,,
31354,Reserved,"CH, CR, NST",N,N,[RFC8701]
31355-35465,Unassigned,,,,
35466,Reserved,"CH, CR, NST",N,N,[RFC8701]
35467-39577,Unassigned,,,,
39578,Reserved,"CH, CR, NST",N,N,[RFC8701]
39579-43689,Unassigned,,,,
43690,Reserved,"CH, CR, NST",N,N,[RFC8701]
43691-47801,Unassigned,,,,
47802,Reserved,"CH, CR, NST",N,N,[RFC8701]
47803-51913,Unassigned,,,,
51914,Reserved,"CH, CR, NST",N,N,[RFC8701]
51915-56025,Unassigned,,,,
56026,Reserved,"CH, CR, NST",N,N,[RFC8701]
56027-60137,Unassigned,,,,
60138,Reserved,"CH, CR, NST",N,N,[RFC8701]
60139-64249,Unassigned,,,,
64250,Reserved,"CH, CR, NST",N,N,[RFC8701]
64251-65279,Unassigned,,,,
65280,Reserved for Private Use,,,,[RFC8446]
65281,renegotiation_info,-,N,Y,[RFC5746]
65282-65535,Reserved for Private Use,,,,[RFC8446]
1 Value Extension Name TLS 1.3 DTLS-Only Recommended Reference
2 0 server_name CH, EE, CR N Y [RFC6066][RFC9261]
3 1 max_fragment_length CH, EE N N [RFC6066][RFC8449]
4 2 client_certificate_url - N Y [RFC6066]
5 3 trusted_ca_keys - N Y [RFC6066]
6 4 truncated_hmac - N N [RFC6066][IESG Action 2018-08-16]
7 5 status_request CH, CR, CT N Y [RFC6066]
8 6 user_mapping - N Y [RFC4681]
9 7 client_authz - N N [RFC5878]
10 8 server_authz - N N [RFC5878]
11 9 cert_type - N N [RFC6091]
12 10 supported_groups (renamed from "elliptic_curves") CH, EE N Y [RFC8422][RFC7919]
13 11 ec_point_formats - N Y [RFC8422]
14 12 srp - N N [RFC5054]
15 13 signature_algorithms CH, CR N Y [RFC8446]
16 14 use_srtp CH, EE N Y [RFC5764]
17 15 heartbeat CH, EE N Y [RFC6520]
18 16 application_layer_protocol_negotiation CH, EE N Y [RFC7301]
19 17 status_request_v2 - N Y [RFC6961]
20 18 signed_certificate_timestamp CH, CR, CT N N [RFC6962]
21 19 client_certificate_type CH, EE N Y [RFC7250]
22 20 server_certificate_type CH, EE N Y [RFC7250]
23 21 padding CH N Y [RFC7685]
24 22 encrypt_then_mac - N Y [RFC7366]
25 23 extended_master_secret - N Y [RFC7627]
26 24 token_binding - N Y [RFC8472]
27 25 cached_info - N Y [RFC7924]
28 26 tls_lts - N N [draft-gutmann-tls-lts]
29 27 compress_certificate CH, CR N Y [RFC8879]
30 28 record_size_limit CH, EE N Y [RFC8449]
31 29 pwd_protect CH N N [RFC8492]
32 30 pwd_clear CH N N [RFC8492]
33 31 password_salt CH, SH, HRR N N [RFC8492]
34 32 ticket_pinning CH, EE N N [RFC8672]
35 33 tls_cert_with_extern_psk CH, SH N N [RFC8773]
36 34 delegated_credential CH, CR, CT N Y [RFC-ietf-tls-subcerts-15]
37 35 session_ticket (renamed from "SessionTicket TLS") - N Y [RFC5077][RFC8447]
38 36 TLMSP - N N [ETSI TS 103 523-2]
39 37 TLMSP_proxying - N N [ETSI TS 103 523-2]
40 38 TLMSP_delegate - N N [ETSI TS 103 523-2]
41 39 supported_ekt_ciphers CH, EE N Y [RFC8870]
42 40 Reserved [tls-reg-review mailing list]
43 41 pre_shared_key CH, SH N Y [RFC8446]
44 42 early_data CH, EE, NST N Y [RFC8446]
45 43 supported_versions CH, SH, HRR N Y [RFC8446]
46 44 cookie CH, HRR N Y [RFC8446]
47 45 psk_key_exchange_modes CH N Y [RFC8446]
48 46 Reserved [tls-reg-review mailing list]
49 47 certificate_authorities CH, CR N Y [RFC8446]
50 48 oid_filters CR N Y [RFC8446]
51 49 post_handshake_auth CH N Y [RFC8446]
52 50 signature_algorithms_cert CH, CR N Y [RFC8446]
53 51 key_share CH, SH, HRR N Y [RFC8446]
54 52 transparency_info CH, CR, CT N Y [RFC9162]
55 53 connection_id (deprecated) - Y N [RFC9146]
56 54 connection_id CH, SH Y N [RFC9146]
57 55 external_id_hash CH, EE N Y [RFC8844]
58 56 external_session_id CH, EE N Y [RFC8844]
59 57 quic_transport_parameters CH, EE N Y [RFC9001]
60 58 ticket_request CH, EE N Y [RFC9149]
61 59 dnssec_chain CH, CT N N [RFC9102][RFC Errata 6860]
62 60-2569 Unassigned
63 2570 Reserved CH, CR, NST N N [RFC8701]
64 2571-6681 Unassigned
65 6682 Reserved CH, CR, NST N N [RFC8701]
66 6683-10793 Unassigned
67 10794 Reserved CH, CR, NST N N [RFC8701]
68 10795-14905 Unassigned
69 14906 Reserved CH, CR, NST N N [RFC8701]
70 14907-19017 Unassigned
71 19018 Reserved CH, CR, NST N N [RFC8701]
72 19019-23129 Unassigned
73 23130 Reserved CH, CR, NST N N [RFC8701]
74 23131-27241 Unassigned
75 27242 Reserved CH, CR, NST N N [RFC8701]
76 27243-31353 Unassigned
77 31354 Reserved CH, CR, NST N N [RFC8701]
78 31355-35465 Unassigned
79 35466 Reserved CH, CR, NST N N [RFC8701]
80 35467-39577 Unassigned
81 39578 Reserved CH, CR, NST N N [RFC8701]
82 39579-43689 Unassigned
83 43690 Reserved CH, CR, NST N N [RFC8701]
84 43691-47801 Unassigned
85 47802 Reserved CH, CR, NST N N [RFC8701]
86 47803-51913 Unassigned
87 51914 Reserved CH, CR, NST N N [RFC8701]
88 51915-56025 Unassigned
89 56026 Reserved CH, CR, NST N N [RFC8701]
90 56027-60137 Unassigned
91 60138 Reserved CH, CR, NST N N [RFC8701]
92 60139-64249 Unassigned
93 64250 Reserved CH, CR, NST N N [RFC8701]
94 64251-65279 Unassigned
95 65280 Reserved for Private Use [RFC8446]
96 65281 renegotiation_info - N Y [RFC5746]
97 65282-65535 Reserved for Private Use [RFC8446]

159
clienthello/extensions.go Normal file
View File

@ -0,0 +1,159 @@
// SPDX-FileCopyrightText: 2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
// Inspired by Andrew Ayer's tlshacks:
// https://github.com/AGWA/tlshacks/blob/main/generate_extensions.go
package clienthello
import (
_ "embed"
"encoding/csv"
"io"
"log"
"strconv"
"strings"
)
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values-1.csv
//
//go:embed extensions.csv
var extensionsCSV string
var ExtensionList = parseExtensionsCSV()
// === CONSTANTS ===
// TLS extension codes
const (
extensionServerName uint16 = 0
extensionStatusRequest uint16 = 5
extensionSupportedGroups uint16 = 10 // elliptic_curves in TLS versions prior to 1.3, see RFC 8446, Section 4.2.7
extensionSupportedPointFormats uint16 = 11
extensionSignatureAlgorithms uint16 = 13
extensionALPN uint16 = 16
extensionSCT uint16 = 18
extensionPadding uint16 = 21
extensionEncryptThenMac uint16 = 22
extensionExtendedMasterSecret uint16 = 23
extensionCompressCertificate uint16 = 27
extensionSessionTicket uint16 = 35
extensionPreSharedKey uint16 = 41
extensionEarlyData uint16 = 42
extensionSupportedVersions uint16 = 43
extensionCookie uint16 = 44
extensionPSKModes uint16 = 45
extensionCertificateAuthorities uint16 = 47
extensionPostHandshakeAuth uint16 = 49
extensionSignatureAlgorithmsCert uint16 = 50
extensionKeyShare uint16 = 51
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionApplicationSettings uint16 = 17513 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
)
// TLS CertificateStatusType (RFC 3546)
const (
statusTypeOCSP uint8 = 1
)
// === STRUCTS ===
// TLS 1.3 PSK Identity. Can be a Session Ticket, or a reference to a saved
// session. See RFC 8446, Section 4.2.11.
type PSKIdentity struct {
Identity byteSlice `json:"identity"`
ObfuscatedTicketAge uint32 `json:"obfuscated_ticket_age"`
}
type ExtensionData struct {
Raw byteSlice `json:"raw"`
ServerName string `json:"server_name,omitempty"`
StatusType uint8 `json:"status_type,omitempty"`
SupportedGroups []NamedGroup `json:"supported_groups,omitempty"`
SupportedPointFormats []ECPointFormat `json:"supported_point_formats,omitempty"`
SupportedSignatureAlgorithms []SignatureScheme `json:"supported_signature_algorithms,omitempty"`
RenegotiationInfo []byte `json:"renegotiation_info,omitempty"`
ALPNProtocols []string `json:"alpn_protocols,omitempty"`
SupportedVersions []TLSVersion `json:"supported_tls_versions,omitempty"`
Cookie byteSlice `json:"cookie,omitempty"`
KeyShares []KeyShare `json:"key_shares,omitempty"`
PSKModes []PSKMode `json:"psk_modes,omitempty"`
PSKIdentities []PSKIdentity `json:"psk_identities,omitempty"`
PSKBinders []byteSlice `json:"psk_binders,omitempty"`
Length uint16 `json:"length,omitempty"` // padding
}
type Extension struct {
Code uint16 `json:"code"`
Name string `json:"name"`
Recommended bool `json:"-"`
Reference string `json:"-"`
Data ExtensionData `json:"data"`
}
// === FUNCTIONS ===
func parseExtensionsCSV() map[uint16]Extension {
extensions := map[uint16]Extension{}
r := csv.NewReader(strings.NewReader(extensionsCSV))
// Skip CSV header.
_, err := r.Read()
if err != nil {
log.Fatal(err)
}
for {
row, err := r.Read()
if err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
var (
val = row[0]
name = row[1]
rec = row[4]
ref = row[5]
)
if name == "Unassigned" {
continue
}
if strings.HasPrefix(name, "Reserved") && ref != "[RFC8701]" {
continue
}
code, err := strconv.Atoi(val)
if err != nil {
log.Println(err)
}
// Deal with names like "supported_groups (renamed from "elliptic_curves")"
// by stopping at the first space.
name = strings.SplitN(name, " ", 2)[0]
ext := Extension{
Code: uint16(code),
Name: name,
Reference: ref,
}
if rec == "Y" {
ext.Recommended = true
}
if ref == "[RFC8701]" {
ext.Name = "GREASE"
}
extensions[ext.Code] = ext
}
return extensions
}
func GetExtensionInfo(extensionCode uint16) Extension {
info, found := ExtensionList[extensionCode]
if !found {
info = Extension{
Code: extensionCode,
}
}
return info
}

View File

@ -0,0 +1,89 @@
Value,Description,DTLS-OK,Recommended,Reference,Comment
0,Reserved,,,[RFC8447],
1,sect163k1,Y,N,[RFC8422],
2,sect163r1,Y,N,[RFC8422],
3,sect163r2,Y,N,[RFC8422],
4,sect193r1,Y,N,[RFC8422],
5,sect193r2,Y,N,[RFC8422],
6,sect233k1,Y,N,[RFC8422],
7,sect233r1,Y,N,[RFC8422],
8,sect239k1,Y,N,[RFC8422],
9,sect283k1,Y,N,[RFC8422],
10,sect283r1,Y,N,[RFC8422],
11,sect409k1,Y,N,[RFC8422],
12,sect409r1,Y,N,[RFC8422],
13,sect571k1,Y,N,[RFC8422],
14,sect571r1,Y,N,[RFC8422],
15,secp160k1,Y,N,[RFC8422],
16,secp160r1,Y,N,[RFC8422],
17,secp160r2,Y,N,[RFC8422],
18,secp192k1,Y,N,[RFC8422],
19,secp192r1,Y,N,[RFC8422],
20,secp224k1,Y,N,[RFC8422],
21,secp224r1,Y,N,[RFC8422],
22,secp256k1,Y,N,[RFC8422],
23,secp256r1,Y,Y,[RFC8422],
24,secp384r1,Y,Y,[RFC8422],
25,secp521r1,Y,N,[RFC8422],
26,brainpoolP256r1,Y,N,[RFC7027],
27,brainpoolP384r1,Y,N,[RFC7027],
28,brainpoolP512r1,Y,N,[RFC7027],
29,x25519,Y,Y,[RFC8446][RFC8422],
30,x448,Y,Y,[RFC8446][RFC8422],
31,brainpoolP256r1tls13,Y,N,[RFC8734],
32,brainpoolP384r1tls13,Y,N,[RFC8734],
33,brainpoolP512r1tls13,Y,N,[RFC8734],
34,GC256A,Y,N,[RFC9189],
35,GC256B,Y,N,[RFC9189],
36,GC256C,Y,N,[RFC9189],
37,GC256D,Y,N,[RFC9189],
38,GC512A,Y,N,[RFC9189],
39,GC512B,Y,N,[RFC9189],
40,GC512C,Y,N,[RFC9189],
41,curveSM2,N,N,[RFC8998],
42-255,Unassigned,,,,
256,ffdhe2048,Y,N,[RFC7919],
257,ffdhe3072,Y,N,[RFC7919],
258,ffdhe4096,Y,N,[RFC7919],
259,ffdhe6144,Y,N,[RFC7919],
260,ffdhe8192,Y,N,[RFC7919],
261-507,Unassigned,,,,
508-511,Reserved for Private Use,,,[RFC7919],
512-2569,Unassigned,,,,
2570,Reserved,Y,N,[RFC8701],
2571-6681,Unassigned,,,,
6682,Reserved,Y,N,[RFC8701],
6683-10793,Unassigned,,,,
10794,Reserved,Y,N,[RFC8701],
10795-14905,Unassigned,,,,
14906,Reserved,Y,N,[RFC8701],
14907-19017,Unassigned,,,,
19018,Reserved,Y,N,[RFC8701],
19019-23129,Unassigned,,,,
23130,Reserved,Y,N,[RFC8701],
23131-27241,Unassigned,,,,
27242,Reserved,Y,N,[RFC8701],
27243-31353,Unassigned,,,,
31354,Reserved,Y,N,[RFC8701],
31355-35465,Unassigned,,,,
35466,Reserved,Y,N,[RFC8701],
35467-39577,Unassigned,,,,
39578,Reserved,Y,N,[RFC8701],
39579-43689,Unassigned,,,,
43690,Reserved,Y,N,[RFC8701],
43691-47801,Unassigned,,,,
47802,Reserved,Y,N,[RFC8701],
47803-51913,Unassigned,,,,
51914,Reserved,Y,N,[RFC8701],
51915-56025,Unassigned,,,,
56026,Reserved,Y,N,[RFC8701],
56027-60137,Unassigned,,,,
60138,Reserved,Y,N,[RFC8701],
60139-64249,Unassigned,,,,
64250,Reserved,Y,N,[RFC8701],
64251-65023,Unassigned,,,,
65024-65279,Reserved for Private Use,,,[RFC8422],
65280,Unassigned,,,,
65281,arbitrary_explicit_prime_curves,Y,N,[RFC8422],
65282,arbitrary_explicit_char2_curves,Y,N,[RFC8422],
65283-65535,Unassigned,,,,
1 Value Description DTLS-OK Recommended Reference Comment
2 0 Reserved [RFC8447]
3 1 sect163k1 Y N [RFC8422]
4 2 sect163r1 Y N [RFC8422]
5 3 sect163r2 Y N [RFC8422]
6 4 sect193r1 Y N [RFC8422]
7 5 sect193r2 Y N [RFC8422]
8 6 sect233k1 Y N [RFC8422]
9 7 sect233r1 Y N [RFC8422]
10 8 sect239k1 Y N [RFC8422]
11 9 sect283k1 Y N [RFC8422]
12 10 sect283r1 Y N [RFC8422]
13 11 sect409k1 Y N [RFC8422]
14 12 sect409r1 Y N [RFC8422]
15 13 sect571k1 Y N [RFC8422]
16 14 sect571r1 Y N [RFC8422]
17 15 secp160k1 Y N [RFC8422]
18 16 secp160r1 Y N [RFC8422]
19 17 secp160r2 Y N [RFC8422]
20 18 secp192k1 Y N [RFC8422]
21 19 secp192r1 Y N [RFC8422]
22 20 secp224k1 Y N [RFC8422]
23 21 secp224r1 Y N [RFC8422]
24 22 secp256k1 Y N [RFC8422]
25 23 secp256r1 Y Y [RFC8422]
26 24 secp384r1 Y Y [RFC8422]
27 25 secp521r1 Y N [RFC8422]
28 26 brainpoolP256r1 Y N [RFC7027]
29 27 brainpoolP384r1 Y N [RFC7027]
30 28 brainpoolP512r1 Y N [RFC7027]
31 29 x25519 Y Y [RFC8446][RFC8422]
32 30 x448 Y Y [RFC8446][RFC8422]
33 31 brainpoolP256r1tls13 Y N [RFC8734]
34 32 brainpoolP384r1tls13 Y N [RFC8734]
35 33 brainpoolP512r1tls13 Y N [RFC8734]
36 34 GC256A Y N [RFC9189]
37 35 GC256B Y N [RFC9189]
38 36 GC256C Y N [RFC9189]
39 37 GC256D Y N [RFC9189]
40 38 GC512A Y N [RFC9189]
41 39 GC512B Y N [RFC9189]
42 40 GC512C Y N [RFC9189]
43 41 curveSM2 N N [RFC8998]
44 42-255 Unassigned
45 256 ffdhe2048 Y N [RFC7919]
46 257 ffdhe3072 Y N [RFC7919]
47 258 ffdhe4096 Y N [RFC7919]
48 259 ffdhe6144 Y N [RFC7919]
49 260 ffdhe8192 Y N [RFC7919]
50 261-507 Unassigned
51 508-511 Reserved for Private Use [RFC7919]
52 512-2569 Unassigned
53 2570 Reserved Y N [RFC8701]
54 2571-6681 Unassigned
55 6682 Reserved Y N [RFC8701]
56 6683-10793 Unassigned
57 10794 Reserved Y N [RFC8701]
58 10795-14905 Unassigned
59 14906 Reserved Y N [RFC8701]
60 14907-19017 Unassigned
61 19018 Reserved Y N [RFC8701]
62 19019-23129 Unassigned
63 23130 Reserved Y N [RFC8701]
64 23131-27241 Unassigned
65 27242 Reserved Y N [RFC8701]
66 27243-31353 Unassigned
67 31354 Reserved Y N [RFC8701]
68 31355-35465 Unassigned
69 35466 Reserved Y N [RFC8701]
70 35467-39577 Unassigned
71 39578 Reserved Y N [RFC8701]
72 39579-43689 Unassigned
73 43690 Reserved Y N [RFC8701]
74 43691-47801 Unassigned
75 47802 Reserved Y N [RFC8701]
76 47803-51913 Unassigned
77 51914 Reserved Y N [RFC8701]
78 51915-56025 Unassigned
79 56026 Reserved Y N [RFC8701]
80 56027-60137 Unassigned
81 60138 Reserved Y N [RFC8701]
82 60139-64249 Unassigned
83 64250 Reserved Y N [RFC8701]
84 64251-65023 Unassigned
85 65024-65279 Reserved for Private Use [RFC8422]
86 65280 Unassigned
87 65281 arbitrary_explicit_prime_curves Y N [RFC8422]
88 65282 arbitrary_explicit_char2_curves Y N [RFC8422]
89 65283-65535 Unassigned

118
clienthello/named_groups.go Normal file
View File

@ -0,0 +1,118 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
package clienthello
import (
_ "embed"
"encoding/csv"
"fmt"
"io"
"log"
"strconv"
"strings"
)
// RFC 8446, Section 4.2.7
// https://www.rfc-editor.org/rfc/rfc8446.html#section-4.2.7
// https://www.iana.org/assignments/tls-parameters/tls-parameters-8.csv
//
//go:embed named-groups.csv
var namedGroupsCSV string
var NamedGroupList = parseNamedGroupsCSV()
type NamedGroup any // (uint16 | NamedGroupInfo)
type NamedGroupInfo struct {
Code uint16 `json:"code"`
HexCode string `json:"hex_code"`
Name string `json:"name"`
Recommended bool `json:"-"`
Reference string `json:"-"`
}
// TLS 1.3 Key Share. See RFC 8446, Section 4.2.8.
type KeyShare struct {
Group NamedGroup `json:"group"`
Data byteSlice `json:"data"`
}
func parseNamedGroupsCSV() map[uint16]NamedGroupInfo {
namedGroups := map[uint16]NamedGroupInfo{}
r := csv.NewReader(strings.NewReader(namedGroupsCSV))
// Skip CSV header.
_, err := r.Read()
if err != nil {
log.Fatal(err)
}
for {
row, err := r.Read()
if err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
var (
val = row[0]
desc = row[1]
rec = row[3]
ref = row[4]
)
if desc == "Unassigned" {
continue
}
if strings.HasPrefix(desc, "Reserved") && ref != "[RFC8701]" {
continue
}
code, err := strconv.Atoi(val)
if err != nil {
log.Println(err)
}
group := NamedGroupInfo{
Code: uint16(code),
HexCode: fmt.Sprintf("%04X", code),
Name: desc,
Reference: ref,
}
if rec == "Y" {
group.Recommended = true
}
if ref == "[RFC8701]" {
group.Name = "GREASE"
}
namedGroups[group.Code] = group
}
return namedGroups
}
func GetNamedGroupInfo(namedGroupCode uint16) NamedGroupInfo {
info, found := NamedGroupList[namedGroupCode]
if !found {
info = NamedGroupInfo{
Code: namedGroupCode,
HexCode: fmt.Sprintf("%04X", namedGroupCode),
}
}
return info
}
func (m *ClientHelloMsg) AddNamedGroupInfo() {
for i, ext := range m.Extensions {
switch ext.Code {
case extensionSupportedGroups:
for j, group := range ext.Data.SupportedGroups {
m.Extensions[i].Data.SupportedGroups[j] = GetNamedGroupInfo(group.(uint16))
}
case extensionKeyShare:
for j, kShare := range ext.Data.KeyShares {
m.Extensions[i].Data.KeyShares[j].Group = GetNamedGroupInfo(
kShare.Group.(uint16))
}
}
}
}

View File

@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
package clienthello
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
var ECPointFormatList = map[uint8]ECPointFormatInfo{
0: {Code: 0, Name: "uncompressed", Reference: "[RFC8422]"},
1: {Code: 1, Name: "ansiX962_compressed_prime", Reference: "[RFC8422]"},
2: {Code: 2, Name: "ansiX962_compressed_char2", Reference: "[RFC8422]"},
}
type ECPointFormat any // (uint8 | ECPointFormatInfo)
type ECPointFormatInfo struct {
Code uint8 `json:"code"`
Name string `json:"name"`
Reference string `json:"-"`
}
func GetECPointFormatInfo(ecPointFormatCode uint8) ECPointFormatInfo {
info, found := ECPointFormatList[ecPointFormatCode]
if !found {
info = ECPointFormatInfo{
Code: ecPointFormatCode,
}
}
return info
}
func (m *ClientHelloMsg) AddECPointFormatInfo() {
for i, ext := range m.Extensions {
if ext.Code == extensionSupportedPointFormats {
for j, pointFormat := range ext.Data.SupportedPointFormats {
m.Extensions[i].Data.SupportedPointFormats[j] = GetECPointFormatInfo(
pointFormat.(uint8))
}
}
}
}

52
clienthello/psk_modes.go Normal file
View File

@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
// PSK Key Exchange Modes
package clienthello
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-pskkeyexchangemode
// https://www.rfc-editor.org/rfc/rfc8446.html#section-4.2.9
var PSKModeList = map[uint8]PSKModeInfo{
0: {Code: 0, Name: "psk_ke", Recommended: true, Reference: "[RFC8446]"},
1: {Code: 1, Name: "psk_dhe_ke", Recommended: true, Reference: "[RFC8446]"},
0x0B: {Code: 0x0B, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
0x2A: {Code: 0x2A, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
0x49: {Code: 0x49, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
0x68: {Code: 0x68, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
0x87: {Code: 0x87, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
0xA6: {Code: 0xA6, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
0xC5: {Code: 0xC5, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
0xE4: {Code: 0xE4, Name: "GREASE", Recommended: false, Reference: "[RFC8701]"},
}
type PSKMode any // (uint8 | PSKModeInfo)
type PSKModeInfo struct {
Code uint8 `json:"code"`
Name string `json:"name"`
Recommended bool `json:"-"`
Reference string `json:"-"`
}
func GetPSKModeInfo(pskModeCode uint8) PSKModeInfo {
info, found := PSKModeList[pskModeCode]
if !found {
info = PSKModeInfo{
Code: pskModeCode,
}
}
return info
}
func (m *ClientHelloMsg) AddPSKModeInfo() {
for i, ext := range m.Extensions {
if ext.Code == extensionPSKModes {
for j, pskMode := range ext.Data.PSKModes {
m.Extensions[i].Data.PSKModes[j] = GetPSKModeInfo(pskMode.(uint8))
}
}
}
}

View File

@ -0,0 +1,545 @@
Value,Description,Recommended,Reference
0x0000-0x0200,Reserved for backward compatibility,,[RFC8446]
0x0201,rsa_pkcs1_sha1,N,[RFC8446][RFC9155]
0x0202,Reserved for backward compatibility,,[RFC8446]
0x0203,ecdsa_sha1,N,[RFC8446][RFC9155]
0x0204-0x0400,Reserved for backward compatibility,,[RFC8446]
0x0401,rsa_pkcs1_sha256,Y,[RFC8446]
0x0402,Reserved for backward compatibility,,[RFC8446]
0x0403,ecdsa_secp256r1_sha256,Y,[RFC8446]
0x0404-0x041F,Reserved for backward compatibility,,[RFC8446]
0x0420,rsa_pkcs1_sha256_legacy,N,[draft-davidben-tls13-pkcs1-00]
0x0421-0x0500,Reserved for backward compatibility,,[RFC8446]
0x0501,rsa_pkcs1_sha384,Y,[RFC8446]
0x0502,Reserved for backward compatibility,,[RFC8446]
0x0503,ecdsa_secp384r1_sha384,Y,[RFC8446]
0x0504-0x051F,Reserved for backward compatibility,,[RFC8446]
0x0520,rsa_pkcs1_sha384_legacy,N,[draft-davidben-tls13-pkcs1-00]
0x0521-0x0600,Reserved for backward compatibility,,[RFC8446]
0x0601,rsa_pkcs1_sha512,Y,[RFC8446]
0x0602,Reserved for backward compatibility,,[RFC8446]
0x0603,ecdsa_secp521r1_sha512,Y,[RFC8446]
0x0604-0x061F,Reserved for backward compatibility,,[RFC8446]
0x0620,rsa_pkcs1_sha512_legacy,N,[draft-davidben-tls13-pkcs1-00]
0x0621-0x0703,Reserved for backward compatibility,,[RFC8446]
0x0704,eccsi_sha256,N,[draft-wang-tls-raw-public-key-with-ibc]
0x0705,iso_ibs1,N,[draft-wang-tls-raw-public-key-with-ibc]
0x0706,iso_ibs2,N,[draft-wang-tls-raw-public-key-with-ibc]
0x0707,iso_chinese_ibs,N,[draft-wang-tls-raw-public-key-with-ibc]
0x0708,sm2sig_sm3,N,[RFC8998]
0x0709,gostr34102012_256a,N,[RFC9367]
0x070A,gostr34102012_256b,N,[RFC9367]
0x070B,gostr34102012_256c,N,[RFC9367]
0x070C,gostr34102012_256d,N,[RFC9367]
0x070D,gostr34102012_512a,N,[RFC9367]
0x070E,gostr34102012_512b,N,[RFC9367]
0x070F,gostr34102012_512c,N,[RFC9367]
0x0710-0x07FF,Unassigned,,
0x0800-0x0803,Reserved for backward compatibility,,[RFC8446]
0x0804,rsa_pss_rsae_sha256,Y,[RFC8446]
0x0805,rsa_pss_rsae_sha384,Y,[RFC8446]
0x0806,rsa_pss_rsae_sha512,Y,[RFC8446]
0x0807,ed25519,Y,[RFC8446]
0x0808,ed448,Y,[RFC8446]
0x0809,rsa_pss_pss_sha256,Y,[RFC8446]
0x080A,rsa_pss_pss_sha384,Y,[RFC8446]
0x080B,rsa_pss_pss_sha512,Y,[RFC8446]
0x080C-0x0819,Unassigned,,
0x081A,ecdsa_brainpoolP256r1tls13_sha256,N,[RFC8734]
0x081B,ecdsa_brainpoolP384r1tls13_sha384,N,[RFC8734]
0x081C,ecdsa_brainpoolP512r1tls13_sha512,N,[RFC8734]
0x081D-0x083F,Unassigned,,
0x0840,Reserved for backward compatibility,N,[RFC9189]
0x0841,Reserved for backward compatibility,N,[RFC9189]
0x0842-0x08FF,Unassigned,,
0x0900-0x0903,Reserved for backward compatibility,,[RFC8446]
0x0904-0x09FF,Unassigned,,
0x0A00-0x0A03,Reserved for backward compatibility,,[RFC8446]
0x0A04-0x0AFF,Unassigned,,
0x0B00-0x0B03,Reserved for backward compatibility,,[RFC8446]
0x0B04-0x0BFF,Unassigned,,
0x0C00-0x0C03,Reserved for backward compatibility,,[RFC8446]
0x0C04-0x0CFF,Unassigned,,
0x0D00-0x0D03,Reserved for backward compatibility,,[RFC8446]
0x0D04-0x0DFF,Unassigned,,
0x0E00-0x0E03,Reserved for backward compatibility,,[RFC8446]
0x0E04-0x0EFF,Unassigned,,
0x0F00-0x0F03,Reserved for backward compatibility,,[RFC8446]
0x0F04-0x0FFF,Unassigned,,
0x1000-0x1003,Reserved for backward compatibility,,[RFC8446]
0x1004-0x10FF,Unassigned,,
0x1100-0x1103,Reserved for backward compatibility,,[RFC8446]
0x1104-0x11FF,Unassigned,,
0x1200-0x1203,Reserved for backward compatibility,,[RFC8446]
0x1204-0x12FF,Unassigned,,
0x1300-0x1303,Reserved for backward compatibility,,[RFC8446]
0x1304-0x13FF,Unassigned,,
0x1400-0x1403,Reserved for backward compatibility,,[RFC8446]
0x1404-0x14FF,Unassigned,,
0x1500-0x1503,Reserved for backward compatibility,,[RFC8446]
0x1504-0x15FF,Unassigned,,
0x1600-0x1603,Reserved for backward compatibility,,[RFC8446]
0x1604-0x16FF,Unassigned,,
0x1700-0x1703,Reserved for backward compatibility,,[RFC8446]
0x1704-0x17FF,Unassigned,,
0x1800-0x1803,Reserved for backward compatibility,,[RFC8446]
0x1804-0x18FF,Unassigned,,
0x1900-0x1903,Reserved for backward compatibility,,[RFC8446]
0x1904-0x19FF,Unassigned,,
0x1A00-0x1A03,Reserved for backward compatibility,,[RFC8446]
0x1A04-0x1AFF,Unassigned,,
0x1B00-0x1B03,Reserved for backward compatibility,,[RFC8446]
0x1B04-0x1BFF,Unassigned,,
0x1C00-0x1C03,Reserved for backward compatibility,,[RFC8446]
0x1C04-0x1CFF,Unassigned,,
0x1D00-0x1D03,Reserved for backward compatibility,,[RFC8446]
0x1D04-0x1DFF,Unassigned,,
0x1E00-0x1E03,Reserved for backward compatibility,,[RFC8446]
0x1E04-0x1EFF,Unassigned,,
0x1F00-0x1F03,Reserved for backward compatibility,,[RFC8446]
0x1F04-0x1FFF,Unassigned,,
0x2000-0x2003,Reserved for backward compatibility,,[RFC8446]
0x2004-0x20FF,Unassigned,,
0x2100-0x2103,Reserved for backward compatibility,,[RFC8446]
0x2104-0x21FF,Unassigned,,
0x2200-0x2203,Reserved for backward compatibility,,[RFC8446]
0x2204-0x22FF,Unassigned,,
0x2300-0x2303,Reserved for backward compatibility,,[RFC8446]
0x2304-0x23FF,Unassigned,,
0x2400-0x2403,Reserved for backward compatibility,,[RFC8446]
0x2404-0x24FF,Unassigned,,
0x2500-0x2503,Reserved for backward compatibility,,[RFC8446]
0x2504-0x25FF,Unassigned,,
0x2600-0x2603,Reserved for backward compatibility,,[RFC8446]
0x2604-0x26FF,Unassigned,,
0x2700-0x2703,Reserved for backward compatibility,,[RFC8446]
0x2704-0x27FF,Unassigned,,
0x2800-0x2803,Reserved for backward compatibility,,[RFC8446]
0x2804-0x28FF,Unassigned,,
0x2900-0x2903,Reserved for backward compatibility,,[RFC8446]
0x2904-0x29FF,Unassigned,,
0x2A00-0x2A03,Reserved for backward compatibility,,[RFC8446]
0x2A04-0x2AFF,Unassigned,,
0x2B00-0x2B03,Reserved for backward compatibility,,[RFC8446]
0x2B04-0x2BFF,Unassigned,,
0x2C00-0x2C03,Reserved for backward compatibility,,[RFC8446]
0x2C04-0x2CFF,Unassigned,,
0x2D00-0x2D03,Reserved for backward compatibility,,[RFC8446]
0x2D04-0x2DFF,Unassigned,,
0x2E00-0x2E03,Reserved for backward compatibility,,[RFC8446]
0x2E04-0x2EFF,Unassigned,,
0x2F00-0x2F03,Reserved for backward compatibility,,[RFC8446]
0x2F04-0x2FFF,Unassigned,,
0x3000-0x3003,Reserved for backward compatibility,,[RFC8446]
0x3004-0x30FF,Unassigned,,
0x3100-0x3103,Reserved for backward compatibility,,[RFC8446]
0x3104-0x31FF,Unassigned,,
0x3200-0x3203,Reserved for backward compatibility,,[RFC8446]
0x3204-0x32FF,Unassigned,,
0x3300-0x3303,Reserved for backward compatibility,,[RFC8446]
0x3304-0x33FF,Unassigned,,
0x3400-0x3403,Reserved for backward compatibility,,[RFC8446]
0x3404-0x34FF,Unassigned,,
0x3500-0x3503,Reserved for backward compatibility,,[RFC8446]
0x3504-0x35FF,Unassigned,,
0x3600-0x3603,Reserved for backward compatibility,,[RFC8446]
0x3604-0x36FF,Unassigned,,
0x3700-0x3703,Reserved for backward compatibility,,[RFC8446]
0x3704-0x37FF,Unassigned,,
0x3800-0x3803,Reserved for backward compatibility,,[RFC8446]
0x3804-0x38FF,Unassigned,,
0x3900-0x3903,Reserved for backward compatibility,,[RFC8446]
0x3904-0x39FF,Unassigned,,
0x3A00-0x3A03,Reserved for backward compatibility,,[RFC8446]
0x3A04-0x3AFF,Unassigned,,
0x3B00-0x3B03,Reserved for backward compatibility,,[RFC8446]
0x3B04-0x3BFF,Unassigned,,
0x3C00-0x3C03,Reserved for backward compatibility,,[RFC8446]
0x3C04-0x3CFF,Unassigned,,
0x3D00-0x3D03,Reserved for backward compatibility,,[RFC8446]
0x3D04-0x3DFF,Unassigned,,
0x3E00-0x3E03,Reserved for backward compatibility,,[RFC8446]
0x3E04-0x3EFF,Unassigned,,
0x3F00-0x3F03,Reserved for backward compatibility,,[RFC8446]
0x3F04-0x3FFF,Unassigned,,
0x4000-0x4003,Reserved for backward compatibility,,[RFC8446]
0x4004-0x40FF,Unassigned,,
0x4100-0x4103,Reserved for backward compatibility,,[RFC8446]
0x4104-0x41FF,Unassigned,,
0x4200-0x4203,Reserved for backward compatibility,,[RFC8446]
0x4204-0x42FF,Unassigned,,
0x4300-0x4303,Reserved for backward compatibility,,[RFC8446]
0x4304-0x43FF,Unassigned,,
0x4400-0x4403,Reserved for backward compatibility,,[RFC8446]
0x4404-0x44FF,Unassigned,,
0x4500-0x4503,Reserved for backward compatibility,,[RFC8446]
0x4504-0x45FF,Unassigned,,
0x4600-0x4603,Reserved for backward compatibility,,[RFC8446]
0x4604-0x46FF,Unassigned,,
0x4700-0x4703,Reserved for backward compatibility,,[RFC8446]
0x4704-0x47FF,Unassigned,,
0x4800-0x4803,Reserved for backward compatibility,,[RFC8446]
0x4804-0x48FF,Unassigned,,
0x4900-0x4903,Reserved for backward compatibility,,[RFC8446]
0x4904-0x49FF,Unassigned,,
0x4A00-0x4A03,Reserved for backward compatibility,,[RFC8446]
0x4A04-0x4AFF,Unassigned,,
0x4B00-0x4B03,Reserved for backward compatibility,,[RFC8446]
0x4B04-0x4BFF,Unassigned,,
0x4C00-0x4C03,Reserved for backward compatibility,,[RFC8446]
0x4C04-0x4CFF,Unassigned,,
0x4D00-0x4D03,Reserved for backward compatibility,,[RFC8446]
0x4D04-0x4DFF,Unassigned,,
0x4E00-0x4E03,Reserved for backward compatibility,,[RFC8446]
0x4E04-0x4EFF,Unassigned,,
0x4F00-0x4F03,Reserved for backward compatibility,,[RFC8446]
0x4F04-0x4FFF,Unassigned,,
0x5000-0x5003,Reserved for backward compatibility,,[RFC8446]
0x5004-0x50FF,Unassigned,,
0x5100-0x5103,Reserved for backward compatibility,,[RFC8446]
0x5104-0x51FF,Unassigned,,
0x5200-0x5203,Reserved for backward compatibility,,[RFC8446]
0x5204-0x52FF,Unassigned,,
0x5300-0x5303,Reserved for backward compatibility,,[RFC8446]
0x5304-0x53FF,Unassigned,,
0x5400-0x5403,Reserved for backward compatibility,,[RFC8446]
0x5404-0x54FF,Unassigned,,
0x5500-0x5503,Reserved for backward compatibility,,[RFC8446]
0x5504-0x55FF,Unassigned,,
0x5600-0x5603,Reserved for backward compatibility,,[RFC8446]
0x5604-0x56FF,Unassigned,,
0x5700-0x5703,Reserved for backward compatibility,,[RFC8446]
0x5704-0x57FF,Unassigned,,
0x5800-0x5803,Reserved for backward compatibility,,[RFC8446]
0x5804-0x58FF,Unassigned,,
0x5900-0x5903,Reserved for backward compatibility,,[RFC8446]
0x5904-0x59FF,Unassigned,,
0x5A00-0x5A03,Reserved for backward compatibility,,[RFC8446]
0x5A04-0x5AFF,Unassigned,,
0x5B00-0x5B03,Reserved for backward compatibility,,[RFC8446]
0x5B04-0x5BFF,Unassigned,,
0x5C00-0x5C03,Reserved for backward compatibility,,[RFC8446]
0x5C04-0x5CFF,Unassigned,,
0x5D00-0x5D03,Reserved for backward compatibility,,[RFC8446]
0x5D04-0x5DFF,Unassigned,,
0x5E00-0x5E03,Reserved for backward compatibility,,[RFC8446]
0x5E04-0x5EFF,Unassigned,,
0x5F00-0x5F03,Reserved for backward compatibility,,[RFC8446]
0x5F04-0x5FFF,Unassigned,,
0x6000-0x6003,Reserved for backward compatibility,,[RFC8446]
0x6004-0x60FF,Unassigned,,
0x6100-0x6103,Reserved for backward compatibility,,[RFC8446]
0x6104-0x61FF,Unassigned,,
0x6200-0x6203,Reserved for backward compatibility,,[RFC8446]
0x6204-0x62FF,Unassigned,,
0x6300-0x6303,Reserved for backward compatibility,,[RFC8446]
0x6304-0x63FF,Unassigned,,
0x6400-0x6403,Reserved for backward compatibility,,[RFC8446]
0x6404-0x64FF,Unassigned,,
0x6500-0x6503,Reserved for backward compatibility,,[RFC8446]
0x6504-0x65FF,Unassigned,,
0x6600-0x6603,Reserved for backward compatibility,,[RFC8446]
0x6604-0x66FF,Unassigned,,
0x6700-0x6703,Reserved for backward compatibility,,[RFC8446]
0x6704-0x67FF,Unassigned,,
0x6800-0x6803,Reserved for backward compatibility,,[RFC8446]
0x6804-0x68FF,Unassigned,,
0x6900-0x6903,Reserved for backward compatibility,,[RFC8446]
0x6904-0x69FF,Unassigned,,
0x6A00-0x6A03,Reserved for backward compatibility,,[RFC8446]
0x6A04-0x6AFF,Unassigned,,
0x6B00-0x6B03,Reserved for backward compatibility,,[RFC8446]
0x6B04-0x6BFF,Unassigned,,
0x6C00-0x6C03,Reserved for backward compatibility,,[RFC8446]
0x6C04-0x6CFF,Unassigned,,
0x6D00-0x6D03,Reserved for backward compatibility,,[RFC8446]
0x6D04-0x6DFF,Unassigned,,
0x6E00-0x6E03,Reserved for backward compatibility,,[RFC8446]
0x6E04-0x6EFF,Unassigned,,
0x6F00-0x6F03,Reserved for backward compatibility,,[RFC8446]
0x6F04-0x6FFF,Unassigned,,
0x7000-0x7003,Reserved for backward compatibility,,[RFC8446]
0x7004-0x70FF,Unassigned,,
0x7100-0x7103,Reserved for backward compatibility,,[RFC8446]
0x7104-0x71FF,Unassigned,,
0x7200-0x7203,Reserved for backward compatibility,,[RFC8446]
0x7204-0x72FF,Unassigned,,
0x7300-0x7303,Reserved for backward compatibility,,[RFC8446]
0x7304-0x73FF,Unassigned,,
0x7400-0x7403,Reserved for backward compatibility,,[RFC8446]
0x7404-0x74FF,Unassigned,,
0x7500-0x7503,Reserved for backward compatibility,,[RFC8446]
0x7504-0x75FF,Unassigned,,
0x7600-0x7603,Reserved for backward compatibility,,[RFC8446]
0x7604-0x76FF,Unassigned,,
0x7700-0x7703,Reserved for backward compatibility,,[RFC8446]
0x7704-0x77FF,Unassigned,,
0x7800-0x7803,Reserved for backward compatibility,,[RFC8446]
0x7804-0x78FF,Unassigned,,
0x7900-0x7903,Reserved for backward compatibility,,[RFC8446]
0x7904-0x79FF,Unassigned,,
0x7A00-0x7A03,Reserved for backward compatibility,,[RFC8446]
0x7A04-0x7AFF,Unassigned,,
0x7B00-0x7B03,Reserved for backward compatibility,,[RFC8446]
0x7B04-0x7BFF,Unassigned,,
0x7C00-0x7C03,Reserved for backward compatibility,,[RFC8446]
0x7C04-0x7CFF,Unassigned,,
0x7D00-0x7D03,Reserved for backward compatibility,,[RFC8446]
0x7D04-0x7DFF,Unassigned,,
0x7E00-0x7E03,Reserved for backward compatibility,,[RFC8446]
0x7E04-0x7EFF,Unassigned,,
0x7F00-0x7F03,Reserved for backward compatibility,,[RFC8446]
0x7F04-0x7FFF,Unassigned,,
0x8000-0x8003,Reserved for backward compatibility,,[RFC8446]
0x8004-0x80FF,Unassigned,,
0x8100-0x8103,Reserved for backward compatibility,,[RFC8446]
0x8104-0x81FF,Unassigned,,
0x8200-0x8203,Reserved for backward compatibility,,[RFC8446]
0x8204-0x82FF,Unassigned,,
0x8300-0x8303,Reserved for backward compatibility,,[RFC8446]
0x8304-0x83FF,Unassigned,,
0x8400-0x8403,Reserved for backward compatibility,,[RFC8446]
0x8404-0x84FF,Unassigned,,
0x8500-0x8503,Reserved for backward compatibility,,[RFC8446]
0x8504-0x85FF,Unassigned,,
0x8600-0x8603,Reserved for backward compatibility,,[RFC8446]
0x8604-0x86FF,Unassigned,,
0x8700-0x8703,Reserved for backward compatibility,,[RFC8446]
0x8704-0x87FF,Unassigned,,
0x8800-0x8803,Reserved for backward compatibility,,[RFC8446]
0x8804-0x88FF,Unassigned,,
0x8900-0x8903,Reserved for backward compatibility,,[RFC8446]
0x8904-0x89FF,Unassigned,,
0x8A00-0x8A03,Reserved for backward compatibility,,[RFC8446]
0x8A04-0x8AFF,Unassigned,,
0x8B00-0x8B03,Reserved for backward compatibility,,[RFC8446]
0x8B04-0x8BFF,Unassigned,,
0x8C00-0x8C03,Reserved for backward compatibility,,[RFC8446]
0x8C04-0x8CFF,Unassigned,,
0x8D00-0x8D03,Reserved for backward compatibility,,[RFC8446]
0x8D04-0x8DFF,Unassigned,,
0x8E00-0x8E03,Reserved for backward compatibility,,[RFC8446]
0x8E04-0x8EFF,Unassigned,,
0x8F00-0x8F03,Reserved for backward compatibility,,[RFC8446]
0x8F04-0x8FFF,Unassigned,,
0x9000-0x9003,Reserved for backward compatibility,,[RFC8446]
0x9004-0x90FF,Unassigned,,
0x9100-0x9103,Reserved for backward compatibility,,[RFC8446]
0x9104-0x91FF,Unassigned,,
0x9200-0x9203,Reserved for backward compatibility,,[RFC8446]
0x9204-0x92FF,Unassigned,,
0x9300-0x9303,Reserved for backward compatibility,,[RFC8446]
0x9304-0x93FF,Unassigned,,
0x9400-0x9403,Reserved for backward compatibility,,[RFC8446]
0x9404-0x94FF,Unassigned,,
0x9500-0x9503,Reserved for backward compatibility,,[RFC8446]
0x9504-0x95FF,Unassigned,,
0x9600-0x9603,Reserved for backward compatibility,,[RFC8446]
0x9604-0x96FF,Unassigned,,
0x9700-0x9703,Reserved for backward compatibility,,[RFC8446]
0x9704-0x97FF,Unassigned,,
0x9800-0x9803,Reserved for backward compatibility,,[RFC8446]
0x9804-0x98FF,Unassigned,,
0x9900-0x9903,Reserved for backward compatibility,,[RFC8446]
0x9904-0x99FF,Unassigned,,
0x9A00-0x9A03,Reserved for backward compatibility,,[RFC8446]
0x9A04-0x9AFF,Unassigned,,
0x9B00-0x9B03,Reserved for backward compatibility,,[RFC8446]
0x9B04-0x9BFF,Unassigned,,
0x9C00-0x9C03,Reserved for backward compatibility,,[RFC8446]
0x9C04-0x9CFF,Unassigned,,
0x9D00-0x9D03,Reserved for backward compatibility,,[RFC8446]
0x9D04-0x9DFF,Unassigned,,
0x9E00-0x9E03,Reserved for backward compatibility,,[RFC8446]
0x9E04-0x9EFF,Unassigned,,
0x9F00-0x9F03,Reserved for backward compatibility,,[RFC8446]
0x9F04-0x9FFF,Unassigned,,
0xA000-0xA003,Reserved for backward compatibility,,[RFC8446]
0xA004-0xA0FF,Unassigned,,
0xA100-0xA103,Reserved for backward compatibility,,[RFC8446]
0xA104-0xA1FF,Unassigned,,
0xA200-0xA203,Reserved for backward compatibility,,[RFC8446]
0xA204-0xA2FF,Unassigned,,
0xA300-0xA303,Reserved for backward compatibility,,[RFC8446]
0xA304-0xA3FF,Unassigned,,
0xA400-0xA403,Reserved for backward compatibility,,[RFC8446]
0xA404-0xA4FF,Unassigned,,
0xA500-0xA503,Reserved for backward compatibility,,[RFC8446]
0xA504-0xA5FF,Unassigned,,
0xA600-0xA603,Reserved for backward compatibility,,[RFC8446]
0xA604-0xA6FF,Unassigned,,
0xA700-0xA703,Reserved for backward compatibility,,[RFC8446]
0xA704-0xA7FF,Unassigned,,
0xA800-0xA803,Reserved for backward compatibility,,[RFC8446]
0xA804-0xA8FF,Unassigned,,
0xA900-0xA903,Reserved for backward compatibility,,[RFC8446]
0xA904-0xA9FF,Unassigned,,
0xAA00-0xAA03,Reserved for backward compatibility,,[RFC8446]
0xAA04-0xAAFF,Unassigned,,
0xAB00-0xAB03,Reserved for backward compatibility,,[RFC8446]
0xAB04-0xABFF,Unassigned,,
0xAC00-0xAC03,Reserved for backward compatibility,,[RFC8446]
0xAC04-0xACFF,Unassigned,,
0xAD00-0xAD03,Reserved for backward compatibility,,[RFC8446]
0xAD04-0xADFF,Unassigned,,
0xAE00-0xAE03,Reserved for backward compatibility,,[RFC8446]
0xAE04-0xAEFF,Unassigned,,
0xAF00-0xAF03,Reserved for backward compatibility,,[RFC8446]
0xAF04-0xAFFF,Unassigned,,
0xB000-0xB003,Reserved for backward compatibility,,[RFC8446]
0xB004-0xB0FF,Unassigned,,
0xB100-0xB103,Reserved for backward compatibility,,[RFC8446]
0xB104-0xB1FF,Unassigned,,
0xB200-0xB203,Reserved for backward compatibility,,[RFC8446]
0xB204-0xB2FF,Unassigned,,
0xB300-0xB303,Reserved for backward compatibility,,[RFC8446]
0xB304-0xB3FF,Unassigned,,
0xB400-0xB403,Reserved for backward compatibility,,[RFC8446]
0xB404-0xB4FF,Unassigned,,
0xB500-0xB503,Reserved for backward compatibility,,[RFC8446]
0xB504-0xB5FF,Unassigned,,
0xB600-0xB603,Reserved for backward compatibility,,[RFC8446]
0xB604-0xB6FF,Unassigned,,
0xB700-0xB703,Reserved for backward compatibility,,[RFC8446]
0xB704-0xB7FF,Unassigned,,
0xB800-0xB803,Reserved for backward compatibility,,[RFC8446]
0xB804-0xB8FF,Unassigned,,
0xB900-0xB903,Reserved for backward compatibility,,[RFC8446]
0xB904-0xB9FF,Unassigned,,
0xBA00-0xBA03,Reserved for backward compatibility,,[RFC8446]
0xBA04-0xBAFF,Unassigned,,
0xBB00-0xBB03,Reserved for backward compatibility,,[RFC8446]
0xBB04-0xBBFF,Unassigned,,
0xBC00-0xBC03,Reserved for backward compatibility,,[RFC8446]
0xBC04-0xBCFF,Unassigned,,
0xBD00-0xBD03,Reserved for backward compatibility,,[RFC8446]
0xBD04-0xBDFF,Unassigned,,
0xBE00-0xBE03,Reserved for backward compatibility,,[RFC8446]
0xBE04-0xBEFF,Unassigned,,
0xBF00-0xBF03,Reserved for backward compatibility,,[RFC8446]
0xBF04-0xBFFF,Unassigned,,
0xC000-0xC003,Reserved for backward compatibility,,[RFC8446]
0xC004-0xC0FF,Unassigned,,
0xC100-0xC103,Reserved for backward compatibility,,[RFC8446]
0xC104-0xC1FF,Unassigned,,
0xC200-0xC203,Reserved for backward compatibility,,[RFC8446]
0xC204-0xC2FF,Unassigned,,
0xC300-0xC303,Reserved for backward compatibility,,[RFC8446]
0xC304-0xC3FF,Unassigned,,
0xC400-0xC403,Reserved for backward compatibility,,[RFC8446]
0xC404-0xC4FF,Unassigned,,
0xC500-0xC503,Reserved for backward compatibility,,[RFC8446]
0xC504-0xC5FF,Unassigned,,
0xC600-0xC603,Reserved for backward compatibility,,[RFC8446]
0xC604-0xC6FF,Unassigned,,
0xC700-0xC703,Reserved for backward compatibility,,[RFC8446]
0xC704-0xC7FF,Unassigned,,
0xC800-0xC803,Reserved for backward compatibility,,[RFC8446]
0xC804-0xC8FF,Unassigned,,
0xC900-0xC903,Reserved for backward compatibility,,[RFC8446]
0xC904-0xC9FF,Unassigned,,
0xCA00-0xCA03,Reserved for backward compatibility,,[RFC8446]
0xCA04-0xCAFF,Unassigned,,
0xCB00-0xCB03,Reserved for backward compatibility,,[RFC8446]
0xCB04-0xCBFF,Unassigned,,
0xCC00-0xCC03,Reserved for backward compatibility,,[RFC8446]
0xCC04-0xCCFF,Unassigned,,
0xCD00-0xCD03,Reserved for backward compatibility,,[RFC8446]
0xCD04-0xCDFF,Unassigned,,
0xCE00-0xCE03,Reserved for backward compatibility,,[RFC8446]
0xCE04-0xCEFF,Unassigned,,
0xCF00-0xCF03,Reserved for backward compatibility,,[RFC8446]
0xCF04-0xCFFF,Unassigned,,
0xD000-0xD003,Reserved for backward compatibility,,[RFC8446]
0xD004-0xD0FF,Unassigned,,
0xD100-0xD103,Reserved for backward compatibility,,[RFC8446]
0xD104-0xD1FF,Unassigned,,
0xD200-0xD203,Reserved for backward compatibility,,[RFC8446]
0xD204-0xD2FF,Unassigned,,
0xD300-0xD303,Reserved for backward compatibility,,[RFC8446]
0xD304-0xD3FF,Unassigned,,
0xD400-0xD403,Reserved for backward compatibility,,[RFC8446]
0xD404-0xD4FF,Unassigned,,
0xD500-0xD503,Reserved for backward compatibility,,[RFC8446]
0xD504-0xD5FF,Unassigned,,
0xD600-0xD603,Reserved for backward compatibility,,[RFC8446]
0xD604-0xD6FF,Unassigned,,
0xD700-0xD703,Reserved for backward compatibility,,[RFC8446]
0xD704-0xD7FF,Unassigned,,
0xD800-0xD803,Reserved for backward compatibility,,[RFC8446]
0xD804-0xD8FF,Unassigned,,
0xD900-0xD903,Reserved for backward compatibility,,[RFC8446]
0xD904-0xD9FF,Unassigned,,
0xDA00-0xDA03,Reserved for backward compatibility,,[RFC8446]
0xDA04-0xDAFF,Unassigned,,
0xDB00-0xDB03,Reserved for backward compatibility,,[RFC8446]
0xDB04-0xDBFF,Unassigned,,
0xDC00-0xDC03,Reserved for backward compatibility,,[RFC8446]
0xDC04-0xDCFF,Unassigned,,
0xDD00-0xDD03,Reserved for backward compatibility,,[RFC8446]
0xDD04-0xDDFF,Unassigned,,
0xDE00-0xDE03,Reserved for backward compatibility,,[RFC8446]
0xDE04-0xDEFF,Unassigned,,
0xDF00-0xDF03,Reserved for backward compatibility,,[RFC8446]
0xDF04-0xDFFF,Unassigned,,
0xE000-0xE003,Reserved for backward compatibility,,[RFC8446]
0xE004-0xE0FF,Unassigned,,
0xE100-0xE103,Reserved for backward compatibility,,[RFC8446]
0xE104-0xE1FF,Unassigned,,
0xE200-0xE203,Reserved for backward compatibility,,[RFC8446]
0xE204-0xE2FF,Unassigned,,
0xE300-0xE303,Reserved for backward compatibility,,[RFC8446]
0xE304-0xE3FF,Unassigned,,
0xE400-0xE403,Reserved for backward compatibility,,[RFC8446]
0xE404-0xE4FF,Unassigned,,
0xE500-0xE503,Reserved for backward compatibility,,[RFC8446]
0xE504-0xE5FF,Unassigned,,
0xE600-0xE603,Reserved for backward compatibility,,[RFC8446]
0xE604-0xE6FF,Unassigned,,
0xE700-0xE703,Reserved for backward compatibility,,[RFC8446]
0xE704-0xE7FF,Unassigned,,
0xE800-0xE803,Reserved for backward compatibility,,[RFC8446]
0xE804-0xE8FF,Unassigned,,
0xE900-0xE903,Reserved for backward compatibility,,[RFC8446]
0xE904-0xE9FF,Unassigned,,
0xEA00-0xEA03,Reserved for backward compatibility,,[RFC8446]
0xEA04-0xEAFF,Unassigned,,
0xEB00-0xEB03,Reserved for backward compatibility,,[RFC8446]
0xEB04-0xEBFF,Unassigned,,
0xEC00-0xEC03,Reserved for backward compatibility,,[RFC8446]
0xEC04-0xECFF,Unassigned,,
0xED00-0xED03,Reserved for backward compatibility,,[RFC8446]
0xED04-0xEDFF,Unassigned,,
0xEE00-0xEE03,Reserved for backward compatibility,,[RFC8446]
0xEE04-0xEEFF,Unassigned,,
0xEF00-0xEF03,Reserved for backward compatibility,,[RFC8446]
0xEF04-0xEFFF,Unassigned,,
0xF000-0xF003,Reserved for backward compatibility,,[RFC8446]
0xF004-0xF0FF,Unassigned,,
0xF100-0xF103,Reserved for backward compatibility,,[RFC8446]
0xF104-0xF1FF,Unassigned,,
0xF200-0xF203,Reserved for backward compatibility,,[RFC8446]
0xF204-0xF2FF,Unassigned,,
0xF300-0xF303,Reserved for backward compatibility,,[RFC8446]
0xF304-0xF3FF,Unassigned,,
0xF400-0xF403,Reserved for backward compatibility,,[RFC8446]
0xF404-0xF4FF,Unassigned,,
0xF500-0xF503,Reserved for backward compatibility,,[RFC8446]
0xF504-0xF5FF,Unassigned,,
0xF600-0xF603,Reserved for backward compatibility,,[RFC8446]
0xF604-0xF6FF,Unassigned,,
0xF700-0xF703,Reserved for backward compatibility,,[RFC8446]
0xF704-0xF7FF,Unassigned,,
0xF800-0xF803,Reserved for backward compatibility,,[RFC8446]
0xF804-0xF8FF,Unassigned,,
0xF900-0xF903,Reserved for backward compatibility,,[RFC8446]
0xF904-0xF9FF,Unassigned,,
0xFA00-0xFA03,Reserved for backward compatibility,,[RFC8446]
0xFA04-0xFAFF,Unassigned,,
0xFB00-0xFB03,Reserved for backward compatibility,,[RFC8446]
0xFB04-0xFBFF,Unassigned,,
0xFC00-0xFC03,Reserved for backward compatibility,,[RFC8446]
0xFC04-0xFCFF,Unassigned,,
0xFD00-0xFD03,Reserved for backward compatibility,,[RFC8446]
0xFD04-0xFDFF,Unassigned,,
0xFE00-0xFFFF,Reserved for Private Use,,[RFC8446]
1 Value Description Recommended Reference
2 0x0000-0x0200 Reserved for backward compatibility [RFC8446]
3 0x0201 rsa_pkcs1_sha1 N [RFC8446][RFC9155]
4 0x0202 Reserved for backward compatibility [RFC8446]
5 0x0203 ecdsa_sha1 N [RFC8446][RFC9155]
6 0x0204-0x0400 Reserved for backward compatibility [RFC8446]
7 0x0401 rsa_pkcs1_sha256 Y [RFC8446]
8 0x0402 Reserved for backward compatibility [RFC8446]
9 0x0403 ecdsa_secp256r1_sha256 Y [RFC8446]
10 0x0404-0x041F Reserved for backward compatibility [RFC8446]
11 0x0420 rsa_pkcs1_sha256_legacy N [draft-davidben-tls13-pkcs1-00]
12 0x0421-0x0500 Reserved for backward compatibility [RFC8446]
13 0x0501 rsa_pkcs1_sha384 Y [RFC8446]
14 0x0502 Reserved for backward compatibility [RFC8446]
15 0x0503 ecdsa_secp384r1_sha384 Y [RFC8446]
16 0x0504-0x051F Reserved for backward compatibility [RFC8446]
17 0x0520 rsa_pkcs1_sha384_legacy N [draft-davidben-tls13-pkcs1-00]
18 0x0521-0x0600 Reserved for backward compatibility [RFC8446]
19 0x0601 rsa_pkcs1_sha512 Y [RFC8446]
20 0x0602 Reserved for backward compatibility [RFC8446]
21 0x0603 ecdsa_secp521r1_sha512 Y [RFC8446]
22 0x0604-0x061F Reserved for backward compatibility [RFC8446]
23 0x0620 rsa_pkcs1_sha512_legacy N [draft-davidben-tls13-pkcs1-00]
24 0x0621-0x0703 Reserved for backward compatibility [RFC8446]
25 0x0704 eccsi_sha256 N [draft-wang-tls-raw-public-key-with-ibc]
26 0x0705 iso_ibs1 N [draft-wang-tls-raw-public-key-with-ibc]
27 0x0706 iso_ibs2 N [draft-wang-tls-raw-public-key-with-ibc]
28 0x0707 iso_chinese_ibs N [draft-wang-tls-raw-public-key-with-ibc]
29 0x0708 sm2sig_sm3 N [RFC8998]
30 0x0709 gostr34102012_256a N [RFC9367]
31 0x070A gostr34102012_256b N [RFC9367]
32 0x070B gostr34102012_256c N [RFC9367]
33 0x070C gostr34102012_256d N [RFC9367]
34 0x070D gostr34102012_512a N [RFC9367]
35 0x070E gostr34102012_512b N [RFC9367]
36 0x070F gostr34102012_512c N [RFC9367]
37 0x0710-0x07FF Unassigned
38 0x0800-0x0803 Reserved for backward compatibility [RFC8446]
39 0x0804 rsa_pss_rsae_sha256 Y [RFC8446]
40 0x0805 rsa_pss_rsae_sha384 Y [RFC8446]
41 0x0806 rsa_pss_rsae_sha512 Y [RFC8446]
42 0x0807 ed25519 Y [RFC8446]
43 0x0808 ed448 Y [RFC8446]
44 0x0809 rsa_pss_pss_sha256 Y [RFC8446]
45 0x080A rsa_pss_pss_sha384 Y [RFC8446]
46 0x080B rsa_pss_pss_sha512 Y [RFC8446]
47 0x080C-0x0819 Unassigned
48 0x081A ecdsa_brainpoolP256r1tls13_sha256 N [RFC8734]
49 0x081B ecdsa_brainpoolP384r1tls13_sha384 N [RFC8734]
50 0x081C ecdsa_brainpoolP512r1tls13_sha512 N [RFC8734]
51 0x081D-0x083F Unassigned
52 0x0840 Reserved for backward compatibility N [RFC9189]
53 0x0841 Reserved for backward compatibility N [RFC9189]
54 0x0842-0x08FF Unassigned
55 0x0900-0x0903 Reserved for backward compatibility [RFC8446]
56 0x0904-0x09FF Unassigned
57 0x0A00-0x0A03 Reserved for backward compatibility [RFC8446]
58 0x0A04-0x0AFF Unassigned
59 0x0B00-0x0B03 Reserved for backward compatibility [RFC8446]
60 0x0B04-0x0BFF Unassigned
61 0x0C00-0x0C03 Reserved for backward compatibility [RFC8446]
62 0x0C04-0x0CFF Unassigned
63 0x0D00-0x0D03 Reserved for backward compatibility [RFC8446]
64 0x0D04-0x0DFF Unassigned
65 0x0E00-0x0E03 Reserved for backward compatibility [RFC8446]
66 0x0E04-0x0EFF Unassigned
67 0x0F00-0x0F03 Reserved for backward compatibility [RFC8446]
68 0x0F04-0x0FFF Unassigned
69 0x1000-0x1003 Reserved for backward compatibility [RFC8446]
70 0x1004-0x10FF Unassigned
71 0x1100-0x1103 Reserved for backward compatibility [RFC8446]
72 0x1104-0x11FF Unassigned
73 0x1200-0x1203 Reserved for backward compatibility [RFC8446]
74 0x1204-0x12FF Unassigned
75 0x1300-0x1303 Reserved for backward compatibility [RFC8446]
76 0x1304-0x13FF Unassigned
77 0x1400-0x1403 Reserved for backward compatibility [RFC8446]
78 0x1404-0x14FF Unassigned
79 0x1500-0x1503 Reserved for backward compatibility [RFC8446]
80 0x1504-0x15FF Unassigned
81 0x1600-0x1603 Reserved for backward compatibility [RFC8446]
82 0x1604-0x16FF Unassigned
83 0x1700-0x1703 Reserved for backward compatibility [RFC8446]
84 0x1704-0x17FF Unassigned
85 0x1800-0x1803 Reserved for backward compatibility [RFC8446]
86 0x1804-0x18FF Unassigned
87 0x1900-0x1903 Reserved for backward compatibility [RFC8446]
88 0x1904-0x19FF Unassigned
89 0x1A00-0x1A03 Reserved for backward compatibility [RFC8446]
90 0x1A04-0x1AFF Unassigned
91 0x1B00-0x1B03 Reserved for backward compatibility [RFC8446]
92 0x1B04-0x1BFF Unassigned
93 0x1C00-0x1C03 Reserved for backward compatibility [RFC8446]
94 0x1C04-0x1CFF Unassigned
95 0x1D00-0x1D03 Reserved for backward compatibility [RFC8446]
96 0x1D04-0x1DFF Unassigned
97 0x1E00-0x1E03 Reserved for backward compatibility [RFC8446]
98 0x1E04-0x1EFF Unassigned
99 0x1F00-0x1F03 Reserved for backward compatibility [RFC8446]
100 0x1F04-0x1FFF Unassigned
101 0x2000-0x2003 Reserved for backward compatibility [RFC8446]
102 0x2004-0x20FF Unassigned
103 0x2100-0x2103 Reserved for backward compatibility [RFC8446]
104 0x2104-0x21FF Unassigned
105 0x2200-0x2203 Reserved for backward compatibility [RFC8446]
106 0x2204-0x22FF Unassigned
107 0x2300-0x2303 Reserved for backward compatibility [RFC8446]
108 0x2304-0x23FF Unassigned
109 0x2400-0x2403 Reserved for backward compatibility [RFC8446]
110 0x2404-0x24FF Unassigned
111 0x2500-0x2503 Reserved for backward compatibility [RFC8446]
112 0x2504-0x25FF Unassigned
113 0x2600-0x2603 Reserved for backward compatibility [RFC8446]
114 0x2604-0x26FF Unassigned
115 0x2700-0x2703 Reserved for backward compatibility [RFC8446]
116 0x2704-0x27FF Unassigned
117 0x2800-0x2803 Reserved for backward compatibility [RFC8446]
118 0x2804-0x28FF Unassigned
119 0x2900-0x2903 Reserved for backward compatibility [RFC8446]
120 0x2904-0x29FF Unassigned
121 0x2A00-0x2A03 Reserved for backward compatibility [RFC8446]
122 0x2A04-0x2AFF Unassigned
123 0x2B00-0x2B03 Reserved for backward compatibility [RFC8446]
124 0x2B04-0x2BFF Unassigned
125 0x2C00-0x2C03 Reserved for backward compatibility [RFC8446]
126 0x2C04-0x2CFF Unassigned
127 0x2D00-0x2D03 Reserved for backward compatibility [RFC8446]
128 0x2D04-0x2DFF Unassigned
129 0x2E00-0x2E03 Reserved for backward compatibility [RFC8446]
130 0x2E04-0x2EFF Unassigned
131 0x2F00-0x2F03 Reserved for backward compatibility [RFC8446]
132 0x2F04-0x2FFF Unassigned
133 0x3000-0x3003 Reserved for backward compatibility [RFC8446]
134 0x3004-0x30FF Unassigned
135 0x3100-0x3103 Reserved for backward compatibility [RFC8446]
136 0x3104-0x31FF Unassigned
137 0x3200-0x3203 Reserved for backward compatibility [RFC8446]
138 0x3204-0x32FF Unassigned
139 0x3300-0x3303 Reserved for backward compatibility [RFC8446]
140 0x3304-0x33FF Unassigned
141 0x3400-0x3403 Reserved for backward compatibility [RFC8446]
142 0x3404-0x34FF Unassigned
143 0x3500-0x3503 Reserved for backward compatibility [RFC8446]
144 0x3504-0x35FF Unassigned
145 0x3600-0x3603 Reserved for backward compatibility [RFC8446]
146 0x3604-0x36FF Unassigned
147 0x3700-0x3703 Reserved for backward compatibility [RFC8446]
148 0x3704-0x37FF Unassigned
149 0x3800-0x3803 Reserved for backward compatibility [RFC8446]
150 0x3804-0x38FF Unassigned
151 0x3900-0x3903 Reserved for backward compatibility [RFC8446]
152 0x3904-0x39FF Unassigned
153 0x3A00-0x3A03 Reserved for backward compatibility [RFC8446]
154 0x3A04-0x3AFF Unassigned
155 0x3B00-0x3B03 Reserved for backward compatibility [RFC8446]
156 0x3B04-0x3BFF Unassigned
157 0x3C00-0x3C03 Reserved for backward compatibility [RFC8446]
158 0x3C04-0x3CFF Unassigned
159 0x3D00-0x3D03 Reserved for backward compatibility [RFC8446]
160 0x3D04-0x3DFF Unassigned
161 0x3E00-0x3E03 Reserved for backward compatibility [RFC8446]
162 0x3E04-0x3EFF Unassigned
163 0x3F00-0x3F03 Reserved for backward compatibility [RFC8446]
164 0x3F04-0x3FFF Unassigned
165 0x4000-0x4003 Reserved for backward compatibility [RFC8446]
166 0x4004-0x40FF Unassigned
167 0x4100-0x4103 Reserved for backward compatibility [RFC8446]
168 0x4104-0x41FF Unassigned
169 0x4200-0x4203 Reserved for backward compatibility [RFC8446]
170 0x4204-0x42FF Unassigned
171 0x4300-0x4303 Reserved for backward compatibility [RFC8446]
172 0x4304-0x43FF Unassigned
173 0x4400-0x4403 Reserved for backward compatibility [RFC8446]
174 0x4404-0x44FF Unassigned
175 0x4500-0x4503 Reserved for backward compatibility [RFC8446]
176 0x4504-0x45FF Unassigned
177 0x4600-0x4603 Reserved for backward compatibility [RFC8446]
178 0x4604-0x46FF Unassigned
179 0x4700-0x4703 Reserved for backward compatibility [RFC8446]
180 0x4704-0x47FF Unassigned
181 0x4800-0x4803 Reserved for backward compatibility [RFC8446]
182 0x4804-0x48FF Unassigned
183 0x4900-0x4903 Reserved for backward compatibility [RFC8446]
184 0x4904-0x49FF Unassigned
185 0x4A00-0x4A03 Reserved for backward compatibility [RFC8446]
186 0x4A04-0x4AFF Unassigned
187 0x4B00-0x4B03 Reserved for backward compatibility [RFC8446]
188 0x4B04-0x4BFF Unassigned
189 0x4C00-0x4C03 Reserved for backward compatibility [RFC8446]
190 0x4C04-0x4CFF Unassigned
191 0x4D00-0x4D03 Reserved for backward compatibility [RFC8446]
192 0x4D04-0x4DFF Unassigned
193 0x4E00-0x4E03 Reserved for backward compatibility [RFC8446]
194 0x4E04-0x4EFF Unassigned
195 0x4F00-0x4F03 Reserved for backward compatibility [RFC8446]
196 0x4F04-0x4FFF Unassigned
197 0x5000-0x5003 Reserved for backward compatibility [RFC8446]
198 0x5004-0x50FF Unassigned
199 0x5100-0x5103 Reserved for backward compatibility [RFC8446]
200 0x5104-0x51FF Unassigned
201 0x5200-0x5203 Reserved for backward compatibility [RFC8446]
202 0x5204-0x52FF Unassigned
203 0x5300-0x5303 Reserved for backward compatibility [RFC8446]
204 0x5304-0x53FF Unassigned
205 0x5400-0x5403 Reserved for backward compatibility [RFC8446]
206 0x5404-0x54FF Unassigned
207 0x5500-0x5503 Reserved for backward compatibility [RFC8446]
208 0x5504-0x55FF Unassigned
209 0x5600-0x5603 Reserved for backward compatibility [RFC8446]
210 0x5604-0x56FF Unassigned
211 0x5700-0x5703 Reserved for backward compatibility [RFC8446]
212 0x5704-0x57FF Unassigned
213 0x5800-0x5803 Reserved for backward compatibility [RFC8446]
214 0x5804-0x58FF Unassigned
215 0x5900-0x5903 Reserved for backward compatibility [RFC8446]
216 0x5904-0x59FF Unassigned
217 0x5A00-0x5A03 Reserved for backward compatibility [RFC8446]
218 0x5A04-0x5AFF Unassigned
219 0x5B00-0x5B03 Reserved for backward compatibility [RFC8446]
220 0x5B04-0x5BFF Unassigned
221 0x5C00-0x5C03 Reserved for backward compatibility [RFC8446]
222 0x5C04-0x5CFF Unassigned
223 0x5D00-0x5D03 Reserved for backward compatibility [RFC8446]
224 0x5D04-0x5DFF Unassigned
225 0x5E00-0x5E03 Reserved for backward compatibility [RFC8446]
226 0x5E04-0x5EFF Unassigned
227 0x5F00-0x5F03 Reserved for backward compatibility [RFC8446]
228 0x5F04-0x5FFF Unassigned
229 0x6000-0x6003 Reserved for backward compatibility [RFC8446]
230 0x6004-0x60FF Unassigned
231 0x6100-0x6103 Reserved for backward compatibility [RFC8446]
232 0x6104-0x61FF Unassigned
233 0x6200-0x6203 Reserved for backward compatibility [RFC8446]
234 0x6204-0x62FF Unassigned
235 0x6300-0x6303 Reserved for backward compatibility [RFC8446]
236 0x6304-0x63FF Unassigned
237 0x6400-0x6403 Reserved for backward compatibility [RFC8446]
238 0x6404-0x64FF Unassigned
239 0x6500-0x6503 Reserved for backward compatibility [RFC8446]
240 0x6504-0x65FF Unassigned
241 0x6600-0x6603 Reserved for backward compatibility [RFC8446]
242 0x6604-0x66FF Unassigned
243 0x6700-0x6703 Reserved for backward compatibility [RFC8446]
244 0x6704-0x67FF Unassigned
245 0x6800-0x6803 Reserved for backward compatibility [RFC8446]
246 0x6804-0x68FF Unassigned
247 0x6900-0x6903 Reserved for backward compatibility [RFC8446]
248 0x6904-0x69FF Unassigned
249 0x6A00-0x6A03 Reserved for backward compatibility [RFC8446]
250 0x6A04-0x6AFF Unassigned
251 0x6B00-0x6B03 Reserved for backward compatibility [RFC8446]
252 0x6B04-0x6BFF Unassigned
253 0x6C00-0x6C03 Reserved for backward compatibility [RFC8446]
254 0x6C04-0x6CFF Unassigned
255 0x6D00-0x6D03 Reserved for backward compatibility [RFC8446]
256 0x6D04-0x6DFF Unassigned
257 0x6E00-0x6E03 Reserved for backward compatibility [RFC8446]
258 0x6E04-0x6EFF Unassigned
259 0x6F00-0x6F03 Reserved for backward compatibility [RFC8446]
260 0x6F04-0x6FFF Unassigned
261 0x7000-0x7003 Reserved for backward compatibility [RFC8446]
262 0x7004-0x70FF Unassigned
263 0x7100-0x7103 Reserved for backward compatibility [RFC8446]
264 0x7104-0x71FF Unassigned
265 0x7200-0x7203 Reserved for backward compatibility [RFC8446]
266 0x7204-0x72FF Unassigned
267 0x7300-0x7303 Reserved for backward compatibility [RFC8446]
268 0x7304-0x73FF Unassigned
269 0x7400-0x7403 Reserved for backward compatibility [RFC8446]
270 0x7404-0x74FF Unassigned
271 0x7500-0x7503 Reserved for backward compatibility [RFC8446]
272 0x7504-0x75FF Unassigned
273 0x7600-0x7603 Reserved for backward compatibility [RFC8446]
274 0x7604-0x76FF Unassigned
275 0x7700-0x7703 Reserved for backward compatibility [RFC8446]
276 0x7704-0x77FF Unassigned
277 0x7800-0x7803 Reserved for backward compatibility [RFC8446]
278 0x7804-0x78FF Unassigned
279 0x7900-0x7903 Reserved for backward compatibility [RFC8446]
280 0x7904-0x79FF Unassigned
281 0x7A00-0x7A03 Reserved for backward compatibility [RFC8446]
282 0x7A04-0x7AFF Unassigned
283 0x7B00-0x7B03 Reserved for backward compatibility [RFC8446]
284 0x7B04-0x7BFF Unassigned
285 0x7C00-0x7C03 Reserved for backward compatibility [RFC8446]
286 0x7C04-0x7CFF Unassigned
287 0x7D00-0x7D03 Reserved for backward compatibility [RFC8446]
288 0x7D04-0x7DFF Unassigned
289 0x7E00-0x7E03 Reserved for backward compatibility [RFC8446]
290 0x7E04-0x7EFF Unassigned
291 0x7F00-0x7F03 Reserved for backward compatibility [RFC8446]
292 0x7F04-0x7FFF Unassigned
293 0x8000-0x8003 Reserved for backward compatibility [RFC8446]
294 0x8004-0x80FF Unassigned
295 0x8100-0x8103 Reserved for backward compatibility [RFC8446]
296 0x8104-0x81FF Unassigned
297 0x8200-0x8203 Reserved for backward compatibility [RFC8446]
298 0x8204-0x82FF Unassigned
299 0x8300-0x8303 Reserved for backward compatibility [RFC8446]
300 0x8304-0x83FF Unassigned
301 0x8400-0x8403 Reserved for backward compatibility [RFC8446]
302 0x8404-0x84FF Unassigned
303 0x8500-0x8503 Reserved for backward compatibility [RFC8446]
304 0x8504-0x85FF Unassigned
305 0x8600-0x8603 Reserved for backward compatibility [RFC8446]
306 0x8604-0x86FF Unassigned
307 0x8700-0x8703 Reserved for backward compatibility [RFC8446]
308 0x8704-0x87FF Unassigned
309 0x8800-0x8803 Reserved for backward compatibility [RFC8446]
310 0x8804-0x88FF Unassigned
311 0x8900-0x8903 Reserved for backward compatibility [RFC8446]
312 0x8904-0x89FF Unassigned
313 0x8A00-0x8A03 Reserved for backward compatibility [RFC8446]
314 0x8A04-0x8AFF Unassigned
315 0x8B00-0x8B03 Reserved for backward compatibility [RFC8446]
316 0x8B04-0x8BFF Unassigned
317 0x8C00-0x8C03 Reserved for backward compatibility [RFC8446]
318 0x8C04-0x8CFF Unassigned
319 0x8D00-0x8D03 Reserved for backward compatibility [RFC8446]
320 0x8D04-0x8DFF Unassigned
321 0x8E00-0x8E03 Reserved for backward compatibility [RFC8446]
322 0x8E04-0x8EFF Unassigned
323 0x8F00-0x8F03 Reserved for backward compatibility [RFC8446]
324 0x8F04-0x8FFF Unassigned
325 0x9000-0x9003 Reserved for backward compatibility [RFC8446]
326 0x9004-0x90FF Unassigned
327 0x9100-0x9103 Reserved for backward compatibility [RFC8446]
328 0x9104-0x91FF Unassigned
329 0x9200-0x9203 Reserved for backward compatibility [RFC8446]
330 0x9204-0x92FF Unassigned
331 0x9300-0x9303 Reserved for backward compatibility [RFC8446]
332 0x9304-0x93FF Unassigned
333 0x9400-0x9403 Reserved for backward compatibility [RFC8446]
334 0x9404-0x94FF Unassigned
335 0x9500-0x9503 Reserved for backward compatibility [RFC8446]
336 0x9504-0x95FF Unassigned
337 0x9600-0x9603 Reserved for backward compatibility [RFC8446]
338 0x9604-0x96FF Unassigned
339 0x9700-0x9703 Reserved for backward compatibility [RFC8446]
340 0x9704-0x97FF Unassigned
341 0x9800-0x9803 Reserved for backward compatibility [RFC8446]
342 0x9804-0x98FF Unassigned
343 0x9900-0x9903 Reserved for backward compatibility [RFC8446]
344 0x9904-0x99FF Unassigned
345 0x9A00-0x9A03 Reserved for backward compatibility [RFC8446]
346 0x9A04-0x9AFF Unassigned
347 0x9B00-0x9B03 Reserved for backward compatibility [RFC8446]
348 0x9B04-0x9BFF Unassigned
349 0x9C00-0x9C03 Reserved for backward compatibility [RFC8446]
350 0x9C04-0x9CFF Unassigned
351 0x9D00-0x9D03 Reserved for backward compatibility [RFC8446]
352 0x9D04-0x9DFF Unassigned
353 0x9E00-0x9E03 Reserved for backward compatibility [RFC8446]
354 0x9E04-0x9EFF Unassigned
355 0x9F00-0x9F03 Reserved for backward compatibility [RFC8446]
356 0x9F04-0x9FFF Unassigned
357 0xA000-0xA003 Reserved for backward compatibility [RFC8446]
358 0xA004-0xA0FF Unassigned
359 0xA100-0xA103 Reserved for backward compatibility [RFC8446]
360 0xA104-0xA1FF Unassigned
361 0xA200-0xA203 Reserved for backward compatibility [RFC8446]
362 0xA204-0xA2FF Unassigned
363 0xA300-0xA303 Reserved for backward compatibility [RFC8446]
364 0xA304-0xA3FF Unassigned
365 0xA400-0xA403 Reserved for backward compatibility [RFC8446]
366 0xA404-0xA4FF Unassigned
367 0xA500-0xA503 Reserved for backward compatibility [RFC8446]
368 0xA504-0xA5FF Unassigned
369 0xA600-0xA603 Reserved for backward compatibility [RFC8446]
370 0xA604-0xA6FF Unassigned
371 0xA700-0xA703 Reserved for backward compatibility [RFC8446]
372 0xA704-0xA7FF Unassigned
373 0xA800-0xA803 Reserved for backward compatibility [RFC8446]
374 0xA804-0xA8FF Unassigned
375 0xA900-0xA903 Reserved for backward compatibility [RFC8446]
376 0xA904-0xA9FF Unassigned
377 0xAA00-0xAA03 Reserved for backward compatibility [RFC8446]
378 0xAA04-0xAAFF Unassigned
379 0xAB00-0xAB03 Reserved for backward compatibility [RFC8446]
380 0xAB04-0xABFF Unassigned
381 0xAC00-0xAC03 Reserved for backward compatibility [RFC8446]
382 0xAC04-0xACFF Unassigned
383 0xAD00-0xAD03 Reserved for backward compatibility [RFC8446]
384 0xAD04-0xADFF Unassigned
385 0xAE00-0xAE03 Reserved for backward compatibility [RFC8446]
386 0xAE04-0xAEFF Unassigned
387 0xAF00-0xAF03 Reserved for backward compatibility [RFC8446]
388 0xAF04-0xAFFF Unassigned
389 0xB000-0xB003 Reserved for backward compatibility [RFC8446]
390 0xB004-0xB0FF Unassigned
391 0xB100-0xB103 Reserved for backward compatibility [RFC8446]
392 0xB104-0xB1FF Unassigned
393 0xB200-0xB203 Reserved for backward compatibility [RFC8446]
394 0xB204-0xB2FF Unassigned
395 0xB300-0xB303 Reserved for backward compatibility [RFC8446]
396 0xB304-0xB3FF Unassigned
397 0xB400-0xB403 Reserved for backward compatibility [RFC8446]
398 0xB404-0xB4FF Unassigned
399 0xB500-0xB503 Reserved for backward compatibility [RFC8446]
400 0xB504-0xB5FF Unassigned
401 0xB600-0xB603 Reserved for backward compatibility [RFC8446]
402 0xB604-0xB6FF Unassigned
403 0xB700-0xB703 Reserved for backward compatibility [RFC8446]
404 0xB704-0xB7FF Unassigned
405 0xB800-0xB803 Reserved for backward compatibility [RFC8446]
406 0xB804-0xB8FF Unassigned
407 0xB900-0xB903 Reserved for backward compatibility [RFC8446]
408 0xB904-0xB9FF Unassigned
409 0xBA00-0xBA03 Reserved for backward compatibility [RFC8446]
410 0xBA04-0xBAFF Unassigned
411 0xBB00-0xBB03 Reserved for backward compatibility [RFC8446]
412 0xBB04-0xBBFF Unassigned
413 0xBC00-0xBC03 Reserved for backward compatibility [RFC8446]
414 0xBC04-0xBCFF Unassigned
415 0xBD00-0xBD03 Reserved for backward compatibility [RFC8446]
416 0xBD04-0xBDFF Unassigned
417 0xBE00-0xBE03 Reserved for backward compatibility [RFC8446]
418 0xBE04-0xBEFF Unassigned
419 0xBF00-0xBF03 Reserved for backward compatibility [RFC8446]
420 0xBF04-0xBFFF Unassigned
421 0xC000-0xC003 Reserved for backward compatibility [RFC8446]
422 0xC004-0xC0FF Unassigned
423 0xC100-0xC103 Reserved for backward compatibility [RFC8446]
424 0xC104-0xC1FF Unassigned
425 0xC200-0xC203 Reserved for backward compatibility [RFC8446]
426 0xC204-0xC2FF Unassigned
427 0xC300-0xC303 Reserved for backward compatibility [RFC8446]
428 0xC304-0xC3FF Unassigned
429 0xC400-0xC403 Reserved for backward compatibility [RFC8446]
430 0xC404-0xC4FF Unassigned
431 0xC500-0xC503 Reserved for backward compatibility [RFC8446]
432 0xC504-0xC5FF Unassigned
433 0xC600-0xC603 Reserved for backward compatibility [RFC8446]
434 0xC604-0xC6FF Unassigned
435 0xC700-0xC703 Reserved for backward compatibility [RFC8446]
436 0xC704-0xC7FF Unassigned
437 0xC800-0xC803 Reserved for backward compatibility [RFC8446]
438 0xC804-0xC8FF Unassigned
439 0xC900-0xC903 Reserved for backward compatibility [RFC8446]
440 0xC904-0xC9FF Unassigned
441 0xCA00-0xCA03 Reserved for backward compatibility [RFC8446]
442 0xCA04-0xCAFF Unassigned
443 0xCB00-0xCB03 Reserved for backward compatibility [RFC8446]
444 0xCB04-0xCBFF Unassigned
445 0xCC00-0xCC03 Reserved for backward compatibility [RFC8446]
446 0xCC04-0xCCFF Unassigned
447 0xCD00-0xCD03 Reserved for backward compatibility [RFC8446]
448 0xCD04-0xCDFF Unassigned
449 0xCE00-0xCE03 Reserved for backward compatibility [RFC8446]
450 0xCE04-0xCEFF Unassigned
451 0xCF00-0xCF03 Reserved for backward compatibility [RFC8446]
452 0xCF04-0xCFFF Unassigned
453 0xD000-0xD003 Reserved for backward compatibility [RFC8446]
454 0xD004-0xD0FF Unassigned
455 0xD100-0xD103 Reserved for backward compatibility [RFC8446]
456 0xD104-0xD1FF Unassigned
457 0xD200-0xD203 Reserved for backward compatibility [RFC8446]
458 0xD204-0xD2FF Unassigned
459 0xD300-0xD303 Reserved for backward compatibility [RFC8446]
460 0xD304-0xD3FF Unassigned
461 0xD400-0xD403 Reserved for backward compatibility [RFC8446]
462 0xD404-0xD4FF Unassigned
463 0xD500-0xD503 Reserved for backward compatibility [RFC8446]
464 0xD504-0xD5FF Unassigned
465 0xD600-0xD603 Reserved for backward compatibility [RFC8446]
466 0xD604-0xD6FF Unassigned
467 0xD700-0xD703 Reserved for backward compatibility [RFC8446]
468 0xD704-0xD7FF Unassigned
469 0xD800-0xD803 Reserved for backward compatibility [RFC8446]
470 0xD804-0xD8FF Unassigned
471 0xD900-0xD903 Reserved for backward compatibility [RFC8446]
472 0xD904-0xD9FF Unassigned
473 0xDA00-0xDA03 Reserved for backward compatibility [RFC8446]
474 0xDA04-0xDAFF Unassigned
475 0xDB00-0xDB03 Reserved for backward compatibility [RFC8446]
476 0xDB04-0xDBFF Unassigned
477 0xDC00-0xDC03 Reserved for backward compatibility [RFC8446]
478 0xDC04-0xDCFF Unassigned
479 0xDD00-0xDD03 Reserved for backward compatibility [RFC8446]
480 0xDD04-0xDDFF Unassigned
481 0xDE00-0xDE03 Reserved for backward compatibility [RFC8446]
482 0xDE04-0xDEFF Unassigned
483 0xDF00-0xDF03 Reserved for backward compatibility [RFC8446]
484 0xDF04-0xDFFF Unassigned
485 0xE000-0xE003 Reserved for backward compatibility [RFC8446]
486 0xE004-0xE0FF Unassigned
487 0xE100-0xE103 Reserved for backward compatibility [RFC8446]
488 0xE104-0xE1FF Unassigned
489 0xE200-0xE203 Reserved for backward compatibility [RFC8446]
490 0xE204-0xE2FF Unassigned
491 0xE300-0xE303 Reserved for backward compatibility [RFC8446]
492 0xE304-0xE3FF Unassigned
493 0xE400-0xE403 Reserved for backward compatibility [RFC8446]
494 0xE404-0xE4FF Unassigned
495 0xE500-0xE503 Reserved for backward compatibility [RFC8446]
496 0xE504-0xE5FF Unassigned
497 0xE600-0xE603 Reserved for backward compatibility [RFC8446]
498 0xE604-0xE6FF Unassigned
499 0xE700-0xE703 Reserved for backward compatibility [RFC8446]
500 0xE704-0xE7FF Unassigned
501 0xE800-0xE803 Reserved for backward compatibility [RFC8446]
502 0xE804-0xE8FF Unassigned
503 0xE900-0xE903 Reserved for backward compatibility [RFC8446]
504 0xE904-0xE9FF Unassigned
505 0xEA00-0xEA03 Reserved for backward compatibility [RFC8446]
506 0xEA04-0xEAFF Unassigned
507 0xEB00-0xEB03 Reserved for backward compatibility [RFC8446]
508 0xEB04-0xEBFF Unassigned
509 0xEC00-0xEC03 Reserved for backward compatibility [RFC8446]
510 0xEC04-0xECFF Unassigned
511 0xED00-0xED03 Reserved for backward compatibility [RFC8446]
512 0xED04-0xEDFF Unassigned
513 0xEE00-0xEE03 Reserved for backward compatibility [RFC8446]
514 0xEE04-0xEEFF Unassigned
515 0xEF00-0xEF03 Reserved for backward compatibility [RFC8446]
516 0xEF04-0xEFFF Unassigned
517 0xF000-0xF003 Reserved for backward compatibility [RFC8446]
518 0xF004-0xF0FF Unassigned
519 0xF100-0xF103 Reserved for backward compatibility [RFC8446]
520 0xF104-0xF1FF Unassigned
521 0xF200-0xF203 Reserved for backward compatibility [RFC8446]
522 0xF204-0xF2FF Unassigned
523 0xF300-0xF303 Reserved for backward compatibility [RFC8446]
524 0xF304-0xF3FF Unassigned
525 0xF400-0xF403 Reserved for backward compatibility [RFC8446]
526 0xF404-0xF4FF Unassigned
527 0xF500-0xF503 Reserved for backward compatibility [RFC8446]
528 0xF504-0xF5FF Unassigned
529 0xF600-0xF603 Reserved for backward compatibility [RFC8446]
530 0xF604-0xF6FF Unassigned
531 0xF700-0xF703 Reserved for backward compatibility [RFC8446]
532 0xF704-0xF7FF Unassigned
533 0xF800-0xF803 Reserved for backward compatibility [RFC8446]
534 0xF804-0xF8FF Unassigned
535 0xF900-0xF903 Reserved for backward compatibility [RFC8446]
536 0xF904-0xF9FF Unassigned
537 0xFA00-0xFA03 Reserved for backward compatibility [RFC8446]
538 0xFA04-0xFAFF Unassigned
539 0xFB00-0xFB03 Reserved for backward compatibility [RFC8446]
540 0xFB04-0xFBFF Unassigned
541 0xFC00-0xFC03 Reserved for backward compatibility [RFC8446]
542 0xFC04-0xFCFF Unassigned
543 0xFD00-0xFD03 Reserved for backward compatibility [RFC8446]
544 0xFD04-0xFDFF Unassigned
545 0xFE00-0xFFFF Reserved for Private Use [RFC8446]

View File

@ -0,0 +1,111 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
package clienthello
import (
_ "embed"
"encoding/csv"
"fmt"
"io"
"log"
"strconv"
"strings"
)
// RFC 8446, Section 4.2.3
// https://www.rfc-editor.org/rfc/rfc8446.html#section-4.2.3
// https://www.iana.org/assignments/tls-parameters/tls-signaturescheme.csv
//
//go:embed signature-schemes.csv
var signatureSchemesCSV string
var SignatureSchemeList = parseSignatureSchemesCSV()
type SignatureScheme any // (uint16 | SignatureSchemeInfo)
type SignatureSchemeInfo struct {
Code uint16 `json:"code"`
HexCode string `json:"hex_code"`
Name string `json:"name"`
Recommended bool `json:"-"`
Reference string `json:"-"`
}
func parseSignatureSchemesCSV() map[uint16]SignatureSchemeInfo {
signatureSchemes := map[uint16]SignatureSchemeInfo{}
r := csv.NewReader(strings.NewReader(signatureSchemesCSV))
// Skip CSV header.
_, err := r.Read()
if err != nil {
log.Fatal(err)
}
for {
row, err := r.Read()
if err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
var (
val = row[0]
desc = row[1]
rec = row[2]
ref = row[3]
)
if desc == "Unassigned" {
continue
}
if strings.HasPrefix(desc, "Reserved") && ref != "[RFC8701]" {
continue
}
val = strings.Replace(val, "0x", "", 1)
code, err := strconv.ParseUint(val, 16, 16)
if err != nil {
log.Println(err)
}
sigScheme := SignatureSchemeInfo{
Code: uint16(code),
HexCode: fmt.Sprintf("%04X", code),
Name: desc,
Reference: ref,
}
if rec == "Y" {
sigScheme.Recommended = true
}
if ref == "[RFC8701]" || isGREASE(sigScheme.Code) {
// (We call isGREASE() because the IANA signature scheme registry
// doesn't currently include GREASE values).
sigScheme.Name = "GREASE"
}
signatureSchemes[sigScheme.Code] = sigScheme
}
return signatureSchemes
}
func GetSignatureSchemeInfo(sigSchemeCode uint16) SignatureSchemeInfo {
info, found := SignatureSchemeList[sigSchemeCode]
if !found {
info = SignatureSchemeInfo{
Code: sigSchemeCode,
HexCode: fmt.Sprintf("%04X", sigSchemeCode),
}
}
return info
}
func (m *ClientHelloMsg) AddSignatureSchemeInfo() {
for i, ext := range m.Extensions {
if ext.Code == extensionSignatureAlgorithms ||
ext.Code == extensionSignatureAlgorithmsCert {
for j, sigAlg := range ext.Data.SupportedSignatureAlgorithms {
m.Extensions[i].Data.SupportedSignatureAlgorithms[j] = GetSignatureSchemeInfo(
sigAlg.(uint16))
}
}
}
}

View File

@ -0,0 +1,66 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
package clienthello
import (
"fmt"
)
var TLSVersionList = map[uint16]TLSVersionInfo{
768: {Code: 768, HexCode: "0300", Name: "SSL 3.0"},
769: {Code: 769, HexCode: "0301", Name: "TLS 1.0"},
770: {Code: 770, HexCode: "0302", Name: "TLS 1.1"},
771: {Code: 771, HexCode: "0303", Name: "TLS 1.2"},
772: {Code: 772, HexCode: "0304", Name: "TLS 1.3"},
0x0A0A: {Code: 0x0A0A, HexCode: "0A0A", Name: "GREASE"},
0x1A1A: {Code: 0x1A1A, HexCode: "1A1A", Name: "GREASE"},
0x2A2A: {Code: 0x2A2A, HexCode: "2A2A", Name: "GREASE"},
0x3A3A: {Code: 0x3A3A, HexCode: "3A3A", Name: "GREASE"},
0x4A4A: {Code: 0x4A4A, HexCode: "4A4A", Name: "GREASE"},
0x5A5A: {Code: 0x5A5A, HexCode: "5A5A", Name: "GREASE"},
0x6A6A: {Code: 0x6A6A, HexCode: "6A6A", Name: "GREASE"},
0x7A7A: {Code: 0x7A7A, HexCode: "7A7A", Name: "GREASE"},
0x8A8A: {Code: 0x8A8A, HexCode: "8A8A", Name: "GREASE"},
0x9A9A: {Code: 0x9A9A, HexCode: "9A9A", Name: "GREASE"},
0xAAAA: {Code: 0xAAAA, HexCode: "AAAA", Name: "GREASE"},
0xBABA: {Code: 0xBABA, HexCode: "BABA", Name: "GREASE"},
0xCACA: {Code: 0xCACA, HexCode: "CACA", Name: "GREASE"},
0xDADA: {Code: 0xDADA, HexCode: "DADA", Name: "GREASE"},
0xEAEA: {Code: 0xEAEA, HexCode: "EAEA", Name: "GREASE"},
0xFAFA: {Code: 0xFAFA, HexCode: "FAFA", Name: "GREASE"},
}
type TLSVersion any // (uint16 | TLSVersioninfo)
type TLSVersionInfo struct {
Code uint16 `json:"code"`
HexCode string `json:"hex_code"`
Name string `json:"name"`
}
func GetTLSVersionInfo(tlsVersionCode uint16) TLSVersionInfo {
info, found := TLSVersionList[tlsVersionCode]
if !found {
info = TLSVersionInfo{
Code: tlsVersionCode,
HexCode: fmt.Sprintf("%04X", tlsVersionCode),
}
}
return info
}
func (m *ClientHelloMsg) AddTLSVersionInfo() {
m.RecordHeaderTLSVersion = GetTLSVersionInfo(m.RecordHeaderTLSVersion.(uint16))
m.TLSVersion = GetTLSVersionInfo(m.TLSVersion.(uint16))
for i, ext := range m.Extensions {
if ext.Code == extensionSupportedVersions {
for j, versionCode := range ext.Data.SupportedVersions {
m.Extensions[i].Data.SupportedVersions[j] = GetTLSVersionInfo(
versionCode.(uint16))
}
}
}
}

View File

@ -1,3 +1,7 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
package main
import (

4
go.mod
View File

@ -1,3 +1,7 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
module tildegit.org/nervuri/client-hello-mirror
go 1.19

View File

@ -1,6 +1,6 @@
# TLS Client Hello Mirror
=> /json/v1 Your browser's TLS Client Hello, reflected as JSON
## Your browser's TLS Client Hello, reflected as JSON
This test:
@ -9,14 +9,16 @@ This test:
* supports multiple protocols (currently HTTP and Gemini);
* is free as in freedom and trivial to self-host.
JSON only, for now. The API is largely stable - fields may be added, but existing fields will not be modified or removed. IANA-assigned codes for TLS parameters and extensions are available at:
## Endpoints
=> https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml TLS parameters
=> https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml TLS extensions
=> /json/v1 json/v1 - basic
=> /json/v2 json/v2 - detailed
Note that these lists do not include draft extensions and GREASE values. Missing values will be documented here as the project evolves.
JSON only, for now. The API is largely stable - fields may be added, but existing fields will not be modified or removed. See the documentation for details:
=> https://tildegit.org/nervuri/client-hello-mirror/src/branch/master/DOC.md API documentation
_____________________
=> https://nervuri.net/ Author: nervuri
=> https://tildegit.org/nervuri/client-hello-mirror Source (contributions welcome)
=> https://www.gnu.org/licenses/agpl-3.0.en.html License: AGPL-3.0-or-later
=> https://opensource.org/license/BSD-3-clause/ License: BSD-3-Clause

View File

@ -1,62 +1,71 @@
<!--
SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
SPDX-License-Identifier: BSD-3-Clause
-->
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#000">
<meta name="referrer" content="no-referrer">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="theme-color" content="#000"/>
<meta name="referrer" content="no-referrer"/>
<title>TLS Client Hello Mirror</title>
<style>
:root {
color-scheme: dark;
}
::selection {
color: #FFF;
background-color: #070;
}
body {
color: #DDD;
background-color: #000;
margin: 1em auto;
max-width: 38em;
padding: 0 .62em;
font: 1.1em/1.62 sans-serif;
}
@media print{
body{
max-width: none;
:root {
color-scheme: dark;
}
}
a:link {color:#EEE;}
a:visited {color:#EEE;}
a:hover {color:#FFF;}
a:active {color:#FFF;}
::selection {
color: #FFF;
background-color: #070;
}
body {
color: #DDD;
background-color: #000;
margin: 1em auto;
max-width: 38em;
padding: 0 .62em;
font: 1.1em/1.62 sans-serif;
tab-size: 4;
}
@media print{
body{
max-width: none;
}
}
h1 {
text-align: center;
}
a:link {color:#EEE;}
a:visited {color:#EEE;}
a:hover {color:#FFF;}
a:active {color:#FFF;}
</style>
</head>
<body>
<main>
<center>
<h1>TLS Client Hello Mirror</h1>
</center>
<h3><a href="/json/v1">Your browser's TLS Client Hello, reflected as JSON</a></h3>
<p>This test:
<ul>
<li>reflects the complete Client Hello message, preserving the order in which TLS parameters and extensions are sent;</li>
<li>can be used to check for TLS privacy pitfalls (<a href="https://svs.informatik.uni-hamburg.de/publications/2018/2018-12-06-Sy-ACSAC-Tracking_Users_across_the_Web_via_TLS_Session_Resumption.pdf">session resumption</a>, <a href="https://tlsfingerprint.io/">TLS fingerprinting</a>, <a href="https://datatracker.ietf.org/doc/html/draft-mathewson-no-gmtunixtime">system time exposure</a>);</li>
<li>supports both HTTP and <a href="https://gemini.circumlunar.space/">Gemini</a>;</li>
<li>is <a href="https://www.gnu.org/philosophy/free-sw.en.html">free as in freedom</a> and trivial to self-host.</li>
</ul>
</p>
<p>JSON only, for now, but a UI is on <a href="https://tildegit.org/nervuri/client-hello-mirror#roadmap">the roadmap</a>.</p>
<p>The API is largely stable - fields may be added, but existing fields will not be modified or removed. IANA-assigned codes for TLS parameters and extensions are documented at:
<ul>
<li><a href="https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml">TLS parameters</a></li>
<li><a href="https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml">TLS extensions</a></li>
</ul>
Note that these lists do not include draft extensions and <a href="https://datatracker.ietf.org/doc/html/rfc8701">GREASE</a> values. Missing values will be documented here as the project evolves.
</p>
<h1>TLS Client Hello Mirror</h1>
<h3>Your browser's TLS Client Hello, reflected as JSON</h3>
<p>This test:</p>
<ul>
<li>reflects the complete Client Hello message, preserving the order in which TLS parameters and extensions are sent;</li>
<li>can be used to check for TLS privacy pitfalls (<a href="https://svs.informatik.uni-hamburg.de/publications/2018/2018-12-06-Sy-ACSAC-Tracking_Users_across_the_Web_via_TLS_Session_Resumption.pdf">session resumption</a>, <a href="https://tlsfingerprint.io/">TLS fingerprinting</a>, <a href="https://datatracker.ietf.org/doc/html/draft-mathewson-no-gmtunixtime">system time exposure</a>);</li>
<li>supports both HTTP and <a href="https://gemini.circumlunar.space/">Gemini</a>;</li>
<li>is <a href="https://www.gnu.org/philosophy/free-sw.en.html">free as in freedom</a> and trivial to self-host.</li>
</ul>
<h3>Endpoints</h3>
<ul>
<li><a href="/json/v1">json/v1 - basic</a></li>
<li><a href="/json/v2">json/v2 - detailed</a></li>
</ul>
<p>JSON only, for now. The API is largely stable - fields may be added, but existing fields will not be modified or removed. See <a href="https://tildegit.org/nervuri/client-hello-mirror/src/branch/master/DOC.md">the documentation</a> for details.</p>
</main>
<hr>
<hr/>
<footer>
Author: <a href="https://nervuri.net/">nervuri</a><br>
<a href="https://tildegit.org/nervuri/client-hello-mirror">Source</a> (contributions welcome)<br>
License: <a href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPL-3.0-or-later</a>
Author: <a href="https://nervuri.net/">nervuri</a><br/>
<a href="https://tildegit.org/nervuri/client-hello-mirror">Source</a> (contributions welcome)<br/>
License: <a href="https://opensource.org/license/BSD-3-clause/">BSD-3-Clause</a>
</footer>
</body>
</html>

59
request.go Normal file
View File

@ -0,0 +1,59 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
package main
import (
"errors"
"net/url"
"strings"
)
type request struct {
Protocol int
HTTPMethod int
Path string
}
// Supported protocols
const (
httpProtocol = 1
geminiProtocol = 2
)
// Supported HTTP methods
const (
getMethod = 1
headMethod = 2
)
var ErrNotSupported = errors.New("Unsupported protocol or HTTP method")
// Get request information from the first line of the request.
func getRequestInfo(firstLine string) (req request, err error) {
if strings.HasPrefix(firstLine, "gemini://") {
req.Protocol = geminiProtocol
var u *url.URL
u, err = url.Parse(firstLine)
if err != nil {
return
}
req.Path = u.Path
} else if strings.HasPrefix(firstLine, "GET ") {
req.HTTPMethod = getMethod
} else if strings.HasPrefix(firstLine, "HEAD ") {
req.HTTPMethod = headMethod
} else {
err = ErrNotSupported
return
}
if req.HTTPMethod != 0 {
req.Protocol = httpProtocol
req.Path = strings.Split(firstLine, " ")[1]
}
if req.Path == "" {
req.Path = "/"
}
return
}

55
response.go Normal file
View File

@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
package main
import (
"fmt"
"strings"
"time"
)
type response struct {
req *request
StatusLine string
Headers map[string]string
Body string
}
func NewResponse(req *request) response {
var r = response{
req: req,
Headers: make(map[string]string),
}
if r.req.Protocol == httpProtocol {
r.StatusLine = "HTTP/1.1 200 OK"
r.Headers["Content-Type"] = "text/html; charset=utf-8"
} else if r.req.Protocol == geminiProtocol {
r.StatusLine = "20 text/gemini"
}
return r
}
func (r *response) DisableCaching() {
r.Headers["Cache-Control"] = "no-store"
r.Headers["Vary"] = "*"
}
func (r *response) Prepare() []byte {
var responseBytes = []byte(r.StatusLine + "\r\n")
if r.req.Protocol == httpProtocol {
t := time.Now().UTC()
r.Headers["Date"] = strings.Replace(t.Format(time.RFC1123), "UTC", "GMT", 1)
r.Headers["Content-Length"] = fmt.Sprint(len(r.Body))
r.Headers["Connection"] = "close"
for name, value := range r.Headers {
responseBytes = append(responseBytes, []byte(name+": "+value+"\r\n")...)
}
responseBytes = append(responseBytes, []byte("\r\n")...) // end of headers
}
if r.req.HTTPMethod != headMethod {
responseBytes = append(responseBytes, []byte(r.Body)...)
}
return responseBytes
}

168
server.go
View File

@ -1,4 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
// SPDX-FileCopyrightText: 2022-2023 nervuri <https://nervuri.net/contact>
//
// SPDX-License-Identifier: BSD-3-Clause
package main
@ -13,20 +15,20 @@ import (
"io"
"log"
"net"
"net/url"
"os"
"strings"
"time"
"tildegit.org/nervuri/client-hello-mirror/clienthello"
)
const readTimeout = 10 // seconds
const writeTimeout = 10 // seconds
type tlsConnectionInfo struct {
TlsVersion uint16 `json:"tls_version"`
CipherSuite uint16 `json:"cipher_suite"`
SessionResumed bool `json:"session_resumed"`
NegotiatedProtocol string `json:"alpn_negotiated_protocol"` // ALPN
TLSVersion clienthello.TLSVersion `json:"tls_version"`
CipherSuite clienthello.CipherSuite `json:"cipher_suite"`
SessionResumed bool `json:"session_resumed"`
NegotiatedProtocol string `json:"alpn_negotiated_protocol"` // ALPN
}
// Connection wrapper that enables exposing the Client Hello to the
@ -58,9 +60,17 @@ var gemtext string
// Copy the Client Hello message before starting the TLS handshake.
func peek(conn net.Conn, tlsConfig *tls.Config) {
defer conn.Close()
// Set read timeout.
err := conn.SetReadDeadline(time.Now().Add(readTimeout * time.Second))
if err != nil {
log.Println("SetReadDeadline error: ", err.Error())
return
}
var buf bytes.Buffer
// Copy TLS record header.
_, err := io.CopyN(&buf, conn, 5)
_, err = io.CopyN(&buf, conn, 5)
if err != nil {
log.Println(err)
return
@ -71,7 +81,11 @@ func peek(conn net.Conn, tlsConfig *tls.Config) {
}
// Extract handshake message length.
handshakeMessageLength := binary.BigEndian.Uint16(buf.Bytes()[3:5])
// Copy handshake message (should be a Client Hello).
if handshakeMessageLength == 0 {
log.Println("Zero-length handshake message")
return
}
// Copy handshake message.
_, err = io.CopyN(&buf, conn, int64(handshakeMessageLength))
if err != nil {
log.Println(err)
@ -79,6 +93,12 @@ func peek(conn net.Conn, tlsConfig *tls.Config) {
}
rawClientHello := buf.Bytes()
// Check if this really is a Client Hello message.
if rawClientHello[5] != 1 {
log.Println("HandshakeType is not client_hello")
return
}
// "Put back" the Client Hello bytes we just read, so that they can be
// used in the TLS handshake. Concatenate the read bytes with the
// unread bytes using a MultiReader, inside a connection wrapper.
@ -99,6 +119,7 @@ func peek(conn net.Conn, tlsConfig *tls.Config) {
func requestHandler(conn *tls.Conn, rawClientHello []byte) {
defer conn.Close()
// Read first line.
scanner := bufio.NewScanner(conn)
scanner.Scan()
line := scanner.Text()
@ -108,60 +129,22 @@ func requestHandler(conn *tls.Conn, rawClientHello []byte) {
return
}
var protocol string
var path string // requested page
// Detect protocol by checking the first few characters.
if strings.HasPrefix(line, "gemini://") {
protocol = "Gemini"
u, err := url.Parse(line)
if err != nil {
log.Println(err)
return
}
path = u.Path
if path == "" {
path = "/"
}
if path == "/" {
_, err = conn.Write([]byte("20 text/gemini\r\n"))
} else if path == "/json/v1" {
_, err = conn.Write([]byte("20 application/json\r\n"))
}
} else if strings.HasPrefix(line, "GET ") ||
strings.HasPrefix(line, "POST ") ||
strings.HasPrefix(line, "HEAD ") {
protocol = "HTTP"
path = strings.Split(line, " ")[1]
if path == "/" {
_, err = conn.Write([]byte("HTTP/1.1 200 OK\r\n"))
_, err = conn.Write([]byte("Content-Type: text/html; charset=utf-8\r\n"))
_, err = conn.Write([]byte("Cache-Control: no-store\r\n"))
_, err = conn.Write([]byte("Vary: *\r\n"))
} else if path == "/json/v1" {
_, err = conn.Write([]byte("HTTP/1.1 200 OK\r\n"))
_, err = conn.Write([]byte("Content-Type: application/json\r\n"))
_, err = conn.Write([]byte("Cache-Control: no-store\r\n"))
_, err = conn.Write([]byte("Vary: *\r\n"))
} else {
_, err = conn.Write([]byte("HTTP/1.1 404 Not Found\r\n"))
}
_, err = conn.Write([]byte("\r\n")) // end headers
if strings.HasPrefix(line, "HEAD ") {
return // headers only
}
} else {
log.Println("Unknown protocol")
// Get request info from first line.
req, err := getRequestInfo(line)
if err != nil {
log.Println(err)
return
}
var clientHello clientHelloMsg
if !clientHello.unmarshal(rawClientHello) {
// Parse Client Hello message.
var clientHelloMsg clienthello.ClientHelloMsg
if !clientHelloMsg.Unmarshal(rawClientHello) {
log.Println("Failed to parse Client Hello")
return
}
connectionState := conn.ConnectionState() // TLS
// Get TLS connection info.
connectionState := conn.ConnectionState()
tlsConnInfo := tlsConnectionInfo{
connectionState.Version,
connectionState.CipherSuite,
@ -169,21 +152,35 @@ func requestHandler(conn *tls.Conn, rawClientHello []byte) {
connectionState.NegotiatedProtocol,
}
if path == "/" {
if protocol == "HTTP" {
_, err = conn.Write([]byte(html))
} else if protocol == "Gemini" {
_, err = conn.Write([]byte(gemtext))
} else {
log.Println("Unknown protocol")
return
// Prepare response.
var resp = NewResponse(&req)
if req.Path == "/" {
if req.Protocol == httpProtocol {
resp.DisableCaching()
resp.Body = html
} else if req.Protocol == geminiProtocol {
resp.Body = gemtext
}
} else if req.Path == "/json/v1" || req.Path == "/json/v2" {
if req.Protocol == httpProtocol {
resp.Headers["Content-Type"] = "application/json"
resp.DisableCaching()
} else if req.Protocol == geminiProtocol {
resp.StatusLine = "20 application/json"
}
if req.Path == "/json/v2" {
clientHelloMsg.AddInfo()
tlsConnInfo.TLSVersion = clienthello.GetTLSVersionInfo(
tlsConnInfo.TLSVersion.(uint16))
tlsConnInfo.CipherSuite = clienthello.GetCipherSuiteInfo(
tlsConnInfo.CipherSuite.(uint16))
}
} else if path == "/json/v1" {
output := struct {
ClientHello clientHelloMsg `json:"client_hello"`
TlsConnectionInfo tlsConnectionInfo `json:"connection_info"`
ClientHello clienthello.ClientHelloMsg `json:"client_hello"`
TLSConnectionInfo tlsConnectionInfo `json:"connection_info"`
}{
clientHello,
clientHelloMsg,
tlsConnInfo,
}
outputJSON, err := json.MarshalIndent(output, "", " ")
@ -191,8 +188,24 @@ func requestHandler(conn *tls.Conn, rawClientHello []byte) {
log.Println(err)
return
}
_, err = conn.Write(outputJSON)
resp.Body = string(outputJSON)
} else {
if req.Protocol == httpProtocol {
resp.StatusLine = "HTTP/1.1 404 Not Found"
resp.Headers["Content-Type"] = "text/plain; charset=utf-8"
resp.Body = "404 Not Found"
} else if req.Protocol == geminiProtocol {
resp.StatusLine = "51 Not Found!"
}
}
// Set write timeout.
err = conn.SetWriteDeadline(time.Now().Add(writeTimeout * time.Second))
if err != nil {
log.Println("SetWriteDeadline error: ", err.Error())
return
}
// Write response.
_, err = conn.Write(resp.Prepare())
if err != nil {
log.Println(err)
return
@ -205,7 +218,7 @@ func main() {
var userToSwitchTo string
var hostAndPort string
// Parse arguments
// Parse arguments.
flag.StringVar(&certFile, "c", "", "path to certificate file")
flag.StringVar(&keyFile, "k", "", "path to private key file")
flag.StringVar(&userToSwitchTo, "u", "", "user to switch to, if running as root")
@ -215,7 +228,7 @@ func main() {
fatalError("usage: client-hello-mirror -c cert.pem -k key.pem [-u user] host:port")
}
// Load cert
// Load cert.
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
fatalError(err)
@ -227,7 +240,7 @@ func main() {
NextProtos: []string{"http/1.1"},
}
// Listen for connections
// Listen for connections.
ln, err := net.Listen("tcp", hostAndPort)
if err != nil {
fatalError(err)
@ -245,17 +258,6 @@ func main() {
log.Println("Error accepting: ", err.Error())
continue
}
// Set connection timeouts.
err = conn.SetReadDeadline(time.Now().Add(readTimeout * time.Second))
if err != nil {
log.Println("SetReadDeadline error: ", err.Error())
continue
}
err = conn.SetWriteDeadline(time.Now().Add(writeTimeout * time.Second))
if err != nil {
log.Println("SetWriteDeadline error: ", err.Error())
continue
}
// Process the request.
go peek(conn, &tlsConfig)
}