0

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

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

我实际发现的是 16 字节输入的 32 字节加密数据。

具体来说,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>
4

1 回答 1

1

PKCS#5/7 填充指示块必须将a字节的字节附加a到明文,直到块完成。也就是说,如果您尝试加密:

  • 15 字节:填充变为01
  • 14字节:填充变为02 02
  • 13 字节:填充变为03 03 03

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

于 2017-03-13T20:39:09.617 回答