Node.js 中的 RSA 加密、解密、签名与验证详解

引言

在现代的网络通信中,数据安全显得尤为重要。RSA加密算法因其非对称的特性,广泛应用于数据的加密、解密、签名和验证等安全领域。本文将详细介绍RSA算法的基本原理,并结合Node.js环境,展示如何使用内置的crypto模块和第三方库node-rsa来实现RSA的加密、解密、签名和验证。

RSA算法原理

RSA算法是一种非对称加密算法,由Ron Rivest、Adi Shamir和Leonard Adleman于1977年提出。它的安全性基于大数分解的困难性。RSA算法涉及到三个关键的概念:密钥对生成、加密和解密。

密钥对生成

  1. 选择两个大的质数pq
  2. 计算n = p * qn用于构成公钥和私钥。
  3. 计算φ(n) = (p-1) * (q-1)φ(n)用于选择公钥指数e和私钥指数d
  4. 选择一个小于φ(n)的整数e,通常取65537(2^16 + 1),因为其具有良好的数学性质。
  5. 计算d,使得(e * d) % φ(n) = 1
  6. 公钥为(n, e),私钥为(n, d)

加密和解密

  • 加密:假设明文为M,密文C计算公式为C ≡ M^e (mod n)
  • 解密:密文C解密回明文M计算公式为M ≡ C^d (mod n)

签名和验证

  • 签名:发送方使用私钥对消息M进行签名,生成签名S ≡ M^d (mod n)
  • 验证:接收方使用发送方的公钥验证签名S,如果S^e (mod n) == M,则签名有效。

Node.js 使用 RSA 的图解框架

  1. 客户端生成密钥对:客户端使用Node.js的crypto模块生成RSA密钥对,包括一个私钥和一个公钥。
  2. 服务器发送公钥:服务器将其公钥发送给客户端。这可以通过HTTP请求、文件传输或其他通信方式完成。
  3. 客户端接收公钥:客户端接收到服务器的公钥,并将其存储起来,以便用于加密要发送给服务器的数据。
  4. 服务器接收加密数据:客户端使用服务器的公钥对数据进行加密,并将加密后的数据发送给服务器。服务器接收到加密数据。
  5. 服务器使用私钥解密数据:服务器使用其私钥对收到的加密数据进行解密,得到原始数据,并进行处理。处理完成后,服务器可以对响应数据进行加密,并将其发送回客户端。

注意:这个图解是一个简化的表示,实际应用中可能包含更多的步骤和安全措施,例如签名验证、密钥管理和存储等。

使用Node.js实现RSA

环境准备

在Node.js中,我们可以使用内置的crypto模块或第三方库node-rsa来实现RSA的功能。

使用内置crypto模块

Node.js的crypto模块提供了丰富的加密功能,包括RSA的加密和解密。

const crypto = require('crypto');// 生成RSA密钥对
const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {modulusLength: 2048,publicKeyEncoding: {type: 'spki',format: 'pem'},privateKeyEncoding: {type: 'pkcs8',format: 'pem',cipher: 'aes-256-cbc',passphrase: 'your-secret-passphrase'}
});// 加密数据
const data = 'Hello RSA!';
const encrypted = crypto.publicEncrypt({key: publicKey,padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,oaepHash: 'sha256'
}, Buffer.from(data));// 解密数据
const decrypted = crypto.privateDecrypt({key: privateKey,padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,oaepHash: 'sha256'
}, encrypted);// RSA签名
const sign = crypto.createSign('SHA256');
sign.update(data);
const signature = sign.sign(privateKey, 'base64');// RSA签名验证
const verify = crypto.createVerify('SHA256');
verify.update(data);
const result = verify.verify(publicKey, signature, 'base64');
使用node-rsa

node-rsa是一个纯JavaScript实现的RSA加密库,不需要依赖于任何外部的加密库。

const NodeRSA = require('node-rsa');// 创建NodeRSA实例
const nodeRSA = new NodeRSA({ b: 2048 }); // b是密钥长度// 生成密钥对
const keyPair = nodeRSA.generateKeyPair();// 加密数据
const encrypted = nodeRSA.encrypt(data, 'base64', 'public');// 解密数据
const decrypted = nodeRSA.decrypt(encrypted, 'utf8', 'private');// RSA签名
const signature = nodeRSA.sign('SHA256', data, 'base64', 'private');// RSA签名验证
const verifyResult = nodeRSA.verify('SHA256', data, signature, 'public');

