前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# 5分钟入门非对称加密用法

30 秒速记

  • 非对称加密 = 一对钥匙:公钥公开,私钥自己藏好
  • 保密:公钥加密 → 私钥解密;证明身份:私钥签名 → 公钥验签,两件事别混
  • RSA 只能加密很短的数据(2048 位 OAEP 最多 214 字节),大数据走混合加密
  • Node.js 里全在 crypto 模块:publicEncrypt / privateDecrypt,签名用 crypto.sign / crypto.verify
  • 密钥至少 2048 位,私钥别进代码仓库,加密填充用 OAEP,签名用 PSS

非对称加密就像一把只能锁不能开的挂锁:公钥是挂锁,谁都可以拿去锁箱子;私钥是唯一的钥匙,只有你能打开。 所以保密的用法是对方用你的公钥加密,你用私钥解密。反过来用私钥处理、公钥校验,就是数字签名,证明东西确实是你发的、没被改过,这两个目的不要混。RSA 很慢,能加密的长度也很短,实际项目里都是混合加密:随机生成一个 AES 密钥加密正文,再用 RSA 公钥加密这个 AES 密钥,HTTPS 的思路也是这样。在 Node.js 里这些都在内置的 crypto 模块里,不用装第三方库。

理解「5分钟入门非对称加密用法」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 security 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

非对称加密真正要记住的只有一张表:

目的 谁来操作 用哪把钥匙 Node.js 方法
保密(只让接收方看到) 发送方加密 接收方的公钥 crypto.publicEncrypt
接收方解密 接收方的私钥 crypto.privateDecrypt
签名(证明是我发的、没被改) 发送方签名 发送方的私钥 crypto.sign
接收方验签 发送方的公钥 crypto.verify

下面这段代码不依赖任何外部文件,直接 node demo.js 就能跑,把加密和签名两条路都走了一遍:

const crypto = require('node:crypto');

// 1. 生成一对 2048 位 RSA 密钥
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
  modulusLength: 2048,
});

// 2. 保密:公钥加密,私钥解密(默认就是 OAEP 填充)
const encrypted = crypto.publicEncrypt(publicKey, Buffer.from('你好,世界'));
const decrypted = crypto.privateDecrypt(privateKey, encrypted);
console.log(decrypted.toString()); // 你好,世界

// 3. 签名:私钥签名,公钥验签
const data = Buffer.from('转账 100 元给张三');
const signature = crypto.sign('sha256', data, {
  key: privateKey,
  padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
});
const ok = crypto.verify('sha256', data, {
  key: publicKey,
  padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
}, signature);
console.log(ok); // true

// 4. 内容被改一个字,验签失败
console.log(crypto.verify('sha256', Buffer.from('转账 900 元给张三'), {
  key: publicKey,
  padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
}, signature)); // false
@前端进阶之旅: 代码已经复制到剪贴板

实际项目里很少单独用 RSA 加密业务数据,原因有两个:一是慢,比 AES 慢几个数量级;二是长度有上限,2048 位密钥加 OAEP(SHA-1)一次最多加密 256 - 2×20 - 2 = 214 字节,一个中文字符在 UTF-8 里占 3 字节,也就是七十来个汉字。所以标准做法是混合加密:每次随机生成一个 AES 密钥加密正文,再用对方的 RSA 公钥加密这个 AES 密钥,把两者一起发过去。对方先用私钥解出 AES 密钥,再解正文。

面试官追问

追问 1公钥加密的消息私钥能解开,能证明消息是某个用户发的吗?
参考回答

不能。公钥是公开的,谁都能用它加密,解开只说明消息是发给你的,说明不了是谁发的。要确认发送方,得让对方用他的私钥签名,你用他的公钥验签。

追问 2能不能用 RSA 直接加密用户上传的 10MB 文件?
参考回答

不行。RSA 一次能加密的长度受密钥大小限制,2048 位配 OAEP 最多 214 字节,超了直接报错。正确做法是 AES-256-GCM 加密文件,RSA 只加密那个 32 字节的随机密钥。

追问 3示例里的私钥直接写在 keys.js 里提交到仓库,有什么问题?
参考回答

私钥一旦进了 git 历史,删文件也没用,等于公开了。私钥要放环境变量、密钥管理服务或部署时挂载的文件,权限只给服务进程,泄露后能换钥匙。

追问 4怎么在 Node.js 里现场生成一对密钥?
参考回答

