RE: New Editor's Draft

I agree with Arun that we should support key neutering of some sort.

Keys are in fact significantly expensive objects to set up. For example, keys in secure elements need a construct to convey PIN caching lifetime, while AES and HMAC keys require fairly expensive key expansion to be done up front. So it is useful to have a Key object that can last across operations for an application-controlled amount of time. This seems to necessitate a destroy or neuter operation for keys.

One may argue that this is not what WebCrypto key objects are for; that these are very lightweight objects that are unburdened with such semantics, and therefore should be treated as more disposable. The problem is that we would then need a different construct to hang the above semantics off of; they are too important to performance and possibly UX. We don't have any other object to serve this purpose, so it seems simpler just to do it with Key.

Did you have an alternative construct in mind to serve as a "key context holder" in the above examples?

-----Original Message-----
From: Ryan Sleevi [mailto:sleevi@google.com] 
Sent: Thursday, August 9, 2012 2:08 PM
To: Arun Ranganathan
Cc: public-webcrypto@w3.org; GALINDO Virginie; Wan-Teh Chang; David Dahl; Arun Ranganathan; Wendy Seltzer; Harry Halpin
Subject: Re: New Editor's Draft

On Thu, Aug 9, 2012 at 1:50 PM, Arun Ranganathan <aranganathan@mozilla.com> wrote:
> On Aug 9, 2012, at 3:42 PM, Ryan Sleevi wrote:
>
>> On Thu, Aug 9, 2012 at 12:29 PM, Arun Ranganathan 
>> <aranganathan@mozilla.com> wrote:
>>> Ryan,
>>>
>>> A few comments and observations based on the latest Editor's draft:
>>>
>>> 1. You raise the issue (within an Editor's Note) about CryptoOperation being clonable or transferable.  It would seem to me that CryptoOperation objects are "readonly" objects, which suggests that there's no point invalidating them on the sending side.  It may be possible for the implementation to share data between two threads anyway.
>>>
>>> The Key object, a readonly attribute of the CryptoOperation, *should* be close-able.  This ties into Issue 16 (https://www.w3.org/2012/webcrypto/track/issues/16).  Additionally, if we think of the Key object as a sort of special-case file, we may want to crib some of the semantics of Blob, which is close-able.  I think my vote is for"Application Semantics" *and* "Implementation Semantics."  We can have a lifetime stipulation on Keys, as well as a close().  I'm not sure what that lifetime should be exactly, but this is something we should discuss.  I wonder if Keys should last past a microtask checkpoint.
>>>
>>> Of course, having both an init() and a close() is unusual, but I 
>>> think I can stomach it :)
>>
>> If Key were simply a DOMString (referencing some identifier), would 
>> these same concerns apply?
>
>
> I still think so.
>
>
>> My thinking of the Key object is that it's really just a lightweight 
>> property bag - more expressible than a DOMString, but lighter weight 
>> than a File - more akin to a Blob URI
>> (eg: DOMString) than the Blob itself.
>>
>
> A Blob URI can be revoked.  Do you disagree that we should be able to revoke a Key?  In fact, a Blob URI can be revoked by default (autoRevoke is now true by default).
>
>
>> Of course, I'm not sure the best way to prose this concept up, or if 
>> it's the right approach, so I definitely agree more discussion re:
>> ISSUE-16 is good.
>
>
> Yes, programmatic revocation of objects in JS is sticky.  If we can arrive at:
>
> 1. A safe implementation default which includes an application 
> semantics default AND 2. An optional application semantics mechanism 
> that works in addition to 1. above then
>
> that's probably good.  This is like autoRevoke and URL.revokeObjectURL.

At a terminology level, "revoke" is going to be problematic, since "revoking keys" often means a very different thing than I think you mean here.

As I understand it, revocation is only meant for certain objects that may consume significant resources. I'm not yet convinced Key (for any sane implementation) fits those criteria, at least not from the perspective of JS, which is why I have trouble understanding the necessity.

I think this may be an open issue that will require implementation feedback to see if there is a perf bottleneck that /must/ be solved at the application side. I think the only concern where this even becomes remotely meaningful is for smart cards / secure elements, and since I don't think the first implementations will even be supporting those, I'm sort of hesitant to add complexity for them.

>
>>
>>>
>>> 2. Is it worth overloading processData to take a Blob argument?  And, should we allow "result" to return a Blob argument?  This would then mean, of course, that in order to process a "payload" you'd have to read* it as a certain type.  Which may be overly complex, but it does allow us to work at the level of more things other than ArrayBuffers.
>>
>> I think this question is related to the concerns raised in ISSUE-18.
>
>
> Indeed!
>
>
>>
>> Perhaps I've misunderstood the File API spec, but my concern with 
>> taking a Blob is that the Blob, AIUI, has no defined canonical format 
>> (hence the "readAs" methods). In particular, it opens up the 
>> possibility for lossy transformations (due to creating a Blob from 
>> DOMStrings).
>
>
> No, your understanding is spot-on.  A Blob has no canonical format, and *can* result in lossy transformations (notably, forcing an enctype on a stream of bytes and reading them as a string may result in garbled characters, by design).  But, that looseness is now at the programmer's behest -- he/she can read as a string now, or anything else.
>
> Of course, the only way to guarantee lossless-ness is an ArrayBuffer, which may mean my brief flirtation with allowing Blobs as both payloads and as results may be over.
>
>
>>
>>>
>>> 3. We may wish to define init() in terms of the lifetime of a Key.  How we define init() might be useful for expiration questions.
>>
>> I'm not sure I understand this comment. Were you talking init() on a 
>> Key object (as described in point 1), or init() on the 
>> CryptoOperation object? If the latter, then I'm definitely confused.
>
> In fact, I was referring to the CryptoOperation object, which is the only place where init() is defined.  What I meant was something like this:
>
> 1. Developer calls init() and thus initiates an asynchronous cryptographic operation.
>
> 2. The Key affiliated with this operation, if any, now has a ticking clock associated with it.  Or perhaps the entire CryptoStream has a ticking clock.
>
> "Ticking clock" is truly bad phraseology.  What I mean is: some sort of lifetime stipulation, akin to autoRevoke on Blob URIs.  Basically, when does the Key become invalidated?  Is a microtask checkpoint (used in HTML5) a useful concept here?

I was thinking that the
1) The Key is not neutered; that is, passing it to a CryptoOperation does not invalidate the caller's existing Key object
2) The Key may be used for any number of further operations
3) At any point, a caller can clone the Key from the CryptoOperation and, along with say, the .algorithm (or other suitable attributes), create a new, equivalent CryptoOperation in an initial state.

As I understand, having the "ticking clock" (or neutering) would prevent this, right?

>
>>
>>>
>>> 4. If dictionary members like "label" are to be interpreted as an opaque series of bytes, we should just use ArrayBuffer.  This is applicable for RsaOaepParams.  I don't think we gain that much more simplification with Base64 or with char conversions.


>>
>> ArrayBuffer or Blob? :)
>
>
> Touché :)  Again, I touted Blob as an option for CryptoOperation payloads and results *only to the extent* that it might lead to programmer convenience by not being bound to a canonical type (and thus sparing a developer a trip into ArrayBuffer land).   But in the case of things that have to be garbled by design, it seemed prudent to just go into ArrayBuffer land anyway (after all, if you have to Base64 something, it may as well be a sequence of bytes).  This might be too arbitrary a distinction, though.


>
> -- A*

Right, one thing I've been wondering about stylistically (and reflected in ISSUE-14/rawKey) is whether to use ArrayBuffer, ArrayBufferView, or Uint8Array as the 'canonical' "bag o bytes" type.
It would seem like Uint8Array is the uniformly correct type - is this correct?

Received on Tuesday, 14 August 2012 16:34:00 UTC