New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 603769 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner:
Last visit > 30 days ago
Closed: Apr 2016
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 3
Type: Bug



Sign in to add a comment

AES-CTR does not decrypt encrypted bytes

Reported by julianga...@juliangautier.com, Apr 15 2016

Issue description

Chrome Version       : 49.0.2623.110
OS Version: OS X 10.11.4
URLs (if applicable) : https://jsbin.com/tevaruwiza/edit?js,output
Other browsers tested:
  Add OK or FAIL after other browsers where you have tested this issue:
     Safari 5:
  Firefox 4.x:
     IE 7/8/9:

What steps will reproduce the problem?
1. Run JSBin code.


What is the expected result?

That I can encrypt chunks of data, and then combine them and decrypt them all at once use AES-CTR.

What happens instead of that?

Unable to decrypte all chunks ta once.

Please provide any additional information below. Attach a screenshot if
possible.

UserAgentString: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36



 
aes-ctr is a block cipher. For any given crypt operation you are creating a block. You're encrypt op is creating 11 blocks and you decrypt those 11 blocks but when you pack it all into one it doesn't because the one block isn't the same as 11 blocks combined.

I suggest you just pack the data into one block and send it into the crypt routine.

Something like:
      var buf = new ArrayBuffer(22);
      var bufView = new Uint16Array(buf);
      for (var i=0; i < 11; ++i) {
         bufView[i] = rawString.charCodeAt(i);
      }
      window.crypto.subtle.encrypt({
        "name": "AES-CTR",
        "counter": new Uint8Array(16),
        "length": 128
      },
      aesKey,
      buf).then(function (encrypted) {
\          window.crypto.subtle.decrypt({
            "name": "AES-CTR",
            "counter": new Uint8Array(16),
            "length": 128
          },
          aesKey,
          encrypted).then(function (decrypted) {
            var decryptedChar =  new Uint16Array(decrypted);
            document.write(String.fromCharCode.apply(null, decryptedChar));
}
Labels: Needs-Feedback
Thanks for looking into this.  Just to give you an idea of the use case here is I am capturing data from a microphone and encrypting each chunk using a script processor node and sending that data down web sockets to other users which can play the audio live.  At the same time as other users are getting the audio I am also storing the encrypted chunks on the server.  Afterwards the clients would like to be able to fetch all of the bytes at once and decrypt it all at once.  I can work around this by decrypting the file in chunks but it seems like other platforms support this.  Take a look at this code in node:

var crypto = require("crypto");
var cipher = crypto.createCipher("aes-256-ctr", "test");
var decipher = crypto.createDecipher("aes-256-ctr", "test");
var rawString = "hello world";
var encryptedBuffers = [];
for (var i = 0; i < rawString.length; i++) {
    encryptedBuffers.push(cipher.update(rawString[i]));
    console.log(decipher.update(encryptedBuffers[i]).toString("utf8"));
}
var decipher = crypto.createDecipher("aes-256-ctr", "test");
console.log(decipher.update(Buffer.concat(encryptedBuffers)).toString("utf8"));

See how it can encrypt/decrypt chunks and then also decrypt them combined?  Also AES-CTR is suppose to make AES work as a stream cipher: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29 which I thought would enable this functionality, but maybe I am misunderstanding.  Additionally I have colleagues who are working on iOS and Android who are using AES-CTR in a similar fashion encrypting/decrypting chunks and then decrypting them combined. 

Thoughts?
Project Member

Comment 4 by sheriffbot@chromium.org, Apr 16 2016

Labels: -Needs-Feedback Needs-Review
Owner: ranjitkan@chromium.org
Thank you for providing more feedback. Adding requester "ranjitkan@chromium.org" for another review and adding "Needs-Review" label for tracking.

For more details visit https://sites.google.com/a/chromium.org/dev/issue-tracking/autotriage - Your friendly Sheriffbot

Comment 5 by rsesek@chromium.org, Apr 18 2016

Components: Blink>WebCrypto

Comment 6 by eroman@chromium.org, Apr 18 2016

Status: WontFix (was: Unconfirmed)
In short, the WebCrypto API does not support this.
WebCrypto provides only a one-shot interface for encryption/decryption.

You can raise the issue to the WebCrypto Working Group [1], however this was already discussed and rejected.

I agree that unfortunately using AES-CTR in WebCrypto is fairly unwieldly (can't stream data to it, and also the incremented counter is not exposed)

If you wanted you could in theory layer your own stream interface on top of the existing primitive, by varying the "counter" parameter manually. To do this efficiently (at least with what WebCrypto exposes) you would want to buffer a block worth of data, encrypt it, and then update the counter.

There are other hacks you could do to recover the pad and then encipher byte by byte, but the amount of effort isn't worth it (might as well just re-implement AES-CTR outside of WebCrypto at that point).

As described your protocol does sound a bit sketchy. Are you varying the counter? Are you providing integrity through some other means?

I am afraid I don't have a better answer than that. Sending an email to the W3C WebCrypto working group is probably your best recourse.

[1] https://www.w3.org/2012/webcrypto/
Thanks for looking into it.  At least now I know its a limitation of the API and not something that I was doing incorrectly.

Sign in to add a comment