Re: ACTION-22: Key export

Ryan,

First off, thank you. Things are beginning to make more sense because of 
your detailed response. More inline below...

On 8/25/12 1:10 PM, Ryan Sleevi wrote:
> On Fri, Aug 24, 2012 at 7:26 PM, Mitch Zollinger <mzollinger@netflix.com> wrote:
>> On 8/23/12 3:44 AM, Ryan Sleevi wrote:
>>> On Wed, Aug 22, 2012 at 1:23 AM, Mitch Zollinger <mzollinger@netflix.com>
>>> wrote:
>>>> Sorry for the slow response on this issue. I'm currently on business
>>>> travel
>>>> in Asia.
>>>>
>>>> Responses below.
>>>>
>>>>
>>>> On 8/17/12 3:50 AM, Vijay Bharadwaj wrote:
>>>>
>>>> No, I was thinking of authorization and export as separable issues.
>>>>
>>>>
>>>>
>>>> -          You can only see keys that you are authorized for.
>>>>
>>>> -          Of the keys you can see, you can potentially export the
>>>> exportable ones without UI.
>>>>
>>>>
>>>> Ok. This matches my understanding.
>>>>
>>>>
>>>>
>>>>
>>>> Regarding the DH+KDC model, I wonder if this isn’t getting real close to
>>>> a
>>>> high-level API. It feels like it’s a hop and a skip away from a generic
>>>> box/unbox API. This is not to say that it isn’t a worthy goal, just that
>>>> it
>>>> may be hard to generalize to a low-level API.
>>>>
>>>>
>>>> When I first read your response, my initial reaction was actually to
>>>> agree
>>>> with this. If I assume that there is no possibility of protected key
>>>> exchange + key derivation, then I know that if my JS app is compromised,
>>>> the
>>>> session key is exposed. But if a security attack happens (and let's
>>>> assume I
>>>> hear about it!), I *could* actually fall back to using pre-shared keys to
>>>> "recover" my secure session with the device.
>>>>
>>>> But, after a bit more thought, I actually believe that there is a reason
>>>> to
>>>> push for protected key exchange / derivation based on:
>>>> * We have explicitly stated that we want key protection; that is, in some
>>>> instances of keys, the JS is not allowed access to the keying material.
>>>> * We have explicitly stated that we want session keys as the product of
>>>> some
>>>> key exchange mechanism.
>>>> * Taken together, there's no way to satisfy the above two goals without a
>>>> protected key exchange / key derivation, correct?
>>> Probably not as you'd like, but the existing spec does cover this, so
>>> I think it'd be helpful if it was understood why this would be
>>> unacceptable.
>>>
>>> As discussed on the phone call, you could generate a DH key pair with
>>> a KeyGenerator (with the DH private key/value that is "opaque" to
>>> content script, but not necessarily the U-A)
>>
>> Do you have actual pseudo-code you can share? I'm not seeing this as obvious
>> from the spec. Unfortunately, I haven't been able to attend the calls while
>> in Asia / won't be able to attend the calls until I'm back from Asia in a
>> week or so.
>>
>>
>>>    and derive a shared
>>> secret key with a KeyDeriver (passing the peer's DH public value). If
>>> there was a need for more rounds, you could use multiple KeyDerivers,
>>> passing in different Key objects as appropriate. For example, an RFC
>>> 2631 scheme that has a single round to expand the DH shared secret
>>> into an appropriate symmetric key, or an RFC 6189 style exchange that
>>> derived expanded ZRTP Confirm1/Confirm2 into an SRTP session key.
>>
>> Again, some example pseudo-code of what you're proposing would help greatly.
> Ok, here's a rather complete-yet-still-pseudo code of performing X9.42
> / RFC 2631 key agreement. I did X9.42 rather than ZRTP, as ZRTP has
> other parameters (eg: commit hashes) that just add code, but don't
> actually demonstrate the code concept. X9.42 / RFC 2631 takes an
> agreed upon shared secret (the result of DH Phase 2) and expands that
> into keying material suitable for the underlying algorithm.
>
> If anything, the immense complexity of this highlights why I think a
> synchronous-and-worker-only API "MIGHT" be a simpler API...
>
> // Using Diffie-Hellman
> // Obtain DH parameters (eg: from server certificate, from protocol
> exchange, from NIST well-known params)
> var prime = ...;
> var generator = ...;
>
> // Handles completion of the X9.42 expansion/agreement
> function onX942DeriveKeyComplete(keyDeriver) {
>    var finalKey = keyDeriver.result;
>    // You now have a Key object (possibly fully opaque/non-exportable) that
>    // contains the X9.42-agreed key.
> };
>
> // Handles completion of Phase 2 of DH agreement
> function onDHDeriveKeyComplete(keyDeriver) {
>    // zz is the result of the Phase 2 of PKCS #3 and is equivalent to ZZ
>    // as documented in X9.42 - aka the shared secret
>    // ZZ = g ^ (xb * xa) mod p
>    var zz = keyDeriver.result;

Is zz the actual shared secret, or is it an opaque handle at this point?

>
>    // Now expand zz according to X9.42/RFC 2631. Completely hypothetical
>    // specification of params here.
>    var otherInfo = {
>      'keyInfo': { 'algorithm': { 'name': 'AES-CBC', 'params': {
> 'length': '128' } } },
>    };
>
>    var x942 = window.crypto.deriveKey({ 'name': 'X9.42', 'params':
> otherInfo}, zz);
>    x942.addEventListener('oncomplete', onX942DeriveKeyComplete);
>    x942.derive();
> };
>
> function onExportComplete(keyExporter) {
>    // Obtain our public value (eg: an ArrayBuffer)
>    var ourPublic = keyExporter.result;
>
>    // Get peer public value (eg: from certificate, from protocol
> exchange, from pre-provisioned key)
>    var peerPublic = ...;
>
>    // Send peer the generated public value
>
>    var dhDerive = window.crypto.deriveKey({ 'name': 'DH', 'params': {
> 'public': peerPublic } }, 'key': generatedKey);
>    dhDerive.addEventListener('oncomplete', onDeriveKeyComplete);
>    dhDerive.derive();
> };
>
> // Handles completion of Phase 1, aka key generation
> function onGenerateKeyComplete(keyGenerator) {
>    // TODO - asymmetric key pair generation needs to indicate that
> Result is a Pair of Keys, not a single Key.
>    var generatedKey = keyGenerator.result.publicKey;
>
>    var keyExporter = window.crypto.exportKey('json', generatedKey);
>    keyExporter.addEventListener('oncomplete', onExportComplete);
>    keyExporter.export();
> }
>
> var dhKeygen = window.crypto.generateKey({ 'name': 'DH', 'params': {
> 'prime': prime, 'generator': generator} });
> dhKeygen.addEventListener('oncomplete', onGenerateKeyComplete);
>
>
>>
>>>> What if we were to simplify the last proposed mechanism to this instead:
>>>>
>>>> ProtectedKeyExchange kex = ProtectedKeyExchange(/*algorithm*/"foo");
>>>> kex.init(/*algorithm specific params*/);
>>>> while(! kex.done()) {
>>>>     Uint8Array client_data = kex.getNext();
>>>>     /* ...send client_data to server... */
>>>>     /* ...get server_data from server... */
>>>>     kex.step(server_data);
>>>> }
>>>> /* get a handle to the protected key that was exchanged */
>>>> Key key = kex.getKey();
>>>>
>>>> ?
>>>>
>>>> The net effect is that we don't have to declare any sort of first class
>>>> key
>>>> exchange + key derivation concepts at the WebCrypto API level; we simply
>>>> exchange keys where the end result is a handle to a non-exportable key.
>>>>
>>>> This "ProtectedKeyExchange" could simply be thought of as short-hand for
>>>> something like:
>>>>
>>>> KeyExchange kex = KeyExchange(/*algorithm*/"foo", /*exportable*/false);
>>>>
>>>> The difference being that we may want to specify ProtectedKeyExchange as
>>>> a
>>>> simplification. (What if exportable is "true"? Also, the algorithm names
>>>> for
>>>> ProtectedKeyExchange will be different from KeyExchange.) But, that's
>>>> really
>>>> more of a style question.
>>>>
>>>> Would the above better meet the goal of avoiding a "high level API"?
>>>>
>>>>
>>>> Mitch
>>> - If the only purpose of "ProtectedKeyExchange" is to imply a default
>>> value for KeyExchange (/*extractable*/ false), then that's a
>>> non-starter. The implementation overhead of bindings for that,
>>> especially for what is nominally just a parameter value, would not be
>>> acceptable.
>>
>> There is more to it than that: the key exchange under the covers is
>> functionally / conceptually distinct from the generic KeyExchange( bool
>> extractable ) case.
>>
>> By way of example, let's say that I'm doing a "signed DH exchange" (yes, I'm
>> inventing an implementation for the example and trying to inform the API
>> based on this synthetic protected exchange, but this is something similar to
>> what we have now & will need in WebCrypto) for the ProtectedKeyExchange, but
>> just a generic DH exchange for KeyExchange. In this example, I cannot create
>> a KeyExchange object using the "Signed DH" algorithm; that can only be
>> created for a ProtectedKeyExchange. The other possibility is to allow
>> "Signed DH" key exchange algorithm only when the "exportable" boolean is set
>> to false. I would be ok with that, but stylistically it feels less correct.
> The latter is, I believe, more consistent with existing APIs, but I
> can understand the "code smell".
>
> Understandably, we're in a place where we're no longer talking about
> existing, standards-oriented algorithms, but things that are almost
> certainly going in to the realm of algorithms that are specific to
> certain user agents or implementations. Unless, of course, you simply
> mean that "ProtectedKeyExchange" means no intermediate key material is
> available to the content script - at which point, I think we've
> already got that sufficiently covered.

