W3C home > Mailing lists > Public > public-webcrypto@w3.org > April 2013

Re: AlgorithmIdentifier in encrypt/decrypt/sign/verify operations

From: Mark Watson <watsonm@netflix.com>
Date: Mon, 15 Apr 2013 12:03:28 -0700
Message-ID: <CAEnTvdBuZ-4GX0hWh_iL8peSJG+PhATH4pLTt5N5qR4wmT9kzA@mail.gmail.com>
To: Ryan Sleevi <sleevi@google.com>
Cc: Richard Barnes <rbarnes@bbn.com>, "public-webcrypto@w3.org" <public-webcrypto@w3.org>
On Mon, Apr 15, 2013 at 11:32 AM, Ryan Sleevi <sleevi@google.com> wrote:

> On Sat, Mar 30, 2013 at 9:52 AM, Mark Watson <watsonm@netflix.com> wrote:
> >
> >
> > On Fri, Mar 29, 2013 at 11:22 AM, Richard Barnes <rbarnes@bbn.com>
> wrote:
> >>
> >>
> >> On Mar 27, 2013, at 9:10 PM, Mark Watson <watsonm@netflix.com> wrote:
> >>
> >> > This may be related to ISSUE-12 and apologies again if this has been
> >> > discussed before - it is coming up now frequently in implementation
> >> > discussions.
> >> >
> >> > In the encrypt/decrypt/sign/verify operations, two AlgorithmIdentifier
> >> > objects are provided as input, one as an explicit parameter and one
> which is
> >> > associated with the Key object (and appears as the Key.algorithm
> attribute).
> >> > Presumably it is an error if the "name" member of the dictionary does
> not
> >> > match (after normalization), though I am not sure if this is clearly
> >> > specified.
> >> >
> >> > In some cases, it is specified that the params member will have
> >> > different types in these two places (I'm assuming that the
> Key.algorithm
> >> > attribute takes the value that was provided to generateKey). For
> example for
> >> > AES-CTR, the params in Key.algorithm contains the key length and
> params in
> >> > encrypt/decrypt contains the IV.
> >> >
> >> > But for other cases things are very unclear. For example, for HMAC,
> the
> >> > same AlgorithmParameters type is used, containing the hash algorithm.
> In
> >> > this case it seems completely redundant to provide the same object
> twice to
> >> > the sign/verify call (once in the method parameters and again in the
> >> > Key.algorithm attribute).
> >> >
> >> > Am I missing something ? Does anyone else find this confusing ?
> >> >
> >> > I think the confusion could be resolved by
> >> > (i) replacing the AlgorithmIdentifier argument to
> >> > sign/verify/encrypt/decrypt with AlgorithmParameters.
> >> > (ii) for HMAC, the params provided to sign/verify must be null, as the
> >> > hash algorithm should have been provided when the Key was
> >> > created/imported/unwrapped
> >>
> >> I agree that it could be made clearer.
> >>
> >> When I was implementing PolyCrypt, my read of the specification was as
> >> follows:
> >> 1. The algorithm provided as a parameter to encrypt() specifies the
> >> encryption (and parameters)
> >> 2. Throw an error if the Key.algorithm.name != algorithm.name
> >>
> >> That is, for the algorithm in the Key, everything besides the name is
> >> ignored.  This seems right to first order, but might be wrong, e.g., for
> >> HMAC, where you might want to compare the hash algorithm as well.
> >
> >
> > It seems ambiguous to me whether the hash algorithm is a property of the
> key
> > or a parameter to the operation. Another source of confusion.
> >
> >>
> >>
> >> I'm leery of removing the algorithm parameter from encrypt(), if only
> >> because it seems really confusing and non-idiomatic.
> >
> >
> > What idiom, and why do you say it's confusing ? The algorithm is a
> property
> > of the key, so it's confusing that I need to re-specify it as a method
> > parameter. That only seems to introduce an unnecessary failure path and
> give
> > the incorrect impression to developer that they have some choice about
> the
> > algorithm here. They don't. It's implicit in the Key.
> >
> >>
> >> I don't think it's terrible to have the algorithm specified in two
> places,
> >> as long as its clear how those two specifications relate to each other
> >
> >
> > It's not clear now. IIUC, anything in the method AlgorithmIdentifier
> that is
> > also a property of the Key must match. Anything else is a method
> parameter.
> >
> > A particularly confusing case is when there are both algorithm and method
> > parameters. For example, suppose a create an AES-CBC key with { name :
> > "AES-CBC", params: { length: 128 } }. Am I supposed to write
> >
> > encrypt( { name: "AES-CBC", { "length" : 128, "iv" : iv } }, ... )
> >
> > ?
>
> No.
>
> This is documented in
>
> https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#aes-cbc
> - the encrypt() operation takes AesCbcParams, which is a dictionary
> only containing a key for IV. generateKey() takes an AesKeyGenParams,
> which is a dictionary containing only a key for IV.
>
> >
> > If I'm allowed to miss out the length here, why is it that it makes
> sense to
> > miss out some of the Key properties and not others (the algorithm name
> > itself) ?
>
> From the start, there has been immense conflict over whether or not we
> would support key tainting. There has been support expressed from most
> of the contributors on this thread, at some point, AGAINST key
> tainting.
>
> In such a scheme, a given key object may be thought of an algorithm
> "family" - whether it be "RSA" or even potentially more specific as
> "RSA-PSS" or "RSA-PKCS#1v1.5"
>
> However, such definitions are not complete definitions from the
> perspective of the security proofs and correctness. For example, one
> should not assume that the hash algorithm for PKCS#1v1.5 is
> interchangeable without affecting the security correctness proofs.
>
> For this reason, because members objected to fully scoping a key's
> usage at the time of creation/import, it was forced to be left to the
> point of instantiating the algorithm.
>
> The only way I see your proposal working (splitting "Algorithm" and
> "Operation" parameters) is if we can fully agree on a workable,
> extensible definition for what separates the two. You've picked AES
> keys, which are perhaps the easiest to conceptualize, but fail to show
> the edge cases. It's also easier to conceptualize because we accepted
> to keep the block cipher mode (CBC, CTR, CMAC, GCM, etc) as a
> *separate* algorithm, rather than as a parameter - a point which took
> several months to coalesce, particularly as it related to ECB/Raw.
>
> I would instead suggest we look at RSA keys - whether PSS, OAEP, or
> PKCS#1v1.5. There are a set of parameters not strictly tied to the key
> *material* (eg: the choice of hash algorithm / MGF), but which do
> ultimately affect whether or not the key is supported (by the
> underlying implementation) and/or whether or not it can be safely
> used.
>
> Perhaps you can make a rough sketch - and I don't mean a formal
> writeup of proposed text - of a definition you see as workable (for
> the current algorithms), along with a simple split.
>
> eg:
>
> AES:
> Mode - New algorithm for each mode (CBC, GCM, CFB, CMAC)
> Per-Key Params (CBC): Length
> Per-Operation Params (CBC): IV
> Per-Key Params (GCM): Length
> Per-Operation Params (GCM): IV, AAD, Tag Length
>
> etc
>
> Just something that puts forward a definition that can actually be
> used - or as a starting point.
>

