W3C home > Mailing lists > Public > public-webcrypto-comments@w3.org > December 2012

Re: Streaming - [Re: CryptoOperation and its life cycle]

From: Ryan Sleevi <sleevi@google.com>
Date: Thu, 13 Dec 2012 10:49:32 -0800
Message-ID: <CACvaWvZh6Rc-84=unXNsds0yDfty+gHtqcuB4FDiTaQsO1V-jQ@mail.gmail.com>
To: Aymeric Vitte <vitteaymeric@gmail.com>
Cc: rbarnes@bbn.com, public-webcrypto-comments@w3.org
On Thu, Dec 13, 2012 at 2:16 AM, Aymeric Vitte <vitteaymeric@gmail.com> wrote:
>>
>> onprogress follows the Progress Events model, in which the client is
>> informed of progress. There is always at least one onprogress event
>> (which may be due to the final completion of the data), and there is
>> always zero or one oncomplete events. At the oncomplete event firing,
>> all of the data is available in result.
>>
>> This was raised as a point of concern by Wan-Teh back on June 20th,
>> but it arguably follows the model of what existing APIs (such as File
>> API or Streams API) do through their readAsArrayBuffer methods, and
>> with how XMLHttpRequest makes data available through progress events.
>>
>> To be clear: .result contains the data available, and may grow to add
>> more data, up and until oncomplete is fired.
>>
> The specs say : "an interface to support streaming/progressive output has also been requested. How such an interface would be implemented, if at all, remains TBD."


This is talking in particular about accepting Blob objects from the
File API ( http://dev.w3.org/2006/webapi/FileAPI/ ) **and returning
Blob**, or accepting Stream objects from the Streams API (
http://dvcs.w3.org/hg/streams-api/raw-file/tip/Overview.htm ) **and
returning Stream objects**

>
>
> I assume this is related to the case below, current implementations of streaming can do something like :
>
> var H=new Hash('sha1');
> H.update(stream1);
> var res1=H.digest(stream1);
> H.update(stream2);//hash stream1+stream2
> var res2=H.digest(stream2);
> etc...
>
> Which can become with Webcrypto something like :
>
> var H=(new Hash('sha1')).digest();
> H.process(stream);//stream1
> H.onprogress=function() {
>     console.log(this.result);
>     this.process(stream);//stream2
> };
>
>
> Apparently this will return stream1 hash and stream2 hash (not stream1 hash followed by stream1 + stream2 hash), probably I am misreading something because it looks therefore useless to call several time "process" for the same CryptoOperation object and the list of pending data is only feeded by "process" which empty it, then for now it's not really a list (should not the list of pending data be updated when process ends ?).

There is presently **no** requirement that the underlying
implementation support multi-part operations. The language was worded
in such that a browser implementation MAY synthesize multi-part
operations under the hood into a single operation.

Syntactically, the call sequence under the current Editor's Draft (
https://dvcs.w3.org/hg/webcrypto-api/raw-file/f5e8d9a3e18f/spec/Overview.html
) is

var h = window.crypto.digest("sha1");
h.process(stream1);  // MUST be an ArrayBufferView
h.process(stream2);  // MUST be an ArrayBufferView
h.finish();

Given that API ONLY defines SHA-family hashes at present, and that
there is NO incremental hashing supported by these constructs (since
the final block contains both padding and the finalized length), it
makes no sense to to return the intermediate parts.

Really, what I think you're asking about is ISSUE-22, which asks where
CryptoOperations should be clonable. IF they were (and I presently
don't think so yet), THEN you would write something like

var h1 = window.crypto.digest("SHA1");
h1.process(stream1);  // MUST be an ArrayBufferView
var h2 = h1.clone();
h1.finish();
h2.process(stream2);  // MUST be an ArrayBufferView
h2.finish();

Upon invoking their oncomplete callbacks for h1 and h2, h1.result ==
H(stream1) and h2.result == H(stream1+stream2);

However, like I said, I am generally opposed to clone methods (not
structured clone, but explicit clone), in particular when the
object-being-cloned is an EventTarget, as I think it creates confusion
for what to do with pending tasks in the HTML Event Loop when the
object is cloned during a task? Do they get cloned as well? If not,
it's possible for h2.result == H(Stream2), which would not be
expected.

In short, the only way to do what you're asking today is

var h1 = window.crypto.digest("SHA1");
var h2 = window.crypto.digest("SHA1");
h1.process(stream1);
h2.process(stream1);
h2.process(stream2);
h1.finish();
h2.finish();

As you can see, multi-part operations, streaming, and cloning are
rather complex issues, whereas 'single shot' operations are much
clearer:

var h1 = window.crypto.digest("SHA1", [ stream1 ]);
// no .process() method, no .finish() method. Only digests the data
supplied in the .digest call
var h2 = window.crypto.digest("SHA1", [ stream1, stream2 ]);
// no .process(), no .finish(). Only digests the data supplied in the
.digest call

>
>
> PS : typos in the spec
> 12.1.2.3bis "Remove data from the list of pending data." --> "Remove item from the list of pending data."
> 19.3.4 "Upon invoking init: " --> what init method ?
>
> --
> jCore
> Email :  avitte@jcore.fr
> GitHub : https://www.github.com/Ayms
> Web :    www.jcore.fr
> Webble : www.webble.it
> Extract Widget Mobile : www.extractwidget.com
> BlimpMe! : www.blimpme.com
>
Received on Thursday, 13 December 2012 18:50:02 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Thursday, 13 December 2012 18:50:02 GMT