解密的字符串在后续的节点会话中未正确编码

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

我有需要加密的crypto.randomBytes(30).toString("hex")形式的文本。

下面是我使用的加密和解密算法。

import crypto from "crypto";

const ALGORITHM = "aes-256-ctr";
const IV_LENGTH = 16;
const ENCRYPTION_KEY = crypto.randomBytes(32);

export const encrypt = (text: string) => {
  const iv = crypto.randomBytes(IV_LENGTH);
  const cipher = crypto.createCipheriv(ALGORITHM, ENCRYPTION_KEY, iv);
  const encryptedText = cipher.update(text, "utf8", "base64") + cipher.final("base64");

  return `${iv.toString("hex")}:${encryptedText}`;
};

export const decrypt = (text: string) => {
  const textParts = text.split(":");
  const iv = Buffer.from(textParts.shift(), "hex");
  const decipher = crypto.createDecipheriv(ALGORITHM, ENCRYPTION_KEY, iv);
  const encryptedText = Buffer.from(textParts.join(":"), "base64");

  return decipher.update(encryptedText, "base64", "utf8") + decipher.final("utf8");
};

我在终端中运行node,并且能够在类似repl的环境中使用这些功能。

当我处于该node会话中时,会看到以下内容:

const encryptedText = encrypt("0e1819ff39ce47ec80488896a16520bc6b8fcd7d55dc918c96c61ff8e426")
// Output: "9fa7486458345eae2b46687a81a9fcf5:LOrlVD06eotggmIPAq0z9yzP/EHoeQyZyK6IiBYKZMIWvWYLekmSe73OjlgXdWJVOrcTyWS/eP3UU2yv"

const decryptedText = decrypt(encryptedText);
// Output: "0e1819ff39ce47ec80488896a16520bc6b8fcd7d55dc918c96c61ff8e426"

就像我想要的一样!

如果退出node会话,然后打开一个新的node会话并复制并粘贴以解密相同的字符串,则会得到以下信息:

const decryptedText = decrypt(ENCRYPTED_TEXT_FROM_ABOVE)
// Output: "�Z<�\r����S78V��z|Z\u0013��\u001a}�����@ߩ����Ɣh���*����y\b�\u001d���l'�m�'�"

为什么会这样?发生了什么变化?显然,节点似乎不再知道如何显示字符或其他内容。我不知道现在是什么编码。

之所以遇到此问题,是因为我将加密的数据存储在Postgres中,并且在检索时有时需要对其进行解密。由于某些原因,当我重新启动节点会话时,它会忘记如何读取它。

有趣的是,我可以在新的decrypt(encrypt("another string")) => "another string"终端中使用node,它可以工作,但是原来的字符串不再起作用。

node.js character-encoding base64 buffer cryptojs
1个回答
1
投票

解密步骤在这里失败,因为您正在为该行中的每个会话生成一个新密钥:

const ENCRYPTION_KEY = crypto.randomBytes(32);

如果您这样登录密钥:

console.log( { key: ENCRYPTION_KEY.toString("hex") });

您将看到每次运行的键都不相同。因此,我们无法解密先前会话中的加密数据是很有意义的!

如果更改为使用固定键:

const ENCRYPTION_KEY = Buffer.from("8b3d2068cf410479451eef41fe07d43e62ec80b962ae30cd99f7698499acfd61", "hex");

每个会话的输出应在下一个中解密。

当然,我们不想在代码中保留键,因此为此目的最好使用环境变量。

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