- From: Richard Barnes <rbarnes@bbn.com>
- Date: Thu, 14 Feb 2013 15:18:30 -0500
- To: Ryan Sleevi <sleevi@google.com>
- Cc: "public-webcrypto@w3.org Group" <public-webcrypto@w3.org>
Ok, great. Thanks, that does clarify things. I had missed the padding spec in the CBC section.
However, it seems rather outside the spirit of the low-level API to include padding in the algorithm. It's necessary in some cases (e.g., RSA signature schemes), but for CBC, it could just as easily be done by the application.
--Richard
On Feb 14, 2013, at 3:07 PM, Ryan Sleevi <sleevi@google.com> wrote:
> 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:19:04 UTC