Re: WebRTC Certificate Management - a plea to NOT use Web Crypto

On Dec 23, 2014 6:21 AM, "Richard Barnes" <rlb@ipv.sx> wrote:
>
> As the originator of the idea that Ryan's pleading against, I feel like I
should provide some response here.  In the spirit of long messages for the
holidays, ...
>
> First, Ryan, thanks for taking the time to lay out the overall context.
Your characterization of the high-level requirements and the arguments for
reusing CryptoKey are pretty much accurate.  Though I reserve the right to
disagree with them on some points :)
>
> If I were to summarize your proposal for WebRTC in a sentence, it would
be, "Create a custom key pair object that is specific to WebRTC".  If you
look at this just in the context of WebRTC, that doesn't sound all that
bad.  However,
> I'm concerned about the bigger direction for APIs.
>
> I want to live in a world where cryptographic security is easy and
ubiquitous.  WebRTC and WebPush are both good examples of new APIs that
build security in from the start, and indeed make it a core component.  I
want it to be easy for future APIs to do that too.

At the risk of saying that "I, too, like freedom and apple pie", I am very
much looking at the big picture and thinking of developers. Bluntly, your
proposal:
- Undoes three years of hard work to design some semblance of security
guarantees regarding what is usable and exposed.
- Introduces unnecessary ontological confusion by attempting to overlay a
high-level semantic onto the notion of keys that the WG *repeatedly* has
rejected
- attempts to redefine the charter and scope of a WG and its key deliverable