That's what I meant. The above proposal was one way to skin that cat, 
where I was going for simplicity and extensibility.

>
> Again, It seems that ProtectedKeyExchange's purpose is purely to serve
> as syntactic sugar for a functionality boundary / default parameter.
> If I understand your proposal correctly, ProtectedKeyExchange simply
> means the client application will never be able to access the keying
> material that results. Is that correct?

Yes.

> Am I also understanding that
> this is being proposed as an OPTIONAL / MAY (not even a normative RFC
> SHOULD) - eg: not all user agents need to support
> ProtectedKeyExchange?

I don't want to add the ProtectedKeyExchange if we can meet the intended 
goals of a multi-step key exchange / derivation where no keying material 
created during the different phases is visible to the script code at any 
time.

>
> My quick take on this, admittedly having not fully considered the
> ramifications, is that it is reasonable to have certain algorithms /
> operations that do not support exporting the (generated, derived,
> imported) keys, that result from the existing interfaces. Further, if
> we are to ever consider the possibility of secure elements, then
> regardless of how the user agent provides interaction with them, it's
> quite likely that a key may be generated on such a secure element that
> is immediately and perpetually unexportable. Unlike how I understand
> your PKE scenario (in which the web application is explicitly
> requesting PKE), this would be a situation where it's perhaps the
> result of a user decision (or by the user agent), and thus the web
> application is completely unaware of the fact that a PKE has happened.
>
> Normatively, this would be something more spec-y, but would say:
> If the user requests an operation+algorithm with exportable=true, and
> that request cannot be fulfilled, the operation should fail and the
> onerror event should be called.
>
> Thus, you could have your custom algorithm, such as
> NetflixProtectedKeyExchangePhase1
> NetflixProtectedKeyExchangePhase2
> NetflixProtectedKeyExchangePhase3
>
> Where each phase had some Result object (including possibly an opaque
> series of bytes / ArrayBufferView, if that's how you wished to spec
> it) that had to be passed to the peer before the next phase.
>
> Or you could have a single algorithm, which just differentiated based
> on the Params dict - eg:
>
> enum NetflixPhase {
>    "MEK-exchange",
>    "KEK-exchange",
>    "KEK-unwrap",
>    "KEK-secure-proof",
> };
>
> dictionary NetflixProtectedKeyExchangeParams : AlgorithmParams {
>    NetflixPhase currentPhase;
>    ArrayBufferView opaqueBytes;
> };
>
> Where you just repeatedly created KeyDeriver objects for each of the
> phases, as appropriate, until you ended up with the "final" Key.

