首页 > 解决方案 > 解密的字符串在后续节点会话中未正确编码

问题描述

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.jscharacter-encodingbase64buffercryptojs

解决方案


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

const ENCRYPTION_KEY = crypto.randomBytes(32);

如果您像这样记录密钥:

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

您会看到每次运行的密钥都不同。因此,我们未能从前一个会话中解密加密数据是有道理的!

如果您更改为使用固定键:

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

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

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


推荐阅读