Re: Incomplete blocks

On Thu, Feb 14, 2013 at 11:13 AM, Richard Barnes <rbarnes@bbn.com> wrote:
> Suppose I make the following call:
>
> /* my_iv and my_key pre-defined */
> var my_pt = new Uint8Array(24);
> var my_ct;
> var op = window.crypto.encrypt(
>     {name: "AES-CBC", params: {iv: my_iv}},
>     my_key,
>     my_pt
> );
> op.oncomplete = function(e) {
>     my_ct = e.target.result;
> }
>
> That is, I've asked the API to encrypt 24 octets -- 1.5 blocks -- of data.  However, CBC only operates on whole blocks (unlike CTR, GCM).  What should then happen?  (Using enc() to represent encryption, and '+' for concatenation)

Your assumption (that CBC only operates on whole blocks) reflects a
spec ambiguity - one that was raised in Sept and filed as
https://www.w3.org/Bugs/Public/show_bug.cgi?id=18953

This was clarified in https://dvcs.w3.org/hg/webcrypto-api/rev/0c723a7d29b3

>
> 1) Complete, result = enc(my_pt[0:16])
> 2) Complete, result = enc(my_pt[0:16]) + my_pt[16:]
> 3) Complete, result = enc(my_pt + padding)
> 4) Error

As reflected in https://dvcs.w3.org/hg/webcrypto-api/rev/0c723a7d29b3
, it would be 3 - because the AES-CBC mode is defined to use
PKCS#5/PKCS#7 padding.

I also note that this is related to you using the 'one-shot' form.

Consider the following:

var op = window.crypto.encrypt({name: 'AES-CBC', params: {iv: my_iv}}, my_key);
op.process(new Uint8Array(5));
op.process(new Uint8Array(19));
op.process(new Uint8Array(7));
op.finish();

For an implementation that supports incremental encryption, the
expected result would be:

[op.process(5)]
[op.process(19)]
queue an onProgress, with op.result.byteLength == 16 (that is, it
encrypted the 5 bytes from the first process call and 11 bytes from
the second process call to yield 16 bytes CT)
[op.process(7)]
[op.finish()]
queue an onProgress, with op.result.byteLength == 32 (that is, 8 bytes
remaining from the second process call, the 7 bytes from the third
process call, and 1 byte of padding)

For an implementation that doesn't support incremental encryption
[op.process(5)]
[op.process(19)]
[op.process(7)]
[op.finish()]
onProgress, with op.result.byteLength == 32 (that is, the combined 31
bytes, plus one byte of padding)

>
> Right now, PolyCrypt does (2), because that's what CryptoJS does if you tell it "no padding"; my development branch does (3).  I'm pretty sure both of these are wrong, and (1) or (4) should be the outcome.
>
> In terms of the spec, I believe this ambiguity relates to 12.1 / Step 2 / Steps 3/6 (in the branches, respectively).
>
> Thoughts?

Received on Thursday, 14 February 2013 20:08:02 UTC