>
> Forcing each API to make a new "LimitedUseKey" construct is inimical to
that objective.  Different APIs have different event structures, but we
don't make developers learn a new event system for each API -- we map the
API to DOM Events or Promises.  So whatever we end up with, it should be
re-usable across at least WebRTC and WebPush, and hopefully future things
as well.  In other words, the choices here are one key object or two --
CryptoKey or CryptoKey+ApplicationUsableKey -- not O(#apis) different
versions.

No. This is a deeply flawed argument. We have ArrayBuffer, File, Blob and
Stream. We do not try to shape these things to fit some broken and
ill-fitting concept because of ideological purity, we recognize they serve
different purposes and express - both to developers and at an
implementation level - that there are differences. Even when there are
similarities - e.g. Files and Blobs exposed as Streams - we still keep
separate types with well-defined hierarchies.

Your parallel to Keys as Promises or Events is deeply flawed and again
hearkens back to an approach that was repeatedly rejected as out of scope
by the Web Crypto WG; that is, the notion that keys should be some high
level API.

No, they aren't.

Now, we could certainly recharter Web Crypto WG, redefine the deliverables,
and introduce a base "opaque key" type for which both Web Crypto and WebRTC
can build upon, but that would be deeply silly. That is because it is
entirely irrelevant to the developer that both Web Crypto and WebRTC are
built upon an opaque type, and to an implementation, all you're doing is
copying one line of hand-wave between the two: "Key represents an opaque
platform type that is implementation specific".

>
> The main question, then, is how big the difference is between CryptoKey
and ApplicationUsableKey.  The base requirements we're seeing are for
public and private key objects with the following properties

No, there is zero need for WebRTC to treat these concepts as separable.
That is, WebRTC *always* deals in Identities - a public and private key
pair that *together* define a representation to the user. You could express
this with a singular object, because for WebRTC, it is a singular idea.

> (to refine your requirements list a bit, with a separate numbering space):
>
> [Requirement A=1,2] Private keys are protected from application access
(browser-locked)
> [Requirement B=3] Private keys can be scoped to specific uses
> [Requirement C=4] Private keys can be persisted
> [Requirement D=5] Public keys can be serialized to different formats
>
> CryptoKey provides these properties.

No, it does not.

I am sorry that I have to take this apart point by point, but:
- Your notion of browser-locked (A/1,2) is unique to your case. You have
explicitly stated in the past that you wish to deny the import of keys and
distinguish them from those generated in the browser. This is contrary to
the CryptoKey, which explicitly does not track this.
- B/3 is an artificial requirement that you have introduced precisely
BECAUSE you're trying to overload the concept. That is, specifying your own
object makes it intrinsically unnecessary to have this requirement, because
it is there by definition.
- C/4 is as simple as structured clone.
- D/5 is simply incorrect. That is, there is no reason to express this as a
fundamental requirement - it is pure syntactic sugar that can be layered
upon choosing a canonical key form for the API. Put differently, you can
express a JWK-via-API as an SPKI purely through script; expressing it via
API is thus sugar. Per the Extensible Web Manifesto [1] that so many of
your colleagues are signatories to, this is unnecessary. [2]

> Any ApplicationUsableKey construct would have to duplicate at least that
much of CryptoKey.  This gets us down to the question of what harm there
would be in re-using CryptoKey.
>
> It seems like there are a couple of things that are making you sad about
the idea of re-using CryptoKeys for applications outside of WebCrypto.
>
> [Objection 1] If other apps use CryptoKeys, they won't be usable with
WebCrypto methods.
> [Objection 2] WebCrypto's algorithms align poorly with TLS
>
> Both of these arguments seem to miss the fact that WebCrypto itself is an
application of CryptoKeys.  It's the first, and one that was co-designed
with CryptoKeys, but it need not be the only.  In fact, it's a *set* of
applications -- sign, verify, encrypt, and decrypt.  Each of these has
separate processing for keys.  In light of that, Objection 1 looks kind of
funny: We *already* have WebCrypto keys that are usable for one application
and not another, e.g., sign() and not decrypt().  It's baked into the
design.

Oh, come on. You're arguing apples and oranges are the same thing because
they're both fruit.

You're rewriting history - and a long set of debate - to suggest that the
WebCrypto WG was at all chartered or intended to make CryptoKey some
generic object like Blobs or Streams. You know full well this was a
non-goal that was rejected. Again, CryptoKey is designed and expresses a
set of concepts deeply linked to window.crypto.subtle, and is NOT some
generic high level representation.

>
> Objection 2 misses another important underlying fact: While CryptoKey
expresses constraints, it's up to the application to enforce that
constraint in a manner appropriate to that application.  Each of the
WebCrypto algorithm descriptions describes different processing for the
"algorithm" dictionary on the key.  A TLS usage could do likewise, e.g.,
ignoring the "hash" parameter on an RSASSA-PKCS1-v1_5 algorithm if present.

This here is a deeply disturbing line of thinking. If I can rephrase
Objection 2, it would be that "WebRTC proposes to ignore the security
protections of CryptoKeys". Now you can see why it smells so bad and
engenders such a strong negative reaction from me.

You cannot argue that ignoring the restrictions upon which the entire
security analysis of the API rests makes any sense at all. It is truly
trying to make a square hole fit a round peg, just because the API concepts
share a noun.

>
> It may be that the requirements from other applications lead to some
changes to the CryptoKey structure, e.g., to make the "hash" parameter not
required by the syntax (it can still be enforced by sign()).  I'm OK with
that.  It's not monkey-patching, it's discovering weaknesses in CryptoKey
that prevent it from being reusable.  And it's a natural, healthy process
for APIs to go through.
>

No, no, no. This is just wrong and dangerous. It is not a "weakness" that
your use was intentionally not supported - it is intentional! That is the
point - you're reopening a debate that was settled some time ago, and doing
it through another WG, and for no real benefit to developers.

Luckily, we have the TAG to provide guidance on these sorts of design
decisions, but I cannot stress enough that you are taking an ill-fitting
API and trying to apply it to a problem in a way that is hostile to both
developers AND implementors. We need not do that.

If your proposal was adopted, let's look at the very real sharp edges and
developer missteps introduced:

- If I want to use a CryptoKey object with WebRTC, I must create it with
some WebRTC-specific API. The canonical wag to create CryptoKey's leaves me
with a key I cannot use.
- If we choose to instead rewrite the WebCrypto spec to fit your vision
(which you know it would require breaking API changes to do), then even
though generateKey yields a key I can use, I cannot use importKey
- How I specify an algorithm now depends on context. If I want to use it
for signing, I have to specify a hash, but if I want to use it for WebRTC,
I don't, even though both follow the same structure and pattern.
- Any key I export contains redundant information (e.g. usages, of which
there is only ever one, 'webrtc') or unnecessary restrictions ('alg')

None of these are positive outcomes at all for developers. Do the right
thing. Use the right type. Not every Blob has to be a File, not every
ArrayBuffer is aspiring to semantically be a Stream, and not every
RTCIdentity is trying to be a CryptoKey.

Consider the use of DTLS methods that might use SRP or other
non-certificate forms of authentication - they now become inexpressible.
You're fundamentally looking for an API to express the identity you present
your peer, with a secondary goal of being able to provision some of those.
Whether this relies on bare keys, certificates, or zero-knowledge proofs
should be entirely opaque to your API.

Not only is your proposal bad for the security of Web Crypto, bad for
developers who use either, but it artificially limits you to expressing the
concepts with an imprecise and incomplete vocabulary.

> Happy holidays,
> --Richard
>

[1] https://extensiblewebmanifesto.org
[2] I am avoiding a discussion of why Web Crypto does so within the body,
only to note that it is very much an unpolyfillable security feature
derived from a particular threat model for wrap/unwrap that is not relevant
for Web RTC.

Received on Tuesday, 23 December 2014 18:49:34 UTC