- From: Mark Watson <watsonm@netflix.com>
- Date: Fri, 25 Apr 2014 16:19:10 -0700
- To: Ryan Sleevi <sleevi@google.com>
- Cc: Matt Miller <mamille2@cisco.com>, "public-webcrypto-comments@w3.org" <public-webcrypto-comments@w3.org>
- Message-ID: <CAEnTvdAt93oHXk6YDFD8ETd+5CUQAtgcrJ6eY2=3DEtoTFR20g@mail.gmail.com>
On Fri, Apr 25, 2014 at 3:44 PM, Ryan Sleevi <sleevi@google.com> wrote: > > On Thu, Apr 24, 2014 at 1:38 PM, Matt Miller <mamille2@cisco.com> wrote: > >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA512 >> >> Hello all, >> >> Below are my comments after reading the current draft of WebCryptoAPI. >> I apologize if I've repeated anything stated before; I've not really >> followed the discussion leading up to this document's current state. >> >> >> >> Potential Defects: >> ============================================== >> >> The definition for "PBKDF2" includes an editor note that does not >> appear to be relevant. It discusses a "password" field that is not >> present in any of the immediately surrounding content. >> >> > Thanks for highlighting. Will fix. > > >> >> Comments: >> ============================================== >> >> Key Storage/Retrieval >> - ---------------------------------------------- >> >> The draft discusses "retrieving keys" -- distinct from import/unwrap >> - -- but does not in any other way indicate how this is dealt with. It >> would help to explicitly mention that key storage/retrieval can be >> done with mechanisms that support structured cloning, such as IndexedDB. >> >> > Is there a particular section you have a concern of? The only mention of > this is in Section 4.4 of the "out of scope". > > >> >> KeyPairs and Extractability >> - ---------------------------------------------- >> >> Assuming that when generateKey returns a KeyPair that the public key >> is always extractable, this should be explicitly stated somewhere >> separate from the individually registered algorithms. At a minimum, >> this ought to be stated in § 18.3. "Defining an Algorithm", but it >> could also be helpful for have it stated at or around § 14.3.6. "The >> generateKey method" from the perspective of an API user. >> >> > I don't agree with this. I've tried very hard to specifically avoid > listing algorithm-specific concerns in generic sections. > > >> >> "Defining an algorithm" Guidelines >> - ---------------------------------------------- >> >> If the to-be-defined algorithm supports the "importKey" operation, the >> definition ought to clearly specify how [extractable] applies. > > >> Examples >> - ---------------------------------------------- >> >> It would be nice to a somewhat non-trivial deriveKey example. For my >> own edification, I put together a mythical example (included below) to >> see if I'm understanding the API interactions correctly. And, please, >> correct my misconceptions of how the API works if my example has >> egregious errors. >> >> Key Lifetimes >> - ---------------------------------------------- >> >> I suspect this is controversial. It would be nice if a generated Key >> could have some sort of lifetime that the user agent enforces. At a >> minimum, I would highly desire the ability to specify that a Key >> should not be used for more than a browser session (similar to >> sessionStorage), but would value having a fixed expiration date/time >> or a certain amount of time after generateKey's promise is fulfilled. >> >> I realize that this can complicate things (e.g., how does this >> interact with importKey?), and can live with some restrictions (e.g., >> limited-life Keys are never extractable). I think it's also >> acceptable for the lifetime to be tied to just the private Key of a >> KeyPair, if it helps simplify things at all. >> >> > Yeah, controversial. WebCrypto provides no statements about all about Key > Storage - this is very important, least of all for its security concerns. > > You already have the ability to specify that a Key should not be used more > than a browser session - don't persist it anywhere! > > I disagree with the premise that there's any security benefits to be had > here - it's fully in the control of the site author to control the lifetime > of their key, with either method. The proposal you make provides some > syntactic sugar, but notably complicates things - including forcing > WebCrypto to make explicit statements about Key Storage that simply cannot > or should not be made. > > >> >> Thank you, >> >> - - m&m >> >> Matt Miller < mamille2@cisco.com > >> Cisco Systems, Inc. >> >> - -----BEGIN EXAMPLE----- >> >> // Agree to a session key with another user >> var promise, >> us = {}, >> them = {}, >> sessionKey = null; >> >> // helper for prefixing data with a length encoding >> function __UINT32(value) { >> var output = new Uint8Array([ >> (value >>> 24) & 0xff, >> (value >>> 16) & 0xff, >> (value >>> 8) & 0xff, >> value & 0xff >> ]); >> } >> >> // Generate an EC Key for ECDH >> var params = { >> name: "ECDH", >> namedCurve: "P-256" >> }; >> promise = window.crypto.subtle.generateKey(params, >> false, >> [ "deriveKey" ]); >> promise = promise.then(function (keypair) { >> // remember the generated key for right now >> us.pivateKey = keypair.privateKey; >> us.publicKey = keypair.publicKey; >> >> // set our identifier >> var ident = new TextEncoding("utf-8").encode("me@example.com"); >> us.info = new Uint8Array(4 + ident.byteLength); >> us.info.set(__UINT32(ident.byteLength)); >> us.info.set(ident, 4); >> >> // export public key as JWK >> return window.crypto.subtle.exportKey("jwk", us.publicKey); >> }); >> >> promise = promise.then(function(jwk) { >> // exchange public keys with 'them'; >> // returns a promise with the other user's public key, >> // it could use XMLHttpRequest or WebSocket for the actual exchnage >> return exchangePeerInfo({ >> publicKey: jwk, >> info: us.info >> }); >> }); >> >> promise = promise.then(function (other) { >> them = other; >> >> // import the key >> return window.crypto.subtle.importKey("jwk", >> them.key, >> { name: "ECDH" }, >> true, >> [ "deriveBits" ]); >> }); >> >> promise = promise.then(function (theirKey) { >> // remember their Key object >> them.publicKey = theirKey; >> >> // generate the shared secret "Key" >> var params = { >> name: "ECDH", >> public: their.publicKey >> }; >> >> return window.crypto.subtle.deriveKey(params, >> us.privateKey, >> { name: "CONCAT" }, >> false, >> [ "deriveKey" ]); >> }); >> > > Concat only supports deriveBits, as currently specified. > > Filed https://www.w3.org/Bugs/Public/show_bug.cgi?id=25468 > As I have noted in the bug, this is a mis-understanding. There is no "derive key" operation. The deriveBits and deriveKey methods both refer to the "derive bits" operation. If an algorithm supports that it will work with both deriveBits and deriveKey. This is because the difference between those two methods is in whether the generated keying material is passed to the import operation of the target *derived key algorithm*, or not. This could be (generally is) a completely separate algorithm from the one doing the deriving. So there is no point in distinguishing the two methods from the derivation algorithm point of view. I have proposed some time ago that we make this distinction between methods and operations clearer (https://www.w3.org/Bugs/Public/show_bug.cgi?id=24827), but so far noone has commented on this. It seems to be a repeated source of confusion. ...Mark > > >> >> promise = promise.then(function (secret) { >> // construct the algorithmId UINT32(algorithm.length) || algorithm >> var algName = new TextEncoder("utf-8").encode("A128GCM"); >> var algId = new Uint8Array(4 + algName.byteLength); >> algId.set(__UINT32(algName.byteLength)); >> algId.set(algName, 4); >> >> var params = { >> name: "CONCAT", >> hash: "SHA-256", >> algorithmsId: algId, >> partyUInfo: us.info, >> partyVInfo: them.info >> }; >> >> var derived = { >> name: "AES-GCM", >> length: 128 >> }; >> return window.crypto.subtle.deriveKey(params, >> secret, >> derived, >> false, >> [ "encrypt", "decrypt" ]); >> }); >> >> > The above certainly strikes me as somewhat dangerous (re-using the same > key for encryption and decryption). I would presume you would be generating > separate keys here - an encryption key that uses { partyUInfo: us.info, > partyVInfo: them.info }, and a decryption key that uses { partyUInfo: > them.info, partyVInfo: us.info } > > Otherwise, yes, that looks correct. >
Received on Friday, 25 April 2014 23:19:39 UTC