Re: Algorithm Discovery (was Re: Strawman proposal for the low-level API - about the interoperable set of algo and algo naming)

On Tue, Jul 3, 2012 at 11:03 AM, Anthony Nadalin <tonynad@microsoft.com>wrote:

>  My concerns are:****
>
> ** **
>
> **(1)    **Discovery as I read the various appends, deals with the
> algorithms not the permutations of parameters that may be allowed or
> supported, so thus discovery of the algorithm may be successful but may
> still fail, and thus the extra effort for discovery is overhead and extra
> code path
>
Using the strawman, discovery would look something like:

if (window.crypto == undefined) {
  // No support at all
}

if (!window.crypto.supports({ 'name': 'HMAC', 'params': { 'hash': { 'name':
'SHA512' } } }) {
  // Using the full (non-abbreviated) form of algorithm identifiers
} else if (!window.crypto.supports('ES256'')) {
  // Using the abbreviated (JWA) form for ECDSA with a P-256 curve and
SHA-256
}

// Get a specific key handle - method TBD
var key = ...;
if (!window.crypto.supports('ES256', key)) {
  // |key| does not support ECDSA.
  console.log(key.algorithm);  // might output "RSA" or "RSA-1024"
}

****
>
> **(2)    **Maintaining the discoverable algorithms, ongoing work, how do
> we ensure this is always up to date and accessible
>
This seems fully orthogonal from discovery. This seems to be related to the
mandatory discussion - and more importantly, whether or not the list of
algorithms can be extended.

My assumption has been that U-As can, will, and should be able to support
arbitrary algorithms. This is inline with how media is handled and how APIs
such as how the Device APIs WG work products are emerging - such as Web
Intents.

As such, the semantics of algorithms is an "ongoing" problem. The WG can
and should specify well-known algorithms, their naming, and their semantics
with regards to inputs/outputs. For anything not on the list, it is
implicitly vendor-defined. This provides the future-proofing of tomorrows
U-As supporting new algorithms - standardized or not.


> ****
>
> **(3)    **Means that there has to be some understanding of the keying
> material, not sure this will always be the case
>
Not necessarily. As provided in the WebIDL for the strawman, Key is
optional. Some algorithms are keying dependent - for example, many
signature schemes. Some materials are keying independent - such as hashing.
And some may or may not be keying dependent - such as cipher operations
such as AES-et-al that have a component of both "Is it supported at all"
and "Is it supported for this particular key"


> ****
>
> **(4)    **Not sure that we will have user agents in all cases or what
> the user agent is capable of doing
>
I'm not sure I follow. The "not sure what the user agent is capable of
doing" though is exactly part of the problem that discoverability attempts
to address.


> ****
>
> **(5)    **Can we assume that .discovery is optional?
>
While I would think algorithms can and should be optional, I do not think
core points of the API should be. I would personally rather see an all or
nothing approach. Either applications should manually re-implement
discovery in terms of try/catch blocks, or we can/should provide a way to
determine if its supported. Under the hood, I believe the implementations
will be identical, which is why I suggested it by part of the core API
rather than being boilerplate that each app dev needs to re-implement.


> ****
>
> ** **
>
> *From:* Ryan Sleevi [mailto:sleevi@google.com]
> *Sent:* Tuesday, July 03, 2012 10:48 AM
> *To:* Anthony Nadalin
> *Cc:* David Dahl; Mike Jones; GALINDO Virginie; Seetharama Rao Durbha;
> public-webcrypto@w3.org
> *Subject:* Algorithm Discovery (was Re: Strawman proposal for the
> low-level API - about the interoperable set of algo and algo naming)****
>
> ** **
>
> Could you explain the overhead/complexity/maintenance concerns?****
>
> ** **
>
> As you mentioned, the assumption is that .encrypt/.decrypt/.sign/.verify
> will all have some error handling mode if an invalid algorithm is
> specified. Likely, this will be some form of exception.****
>
> ** **
>
> So we know that there will need to be logic in place to determine if a
> given set of parameters are valid for an operation.****
>
> ** **
>
> What is the overhead of providing an explicit method to determine that
> up-front? Presumably, .discover would provide the same implementation.****
>
> ** **
>
> The arguments in favour of the explicit discover method:****
>
>    - It does not require the caller to (yet) have access to the keying
>    material that will be used with the operation.****
>
>
>     - This seems valuable for situations where keying material may need
>       to be generated or located, which may involve user prompting/interaction
>       (at a UA's discretion).****
>       - For situations where generating keying material may be
>       computationally intensive, it avoids the perception of a 'slow' web app,
>       especially if the keying material will not be usable for the operation
>       requested.****
>
>
>    - It allows an application to implement the appropriate
>    feature-discovery mechanisms within their app. If the app only supports a
>    particular mechanism, and that mechanism has been (deprecated, not yet
>    supported), it gives the application the up-front ability to signal that
>    fact, without having to wait until deep within the application logic. This
>    is perhaps a weaker argument, but combines with the next point.****
>    - The caller does not have to track the objects it creates and pass
>    them through its internal layers in order to be able to do both discovery
>    and to use them.****
>
>
>     - What I mean by this is - imagine a U-A that wants to implement a
>       prompt-per-key-use scheme of user interaction, using an unspoofable UI to
>       ensure the user wishes to allow the application access - EVEN if they have
>       granted access a-prioi. This is conceptually similar to smart cards that
>       require an explicit button push for signing operations. Under such a
>       scheme, a web application would want to separate out discovery (You COULD
>       use this algorithm, no prompting necessary) with use (which will be ACL'd,
>       and may fail)****
>       - Under such a scheme, to minimize prompting, once a user has a
>       CryptoStream object (used for discovery), it would then need to pass that
>       object to the layers that will (eventually) need it.****
>       - This is especially problematic if an application is trying to
>       discover a supported 'suite' of algorithms (so that it knows whether or not
>       the U-A will even work with the application), and each possible combination
>       may result in prompting, even if only a single object (the negotiated
>       suite) will be used.****
>
>  Now, I'll readily acknowledge that these issues may be solvable through
> other means. It may further be that we decide some of the above scenarios
> are not at all applicable problems.****
>
> ** **
>
> Naturally, I'm coming with a bias towards user agents, and wanting to
> think through ways that UAs may interact with keys and users, the security
> implications, and how such information is exposed to web applications.
> These are ultimately design decisions that I would want to keep web
> applications unaware of. I think discovery provides a means for
> applications to remain blissfully unaware of the U-A's implementation
> details.****
>
> ** **
>
> Note that I'm imagining discovery working as a "Can you do the follow?",
> and NOT a "Enumerate all possible supported combinations and permutations".
> If you felt I was suggesting the latter, I'd absolutely agree that it was
> needlessly complex and with significant (implementation) overhead - such
> that it would likely be unrealistic for U-As to reasonably implement across
> disparate crypto systems.****
>
> ** **
>
> On Tue, Jul 3, 2012 at 7:31 AM, Anthony Nadalin <tonynad@microsoft.com>
> wrote:****
>
> Seems way to much overhead, complexity and maintenance, what is wrong with
> a simple exception if the algorithm is not there, as you will have to go
> this route if there is an error processing the algorithm (bad padding, bad
> key, etc)****
>
>
> -----Original Message-----
> From: David Dahl [mailto:ddahl@mozilla.com]
> Sent: Monday, July 02, 2012 7:22 PM
> To: Anthony Nadalin****
>
> Cc: Mike Jones; GALINDO Virginie; Seetharama Rao Durbha;
> public-webcrypto@w3.org; Ryan Sleevi
> Subject: Re: Strawman proposal for the low-level API - about the
> interoperable set of algo and algo naming
>
> The thoughts on a discovery API were centered on allowing developers to
> test for capabilities before attempting operations.
>
> Cheers,
>
> David
>
> ----- Original Message -----
> From: "Anthony Nadalin" <tonynad@microsoft.com>
> To: "Ryan Sleevi" <sleevi@google.com>
> Cc: "Mike Jones" <Michael.Jones@microsoft.com>, "GALINDO Virginie" <
> Virginie.GALINDO@gemalto.com>, "Seetharama Rao Durbha" <
> S.Durbha@cablelabs.com>, "David Dahl" <ddahl@mozilla.com>,
> public-webcrypto@w3.org
> Sent: Monday, July 2, 2012 9:00:49 PM
> Subject: RE: Strawman proposal for the low-level API - about the
> interoperable set of algo and algo naming
>
> My concern is why do we need discovery?
>
> From: Ryan Sleevi [mailto:sleevi@google.com]
> Sent: Monday, July 02, 2012 5:01 PM
> To: Anthony Nadalin
> Cc: Mike Jones; GALINDO Virginie; Seetharama Rao Durbha; David Dahl;
> public-webcrypto@w3.org
> Subject: Re: Strawman proposal for the low-level API - about the
> interoperable set of algo and algo naming
>
> Hi Anthony,
>
> If the work of this WG was strictly confined to defining a set of
> JavaScript/DOM bindings that produced  JWS/JWE outputs, as defined by the
> IETF JOSE WG, I absolutely agree that it would make perfect sense to use
> the JOSE registry.
>
> However, we can already see impedence between the work of this WG and the
> use cases and the JOSE work. For example, symmetric keys cannot be
> represented as JWKs, nor does JWK ascribe to attempting to do so, so the
> use of JWKs as key identifiers for this API is something that we cannot do.
>
> Everything that can be expressed by JOSE SHOULD, I believe, be possible
> with this API. However, there are and will be algorithms/methods/outputs
> that do not overlap with the JOSE work products, so the choice of JOSE as
> the registry seems like an ill fit.
>
> Given this, the choice of JOSE as a registry seems to be solely motivated
> by the relation to JavaScript, and not necessarily related to how the APIs
> do (or, in this case, don't) overlap.
> On Mon, Jul 2, 2012 at 3:39 PM, Anthony Nadalin <tonynad@microsoft.com
> <mailto:tonynad@microsoft.com>> wrote:
> Does not do us all any good to have multiple registries either, still
> wondering why we need this feature
>
> From: Ryan Sleevi [mailto:sleevi@google.com<mailto:sleevi@google.com>]
> Sent: Monday, July 02, 2012 9:14 AM
> To: Mike Jones
> Cc: GALINDO Virginie; Seetharama Rao Durbha; David Dahl;
> public-webcrypto@w3.org<mailto:public-webcrypto@w3.org>
> Subject: Re: Strawman proposal for the low-level API - about the
> interoperable set of algo and algo naming
>
> My concern with such an approach is that it limits the
> functionality/utility of the web crypto API to the points where it overlaps
> with JOSE. I think the use cases we've seen presented so far do not
> necessarily depend on JOSE nor do they overlap with the problems being
> solved by JOSE, so it seems non-ideal to delegate the registry out.
> On Mon, Jul 2, 2012 at 8:15 AM, Mike Jones <Michael.Jones@microsoft.com
> <mailto:Michael.Jones@microsoft.com>> wrote:
> IANA will be maintaining a registry of algorithm names for JOSE.  It will
> handle the addition of new algorithm identifiers, designating obsolete
> algorithms deprecated, etc.  We could do worse than to simply use that
> registry.
>
>                                                             -- Mike
>
> From: GALINDO Virginie [mailto:Virginie.GALINDO@gemalto.com<mailto:
> Virginie.GALINDO@gemalto.com>]
> Sent: Sunday, July 01, 2012 12:30 PM
> To: Mike Jones
> Cc: Seetharama Rao Durbha; Ryan Sleevi; David Dahl;
> public-webcrypto@w3.org<mailto:public-webcrypto@w3.org>
> Subject: RE: Strawman proposal for the low-level API - about the
> interoperable set of algo and algo naming
>
> Mike, and all,
>
> The WG has already discussed that, and we mentioned that we would not
> mandate any algorithm, but will have instead an algo discovery mechanism to
> help developers to tune their app behavior across the different platforms.
> We also suspected that the minimum core of algorithm implemented would be
> market driven and may evolve in the time, and thus would not need to be
> directed by the Web Crypto WG. Note for the editors : this implies that we
> will have to maintain a list of names for algorithms in our algo
> dictionary, and think about regular updates (a job for your entire life,
> guys :)).
>
> Regards,
>
> Virginie
> gemalto
> Chair of Web Crypto WG
>
> From: Ryan Sleevi [mailto:sleevi@google.com]<mailto:[mailto:
> sleevi@google.com]>
> Sent: jeudi 21 juin 2012 20:34
> To: Mike Jones
> Cc: Seetharama Rao Durbha; David Dahl; public-webcrypto@w3.org<mailto:
> public-webcrypto@w3.org>
> Subject: Re: Strawman proposal for the low-level API
>
>
> On Thu, Jun 21, 2012 at 11:22 AM, Mike Jones <Michael.Jones@microsoft.com
> <mailto:Michael.Jones@microsoft.com>> wrote:
> I believe there are advantages beyond what a browser must implement.  For
> one, producing the set of defined algorithm/parameter combination labels
> forces the working group to make conscious choices about what combinations
> make sense to promote the usage of, just as JOSE is doing.  This will
> likely aid interop.
>
> Fair enough. I think we'll probably be in disagreement on this - I don't
> think the WG should be in the position of arbitrar of what can or should be
> implemented, as I think it significantly limits the utility of the API and
> the ability  to make useful combinations. If any value decisions need to be
> made, I think they make more sense within the context of a high-level API,
> which the survey respondants indicated less interest in. The discussion of
> JWA/JWK/JWS previously were, as I perceived, discussions about how the
> high-level API should behave.
>
> My view of interop is that the API should behave consistently across all
> platforms.
> What I understand you to be saying (and may be mistaken on), is that you
> view interop is that the same algorithms should be implemented across all
> platforms.
>
> I don't think that sort of view of interop is attainable, given how/where
> the web runs, in the same way that the <img> tag does not require a JPG
> implementation (as spec'd), nor does the <video> tag require H2.64 or WebM.
>
>
> Also, it makes it simpler for code using the API to query whether a
> combination is supported.  A query for "ES256" is simple to formulate (and
> to respond to).  A query for { name: 'ECDSA', params: { hash: { name:
> SHA256' } } } - not so much.
>
>                                                                 -- Mike
>
> Sure. But as I mentioned several times, the shorthand "ES256" is fully
> valid within what I was proposing. I agree, shorthand is good! At the same
> time, shorthand that sacrifices flexibility/extensibility is, I believe,
> short-sighted, which is why the API specifies the long form, for which the
> short form fits, rather than describing only a short-form, of which a
> long-form does not fit.
>
>
> From: Ryan Sleevi [mailto:sleevi@google.com<mailto:sleevi@google.com>]
> Sent: Thursday, June 21, 2012 11:13 AM
> To: Seetharama Rao Durbha
> Cc: Mike Jones; David Dahl; public-webcrypto@w3.org<mailto:
> public-webcrypto@w3.org>
>
> Subject: Re: Strawman proposal for the low-level API
>
>
> On Thu, Jun 21, 2012 at 9:27 AM, Seetharama Rao Durbha <
> S.Durbha@cablelabs.com<mailto:S.Durbha@cablelabs.com>> wrote:
>
> "HS256" is the same as the hypothetical { name: 'HMAC', params: { hash: {
> name: 'SHA256' } } } "ES256" is the same as the hypothetical { name:
> 'ECDSA', params: { hash: { name: SHA256' } } }
>
> May be so. But the advantage/flexibility you are referring to here allows
> a future replacement of SHA256 with SHA1024, let us say. It is not so
> obvious to me how the developer may check the availability of ECDSA with
> SHA1024 in a specific browser. The above hypothetical may throw an
> unsupported algorithm/combination exception, but its much easier to
> query/check availability with one name.
> JCE is another reference here (
> http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#impl).
> The algorithm names in the table are essentially similar in approach to the
> JWA names. Its very clear from the table that if one were to write a Java
> program that is shipped and may run in unknown containers/VMs, it is better
> to not use RSA with SHA512.
>
> I agree that this same information could have been provided by splitting
> the Algorithm column into multiple columns, one for each parameter. Its
> just a little harder to enforce it during development. For example, its
> very easy to provide constants for supported combinations, and thus enable
> compile time checking.
>
> Except we're in JavaScript, the concept of compile time checking is a bit
> of a foregone conclusion. Providing hard constants (eg: an enum on an
> Interface) means that any implementation that extends this interface would
> be Non-Compliant, and any adoption of new algorithms MUST be done via
> updating the spec (which then makes legacy implementations non-compliant).
>
> There are effectively two ways to check - using the .supports({ name:
> 'ECDSA', params: { hash: { name: SHA1024 } } }) (which returns a bool) or
> by attempting to instantiate it, such as via .encrypt({ name: 'ECDSA', ...
> })
>
> This is the exact same way an application would check for support using
> strings as identifiers - .supports('ES1024') / .encrypt('ES1024')
>
> Again, it sounds like the argument you're making is orthogonal to the
> representation - for example, "It's better to not use RSA with SHA512" is
> only true because it's not explicitly listed within the Implementation
> Requirements. However, as also noted within that spec, third-party
> providers can implement whatever they want.
>
> The discussion about what U-A's MUST/SHOULD/MAY implement is a useful
> discussion to have, but it seems perhaps separate from the API discussion.
> The API should be flexible enough to support 'any' algorithm - not strictly
> for vendor extensibility, but simply on the basis of providing a well
> defined method for how we, as a WG, extend this spec in the future.
>
> Is there an advantage to the 'string' representation that is not directly
> tied to what a browser MUST implement? The limitation I described I believe
> is reasonable - cannot provide arbitrary/algorithm-specific data, such as
> OAEP label.
>
>
>
> From: Ryan Sleevi <sleevi@google.com<mailto:sleevi@google.com>>
> To: Seetharama Rao Durbha <s.durbha@cablelabs.com<mailto:
> s.durbha@cablelabs.com>>
> Cc: Mike Jones <Michael.Jones@microsoft.com<mailto:
> Michael.Jones@microsoft.com>>, David Dahl <ddahl@mozilla.com<mailto:
> ddahl@mozilla.com>>, "public-webcrypto@w3.org<mailto:
> public-webcrypto@w3.org>" <public-webcrypto@w3.org<mailto:
> public-webcrypto@w3.org>>
>
>
> Subject: Re: Strawman proposal for the low-level API
>
> On Wed, Jun 20, 2012 at 3:06 PM, Seetharama Rao Durbha <
> S.Durbha@cablelabs.com<mailto:S.Durbha@cablelabs.com>> wrote:
> I think this is tussle between interoperability and extensibility. For
> interoperability, we certainly need a published set of algorithms and their
> combinations that developers can rely on (previously I expressed that we
> need a mandatory list of such). The question is whether this set gets baked
> into the API itself (through an ENUM for example) or validated through
> interop tests. The former is more easier for developers to verify that
> their implementations are going to be cross-platform/browser compatible.
> The later allows developers to take advantage of features when they are
> available in certain platforms/browsers.
>
> I personally believe that having the API limit/specify features is a good
> thing. It cuts down a lot of time (doing research on what browser
> implements what algorithms) as well as second guessing what is a good
> combination.
>
> On the other hand, concatenated combinations do not limit extensibility.
> If a particular browser provides a specific combination not in the spec, it
> can do so through a custom namespace - something like what people did with
> CSS, through -webkit or -mozilla prefixes.
>
> --Seetharama
>
> It's worth noting that the (continued) use of prefixes is an area of great
> stylistic/semantic debate within the other WGs, and my understanding from
> the light following of discussions is that the prevailing opinion is that
> it is not the Right Way Forward. As we've seen, in practice simply forces
> vendors to implement each other's prefixes, since early adopters either
> fail to or, with some of the semantics, simply cannot, use prefixes in a
> way that will be forwards compatible.
>
> I fundamentally don't see any differences between Mike's JWA reference and
> what I proposed, other than brevity, so I'm trying to understand what
> exactly the argument is. Both you and Mike have made references to
> interoperability, but that seems to me to be wholly orthogonal to the
> representation of algorithms and their parameters.
>
> Likewise, the argument of "restricting people from getting it wrong" seems
> more an argument in favour of a high-level API, since by very nature,
> low-level APIs, in order to be useful for situations both described and yet
> to be discovered, must give you enough rope to hang yourself.
>
> If the WG decides that there should be a list of MUST implements, then
> whether it's a set of string identifiers or a set of
> Algorithms+AlgorithmParams, its no different which scheme we choose.
>
> "HS256" is the same as the hypothetical { name: 'HMAC', params: { hash: {
> name: 'SHA256' } } } "ES256" is the same as the hypothetical { name:
> 'ECDSA', params: { hash: { name: SHA256' } } }
>
> Both are fully extensible schemes - that is, new JWA algorithm identifiers
> can be registered via IANA or extended via URI, and new Algorithms can be
> implemented by vendors/implementations and possibly standardized as
> appropriate (eg: W3C WG efforts, the same as already happens for CSS, HTML,
> etc). As I mentioned to David, it's fully possible to express a JWA
> algorithm via short-name, such as { name: 'ES256' }, which serves as
> reasonable 'default' values.
>
> As far as I can tell, the only actual difference at play is whether we use
> a single string or a dictionary. Under a single string, there is no way to
> convey additional, application specific data or optional parameters, as far
> as I can tell. For example, under JWA's single-string naming, with
> RSA-OAEP, there's no way for an application to include the 'label' data. I
> imagine that under the scheme, one would have to construct some canonical
> URI form and then append something like query parameters to specify
> additional data - encoding into an appropriate ASCII representation as
> necessary (base64?)
>
> Again, I'm not trying to suggest that an implementor of a scheme like HMAC
> be required to support HMAC with every possible hash function real or
> imagined - just that the semantics of the arguments and their handling are
> well defined, both when supported and not. The API specification itself
> should be able to react to any set of identifiers/parameters - and that
> equally applies whether using pure string identifiers ("ES256") or using
> dictionaries.
>
> It seems like this is really a discussion of more complexity/more
> flexibility vs less complexity/less flexibility. I'd much rather err on the
> side of more complexity/flexibility, since if there has been anything
> learned from the meteoric growth of the Internet and the richness of the
> Web, it's that there are so many ideas and use cases that we have yet to
> imagine.
>
> I think a perfect parallel to the APIs we're discussing here would be
> WebGL (which allows for browser/vendor specific extensions), Web Intents
> (which allow for arbitrary intents to be registered), WebRTC (which does
> not specify the format of the MediaStream), the video tag (which allows
> arbitrary types), or even further back, the catch-all cloaca that is the
> <object> tag. All of these, by virtue of flexibility, have allowed for very
> quick and rapid iteration and adoption of new features/abilities, without
> mandating any specific behaviours beyond the core API.
>
> Cheers,
> Ryan
>
>
> From: Ryan Sleevi <sleevi@google.com<mailto:sleevi@google.com>>
> To: Mike Jones <Michael.Jones@microsoft.com<mailto:
> Michael.Jones@microsoft.com>>
> Cc: David Dahl <ddahl@mozilla.com<mailto:ddahl@mozilla.com>>, "
> public-webcrypto@w3.org<mailto:public-webcrypto@w3.org>" <
> public-webcrypto@w3.org<mailto:public-webcrypto@w3.org>>
>
> Subject: Re: Strawman proposal for the low-level API
>
>
> On Wed, Jun 20, 2012 at 1:47 PM, Mike Jones <Michael.Jones@microsoft.com
> <mailto:Michael.Jones@microsoft.com>> wrote:
>
> As a data point, the IETF JOSE work intentionally has only algorithm
> identifiers and no separate algorithm parameters.  Instead, the particular
> parameter choices are baked into the identifier.
>
>
>
> So for instance, rather than having a generic RSA signature algorithm and
> hash functions as parameters, there are separate algorithm identifiers such
> as:
>
>                 RS256 - RSA signature using SHA-256 hash algorithm
>
>                 RS384 - RSA signature using SHA-384 hash algorithm
>
>                 RS512 - RSA signature using SHA-512 hash algorithm
>
>
>
> The designers of the JOSE specs felt that it would be better, both for
> implementers and for interop, to specify a small set of meaningful
> algorithm combinations, than to face the combinatorial explosion that
> independently specifying each parameter causes.
>
>
> See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms for
> the algorithm combinations specified and the identifiers for them.
>
>
>
> I'd personally rather see the WebCrypto APIs follow this model, than allow
> all parameter combinations as XML DSIG and XML ENC do.  As a bonus, the
> WebCrypto work could then directly use the algorithm identifiers in the JWA
> spec, rather than inventing new ones.
>
>
>
>                                                                 Best
> wishes,
>
>                                                                 -- Mike
>
> Mike,
>
> It's not clear to me how that scheme or the spec actually avoid
> combinatorial growth. You're still individually specifying algorithm
> parameters - you're just doing it symbolically via the algorithm identifier.
>
> Even under a MUST implement scheme (which I'm still fairly opposed to),
> extensibility is still important. Under JWA, extensibility must be
> accomplished by concatenating symbols together to form an identifier.
> Unrecognized identifiers are rejected.
>
> Under the above proposal, extensibility is accomplished by defining
> parameters. Unrecognized parameters or unsupported parameter options are
> rejected.
>
> I certainly don't mean to imply that every possible hash algorithm + RSA
> PKCSv1.5 must be supported for an implementation to be compliant. For that
> matter, I don't even think an implementation needs to understand RSA to be
> compliant. However, it MUST have well-defined behaviour encountering
> unrecognized algorithm/parameters.
>
> For example, under the current JWA specification (draft-02), there's no
> way to use RSA-PSS. That's specifically called out within Section 3.3. If
> an implementation wanted to support RSA-PSS with SHA-1/2-224,2-256,2-512,
> then according to Section 6.2, a new 'alg' value would be registered with
> IANA OR be a URI (as per 3.6).
>
> So JWA still has a fully extensible API with full combinatorial growth, it
> just requests that you go through the IANA registry. I don't see how that's
> different than what I was proposing. Is it just a matter of difference in
> who operates the registry? Given that URIs can be used, even the registry
> isn't actually required.
>
> Cheers
>
> From: Ryan Sleevi [mailto:sleevi@google.com<mailto:sleevi@google.com>]
> Sent: Wednesday, June 20, 2012 1:17 PM
> To: David Dahl
> Cc: public-webcrypto@w3.org<mailto:public-webcrypto@w3.org>
> Subject: Re: Strawman proposal for the low-level API
>
>
> On Wed, Jun 20, 2012 at 12:42 PM, David Dahl <ddahl@mozilla.com<mailto:
> ddahl@mozilla.com>> wrote:
> ----- Original Message -----
> > From: "Ryan Sleevi" <sleevi@google.com<mailto:sleevi@google.com>>
> > To: public-webcrypto@w3.org<mailto:public-webcrypto@w3.org>
> > Sent: Monday, June 18, 2012 12:53:03 PM
> > Subject: Strawman proposal for the low-level API
> >
> > Hi all,
> >
> >    While I'm still in the process of learning WebIDL [1] and the W3C
> >    Manual
> > of Style [2], I wanted to take a quick shot at drafting a strawman
> > low-level API for discussion.
> This is great, thanks for taking the time.
>
> >
> > First, a bit of the IDL definition, to set the stage. This is also
> > using using ArrayBuffer from TypedArray [6], which I'm not sure if
> > it's altogether appropriate, but it's been incorporated by reference
> > into FileAPI [7], so it seems alright to use here.
> >
> I think so. ArrayBuffers seem a natural fit for this API.
>
> > [interface]
> > interface CryptoStream : EventTarget {
> >   void processData(ArrayBuffer buffer);
> >   void processData(DOMString data);
> The flexibility of accepting either a string or ArrayBuffer is a good
> idea, with an internal, seamless conversion.
>
> I'm not sure whether it should be a literal ArrayBuffer or if it should be
> an ArrayBufferView. In looking at more specs, I suspect the latter is
> actually more correct.
>
> Well, no, it's not necessarily a seamless conversion :-) DOMString is
> UTF-16, so the conversion into a byte sequence is problematic if
> underspecified (eg: as I've unfortunately done here)
>
> Representation of binary data via DOMString is a known problematic area
> (eg: see WHATWG's work on StringEncoding via the TextEncoder/TextDecoder
> interface).
>
> Within the W3C, I understand this is part of ongoing discussions in
> public-webapps.
>
>
> >   void complete();
> >
> >   readonly attribute (DOMString or ArrayBuffer)? result;
> >
> >   attribute [TreatNonCallableAsNull] Function? onerror;
> >   attribute [TreatNonCallableAsNull] Function? onprogress;
> >   attribute [TreatNonCallableAsNull] Function? oncomplete; };
> >
> > dictionary AlgorithmParams {
> > };
> >
> > dictionary Algorithm {
> >   DOMString name;
> >   AlgorithmParams? params;
> > };
> >
> > [NoInterfaceObject]
> > interface Crypto {
> >   CryptoStream encrypt(Algorithm algorithm, Key key);
> >   CryptoStream decrypt(Algorithm algorithm, Key key);
> >
> >   // Also handles MACs
> >   CryptoStream sign(Algorithm algorithm, Key key);
> >   CryptoStream verify(Algorithm algorithm, Key key, ArrayBuffer
> >   signature);
> >
> >   CryptoStream digest(Algorithm algorithm);
> >
> >   // This interface TBD. See discussion below.
> >   bool supports(Algorithm algorithm, optional Key key);
> >
> >   // Interfaces for key derivation/generation TBD.
> > };
> >
> >
> > As you can see, CryptoStream is used for all of the actual crypto
> > operations. That's because, in looking at the operations, I think all
> > of them will work on a series of calls to provide input, and the
> > result of which is either: error, some data output, or operation
> > complete.
> >
> > The real challenge, I think, lies in the AlgorithmParams structure,
> > which is where all of the algorithm-specific magic happens. My belief
> > is that we can/should be able to define this API independent of any
> > specific AlgorithmParams - that is, we can define the generic state
> > machine, error handling, discovery. Then, as a supplemental work
> > (still within the scope of the primary goal), we define and enumerate
> > how exactly specific algorithms are implemented within this state
> > machine.
> >
> > To show how different AlgorithmParams might be implemented, here's
> > some varies definitions:
> >
> > // For the 'RSA-PSS' algorithm.
> > dictionary RsaPssParams : AlgorithmParams {
> >   // The hashing function to apply to the message (eg: SHA1).
> >   AlgorithmParams hash;
> >   // The mask generation function (eg: MGF1-SHA1)
> >    AlgorithmParams mgf;
> >   // The desired length of the random salt.
> >   unsigned long saltLength;
> > };
> >
> > // For the 'RSA-OAEP' algorithm.
> > dictionary RsaOaepParams : AlgorithmParams {
> >   // The hash function to apply to the message (eg: SHA1).
> >    AlgorithmParams hash;
> >   // The mask generation function (eg: MGF1-SHA1).
> >    AlgorithmParams mgf;
> >   // The optional label/application data to associate with the
> >   signature.
> >   DOMString? label = null;
> > };
> >
> > // For the 'AES-GCM' algorithm.
> > dictionary AesGcmParams : AlgorithmParams {
> >   ArrayBufferView? iv;
> >   ArrayBufferView? additional;
> >   unsigned long tagLength;
> > };
> >
> > // For the 'AES-CCM' algorithm.
> > dictionary AesCcmParams : AlgorithmParams {
> >   ArrayBufferView? nonce;
> >   ArrayBufferView? additional;
> >   unsigned long macLength;
> > };
> >
> > // For the 'HMAC' algorithm.
> > dictionary HmacParams : AlgorithmParams {
> >   // The hash function to use (eg: SHA1).
> >   AlgorithmParams hash;
> > };
> >
> >
> > The API behaviour is this:
> > - If encrypt/decrypt/sign/verify/digest is called with an unsupported
> > algorithm, throw InvalidAlgorithmError.
> > - If " is called with an invalid key, throw InvalidKeyError.
> > - If " is called with an invalid key/algorithm combination, throw
> > UnsupportedAlgorithmError.
> > - Otherwise, return a CryptoStream.
> >
> > For encrypt/decrypt
> > - The caller calls processData() as data is available.
> > - If the data can be en/decrypted, it will raise an onprogress event
> > (event type TBD).
> >   - If new (plaintext, ciphertext) data is available, .result will be
> > updated. [This is similar to the FileStream API behaviour]
> > - If the data cannot be en/decrypted, raise the onMGF1-SHA1error with
> > an appropriate error
> > - The caller calls .complete() once all data has been processed.
> >   - If the final block validates (eg: no padding errors), call
> >   onprocess
> > then oncomplete.
> >   - If the final block does not validate, call onerror with an
> >   appropriate
> > error.
> >
> > For authenticated encryption modes, for example, the .result may not
> > contain any data until .complete has been called (with the result
> > data).
> >
> > For sign/verify, it behaves similarly.
> > - The caller calls processData() as data is available.
> > - [No onprogress is called/needs to be called?]
> > - The caller calls .complete() once all data has been processed
> > - For sign, once .complete() is called, the signature is generated,
> > and either onprogress+oncomplete or onerror is called. If successful,
> > the resultant signature is in .result.
> > - For verify, once .complete() is called, the signature is compared,
> > and either onprogress+oncomplete or onerror is called. If the
> > signatures successfully matched, .result will contain the input
> > signature (eg:
> > the
> > constant-time comparison happens within the library). If the
> > signatures don't match, .result will be null and the error handler
> > will have been called.
> >
> > Finally, for digesting, it behaves like .sign/.verify in that no data
> > is available until .complete() is called, and once .compete() is
> > called, the resultant digest is in .result.
> The final result of any of these operations would have all result data
> passed into the oncomplete event handler, correct?
>
> No. The oncomplete event handler follows the DOMCore event handling
> semantics. Since I didn't define a custom event type (eg: one that would
> curry the result), it would be expected that callers obtain the result via
> evt.target.result. evt.target is bound to an EventTarget, which the
> CryptoStream inherits from, and is naturally the target of the events it
> raises.
>
> This is shown in the pseudo-code example of how evt.target.result is read.
>
> But yes, for all successful operations (eg: no onerror callback),
> evt.target.result contains the data available. In the case of operations
> which yield "good" or "bad" (eg: MAC & Signature verification), the .result
> contains the verified data.
>
> Note that I didn't spec Verify+Recovery, since I'm still mulling that one
> over, but if implemented, I would imagine verifyRecover would presumably
> have the recovered PT (rather than the original signature) in .result.
>
>
>
> >
> > What I haven't fully worked out is how key derivation/agreement will
> > work - particularly if the result of some result of key agreement
> > results in multiple keys (eg: how SSL/TLS key derivation works in
> > PKCS#11). This is somewhat dependent on how we treat keys.
> >
> > Note that I left the Key type unspecified. It's not clear if this will
> > be something like (Key or DOMString), indicating some either/or of
> > handle / id, if it might be a dictionary type (with different naming
> > specifiers, such as 'id' or 'uuid'), or if it will be a concrete type
> > obtained via some other call (eg: .queryKeys()). I think that will be
> > borne out over the next week or two as we continue to discuss key
> > management/lifecycle.
> >
> > For a pseudo-code example:
> >
> > var stream = window.crypto.sign({ name: 'RSA-PSS', params: { hash: {
> > name:
> > 'sha1' }, mgf: { name: 'mgf-sha1' }, saltLength: 32 }}, key);
> > stream.oncomplete = function(evt) { window.alert('The signature is '
> > +
> > e.target.result); };
> > stream.onerror = function(evt) { window.alert('Signing caused an
> > error: ' +
> > e.error); };
> >
> > var filereader = FileReader();
> > reader.onload = function(evt) {
> > stream.processData(evt.target.result);
> > stream.complete(); }
> > filereader.readAsArrayBuffer(someFile);
> >
> >
> > The FileAPI is probably not the best example of why the iterative API
> > (.processData() + .complete()) is used, since FileReader has the
> > FileReader.result containing all of the processed data, but it's
> > similar than demonstrating a streaming operation that may be using
> > WebSockets [8] or PeerConnection [9].
> >
> > Note that I think during the process of algorithm specification, we
> > can probably get away with also defining well-known shorthand. eg:
> > 'RSA-PSS-SHA256' would mean that the hash is SHA-256, the mgf is
> > MGF1-SHA256, and only the saltLength needs to be specified (or should
> > it be
> > implied?)
> Since this is a low-level API, perhaps we imply a sensible default, with
> the ability to override for properties like saltLength?
>
> I think "sensible default" is actually quite appropriate for high-level,
> but not for low-level.
>
> One of my biggest concerns with "sensible default" is that, once spec'd,
> you cannot ever change the defaults. This creates potential problems when
> we talk about deprecating or removing support for algorithms.
>
> This is why I proposed the short-hand notation as an algorithm name,
> rather than being default/optional values on the Dictionary type.
>
> For example, rewind ten years ago (or lets go 20, to be fair), and a
> sensible default for RSA signatures would be RSA-PKCSv1.5 + MD5 for the
> message digest function.
>
> So applications get written using window.crypto.sign({'name': 'RSA' },
> RsaKey);
>
> Now, as we move forward in time, we discover that MD5 isn't all that
> great, and really people should be using SHA-1. However, we can not change
> the default for { 'name': 'RSA' }, because that would be a semantic break
> for all applications expecting it to mean MD5.
>
> Further, as we continue moving forward in time, we discover that PKCSv1.5
> isn't all that great, and PSS is much better. However, again, we cannot
> change the defaults, because it would break existing applications.
>
> The result of being unable to change the defaults is that when /new/
> applications are written, because they're not required to specify values
> (eg: there are defaults), they don't. The result is that new applications
> can end up using insecure mechanisms without ever being aware of it. By
> forcing the app developer to consider their parameters, whether explicitly
> via AlgorithmParams or implicitly via the algorithm 'name', it at least
> encourages 'best practice' whenever a new application is being written.
>
> The argument for default arguments is very compelling - there is no doubt
> about it. The less boiler plate, arguably the better. However, for a
> low-level API, particularly one whose functionality is inherently security
> relevant, defaults tend to end up on the short-end of the security stick
> over time, and that does more harm than good.
>
> That's why I provided the 'escape hatch' of defaults by using the
> algorithm name as a short-hand for the more tedious AlgorithmParams portion.
>
>
> >
> > Anyways, hopefully this straw-man is able to spark some discussion,
> > and hopefully if it's not fatally flawed, I'll be able to finish
> > adopting it to the W3C template for proper and ongoing discussions.
> >
> I like what you have here. I think this interface is elegant in the
> central concept of the CryptoStream being able to handle any operation
> possible for the algorithm. This interface is simpler to work with than my
> proposal.
>
> Like Wan-Teh said in the meeting this week,  we should figure out how key
> generation works, the structure of the key handle, or,  extracted key data
> properties look like.
>
> With the Algorithm and its AlgorithmParams are we headed down the path of
> maintaining a cipher suite for this API?
>
> So, as I mentioned on the phone and the preamble, I think as a WG we
> can/should first focus on defining the practical parts of the API - eg:
> without defining any ciphers (MUST or SHOULD) - and what the semantic
> behaviours are for consumers of this API.
>
> Following that, I think the WG can supplementally extend the spec to talk
> about different algorithms, modes, etc - eg: AES, RSA, HMAC, etc.
>
> I think part of this is pragmatic - while we can talk about all the
> 'popular' suites of today (AES, RSA, SHA-1/2), there's no guarantees
> they'll be secure 'tomorrow' (ECC, SHA-3, SomeNewKDF), and putting those as
> MUST-IMPLEMENT imposes a real security cost going forward. Further, as we
> look across the space of devices that might implement this API - from beefy
> desktops, to resource constrained mobile devices, to game consoles, to who
> knows what - it seems we must also recognize that the ability to reasonably
> support some algorithms is simply not going to exist. Whether this is being
> unable to AES in cipher-text-stealing mode or DSA/DSA2, a lack of support
> for ECC or MD5, mandating algorithms won't do much to help adoption of the
> core API, I believe.
>
> Yes, extensibility carries risks - vendor-specific encryption schemes may
> be added that aren't implemented by other user agents. However, this risk
> exists with just about any generic and usable web API defined by the W3C -
> we've seen it with custom HTML tags, custom CSS prefixes, <video> and
> <audio> algorithm support. I see the Algorithm/AlgorithmParams operating
> within that same space - something that can be (independently) standardized
> without changing this core API.
>
> Note: I do think the Core API can define sensible values for the
> algorithms we know/care about, I just don't think it's a function of the
> core API to dictate what must be implemented, just how it will behave if it
> is implemented.
>
> Cheers,
> Ryan
>
>
> Thanks again for putting this together, I think we should begin nailing
> down the hand wavy 'Keys' for this proposal.
>
>
> Regards,
>
> David
>
>
>
>
>
>
>
>
>
> ****
>
> ** **
>

Received on Tuesday, 3 July 2012 18:20:49 UTC