node中的crypto模块指南

news2024/11/15 21:51:09

node中的crypto模块指南

加密操作可能很棘手,以至于付费的加密服务公司的存在只是为了确保在代码库中正确实现加密操作。好消息是,只需学习一些知识,我们就可以使用 Node 的内置加密模块免费进行适当的加密。

在本指南中,我们将探讨如何使用 Node 的内置加密模块正确执行(对称)加密/解密操作,以保护应用程序的数据。

首先,我们需要了解对称加密的概念。

对称加密

当人们谈论“加密”时,他们往往指的是对称加密,这对于将文本加密为随机字符串非常有用。与此相关的一个常见场景是对服务器上的用户数据进行加密,以便将其“静态加密”存储在数据库中。

通俗地说,对称加密就是获取要加密的文本(称为明文),并使用带有加密算法的密钥来输出加密文本(称为密文)。该操作是可逆的,因此解密是我们可以使用与明文相同的密钥。

在这里插入图片描述
看起来很容易吧?

但是当真正需要实现对称加密时,开发人员经常会犯错误,因为有很多东西需要理解:

  • 编码格式:数据可以通过多种方式进行编码/解码,例如base64hex等。当从一种格式转换为另一种格式时,这些不同的表示方式常常使开发人员感到困惑。
  • 算法和配置:有许多加密算法需要考虑,例如aes-256-gcmaes-256-cbc,每种算法都有自己的要求。
  • 随机性:加密过程中使用的密钥应随机生成,以确保高熵。很多时候,开发人员认为他们正在生成足够随机的密钥,但事实并非如此。
  • 复杂性:Node.js 中的加密涉及几个步骤,这些步骤对开发人员来说并不总是直观的,而且有些概念一开始确实令人费解。以初始化向量(IV)的概念为例;刚接触密码学的开发人员经常在加密过程中重复使用这些内容,这是一个很大的禁忌。

无论如何,在本文中并不会讨论上述细微差别,但更多地关注我们如何通过示例使用 Node.js 正确执行加密。

解释如何正确执行加密的最佳方法是演示使用aes-256-gcm算法的正确实现。让我们从加密开始。

加密

const crypto = require('crypto');

const encryptSymmetric = (key, plaintext) => {
  const iv = crypto.randomBytes(12).toString('base64');
  const cipher = crypto.createCipheriv(
    "aes-256-gcm", 
    Buffer.from(key, 'base64'), 
    Buffer.from(iv, 'base64')
  );
  let ciphertext = cipher.update(plaintext, 'utf8', 'base64');
  ciphertext += cipher.final('base64');
  const tag = cipher.getAuthTag()
  
  return { ciphertext, tag }
}

const plaintext = "encrypt me";
const key = crypto.randomBytes(32).toString('base64');

const { ciphertext, iv, tag } = encryptSymmetric(key, plaintext);

要执行加密,我们需要两项:

  • plaintext:要加密的文本。
  • key:256 位加密密钥。

我们从加密中得到以下输出:

  • ciphertext:加密文本。
  • iv:一个 96 位初始化向量,用于提供加密的初始状态,并允许在未来的加密操作中以不同iv重复使用相同key
  • tag:在加密过程中生成的一段数据,用于帮助验证加密文本在稍后的解密过程中没有被篡改。

让我们看一下代码:

const plaintext = "encrypt me";
const key = crypto.randomBytes(32).toString('base64');

这里我们定义执行加密所需的输入变量。除了要加密的文本之外,生成随机数以通过更高的熵key确保安全性也很重要;我更喜欢使用内置crypto.randomBytes()来生成。我还将所有内容转换为base64格式,因为它在概念上易于存储。

接下来我们来剖析一下加密函数:

const encryptSymmetric = (key, plaintext) => {
  // 创建随机初始化向量
  const iv = crypto.randomBytes(12).toString('base64');

  // 创建一个密码对象
  const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);

  // 使用明文更新 cipher 对象以进行加密
  let ciphertext = cipher.update(plaintext, 'utf8', 'base64');

  // 完成加密过程
  ciphertext += cipher.final('base64');
  
  // 检索加密的身份验证标签
  const tag = cipher.getAuthTag();
  
  return { ciphertext, iv, tag };
}

在这里,加密函数在使用aes-256-gcm(可以将其视为一种加密算法)算法、keyiv``crypto.createCipheriv初始化期间创建一个新的密码。下一部分加载要加密的文本plaintext并执行加密并检索身份验证标记,可以使用该标记来检查ciphertext解密过程中文本未被篡改。