如何使用 Node.js 进行 RSA 密钥的管理和存储?

在Node.js中进行RSA密钥的管理和存储是一个重要的安全实践。正确的管理存储机制可以确保私钥的安全性和公钥的可用性。以下是一些关于如何使用Node.js进行RSA密钥管理和存储的建议和方法:

1. 生成密钥对

首先,你需要生成RSA密钥对。在Node.js中,你可以使用crypto模块来生成密钥对。

const crypto = require('crypto');const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {modulusLength: 2048,publicKeyEncoding: {type: 'spki',format: 'pem',},privateKeyEncoding: {type: 'pkcs8',format: 'pem',cipher: 'aes-256-cbc',passphrase: 'your-secret-passphrase'},
});

2. 存储密钥

生成密钥对后,你需要将它们安全地存储起来。以下是一些存储方法:

2.1 文件系统

将密钥存储在文件系统中是一种常见的做法。你可以将公钥和私钥写入不同的文件,并确保这些文件的权限设置得当,以防止未授权访问。

const fs = require('fs');// 将私钥写入文件
fs.writeFileSync('private_key.pem', privateKey);// 将公钥写入文件
fs.writeFileSync('public_key.pem', publicKey);

确保只有运行Node.js应用的用户(通常是web服务器用户)有权限访问这些文件。

2.2 环境变量

对于私钥,你可以将其存储在环境变量中,这样可以避免将其硬编码在代码中或存储在文件系统中。

process.env.PRIVATE_KEY = privateKey;

然后,你可以使用process.env.PRIVATE_KEY来访问私钥。

2.3 密钥管理服务

对于生产环境,建议使用专门的密钥管理服务(如AWS KMS、Google Cloud KMS或HashiCorp Vault)来存储和管理密钥。这些服务提供了额外的安全措施,如硬件安全模块(HSM)保护、访问控制和审计日志。

3. 加载密钥

当你需要使用密钥时,你可以从存储位置加载它们。

3.1 从文件加载

如果你将密钥存储在文件中,可以使用fs模块来加载它们。

const fs = require('fs');// 从文件加载私钥
const privateKey = fs.readFileSync('private_key.pem', 'utf8');// 从文件加载公钥
const publicKey = fs.readFileSync('public_key.pem', 'utf8');

3.2 从环境变量加载

如果你将密钥存储在环境变量中,可以直接使用process.env来访问它们。

const privateKey = process.env.PRIVATE_KEY;
const publicKey = process.env.PUBLIC_KEY;

3.3 从密钥管理服务加载

如果你使用密钥管理服务,通常会有相应的SDK或API来从服务中检索密钥。

4. 安全考虑

  • 保护私钥:确保私钥不会被泄露。使用强密码短语保护私钥,并限制对私钥文件的访问权限。
  • 定期轮换密钥:定期更换密钥可以减少因密钥泄露带来的风险。
  • 备份密钥:对密钥进行安全备份,以防原始密钥丢失或损坏。
  • 使用最新算法:使用最新的加密算法和足够长的密钥长度来抵御计算力的增长。

通过遵循这些最佳实践,你可以确保在Node.js应用中安全地管理和存储RSA密钥。

使用 Node.js 和 RSA 加密进行安全通信的实战案例

例子:模拟一个简单的客户端和服务器之间的安全通信过程,其中服务器使用RSA加密来保护传输的数据。这个例子将展示如何生成RSA密钥对、加密数据、发送加密数据以及服务器端解密数据的过程。

步骤 1: 生成RSA密钥对

首先,我们需要生成一对RSA密钥。在这个例子中,我们将使用Node.js的crypto模块来生成密钥对。

const crypto = require('crypto');// 生成RSA密钥对
const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {modulusLength: 2048,publicKeyEncoding: {type: 'spki',format: 'pem',},privateKeyEncoding: {type: 'pkcs8',format: 'pem',},
});console.log('Public Key:', publicKey);
console.log('Private Key:', privateKey);

步骤 2: 客户端加密数据

客户端将使用服务器的公钥来加密要发送的数据。这里我们假设数据是一个简单的文本消息。

