- From: Ryan Sleevi <sleevi@google.com>
- Date: Mon, 15 Apr 2013 11:32:59 -0700
- To: Mark Watson <watsonm@netflix.com>
- Cc: Richard Barnes <rbarnes@bbn.com>, "public-webcrypto@w3.org" <public-webcrypto@w3.org>
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. 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. 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. > > 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 18:33:27 UTC