jsencrypt.js 完整详解

仓库:travist/jsencrypt,底层封装 Tom Wu 的 jsbn 大数库,RSA 非对称加密前端库 ,浏览器、Node.js 都可用,兼容 OpenSSL 标准 PEM 密钥 默认填充:PKCS#1 v1.5 (encrypt());新版支持 OAEP 填充 encryptOAEP()

一、核心原理与业务流程

RSA 一对密钥:公钥 publicKey(公开)、私钥 privateKey(仅后端保存) ✅ 标准业务:前端公钥加密 → 传给后端 → 后端私钥解密

口诀:公钥加密,私钥解密;私钥签名,公钥验签 ❌ 严禁前端存放私钥!前端私钥等于裸奔,任何人F12都能拿到

密钥格式(重点,对接失败90%是密钥格式不对)

jsencrypt 识别标准 PEM:

  • 公钥:-----BEGIN PUBLIC KEY----- (PKCS#8)
  • 私钥:-----BEGIN RSA PRIVATE KEY-----(PKCS#1)> > 注意:不要带多余空格换行、不要传 JWK、不要用 openssl 新格式 PKCS#8 私钥(BEGIN PRIVATE KEY),这个库不认!

二、安装 & 引入

1. CDN(浏览器直接用)

xml 复制代码
<script src="[https://cdn.jsdelivr.net/npm/jsencrypt/bin/jsencrypt.min.js](https://cdn.jsdelivr.net/npm/jsencrypt/bin/jsencrypt.min.js)"></script>

全局变量:JSEncrypt

2. npm 方式

javascript 复制代码
npm i jsencrypt
import { JSEncrypt } from 'jsencrypt'
// 或者 commonjs
const { JSEncrypt } = require('jsencrypt')

三、完整 API 清单

arduino 复制代码
// 1. 实例化
const crypt = new JSEncrypt()
// 可选:实例化时指定密钥长度,用于前端生成密钥对(仅测试,生产不要前端生成密钥)
// const crypt = new JSEncrypt({default_key_size: 2048})
方法 作用 备注
setPublicKey(pubKey) 设置公钥,用于加密 传完整PEM字符串
setPrivateKey(priKey) 设置私钥,用于解密/签名 前端一般不用
encrypt(plainText) RSA加密,PKCS#1 v1.5 返回base64密文;超长返回false
encryptOAEP(plainText, hash) OAEP加密(更安全) hash默认sha1,推荐sha256
decrypt(cipherBase64) 解密,PKCS#1 v1.5 私钥必须正确
sign(str, hashName) 私钥签名 hash:sha256/sha1/md5
verify(str, signStr, hashName) 公钥验签 返回布尔值
getPublicKey() 获取当前公钥PEM
getPrivateKey() 获取当前私钥PEM
getKey() 获取底层jsbn key对象 可拿n、e、d等大数

最简加密示例

vbnet 复制代码
const crypt = new JSEncrypt()
crypt.setPublicKey(`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs...
-----END PUBLIC KEY-----`)

const cipher = crypt.encrypt('123456')
console.log(cipher) // base64密文

解密示例(仅后端/本地调试用,禁止线上前端解密)

vbnet 复制代码
const crypt = new JSEncrypt()
crypt.setPrivateKey(`-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQ...
-----END RSA PRIVATE KEY-----`)
const plain = crypt.decrypt(cipher)

签名验签(防篡改)

arduino 复制代码
const crypt = new JSEncrypt()
crypt.setPrivateKey(priKey)
const sign = crypt.sign('hello', 'sha256') // 私钥签名

crypt.setPublicKey(pubKey)
const ok = crypt.verify('hello', sign, 'sha256') // 公钥验签

四、致命限制:RSA明文长度上限(高频踩坑)

PKCS#1 填充固定占用 11 字节开销

  • 1024 bit RSA:最大明文字节 = 128 - 11 = 117字节
  • 2048 bit RSA:最大明文字节 = 256 - 11 = 245字节

⚠️ 大坑:汉字是UTF-8,一个汉字占3字节! 比如2048密钥,最多只能传80个左右汉字,直接超长返回 false,不会抛异常,很容易漏判。

✅ 两种正确方案:

  1. 混合加密(生产推荐) :前端随机生成AES密钥,RSA加密AES密钥,AES加密业务长文本;后端RSA解出AES密钥,再AES解正文
  2. 分段RSA加密(不推荐,容易中文截断、兼容性差,仅老项目兼容)
ini 复制代码
// 【不推荐】分段加密示例(仅了解,优先AES+RSA)
JSEncrypt.prototype.encryptLong = function(text) {
  const k = this.getKey()
  const max = ((k.n.bitLength()+7)>>3)-11
  let res = ""
  for(let i=0;i<text.length;i+=max){
    const seg = text.substr(i,max)
    res += k.encrypt(seg)
  }
  return res
}

五、安全边界(非常重要)

  1. jsencrypt 不能替代 HTTPS HTTPS是传输底层加密;RSA在这里只是应用层额外保护敏感字段(密码、手机号) ,抓包只能拿到密文,拿不到明文。HTTPS还是必须开。
  2. 前端加密只是防明文抓包,不是防逆向:公钥公开,JS代码可被逆向,RSA本身无法防重放攻击,业务层要加时间戳、随机nonce、签名校验。
  3. 密钥长度:生产禁止1024位,最低2048,推荐4096;1024已经不安全。
  4. 填充模式:PKCS#1 v1.5有历史漏洞;新项目优先 encryptOAEP。

六、常见报错 & 对接坑

  1. encrypt返回false:明文超长、密钥格式错误、密钥首尾标记丢失、换行空格乱码
  2. 后端解密失败:
  • 后端用的是PKCS#8私钥,前端是PKCS#1;

  • 后端填充模式不一致(Java默认有些是OAEP,jsencrypt默认PKCS1)

  1. 中文解密乱码:统一UTF-8,不要用GBK
  2. 密钥生成命令(openssl)
csharp 复制代码
# 生成PKCS#1 RSA私钥(jsencrypt兼容)
openssl genrsa -out private.key 2048
# 从私钥导出公钥(PKCS#8,jsencrypt兼容)
openssl rsa -in private.key -pubout -out public.key

七、和其他加密库对比

库 算法 用途
jsencrypt RSA 非对称,公钥加密、签名验签
crypto-js AES/DES/SHA 对称加密、摘要
jsrsasign RSA/ECC 功能最全,体积大,支持更多标准

八、生产标准架构(最佳实践)

  1. 后端启动生成RSA2048密钥对,私钥保存在服务端,公钥返回前端
  2. 前端:随机生成AES-256密钥
  3. 用RSA公钥加密AES密钥
  4. 用AES加密业务表单/长文本
  5. 请求传给后端:rsaAesKey + aesData
  6. 后端RSA解密得到AES密钥,AES解密正文> > 兼顾RSA密钥分发安全 + AES高速加密长文本,解决RSA长度限制问题
相关推荐
Hilaku3 小时前
你们公司有 35 岁以上的前端吗?
前端·javascript·程序员
鸿蒙开发3 小时前
小程序存档写到一半怎么办?双槽保存与损坏恢复实战
前端·javascript·react.js
知忆_IS4 小时前
TerriaMap 开发实战04:MVT数据自定义符号化 - terriajs源码修改
javascript·webgis·terriamap·terriajs
云上工程笔记6 小时前
SRT字幕一键转手绘动画:srt-whiteboard-animation的复刻实录
大数据·开发语言·javascript·人工智能·机器学习
FungLeo7 小时前
成为全栈·Vue管理后台篇·<scriptsetup>:把页面拆成可读、可测的 Vue 组件
前端·javascript·vue.js·typescript·前端组件化·composition api·vue sfc
清晨Coding19 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
kyriewen19 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
程序员大阳21 小时前
HTML+CSS+JS对话式实战(9)-项目总结与问题分析
javascript·css·html·实战·项目总结
Hilaku1 天前
MCP 协议会成为前端 AI 工程的标准接口吗?
前端·javascript·程序员