AES-128-CTR 解密在使用 crypto 和 Crypto-JS 模块时在节点中给出空字符串输出

问题描述 投票:0回答:1

我正在尝试使用 crypto-js javascript 库解密数据,并尝试使用节点加密库在 Nodejs 端加密相同的加密文本。我正在使用 CTR 模式的 AES 128 加密算法。我能够正确加密,但 crypto-js 模块的描述不会生成相同的纯文本。它给出一个空字符串。

请查找以下代码示例。

// Encryption using built-in node-js (crypto module)
const crypto = require('crypto');

const encrypt = (plaintext, key, iv) => {
  const cipher = crypto.createCipheriv('aes-128-ctr', key, iv);
  const ciphertext =
    cipher.update(plaintext, 'utf-8', 'hex') + cipher.final('hex');
  return ciphertext;
};
// Decryption using node Crypto-JS module (https://www.npmjs.com/package/crypto-js)

const CryptoJS = require('crypto-js');

const decrypt = (ciphertext, key, iv) => {
  const decipher = CryptoJS.AES.decrypt(
    { ciphertext: CryptoJS.lib.WordArray.create(ciphertext) },
    { key: CryptoJS.lib.WordArray.create(key) },
    { iv: CryptoJS.lib.WordArray.create(iv),
      mode: CryptoJS.mode.CTR,
      padding: CryptoJS.pad.NoPadding, 
    }

  );
  const plaintext = decipher.toString(CryptoJS.enc.Utf8);
  return plaintext;
};

const key = 'b0aad3da3cab2622';
const iv = 'ZGZjMGQ2NjNhYQ==';
const plaintext = 'Hello World';
const ciphertext = encrypt(plaintext, key, iv);
const decryptedText = decrypt(ciphertext, key, iv);
console.log(ciphertext);
console.log(decryptedText);
javascript node.js cryptography aes es6-modules
1个回答
0
投票

在 CryptoJS 代码中,密钥和 IV 必须作为

WordArray
传递,密文作为
CipherParams
对象传递,例如:

var key = 'b0aad3da3cab2622';
var iv = 'ZGZjMGQ2NjNhYQ==';
var ciphertextHex = '9c494d260c23bb9caa2162';

var keyWA = CryptoJS.enc.Utf8.parse(key);
var ivWA = CryptoJS.enc.Utf8.parse(iv);
var ciphertextWA = CryptoJS.enc.Hex.parse(ciphertextHex);
var ciphertextCP = {ciphertext: ciphertextWA};

const decrypt = (ciphertext, key, iv) => {
    const decipher = CryptoJS.AES.decrypt(
        ciphertext,
        key,
        { 
            iv: iv,
            mode: CryptoJS.mode.CTR,
            padding: CryptoJS.pad.NoPadding, 
        }
    );
    const plaintext = decipher.toString(CryptoJS.enc.Utf8);
    return plaintext;
};

var decrypted = decrypt(ciphertextCP, keyWA, ivWA);
console.log(decrypted); // Hello World
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

在上面的示例中,

ciphertextHex
是十六进制编码的密文,由 NodeJS 代码的输入数据生成。


安全:

请注意,密钥和 IV 应对应于值在 0x00 和 0xFF 之间的随机字节序列,并且不应使用任何字符串(即,未经事先解码,不得使用 Base64 或十六进制字符串)。

如果要使用字符串作为密钥材料,则必须将密钥派生函数(至少 PBKDF2)与每次加密的随机盐结合应用。

此外,不得使用静态 IV。相反,每次加密都会生成一个随机 IV。
请注意,CTR 和基于 CTR 的算法重复使用密钥/IV 对是一个严重的漏洞。

Salt 和 IV 不是秘密的,它们与密文(通常是串联的)一起传递到解密方。

考虑使用 GCM 模式(基于 CTR),因为 GCM 还需要进行身份验证,因此比 CTR 更安全(不幸的是 CryptoJS 不支持 GCM,因此必须使用另一个库)。

© www.soinside.com 2019 - 2024. All rights reserved.