2
$\begingroup$

This question already has an answer here:

What I'm trying to do is encrypt 16 byte packets of data using the 128 bit AES-CBC encryption provided by SubtleCrypto.encrypt() in a web browser.

What I expected to find was 16 bytes of encrypted data for 16 bytes of input.

What I actually find is 32 bytes of encrypted data for 16 bytes of input.

Specifically, 15 bytes of input produces 16 bytes of output, 16 bytes of input produces 32 bytes of output, and 17 bytes of data produces 32 bytes of output.

My question is, why does 16 bytes of input data produce 32 bytes of output? I would have suspected that this might happen only with > 16 bytes of input data, not >= 16 bytes.

Save the following test code to a file and open with a web browser.

<html>
<head>
<script>

  var myKey = window.crypto.getRandomValues(new Uint8Array(16));
  console.log("Raw key = " + myKey);
  var keyObj = {};
  var keyFormat = "raw"; 
  var extractable = false;
  var usages = ["encrypt", "decrypt"];
  window.crypto.subtle.importKey(keyFormat, myKey, "AES-CBC", extractable, usages)
  .then(function(importedKey) {
    keyObj = importedKey;
    console.log("Encryption/Decryption key object = " + keyObj);

    var vector = window.crypto.getRandomValues(new Uint8Array(16));

    var encryptThis15 = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
    var encryptThis16 = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    var encryptThis17 = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]);

    var decryptSuccess = function(decrypted) {
      var decryptedData = new Uint8Array(decrypted);
      console.log("Decrypted data = " + decryptedData.length + " bytes: " + decryptedData);
    };

    var decryptFail = function(error) {
      // Fail.
      console.log("Failure decrypting data.  Error: " + error);
    };

    var encryptSuccess = function(encData) {
      var encryptedData = new Uint8Array(encData);
      console.log("Encrypted data = " + encryptedData.length + " bytes: " + encryptedData);
      return encData;
    };

    var encryptFail = function(error) {
      console.log("Failure encrypting data.  Error: " + error);
    };

    console.log("15 byte data array as input = " + encryptThis15);

    window.crypto.subtle.encrypt({name: "AES-CBC", iv: vector}, keyObj, encryptThis15)
    .then(encryptSuccess)
    .then(function(encrypted){return window.crypto.subtle.decrypt({name: "AES-CBC", iv: vector}, keyObj, encrypted);})
    .then(decryptSuccess)
    .catch(decryptFail);

    console.log("16 byte data array as input = " + encryptThis16);

    window.crypto.subtle.encrypt({name: "AES-CBC", iv: vector}, keyObj, encryptThis16)
    .then(encryptSuccess)
    .then(function(encrypted){return window.crypto.subtle.decrypt({name: "AES-CBC", iv: vector}, keyObj, encrypted);})
    .then(decryptSuccess)
    .catch(decryptFail);

    console.log("17 byte data array as input = " + encryptThis17);

    window.crypto.subtle.encrypt({name: "AES-CBC", iv: vector}, keyObj, encryptThis17)
    .then(encryptSuccess)
    .then(function(encrypted){return window.crypto.subtle.decrypt({name: "AES-CBC", iv: vector}, keyObj, encrypted);})
    .then(decryptSuccess)
    .catch(decryptFail);

  })
  .catch(function(err){
    console.log("Key generation error = " + err);
  });

</script>
<title>WebCrypto encrypt test</title>
</head>
<body>
<p>See console log.</p>
</body>
</html>
$\endgroup$

marked as duplicate by Geoffroy Couteau, yyyyyyy, otus, tylo, Maarten Bodewes Mar 16 '17 at 21:14

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 2
    $\begingroup$ en.wikipedia.org/wiki/Padding_(cryptography) $\endgroup$ – Richie Frame Mar 13 '17 at 3:55
  • 2
    $\begingroup$ TL;DR: CBC must encrypt a multiple of the block size. Thus if you have a full block, you must fully pad another because otherwise you might get problems if you end your message with characteristic padding bytes... $\endgroup$ – SEJPM Mar 13 '17 at 9:04

Browse other questions tagged or ask your own question.