
Public Key Pinning Extension for HTTP - hepha1979
https://tools.ietf.org/html/draft-ietf-websec-key-pinning-20
======
tptacek
Note that beyond just thwarting many attempts at hijacking CAs on an
individual connection level, HPKP and/or TACK form the basis of a surveillance
system that drastically changes the risk/reward for using compromised CA
certificates to conduct mass surveillance. Mass MITM apparatuses will have to
assume that some of their victims speak HPKP/TACK and will detect forged
certificates; when that happens, there's a decent chance the incident burns
the whole CA.

It's not a perfect fix to the CA problem, but it is a huge step in the right
direction (which is towards decentralization and peer trust).

~~~
steakejjs
It's a shame more people haven't really spent time on Tack. I spent a weekend
playing with it and it was really great.

Trevor stopped paying for the TACK test server so Im guessing the push has
died. Trust agility and certificate transparency really need to come
about...yesterday.

~~~
moxie
At this point Google pretty much controls the future of web-oriented internet
protocols, since they control the client in the form of Chrome, as well as the
server in the form of Google properties. What they do is basically what goes.

People inside of Google were putting together HPKP at the same time that we
were putting together TACK, so that was pretty much the end of TACK. HPKP is
really simple for Google (just pin their own CA), but isn't as clean for most
other major sites (who are stuck with many CAs). It also doesn't offer a layer
of indirection away from CAs, which again, is not an issue for Google (they
already have a layer of indirection in the form of their own CA), but is less
ideal for the rest of us.

It's better than only being able to hardcode pins in the browser binary, but
it's a shame that it doesn't take on some of the other pain that's come up
with pinning.

~~~
rakoo
AFAIU the difference between TACK and HPKP is:

\- For TACK, the pinned key is a custom key created just for that, and is
transmitted in TLS

\- For HPKP, the pinned key is a CA cert key (one of the CA on the chain), and
is transmitted in HTTP

I think pinning the CA cert key makes more sense, because this is what they
were created for: certs certify, the matter is in how you transport them. OTOH
putting all the pinning information directly in the certificate makes more
sense to me. We should have every domain owner running its own CA, with a cert
that has all required pinning data, signing all TLS keys of the servers, and
then sending the minimal chain "server cert" <\- "CA cert", and then browsers
would pin that cert.

------
phlo
The link points to version 20 (August 2014) of the draft, a more current
version 21 (October 2014) is available at [1], linked in the article.

Chrome has been doing public key pinning out of the box for about three years
now, though the feature has only been active for some Google properties and a
couple of hand-picked high-profile sites [2]. Firefox has recently added
support for static pins, plans to support the HTTP extensions exist [3].

Alternative or complementary proposals include DANE/TLSA [4] (DNS-based
Authentication of Named Entities; stores certificate infos for any protocols
in a new DNS record; requires DNSSEC) and TACK [5] (Trust Assertions for
Certificate Keys; a similar mechanism to the one proposed in this draft but
implemented as a TLS extension; possibly discontinued).