// 客户端代码
const crypto = require('crypto');// 服务器的公钥
const publicKey = '...'; // 从步骤1中获取的公钥// 要发送的数据
const data = 'Secret Message';// 使用公钥加密数据
const encryptedData = crypto.publicEncrypt({key: publicKey,padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,oaepHash: 'sha256',
}, Buffer.from(data)).toString('base64');console.log('Encrypted Data:', encryptedData);

步骤 3: 服务器端接收并解密数据

服务器端接收到加密数据后,将使用自己的私钥来解密数据。

// 服务器端代码
const crypto = require('crypto');// 服务器的私钥
const privateKey = '...'; // 从步骤1中获取的私钥// 客户端发送的加密数据
const encryptedData = '...'; // 从客户端接收到的加密数据// 使用私钥解密数据
const decryptedData = crypto.privateDecrypt({key: privateKey,padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,oaepHash: 'sha256',
}, Buffer.from(encryptedData, 'base64')).toString('utf8');console.log('Decrypted Data:', decryptedData);

步骤 4: 确保数据的完整性和认证

为了确保数据的完整性和认证,我们可以使用RSA签名来验证数据是否被篡改,并且确实是由预期的发送方发送的。

// 客户端签名数据
const sign = crypto.createSign('SHA256');
sign.update(data);
const signature = sign.sign(privateKey, 'base64');// 客户端发送数据和签名给服务器// 服务器端验证签名
const verify = crypto.createVerify('SHA256');
verify.update(data);
const isValidSignature = verify.verify(publicKey, signature, 'base64');if (isValidSignature) {console.log('Signature is valid, data is authentic.');
} else {console.log('Signature is invalid, data may have been tampered.');
}

通过这个实战案例,我们展示了如何在Node.js中使用RSA加密来保护客户端和服务器之间的通信。我们生成了RSA密钥对,客户端使用服务器的公钥加密数据,然后服务器使用自己的私钥解密数据。此外,我们还使用了RSA签名来确保数据的完整性和认证。这种方法可以有效地防止数据在传输过程中被窃听或篡改,从而提高通信的安全性。 

总结

RSA算法作为一种非对称加密技术,在保障数据传输安全方面发挥着重要作用。Node.js提供了内置的crypto模块和第三方库node-rsa,使得在Node.js环境中实现RSA加密、解密、签名和验证变得简单易行。开发者可以根据项目需求和环境选择合适的工具进行数据加密和安全保护。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python接口自动化 —— Web接口(2)

1.2.3 HTTP HTTP概念 Hyper Text Transfer Protocal超文本传输协议,基于tcp/ip通信协议来传递数据,属于应用层协议主要特点: 无连接: 每次连接只处理一个请求,服务器处理完请求并受到客户端应答后就断开连接媒体独立。 只要服务器和客…

ActiveMQ 07 集群配置

Active MQ 07 集群配置 官方文档 http://activemq.apache.org/clustering 主备集群 http://activemq.apache.org/masterslave.html Master Slave TypeRequirementsProsConsShared File System Master SlaveA shared file system such as a SANRun as many slaves as requ…

【日常记录】【CSS】SASS循环的使用

