Re: On Crypto API Safety in the Hands of Unskilled Developers

Richard,

You asked for opinions, so here are some more non-crypto-expert ones
(though I believe I know enough about crypto to know that what I don't know
could make me dangerous ;-)

I agree with Ryan that a serialization of CryptoOperation isn't appropriate
for this API. But I do think that the algorithm, key and result attributes
of CryptoOperation should (on completion) contain the information needed to
perform the reverse operation (and per my other mail, algorithm here should
be replaced with operation parameters, as the algorithm and algorithm
parameters are in the Key).

As for browser-provided defaults for algorithms, I'm not sure that would
achieve the objectives you outlined. If a developer is led to believe that
the browser will pick sensible defaults, they will immediately face the
problem that different browsers will pick different defaults. Now, their
system will still work, since they will communicate the parameters used (as
they appear in the CryptoOperation) with the data, but the receiver of that
information will be faced with uncontrolled diversity in the incoming
messages which introduces operational and testing complexity that the
developer probably didn't think they were signing up for when they decided
to use browser defaults. It will happen that a browser default will change
to something not supported by the other side.

I wouldn't be opposed to specification-defined defaults - set for all time
- but this does little more than save some typing.

Browser-provided default behaviour for operation parameters like IVs might
be useful. If there is a unique "sensible" way to set the parameter (a
random value in the case of an IV), then it makes sense for the browser to
fill it in. But perhaps IVs are the only example here ?

...Mark

On Fri, Mar 29, 2013 at 3:32 AM, Aymeric Vitte <vitteaymeric@gmail.com>wrote:

> Opinion of a non crypto expert but crypto user :
>
> I am not sure that the comparison with xhr and CSP is relevant, xhr was
> invented before being speced and I have some doubts about CSP making it one
> day or solving things, the web should better eradicate some stuff like
> iframes, but of course it's impossible now.
>
> From my standpoint WebCrypto API is well designed and I don't see it very
> complicate, I don't find serious papers saying that it's too complicate
> because js devs are too stupid.
>
> Now if someone wants to implement a crypto project, only a crazy person
> would design it by himself, you are supposed to follow things that have
> been speced by crypto experts.
>
> But you can not avoid crazy people, as Ryan mentionned outside of crypto
> you can do terrible unsecured things, and that's in fact the reality of the
> web, so I don't understand why it's a so big concern, if people are using
> the API wrongly as the vast majority of webmasters are using the DOM
> wrongly, that's their problem.
>
> The target of the API should be I think to provide flexibility to
> implement whatever needed without accumulating things, for example I had a
> hard time using openssl, too many things, too many options or redundant
> stuff, perfectly ununderstandable when you must decide what to use.
>
> Regarding the High level API, still a bit skeptical but why not, as far as
> it is usable in reality (ie not too high level or too low level...)
>
> Now maybe I am missing some subtilities like your encrypt horror example
> but I presume that someone that is coding this is supposed to know it or to
> do a minimum of research to implement it correctly.
>
> Regards,
>
>
>
> Le 29/03/2013 03:45, Richard Barnes a écrit :
>
>  Inline.
>>
>>
>>  The utility of XMLHttpRequest for XSS / CSRF is actually a nice example
>>>> of this sort of scalability.  XHR is subject to the same-origin policy,
>>>> because that's a safe default.  But you can use CORS to implement more
>>>> advanced use cases.  General HTML document assembly is the opposite
>>>> example, where the starting point was too open, and now we need CSP to lock
>>>> it back down.
>>>>
>>>> What I'm arguing is that we should follow the XHR example instead of
>>>> the HTML example.  Make the easy case safe, but allow for the complex
>>>> stuff.  Don't force developers to risky stuff they don't want to do, just
>>>> to make something basic.
>>>>
>>> FWIW, you're comparing a document language to an API. Can we just
>>> agree the comparison is "Apples to Motor Oil" and not at all a fair or
>>> reasonable compare/contrast?
>>>
>> Ok, if you want to be more precise, I meant DOM API.  Whether we're
>> talking about the initial load of an HTML document or subsequent JS
>> manipulation of the DOM, there's a channel for making a UA send HTTP
>> requests to arbitrary URIs.  And that's the XSS / CSRF problem that CSP is
>> having to solve.
>>
>> So the point stands: XHR API starts safe, takes effort to use unsafe
>> (CORS).  DOM API starts unsafe, requires effort to make safe (CSP).   We
>> should consider carefully which of these courses we want to emulate.
>>
>> It might also be worth noting that the CSP spec is more than twice the
>> CORS spec.  6000 words vs. 2500.  It's easier to describe how to do things
>> right than to say how not to do things wrong.
>>
>>
>>
>>  I'm also not suggesting huge changes here:
>>>> -- Allow for the algorithm parameter (or parts of it, like IVs) to be
>>>> optional in encrypt/sign
>>>>
>>> I've already explained to you several times why this doesn't work.
>>>
>>> Compare the simple case, that you've given below. In order for any
>>> peer to be able to decrypt this, the peer MUST know the IV that it was
>>> originally encrypted under.
>>>
>>> So either *every* caller is forced to supply the IV (thus ignoring
>>> your syntactic sugar - and only increasing the API complexity) OR
>>> you're forced to return the "autogenerated" IV back as part of some
>>> output (eg: as part of result)
>>>
>>> This then introduces a host of new problems that you've not yet
>>> addressed, but hopefully will demonstrate exactly why this is
>>> misguided:
>>>
>>> - If the API caller originally supplied the IV, is it necessary to
>>> return the IV to the caller?
>>> - In a multi-part operation, is it necessary to return the IV on every
>>> call, or should it only be returned on the first block? What if the
>>> implementation doesn't support multi-part operations? What if the
>>> caller is only interested in the oncomplete result - must the IV be
>>> preserved until then?
>>>
>>> How is this different from what you've passionately advocated against
>>> in JOSE - that is, having multiple, seemingly arbitrary, code paths
>>> that yield different results contingent upon their inputs?
>>>
>>
>> I'm unclear on what you think is new here.  The CryptoOperation interface
>> already returns an AlgorithmIdentifier that contains all the parameters.
>>  So whenever a callback is called, the parameters are there, including the
>> IV (supplied or generated).
>>
>> So the totality of the new code over the current API is one 'if'
>> statement:
>>
>> if (/* parameters are not provided */) {
>>      /* generate parameters */
>> }
>>
>> Maybe a second 'if' statement if you want to allow the browser to check
>> when it supports generating parameters for an algorithm.  This is not a
>> dramatic amount of complexity.
>>
>>
>>
>>  -- Add a toString() method (or something similar) to CryptoOperation
>>>>
>>> That's so anti-idiomatic to the way the web platform works. Why not
>>> call it .toJOSE(), since effectively it becomes a format for saying
>>> "This encryption algorithm, under these parameters"? I know you've
>>> advocated for JOSE's use of SPI, which is effectively that this is,
>>> but that only further highlights that we're talking about something
>>> higher level.
>>>
>>> I further don't believe this is actually borne out by the real-world
>>> use cases for this API, and instead for a notion of how developers
>>> "might" use this, and how it "might" be easier for them. This is such
>>> an abstract concept, and everyone has their own opinions about who the
>>> 'ideal' user is, that I'd much rather focus on the actual concrete use
>>> cases and identify
>>> 1) Does this address an unmet need?
>>> 2) Is this syntactic sugar?
>>>
>>> Look, compare this discussion to jQuery, Moo, Prototype, YUI, etc.
>>> They all build a wide variety of sugar on top of the DOM that allows
>>> developers to use different idiomatic approaches - but all yield the
>>> same results.
>>>
>>> I'm sympathetic to the notion that there should be a "right" way, if
>>> only because it's convenient, but there's not some "right" way that's
>>> magically going to lead to secure code, which is the crux of the
>>> justification.
>>>
>> I'm actually not being a JOSE partisan here.  Technically, the only
>> requirement for this serialization is that it be something that the API can
>> turn back into an object from which it can get algorithm, key, and data
>> parameters.  (This might argue for making a separate "CryptoResult" object
>> instead of hanging these things on CryptoOperation, but that's a minor
>> point.)  JOSE seems like an obvious choice to me, but it could just as well
>> be an opaque string that only a particular browser instance can interpret.
>>
>> If this were Java, this would just be the Serializable interface.  This
>> is not a far leap from Clonable, which we already have for keys,
>> algorithms, and data individually (Key objects, AlgorithmIdentifier
>> dictionaries, and ArrayBufferViews).
>>
>> Really, it might be enough here to just create a CryptoResult object (==
>> alg+key+data), and make it Clonable.  That way, applications could at least
>> store cryptographically protected objects locally.  A serialization of this
>> format would help address applications with server-side storage, but I'll
>> admit this is a secondary consideration.
>>
>>
>>
>>  I've asked before for examples of how these are harmful.  Maybe I'm
>>>> forgetting some, but the worst case I remember you bringing up is that
>>>> default parameters could lock browsers into a choice.  As I explained in
>>>> the essay below, that is a problem, but it's one that can be addressed by
>>>> also making it easy for developers to capture all the data they need.
>>>>
>>> Which is, again, a task of an overall format and protocol, not an API.
>>> Look, fundamentally we're talking KeyCzar/NaCL vs OpenSSL/NSS - a
>>> point of debate we've long since settled, and which this is just
>>> effectively the same conversation.
>>>
>> I don't think anyone has ever complained that OpenSSL or NSS was too easy
>> to use.  :)  Keep in mind that for exactly that reason, OpenSSL includes
>> two simplified interfaces (CMS_encrypt and EVP_seal) that do generate
>> parameters for you.
>>
>> You're also posing a false dichotomy here.  I'm not proposing that we
>> remove functionality from the API.  All I'm saying is that we shouldn't
>> force developers to touch all of the knobs all of the time.  They should
>> only have to care about advanced settings if they're doing advanced things.
>>
>> So in fact, I'm actually proposing what OpenSSL / libcrypto offers:
>> Fine-grained control when you want it (EVP_CipherInit, etc.), simpler
>> things when you don't.
>>
>>
>>
>>  What's the remaining risk?
>>>>
>>>>
>>>> By way of contrast, here's my 3-line horror story for the current API:
>>>>     let alg = { name: "AES-GCM", params: { iv: new
>>>> Uint32Array([0,0,0]), tagLength: 0 }}
>>>>     let op1 = window.polycrypt.encrypt( alg, key, content1 );
>>>>     let op2 = window.polycrypt.encrypt( alg, key, content2 );
>>>> Run that by some developers, see if they can spot the problem.
>>>>
>>>> Contrast with proposed syntax:
>>>>     let op1 = window.polycrypt.encrypt( "AES-GCM", key, content1 );
>>>>     let op2 = window.polycrypt.encrypt( "AES-GCM", key, content2 );
>>>> UA provides a fresh IV and a full-length authentication tag, nobody
>>>> gets hurt.  But if you want to specify those things, you still can!
>>>>
>>> As explained above, your example does not work.
>>>
>>> Further, I encourage you to apply this "idea" to the other algorithms
>>> currently specified. You will find that for the vast majority, the
>>> parameters that are required all have trade-offs and security
>>> considerations associated with them - there truly is no "one size fits
>>> all answer". Further, any defaults tacitly suggest there is some
>>> minimal set of 'security guarantees' provided - which is exactly
>>> something that CANNOT be guaranteed nor can be asserted from an API.
>>>
>> Sure there are trade-offs, but to first order it's not that hard to make
>> reasonably safe, widely-interoperable choices:
>>
>> RsaSsaParams.hash - Just use SHA-256
>> EcKeyGenParams.namedCurve - Use P-384
>> Etc.
>>
>>
>> Yes, there are subtle trade-offs that one can get caught up in, but these
>> choices are sufficient for a wide variety of applications.  And if an
>> application wants to manage the trade-offs, it can override the UA's
>> choices.
>>
>> The real question is who we think is best suited to make these choices.
>>  The current API makes the assumption that developers will thoughtfully
>> consider the trade-offs and come to good decisions.  I don't know how
>> anyone can take that assumption seriously.  Even otherwise well-qualified
>> web developers can't be expected to understand the nuances of cryptographic
>> parameter selection.
>>
>> What I'm proposing is that much like the WebCrypto API allows application
>> code to benefit from high-quality crypto code inside the browser, we allow
>> developers to benefit from the high-quality cryptographic expertise inside
>> the browser vendors.
>>
>> --Richard
>>
>>
>>
>>
>>
>>
>>>> --Richard
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Mar 28, 2013, at 11:52 AM, Ryan Sleevi <sleevi@google.com> wrote:
>>>>
>>>>  Mark,
>>>>>
>>>>> Richard's points about defaults gave been repeatedly discussed in the
>>>>> group and numerous examples provided for how they fundamentally represent
>>>>> bad API design for a low-level API, but are very much a part of a
>>>>> high-level API.
>>>>>
>>>>> Further, it has also been discussed with how the argument that crypto
>>>>> is somehow "special" or inherently more dangerous than other APIs is a
>>>>> fundamentally flawed assertion. The ability for CSRF, cookie leaking, or
>>>>> XSS all represent vastly more serious and real threats than bad
>>>>> cryptography.
>>>>>
>>>>> Developers can write extremely poor performant WebGL, but you don't
>>>>> see us discussing VRML as the solution. Developers can write absolutely
>>>>> horribly performing CSS, but you don't see us discussing ways to provide a
>>>>> default set of "site templates," ala GeoCities of yore, to have code
>>>>> blessed by the design priesthood.
>>>>>
>>>>> The argument that Crypto can or is used to implement "security," a
>>>>> fundamentally amorphous term that van mean completely contradictory things
>>>>> depending on personal views (e.g. DRM) is irrelevant to the discussion of
>>>>> the API - but it makes up the fundamental argument of Richard's position.
>>>>>
>>>>> There is unfortunately nothing here that has not already been
>>>>> discussed at length, and with numerous examea provided as to its
>>>>> unsuitablity for a low-level API.
>>>>>
>>>>> Discussions of parameters and serialization are EXACTLY the issue that
>>>>> a high-level API tries to solve; when you say 'let's combine primitives and
>>>>> serialization/persistence', you are no longer discussing a low-level API.
>>>>>
>>>>> I did not say Richard's points were wrong - in the context of a
>>>>> high-level API, they're an imminently sensible reminder of objectives. But
>>>>> in the context of a low-level API, but especially in the context of this
>>>>> group, its a retread of points not applicable.
>>>>>
>>>>> On Mar 28, 2013 8:42 AM, "Mark Watson" <watsonm@netflix.com> wrote:
>>>>> Ryan,
>>>>>
>>>>> I thought Richard's piece was well written, made some good points and
>>>>> was clearly targeted at the low-level API on which we are working. His
>>>>> suggested remediation for the problems is straightforward. IMHO, at the
>>>>> very least, it deserves a more considered response.
>>>>>
>>>>> ...Mark
>>>>>
>>>>> On Thu, Mar 28, 2013 at 8:39 AM, Ryan Sleevi <sleevi@google.com>
>>>>> wrote:
>>>>> Thank you for your description of a high-level API.
>>>>>
>>>>> At this time, the WG is pursuing a low-level API.
>>>>>
>>>>> On Mar 28, 2013 8:21 AM, "Richard Barnes" <rbarnes@bbn.com> wrote:
>>>>> The SubtleCrypto thread reminded me that I'd been meaning to send out
>>>>> some notes I wrote down about unskilled developers.
>>>>>
>>>>> Brief essay follows.  Comments welcome.
>>>>>
>>>>> --Richard
>>>>>
>>>>>
>>>>>
>>>>> On Crypto API Safety in the Hands of Unskilled Developers
>>>>> ==============================**===========================
>>>>>
>>>>> I. What is the problem (general)?
>>>>> ------------------------------**---
>>>>>
>>>>> The current API's approach of exposing unmitigated complexity to the
>>>>> developer -- no defaults, no help from the browser -- is only plausible if
>>>>> we assume that the only people who will use the API are experienced
>>>>> cryptographers.  This assumption is clearly not true.  Any API that is
>>>>> supplied in the DOM will be exposed to, and get used by, a much wider
>>>>> variety of developers than we ever intend.
>>>>>
>>>>> That's true of any DOM API, whether it's crypto, geolocation, canvas,
>>>>> etc.  But crypto is special.
>>>>>
>>>>> -- Bad crypto design leads to worse consequences
>>>>> -- Bad crypto design is hard to detect
>>>>>
>>>>> The whole point of having a crypto API is to protect sensitive things.
>>>>>  So by definition, if you screw up your usage of the crypto API, you are
>>>>> exposing sensitive things.  Moreover, if this happens, you are likely not
>>>>> to notice it.  If you screw up your WebGL rendering code, things will look
>>>>> bad.  If you re-use the same nonce twice in GCM, nothing is obviously
>>>>> different.
>>>>>
>>>>> So in its current state, the API makes it likely for bad things to
>>>>> happen.  It would be irresponsible of this group to release an API in this
>>>>> state.  We need to think seriously about how to make the default mode of
>>>>> the API less likely to lead to pain, while still allowing for full
>>>>> generality.
>>>>>
>>>>> Think of this like consumer protection.  You can't ship a lawn mower
>>>>> that doesn't have a guard around the blade.  Someone can buy a lawn mower,
>>>>> take off the guard, and use the motor and blade in new and creative ways,
>>>>> at the risk of injuring himself.  Even if someone isn't doing something
>>>>> advanced, they can still stick their hand under the guard and get cut.  But
>>>>> by default, in most use cases, the lawn mower is safe to use.
>>>>>
>>>>>
>>>>>
>>>>> II. What is the problem (specific)?
>>>>> ------------------------------**-----
>>>>>
>>>>> Conceptually, there are two classes of CryptoOperation: "Plain to
>>>>> ciphertext" operations that convert plaintext to data with cryptographic
>>>>> structure, and "Cipher to plaintext" operations that do the reverse.
>>>>>
>>>>> P2C       C2P
>>>>> -----------------
>>>>> sign      verify
>>>>> encrypt   decrypt
>>>>> digest
>>>>>
>>>>> The difference is this: P2C operations can meaningfully be done with
>>>>> many different choices of parameters.  C2P operations can only be done with
>>>>> a specific set of parameters.
>>>>>
>>>>> Both of these create problems for developers.
>>>>>
>>>>> For P2C operations, the developer must choose how to set multiple
>>>>> parameters, choices that are likely not obvious to someone not skilled in
>>>>> the art.
>>>>> For C2P operations, the developer needs to make sure that they keep
>>>>> all the relevant parameters together with protected information.
>>>>>
>>>>> So we have two problems:
>>>>> P2C: How to help developers make good choices
>>>>> C2P: How to help developers keep ciphertext associated to parameters
>>>>>
>>>>>
>>>>>
>>>>> III. What would a solution look like?
>>>>> ------------------------------**-------
>>>>>
>>>>> On the face of it, the P2C problem -- choosing parameters -- seems
>>>>> easy to solve.  If there are multiple valid sets of parameters, just have
>>>>> the browser / API implementation make the choice on behalf of the developer.
>>>>>
>>>>> However, this exacerbates the C2P problem, because there are now many
>>>>> ways for the ciphertext to be separated from its parameters.  If a web app
>>>>> does not store the parameters with which the ciphertext was computed
>>>>> (relying on the browser's defaults), then if the browser changes defaults,
>>>>> then the app will be unable to decrypt the ciphertext (or validate the
>>>>> signature).  Even if the app stores the parameters, then it needs to make
>>>>> sure that the ciphertext is always associated with the correct parameters;
>>>>> the app cannot, for example, send the ciphertext for storage on a server,
>>>>> but not the parameters.
>>>>>
>>>>> So in order to solve the P2C problem, we also need to solve the C2P
>>>>> problem.  Namely, we need to make it easy by default for apps to keep
>>>>> parameters and ciphertext together.  In API terms, that would seem to
>>>>> indicate that the results of a crypto operation should be provided as an
>>>>> object that contains all the relevant parameters (as indeed,
>>>>> CryptoOperation already does).  In addition, it would be helpful if this
>>>>> object had a default serialization, to address the issue of parameters
>>>>> getting lost when the object is stored or sent someplace else.
>>>>>
>>>>> This gives us two solutions to match the two problems:
>>>>> P2C: Provide browser-chosen defaults
>>>>> C2P: Provide results in an object with parameters and a serialization
>>>>>
>>>>> These don't prevent developers from running into problems -- choosing
>>>>> bad IVs, or deleting default parameters from the object -- but it
>>>>> encourages a default life-cycle that should be problem free:
>>>>> * Process plaintext, get ciphertext+parameters
>>>>> * Store ciphertext+parameters
>>>>> * Process ciphertext+parameters, get plaintext
>>>>>
>>>>> These solutions also don’t get in the way of more advanced developers.
>>>>>  You can still specify all the parameters, and still use whatever parts of
>>>>> the object you want.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>
> --
> jCore
> Email :  avitte@jcore.fr
> iAnonym : http://www.ianonym.com
> node-Tor : https://www.github.com/Ayms/**node-Tor<https://www.github.com/Ayms/node-Tor>
> GitHub : https://www.github.com/Ayms
> Web :    www.jcore.fr
> Webble : www.webble.it
> Extract Widget Mobile : www.extractwidget.com
> BlimpMe! : www.blimpme.com
>
>

Received on Friday, 29 March 2013 16:13:49 UTC