[1] [https://tools.ietf.org/html/draft-ietf-websec-key-
pinning-21](https://tools.ietf.org/html/draft-ietf-websec-key-pinning-21)

[2]
[https://www.imperialviolet.org/2011/05/04/pinning.html](https://www.imperialviolet.org/2011/05/04/pinning.html)

[3]
[https://wiki.mozilla.org/SecurityEngineering/Public_Key_Pinn...](https://wiki.mozilla.org/SecurityEngineering/Public_Key_Pinning)

[4] [https://en.wikipedia.org/wiki/DNS-
based_Authentication_of_Na...](https://en.wikipedia.org/wiki/DNS-
based_Authentication_of_Named_Entities)

[5] [http://tack.io](http://tack.io)

~~~
pierre_massat
I believe your first link is still version 20. Here is version 21:
[https://tools.ietf.org/html/draft-ietf-websec-key-
pinning-21](https://tools.ietf.org/html/draft-ietf-websec-key-pinning-21) .

Also, your second link point to a 404.

There is a 'g' missing in the link to Mozilla Wiki:
[https://wiki.mozilla.org/SecurityEngineering/Public_Key_Pinn...](https://wiki.mozilla.org/SecurityEngineering/Public_Key_Pinning)
.

And [https://tack.io](https://tack.io) doesn't respond for me whereas
[http://tack.io](http://tack.io) does.

~~~
phlo
Somehow I managed to break every single link. Fixed them now. Thanks for the
heads-up!

------
higherpurpose
I wish I could pin certificates myself. I'd like the browser or an extension
to allow me to either automatically pin all certificates on "first use", or do
it manually.

~~~
exo762
Plugin for firefox.

[https://addons.mozilla.org/en-
US/firefox/addon/certificate-p...](https://addons.mozilla.org/en-
US/firefox/addon/certificate-patrol/)

~~~
heavenlyhash
I also use Certificate Patrol and highly recommend it.

It does exactly the most useful thing possible within the current state of the
internet: it remembers the certs you've seen before (gasp!) and tells you if
they've changed. Simple.

------
infogulch
How are pinned Public Keys updated when the host changes keys?

Say a user visits a website for the first time and the site's key is pinned in
their browser. Then the user doesn't visit for a long time and the pinned key
expires. Later, the user visits again but now the pinned key is no longer
being used. What _should_ happen? According to the document:

> The UA MUST ignore any expired Known Pinned Hosts in its cache.

This is unfortunate, since the point of pinning keys is to minimize the risk
of hijacked CAs down to the very first connection. With this system that risk
occurs every time the key expires, and with several pushes to shorten the
expiry times of public keys this could be quite often.

In the example above, could the expired key be used to sign the new one? It
wouldn't be used to secure the connection, but only to update the pinned key,
where the chain of trust is unbroken from that very first visit.

------
agwa
Note there is a newer version of the draft:
[https://tools.ietf.org/html/draft-ietf-websec-key-
pinning-21](https://tools.ietf.org/html/draft-ietf-websec-key-pinning-21)

------
mhandley
From the introduction of the I-D:

    
    
       Key pinning is a trust-on-first-use (TOFU) mechanism. The first time
       a UA connects to a host, it lacks the information necessary to
       perform Pin Validation; UAs can only apply their normal cryptographic
       identity validation.  (In this document, it is assumed that UAs apply
       X.509 certificate chain validation in accord with [RFC5280].)
    
       The UA will not be able to detect and thwart a MITM attacking the
       UA's first connection to the host.  (However, the requirement that
       the MITM provide an X.509 certificate chain that can pass the UA's
       validation requirements, without error, mitigates this risk
       somewhat.)  Worse, such a MITM can inject its own PKP header into the
       HTTP stream, and pin the UA to its own keys.  To avoid post facto
       detection, the attacker would have to be in a position to intercept
       all future requests to the host from that UA.
    
       Thus, key pinning as described in this document is not a perfect
       defense against MITM attackers capable of passing certificate chain
       validation procedures -- nothing short of pre-shared keys can be.
    

I think for most of us, this is still a big improvement. But for people under
repressive regimes, isn't there a high chance that you get the MITM great-
firewall-of-wherever the first time, and then you're stuck with it from then
onwards even if you can tunnel out at some later time (this is assuming the
government has control over at least one CA)?

~~~
xorcist
> nothing short of pre-shared keys can be.

Any out of band key exchange is.

------
xorcist
There's also the easy way which avoids the problem almost altogether: let the
only entity with the legal power to tell who holds which domain also do so
cryptographically.

The infrastructure is already in place. Do a good deed and publish your
records today, if you haven't already.

------
peterwwillis
tl;dr HSTS thwarts sslstrip, HPKP thwarts CAs hijacking, but neither is
actually foolproof. read below for my solution.

The sslstrip problem seems impossible to make secure using the existing web.
The inherent problem is that the web allows both insecure and secure
connections; if https doesn't work, people [or browsers] will just try http,
and there is no way to determine if a site is supposed to use https or not.
(It would be nice if we required a 'ssl.' subdomain be used for https-only
connections, but nobody seems to like that suggestion, and there's some
scaling issues)

I think the most permanent, flexible solution for all these problems is
twofold: one, a protocol which makes secure connections mandatory, and two,
mandatory multiple identity verification.

Unlike SPDY, which allows non-SSL connections and used to allow compressed
headers to be encrypted, another protocol (or layer?) should be introduced
that makes it impossible to have a connection which isn't encrypted and signed
by a CA (no self-signed certs allowed). This would ensure that no
communication with a host over this protocol would be of questionable
integrity. Users could decide for themselves that if this connection doesn't
work, they simply won't try to contact the host via lesser means (like https).

Going further, it seems to me there's two logical ways to prevent a hijacked
CA from feeding you spoofed certs on the initial connection: Convergence,
and/or multiple CA verification.

Convergence stops the initial-connection attack by requiring multiple
independent parties agree on the data you're getting. The hijacker would have
to also hijack all the Convergence peers for this to succeed, which is
effectively very difficult. But this requires a highly available public
network of peers to work, which is problematic in many cases.

Instead, one could provide a certificate chain on the initial connection to
the destination host with the same certificate signed by multiple independent
CAs. IMO this is a better solution than Convergence because it doesn't require
the consensus of a live public network or multiple hosts, but does still
provide a guarantee of authenticity verified by multiple independent parties,
which would again be very difficult to hijack all at once.

To provide this second method you'd need to do several things: One, send the
same CSR to multiple CAs and collect the certs (this already works). Two,
require a protocol identifier that mandates only secured connections
(something other than http/https, so users don't get confused). Three, mandate
no self-signed certs. Four, require a certain minimum 'assurance index' be
reached by using a set of heuristics to classify the certs received and
determine if they're from enough CAs (or CAs different enough from each other,
like one from the UK, one from Iran and one from Brazil). Five, make sure all
the certs match and are all signed by the same origin host key.

Then all you'd have to do as a user is type in 'rfsp://mybank.com' and your
connection would either succeed securely the first time, or irreversibly fail.
The server admin would just tack on a bunch of different certs from different
CAs into the chain and provide the new encryption layer, under which HTTP (or
whatever) would pass.

~~~
notatoad
>The sslstrip problem seems impossible to make secure

I just do a 301 redirect to HTTPS on any requests that hit port 80. What makes
that insecure?

~~~
xorcist
It's not secure against traffic hijacking, where a malicious server would
serve plaintext to the client and the average user would be none the wiser (no
broken padlock).

~~~
notatoad
oh, of course. that makes sense. thanks.

