Understanding the TLS/SSL protocol
I'm currently taking a university class on security and cryptography, and one of the projects we're doing involves implementing a basic TLS socket.
So, I've studied the TLS protocol using both my textbook as well as the latest RFC, so I have a pretty good understanding of how TLS/SSL works, and also how the TLS record format is laid out, byte-by-byte.
So, to start out I decided to write a server program that listens on port 443 and accepts incoming secure HTTP connections. All it does is accept a client connection and then print out a hex dump of the initial message sent by the client.
But when I connect to my server using a web-browser (Firefox), I'm totally baffled by the bytestream the browser sends me. According to the RFC, the first thing a TLS client must do is send a ClientHello
message. All messages must be encapsulated in a TLS record format, which is supposed to be formatted like this (using the C-ish notation the RFC uses):
struct {
ContentType type;
ProtocolVersion version;
uint16 length;
opaque fragment[TLSPlaintext.length];
} TLSPlaintext;
The ContentType
field is a single enum value that must be one of the following types: change_cipher_spec = 0x14, alert = 0x15, handshake = 0x16, application_data = 0x17
So, since the first thing a client must do is send a ClientHello message, which is part of the handshake,开发者_如何转开发 I'd expect the very first byte in the bytestream to be a 0x16
, indicating this is a handshake message.
But instead, the actual bytestream my browser sends is:
80 55 01 03 00 00 3c 00 00 00 10 00 00 88 00 00 87 00 00 39 00 00
38 00 00 84 00 00 35 00 00 45 00 00 44 00 00 33 00 00 32 00 00 96
00 00 41 00 00 04 00 00 05 00 00 2f 00 00 16 00 00 13 00 fe ff 00
00 0a 00 00 ff 07 99 58 ad 17 f3 17 23 be 63 8c 6d cb 9b 5f 6f
I can't make any sense of this bytestream, even after pouring over the RFC for hours. Everything I read about TLS tells me that the first byte should be a 0x16
to indicate a handshake, followed by a two-byte version field, followed by a two-byte record length field. But this byte-stream begins with an 0x80 0x55
, which is meaningless to me.
Can anyone clear up what's going on here? Am I misunderstanding some part of the TLS protocol?
What you are seeing is the SSL version 2 compatible hello. Look at appendix E of RFC 5246. I don't believe the newest versions of firefox will send that, they'll only send the V3 hello format that you were expecting.
Wireshark has a parser for HTTPS/TLS/SSL, this will be able to make sense of the plain text part of the handshake.
Also make sure to read The First few milliseconds of an HTTPS connection.
精彩评论