The power in a certificate is NOT in the certificate. It is in the private key. When a server "uses a certificate", it really uses the private key; and the server shows the certificate (that contains only the public key) to the client. The certificate is a proof that a given public key belongs to a specifically named entity. For instance, the certificate that is used by the SSL server www.google.com
contains that name (www.google.com
) and Google's public key. Google won't show you their private key, of course !
A certificate is not accepted as proof merely because it exists; a client is supposed to perform certificate validation, a complex and convoluted process which entails building certificate chains and verifying a lot of signatures, because a certificate is signed by an authority that is endowed with the power to sign certificate, and is therefore named a certification authority (or CA for short).
Certificates are described in X.509, which is best described as "the Devil's Masterpiece Of Confusion". To practically cope with the sheer complexity of X.509, implementations, in particular Web browsers and other SSL client applications, tend to "take shortcuts" which allow the whole validation thing to complete within reasonable time, but also have a deleterious effect on overall security.
Certificate pinning is a method by which some implementations try to restore a bit of security while still being practical. All of X.509 is context-free: a client is supposed to be able to validate a server certificate without any memory or state kept from previous validations. Certificate pinning is the negation of that notion: the client "pins" a certificate by remembering that a given certificate was used by some server, and then using that information to efficiently "validate" that certificate, should the client connect again to the same server. Pinning even goes to reject a server certificate if it is not the same as the one used by the server during a previous connection to that same server.
The idea is that if an attacker tries to show you a fake server, he won't be able to show the certificate of the genuine server -- of course, the attacker could show a copy of the true certificate (that's public data, the server sends it to all connecting clients), but the attacker would not be able to use the corresponding private key, since he does not have it (the private key, as the name says, is private). Instead, in order to be able to pose as a fake server that can do a complete SSL handshake, the attacker must feed the client a fake certificate that contains the attacker's public key, distinct from that of the server. With certificate pinning, the suspicious client will notice that the server apparently switched certificates, and will find that fishy, and will complain to the user, who will then click off the friggin' warning popup and proceed to sending his credit card number to the attacker because users are like that.
It shall be noted that certificate pinning does any good only in cases where the attacker could obtain a certificate that is accepted by what passes for certificate validation code in client applications. There have been a few highly publicized cases of a CA being bribed or hacked into issuing fake certificates; however, this is still rare. Also, certificate pinning cannot be really absolute because certificates have validity dates, for a bunch of reasons (some of them being even rationally acceptable), so there must be some situations where a client with certificate pinning will still accept that the server changed its certificate.
An example of protocol, similar to SSL, and using public/private key pairs (not X.509 certificates, though) in a "full pinning" model, is SSH. When you connect to a SSH server for the first time, the client asks confirmation about whether the public key sent by the server is the right one (the human user is supposed to check the hash of that key with some authoritative source); then, the client remembers that key (in the .ssh/known_hosts
file for Unix-based SSH clients) and will scream loudly if the server ever happens to change its key.