Here's the summary of the current algorithm and operation parameters that I
circulated earlier:

https://docs.google.com/document/d/1fKtA6U0b_R-kml3qgvdnq-diu3oyDsFbEGKG2AB-tq0/edit?usp=sharing

It's possible that my concerns can be addressed by some things which are
mainly cosmetic. What I'm sure of is that the present situation where the
same AlgorithmIdentifier structure, with different data types for the
params member when used in different methods (generate, sign etc.) is
confusing. I'm sure because of empirical evidence in many emails exchanges
with my colleagues, including those who fully qualify as crypto experts ;-)

I think the simplest concrete solution would be
1) to define a new OperationParameters dictionary, from which the various
dictionaries used with sign, verify, encrypt, decrypt and derive inherit
2) replace the AlgorithmIdentifier parameter to those operations with
OperationParameters
3) decide whether hash is a property of a HMAC key, or an input into an
HMAC operation


>
> Note that the discussion is similar for HMAC. There was some initial
> discussions, raised by Netflix, about the conceptualization of a
> "Generic" key object - that is, a key that is not part of a
> private/public keypair (alternatively, a 'secret' key). The initial
> discussions were regarding treating these keys as simply an opaque
> handle to a series of bytes - that is, no formal algorithm attached to
> them until their use. This is suitable for things like key derivation
> schemes like DH, which yield a shared secret that can then be used,
> either as input to a KDF or (provided there is sufficient entropy), to
> use as something like a MAC key
>
> Under your proposal, it would be necessarily to fully specify the
> intended use of this key material and bind it to a fully specified
> algorithm at time of creation, rather than at use. This is
> particularly interesting for protocols that involve cipher
> negotiations. Note that most cryptographic APIs do NOT place this
> requirement on 'secret'/'generic' keys, and so the implications this
> would have are, quite frankly, not well understood in the three weeks
> since this proposal. If we do adopt it (which I'm not convinced it's
> mature enough to vote on yet), then I think we'd at least have to
> concede this as a point where we're significantly diverging for no
> apparently good reason, and we must be willing to alter the design if
> it turns out to be unworkable in practice.
>