crypto.generateKeyPairSync('rsa', { modulusLength: 2048, publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' } }),拿到的就是 PEM 格式的公钥和私钥字符串。1024 位已经不安全了,别再用。

# 加密、解密方法

30 秒速记

  • 加密:crypto.publicEncrypt(publicKey, buffer),解密:crypto.privateDecrypt(privateKey, buffer)
  • 入参和返回值都是 Buffer,跨 JSON 传输要转 base64
  • publicEncrypt 默认填充就是 RSA_PKCS1_OAEP_PADDING,两端填充和哈希必须一致
  • 新版 Node.js 的 privateDecrypt 已禁用 PKCS#1 v1.5 填充(Marvin 攻击),老密文要迁移
  • privateEncrypt / publicDecrypt 不是加密,要做签名请用 crypto.sign / crypto.verify

Node.js 的非对称加解密就两个函数:crypto.publicEncrypt 用公钥加密,crypto.privateDecrypt 用私钥解密,参数和返回值都是 Buffer。 key 参数可以直接传 PEM 字符串,也可以传对象指定填充方式,比如 { key, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: 'sha256' }。默认填充已经是 OAEP,问题一般出在两端不一致:前端用了 PKCS#1 v1.5 或 SHA-256,后端用默认的 SHA-1,结果就是解密报错。密文要放进 JSON 或数据库,记得先 toString('base64'),取出来再 Buffer.from(str, 'base64')。

const crypto = require('node:crypto');
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', { modulusLength: 2048 });

const opts = { padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: 'sha256' };
const cipher = crypto.publicEncrypt({ key: publicKey, ...opts }, Buffer.from('hello'));
const b64 = cipher.toString('base64'); // 存库 / 传 JSON 用这个

const plain = crypto.privateDecrypt({ key: privateKey, ...opts }, Buffer.from(b64, 'base64'));
console.log(plain.toString()); // hello
@前端进阶之旅: 代码已经复制到剪贴板

在Node.js中,负责安全的模块是crypto。非对称加密中,公钥加密,私钥解密,加解密对应的API分别如下。

加密函数:

crypto.publicEncrypt(key, buffer)
@前端进阶之旅: 代码已经复制到剪贴板

解密函数:

crypto.privateDecrypt(privateKey, buffer)
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
      • 加密、解密方法
      • 入门例子
      • 小结
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

5分钟入门非对称加密用法|Nodejs专题系列

# 5分钟入门非对称加密用法

30 秒速记

  • 非对称加密 = 一对钥匙:公钥公开,私钥自己藏好
  • 保密:公钥加密 → 私钥解密;证明身份:私钥签名 → 公钥验签,两件事别混
  • RSA 只能加密很短的数据(2048 位 OAEP 最多 214 字节),大数据走混合加密
  • Node.js 里全在 crypto 模块:publicEncrypt / privateDecrypt,签名用 crypto.sign / crypto.verify
  • 密钥至少 2048 位,私钥别进代码仓库,加密填充用 OAEP,签名用 PSS

非对称加密就像一把只能锁不能开的挂锁:公钥是挂锁,谁都可以拿去锁箱子;私钥是唯一的钥匙,只有你能打开。 所以保密的用法是对方用你的公钥加密,你用私钥解密。反过来用私钥处理、公钥校验,就是数字签名,证明东西确实是你发的、没被改过,这两个目的不要混。RSA 很慢,能加密的长度也很短,实际项目里都是混合加密:随机生成一个 AES 密钥加密正文,再用 RSA 公钥加密这个 AES 密钥,HTTPS 的思路也是这样。在 Node.js 里这些都在内置的 crypto 模块里,不用装第三方库。

理解「5分钟入门非对称加密用法」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 security 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

非对称加密真正要记住的只有一张表:

目的 谁来操作 用哪把钥匙 Node.js 方法
保密(只让接收方看到) 发送方加密 接收方的公钥 crypto.publicEncrypt
接收方解密 接收方的私钥 crypto.privateDecrypt
签名(证明是我发的、没被改) 发送方签名 发送方的私钥 crypto.sign
接收方验签 发送方的公钥 crypto.verify

下面这段代码不依赖任何外部文件,直接 node demo.js 就能跑,把加密和签名两条路都走了一遍:

const crypto = require('node:crypto');

// 1. 生成一对 2048 位 RSA 密钥
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
  modulusLength: 2048,
});

// 2. 保密:公钥加密,私钥解密(默认就是 OAEP 填充)
const encrypted = crypto.publicEncrypt(publicKey, Buffer.from('你好,世界'));
const decrypted = crypto.privateDecrypt(privateKey, encrypted);
console.log(decrypted.toString()); // 你好,世界

// 3. 签名:私钥签名,公钥验签
const data = Buffer.from('转账 100 元给张三');
const signature = crypto.sign('sha256', data, {
  key: privateKey,
  padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
});
const ok = crypto.verify('sha256', data, {
  key: publicKey,
  padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
}, signature);
console.log(ok); // true

// 4. 内容被改一个字,验签失败
console.log(crypto.verify('sha256', Buffer.from('转账 900 元给张三'), {
  key: publicKey,
  padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
}, signature)); // false
@前端进阶之旅: 代码已经复制到剪贴板