关于加密,我们应该了解的最后一件事是如何处理数据。在加密用户数据并静态存储它的情况下,需要将加密的数据ciphertextiv、 和tag存储在数据库中,并将密钥安全地存储在其他地方,例如服务器上的环境变量。当我们想要检索数据时,可以从数据库中查询并使用密钥对其进行解密。

说到这里,让我们深入解密。

解密

const decryptSymmetric = (key, ciphertext, iv, tag) => {
  const decipher = crypto.createDecipheriv(
    "aes-256-gcm", 
    Buffer.from(key, 'base64'),
    Buffer.from(iv, 'base64')
  );
  
  decipher.setAuthTag(Buffer.from(tag, 'base64'));

  let plaintext = decipher.update(ciphertext, 'base64', 'utf8');
  plaintext += decipher.final('utf8');

  return plaintext;
}

const plaintext = decryptSymmetric(key, ciphertext, iv, tag);

要执行解密,我们需要四项:

  • key:用于加密原始文本的256位加密密钥。
  • ciphertext:要解密的密文。
  • iv:加密期间使用的 96 位初始化向量。
  • tag:加密时生成的标签。

我们从加密中得到以下输出:

  • plaintext:我们加密的原始文本。

让我们看一下解密函数:

const decryptSymmetric = (key, ciphertext, iv, tag) => {
  // 创建一个解密对象
  const decipher = crypto.createDecipheriv(
    "aes-256-gcm", 
    Buffer.from(key, 'base64'),
    Buffer.from(iv, 'base64')
  );
  
  // 设置解密对象 decipher 的认证标签
  decipher.setAuthTag(Buffer.from(tag, 'base64'));

  // 使用 Base64 编码的密文更新解密对象
  let plaintext = decipher.update(ciphertext, 'base64', 'utf8');

  // 完成解密
  plaintext += decipher.final('utf8');

  return plaintext;
}

这里,解密函数在用aes-256-gcm算法进行crypto.createDecipheriv初始化时创建了一个解密对象,keyiv是之前创建的。接下来设置身份验证标签,用于检查是否被ciphertext篡改,最后我们执行解密以获得原始文本。

最后,我们的数据的安全程度取决于用于加密数据的密钥。因此,强烈建议安全地存储加密密钥,并在应用程序中将它们作为环境变量进行访问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1074508.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kickstart:快速、可靠的Linux系统自动安装

1 kickstart介绍 由于安装多台服务器系统需要重复回答多个问题,我们需要一个可以记录这些答案的脚本,自动的去回答问题,该文件叫kickstart脚本 2 环境搭建 2.1 配置软件仓库 2.2 关闭防火墙,搭建DHCP,httpd服务 sy…

JavaScript进阶 第一天笔记

JavaScript 进阶 - 第1天 学习作用域、变量提升、闭包等语言特征,加深对 JavaScript 的理解,掌握变量赋值、函数声明的简洁语法,降低代码的冗余度。 理解作用域对程序执行的影响能够分析程序执行的作用域范围理解闭包本质,利用闭包…

web漏洞-xml外部实体注入(XXE)

web漏洞-xml外部实体注入(XXE) 目录 web漏洞-xml外部实体注入(XXE)概念危害检测方法利用方法漏洞利用xxe-lab有回显情况无回显情况 pikachu靶场有回显内容无回显 修复方案 概念 xml可拓展标记语言: xml是一种可拓展的标…

面试经典 150 题 14 —(数组 / 字符串)— 134. 加油站