文章目录 1、引言2、安装3、举例4、参考链接 1、引言 目前在任何项目框架中,都会有css 预处理器,目前一般使用 sass、less 这俩其中之一,它可以简化css的书写 Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (v…

HarmonyOS开发实例:【分布式数据服务】

介绍 分布式数据服务(Distributed Data Service,DDS)为应用程序提供不同设备间数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。通过结合帐号、应用和分布式数据服务对属于不同的应用的数据进行隔离,保证不同…

【kubeEdge】离线部署

部署 kubeEdge 在线部署 在线方式部署直接执行以下命令,会联网下载需要的安装文件执行安装 $ keadm init --advertise-address{ip} --kubeedge-version{version} --kube-config{config_path}, 离线部署 离线准备工作 所有下载操作均在可以联网的机…

VulnHub系列 DC-4靶机 渗透详细过程 | 红队打靶

VulnHub系列 DC-4靶机详细渗透测试过程 目录 VulnHub系列 DC-4靶机详细渗透测试过程一、将靶机导入到虚拟机当中二、渗透流程主机发现端口扫描Web渗透暴力破解命令执行反弹shellSSH暴力破解提权 一、将靶机导入到虚拟机当中 靶机地址: https://download.vulnhub.c…

JVM复习

冯诺依曼模型与计算机处理数据过程相关联: 冯诺依曼模型: 输入/输出设备存储器输出设备运算器控制器处理过程: 提取阶段:输入设备传入原始数据,存储到存储器解码阶段:由CPU的指令集架构ISA将数值解…

【leetcode面试经典150题】34.有效的数独(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…

vue3第二十节(新增编译宏defineModel)

为什么会需要使用defineModel() 注意:defineModel() 需要在3.4及以上版本才可使用; 组件之间通讯,通过 props 和 emits 进行通讯,是单向数据流,比如:props是自上而下的(父组件数据修改导致子组件更新&…

FactoryMethod工厂方法模式详解

目录 模式定义实现方式简单工厂工厂方法主要优点 应用场景源码中的应用 模式定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类。 Factory Method 使得一个类的实例化延迟到子类。 实现方式 简单工厂 以下示例非设计模式,仅为编码的一种规…

贝锐蒲公英自研异地组网新技术:远程视频监控,流畅度、清晰度大幅提升

在远程视频监控过程中,若遇到网络带宽若遇到网络波动,如:丢包、高延迟等,往往会导致视频流传输时发生数据丢失或延迟现象,从而严重影响视频画面的清晰度和流畅度。 比如:在公司总部集中监看远程矿山或户外水…

力扣hot100:136. 只出现一次的数字 及其衍生

文章目录 一、LeetCode:136. 只出现一次的数字 使用到的异或运算的特点: 两个相同的数异或,结果为0 一、LeetCode:136. 只出现一次的数字 LeetCode:136. 只出现一次的数字 这里数组nums的特点是,除了一…

YOLOv8结合CVPR2024最新图像增强算法!让你的模型无惧风雨【含端到端推理脚本】

篇博客的算法来自于CVPR2024,代码刚刚开源没几天~ 原图去雨去雨检测 如何有效地探索雨痕的多尺度表示对于图像去雨是很重要的。与现有的基于Transformer的方法相比,这些方法主要依赖于单一尺度的雨痕外观,我们开发了一个端到端的多尺度Trans…

软考132-上午题-【软件工程】-沟通路径

一、定义 1-1、沟通路径1 沟通路径 1-2、沟通路径2 沟通路径 n-1 二、真题 真题1: 真题2: 真题3:

ElasticSearch入门篇

简介 ElasticSearch简介:简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用Java开发并使用Lucene…

离世界模型更近一步!Meta开源OpenEQA,评估AI Agent情景理解能力

Yann LeCun 朝着 “世界模型” 又近了一步。 Meta最新的开源工作OpenEQA:从文字模型到世界模型,可以像人一样记忆、推理的新基准,AI理解物理空间又近了一步。 场景1: 假设你正准备离开家,但找不到你的工牌。 现在,…

Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码

Java语言开发的AI智慧导诊系统源码springbootredis 3D互联网智导诊系统源码 智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应…

(CVPR,2024)CAT-Seg:基于成本聚合的开放词汇语义分割

文章目录 摘要引言方法计算成本与嵌入空间成本聚合类别成本聚合CAT-Seg框架 实验 摘要 开放词汇的语义分割面临着根据各种文本描述对图像中的每个像素进行标记的挑战。在这项工作中,我们引入了一种新颖的基于成本的方法,以适应视觉语言基础模型&#xf…

1.SCI各模块

1.学会“抄” 写论文,一定要学会“抄”!这样才能事半功倍,尤其是对于初次写作的新手,否则写作过程一定会让你痛不欲生,而且写出来的东西就是一坨shi,不仅折磨自己,也折磨导师。 写论文与建大楼…

【Spring进阶系列丨第十篇】基于注解的面向切面编程(AOP)详解

文章目录 一、基于注解的AOP1、配置Spring环境2、在beans.xml文件中定义AOP约束3、定义记录日志的类【切面】4、定义Bean5、在主配置文件中配置扫描的包6、在主配置文件中去开启AOP的注解支持7、测试8、优化改进9、总结 一、基于注解的AOP 1、配置Spring环境 <dependencie…