实际项目里很少单独用 RSA 加密业务数据,原因有两个:一是慢,比 AES 慢几个数量级;二是长度有上限,2048 位密钥加 OAEP(SHA-1)一次最多加密 256 - 2×20 - 2 = 214 字节,一个中文字符在 UTF-8 里占 3 字节,也就是七十来个汉字。所以标准做法是混合加密:每次随机生成一个 AES 密钥加密正文,再用对方的 RSA 公钥加密这个 AES 密钥,把两者一起发过去。对方先用私钥解出 AES 密钥,再解正文。

面试官追问

追问 1公钥加密的消息私钥能解开,能证明消息是某个用户发的吗?
参考回答

不能。公钥是公开的,谁都能用它加密,解开只说明消息是发给你的,说明不了是谁发的。要确认发送方,得让对方用他的私钥签名,你用他的公钥验签。

追问 2能不能用 RSA 直接加密用户上传的 10MB 文件?
参考回答

不行。RSA 一次能加密的长度受密钥大小限制,2048 位配 OAEP 最多 214 字节,超了直接报错。正确做法是 AES-256-GCM 加密文件,RSA 只加密那个 32 字节的随机密钥。

追问 3示例里的私钥直接写在 keys.js 里提交到仓库,有什么问题?
参考回答

私钥一旦进了 git 历史,删文件也没用,等于公开了。私钥要放环境变量、密钥管理服务或部署时挂载的文件,权限只给服务进程,泄露后能换钥匙。

追问 4怎么在 Node.js 里现场生成一对密钥?
参考回答

crypto.generateKeyPairSync('rsa', { modulusLength: 2048, publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' } }),拿到的就是 PEM 格式的公钥和私钥字符串。1024 位已经不安全了,别再用。

# 加密、解密方法

30 秒速记

  • 加密:crypto.publicEncrypt(publicKey, buffer),解密:crypto.privateDecrypt(privateKey, buffer)
  • 入参和返回值都是 Buffer,跨 JSON 传输要转 base64
  • publicEncrypt 默认填充就是 RSA_PKCS1_OAEP_PADDING,两端填充和哈希必须一致
  • 新版 Node.js 的 privateDecrypt 已禁用 PKCS#1 v1.5 填充(Marvin 攻击),老密文要迁移
  • privateEncrypt / publicDecrypt 不是加密,要做签名请用 crypto.sign / crypto.verify

Node.js 的非对称加解密就两个函数:crypto.publicEncrypt 用公钥加密,crypto.privateDecrypt 用私钥解密,参数和返回值都是 Buffer。 key 参数可以直接传 PEM 字符串,也可以传对象指定填充方式,比如 { key, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: 'sha256' }。默认填充已经是 OAEP,问题一般出在两端不一致:前端用了 PKCS#1 v1.5 或 SHA-256,后端用默认的 SHA-1,结果就是解密报错。密文要放进 JSON 或数据库,记得先 toString('base64'),取出来再 Buffer.from(str, 'base64')。

const crypto = require('node:crypto');
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', { modulusLength: 2048 });

const opts = { padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, oaepHash: 'sha256' };
const cipher = crypto.publicEncrypt({ key: publicKey, ...opts }, Buffer.from('hello'));
const b64 = cipher.toString('base64'); // 存库 / 传 JSON 用这个

const plain = crypto.privateDecrypt({ key: privateKey, ...opts }, Buffer.from(b64, 'base64'));
console.log(plain.toString()); // hello
@前端进阶之旅: 代码已经复制到剪贴板

在Node.js中,负责安全的模块是crypto。非对称加密中,公钥加密,私钥解密,加解密对应的API分别如下。

加密函数:

crypto.publicEncrypt(key, buffer)
@前端进阶之旅: 代码已经复制到剪贴板

解密函数:

crypto.privateDecrypt(privateKey, buffer)
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1有人把私钥传给 publicEncrypt,让对方用公钥解,说只是参数对调,对吗?
参考回答

不对。publicEncrypt 传私钥时 Node 会从中取出公钥部分来加密,对方用公钥根本解不开。私钥处理、公钥校验那是签名的语义,要用 crypto.sign / crypto.verify。

追问 2前端用 JSEncrypt 加密,Node 端 privateDecrypt 一直报错,先查什么?
参考回答

先查填充。JSEncrypt 默认用 PKCS#1 v1.5,Node 默认按 OAEP 解,对不上;新版 Node 还禁止用 v1.5 解密。改成前端用 Web Crypto 的 RSA-OAEP,两端 hash 都指定 SHA-256。

追问 3密文直接 toString() 存进数据库,取出来解密失败,为什么?
参考回答

密文是任意二进制,按 UTF-8 转字符串会把非法字节替换掉,数据就坏了。要用 toString('base64') 存,解密前 Buffer.from(str, 'base64') 还原。

追问 4换了一套新密钥,老客户端发来的密文全解不开,怎么平滑切换?
参考回答

密文里带上密钥版本号,比如 { kid: 'v2', data: '...' },服务端按 kid 选私钥。过渡期新老私钥都保留,新客户端用新公钥,等老版本客户端下线再删老私钥。

# 入门例子

← 9.6 v8cluster →

fe