How does SSL/TLS work?
How does SSL work? I just realised we don't actually have a definitive answer here, and it's something worth covering.
I'd like to see details in terms of:
- A high level description of the protocol.
- How the key exchange works.
- How authenticity, integrity and confidentiality are enforced.
- What the purpose of having CAs is, and how they issue certificates.
- Details of any important technologies and standards (e.g. PKCS) that are involved.
SSL (and its successor, TLS) is a protocol that operates directly on top of TCP (although there are also implementations for datagram based protocols such as UDP). This way, protocols on higher layers (such as HTTP) can be left unchanged while still providing a secure connection. Underneath the SSL layer, HTTP is identical to HTTPS.
When using SSL/TLS correctly, all an attacker can see on the cable is which IP and port you are connected to, roughly how much data you are sending, and what encryption and compression are used. He can also terminate the connection, but both sides will know that the connection has been interrupted by a third party.
In typical use, the attacker will also be able to figure out which hostname you're connecting to (but not the rest of the URL): although HTTPS itself does not expose the hostname, your browser will usually need to make a DNS request first to find out what IP address to send the request to.
High-level description of the protocol
After building a TCP connection, the SSL handshake is started by the client. The client (which can be a browser as well as any other program such as Windows Update or PuTTY) sends a number of specifications:
- which version of SSL/TLS it is running,
- what ciphersuites it wants to use, and
- what compression methods it wants to use.
The server checks what the highest SSL/TLS version is that is supported by them both picks a ciphersuite from one of the client's options (if it supports one), and optionally picks a compression method.
After this the basic setup is done, the server sends its certificate. This certificate must be trusted by either the client itself or a party that the client trusts. For example, if the client trusts GeoTrust, then the client can trust the certificate from Google.com because GeoTrust cryptographically signed Google's certificate.
Having verified the certificate and being certain this server really is who he claims to be (and not a man in the middle), a key is exchanged. This can be a public key, a "PreMasterSecret" or simply nothing, depending on the chosen ciphersuite. Both the server and the client can now compute the key for the symmetric encryption whynot PKE?. The client tells the server that from now on, all communication will be encrypted, and sends an encrypted and authenticated message to the server.
The server verifies that the MAC (used for authentication) is correct and that the message can be correctly decrypted. It then returns a message, which the client verifies as well.
To close the connection, a close_notify 'alert' is used. If an attacker tries to terminate the connection by finishing the TCP connection (injecting a FIN packet), both sides will know the connection was improperly terminated. The connection cannot be compromised by this though, merely interrupted.
Some more detailsWhy can you trust Google.com by trusting GeoTrust?
A website wants to communicate with you securely. In order to prove its identity and make sure that it is not an attacker, you must have the server's public key. However, you can hardly store all keys from all websites on earth, the database would be huge and updates would have to run every hour!
The solution to this is Certificate Authorities, or CA for short. When you installed your operating system or browser, a list of trusted CAs probably came with it. This list can be modified at will; you can remove whom you don't trust, add others, or even make your own CA (though you will be the only one trusting this CA, so it's not much use for public website). In this CA list, the CA's public key is also stored.
When Google's server sends you its certificate, it also mentions it is signed by GeoTrust. If you trust GeoTrust, you can verify (using GeoTrust's public key) that GeoTrust really did sign the server's certificate. To sign a certificate yourself, you need the private key, which is only known to GeoTrust. This way an attacker cannot sign a certificate himself and incorrectly claim to be Google.com. When the certificate has been modified by even one bit, the sign will be incorrect and the client will reject it.So if I know the public key, the server can prove its identity?
Yes. Typically, the public key encrypts and the private key decrypts. Encrypt a message with the server's public key, send it, and if the server can repeat back the original message, it just proved that it got the private key without revealing the key.
This is why it is so important to be able to trust the public key: anyone can generate a private/public key pair, also an attacker. You don't want to end up using the public key of an attacker!
If one of the CAs that you trust is compromised, an attacker can use the stolen private key to sign a certificate for any website they like. When the attacker can send a forged certificate to your client, signed by himself with the private key from a CA that you trust, your client doesn't know that the public key is a forged one, signed with a stolen private key.But a CA can make me trust any server they want!
Yes, and that is where the trust comes in. You have to trust the CA not to make certificates as they please. When organizations like Microsoft, Apple, and Mozilla trust a CA though, the CA must have audits; another organization checks on them periodically to make sure everything is still running according to the rules.
Issuing a certificate is done if, and only if, the registrant can prove they own the domain that the certificate is issued for.What is this MAC for message authentication?
Every message is signed with a so-called Message Authentication Code, or MAC for short. If we agree on a key and hashing cipher, you can verify that my message comes from me, and I can verify that your message comes from you.
For example with the key "correct horse battery staple" and the message "example", I can compute the MAC "58393". When I send this message with the MAC to you (you already know the key), you can perform the same computation and match up the computed MAC with the MAC that I sent.
An attacker can modify the message but does not know the key. He cannot compute the correct MAC, and you will know the message is not authentic.
The server's public key does. Since we have verified that the public key really belongs to the server and no one else, we can encrypt the key using the public key. When the server receives this, he can decrypt it with the private key. When anyone else receives it, they cannot decrypt it.
This is also why key size matters: The larger the public and private key, the harder it is to crack the key that the client sends to the server.
How to crack SSL
- Try if the user ignores certificate warnings;
- The application may load data from an unencrypted channel (e.g. HTTP), which can be tampered with;
- An unprotected login page that submits to HTTPS may be modified so that it submits to HTTP;
- Unpatched applications may be vulnerable for exploits like BEAST and CRIME;
- Resort to other methods such as a physical attack;
- Exploit side channels like message length and the time taken to form the message;
- Wait for quantum attacks.
See also: A scheme with many attack vectors against SSL by Ivan Ristic (png)
There is no simple and straight-forward way; SSL is secure when done correctly. An attacker can try if the user ignores certificate warnings though, which would break the security instantly. When a user does this, the attacker doesn't need a private key from a CA to forge a certificate, he merely has to send a certificate of his own.
Another trick for HTTP is when the login page is not secured, and it submits to an https page. "Great," the developer probably thought, "now I save server load and the password is still sent encrypted!" The problem is sslstrip, a tool that modifies the insecure login page so that it submits somewhere so that the attacker can read it.
There have also been various attacks in the past few years, such as the TLS renegotiation vulnerability, sslsniff, BEAST, and very recently, CRIME. All common browsers are protected against all of these attacks though, so these vulnerabilities are no risk if you are running an up-to-date browser.
Last but not least, you can resort to other methods to obtain the info that SSL denies you to obtain. If you can already see and tamper with the user's connection, it might not be that hard to replace one of his/her .exe downloads with a keylogger, or simply to physically attack that person. Cryptography may be rather secure, but humans and human error is still a weak factor. According to this paper by Verizon, 10% of the data breaches involved physical attacks (see page 3), so it's certainly something to keep in mind.
I would be interested in a little more explanation for "a key is exchanged" for the symmetric key. How does this happen that someone with a packet sniffer can not access.
@Yehosef Good question! I forgot to explain that in my answer. Looking around, it turns out there is actually a question dedicated to this: http://security.stackexchange.com/q/6290/10863
"You have to trust the CA not to make certificates as they please." Isn't what letsencrypt is doing now? As I understand it, anyone can can create a certificate for a domain as long as its points to it server. How can this be considered reliable?
@Iwazaru All CAs do this since day one. The point of a certificate is to provide the public key for a given domain, and the point of signing it to prove it really is the right key for the domain. Let's Encrypt is doing exactly what it should be doing: verifying you own the domain, and sign your certificate (with your key) if you can prove it. Now everyone who trusts Let's Encrypt, which is practically every browser, will trust that certificate.
TLS is NOT implemented directly on top of TCP. The TL in TLS is an acronym for Transport Layer. It is not just a rebranding of SSL post SSL v3.0. ... Also the portions of HTTPS that are left unchanged are because of kernel drivers added or changed to provide the same facade through the socket as SSL abstractions previously did. ... The movement of security to a lower level in both layer abstraction and library call stack was to block certain exploits that were highly exposed only when certificate, key, and cipher exchanges were done in the layer above TCP instead of within it.
"After this the basic setup is done, the server sends its certificate." --> Does the server certificate get encrypted while being transferring to the client? Is the cert always in the payload of the 'server hello' packet?
@匿名柴棍 For TLS1.2 and below: yes. For TLS1.3, there was talk of encrypted SNI and certificates, but I don't know what the status on that is.
You've completely omitted the actual master secret from this otherwise excellent answer.
@user207421 If you feel something important is missing, feel free to submit an edit! Just weigh whether it is vital to a high-level understanding of the protocol, since all details would cover a whole book I have to leave a lot of things out.
@匿名柴棍+ (server) cert chain is a separate _message_ from serverhello _optionally_ in the same record and always in the same flight; the mapping to packets by TCP can vary, but for most certs on most connections the cert(s) will span multiple packets and may share _one_ of them with serverhello. More substantively, for 1.3 server cert message _is_ encrypted; SNI is not encrypted in standard 1.3, but an option to do so is in draft.