I believe I understand what you're proposing & the code would mimic very 
closely what you described above with X9.42 / RFC 2631 key agreement.

> The end result is that such a ProtectedKeyExchange is specific to your
> user-agent, and thus can be specified accordingly.
>
> If you wanted to standardize some sort of generic exchange for working
> with say, devices which have some embedded ID (eg: the TVs mentioned
> previously), you could absolutely do so - whether it be through
> contracts with vendors or through convincing the W3C that there is
> interest in doing so and that it's relevant and consistent with the
> W3C's goals.
>
> I'm by no means trying to take any sort of pejorative stance on such
> approaches, but what I am trying to highlight is an opinion that I
> believe such schemes are inherently specific to a certain use case,
> and thus not within the core realm of "Something everyone would need
> to do anything useful", which is sort of where I'd like to keep this
> API for now in order to be able to make any forward progress on it.
>
> It's tempting to try and describe every possible algorithm, but then I
> fear we'd end up with a document the size of PKCS#11 - hundreds of
> pages trying to describe the exact behaviours of every algorithm, and
> even IT left things underspecified.

Clearly that's not our intent.

>>
>>> - I'm not sure how a "KeyExchange" interface avoids having to declare
>>> a first class key exchange. It seems the very presence of an interface
>>> for key exchange, as proposed, inherently makes it 'first class'. Are
>>> you saying "You avoid having to specify the algorithm?" If so, I think
>>> that would also be a non-starter, as it's inherently not implementable
>>> by open, standards compliant browsers. If you do specify the
>>> algorithm, then I'm confident it's something we could express as a
>>> series of primitive steps without having to resort to opaque "here's
>>> some blob" exchanges.
>>
>> I believe that we can create a generic "low level" API that is algorithm
>> agnostic. Further, I believe that this should be the approach because it
>> allows implementers the freedom to do what they need to do & be creative ;)
> My concern is that I think you can already accomplish this, without
> requiring specific API additions. My further concern is that the API
> extensions proposed so far are, I believe, specific to your problem,
> and thus not generic enough to be useful.
>
> I can appreciate a concern that the API makes a certain use case hard
> - a valid concern that should absolutely be considered. But I'm also
> concerned about proposing APIs that are specific to a particular need
> that are not, perhaps, generic enough.
>
>> Locking this down to only Diffie-Hellman I believe is incorrect.
>> Diffie-Hellman is great, we use it all the time, but we shouldn't disallow
>> things like key unwrapping.
> I believe the underlying API is independent of any specific algorithm,
> by virtue of the same patterns being prevalent in other APIs and that
> they permit what I understand you to desire. I think it may just be
> some misunderstanding between us about why I believe that need is
> already filled in a (generic) way.
>
>> To reiterate: if we want to support key exchange of protected keys, the API
>> needs to treat this transaction as a first class API. The "exportable" flag
>> is insufficient for the task, unless we just dictate implementation behavior
>> that in the protected case we throw an error or some such developer
>> unfriendly thing.
> If a developer requests certain behaviour, and it's not supported (by
> policy, by underlying implementation, by design), I think it should
> cause an error.
>
> I'm honestly unsure whether or not it's reasonable to require that
> implementations MUST support key export *for the key algorithms
> defined in this spec* IF the user requests it. We could put that
> requirement in, but that will certainly immediately preclude a class
> of operations (eg: fully 'outsourcing' the crypto to a secure
> element), which means that the API cannot be conformantly implemented,
> even if everything ELSE could be supported.
>
> It's a reasonable concern, but I do not believe it necessitates the
> creation of Transaction objects - I think that's the KeyDerivation
> equivalent of a JOSE Message Signer - a combination of a series of
> low-level primitives and phases into one, cogently organized, logical
> result. You can polyfill that using the API proposed today, and
> nothing prevents that polyfilled API for being the basis of future,
> high-level standardization.
>
>>
>>> - More fundamentally, I think I have trouble with the idea of key
>>> exchange as a GSS-API like mechanism, which this appears to
>>> effectively be.
>>
>> You have me at a technical standards disadvantage; I had to go Google
>> GSS-API ;)
> Also, SASL, which I suspect at a protocol level is equally similar as
> the ProtectedKeyExchange proposed.
>
>>
>>>    The concept of these opaque bytes going through the
>>> application is, on some deep API level, a bit troubling. The fact that
>>> no such equivalent exists in any of the standards or APIs that I think
>>> are worth considering (PKCS#11 and CDSA as 'true standards',
>>> CryptoAPI, CNG, OpenSSL, BSafe - as "standard" APIs, to name a few) I
>>> think also highlights the specialist nature of this.
>>
>> I would like to think that this is a result of the work we're doing being
>> cutting edge. The fact that we don't trust all script code is a fairly
>> compelling reason to rethink old APIs, IMO.
> I can appreciate the position, but I don't think this is a case of
> "not cutting edge enough," but perhaps simply a miscommunication on
> why the needs (hopefully) are already met under the current API and
> how they've been successfully met over the past several decades.
>
>>
>>> While I understand this may be how you're currently doing things, I'm
>>> not sure this is something that should be supported - or at least, be
>>> considered as something under the 'optional' category that we wait to
>>> address until after we make sure the base level primitives are
>>> acceptable to everyone and implementable.
>>
>> Again, I would argue that protected key exchange -- in general terms --
>> should be in scope. Are you arguing against this as a high level objective
>> or is it more that this is considered a "Netflix proprietary" approach?
> So, there's two meanings of protected key exchange here
> - Protected from content script, but the content script is allowed to
> 'drive' the operation. I think this need is already met (as
> demonstrated by the pseudo-code)

