Your particulars are wrong (it is not a problem of encryption per se) but you have the right general idea.
In SSL/TLS, the client first connect to the server and sends a "ClientHello" message stating "I wish to do some SSL with you". This happens just above the TCP layer, and below anything which is related to HTTP; an HTTP request will be sent within the SSL tunnel only after the SSL tunnel has been created. SSL tunnel creation is done through the procedure called "the handshake", of which the ClientHello message is the first step.
During the handshake, the server sends his certificate to the client. The certificate contains the server name and his public key, and it is signed by a certification authority. The client will accept to use the public key only after having "validated" the certificate, a process which entails the two following steps:
- The client must verify the signature by the certification authority over the certificate. It may have to validate the certification authority's own certificate before that, though; the process is recursive. Certificate validation is full of intricate details which I will skip here because they are not relevant to this discussion.
- The client must check that the intended server name indeed appears in the certificate. Because that's the point of the certificate: to bind a public key (a mathematical object with which cryptography is done) to an identity (the server name); the certification authority issues the certificate (i.e. signs it) only after verified in some way that the public key is indeed the one for which the server controls the corresponding private key.
Once the client is reasonably sure that he has the correct public key, he can finish the handshake: depending on the negotiated cipher suite, this entails asymmetric encryption or digital signatures; either way, the server will use his private key. At the end of the handshake, both client and server end up with a shared session key with which more cryptography is going to happen, this time symmetric encryption.
Then, and only then, can "application data" be transfered through the tunnel. In the case of HTTPS, "application data" contains the actual HTTP request.
Now, the problem is the following: the client wants to contact a given server (with a name such as www.foo.com
), but that intended server name is sent to the server only with the HTTP request. At the TCP level, only IP addresses exist. When the server needs to send his certificate, he only knows that it was contacted under some IP address, but it does not know under what name the client tries to locate it. Nevertheless, the server must send a certificate which contains the right name. When the server only hosts a single HTTPS server per public IP, that's easy: only one possible name. With several HTTPS servers sharing the same public IP, the server has to do some divination, which, on a general basis, is not possible for computers (it is already quite hard for augurs).
Possible solutions:
Embed several names in a certificate. The server has only one certificate, but it contains the names of all the HTTPS servers which share the public IP. This is supported in X.509 as the Subject Alt Names extension. This requires client browsers to actually support standards the way they should, so this is not a given. This page claims that most browsers support it, but I think this warrants at least some extensive testing (especially when there are several names in the extension and these names contain the "wildchar" *
).
Enhance the protocol with an extra exchange at the beginning. This is known as the STARTTLS option. In an HTTP context, this means that the client would first sent a special HTTP request which contains the server name, with a special command (namely "STARTTLS" instead of a normal "GET") to indicate the willingness of the client to engage into an SSL/TLS handshake right away on the same connection. This has been proposed at some point for HTTP, but rejected because it does not work well with existing HTTP proxies. STARTTLS is used in other protocols such as SSMTP or IMAPS, where an actual connection is always available.
Have the client send the intended server name early enough in the handshake, e.g. by smuggling it somewhere in the ClientHello message. This is known as Server Name Indication. This is what the HTTPS world is aiming at.
The biggest issue with SNI is that it is not supported by IE on Windows XP (it requires IE 8+, but also a Vista or newer version; because the actual SSL code used by IE comes from the OS, not from IE itself). So you have to somehow induce your clients with WinXP to switch to Firefox, Chrome, or some other browser which knows about the SNI and does the SSL itself instead of relying on the implementation provided by the OS.