U -> C : { request(W), nc }_Kc C -> U : {{ W, Kw }_K-a }_nc
U -> W : { A, {U, Ku}_K-a, {request, t, {cert}_K-a', ..., nu, Ks }_K-u }_Kw W -> U : { response, nu }_Kssubsequent requests in the same session take the simpler form
U -> W: { request, t, nu' }_K-s
If C gets compromised, C can't forge certificates. It could like and say that it doesn't have any, or give out outdated ones, but these behaviors are really minor mischief.
If A were on line and were successfully attacked, then A might give out false public keys which could allow messages to W to be intercepted, read, and answered falsely.
U decrypts the message with nc and then again with Ka, to find that W's public key is Kw.
U knows this message is a "fresh" response to its request (not a replayed response from some hostile attacker) because it's encrypted with nc, and only C could have known about nc.
No one but U can read the response, because it is encrypted with nc. Thus U's request is private, and so is the response.
Finally, C can't have sent a false certificate because the certificate is still signed by A. (If public keys change regularly, it would be good to include an expiration date inside the certificate.)
{A, {U, Ku}_K-a, {request, t, {cert}_K-a', ..., nu, Ks }_K-u }_Kw
request is the request U is making to W.
To read most of the rest of the message, W needs U's public key, which has thoughtfully been included in the message: {U, Ku}_K-a means that A certifies that Ku is the public key for U. If this were not included, W would have to ask C for U's public key, which would waste W's time since U already knows what it is.
Since W might trust several authorities, the message includes A as well as {U, Ku}_K-a, so that W knows what public key to use (Ka) to decrypt the certificate and get U's public key. It would not be good enough to include just {Ku}_K-a, since we need to know *who* has public key Ku (otherwise the message might really be from V instead of U). Similarly, it would not be good enough to include just (U and) Ku, since the message might really be from V pretending to be U.
In sum, W knows A's public key Ka and decrypts {U, Ku}_K-a to find that U's public key is Ku.
t, the timestamp, helps alleviate malicious hogging of system resources. To wit: perhaps an attacker keeps a copy of U's message to W, and replays it over and over to hog W and drive U crazy. Once the current time is sufficiently past t, W can ignore any requests containing t without feeling guilty.
nu prevents problems from malicious replay of responses. In other words, suppose U's request is intercepted by V (who can't read it) and V sends back a fabricated response. To look realistic, the response will have to be signed by W, i.e., encrypted with W's private key. Thus the fabricated response will have to be an old response of W's. But by including a new random number nu in every request, which W is to include in the response, U can tell whether a response is a bona fide response or a replay of an old response (saying, e.g., that the requested document does not exist).
Ks is called a "session key." U wants W to encrypt the response with Ks. Only U knows K-s so only U will be able to read the response. (One could achieve the same effect by encrypting the response with Ku, but there are other advantages to using Ks.) U created both Ks and K-s just for the current interaction with W (or perhaps for a bit longer if U is feeling reckless).
{cert}_K-a', ... are other certificates that W requires before it will grant a request, authenticating things other than U's public key, generated by servers A' that W trusts and that (I hope) are not available on the net for attack. For example, W might insist on a certificate showing that U is an undergrad, in order to receive a certain service.
W -> U : { response, nu }_Ks
U decrypts the message with K-s, which only it knows, giving privacy for the response. U verifies that nu is included, so that the response is not a replay. Since only W and U know Ks, the response must really have come from W.
We do not need Ks when only two messages (one exchange of messages) take place. In that case use the following:
W -> U: {{ response, nu}_K-w}_Ku
U -> W: {request, t, nu'}_K-s
W knows that the message must come from U, since only U knows K-s. W decrypts the message with Ks.
We assume that W knows *which* Ks goes with the message because W remembers which Ks is associated with the socket on which the message was received. Thus any message coming in on that socket gets decrypted with Ks. If the decryption is unsuccessful then the message was garbled in transit or is from an impostor.
The timestamp t is included to help with malicious replay of requests. A new nonce nu' is included so that U will know that the response is "fresh."
The advantage of using Ks is that the heavy overhead of creating and processing the first message from U to W is avoided in future exchanges. The drawback of using Ks is that if K-s is compromised during the session, the attacker can talk to W using K-s. To help with this, W can use a timeout (explicit or implicit) with Ks, so that U must present its credentials again after a while.
W's second and subsequent responses in a session all look
just like its first response:
W -> U: {response, n_u'}_Ks