This is what we're aiming for.

> - Protected from the user agent (as in, secure element provisioning),
> which I think is, at best, secondary features, but more likely out of
> scope in general.

I get this point. It's still somewhat unclear where this goal is 
incompatible with the "protected from content script" goal given that 
the underlying implementation could call out to a HW element. But that's 
more of a curiosity question.

>
> What I really, really, really want to avoid is trying to do something
> like "JavaScript GlobalPlatform", and I think the moment you start
> talking about "secure provisioning" or "protected key exchange",
> you've immediately entered such terminology. As discussed during
> chartering and in the past, such conversations immediately turn specs
> into multi-year efforts that will inevitably suffer and, for most
> practical/novel uses, be woefully complex and utterly unusable.

Nope. We're just trying to solve a problem in a pragmatic way while 
keeping the user / app as secure as we reasonably can.

> I also think it begins to touch into the 'high-level' concepts.
>
> Part of the reason that operations like key derivation are split into
> phases is because it's not at all uncommon for different algorithms to
> emerge that combine them in different ways. For example, X9.46 builds
> upon the DH phase 1 and phase 2, effectively adding a 'phase 3' of key
> expansion. However, ZRTP goes a different route, taking the DH
> Phase1/Phase2, but then adding in commits and the Confirm1/Confirm2
> phases. By de-composing these multi-step derivations into phases, we
> readily permit polyfill operations - for example, a UA could *ONLY*
> support Phase1/Phase2, and an application could polyfill in X9.46/ZRTP
> support as needed, since all of the primitives (hashing, macing) are
> there.
>
>>
>>> Fundamentally, I recognize that this is closely related to key
>>> wrap/unwrap, which are not yet specified, due to first needing to make
>>> sure that key import/export are the correct APIs, due to the close
>>> relationship between the two. I understand that key transport
>>> (import/export) and key agreement (which I believe is already
>>> accomodated) are part of our primary API features. And I can
>>> appreciate the desire for 'secure provisioning' of keys. However, my
>>> concern is that the practical use cases for such an API are more
>>> closely related to secure elements, smart cards, or other device
>>> specific behaviours, at least as I understand your proposal.
>>
>> Not quite right. In fact, we're interested in protected key exchange which
>> may never involve pre-provisioned keys, crypto hardware or smart cards at
>> all.
> In which case, your application would/should never request the
> 'exportable' flag, and your problem should be solved.

