Re: ACTION-22: Key export

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;

  // 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.

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? 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?

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.

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.

>
>
>>
>> - 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)
- 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.

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.

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.

>
>
>>
>> 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 Saturday, 25 August 2012 04:10:48 UTC