On the simplest level, two people, say Alice and Bob, would like to communicate securely. So, the natural choice is to use cryptography. Alice and Bob could decide on a secret key and then use that to communicate. Naturally, this presupposes that Alice and Bob have, at one point, had a secure communications channel over which to exchange a key. However, this is generally not the case with communications over the Internet.
Very often, communications occur between parties that do not know each other. This is especially true with the Web. A user would like to be able to log on to a website securely without having to first contact the webmaster and request a secret key.
At this point, the idea of public key cryptography [PKY] becomes important. It enables two parties to communicate without ever having a secure channel over which to communicate. In this case, Alice and Bob each have a public and private key pair. When they wish to communicate, they simply exchange public keys. So, when Alice wishes to send Bob a message, she encrypts her message using Bob's public key.
Alice -> Bob {message} Bob's public key
To decrypt the message, Bob simply decrypts the ciphertext using his
private key.
At this point, however, the questions arises: how does Alice really know that the person with whom she is communicating is Bob? To solve this problem, the two parties could use a signature scheme. When Alice wants to make sure that she is talking to Bob, she could send Bob a message and ask him to sign it. Bob signs the message by decrypting it with his private key.
Alice -> Bob message
Bob -> Alice {message} Bob's private key
Alice could then encrypt the message using public Bob's key. If the
result she obtains is the same as the message that she sent Bob, then
she can be relatively sure that she is talking to Bob.
This method of signing works because of the symmetric property of a
private/public key pair; that is,
{{message} private key} public key
= {{message} public key} private key
= message
Seeing as Bob would be, at least in theory, the only person with his
private key, it is fairly certain that Alice is, indeed, talking to
Bob.
The next problem arises here. Based on the above protocol, Bob could be signing anything that Alice wants; Bob could be signing something that he would normally never sign. However, because only he could be in possession of the key, the signed message would be considered as authentic. So, to avoid this, the protocol is changed slightly so that Bob no longer signs a message. Instead, he signs a digest of the message. A digest is simply a value computed by a hash function. The value computed by the hash function depends solely on the message text and has the following properties:
Although the above protocol does represent an improvement, Bob is still not entirely secure. Alice is still generating the message and Bob has no way of knowing what Alice will do with it. So, to remove this dependency on Alice, one lets Bob decide what message to hash and sign.
Bob -> Alice message
Bob -> Alice {digest[message]} Bob's private key
As before, Alice can compare the digest of the first message to the
decrypted second message. Furthermore, Bob can rest assured that what
he is signing is not dangerous. However, the situation has not
improved for Alice. For instance, how does Alice know for certain
that she is, indeed, talking to Bob? That is something that has not
been addressed so far. It is at this point that one needs a trusted
third party to verify Bob's identity. To accomplish this requirement,
SSL makes uses of X509 certificates (see below). The protocol now
becomes:
Bob -> Alice Bob's certificate
Bob -> Alice message
Bob -> Alice {digest[message]} Bob's private key
From this set of information, Alice can verify that Bob's public key
is authentic, by using the certificate and the certifying authority's
public key, which is commonly known. Furthermore, as before, she can
ensure that Bob is truly Bob by comparing the two messages. It is at
this point that a secure communications channel has been established
between Alice and Bob, albeit not in the other direction. The next
step is to switch to a symmetric cryptosystem, so that the secure
channel becomes bidirectional. This can be achieved by appending the
following step to the above protocol.
Alice -> Bob {some secret} Bob's public key
Using this secret, Bob and Alice can both generate the same private
key that will be used for the rest of the session. Now, a
bidirectional secure communications channel has been established. In
actuality, SSL generates two keys: a master-read-key and a master-
write-key. The usage of the two keys makes it even more difficult to
compromise the security of the channel. Specifically, the application
suite uses DES in CBC mode [SNR] for all further communications.
Although all communications between Alice and Bob are secure now, the
above protocol does not prevent an attacker from inserting his own
data and getting one of the two parties to try to act on it. To
protect against this problem, one introduces a Message Authentication
Code (MAC). This is a number that is computed based on the data that
is to be transmitted and some secret that Alice and Bob share. The
MAC is encrypted along with the message and sent to the other party.
Alice -> Bob {message, MAC} secret key
Say Bob receives a message from Alice. He can generate the MAC for
the message and compare it to the MAC that was included with the
message. If the two MACs do not match, the message is simply
discarded. SSL uses MD5 [SNR], a hashing algorithm, to generate the
MAC. The MACs generated will be of 128 bits length. Thus, the
probability of an attacker finding a message that has the same MAC as
the message that was sent is extremely unlikely: 1 in 264.