This could be addressed by defining a specific WebCrypto algorithm name for
raw keying material. The only thing you can then do with those kind of Keys
is derive other keys.


>
> Finally, the last argument - and arguably and unquestionably the
> weakest - has to do with trying to encourage some modicum of secure
> practices by providing a check on the usage of keys and key material
> that prevents the accidental misuse (eg: attempting to use an RSA-PSS
> key for RSA-PKCS#1v1.5). This is one of the same issues that arises
> with defaults - the counter-intuitive notion that the more you have
> the implementation try to 'hide' what is happening, the easier you're
> making it for simple programming errors to introduce cataclysmic
> security failures. There is likely a balance that can be struck here,
> but it's a design consideration that has to be built in from the start
> - and we should at least recognize it's something we have now in the
> current specification that we'd be looking at losing.
>

I'm not convinced that the danger of accidentally using an RSA-PSS key for
some RSA-PKCS#1v1.5 operation is any worse than the danger of accidentally
using the wrong RSA-PKCS#1v1.5 key. Should we have the developer assign an
"id" to each key when creating this and then repeat that "id" when using
it, just to check they're using the right one ? Should the algorithm
parameters specified at key creation be repeated when using the key - just
to check it's the right one ? Just checking the algorithm name and nothing
else seems arbitrary.

It's unlikely that such mistakes would result in a system that worked at
all. The mistakes that we can most usefully guard against are those where
the system might appear to work, but in fact has hidden weaknesses, such as
using the same key with different algorithms.

We then have to balance against the confusion caused by the redundant
information (the algorithm name) and the
similar-looking-but-really-very-different data structures
(AlgorithmIdentifier when used for key generation/import vs
AlgorithmIdentifier when used for encrypt/decrypt/sign/verify etc.

...Mark


>
>
> >
> > This could be completely cleaned up by only specifying the "params"
> member
> > in the methods. Specifically by defining an OperationParameters for that
> > thing and derving the operation parameters objects from that. This would
> > provide a clear separation between algorithm and operation parameters.
> >
> > ...Mark
> >
> >>
> >>
> >>
> >> > As a side note, I believe that to generate a HMAC key we need to
> specify
> >> > the key length. At least according to FIPS 198-1 the key, K, can be
> of any
> >> > length. So, either we require in WebCrypto that it is a particular
> length
> >> > (say, the same size as the hash function), or we need a length
> parameter to
> >> > generateKey for HMAC.
> >>
> >> +1 on adding a length parameter.
> >>
> >> --Richard
> >>
> >> >
> >> > ...Mark
> >>
> >
>
Received on Monday, 15 April 2013 19:03:57 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:17:16 UTC