I believe this is one of the key points that I would like to make 
certain we agree on. Would I be correct in taking the above comment and 
expanding it in more detail:
* Our application would never request "exportable = true".
* If our application ever did request "exportable = true" the underlying 
implementation would throw an error.
* Every phase in our key exchange + session key derivation, including 
the final stage, would have a result which was an opaque handle to the 
underlying key data, inaccessible to the script code.
?

>
>>
>>> Similar to the aforementioned APIs, I would rather expose the
>>> primitives (eg: DH phase 1, DH phase 2, ZRTP part 1, ZRTP part 2),
>>> then trying to describe an entire flow, with all of the
>>> protocol-specific parameters (eg: all the data that flows into an RFC
>>> 6189 3.1.1 exchange). Trying to define an API for an entire ZRTP flow,
>>> as an example, is something that I think is the essential definition
>>> of high-level.
>>
>> Are you saying that we should not have a low level "Key Exchange" API which
>> is agnostic to algorithm? I would propose that this is exactly what we
>> should aim for and that Diffie-Hellman should be a SUGGESTED algorithm
>> rather than making it first class to the exclusion of other key exchange
>> methods, including perhaps key wrapping / unwrapping. Key wrapping, given
>> the proper API design, is something that an implementer can choose to do
>> with version 1.0 of the API without the specification directly addressing
>> that use case.
> We as a work-group previously identified DH as first-class (along with
> ECDH, which I explained on the previous call why it was not yet
> spec'd).
>
> However, as described elsewhere, it by no means precludes any other
> form of Key Exchange - protected or not - regardless of whether they
> build upon DH or some entirely different crypto primitive.
>
> While I understandably don't know much about Netflix's specific
> implementation, I do think that you could suitably accomplish what you
> desire with the current API. I would expect that the concerns, if any
> remain, would most likely be centered around 'simplicity' (high-level,
> opaque) vs 'complexity' (low-level, phases), and trying to make sure
> the API was a sufficient balance, while still respecting our low-level
> API ambitions.
>
> I think an opaque Key Exchange, as proposed, is ideologically
> equivalent to the "Box" and "Unbox" primitives we discussed when
> scoping our work. I don't think there is anything inherently flawed in
> them, but I think it's a high-level API that is full of strong
> politics and preferences, much like trying to decide (WebIDL, JWK, or
> ASN.1 - or all of the above).
>
>> We ran into this same sort of issue with the "Certificate" versus "generic
>> auth token" debate previously. I realize that we want things to be clear as
>> possible to implementers to get WebCrypto boot strapped, but I would not
>> want to exclude interesting use cases & implementations because the APIs are
>> too restrictive. Of course, I'm new to standards & the W3C so my philosophy
>> may simply be misinformed.
>>
>> Looking forward to your response.
>>
>> Mitch
>>
>>
>>> Regards,
>>> Ryan
>>>
>>>>
>>>> From: Mitch Zollinger [mailto:mzollinger@netflix.com]
>>>> Sent: Wednesday, August 15, 2012 10:28 PM
>>>> To: Vijay Bharadwaj
>>>> Cc: public-webcrypto@w3.org
>>>> Subject: Re: ACTION-22: Key export
>>>>
>>>>
>>>>
>>>> On 8/14/12 9:38 AM, Vijay Bharadwaj wrote:
>>>>
>>>> Mitch> As described during our f2f: we would like to use a KDF on a
>>>> Diffie-Hellman negotiated shared secret to create a session key (or
>>>> session
>>>> keys) where the raw session key is never allowed to be accessed by the
>>>> webapp.
>>>>
>>>>
>>>> I agree with the aim, but as discussed earlier I don’t know of a way to
>>>> make
>>>> this work in general. In general, the output of a KDF is “just bytes” as
>>>> far
>>>> as the algorithm is concerned, so it’s hard to see a way to pick some
>>>> bytes
>>>> from that output and designate them as “special” (i.e. key material). I
>>>> suppose this case could be made to work if we applied additional
>>>> restrictions, but that may require a different API that takes in key or
>>>> secret handles rather than an ArrayBuffer.
>>>>
>>>>
>>>> Exactly. As described in the Netflix use case document, the idea is that
>>>> the
>>>> shared secret created by a DH exchange is one which the app is never
>>>> allowed
>>>> to access. There are clearly some pitfalls of implementation in this
>>>> model;
>>>> if a generic Diffie-Hellman was compatible with this DH+KDC model of key
>>>> creation, the server would not know the difference between a client which
>>>> was using DH with exportable shared secret and the special DH+KDC model.
>>>>
>>>> This requires a bit more design; there are ways of doing this that depend
>>>> on
>>>> other types of attestation (imagine that the underlying implementation
>>>> created a signature on the DH public component sent by the client to the
>>>> server only when the special DH+KDC model was invoked, for example), but
>>>> in
>>>> general, I still believe that the API can allow for this type of exchange
>>>> without even specifying the actual algorithms.
>>>>
>>>> ProtectedKeyExchange kex = KeyExchange("KeyExchange Algorithm Foo");
>>>> Uint8Array client_pub = kex.getPublic();
>>>> /* ...send client_pub to server... */
>>>> /* ...get server_pub from server... */
>>>> /* complete exchange, created keying material precursor inside of kex */
>>>> kex.exchange(server_pub);
>>>> /* get handle to shared secret */
>>>> Handle handle = kex.getSharedSecret();
>>>> /* derive a session key */
>>>> Key key = Key.create(KDC.get("MyKDCAlgorithm"), handle);
>>>>
>>>> I know in our offline conversation, you brought up some good points
>>>> around
>>>> FIPS compliance & only using the shared secret for a single key
>>>> derivation.
>>>> Despite that cautionary advice, is there something that would prevent us
>>>> from accomplishing the above?
>>>>
>>>>
>>>>
>>>>
>>>> Mitch> In terms of expected user interaction in a browser, is there some
>>>> idea of a key store password, where the user has to enter the password to
>>>> explicitly export a wrapped key? Or is this a click-through dialog box
>>>> where
>>>> the user simply clicks "Ok" and the webapp gains access to the raw key?
>>>>
>>>>
>>>>
>>>> I was imagining a situation where this is determined by the key itself.
>>>> Most
>>>> exportable keys would be exported with no user interaction at all, and
>>>> non-exportable keys would just fail. Keys stored on smart cards for
>>>> example
>>>> may require UI but that is imposed by the card not the UA.
>>>>
>>>>
>>>> Ok. I was getting this mixed up with Ryan's & Mark's conversation around
>>>> domain bound vs. domain authorized sites. With "domain authorization"
>>>> though, in your model, if the site that created the key created it with
>>>> exportable=true, then the second site could just export the key without
>>>> any
>>>> user interaction? (I don't think this is what you meant.)
>>>>
>>>> Mitch
>>>>
>>>>
>>>>
>>>>
>>>> From: Mitch Zollinger [mailto:mzollinger@netflix.com]
>>>> Sent: Monday, August 13, 2012 5:52 PM
>>>> To: public-webcrypto@w3.org
>>>> Subject: Re: ACTION-22: Key export
>>>>
>>>>
>>>>
>>>> On 8/13/2012 7:54 AM, Vijay Bharadwaj wrote:
>>>>
>>>>
>>>> We’ve gone around on this a few times, including at the f2f, so here is a
>>>> concrete proposal. I’m trying to find a balance between extensibility and
>>>> not loading up the API with a bunch of stuff, so feedback is welcome.
>>>>
>>>>
>>>>
>>>> I see the following use cases for key import/export:
>>>>
>>>> -          Create session key object from derived key bytes (using either
>>>> KDF or secret agreement): this would require raw key import
>>>>
>>>>
>>>> I would add:
>>>>    - Create session key object from derived key bytes, using KDF of
>>>> underlying
>>>> keying material, which does not allow raw key import / export.
>>>>
>>>> As described during our f2f: we would like to use a KDF on a
>>>> Diffie-Hellman
>>>> negotiated shared secret to create a session key (or session keys) where
>>>> the
>>>> raw session key is never allowed to be accessed by the webapp.
>>>>
>>>>
>>>>
>>>> -          Create key object from public key received from peer (for
>>>> asymmetric encryption or signature verification): this would require
>>>> public
>>>> key import, where the public key is likely ASN.1 encoded in many apps
>>>>
>>>> -          Export/import (wrapped) content encryption key for data
>>>> encryption: this could be just the wrapped key or something like a PKCS#7
>>>> RecipientInfo (which is ASN.1 encoded). Import/export requires a handle
>>>> to
>>>> the wrapping key.
>>>>
>>>> -          Export/import of private keys for distribution, with formats
>>>> like
>>>> PKCS#8.
>>>>
>>>>
>>>>
>>>>   From an API perspective, supporting export seems to be straightforward.
>>>> The
>>>> Key object needs an export (or wrap) method, which takes a target format
>>>> and
>>>> potentially a wrapping key as parameters.
>>>>
>>>>
>>>> In terms of expected user interaction in a browser, is there some idea of
>>>> a
>>>> key store password, where the user has to enter the password to
>>>> explicitly
>>>> export a wrapped key? Or is this a click-through dialog box where the
>>>> user
>>>> simply clicks "Ok" and the webapp gains access to the raw key?
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> It seems to me there are two API models to support import. Either have an
>>>> ability to create an empty Key object, then invoke an import method on
>>>> that
>>>> object, or make it part of the construction of the Key object. I propose
>>>> the
>>>> latter, so that we don’t complicate the state model of the Key object.
>>>>
>>>>
>>>>
>>>> So in WebIDL,
>>>>
>>>>
>>>>
>>>> interface Crypto {
>>>>
>>>>
>>>>
>>>> … other stuff …
>>>>
>>>>
>>>>
>>>> KeyGenerator importKey(DOMString format, ArrayBuffer keyBlob, optional
>>>> Key
>>>> wrappingKey=null);
>>>>
>>>> }
>>>>
>>>>
>>>>
>>>> interface Key {
>>>>
>>>>
>>>>
>>>> … other stuff …
>>>>
>>>>
>>>>
>>>> KeyExporter exportKey(DOMString format, optional Key wrappingKey=null);
>>>>
>>>> }
>>>>
>>>>
>>>>
>>>> Where KeyExporter is exactly like KeyGenerator but returns a value
>>>> instead
>>>> of a Key object.
>>>>
>>>>
>>>>
>>>> One big issue is what key formats should be supported. For symmetric keys
>>>> it
>>>> makes sense to support a raw format, but for asymmetric keys things are
>>>> more
>>>> complex. As has been brought up on other threads, many commonly-used
>>>> formats
>>>> are ASN.1 based and so it seems like supporting that would really help
>>>> interoperability. However, I’d like to avoid a repeat of the mandatory
>>>> algorithms discussion. Any ideas here are welcome.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>

Received on Sunday, 26 August 2012 08:07:25 UTC