134. 加油站 方法一 class Solution { public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int minSpare std::numeric_limits<int>::max(); // 初始化最小剩余汽油量为整型的最大值int spare 0; // 当前剩余汽油量int len g…

NSSCTF做题(7)

[第五空间 2021]pklovecloud 反序列化 <?php include flag.php; class pkshow { function echo_name() { return "Pk very safe^.^"; } } class acp { protected $cinder; public $neutron; …

基于Softmax回归的多分类任务

Logistic回归可以有效地解决二分类问题&#xff0c;但在分类任务中&#xff0c;还有一类多分类问题&#xff0c;即类别数C大于2 的分类问题。Softmax回归就是Logistic回归在多分类问题上的推广。 使用Softmax回归模型对一个简单的数据集进行多分类实验。 首先给大家看一下需要的…

【SpringCloud】Ribbon负载均衡原理、负载均衡策略、饥饿加载

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 Ribbon 一、 Ribbon负载均衡原理1.1 负载均…

4.springcloudalibaba sentinel v1.8.6版本服务搭建

文章目录 前言一、sentinel服务端安装1.1 服务端下载1.2 启动sentinel服务 二、客户端使用sentinel2.1.pom增加sentinel包2.2 增加配置2.3 启动服务 三、验证3.1 给hello接口增加流控规则3.2 测试结果如下 总结 前言 前面完成了gateway项目部署并且测试&#xff0c;现在部署搭…

【ONE·C++ || 异常】

总言 主要介绍异常。 文章目录 总言1、C异常1.1、C语言传统的处理错误的方式1.2、异常概念1.3、异常的基本用法1.3.1、异常的抛出和捕获1.3.1.1、异常的抛出和匹配原则1.3.1.2、 在函数调用链中异常栈展开匹配原则 1.3.2、异常的重新抛出1.3.2.1、演示一1.3.2.2、演示二 1.3.3…

滑动窗口算法技巧

大家好&#xff0c;我是 方圆。在我刷了一些滑动窗口相关的题目之后&#xff0c;发现很有技巧性&#xff0c;只要掌握了解题思路&#xff0c;就会很简单&#xff0c;所以我决定用这篇帖子记录一下&#xff0c;也帮助同样在刷滑动窗口相关题目的同学。 使用滑动窗口解决的问题一…

PADS规则设置

一&#xff0e;设置类规则(DRC检测规则) 默认所有类规则设置网络属性分类设置 网络属性附着颜色 选择电源类在DDR中设置非常实用 创建组合 方便模块整旋转移动 二,元件组合 选择组合 旋转组合 CtrlR旋转90&#xff1b;双击旋转任意角度 拆开组合(还独立元件操作) 三,设置过孔…

【java学习】多维数组(10)

文章目录 1. 二维数组 1. 二维数组 二维数组[][]&#xff1a;数组中的数组 格式1&#xff08;动态初始化&#xff09;&#xff1a;int[][] arr new int[3][2]; 解释说明&#xff1a; 定义了名称为arr的二维数组二维数组中有3个一维数组每个一维数组中有2个元素一维数组的名称…

教资面试多烂才不合格 教师资格证面试难度分析

教资面试是否合格&#xff0c;主要取决于考生的表现是否符合教师职业要求和教育教学能力。以下是一些可能导致教资面试不合格的表现&#xff1a; 对教育事业缺乏热情&#xff0c;对所教授的学科不感兴趣&#xff0c;或者对教育工作没有正确的认知。 对学生的关注不足&#xf…

C++学习day3

目录 作业&#xff1a; 1> 思维导图 2>设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 效果图…

【ICer的脚本练习】shell的三剑客:grep/sed/awk

系列的目录说明请见:ICer的脚本练习专栏介绍与全流程目录_尼德兰的喵的博客-CSDN博客 前言 大大小小的脚本我们写了几个了,在上一篇我们借助bashrc简单了解了bash语言的一些语法和组织规则。这一篇呢我们还是回到shell简单看下三个常用命令,毕竟脚本也可以视为复杂的命令尤…

c++运算符

文章目录 运算符位运算符类型转换 运算符 #include<iostream> using namespace std;int main() {// 算术运算符cout << "1 2 " << 1 2 << endl; cout << "1 2 - 3 * 4 " << 1 2 - 3 * 4 << endl;short a…

mfoc-hardnested在visual studio2022编译

1、点击mfoc-hardnested.sln 2、没有clang LLVM (clang-cl) (未安装) 打开installer 点击修改: 单个组件中搜索clang &#xff0c;安装即可 3、编译 4、main函数 5、mfoc-hardnested.exe使用

v-on事件处理指令;简写@事件名

一、v-on 给元素&#xff08;标签&#xff09;绑定事件监听器 oninput、onclick、onchange、onblur等 1、 完整方式v-on:事件名“函数/方法” 2、简写方式事件名“函数/方法”&#xff0c;注意符号不能加冒号“&#xff1a;” input /click/change/blur ..... 代码如下&#xf…

为什么不建议使用SELECT * ?

“不要使用SELECT ”几乎已经成为数据库使用的一条金科玉律&#xff0c;就连很多公司也明确表示不得使用作为查询的字段列表&#xff0c;更是让这条规则拥有了权威的加持。 为什么不建议直接使用SELECT *&#xff1f;我们总得搞清楚这其中的原因吧&#xff0c;不要别人说不建议…

vue3 组件v-model绑定props里的值,修改组件的值要触发回调

很早之前就写了&#xff0c;一直没写篇博客记录下 <select v-model"typeVal" />const emit defineEmits([update:type]); const props defineProps({type: { type: String, default: }, });const typeVal computed({get() {return props.type;},set(value…