使用WebCrypto进行AES加密数据长度

时间:2017-03-13 06:28:05

标签: javascript encryption webcryptoapi

我要做的是使用SubtleCrypto.encrypt()在网络浏览器中提供的128位AES-CBC加密来加密16字节数据包。

我期望找到的是16个字节的加密数据,用于16个字节的输入。

我实际发现的是16个字节的加密数据,用于16个字节的输入。

具体来说,15字节输入产生16字节输出,16字节输入产生32字节输出,17字节数据产生32字节输出。

我的问题是,为什么16字节的输入数据产生32字节的输出?我怀疑这可能只发生在> 16字节的输入数据,不是> = 16字节。

将以下测试代码保存到文件中,然后使用Web浏览器打开。

<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>

1 个答案:

答案 0 :(得分:1)

PKCS#5/7填充指示块必须将字节antlr.MismatchedTokenException: expecting "end", found ')' 的{​​{1}}个字节附加到明文,直到块完成。也就是说,如果您尝试加密:

  • 15个字节:填充变为a
  • 14个字节:填充变为a
  • 13个字节:填充变为01

如果您正在使用此填充模式(您是)并且您加密的数据大小与块大小相同(16字节为您),则块未填充并且使用相同的填充模式进行解密将失败。因此,您必须在明文的末尾添加16个字节的02 02