Forge:web端与 Node.js 安全开发中的加密与网络通信工具集,支持哈希、对称 / 非对称加密及 TLS 实现
- 一、简介
- 二、安装
- 三、哈希加密
- 四、AES对称加密
- 五、DES对称加密
- 六、ED25519数字签名
- 七、RSA非对称加密
- 八、X.509数字证书
- 九、公钥基础设施 - PKCS#5 (对称密钥的派生与存储)
- 十、公钥基础设施 - PKCS#7 (对称密钥的派生与存储)
- 十一、公钥基础设施 - PKCS#8 (私钥加密)
- 十二、公钥基础设施 - PKCS#10 (证书签名请求)
- 十三、公钥基础设施 - PKCS#12 (打包私钥、公钥证书、CA 证书)
- [十四、公钥基础设施 - ASN.1](#十四、公钥基础设施 - ASN.1)
- 十五、SSH传输协议
- 十六、TLS传输协议
- [十七、forge.pki 通用函数](#十七、forge.pki 通用函数)
- [十八、 util.ByteStringBuffer](#十八、 util.ByteStringBuffer)
- 十九、工具函数
夸克资源分享:
表情包:https://pan.quark.cn/s/5b9ddeb237fe
工具箱:https://pan.quark.cn/s/aa2d6a730482,图吧、美蛋、路遥、入梦等
Fiddler Everywhere抓包:https://pan.quark.cn/s/6b1e2fbae019,
Adobe:https://pan.quark.cn/s/13e39cfeaadb,先看安装教程
JetBranis开发者工具:https://pan.quark.cn/s/16e94dcff1f7,先看安装教程下的jetbra教程
逆向工具:https://pan.quark.cn/s/50e93c8ca54c
数据库工具:https://pan.quark.cn/s/2f14eda13d24
kettle:https://pan.quark.cn/s/62f320634c75
前端项目搭建集锦:https://blog.csdn.net/randy521520/article/details/146998467
前端接单》前端接单 》前端接单: https://www.goofish.com/item?id=1008883794643
一、简介
前端 forge 库是一个专注于加密技术与网络通信的 JavaScript 开源库,提供了原生 TLS(传输层安全)实现及一系列加密相关工具,专为构建加密密集型、网络依赖型 Web 应用设计,在密码学处理、安全通信等场景中具有广泛应用,Git链接:https://gitcode.com/gh_mirrors/for/forge?source_module=search_project。
1.全面的加密算法支持:涵盖多种主流加密相关算法与标准,包括 MD5、SHA1、SHA256 等哈希算法,丰富的对称 / 非对称加密方案,以及 PKCS 系列标准(PKCS1、PKCS7、PKCS12 等),可满足证书处理、数据加密解密、数字签名等核心安全需求。
2.原生 TLS 实现:内置 JavaScript 原生 TLS 协议支持,无需依赖额外底层环境,助力 Web 应用实现安全的网络数据传输,保障通信过程的保密性与完整性。
3.实用工具集:提供加密相关辅助工具,例如证书管理、数据编解码、加密参数配置等,适配 Web 应用开发中各类安全相关场景,降低加密功能开发门槛。
二、安装
javascript
yarn add node-forge
yarn add @types/node-forge --dev
三、哈希加密
javascript
import forge from 'node-forge';
let message = 'hello world!';
let sha1 = forge.md.sha1.create();
sha1.update(message);
console.log('sha1:',sha1.digest().toHex());
let sha256 = forge.md.sha256.create();
sha256.update(message);
console.log('sha256:',sha256.digest().toHex());
let sha384 = forge.md.sha384.create();
sha384.update(message);
console.log('sha384:',sha384.digest().toHex());
let sha512 = forge.md.sha512.create();
sha512.update(message);
console.log('sha512:',sha512.digest().toHex());
let md5 = forge.md.md5.create();
md5.update(message);
console.log('md5:',md5.digest().toHex());
let hmac = forge.hmac.create();
hmac.start('sha1', 'Jefe');
hmac.update( message);
console.log('hmac:',hmac.digest().toHex());

四、AES对称加密
1.支持AES-ECB、AES-CBC、AES-CFB、AES-OFB、AES-CTR、AES-GCM
| 加密模式 | 核心特性 | 优点 | 缺点 | 适用场景 | 不适场景 |
|---|---|---|---|---|---|
| AES-ECB | 电子密码本模式,相同明文加密结果相同;分组独立加密 | 1. 算法简单,运算速度最快; 2. 无需维护IV,实现成本低; 3. 支持并行加密/解密(分组独立) | 1. 安全性极差,易暴露明文规律(如重复明文对应重复密文); 2. 无完整性校验,密文易被篡改; 3. 无法隐藏明文结构(如图片加密后仍能看到轮廓) | 1. 加密少量无规律的固定数据(如密码本身的加密存储); 2. 对安全性要求极低的测试场景; 3. 作为其他加密模式的底层辅助 | 1. 传输类数据(如接口请求、文件传输); 2. 敏感数据(如密码、金融信息); 3. 大量重复明文数据 |
| AES-CBC | 密码分组链接模式,需16字节IV;前一分组密文参与后一分组加密 | 1. 安全性优于ECB,相同明文加密结果不同; 2. 兼容性极强,几乎所有加密库都支持; 3. 实现简单,部署成本低 | 1. 不支持并行加密(需依赖前一分组结果); 2. 无内置完整性校验,需额外添加哈希校验(如SHA256); 3. IV若泄露或重复,会降低安全性; 4. 密文一位篡改会导致后续分组明文乱码 | 1. 传统系统的兼容性加密(如老旧项目数据存储); 2. 对性能要求不高的静态数据加密(如本地配置文件加密); 3. 非实时性的数据备份加密 | 1. 高并发实时通信(如视频流、即时消息); 2. 需并行处理的大规模数据加密; 3. 对完整性要求极高的金融场景 |
| AES-CFB | 密文反馈模式,需IV;将前一分组密文加密后与明文异或得到密文;支持按位/按字节加密 | 1. 无需对明文进行分组填充(支持任意长度明文); 2. 安全性优于CBC,密文篡改影响范围小; 3. 可实现流式加密(适合分段传输数据) | 1. 不支持并行加密(依赖前一分组结果); 2. 加密速度慢于CBC; 3. 无内置完整性校验,需额外校验; 4. 解密需依赖加密时的反馈状态,断流后需重新同步 | 1. 流式数据加密(如串口通信、分段传输的文件); 2. 需处理非固定长度明文的场景(如实时日志加密); 3. 网络不稳定的远程数据传输 | 1. 高并发批量数据加密; 2. 对速度要求极高的场景; 3. 需完整性自动校验的敏感场景 |
| AES-OFB | 输出反馈模式,需IV;将加密器输出的伪随机流与明文异或得到密文;分组独立生成伪随机流 | 1. 无需对明文分组填充(支持任意长度明文); 2. 支持并行解密(伪随机流独立生成); 3. 密文一位篡改仅导致明文对应位错误,影响范围小; 4. 适合流式传输,断流后恢复简单 | 1. 不支持并行加密(伪随机流生成依赖前一分组); 2. 无内置完整性校验,易被篡改; 3. 伪随机流若泄露,明文可被还原; 4. 加密速度慢于CBC | 1. 实时流式数据传输(如音频、视频流加密); 2. 网络不稳定的远程数据交互(如卫星通信); 3. 需分段解密的大型文件 | 1. 高并发批量数据加密; 2. 对完整性要求极高的金融、涉密场景; 3. 对加密速度要求严苛的场景 |
| AES-CTR | 计数器模式,需IV(计数器初始值);通过计数器生成伪随机流,与明文异或得到密文 | 1. 支持并行加密/解密(计数器独立,伪随机流可并行生成); 2. 无需明文分组填充(支持任意长度明文); 3. 加密和解密使用同一套逻辑(仅计数器递增方式不同); 4. 安全性高,密文无规律; 5. 适合流式数据,断流后可通过计数器偏移恢复 | 1. 无内置完整性校验,需额外添加校验机制; 2. 计数器若被篡改,会导致后续明文全部乱码; 3. IV(计数器初始值)需唯一,不可重复使用 | 1. 高并发实时通信(如即时消息、视频会议流); 2. 大规模数据并行处理(如云存储文件加密); 3. 流式数据传输(如物联网设备数据上报); 4. 对性能要求较高的分布式系统 | 1. 对完整性要求极高且无法额外添加校验的场景; 2. 计数器易被篡改的不安全环境; 3. 老旧不支持并行处理的系统 |
| AES-GCM | 伽罗瓦/计数器模式,AEAD认证加密模式;需12/16字节IV;支持additionalData;内置认证标签(Tag) | 1. 一站式实现"加密+完整性校验+身份认证",安全性最高; 2. 支持并行加密/解密(基于CTR模式扩展); 3. 无需明文分组填充,支持任意长度明文; 4. 可传递附加认证数据(AAD),验证关联元数据; 5. 加密效率高,兼顾安全与性能 | 1. 实现复杂度高于非AEAD模式; 2. 对IV唯一性要求极高(重复IV会导致密钥泄露); 3. 部分老旧加密库不支持; 4. 认证标签需随密文一起传输,增加少量数据开销 | 1. 高安全要求的敏感数据传输(如金融交易、支付接口); 2. 物联网设备通信(如智能家居、工业设备数据加密); 3. 安全文件传输(如涉密文档、备份文件); 4. 接口加密(如前后端、微服务之间的通信); 5. 需验证元数据完整性的场景 | 1. 兼容性要求极高的老旧系统; 2. 对加密复杂度敏感的极简设备(如低端嵌入式设备); 3. 对安全性要求极低的测试场景 |
| 1. 安全性排序(从低到高):AES-ECB < AES-CBC < AES-CFB ≈ AES-OFB < AES-CTR < AES-GCM 2. 性能排序(从快到慢):AES-ECB > AES-CBC > AES-CTR ≈ AES-GCM > AES-OFB > AES-CFB 3. 核心选型原则: • 优先选择AES-GCM:绝大多数现代场景的最优解,兼顾安全、性能和功能完整性; • 兼容老旧系统选AES-CBC:兼容性最强,需额外添加哈希校验弥补完整性缺陷; • 实时流式传输选AES-CTR/AES-OFB:支持并行处理或断流恢复,适合音视频、物联网数据; • 绝对避免AES-ECB:仅用于极低安全要求的边缘场景,不可用于敏感数据处理。 |
2.AES-ECB加密(AES-128)
javascript
import forge from 'node-forge';
//密钥大小将决定使用 16 字节(AES-128)、24 字节(AES-192)或 32 字节(AES-256)
let key = forge.random.getBytesSync(16);
let iv = forge.random.getBytesSync(16);
let message = 'hello world!';
//支持AES-ECB、AES-CBC、AES-CFB、AES-OFB、AES-CTR、AES-GCM
let cipher = forge.cipher.createCipher('AES-ECB', key);
cipher.start({ iv: iv });
cipher.update(forge.util.createBuffer(message));
cipher.finish();
let encrypted = cipher.output;
let encryptedHex = encrypted.toHex();
console.log('加密结果:', encryptedHex);
let decipher = forge.cipher.createDecipher('AES-ECB', key);
decipher.start({ iv: iv });
decipher.update(forge.util.createBuffer(forge.util.hexToBytes(encryptedHex)));
decipher.finish();
console.log('解密结果:', decipher.output.toString());

3.AES-CBC加密(AES-192)
javascript
import forge from 'node-forge';
let message = 'hello world!';
const sha256 = forge.md.sha256.create();
sha256.update(message);
console.log(sha256.digest().toHex());
//密钥大小将决定使用 16 字节(AES-128)、24 字节(AES-192)或 32 字节(AES-256)
let key = forge.random.getBytesSync(24);
let iv = forge.random.getBytesSync(16);
//支持AES-ECB、AES-CBC、AES-CFB、AES-OFB、AES-CTR、AES-GCM
let cipher = forge.cipher.createCipher('AES-CBC', key);
cipher.start({ iv: iv });
cipher.update(forge.util.createBuffer(`${message},${sha256.digest().toHex()}`));
cipher.finish();
let encrypted = cipher.output;
let encryptedHex = encrypted.toHex();
console.log('加密结果:', encryptedHex);
let decipher = forge.cipher.createDecipher('AES-CBC', key);
decipher.start({ iv: iv });
decipher.update(forge.util.createBuffer(forge.util.hexToBytes(encryptedHex)));
decipher.finish();
console.log('解密结果:', decipher.output.toString().split(',')[0]);

4.AES-GCM加密(AES-256)
javascript
import forge from 'node-forge';
//密钥大小将决定使用 16 字节(AES-128)、24 字节(AES-192)或 32 字节(AES-256)
let key = forge.random.getBytesSync(32);
let iv = forge.random.getBytesSync(16);
let message = 'hello world!';
//支持AES-ECB、AES-CBC、AES-CFB、AES-OFB、AES-CTR、AES-GCM
let cipher = forge.cipher.createCipher('AES-GCM', key);
cipher.start({
iv: iv,
additionalData: '附加数据',
tagLength: 128
});
cipher.update(forge.util.createBuffer(message));
cipher.finish();
let encrypted = cipher.output;
let encryptedHex = encrypted.toHex();
console.log('加密结果:', encryptedHex);
let decipher = forge.cipher.createDecipher('AES-GCM', key);
decipher.start({
iv: iv,
additionalData: '附加数据',
tagLength: 128,
tag: cipher.mode.tag
});
decipher.update(forge.util.createBuffer(forge.util.hexToBytes(encryptedHex)));
decipher.finish();
console.log('解密结果:', decipher.output.toString());

5.分块加密,适合长密文
javascript
import forge from 'node-forge';
let key = forge.random.getBytesSync(16);
let iv = forge.random.getBytesSync(16);
const originalPlainText = `
时间是一个智者,不疾不徐地告诉我三个"最"。经历的越多,我就越能明白时间想要告诉我的"最"是什么。我想要寻找的是长远、安心和温暖,时间指引着我寻找它们。
一、最长远的是简单
很多东西一旦变得复杂了,就会让人觉得索然无味,即使之前再怎么喜欢,也会很快失去兴趣,然后去寻找下一件能够让自己喜欢的东西。但是在这个最不缺改变的世界中,简单也许是稀缺品。越是稀缺,我们越是珍惜,想方设法守护这份简单,让简单一直延续下去。
就像友情,我最好的朋友都是在学生时代结交的,而进入职场后交到的朋友大多都是泛泛之交。因为在校园里,我们没有太多的利益冲突,只要臭味相投,都可 这样的友谊相对来说比较简单,往往能够长久。当进入激烈的社会竞争中,大家都有个人的利益追求,友谊有时候就是利益的踏板,真诚的成分有多少大家心中有数。当没有利用价值了,这样的友谊往往名存实亡。
二、最安心的是平凡的陪伴
虽然大家都在努力地工作赚钱,觉得有车、有房、有存款才有安全感,但是物质上的满足带来的安全感只是表面的、暂时的。人最高的需求并不在于物质,而在于精神,精神上得到的满足远比物质上得到的满足来得更持久、更安心。最令人安心的是平凡的陪伴,无论富有或是贫穷,无论貌美或平凡,都能陪伴在自己身边。在这样的陪伴下,心就能安定下来了。不需要担心任何事情,因为你知道对方一定会陪着你面对所有事情,就像多了一个坚实的后盾,和你不离不弃。
三、最温暖的是懂得
随着阅历的增加,你懂得越多,能懂你的人就越少,因为你已经习惯理解别人,却不是每个人都能同样理解你的酸甜苦辣。当你受到太多来自世界的薄情时,你最渴望的大概就是一份真正的懂得吧。这份懂得, 因为你知道,就算全世界都不理解你也没有关系,只要有一个人懂你就足够了。你会明白你需要的不是所有人的理解,仅仅需要一份真心的懂得。成功了,别人只会看到你的风光,但只有懂你的人才会知道你付出了多少;失败了,别人只会嘲笑你的无能,但只有懂你i的人才会鼓励你不要放弃。最温暖的是懂得,它会给予你勇气和信心。
时间告诉我三个"最":最长远的是简单,最安心的是平凡的陪伴,最温暖的是懂得。我认为人活一世,最需要的正是长远、安心和温暖。时间把方向告诉了我,我会朝着这个方向寻找。也许要用一辈子的时间,才能得到,但是我相信在这个寻找的过程中,我也会得到快乐和成长,这大概也是时间给我的赠礼吧。
`;
const plainTextBytes = forge.util.encodeUtf8(originalPlainText);
let cipher = forge.cipher.createCipher('AES-CFB', key);
cipher.start({ iv: iv });
let length = plainTextBytes.length;
let chunkSize = 1024;
let index = 0;
do {
let buf = forge.util.createBuffer(plainTextBytes.slice(index, index + chunkSize));
cipher.update(buf);
index += chunkSize;
} while(index < length);
cipher.finish();
const encrypted = cipher.output; // 加密后的缓冲区
const encryptedBytes = encrypted.bytes(); // 密文字节串
//分块解密
let decryptIndex = 0;
const decipher = forge.cipher.createDecipher('AES-CFB', key);
decipher.start({ iv: iv });
do {
const currentDecryptChunk = encryptedBytes.slice(decryptIndex, decryptIndex + chunkSize);
const buf = forge.util.createBuffer(currentDecryptChunk);
decipher.update(buf);
decryptIndex += chunkSize;
} while (decryptIndex < encryptedBytes.length);
decipher.finish();
console.log('==============解密结果==============');
console.log(decipher.output.toString());

6.加密对象:forge.cipher.createCipher(algorithm, payload)、解密对象:decipher = forge.cipher.createDecipher(algorithm, payload),返回BlockCipher对象
| 属性 | 类型 | 参数说明 | 返回值 / 属性值说明 | 详细说明 |
|---|---|---|---|---|
| start | Function | options: 可选, 类型为StartOptions, 是加密/解密的启动配置项, 包含: iv(初始向量) tag(认证标签) tagLength(标签长度) additionalData(附加认证数据) 等属性 | 无返回值 | 用于启动加密或解密流程, 必须在update方法之前调用, 传入的配置项需与加密/解密模式匹配(如GCM模式需传入tag, CBC模式需传入iv) |
| update | Function | payload: 必传, 类型为util.ByteStringBuffer, 是待加密的明文缓冲区或待解密的密文缓冲区, 支持分块传入 | 无返回值 | 用于处理待加密/解密的数据, 可多次分块调用(适合处理大文本、大文件等海量数据), 数据会逐步处理并写入output属性 |
| finish | Function | 无参数 | 布尔(boolean): true表示加密/解密流程完全成功; false表示流程失败(常见原因: 密钥不匹配、IV错误、密文被篡改、模式配置异常) | 用于完成最终的加密/解密处理, 包括数据填充补全、认证校验等收尾操作, 调用后才能获取完整的output结果 |
| output | util.ByteStringBuffer | - | 详情见文章中的"util.ByteStringBuffer" | 存储加密后的完整密文或解密后的完整明文, 为forge专属缓冲区类型, 可通过bytes()转为字节串、toHex()转为十六进制字符串、toString()转为普通文本 |
| mode | Mode | - | mode.tag: util.ByteStringBuffer | 存储加密/解密的模式专属对象, 该对象实现了Mode接口, 包含模式特有属性(如GCM模式下的tag认证标签), 仅用于获取模式相关的附加数据 |
五、DES对称加密
1.支持3DES-ECB、3DES-CBC、DES-ECB、DES-CBC
| 加密算法 | 核心特性 | 优点 | 缺点 | 适用场景 | 不适用场景 |
|---|---|---|---|---|---|
| 3DES-ECB | 3重DES(168位密钥)+ 电子密码本模式;无IV,相同明文加密结果相同;分组独立加密 | 1. 密钥长度(168位)比DES安全; 2. 算法简单,运算速度较快; 3. 支持并行加密/解密 | 1. ECB模式安全性弱,易暴露明文规律; 2. 无完整性校验,密文易被篡改; 3. 加密效率低于AES | 1. 老旧系统兼容场景(需替换DES但无法升级AES); 2. 对安全性要求不高的历史数据加密 | 1. 新系统开发(优先选AES); 2. 敏感数据(如金融、隐私信息); 3. 大量重复明文数据 |
| 3DES-CBC | 3重DES + 密码分组链接模式;需8字节IV;前一分组密文参与后一分组加密 | 1. 安全性优于3DES-ECB,相同明文加密结果不同; 2. 兼容性强,老旧加密库普遍支持; 3. 比DES更抗暴力破解 | 1. 不支持并行加密; 2. 无内置完整性校验; 3. 加密效率低(比AES慢数倍); 4. IV若重复会降低安全性 | 1. 老旧金融/通信系统的历史数据加密; 2. 需兼容早期3DES协议的场景 | 1. 高并发/高性能场景; 2. 新系统开发; 3. 大体积数据加密 |
| DES-ECB | DES(56位密钥)+ 电子密码本模式;无IV,分组独立加密 | 1. 算法最简单,运算速度快; 2. 实现成本极低,兼容性极强 | 1. 密钥长度过短(56位),易被暴力破解; 2. ECB模式安全漏洞大,明文规律易暴露; 3. 已被密码学标准淘汰 | 1. 仅用于极低安全要求的历史遗留系统(无替代方案时); 2. 测试/演示场景 | 1. 所有实际生产场景; 2. 任何敏感数据处理; 3. 新系统开发 |
| DES-CBC | DES + 密码分组链接模式;需8字节IV;分组依赖前一分组密文 | 1. 安全性略优于DES-ECB; 2. 兼容性极强,早期系统广泛支持 | 1. 密钥长度过短(56位),安全风险极高; 2. 加密效率低,且无完整性校验; 3. 已被现代密码学标准废弃 | 1. 仅用于无法升级的远古遗留系统(迫不得已时) | 1. 所有生产环境; 2. 敏感数据场景; 3. 新系统/新功能开发 |
| 1. 安全性排序:3DES-CBC > 3DES-ECB > DES-CBC > DES-ECB 2. 性能排序:DES-ECB > DES-CBC > 3DES-ECB > 3DES-CBC 3. 选型原则: • 优先避免使用DES/3DES,现代场景必须选AES; • 仅在老旧系统兼容时使用3DES(优先选3DES-CBC); • 绝对禁止在新系统中使用DES(已完全不安全)。 |
2.3DES-CBC加密
javascript
import forge from 'node-forge';
//密钥大小将决定使用 24 字节(3DES-CBC、3DES-ECB)
let key = forge.random.getBytesSync(24);
let iv = forge.random.getBytesSync(8);
let message = 'hello world!';
//支持3DES-ECB、3DES-CBC、DES-ECB、DES-CBC
let cipher = forge.cipher.createCipher('3DES-CBC', key);
cipher.start({ iv: iv });
cipher.update(forge.util.createBuffer(message));
cipher.finish();
let encrypted = cipher.output;
let encryptedHex = encrypted.toHex();
console.log('加密结果:', encryptedHex);
let decipher = forge.cipher.createDecipher('3DES-CBC', key);
decipher.start({ iv: iv });
decipher.update(forge.util.createBuffer(forge.util.hexToBytes(encryptedHex)));
decipher.finish();
console.log('解密结果:', decipher.output.toString());

3.DES-ECB加密
javascript
import forge from 'node-forge';
//密钥大小将决定使用 8 字节(DES-ECB、DES-CBC)
let key = forge.random.getBytesSync(8);
let iv = forge.random.getBytesSync(8);
let message = 'hello world!';
//支持3DES-ECB、3DES-CBC、DES-ECB、DES-CBC
let cipher = forge.cipher.createCipher('DES-ECB', key);
cipher.start({ iv: iv });
cipher.update(forge.util.createBuffer(message));
cipher.finish();
let encrypted = cipher.output;
let encryptedHex = encrypted.toHex();
console.log('加密结果:', encryptedHex);
let decipher = forge.cipher.createDecipher('DES-ECB', key);
decipher.start({ iv: iv });
decipher.update(forge.util.createBuffer(forge.util.hexToBytes(encryptedHex)));
decipher.finish();
console.log('解密结果:', decipher.output.toString());

六、ED25519数字签名
ED25519基于椭圆曲线的数字签名算法,其密钥长度为 256 位,签名长度为 64 字节。
优点
- 运算速度远快于 RSA;
- 密钥 / 签名长度短,传输、存储成本低;
- 安全性高,具备抗量子攻击的潜力。
缺点
- 兼容性弱于 RSA,部分老旧系统不支持;
- 仅支持签名、验签操作,不支持加密、解密功能。
适用场景
- 现代应用的数字签名场景,比如区块链、API 接口身份认证;
- 移动设备、物联网等轻量级安全场景。
1.普通消息签名
javascript
import forge from 'node-forge';
let ed25519 = forge.pki.ed25519;
let password = 'Mai9ohgh6ahxee0jutheew0pungoozil';
const seed = forge.util.encodeUtf8(password);
let keypair = ed25519.generateKeyPair({ seed: seed });
let signature = ed25519.sign({
message: 'hello world!',
encoding: 'utf8',
privateKey: keypair.privateKey
});
let verify = ed25519.verify({
message: 'hello world!',
encoding: 'utf8',
publicKey: keypair.publicKey,
signature: signature
});
if (verify) {
console.log('🎉 验签通过!消息未被篡改,签名合法有效');
} else {
console.error('❌ 验签失败!消息已被篡改或签名不合法');
}

2.二进制数据签名
javascript
import forge from 'node-forge';
let ed25519 = forge.pki.ed25519;
let password = 'Mai9ohgh6ahxee0jutheew0pungoozil';
const seed = forge.util.encodeUtf8(password);
let keypair = ed25519.generateKeyPair({ seed: seed });
let signature = ed25519.sign({
message: Buffer.from('hello world!', 'utf8'),
privateKey: keypair.privateKey
});
let verify = ed25519.verify({
message: Buffer.from('hello world!', 'utf8'),
publicKey: keypair.publicKey,
signature: signature
});
if (verify) {
console.log('🎉 验签通过!消息未被篡改,签名合法有效');
} else {
console.error('❌ 验签失败!消息已被篡改或签名不合法');
}

3.哈希签名
javascript
import forge from 'node-forge';
let ed25519 = forge.pki.ed25519;
let password = 'Mai9ohgh6ahxee0jutheew0pungoozil';
const seed = forge.util.encodeUtf8(password);
let keypair = ed25519.generateKeyPair({ seed: seed });
let sha256 = forge.md.sha256.create();
sha256.update('hello world!', 'utf8');
let signature = ed25519.sign({
md: sha256,
privateKey: keypair.privateKey
});
let verify = ed25519.verify({
md: sha256,
publicKey: keypair.publicKey,
signature: signature
});
if (verify) {
console.log('🎉 验签通过!消息未被篡改,签名合法有效');
} else {
console.error('❌ 验签失败!消息已被篡改或签名不合法');
}

4.forge.pki.ed25519对象
| 函数名 | 功能描述 | 参数说明 | 返回值说明 |
|---|---|---|---|
| generateKeyPair | 生成公钥/私钥对 | options:加密/解密的启动配置项 -seed:种子,支持Buffer|Uint8Array|String | 生成ED25519密钥对,可选传入种子生成确定性密钥对 |
| privateKeyFromAsn1 | 从ASN.1编码对象中解析提取ED25519私钥 | obj:必传,ASN.1编码格式的对象,包含私钥信息 | 返回包含私钥字节数据的对象,privateKeyBytes为Buffer|Uint8Array类型的私钥数据 |
| publicKeyFromAsn1 | 从ASN.1编码对象中解析提取ED25519公钥 | obj:必传,ASN.1编码格式的对象,包含公钥信息 | 返回Buffer|Uint8Array类型的ED25519公钥 |
| publicKeyFromPrivateKey | 从ED25519私钥中推导对应的公钥(ED25519特性:私钥可推导公钥) | options:必传配置对象 -options.privateKey:ED25519私钥,支持NativeBuffer、forge ByteBuffer、二进制字符串 | 返回Buffer|Uint8Array类型的对应公钥(与私钥配对) |
| sign | 对消息进行ED25519签名,生成不可篡改的数字签名 | options:必传配置对象 -md:哈希加密对象 -message:普通消息加密 -encoding:编码,支持"binary"|"utf8" -privateKey:签名用私钥,支持BinaryBuffer类型 | 返回Buffer|Uint8Array类型的ED25519签名(固定64字节) |
| verify | 验证ED25519签名的有效性,确认消息是否被篡改、签名是否合法 | options:必传配置对象 -md:哈希加密对象 -message:普通消息加密 -encoding:编码,支持"binary"|"utf8" -signature:待验证的签名,支持BinaryBuffer类型 -publicKey:配对的公钥,支持BinaryBuffer类型 | 返回布尔值: true表示验签通过(消息未篡改、签名合法); false表示验签失败(消息篡改或签名非法) |
七、RSA非对称加密
| 名称 | 核心特性 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| RSA | 基于大整数分解难题,支持加密/解密、签名/验签,常用密钥长度2048/4096位 | 1. 兼容性极强,所有加密库/系统均支持; 2. 功能全面(加密+签名) | 1. 运算速度慢(尤其是4096位密钥); 2. 密钥/密文长度长,资源消耗大; 3. 抗量子攻击能力弱 | 1. 传统系统的加密/签名(如HTTPS证书、文件加密); 2. 需兼容老旧设备的场景 |
| RSA-KEM | 基于RSA的密钥封装算法,用于安全传输对称密钥 | 1. 解决RSA直接加密大数据的效率问题; 2. 安全性依赖RSA的数学难题 | 1. 仅用于密钥封装,功能单一; 2. 效率仍低于椭圆曲线类KEM | 1. 对称密钥的安全分发(如AES密钥通过RSA-KEM传输); 2. 传统加密系统的密钥交换 |
1.哈希签名
javascript
import forge from 'node-forge';
let rsa = forge.pki.rsa;
let keypair = rsa.generateKeyPair({ bits: 2048, e: 65537 });
let sha1 = forge.md.sha1.create();
sha1.update('hello world', 'utf8');
let signature = keypair.privateKey.sign(sha1);
let verify = keypair.publicKey.verify(sha1.digest().bytes(), signature);
if (verify) {
console.log('🎉 验签通过!消息未被篡改,签名合法有效');
} else {
console.error('❌ 验签失败!消息已被篡改或签名不合法');
}

2.RSA-PSS签名
javascript
import forge from 'node-forge';
let rsa = forge.pki.rsa;
let keypair = rsa.generateKeyPair({ bits: 2048, e: 65537 });
let sha1 = forge.md.sha1.create();
sha1.update('hello world', 'utf8');
let pss = forge.pss.create({
md: forge.md.sha1.create(),
mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),
saltLength: 20
});
let signature = keypair.privateKey.sign(sha1, pss);
let verify = keypair.publicKey.verify(sha1.digest().getBytes(), signature, pss);
if (verify) {
console.log('🎉 验签通过!消息未被篡改,签名合法有效');
} else {
console.error('❌ 验签失败!消息已被篡改或签名不合法');
}

3.RSA数据加密
javascript
import forge from 'node-forge';
let rsa = forge.pki.rsa;
let keypair = rsa.generateKeyPair({ bits: 2048, e: 65537 });
const plainText = 'hello world';
const encrypted = keypair.publicKey.encrypt(plainText);
console.log('加密后的密文:', forge.util.bytesToHex(encrypted));
const decrypted = keypair.privateKey.decrypt(encrypted);
console.log('解密后的明文:', decrypted);
console.log('');
const encryptedRSAES = keypair.publicKey.encrypt(plainText,'RSAES-PKCS1-V1_5');
console.log('RSAES加密后的密文:', forge.util.bytesToHex(encryptedRSAES));
const decryptedRSAES = keypair.privateKey.decrypt(encryptedRSAES,'RSAES-PKCS1-V1_5');
console.log('RSAES解密后的明文:', decryptedRSAES);
console.log('');
const encryptedRSA = keypair.publicKey.encrypt(plainText,'RSA-OAEP');
console.log('RSA加密后的密文:', forge.util.bytesToHex(encryptedRSA));
const decryptedRSA = keypair.privateKey.decrypt(encryptedRSA,'RSA-OAEP');
console.log('RSA解密后的明文:', decryptedRSA);
console.log('');
let encryptedRSASha256 = keypair.publicKey.encrypt(plainText, 'RSA-OAEP', {
md: forge.md.sha256.create(),
mgf1: {
md: forge.md.sha1.create()
}
});
let decryptedRSASha256 = keypair.privateKey.decrypt(encryptedRSASha256, 'RSA-OAEP', {
md: forge.md.sha256.create(),
mgf1: {
md: forge.md.sha1.create()
}
});
console.log('RSA-SHA256加密后的密文:', forge.util.bytesToHex(encryptedRSASha256));
console.log('RSA-SHA256解密后的明文:', decryptedRSASha256);

4.RSA-KEM密钥交换
javascript
import forge from 'node-forge';
// 通信方A生成RSA密钥对,公开公钥
let rsa = forge.pki.rsa;
let keypair = rsa.generateKeyPair({ bits: 2048, e: 65537 });
// 通信方B用RSA-KEM封装对称密钥
let kdf1 = new forge.kem.kdf1(forge.md.sha1.create());
let kem = forge.kem.rsa.create(kdf1);
let result = kem.encrypt(keypair.publicKey, 16); // 封装生成对称密钥(长度16对应AES-128)
const aesKey = kem.decrypt(keypair.privateKey, result.encapsulation, 16);// 3B将封装结果(encapsulation)发送给A,A用私钥解密,得到对称密钥
const plainText = 'hello world';
let iv = forge.random.getBytesSync(12);
let cipher = forge.cipher.createCipher('AES-GCM', result.key);
cipher.start({ iv: iv });
cipher.update(forge.util.createBuffer( plainText));
cipher.finish();
let encrypted = cipher.output.getBytes();
let tag = cipher.mode.tag.getBytes();
console.log('\nAES-GCM加密结果:');
console.log('密文:', forge.util.bytesToHex(encrypted));
console.log('IV:', forge.util.bytesToHex(iv));
console.log('认证标签:', forge.util.bytesToHex(tag));
let decipher = forge.cipher.createDecipher('AES-GCM', aesKey);
decipher.start({ iv: iv, tag: tag, tagLength: 128 });
decipher.update(forge.util.createBuffer(encrypted));
decipher.finish();
console.log('\nAES-GCM解密结果:', decipher.output.toString());

5.forge.pki.ed25519对象
| 函数名 | 功能描述 | 参数说明 | 返回值说明 |
|---|---|---|---|
| generateKeyPair | 生成RSA密钥对,支持两种参数格式,可选异步回调(适用于大密钥位数生成) | options:配置对象 • bits:可选,number类型,RSA密钥位数,常用2048/4096,默认无,推荐2048 • e:可选,number类型,RSA公钥指数,默认65537(0x10001),为工业标准值 • workerScript:可选,string类型,浏览器环境下Web Worker脚本路径,用于异步生成大位数密钥 • workers:可选,number类型,配合workerScript的Web Worker数量,默认1 • workLoad:可选,number类型,每个Web Worker的工作负载分配参数 • prng:可选,any类型,伪随机数生成器,默认用forge内置安全PRNG • algorithm:可选,string类型,密钥生成算法类型,默认"rsa" callback:可选,异步回调函数 | 返回KeyPair类型的RSA密钥对对象,包含publicKey(公钥)和privateKey(私钥)两个属性 |
6.公钥对象
| 属性名 | 类型 | 详细说明 | 参数说明 | 返回值说明 |
|---|---|---|---|---|
| n | number | RSA公钥的模数,是一个超大整数,由两个大素数p和q相乘得到,是RSA算法的核心参数之一 | - | - |
| e | number | RSA公钥的指数(公共指数),常用值为65537(0x10001),与私钥指数d对应,用于加密和验签运算 | - | - |
| encrypt | Function | 用于对明文进行RSA加密,遵循"公钥加密"原则,只有对应的私钥才能解密该密文 | 1. data:必传,Bytes类型,待加密的明文数据(二进制字符串/字节) 2. scheme:可选,加密方案,支持"RSAES-PKCS1-V1_5"、"RSA-OAEP"、"RAW"等 3. schemeOptions:可选,对应加密方案的配置项(如OAEP模式的哈希算法) | 加密后的密文数据(二进制格式) |
| verify | Function | 用于验证数字签名的有效性,遵循"公钥验签"原则,验证签名是否由对应私钥生成,消息是否完整 | 1. digest:必传,Bytes类型,原始消息的哈希摘要数据 2. signature:必传,Bytes类型,待验证的数字签名(二进制格式) 3. scheme:可选,签名验证方案,支持"RSASSA-PKCS1-V1_5"、"PSS"等 | 布尔值(boolean): true表示验签通过,签名合法且消息未被改; false表示验签失败 |
7.私钥对象
| 属性名 | 类型 | 详细说明 | 参数说明 | 返回值说明 |
|---|---|---|---|---|
| n | number | RSA私钥的模数,与对应公钥的模数n完全一致,由大素数p和q相乘得到 | - | - |
| e | number | RSA私钥中存储的公钥指数,与对应公钥的指数e完全一致,仅用于参数完整性存储 | - | - |
| d | number | RSA私钥的核心指数(私钥指数),是公钥指数e关于(p-1)(q-1)的模逆元,用于解密和签名运算 | - | - |
| p | number | 生成模数n的大素数因子之一,属于私钥核心机密,不可泄露 | - | - |
| q | number | 生成模数n的另一个大素数因子之一,与p成对存在,属于私钥核心机密 | - | - |
| dP | number | 私钥指数d关于(p-1)的模逆元(即d mod (p-1)),用于优化RSA运算速度 | - | - |
| dQ | number | 私钥指数d关于(q-1)的模逆元(即d mod (q-1)),用于优化RSA运算速度 | - | - |
| qInv | number | 素数q关于素数p的模逆元(即q^-1 mod p),用于优化RSA解密和签名效率 | - | - |
| decrypt | Function | 用于对密文进行RSA解密,遵循"私钥解密"原则,仅能解密对应公钥加密的密文 | 1. data:必传,Bytes,待解密的密文数据(二进制格式) 2. scheme:可选,解密方案,需与加密时的scheme一致 3. schemeOptions:可选,对应解密方案的配置项 | 解密后的明文数据(二进制格式) |
| sign | Function | 生成数字签名(二进制格式),遵循"私钥签名"原则,仅能由对应公钥验证 | 1. md:必传,哈希对象 2. scheme:可选,签名验证方案,支持"RSASSA-PKCS1-V1_5"、"PSS"等 | 二进制签名 |
八、X.509数字证书
X.509 是一种数字证书格式标准,其证书内容包含公钥、身份信息、签发者签名等核心数据,是网络安全领域中广泛使用的证书规范。
优点
- 是 HTTPS/SSL/TLS 协议的核心证书格式,支撑了主流网络通信的安全加密;
- 支持证书链信任体系,可通过多级 CA(证书颁发机构)实现跨机构的身份信任传递。
缺点
- 格式设计复杂,对证书的解析、处理需要额外的技术成本;
- 证书吊销机制(如 CRL 证书吊销列表、OCSP 在线证书状态协议)存在效率问题,可能影响验证速度。
适用场景
- 网络通信的身份认证:如网站 HTTPS 证书、代码签名证书等;
- 企业级 PKI(公钥基础设施)体系:用于企业内部的身份管理、数据加密等安全场景。
1.X.509密钥转换
javascript
import forge from 'node-forge';
let pki = forge.pki;
// 生成简易RSA密钥对(2048位,快速生成)
const rsaKeypair = pki.rsa.generateKeyPair({ bits: 2048, e: 65537 });
console.log('1. 原始RSA公钥对象:', rsaKeypair.publicKey);
// 将Forge公钥转为PEM格式
const pemPublicKey = pki.publicKeyToPem(rsaKeypair.publicKey);
console.log('2. RSA公钥转换为PEM格式:', pemPublicKey);
// 将PEM格式公钥解析为Forge公钥
let publicKey = pki.publicKeyFromPem(pemPublicKey);
console.log('3. PEM格式公钥解析为RSA公钥对象:', publicKey);
// 将Forge公钥转为ASN.1 SubjectPublicKeyInfo
let subjectPublicKeyInfo = pki.publicKeyToAsn1(publicKey);
console.log('4. RSA公钥转换为ASN.1 SubjectPublicKeyInfo格式:', subjectPublicKeyInfo);
// 将ASN.1 SubjectPublicKeyInfo解析为Forge公钥
publicKey = pki.publicKeyFromAsn1(subjectPublicKeyInfo);
console.log('5. ASN.1格式解析为RSA公钥对象:', publicKey);
// 获取SHA-1算法的RSAPublicKey格式指纹(字节缓冲)
const fingerprint = pki.getPublicKeyFingerprint(publicKey);
console.log('6. SHA-1 RSAPublicKey格式公钥指纹(字节缓冲):', fingerprint);
// 获取SHA-1算法的SubjectPublicKeyInfo格式指纹(字节缓冲)
const spkiFingerprint = pki.getPublicKeyFingerprint(publicKey, { type: 'SubjectPublicKeyInfo' });
console.log('7. SHA-1 SubjectPublicKeyInfo格式公钥指纹(字节缓冲):', spkiFingerprint);
// 获取16进制、冒号分隔的SHA-1 RSAPublicKey格式公钥指纹
const spkiFingerprintHex = pki.getPublicKeyFingerprint(publicKey, { encoding: 'hex', delimiter: ':' });
console.log('8. 16进制冒号分隔的SHA-1 RSAPublicKey格式公钥指纹:', spkiFingerprintHex);
// 获取16进制、冒号分隔的SHA-1 SubjectPublicKeyInfo格式公钥指纹
const spkiFingerprintHexColon = pki.getPublicKeyFingerprint(publicKey, {
type: 'SubjectPublicKeyInfo',
encoding: 'hex',
delimiter: ':'
});
console.log('9. 16进制冒号分隔的SHA-1 SubjectPublicKeyInfo格式公钥指纹:', spkiFingerprintHexColon);
// 获取16进制、冒号分隔的MD5 RSAPublicKey格式公钥指纹
const rsaFingerprintHexColon = pki.getPublicKeyFingerprint(publicKey, {
md: forge.md.md5.create(),
encoding: 'hex',
delimiter: ':'
});
console.log('10. 16进制冒号分隔的MD5 RSAPublicKey格式公钥指纹:', rsaFingerprintHexColon);
2.创建X.509 v3证书
javascript
import forge from 'node-forge';
let pki = forge.pki;
const now = new Date();
let keys = pki.rsa.generateKeyPair(2048);
let cert = pki.createCertificate();
// 手动为证书绑定公钥(核心:确保证书包含对应的公钥信息,用于后续加密、验签等操作)
cert.publicKey = keys.publicKey;
// 设置证书版本为X.509 v3(目前广泛使用的证书版本,支持扩展字段,v1/v2已基本淘汰)
cert.version = 3;
// 生成随机唯一的证书序列号(16字节随机数转换为十六进制字符串,用于唯一标识证书,避免重复)
cert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16));
// 设置证书生效起始时间为当前时间(证书在此时间之后才具有法律效力/可用性)
cert.validity.notBefore = now;
// 先将证书过期时间初始化为当前时间(后续再进行年份偏移调整,作为有效期设置的过渡步骤)
cert.validity.notAfter = new Date(now.getTime());
// 调整证书过期时间:在生效起始时间基础上增加10年,最终设置证书有效期为10年(长期信任根CA常用有效期)
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 10);
// 证书主体/签发者属性数组(X.509证书的身份标识字段,用于描述证书所属主体/签发CA的信息)
const caAttrs = [
// commonName(CN):通用名称,根CA证书通常填写CA名称,终端证书可填写域名/用户名等
{ name: 'commonName', value: 'My Trusted Root CA' },
// countryName(C):国家代码,使用ISO 3166-1 alpha-2格式,CN代表中国
{ name: 'countryName', value: 'CN' },
// stateOrProvinceName(ST):州/省份名称,填写完整的行政区划名称(与下方shortName: 'ST'是同一字段的不同写法)
{ name: 'stateOrProvinceName', value: 'Beijing' },
// localityName(L):地区/城市名称,填写具体的城市或区县名称
{ name: 'localityName', value: 'Beijing' },
// organizationName(O):组织/机构名称,填写所属单位或企业的正式名称
{ name: 'organizationName', value: 'My CA Organization' },
// shortName: 'ST':州/省份的简写标识,与上方stateOrProvinceName对应,值为Virginia(美国弗吉尼亚州,演示不同地区写法)
{ shortName: 'ST', value: 'Virginia' },
// shortName: 'OU':organizationalUnitName(组织单元)的简写,填写机构内部的部门或团队名称
{ shortName: 'OU', value: 'Test' }
];
cert.setIssuer(caAttrs); // 设置证书的签发者信息(自签名CA证书中,签发者与主体信息一致)
cert.setSubject(caAttrs); // 设置证书的主体信息(描述证书的拥有者,此处为根CA自身)
//添加CA证书必备扩展字段
cert.setExtensions([
// 基础约束扩展:标记该证书为CA证书(cA: true),该扩展为关键扩展(critical: true),缺少或不合法会导致证书验证失败
{ name: 'basicConstraints', cA: true, critical: true },
// 密钥用法扩展:限定密钥用途为证书签名(keyCertSign: true)和CRL签名(cRLSign: true),为关键扩展,确保CA证书仅用于签发证书和吊销列表
{ name: 'keyUsage', keyCertSign: true, cRLSign: true, critical: true },
// 主题密钥标识扩展:通过公钥计算唯一标识,用于关联证书与对应的密钥,方便证书链构建和密钥匹配,自动关联证书中的公钥
{ name: 'subjectKeyIdentifier' },
// 权威密钥标识扩展:自签名证书中,权威密钥标识与主题密钥标识一致(keyIdentifier: true),用于标识签发该证书的CA公钥,方便验证证书链的连续性
{ name: 'authorityKeyIdentifier', keyIdentifier: true },
// 扩展密钥用法扩展:限定证书的额外应用场景,支持服务器身份认证(serverAuth)、客户端身份认证(clientAuth)、代码签名(codeSigning)、邮件保护(emailProtection)、时间戳服务(timeStamping)
{ name: 'extKeyUsage', serverAuth: true, clientAuth: true, codeSigning: true, emailProtection: true, timeStamping: true },
// Netscape证书类型扩展:兼容旧版Netscape浏览器,标记证书可用于客户端认证(client)、服务器认证(server)、邮件加密(email)、对象签名(objsign)、SSL CA(sslCA)、邮件CA(emailCA)、对象CA(objCA)
{ name: 'nsCertType', client: true, server: true, email: true, objsign: true, sslCA: true, emailCA: true, objCA: true },
// 主题备用名称扩展:补充证书主体的额外标识,包含URI类型(type: 6,对应http://example.org/webid#me)和IP地址类型(type: 7,对应127.0.0.1),解决主体通用名称的局限性
{ name: 'subjectAltName', altNames: [{ type: 6, value: 'http://example.org/webid#me' }, { type: 7, ip: '127.0.0.1' }] }
]);
//自签名证书(核心:签名过程中会自动将公钥嵌入证书)
cert.sign(keys.privateKey, forge.md.sha256.create());
const endEntityCertPem = pki.certificateToPem(cert);
console.log('✅ 证书生成完成(PEM格式):\n', endEntityCertPem);
const certCommonName = cert.subject.getField({ name: 'commonName' })?.value;
// 组织名称(O)
const certOrg = cert.subject.getField({ name: 'organizationName' })?.value;
// 国家代码(C)
const certCountry = cert.subject.getField({ name: 'countryName' })?.value;
console.log(`证书通用名称(CN):${certCommonName}`);
console.log(`所属组织(O):${certOrg}`);
console.log(`国家代码(C):${certCountry}`);
console.log(`证书版本:X.509 v${cert.version}`);
console.log(`证书序列号:${cert.serialNumber}`);

3.X.509 数字证书验证(中间 CA 不是必须项)
javascript
import forge from 'node-forge';
let pki = forge.pki;
const now = new Date();
// ===================== 步骤1:生成根CA证书 =====================
let rootCaKeypair = pki.rsa.generateKeyPair(2048);
let rootCaCert = pki.createCertificate();
// 手动为证书绑定公钥(核心:确保证书包含对应的公钥信息,用于后续加密、验签等操作)
rootCaCert.publicKey = rootCaKeypair.publicKey;
// 设置证书版本为X.509 v3(目前广泛使用的证书版本,支持扩展字段,v1/v2已基本淘汰)
rootCaCert.version = 3;
// 生成随机唯一的证书序列号(16字节随机数转换为十六进制字符串,用于唯一标识证书,避免重复)
rootCaCert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16));
// 设置证书生效起始时间为当前时间(证书在此时间之后才具有法律效力/可用性)
rootCaCert.validity.notBefore = now;
// 先将证书过期时间初始化为当前时间(后续再进行年份偏移调整,作为有效期设置的过渡步骤)
rootCaCert.validity.notAfter = new Date(now.getTime());
// 调整证书过期时间:在生效起始时间基础上增加10年,最终设置证书有效期为10年(长期信任根CA常用有效期)
rootCaCert.validity.notAfter.setFullYear(rootCaCert.validity.notBefore.getFullYear() + 10);
// 证书主体/签发者属性数组(X.509证书的身份标识字段,用于描述证书所属主体/签发CA的信息)
const rootCaAttrs = [
// commonName(CN):通用名称,根CA证书通常填写CA名称,终端证书可填写域名/用户名等
{ name: 'commonName', value: 'My Trusted Root CA' },
// countryName(C):国家代码,使用ISO 3166-1 alpha-2格式,CN代表中国
{ name: 'countryName', value: 'CN' },
// stateOrProvinceName(ST):州/省份名称,填写完整的行政区划名称(与下方shortName: 'ST'是同一字段的不同写法)
{ name: 'stateOrProvinceName', value: 'Beijing' },
// localityName(L):地区/城市名称,填写具体的城市或区县名称
{ name: 'localityName', value: 'Beijing' },
// organizationName(O):组织/机构名称,填写所属单位或企业的正式名称
{ name: 'organizationName', value: 'My CA Organization' },
// shortName: 'ST':州/省份的简写标识,与上方stateOrProvinceName对应,值为Virginia(美国弗吉尼亚州,演示不同地区写法)
{ shortName: 'ST', value: 'Virginia' },
// shortName: 'OU':organizationalUnitName(组织单元)的简写,填写机构内部的部门或团队名称
{ shortName: 'OU', value: 'Test' }
];
rootCaCert.setIssuer(rootCaAttrs); // 设置证书的签发者信息(自签名CA证书中,签发者与主体信息一致)
rootCaCert.setSubject(rootCaAttrs); // 设置证书的主体信息(描述证书的拥有者,此处为根CA自身)
//添加CA证书必备扩展字段
rootCaCert.setExtensions([
// 基础约束扩展:标记该证书为CA证书(cA: true),该扩展为关键扩展(critical: true),缺少或不合法会导致证书验证失败
{ name: 'basicConstraints', cA: true, critical: true },
// 密钥用法扩展:限定密钥用途为证书签名(keyCertSign: true)和CRL签名(cRLSign: true),为关键扩展,确保CA证书仅用于签发证书和吊销列表
{ name: 'keyUsage', keyCertSign: true, cRLSign: true, critical: true },
// 主题密钥标识扩展:通过公钥计算唯一标识,用于关联证书与对应的密钥,方便证书链构建和密钥匹配,自动关联证书中的公钥
{ name: 'subjectKeyIdentifier' },
// 权威密钥标识扩展:自签名证书中,权威密钥标识与主题密钥标识一致(keyIdentifier: true),用于标识签发该证书的CA公钥,方便验证证书链的连续性
{ name: 'authorityKeyIdentifier', keyIdentifier: true },
// 扩展密钥用法扩展:限定证书的额外应用场景,支持服务器身份认证(serverAuth)、客户端身份认证(clientAuth)、代码签名(codeSigning)、邮件保护(emailProtection)、时间戳服务(timeStamping)
{ name: 'extKeyUsage', serverAuth: true, clientAuth: true, codeSigning: true, emailProtection: true, timeStamping: true },
// Netscape证书类型扩展:兼容旧版Netscape浏览器,标记证书可用于客户端认证(client)、服务器认证(server)、邮件加密(email)、对象签名(objsign)、SSL CA(sslCA)、邮件CA(emailCA)、对象CA(objCA)
{ name: 'nsCertType', client: true, server: true, email: true, objsign: true, sslCA: true, emailCA: true, objCA: true },
// 主题备用名称扩展:补充证书主体的额外标识,包含URI类型(type: 6,对应http://example.org/webid#me)和IP地址类型(type: 7,对应127.0.0.1),解决主体通用名称的局限性
{ name: 'subjectAltName', altNames: [{ type: 6, value: 'http://example.org/webid#me' }, { type: 7, ip: '127.0.0.1' }] }
]);
//自签名证书(核心:签名过程中会自动将公钥嵌入证书)
rootCaCert.sign(rootCaKeypair.privateKey, forge.md.sha256.create());
const rootCaCertPem = pki.certificateToPem(rootCaCert);
console.log('✅ 根CA证书生成完成(PEM格式):\n', rootCaCertPem.slice(0, 100) + '...\n');
// ===================== 步骤2:生成中间CA密钥对与证书(由根CA签发) =====================
const intermediateCaKeypair = pki.rsa.generateKeyPair(2048);
const intermediateCaCert = pki.createCertificate();
intermediateCaCert.publicKey = intermediateCaKeypair.publicKey;
intermediateCaCert.version = 3;
intermediateCaCert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16));
intermediateCaCert.validity.notBefore = now;
intermediateCaCert.validity.notAfter = new Date(now.getTime());
intermediateCaCert.validity.notAfter.setFullYear(intermediateCaCert.validity.notBefore.getFullYear() + 10);
// 中间CA身份信息
const intermediateCaAttrs = [
{ name: 'commonName', value: 'My Intermediate CA' },
{ name: 'countryName', value: 'CN' },
{ name: 'organizationName', value: 'My Root CA Org' },
{ shortName: 'OU', value: 'Intermediate CA Department' }
];
intermediateCaCert.setSubject(intermediateCaAttrs);
intermediateCaCert.setIssuer(rootCaAttrs); // 由根CA签发
// 中间CA扩展字段
intermediateCaCert.setExtensions([
{ name: 'basicConstraints', cA: true, pathLenConstraint: 0, critical: true }, // 允许签发终端证书,不可再签下级CA
{ name: 'keyUsage', keyCertSign: true, cRLSign: true, critical: true },
{ name: 'subjectKeyIdentifier' },
{ name: 'authorityKeyIdentifier', keyIdentifier: true }
]);
// 根CA签发中间CA证书
intermediateCaCert.sign(rootCaKeypair.privateKey, forge.md.sha256.create());
const intermediateCaCertPem = pki.certificateToPem(intermediateCaCert);
console.log('✅ 中间CA证书生成完成(PEM格式):\n', intermediateCaCertPem.slice(0, 100) + '...\n');
// ===================== 步骤3:生成终端证书(由中间CA签发,用于服务器/客户端认证) =====================
const endEntityKeypair = pki.rsa.generateKeyPair(2048);
const endEntityCert = pki.createCertificate();
endEntityCert.publicKey = endEntityKeypair.publicKey;
endEntityCert.version = 3;
endEntityCert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16));
endEntityCert.validity.notBefore = now;
endEntityCert.validity.notAfter = new Date(now.getTime());
endEntityCert.validity.notAfter.setFullYear(endEntityCert.validity.notBefore.getFullYear() + 10);
// 终端证书身份信息(服务器域名)
const endEntityAttrs = [
{ name: 'commonName', value: 'www.example.com' },
{ name: 'countryName', value: 'CN' },
{ name: 'organizationName', value: 'Example Company' },
{ shortName: 'OU', value: 'IT Department' }
];
endEntityCert.setSubject(endEntityAttrs);
endEntityCert.setIssuer(intermediateCaAttrs); // 由中间CA签发
// 终端证书扩展字段
endEntityCert.setExtensions([
{ name: 'basicConstraints', cA: false, critical: true }, // 非CA证书,不可签发其他证书
{ name: 'keyUsage', digitalSignature: true, keyEncipherment: true, critical: true }, // 用于数字签名和密钥加密
{ name: 'subjectKeyIdentifier' },
{ name: 'authorityKeyIdentifier', keyIdentifier: true },
{ name: 'extKeyUsage', serverAuth: true, clientAuth: true }, // 支持服务器和客户端认证
{ name: 'subjectAltName', altNames: [ // 备用域名/IP,解决CN局限性
{ type: 2, value: 'www.example.com' },
{ type: 2, value: 'api.example.com' },
{ type: 7, ip: '192.168.1.100' }
] }
]);
// 中间CA签发终端证书
endEntityCert.sign(intermediateCaKeypair.privateKey, forge.md.sha256.create());
const endEntityCertPem = pki.certificateToPem(endEntityCert);
console.log('✅ 终端证书生成完成(PEM格式):\n', endEntityCertPem.slice(0, 100) + '...\n');
// ===================== 步骤4:创建CA信任仓库并管理证书 =====================
const caStore = pki.createCaStore([rootCaCertPem]);
console.log('✅ CA信任仓库初始化完成,已导入根CA证书');
// 向仓库添加中间CA证书(支持PEM字符串或证书对象)
caStore.addCertificate(intermediateCaCert); // 也可传入intermediateCaCert(证书对象)
console.log('✅ 中间CA证书已添加到CA信任仓库');
// const issuerCert = caStore.getIssuer(endEntityCert);
// console.log(issuerCert.subject);
// const issuerCommonName = issuerCert.subject.getField({ name: 'commonName' });
// console.log(issuerCommonName);
// ===================== 步骤5:验证证书链有效性 =====================
const certChain = [endEntityCert, intermediateCaCert, rootCaCert];
const verifyResult = pki.verifyCertificateChain(
caStore,
certChain,
(verified, depth, certs) =>
{
if (!verified) {
console.error(`❌ 深度${depth}的证书基础验证失败(签名/格式不合法)`);
return false;
}
const cert = certs[depth];
const certCommonName = cert.subject.getField({ name: 'commonName' })?.value;
// 组织名称(O)
const certOrg = cert.subject.getField({ name: 'organizationName' })?.value;
// 国家代码(C)
const certCountry = cert.subject.getField({ name: 'countryName' })?.value;
// 4. 打印当前验证进度信息
console.log(`\n==================== 证书验证(深度${depth}) ====================`);
console.log(`证书通用名称(CN):${certCommonName}`);
console.log(`所属组织(O):${certOrg}`);
console.log(`国家代码(C):${certCountry}`);
console.log(`证书版本:X.509 v${cert.version}`);
console.log(`证书序列号:${cert.serialNumber}`);
const currentTime = new Date();
const notBefore = cert.validity?.notBefore;
const notAfter = cert.validity?.notAfter;
console.log(`生效时间:${notBefore.toLocaleString()}`);
console.log(`过期时间:${notAfter.toLocaleString()}`);
if (currentTime < notBefore) {
console.error(`❌ 证书${certCommonName}尚未生效(当前时间早于生效时间)`);
return false;
}
if (currentTime > notAfter) {
console.error(`❌ 证书${certCommonName}已过期(当前时间晚于过期时间)`);
return false;
}
// 6校验终端证书(depth=0)的备用名称是否包含目标域名
if (depth === 0) {
const sanExtension = cert.getExtension('subjectAltName');
if (!sanExtension) {
console.warn(`⚠️ 终端证书${certCommonName}缺少主题备用名称(SAN)扩展`);
// 若需强制校验SAN,可改为return false
// return false;
} else {
const targetDomain = 'www.example.com';
const hasTargetDomain = sanExtension.altNames.some((altName) =>
altName.type === 2 && altName.value === targetDomain
);
if (hasTargetDomain) {
console.log(`✅ 终端证书包含目标域名:${targetDomain}`);
} else {
console.error(`❌ 终端证书不包含目标域名:${targetDomain}`);
console.log('证书包含的备用名称:', sanExtension.altNames.map((alt) => `${alt.type === 2 ? '域名' : 'IP'}: ${alt.value || alt.ip}`).join(', '));
return false;
}
}
}
// 校验CA证书(depth>0)是否具备证书签发权限
if (depth > 0) {
const basicConstraints = cert.getExtension('basicConstraints');
if (!basicConstraints?.cA) {
console.error(`❌ 深度${depth}的证书${certCommonName}不是CA证书,不具备签发权限`);
return false;
}
console.log(`✅ CA证书${certCommonName}具备证书签发权限`);
}
return true; // 返回true表示该证书验证通过
}
);
if (verifyResult) {
console.log('\n🎉 证书链验证成功!终端证书可信且有效');
}

4.cert = pki.createCertificate()对象函数,创建证书
| 函数名 | 描述 | 参数说明 | 返回值说明 |
|---|---|---|---|
| setSubject | 设置证书的主体(拥有者)信息,可选指定唯一ID | 1. attrs: CertificateField[] - 主体属性数组 2. uniqueId?: string - 可选唯一ID | void - 无返回值 |
| setIssuer | 设置证书的签发者信息,可选指定唯一ID | 1. attrs: CertificateField[] - 签发者属性数组 2. uniqueId?: string - 可选唯一ID | void - 无返回值 |
| setExtensions | 为证书设置扩展字段数组,配置X.509 v3证书的扩展信息 | 1. exts: any[] - 证书扩展字段数组 | void - 无返回值 |
| getExtension | 根据扩展名称或ID获取证书指定扩展字段,未找到返回undefined | 1. options: string | {name: string} | {id: number} - 扩展名称或ID配置 | {} | undefined - 扩展对象或undefined |
| sign | 使用指定私钥对证书进行签名,可选指定消息摘要算法 | 1. key: pki.rsa.PrivateKey - 签名用私钥 2. md?: md.MessageDigest - 可选消息摘要对象(默认SHA1) | void - 无返回值 |
| verify | 使用当前证书的公钥,验证传入的子证书签名是否有效 | 1. child: Certificate - 待验证的子证书对象 | boolean - true = 验证通过, false = 验证失败 |
| isIssuer | 检查当前证书的签发者是否与传入父证书的主体匹配(不验证签名) | 1. parent: Certificate - 待检验的父证书对象 | boolean - true = 匹配, false = 不匹配 |
| issued | 检查当前证书的主体是否与传入子证书的签发者匹配(不验证签名) | 1. child: Certificate - 待校验的子证书对象 | boolean - true = 匹配, false = 不匹配 |
| generateSubjectKeyIdentifier | 生成当前证书的主体密钥标识符(SKI),返回字节缓冲区格式 | 无参数 | util.ByteStringBuffer - 字节缓冲区格式的SKI |
| verifySubjectKeyIdentifier | 验证证书的主体密钥标识符扩展值与公钥是否一致,无该扩展返回false | 无参数 | boolean - true = 验证通过, false = 验证失败 |
5.cert = pki.createCertificate()对象属性,创建证书
| 属性名称 | 类型定义 | 说明描述 |
|---|---|---|
| version | number | 证书版本号,通常为3(对应X.509 v3标准,主流证书版本) |
| serialNumber | string | 证书唯一序列号,用于唯一标识单个证书,防止重复签发 |
| signatureOid | string | 签名算法的对象标识符(OID),用于标识证书签名所采用的算法类型 |
| signature | any | 证书的数字签名内容,用于验证证书的完整性和签发者身份的真实性 |
| signInfo | { algorithmOid: string; parameters: any; } | 签名详细信息,包含签名算法OID和对应的算法配置参数 |
| validity | { notBefore: Date; notAfter: Date; } | 证书有效期范围,notBefore为生效时间,notAfter为过期时间 |
| issuer | { getField: (sn: string | CertificateFieldOptions) => any; addField: (attr: CertificateField) => void; attributes: CertificateField[]; hash: any; } | 证书签发者信息,包含字段操作方法、签发者属性数组和对应的哈希值 |
| subject | { getField: (sn: string | CertificateFieldOptions) => any; addField: (attr: CertificateField) => void; attributes: CertificateField[]; hash: any; } | 证书主体(拥有者)信息,包含字段操作方法、主体属性数组和对应的哈希值 |
| extensions | any[] | 证书扩展字段数组,存储X.509 v3证书的扩展信息(如SAN、BasicConstraints等) |
| privateKey | PrivateKey | 与证书对应的私钥,用于证书签名、数据解密等私密操作 |
| publicKey | PublicKey | 与证书对应的公钥,对外公开,用于验证签名、数据加密等公开操作 |
| md | md.MessageDigest | 消息摘要对象,用于证书签名和验证过程中的哈希计算(默认SHA1) |
| signatureParameters | any | 签名算法的附加配置参数,配合签名算法完成完整的签名流程 |
| tbsCertificate | asn1.Asn1 | 待签名证书(To Be Signed Certificate)的ASN.1结构,包含证书核心信息 |
6.caStore = pki.createCaStore([rootCaCertPem]) 创建一个 CA 信任仓库
| 函数名 | 说明 | 参数说明 | 返回值类型 |
|---|---|---|---|
| addCertificate | 向CA证书仓库中添加证书,支持证书对象或PEM格式字符串两种形式 | pki.Certificate | 无返回值 |
| hasCertificate | 检查CA证书仓库中是否存在指定证书,用于验证证书是否已入库 | pki.Certificate | 返回true或者false |
| removeCertificate | 从CA证书仓库中移除指定证书,返回被移除的证书(若不存在则返回null) | pki.Certificate | pki.Certificate 证书对象 |
| listAllCertificates | 列出CA证书仓库中所有已存储的证书,返回证书对象数组 | 无参数 | pki.Certificate[](所有证书对象组成的数组) |
| getIssuer | 根据目标证书的签发者(subject),从仓库中查找对应的签发CA证书 | pki.Certificate | pki.Certificate 证书对象 |
| getBySubject | 根据证书主题(subject)字符串,从仓库中查找匹配的证书 | subject: string:证书主题字符串(如证书的DN字段) | pki.Certificate 证书对象 |
7.其他函数
| 函数名 | 描述 | 参数说明 | 返回值类型 |
|---|---|---|---|
| certificateFromAsn1 | 将ASN.1结构对象转换为Certificate证书对象,可选是否计算哈希值 | 1. obj: asn1.Asn1 - 待转换的ASN.1结构对象 2. computeHash?: boolean - 可选,是否计算证书哈希值 | Certificate - 转换后的证书对象 |
| certificationRequestFromAsn1 | 将ASN.1结构对象转换为证书签名请求(CSR)对象,可选是否计算哈希值 | 1. obj: asn1.Asn1 - 待转换的ASN.1结构对象 2. computeHash?: boolean - 可选,是否计算CSR哈希值 | CertificateSigningRequest - 转换后的CSR对象 |
| distinguishedNameToAsn1 | 将可分辨名称(DN,通常为证书主体/签发者信息)转换为ASN.1结构对象 | 1. dn: 包含证书属性的可分辨名称对象 • dn.attributes: ReadonlyArray | asn1.Asn1 - 转换后的ASN.1结构对象 |
| certificateToAsn1 | 将Certificate证书对象转换为对应的ASN.1结构对象 | 1. cert: Certificate - 待转换的证书对象 | asn1.Asn1 - 转换后的ASN.1结构对象 |
| certificationRequestToAsn1 | 将证书签名请求(CSR)对象转换为对应的ASN.1结构对象 | 1. cert: CertificateSigningRequest - 待转换的CSR对象 | asn1.Asn1 - 转换后的ASN.1结构对象 |
| decryptRsaPrivateKey | 从PEM格式数据中解密并提取RSA私钥,支持带密码保护的PEM私钥 | 1. pem: PEM - 包含RSA私钥的PEM格式字符串 2. passphrase?: string - 可选,解密私钥的密码 | rsa.PrivateKey - 解密后的RSA私钥对象 |
| createCertificate | 创建一个空的、未初始化的Certificate证书对象,用于后续配置证书信息 | 无参数 | Certificate - 空证书对象 |
| certificationRequestToPem | 将证书签名请求(CSR)对象转换为PEM格式字符串,可选指定每行最大长度 | 1. csr: CertificateSigningRequest - 待转换的CSR对象 2. maxline?: number - 可选,PEM字符串每行最大字符数 | PEM - 转换后的PEM格式字符串 |
| certificationRequestFromPem | 从PEM格式字符串中解析出证书签名请求(CSR)对象,支持严格格式校验 | 1. pem: PEM - 包含CSR的PEM格式字符串 2. computeHash?: boolean - 可选,是否计算CSR哈希值 3. strict?: boolean - 可选,是否启用严格模式校验 | CertificateSigningRequest - 解析后的CSR对象 |
| createCertificationRequest | 创建一个空的、未初始化的CertificateSigningRequest(CSR)对象,用于后续配置签名请求信息 | 无参数 | CertificateSigningRequest - 空CSR对象 |
| certificateToPem | 将Certificate证书对象转换为PEM格式字符串,可选指定每行最大长度 | 1. cert: Certificate - 待转换的证书对象 2. maxline?: number - 可选,PEM字符串每行最大字符数 | PEM - 转换后的PEM格式字符串 |
| certificateFromPem | 从PEM格式字符串中解析出Certificate证书对象,支持严格模式校验 | 1. pem: PEM - 包含证书的PEM格式字符串 2. computeHash?: boolean - 可选,是否计算证书哈希值 3. strict?: boolean - 可选,是否启用严格模式校验 | Certificate - 解析后的证书对象 |
| verifyCertificateChain | 验证证书链的有效性,基于指定的CA信任仓库,支持自定义验证回调和有效期校验日期 | 1. caStore: CAStore - 可信CA信任仓库 2. chain: Certificate[] - 待验证的证书链数组(终端证书→中间CA→根CA) 3. options配置项,可以直接传入函数,或者按照下面属性配置,函数参数与options.verify一致 • options.verify: ((verified: boolean | string, depth: number, certs: Certificate[]) => boolean); • options.validityCheckDate?: Date | null | undefined; | boolean - true=证书链验证通过, false=证书链验证失败 |
8.CertificateSigningRequest 对象
| 属性/函数名 | 类型 | 说明 | 参数说明 | 返回值说明 |
|---|---|---|---|---|
| version | number | 证书签名请求(CSR)的版本号,遵循X.509标准,通常固定为0(对应版本1),保障CSR格式解析兼容性 | --- | --- |
| signatureOid | string | CSR签名所使用算法的OID(对象标识符),如forge.pki.oids.sha256WithRSAEncryption,标识签名算法类型,签名后自动赋值 | --- | --- |
| signature | any | CSR的数字签名结果数据,存储用私钥加密后的摘要信息,验证CSR有效性时需使用对应公钥解密验证 | --- | --- |
| signInfo | { algorithmOid: string | null } | CSR签名算法元数据对象,仅包含algorithmOid字段,记录签名算法的OID,与signatureOid功能一致,用于兼容不同解析逻辑 | --- | --- |
| subject | Object(嵌套结构) | CSR主题(证书申请者)的身份信息对象,存储申请者的国家、组织、通用名称等身份字段,是CSR的核心身份信息载体 | --- | --- |
| subject.attributes | CertificateField[] | 主题身份信息的字段数组,存储所有已添加的申请者身份字段,如{name: 'commonName', value: 'Example Corp'} | --- | --- |
| subject.hash | any | 主题身份信息的哈希值,用于快速校验主题信息是否被篡改,通常由框架自动计算生成 | --- | --- |
| publicKey | PublicKey | 申请者的公钥对象,与申请者的私钥配对,后续用于生成证书的公钥部分,签名CSR前需设置有效公钥 | --- | --- |
| attributes | CertificateField[] | CSR的扩展属性数组,存储除主题身份外的额外信息(如申请联系方式、密钥用法等),可选配置,用于丰富CSR信息 | --- | --- |
| md | md.MessageDigest | 用于生成CSR签名的消息摘要对象,如forge.md.sha256,指定签名时的哈希算法,签名后自动赋值 | --- | --- |
| signatureParameters | any | CSR签名的附加参数对象,存储签名算法的额外配置(如RSA填充模式),多数场景下由框架自动填充,无需手动配置 | --- | --- |
| certificationRequestInfo | asn1.Asn1 | CSR的核心信息ASN.1结构化对象,存储版本、主题、公钥等核心数据,是CSR编码为PEM/DER格式的基础 | --- | --- |
| subject.getField | Function | 从主题身份信息中获取指定字段,通过字段短名或配置项匹配对应身份属性 | sn: string(字段短名,如CN对应通用名称)/ CertificateFieldOptions(字段配置项) | 匹配到的身份字段值,无匹配则返回空 |
| subject.addField | Function | 向主题身份信息中添加新的身份字段,完善申请者的身份信息 | attr: CertificateField(身份字段对象,包含name、value等属性) | void(无返回值) |
| getAttribute | Function | 从CSR的扩展属性中获取指定属性,通过属性短名或配置项匹配对应扩展信息 | sn: string(属性短名)/ GetAttributeOpts(属性配置项,包含shortName/name/type) | Attribute对象 • name:属性含义名称(如commonName) • shortName:可选,属性短名(如CN) • type:属性标准化OID标识 • value:属性实际数据值 • valueTagClass:属性值的ASN.1数据类型标记 • extensions:可选,属性附加扩展信息 |
| addAttribute | Function | 向CSR的扩展属性中添加新的扩展字段,补充CSR的额外信息 | attr: CertificateField(扩展字段对象,包含name、value等属性) | void(无返回值) |
| setSubject | Function | 批量设置CSR的主题身份信息,覆盖原有主题字段,快速配置申请者身份 | attrs: CertificateField[](身份字段数组,包含多个申请者身份属性) | void(无返回值) |
| setAttributes | Function | 批量设置CSR的扩展属性,覆盖原有扩展字段,快速配置额外信息 | attrs: CertificateField[](扩展字段数组,包含多个额外属性) | void(无返回值) |
| sign | Function | 使用申请者的私钥对CSR进行数字签名,生成有效的CSR数据,签名后CSR方可提交给CA机构申请证书 | 1. key: pki.rsa.PrivateKey(申请者的RSA私钥,用于签名) 2. md?: md.MessageDigest(可选,消息摘要对象,默认使用SHA1,推荐指定SHA256等强哈希算法) | void(无返回值) |
| verify | Function | 验证CSR的签名有效性,使用CSR自身的公钥解密签名并对比摘要,判断CSR是否被篡改、签名是否合法 | --- | boolean(验证通过返回true,失败返回false) |
九、公钥基础设施 - PKCS#5 (对称密钥的派生与存储)
PKCS#5 是公钥基础设施下的规范之一,核心用于对称密钥的派生与存储,常用 PBKDF2 算法基于密码生成加密密钥。
优点
- 增强密码安全性:通过加盐、迭代等方式,提升密码的抗破解能力;
- 兼容性强:广泛支持各类密码派生场景,是行业常用的密钥生成规范。
缺点
- 功能单一:仅聚焦密钥派生与存储,无其他扩展安全能力;
- 早期版本安全性弱:如 PBKDF1 算法的安全强度已无法满足现代需求。
适用场景
- 用户密码的安全存储:例如数据库中密码的哈希加密存储;
- 基于密码的加密密钥生成:通过用户密码生成用于数据加密的对称密钥。
javascript
import forge from 'node-forge';
// 核心参数配置
const password = 'mySecurePassword123'; // 原始密码
const salt = forge.util.bytesToHex(forge.random.getBytesSync(16)); // 随机盐值(16字节,转十六进制)
const iterations = 10000; // 迭代次数(越高越安全,性能消耗越大)
const keySize = 32; // 生成32字节(256位)密钥,适配AES-256加密
/* forge.pkcs5.pbkdf2 参数
1.password: string - 原始密码字符串(用于推导密钥的基础数据)
2.salt: string - 盐值字符串(防止彩虹表攻击,增加密钥唯一性)
3.iterations: number - 迭代次数(次数越多,破解难度越大,安全性越高)
4.keySize: number - 期望生成的密钥长度(以字节为单位)
5.messageDigest?: md.MessageDigest | md.Algorithm - 可选自定义消息摘要算法(默认使用 SHA1)
6.callback?: (err: Error | null, dk: string) => any - 可选异步回调函数:
-err: 错误对象(推导失败时非空)
-dk: 推导后的密钥字符串(成功时返回有效密钥)
* */
const derivedKey = forge.pkcs5.pbkdf2(password, salt, iterations, keySize);
console.log('原始密码:', password);
console.log('盐值(十六进制):', salt);
console.log('迭代次数:', iterations);
console.log('密钥长度(字节):', keySize);
console.log('推导后的密钥(十六进制):', forge.util.bytesToHex(derivedKey));

十、公钥基础设施 - PKCS#7 (对称密钥的派生与存储)
PKCS#7 是公钥基础设施的规范之一,核心用于加密消息、数字签名、证书封装,支持多接收方、多签名的复杂安全场景。
优点
- 适配复杂消息安全需求:可同时实现加密、签名、证书携带等复合操作;
- 是 S/MIME 邮件加密的技术基础,广泛支撑邮件安全场景。
缺点
- 格式设计冗余,对数据的解析、处理复杂度较高;
- 兼容性依赖具体实现,不同系统间的互通可能存在差异。
适用场景
- 安全邮件(S/MIME):实现邮件的加密与签名;
- 带签名 / 加密的电子文档传输:保障文档在传输过程中的安全性与不可否认性。
1.签名验证
javascript
import forge from 'node-forge';
const pkcs7 = forge.pkcs7;
const pki = forge.pki;
const signerKeyPair = pki.rsa.generateKeyPair(2048);
//证书相关文档,教程 "八、X.509数字证书"
const signerCert = pki.createCertificate();
signerCert.publicKey = signerKeyPair.publicKey;
signerCert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16));
signerCert.validity.notBefore = new Date();
signerCert.validity.notAfter = new Date();
signerCert.validity.notAfter.setFullYear(signerCert.validity.notBefore.getFullYear() + 1);
// 设置证书主体/签发者(自签名)
const attrs = [{ name: 'commonName', value: 'Signer CA' }];
signerCert.setSubject(attrs);
signerCert.setIssuer(attrs);
signerCert.sign(signerKeyPair.privateKey, forge.md.sha256.create());
const certOrCertPem = pki.certificateToPem(signerCert);
const signedData = pkcs7.createSignedData();
signedData.content = forge.util.createBuffer('需要签名的敏感数据:用户订单号 #123456', 'utf8');
signedData.addCertificate(certOrCertPem);
signedData.addSigner({
key: signerKeyPair.privateKey, // 签名者私钥
certificate: certOrCertPem, // 签名者证书
digestAlgorithm: forge.pki.oids.sha256, // 摘要算法
authenticatedAttributes: [{
type: forge.pki.oids.contentType,
value: forge.pki.oids.data
}, {
type: forge.pki.oids.messageDigest //值将在签名时自动填充
}, {
type: forge.pki.oids.signingTime,
value: new Date()
}]
});
signedData.sign({ detached: true });
const signedPem = pkcs7.messageToPem(signedData);
console.log('签名后的 PEM 格式数据:', signedPem);
const receivedSignedData = pkcs7.messageFromPem(signedPem);
const verifyResult = receivedSignedData.verify([signerCert]); #"node-forge": "^1.3.3" 暂未实现 verify

2.信封加密(Enveloped Data)
javascript
import forge from 'node-forge';
const pkcs7 = forge.pkcs7;
const pki = forge.pki;
const recipientKeyPair = pki.rsa.generateKeyPair(2048);
//证书相关文档,教程 "八、X.509数字证书"
const recipientCert = pki.createCertificate();
recipientCert.publicKey = recipientKeyPair.publicKey;
recipientCert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16));
recipientCert.validity.notBefore = new Date();
recipientCert.validity.notAfter = new Date();
recipientCert.validity.notAfter.setFullYear(recipientCert.validity.notBefore.getFullYear() + 1);
// 设置证书主体/签发者(自签名)
const attrs = [{ name: 'commonName', value: 'Signer CA' }];
recipientCert.setSubject(attrs);
recipientCert.setIssuer(attrs);
recipientCert.sign(recipientKeyPair.privateKey, forge.md.sha256.create());
const envelopedData = pkcs7.createEnvelopedData();
envelopedData.content = forge.util.createBuffer('需要签名的敏感数据:用户订单号 #123456', 'utf8');
// 添加接收者(官网示例中的 recipient 对应的证书)
envelopedData.addRecipient(recipientCert);
// 加密消息(生成信封数据)
envelopedData.encrypt();
const pem = pkcs7.messageToPem(envelopedData);
console.log('=== 官网示例:加密后的 PEM 数据 ===\n', pem);
const receivedEnvelopedData = pkcs7.messageFromPem(pem);
// const recipient = receivedEnvelopedData.findRecipient(recipientCert);
// 解密消息
receivedEnvelopedData.decrypt(receivedEnvelopedData.recipients[0], recipientKeyPair.privateKey);
console.log('\n=== 官网示例:解密后的消息 ===\n', receivedEnvelopedData.content?.toString());

3.forge.pkcs7对象
| 函数名 | 描述 | 参数说明 | 返回值说明 |
|---|---|---|---|
| createSignedData | 创建一个空的PKCS#7签名数据(PkcsSignedData)对象,用于构建带签名的PKCS#7消息,支持添加证书、签名者并生成数字签名 | 无参数 | PkcsSignedData- PKCS#7签名数据对象 |
| createEnvelopedData | 创建一个空的PKCS#7信封数据(PkcsEnvelopedData)对象,用于构建带加密内容的PKCS#7消息,支持添加接收者、加密/解密内容 | 无参数 | PkcsEnvelopedData- PKCS#7信封数据对象 |
| messageToPem | 将PKCS#7签名数据对象转换为PEM格式字符串,便于存储和传输,可选指定每行最大字符数 | 1. msg: PkcsSignedData - 待转换的PKCS#7签名数据对象 2. maxline?: number - 可选,PEM字符串每行最大字符数(默认64) | string- PEM格式的PKCS#7消息字符串 |
| messageFromPem | 从PEM格式字符串中解析出PKCS#7消息对象(支持签名数据或信封数据),返回包含原始捕获数据的包装对象 | 1. pem: pki.PEM - PEM格式的PKCS#7消息字符串 | pem传PkcsSignedData数据返回PkcsSignedData 传PkcsEnvelopedData返回PkcsEnvelopedData |
| messageFromAsn1 | 从ASN.1结构对象中解析出PKCS#7消息对象(支持签名数据或信封数据),返回包含原始捕获数据的包装对象 | 1. asn: asn1.Asn1 - PKCS#7消息对应的ASN.1结构对象 | asn传PkcsSignedData数据返回PkcsSignedData 传PkcsEnvelopedData返回PkcsEnvelopedData |
4.PkcsSignedData对象
| 属性 | 类型 | 说明 | 参数说明 | 返回值说明 |
|---|---|---|---|---|
| content | string | util.ByteStringBuffer | 待签名的原始数据,可直接传入字符串或forge字节缓冲区,签名后可随签名包一起传输 | --- | --- |
| contentInfo | { value: any[] } | PKCS#7内容信息对象,存储原始数据的类型、格式等元数据,通常由框架自动填充,无需手动配置 | --- | --- |
| certificates | pki.Certificate[] | 存储与签名相关的证书数组(如签名者证书、CA证书链),用于验证签名时确认签名者身份合法性 | --- | --- |
| addCertificate | Function | 向签名数据对象中添加证书,支持传入证书对象/PEM格式的证书字符串,用于绑定签名者身份凭证 | certificate: pki.Certificate(证书对象)/ string(PEM格式证书字符串) | void(无返回值) |
| addSigner | Function | 配置签名者信息,为后续生成数字签名提供必要参数(私钥、证书、摘要算法等) | options配置项: 1. key: 签名者私钥(pki.rsa.PrivateKey对象/PEM格式私钥字符串) 2. certificate: 签名者证书(pki.Certificate对象/PEM格式证书字符串) 3. digestAlgorithm: 摘要算法OID(如forge.pki.oids.sha256) 4. authenticatedAttributes?: 可选认证属性数组,包含内容类型、消息摘要、签名时间等附加信息 | void(无返回值) |
| sign | Function | 生成PKCS#7数字签名,将原始数据、签名者信息、证书打包为签名包 | options?: 可选配置对象 detached: boolean(是否生成分离式签名,true=签名与原始数据分离,false=签名包含原始数据,默认false) | void(无返回值) |
| toAsn1 | Function | 将PKCS#7签名数据对象转换为ASN.1结构对象,用于后续编码为PEM或DER格式进行存储/传输 | --- | --- |
5.PkcsEnvelopedData对象
| 属性 | 类型 | 说明 | 参数说明 | 返回值说明 |
|---|---|---|---|---|
| content | string | util.ByteStringBuffer | 待加密的原始敏感数据,或解密后还原的原始数据,支持字符串或forge字节缓冲区格式 | --- | --- |
| recipients | Recipient[] | 存储所有授权接收者的信息数组,每个接收者对应一套加密的会话密钥和身份信息,仅这些接收者可解密数据 | --- | --- |
| addRecipient | Function | 向授权接收者列表中添加新的接收者,仅该接收者可通过自身私钥解密密信数据 | certificate: pki.Certificate(接收者的X.509证书对象,用于提取公钥加密会话密钥) | void(无返回值) |
| encrypt | Function | 执行PKCS#7信封加密流程,生成包含加密数据和加密会话密钥的完整加密密信 | 1. key?: util.ByteStringBuffer(可选,对称加密使用的会话密钥,不传入则自动生成随机密钥) 2. cipher?: OID(可选,对称加密算法的OID,不传入默认使用AES-256-CBC) | void(无返回值) |
| findRecipient | Function | 根据接收者的X.509证书,查找对应的Recipient接收者对象(通过证书的签发者和序列号匹配) | cert: pki.Certificate(用于匹配接收者的X.509证书对象) | Recipient对象 • version:接收者信息版本号,通常为0,保障格式解析兼容 • issuer:接收者证书签发者身份字段数组,用于匹配证书身份 • serialNumber:接收者证书唯一十六进制序列号,与issuer共同标识证书 • encryptedContent:接收者对应的加密会话密钥及算法元数据集合 • encryptedContent.algorithm:加密会话密钥的非对称加密算法OID • encryptedContent.parameter:非对称加密算法参数,通常为空或默认值 • encryptedContent.content:用接收者公钥加密后的对称会话密钥字节数据 |
| decrypt | Function | 执行PKCS#7信封解密流程,还原原始敏感数据(先通过私钥解密会话密钥,再用会话密钥解密数据) | 1. recipient: Recipient(待使用的接收者对象,需与私钥对应) 2. privKey: pki.rsa.PrivateKey(接收者的RSA私钥对象,用于解密会话密钥) | void(无返回值) |
| toAsn1 | Function | 将PKCS#7信封数据对象转换为ASN.1结构对象,用于后续编码为PEM或DER格式进行存储与传输 | --- | asn1.Asn1(转换后的ASN.1结构对象) |
十一、公钥基础设施 - PKCS#8 (私钥加密)
PKCS#8 是公钥基础设施下的规范之一,核心是私钥的加密存储格式,支持通过对称加密的方式保护私钥安全。
优点
- 统一私钥存储格式:支持 RSA、ED25519 等多种算法;
- 私钥安全保护性强:通过加密方式提升私钥存储的安全性。
缺点
- 功能单一:仅用于私钥存储,无其他扩展安全能力。
适用场景
- 加密库 / 系统的私钥安全存储:如 RSA 私钥、ED25519 私钥的加密存储;
- 密钥管理系统:用于密钥管理平台中私钥的安全管理。
javascript
import forge from 'node-forge';
let pki = forge.pki;
let sha1 = forge.md.sha1.create();
sha1.update('hello world', 'utf8');
// 生成 RSA 2048 位密钥对(原始私钥为 PKCS#1 格式)
const keypair = pki.rsa.generateKeyPair(2048);
// ========================= 将原始 RSA 私钥(PKCS#1 格式)转换为标准 PKCS#8 格式的私钥 PEM 字符串 ========================
let privateKeyPEM = pki.privateKeyToPem(keypair.privateKey); // 私钥对象 → PKCS#8 格式 PEM 字符串(默认生成 PKCS#8,兼容性更强)
let pemPrivateKey = pki.privateKeyFromPem(privateKeyPEM); // PKCS#8 PEM 字符串 → 私钥对象(反序列化)
console.log('PEM私钥是否还原:', keypair.privateKey.sign(sha1) === pemPrivateKey.sign(sha1));
// ========================= 将原始 RSA 私钥(PKCS#1 格式)转换为标准 PKCS#8 格式的私钥 ASN.1 对象 ========================
const privateKeyAsn1 = pki.privateKeyToAsn1(keypair.privateKey); // 私钥对象 → PKCS#1 格式 ASN.1 对象(仅包含 RSA 私钥参数)
let asn1PrivateKey = pki.privateKeyFromAsn1(privateKeyAsn1); // PKCS#1 ASN.1 对象 → 私钥对象(反序列化)
console.log('Asn1私钥是否还原:', keypair.privateKey.sign(sha1) === asn1PrivateKey.sign(sha1));
// ========================= 将原始 RSA 私钥(PKCS#1 格式)转换为标准 PKCS#8 格式的私钥 PEM 字符串 ========================
let privateKeyInfoAsn1 = pki.wrapRsaPrivateKey(privateKeyAsn1); // 包装:PKCS#1 ASN.1 对象 → PKCS#8 格式 PrivateKeyInfo ASN.1 对象(添加算法标识等元数据,通用格式)
let pemAsn1 = pki.privateKeyInfoToPem(privateKeyInfoAsn1); // 转换:PKCS#8 ASN.1 对象 → PKCS#8 格式 PEM 字符串(头部:BEGIN PRIVATE KEY)
let pemPrivateKey2 = pki.privateKeyFromPem(pemAsn1); // 解析:PKCS#8 PEM 字符串 → 私钥对象
console.log('PEM私钥是否还原(RSA私钥):', keypair.privateKey.sign(sha1) === pemPrivateKey2.sign(sha1));
// ========================= 私钥加密保护、序列化、解密还原流程(核心优化部分) ========================
const password = 'myCustomPasswordHere';
/**
* 1. 加密 PKCS#8 私钥信息(生成带密码保护的私钥对象)
* - 输入:PKCS#8 私钥ASN.1对象、密码、加密算法配置
* - 输出:EncryptedPrivateKeyInfo ASN.1 对象(含加密算法、加密后的私钥数据)
* - 算法:aes256 安全性最高,推荐生产环境使用
*/
let encryptedPrivateKeyInfo = pki.encryptPrivateKeyInfo(
privateKeyInfoAsn1, // PKCS#8 格式私钥ASN.1对象(明文)
password, // 私钥保护密码(建议生产环境使用高强度密码)
{ algorithm: 'aes256' } // 对称加密算法配置,支持 aes128/aes192/aes256/3des
);
/**
* 2. 解密加密私钥信息(还原明文 PKCS#8 私钥对象)
* - 输入:加密后的EncryptedPrivateKeyInfo对象、加密密码
* - 输出:原始 PKCS#8 格式 PrivateKeyInfo ASN.1 对象(明文)
* - 注意:密码错误会抛出异常,需添加异常捕获
*/
const privateKeyInfo = pki.decryptPrivateKeyInfo(
encryptedPrivateKeyInfo, // 加密后的私钥对象
password // 对应加密时的密码
);
/**
* 3. 加密私钥对象 → 加密私钥 PEM 字符串(序列化,便于存储/传输)
* - 输出 PEM 头部:-----BEGIN ENCRYPTED PRIVATE KEY-----
* - 该格式是标准加密私钥格式,可被大多数加密库识别
*/
let encryptedPrivatePem = pki.encryptedPrivateKeyToPem(encryptedPrivateKeyInfo);
/**
* 4. 加密私钥 PEM → 加密私钥对象(反序列化,从存储/传输中还原)
* - 解析 PEM 字符串,还原为 EncryptedPrivateKeyInfo ASN.1 对象
*/
encryptedPrivateKeyInfo = pki.encryptedPrivateKeyFromPem(encryptedPrivatePem);
/**
* 5. (可选)直接加密 RSA 私钥(PKCS#1 格式)为加密 PEM
* - encryptRsaPrivateKey:专门用于 RSA 私钥加密,默认生成 PKCS#8 加密格式
* - legacy: true:生成传统 PKCS#1 加密格式(兼容老系统,不推荐现代环境使用)
*/
const encryptedRsaPrivatePem = pki.encryptRsaPrivateKey(keypair.privateKey, password);
/**
* 6. 解密 RSA 加密私钥 PEM → 原始 RSA 私钥对象
* - 输入:加密私钥 PEM 字符串、密码
* - 输出:RSA 私钥对象(可直接用于签名/解密操作)
* - 注意:需确保密码与加密时一致,且 PEM 格式正确
*/
const decryptedRsaPrivateKey = pki.decryptRsaPrivateKey(encryptedRsaPrivatePem, password);
/**
* 7. 从 RSA 私钥对象中提取公钥(通过私钥的 n 模和 e 公钥指数生成)
* - 公钥可公开,用于加密数据或验证私钥签名
*/
const publicKey = pki.setRsaPublicKey(decryptedRsaPrivateKey.n, decryptedRsaPrivateKey.e);
/**
* 8. 验证最终还原的私钥功能一致性(签名对比)
*/
const finalSign = decryptedRsaPrivateKey.sign(sha1);
const originalSign = keypair.privateKey.sign(sha1);
console.log('=== 最终私钥还原验证 ===', finalSign === originalSign ? '✅ 私钥功能完全一致' : '❌ 私钥还原失败');

十二、公钥基础设施 - PKCS#10 (证书签名请求)
PKCS#10 是公钥基础设施下的规范之一,核心是证书签名请求(CSR)格式,用于向 CA(证书颁发机构)申请数字证书。
优点
- 是 CA 签发证书的标准输入格式,通用性强;
- 包含公钥和身份信息,能明确证书申请的主体信息。
缺点
- 仅用于证书申请,功能较为单一。
适用场景
- 向 CA 申请数字证书:如网站申请 HTTPS 证书;
- 企业 PKI 体系的证书签发流程:支撑企业内部证书的申请与发放。
javascript
import forge from 'node-forge';
const pki = forge.pki;
//证书相关文档,教程 "八、X.509数字证书"
const kwyPair = pki.rsa.generateKeyPair(2048);
let csr = forge.pki.createCertificationRequest();
csr.publicKey = kwyPair.publicKey;
csr.setSubject([
{ name: 'commonName', value: 'example.org' },
{ name: 'countryName', value: 'US' },
{ shortName: 'ST', value: 'Virginia' },
{ name: 'localityName', value: 'Blacksburg' },
{ name: 'organizationName', value: 'Test' },
{ shortName: 'OU', value: 'Test' }
]);
csr.setAttributes([
{ name: 'challengePassword', value: 'password' },
{ name: 'unstructuredName', value: 'My Company, Inc.' },
{
name: 'extensionRequest',
extensions: [
{
name: 'subjectAltName',
altNames: [
{ type: 2, value: 'test.domain.com' },
{ type: 2, value: 'other.domain.com' },
{ type: 2, value: 'www.domain.net' }
]
}
]
}
]);
csr.sign(kwyPair.privateKey);
const verified = csr.verify();
console.log('verified:', verified);
const pem = forge.pki.certificationRequestToPem(csr);
console.log('crs转换pem:', pem);
console.log('pem转换后边的crs:', forge.pki.certificationRequestFromPem(pem));
console.log('challengePassword:', csr.getAttribute({ name: 'challengePassword' }));
console.log('extensionRequest:', csr.getAttribute({ name: 'extensionRequest' }).extensions);

十三、公钥基础设施 - PKCS#12 (打包私钥、公钥证书、CA 证书)
PKCS#12 是公钥基础设施下的规范之一,核心用于将私钥、公钥证书、CA 证书链打包为单个文件(如.p12/.pfx 格式)。
优点
- 简化密钥 / 证书的传输与存储,整合多类密钥证书资源;
- 支持密码保护打包文件,提升打包内容的安全性。
缺点
- 格式兼容性存在差异,不同系统间解析可能出现错误;
- 大文件打包时效率较低。
适用场景
- 密钥 / 证书的备份与传输:如 HTTPS 证书对应的.pfx 文件;
- 客户端证书的分发:用于向客户端传递加密所需的证书与密钥。
| 函数名 | 说明 | 参数说明 | 返回值类型 |
|---|---|---|---|
| pkcs12FromAsn1 | 将PKCS#12格式的ASN.1结构化对象解析为可操作的Pkcs12Pfx对象,支持密码解密和严格/非严格解析模式,用于解析P12/PFX文件内容 | 1. obj: any - PKCS#12格式的ASN.1结构化对象 2. strict?: boolean - 可选,是否启用严格解析模式(默认true,非严格模式可兼容轻微格式错误) 3. password?: string - 可选,P12文件解密密码 | Pkcs12Pfx:包含P12内容的可操作对象,包含安全内容和筛选方法 1. Pkcs12Pfx.version:P12/PFX格式版本号,保障解析兼容性 2. Pkcs12Pfx.safeContents:安全内容容器数组,每个容器结构: • encrypted:该容器是否加密(true=加密,false=明文) • safeBags:存储私钥/证书的安全袋数组 3. Pkcs12Pfx.getBags(filter):按筛选条件(本地密钥ID/友好名称等)过滤安全袋,返回分类匹配结果 4. Pkcs12Pfx.getBagsByFriendlyName(friendlyName, bagType):按友好名称+袋类型精准筛选,返回匹配的安全袋数组 5. Pkcs12Pfx.getBagsByLocalKeyId(localKeyId, bagType):按本地密钥ID+袋类型精准筛选,返回匹配的安全袋数组 |
| toPkcs12Asn1 | 根据私钥、证书(链)和配置,构建PKCS#12格式的ASN.1结构化对象,生成P12/PFX文件的核心方法,后续可转为DER二进制格式保存 | 1. key: 用于传入生成P12容器的RSA私钥对象,传入有效pki.rsa.PrivateKey时,私钥会被加密存入P12;传入null时,P12仅存储证书,不包含私钥(极少场景使用) 2. cert: 用于传入要存入P12的X.509证书,支持单个pki.Certificate主证书,也支持证书数组(主证书+CA证书链,用于验证证书有效性) 3. password: 用于设置P12容器的解密密码,传入非空字符串时,P12内容会被密码加密(解密需对应密码);传入null时,P12无密码保护(明文存储,不推荐生产环境);传入空字符串,适配OpenSSL空密码生成的P12场景 4. options配置项: • lgoritnm:P12加密算法,默认aes256(最高安全)、3des兼容老系统 • count:PBKDF2迭代次数,默认1000,越高越安全但速度越慢 • saltSize:密码盐值大小,默认8字节,防彩虹表攻击 • useMac:是否启用MAC校验,默认true,验证P12是否被篡改 • localKeyId:本地密钥ID(十六进制),用于关联私钥与证书 • friendlyName:私钥/证书友好名称,便于工具识别和筛选 • generateLocalKeyId:是否自动生成密钥ID,默认false,true无需手动配置 | 返回asn1.Asn1对象 |
| generateKey | 基于密码、盐值等参数,通过密钥派生函数(PBKDF2)生成加密/解密所需的密钥,是P12文件加密和解密的底层辅助方法,无需手动调用(内部自动使用) | 1. password: 派生密钥的原始密码,null/undefined表示无密码,非空字符串为有效密码 2. salt: 盐值缓冲区,用于增强密码安全性,防止彩虹表攻击 3. id: 密钥用途标识字节,区分私钥/证书等不同用途的加密密钥 4. iter: 密钥派生迭代次数,数值越高,密码破解难度越大 5. n: 要生成的密钥字节长度,决定密钥的强度 6. md: 可选消息摘要对象,用于密钥派生计算,默认使用对应加密算法的默认摘要 | 返回util.ByteStringBuffer |
十四、公钥基础设施 - ASN.1
ASN.1 是公钥基础设施下的抽象语法标记,核心用于描述密码学数据(如证书、密钥)的结构,常用 DER/PEM 编码格式。
优点
- 是 X.509、PKCS 等密码学标准的基础编码格式,通用性极强;
- 跨平台兼容性强,可在不同系统间稳定传输数据。
缺点
- 可读性差(如二进制 DER 编码),非专业工具难以直接解析;
- 解析与序列化的复杂度较高,技术实现成本大。
适用场景
- 密码学数据的标准化存储 / 传输:如证书的 DER/PEM 格式;
- 加密库间的数据交互:保障不同加密工具间的数据兼容。
| 函数名 | 函数描述 | 参数说明 | 返回值类型 |
|---|---|---|---|
| create | 创建符合ASN.1规范的结构化对象,用于构建自定义ASN.1数据结构 | 1. tagClass: asn1.Class - ASN.1标签类 2. type: asn1.Type - ASN.1数据类型 3. constructed: boolean - 是否为构造化类型 4. value: Bytes | Asn1[] | asn1.Asn1 |
| fromDer | 将DER二进制编码数据解析为可操作的ASN.1结构化对象,用于读取ASN.1格式数据 | bytes: Bytes | util.ByteBuffer - 承载DER编码数据的载体 strict: boolean - 解析模式开关 | asn1.Asn1 |
| toDer | 与fromDer功能相反,将内存中的ASN.1对象转换为标准DER二进制格式,该格式是ASN.1数据的实际存储/传输格式(如生成证书文件、P12二进制数据)。返回的util.ByteStringBuffer可通过getBytes()方法转为字节字符串 | obj: asn1.Asn - 待转换的ASN.1结构化对象 | util.ByteStringBuffer |
| oidToDer | 专门用于OID类型的DER编码转换,仅生成OID本身的二进制数据,不包含ASN.1标签和长度字段,通常用于构建AlgorithmIdentifier等包含OID的ASN.1节点 | oid: OID - 点分格式的OID字符串(如"1.2.840.113549.1.1.1",对应RSA加密算法) | util.ByteStringBuffer |
| derToOid | 将DER编码的OID二进制数据转换为点分格式的OID字符串,用于识别算法/对象类型 | bytes: Bytes | util.ByteStringBuffer | util.ByteStringBuffer |
| integerToDer | 针对ASN.1 INTEGER类型的专用编码方法,将JavaScript普通整数转为符合DER规范的二进制数据,适用于构建证书序列号、公钥指数等整数类型字段 | int: number - 需要转换的整数数值 | util.ByteStringBuffer |
| derToInteger | 将DER编码的整数二进制数据转换为普通整数,用于解析ASN.1 INTEGER类型节点的值 | bytes: Bytes | util.ByteStringBuffer | util.ByteStringBuffer:DER编码的整数二进制数据 |
| dateToUtcTime | 将日期转换为ASN.1 UTCTIME类型的字节数据,用于构建证书有效期等时间字段 | date: 需要转换的日期对象或日期字符串(需符合UTC时间格式要求) | util.ByteStringBuffer |
| utcTimeToDate | 用于解析证书等ASN.1数据中的UTCTIME类型时间字段,将字节/字符串格式的时间转换为JavaScript Date对象,方便进行时间比较和格式化展示 | bytes: Bytes - ASN.1 UTCTIME类型的字节数据 | Date:转换后的日期 |
| dateToGeneralizedTime | 将日期转换为ASN.1 GENERALIZEDTIME类型的字节数据,用于构建长期有效时间字段 | date: 需要转换的日期 | string:需要转换的日期对象或日期字符串(支持更宽泛的时间范围,优于UTCTIME) |
| generalizedTimeToDate | 用于解析ASN.1数据中的GENERALIZEDTIME类型时间字段,支持更宽泛的时间范围,转换为JavaScript Date对象,适用于读取长期有效数据的时间信息 | bytes: Bytes - ASN.1 GENERALIZEDTIME类型的字节数据 | Date:转换后的日期 |
十五、SSH传输协议
javascript
import forge from 'node-forge';
// 1. 生成RSA密钥对(基础依赖)
const keyPair = forge.pki.rsa.generateKeyPair(2048);
const privateKey = keyPair.privateKey;
const publicKey = keyPair.publicKey;
const passphrase = '123456'; // 密钥加密密码
const comment = 'test@example.com'; // 密钥注释
// 2. 生成Putty PPK格式私钥
const ppkPrivateKey = forge.ssh.privateKeyToPutty(privateKey, passphrase, comment);
console.log('✅ Putty PPK私钥:\n', ppkPrivateKey);
// 可写入文件:fs.writeFileSync('id_rsa.ppk', ppkPrivateKey);
// 3. 生成OpenSSH格式公钥
const openSshPublicKey = forge.ssh.publicKeyToOpenSSH(publicKey, comment);
console.log('\n✅ OpenSSH公钥:\n', openSshPublicKey);
// 可写入文件:fs.writeFileSync('id_rsa.pub', openSshPublicKey);
// 4. 生成OpenSSH格式私钥(加密)
const openSshPrivateKey = forge.ssh.privateKeyToOpenSSH(privateKey, passphrase);
console.log('\n✅ OpenSSH加密私钥:\n', openSshPrivateKey);
// 可写入文件:fs.writeFileSync('id_rsa', openSshPrivateKey);
// 5. 生成原始字节缓冲区格式公钥指纹
const fingerprintBuffer = forge.ssh.getPublicKeyFingerprint(publicKey);
console.log('\n✅ 原始指纹字节缓冲区:', fingerprintBuffer);
console.log('✅ 原始指纹转十六进制:', fingerprintBuffer.toHex());
// 6. 生成格式化(十六进制+冒号分隔)公钥指纹
const formattedFingerprint = forge.ssh.getPublicKeyFingerprint(publicKey, {
encoding: 'hex',
delimiter: ':'
});
console.log('\n✅ 格式化公钥指纹:', formattedFingerprint);

| 函数名称 | 函数说明 | 参数说明 | 返回值类型 |
|---|---|---|---|
| privateKeyToOpenSSH | 将RSA私钥编码为OpenSSH格式文件,支持可选密码加密,适配OpenSSH环境使用 | 1. privateKey: pki.rsa.PrivateKey - 待转换的RSA私钥对象 2. passphrase?: string - 可选,用于加密私钥的密码,不传则生成无密码OpenSSH私钥 | string(OpenSSH格式私钥字符串) |
| privateKeyToPutty | 将RSA私钥编码(并可选加密)为Putty专用PPK格式文件,适配Putty系列工具使用 | 1. privateKey: pki.rsa.PublicKey - 待转换的RSA私钥对象 2. passphrase?: string - 可选,用于加密PPK文件的密码,不传则生成无密码PPK文件 3. comment?: string - 可选,密钥注释,便于识别密钥用途 | string(Putty PPK格式字符串) |
| publicKeyToOpenSSH | 将RSA公钥编码为OpenSSH格式文件,可添加注释,适配OpenSSH/SSH客户端使用 | 1. publicKey: pki.rsa.PublicKey - 待转换的RSA公钥对象 2. comment?: string - 可选,密钥注释(通常为"用户名@主机名"格式) | string | pki.PEM |
| getPublicKeyFingerprint | 获取指定SSH公钥的指纹,支持自定义编码、分隔符和摘要算法,用于密钥合法性校验 | 1. publicKey: pki.rsa.PublicKey - 待生成指纹的RSA公钥对象 2. options?: FingerprintOptions - 可选配置对象,包含: • options.delimiter: 十六进制编码输出时,字节之间使用的分隔符(可选) • options.encoding: 输出编码格式,不指定则返回ByteStringBuffer(可选,支持"hex"/"binary") • options.md: 计算指纹的摘要算法,不指定默认使用md.md5(可选) | util.ByteStringBuffer | Hex | string |
十六、TLS传输协议
| 函数名称 | 函数说明 | 参数说明 | 返回值类型 |
|---|---|---|---|
| createSessionCache | 创建TLS会话缓存对象,用于存储和复用TLS会话,提升连接建立效率 | SessionCache:缓存对象 • SessionCache.cache:存储TLS会话的键值对集合,以会话ID为键,Session对象为值 • SessionCache.capacity:会话缓存的最大容量,限制可存储的会话数量 • SessionCache.order:会话缓存的存储顺序数组(十六进制格式),用于管理缓存淘汰逻辑 • SessionCache.getSession(sessionId):根据会话ID从缓存中获取对应的TLS会话对象 • SessionCache.setSession(sessionId,session):将指定会话ID和对应的TLS会话对象存入缓存 | SessionCache |
| createConnection | 创建TLS连接对象,用于构建TLS客户端/服务器连接,处理TLS握手与数据传输 | options: 配置项 • options.server:是否为TLS服务器端连接(可选) • options.sessionId:TLS会话ID(可选,可为null) • options.caStore:CA证书仓库或证书数组,用于验证对方证书(可选) • options.sessionCache:TLS会话缓存或会话键对,用于会话复用(可选) • options.cipherSuites:支持的TLS加密套件数组(可选) • options.virtualHost:虚拟主机名(可选,用于SNI扩展) • options.verifyClient:是否验证客户端证书(仅服务器端有效,可选) • options.connected(conn: Connection):TLS连接建立成功后的回调函数 • options.verify(conn: Connection, verified: Verified, depth: number, certs: pki.Certificate[]):证书验证回调函数,用于自定义证书校验逻辑(可选) • options.getCertificate(conn: Connection, hint: CertificateRequest | string[]):获取证书的回调函数,返回PEM格式证书(可选) • options.getPrivateKey(conn: Connection, certificate: pki.Certificate):获取证书对应私钥的回调函数,返回PEM格式私钥(可选) • options.getSignature(conn: Connection, bytes: Bytes, callback: (conn: Connection, bytes: Bytes) => void):生成数字签名的回调函数,处理签名逻辑(可选) • options.tlsDataReady(conn: Connection):TLS加密数据就绪后的回调函数 • options.dataReady(conn: Connection):解密后的应用层数据就绪后的回调函数 • options.heartbeatReceived(conn: Connection, payload: util.ByteBuffer):收到TLS心跳消息后的回调函数(可选) • options.closed(conn: Connection):TLS连接关闭后的回调函数 • options.error(conn: Connection):TLS连接发生错误后的回调函数 • options.deflate(inBytes: Bytes):数据压缩回调函数,对发送数据进行压缩(可选) • options.inflate(inBytes: Bytes):数据解压回调函数,对接收数据进行解压(可选) | Connection对象 • Connection.version:TLS协议版本信息 • Connection.entity:TLS连接类型(客户端/服务器端) • Connection.sessionId:TLS会话ID,可为null • Connection.caStore:CA证书仓库,用于验证对方证书 • Connection.sessionCache:TLS会话缓存,可为null • Connection.cipherSuites:支持的TLS加密套件数组 • Connection.connected(conn: Connection):连接建立成功后的回调函数 • Connection.virtualHost:虚拟主机名(用于SNI扩展) • Connection.verifyClient:是否验证客户端证书(仅服务器端有效) • Connection.verify(conn: Connection, verified: Verified, depth: number, certs: pki.Certificate[]):自定义证书验证的回调函数 • Connection.getCertificate:获取证书的回调函数(conn: Connection, hint: CertificateRequest | string[]) => pki.PEM | readyState.pki.PEM),可为null • Connection.getPrivateKey:获取证书对应私钥的回调函数(conn: Connection, certificate: pki.Certificate) => pki.PEM),可为null • Connection.getSignature:生成数字签名的回调函数(conn: Connection, bytes: Bytes, callback: (conn: Connection, bytes: Bytes) => void),可为null • Connection.input:接收的原始数据字节缓冲区 • Connection.tlsData:待发送的TLS加密数据字节缓冲区 • Connection.data:解密后的应用层数据字节缓冲区 • Connection.tlsDataReady(conn: Connection):TLS加密数据就绪后的回调函数 • Connection.dataReady(conn: Connection):应用层数据就绪后的回调函数 • Connection.heartbeatReceived:收到TLS心跳消息后的回调函数(conn: Connection, payload: util.ByteBuffer) => void;),可为undefined • Connection.closed:连接关闭后的回调函数(conn: Connection) => void;) • Connection.error:连接发生错误后的回调函数(conn: Connection, error: TLSerror) => void;) • Connection.deflate:数据压缩函数((inBytes: Bytes) => Bytes),可为null • Connection.inflate:数据解压函数((inBytes: Bytes) => Bytes),可为null • Connection.reset(clearFail?: boolean):重置TLS连接状态的方法 • Connection.record:当前处理的TLS记录,可为null • Connection.session:当前TLS会话对象,可为null • Connection.peerCertificate:对方的证书对象,可为null • Connection.state:连接状态(包含待处理和当前状态) • Connection.expect:期望接收的数据长度 • Connection.fragmented:分片的TLS记录,可为null • Connection.records:待处理的TLS记录数组 • Connection.open:连接是否处于打开状态 • Connection.handshakes:已完成的握手次数 • Connection.handshaking:是否正在进行TLS握手 • Connection.isConnected:是否已成功建立连接 • Connection.fail:连接是否已失败 • Connection.handshake(sessionId?: Bytes | null):执行TLS握手的方法 • Connection.process(data: Bytes):处理接收数据的方法,返回处理的字节数 • Connection.prepare(data: Bytes):准备发送数据的方法,返回是否准备成功 • Connection.prepareHeartbeatRequest(payload: Bytes | util.ByteBuffer, payloadLength?: number):准备TLS心跳请求的方法,返回是否准备成功 • Connection.close(clearFail?: boolean):关闭TLS连接的方法,返回连接对象 |
| prf_tls1 | 实现TLS 1.0伪随机函数(PRF),用于从密钥材料生成指定长度的密钥数据 | 1. secret: string:密钥种子(共享密钥材料) 2. label: string:标识标签(用于区分不同用途的密钥) 3. seed: string:随机种子(用于增加随机性) 4. length: number:需要生成的密钥数据长度 | util.ByteBuffer(生成的密钥数据字节缓冲区) |
| hmac_sha1 | 基于SHA1算法生成TLS记录的HMAC消息认证码,用于验证记录数据的完整性和真实性 | 1. key: HMAC-SHA1加密密钥,支持字符串、字节数组或字节缓冲区格式 2. seqNum: TLS记录序列号,64位整数(以双元素数组表示) 3. record: 待生成认证码的TLS记录对象 | Bytes |
十七、forge.pki 通用函数
| 函数名 | 说明 | 参数说明 | 返回值类型 |
|---|---|---|---|
| pemToDer | 将PEM格式数据转换为DER二进制编码数据,去除PEM头部、尾部和换行符 | pem: PEM - PEM格式字符串(带头部尾部标识,如私钥/证书PEM) | util.ByteStringBuffer |
| privateKeyToPem | 将RSA私钥对象转换为标准PEM格式字符串,支持指定每行最大长度 | 1. key: PrivateKey - RSA私钥对象 2. maxline?: number - 可选,每行最大字符数,默认按标准拆分 | PEM |
| privateKeyInfoToPem | 将私钥信息的ASN.1对象转换为PEM格式字符串,支持指定每行最大长度 | 1. key: asn1.Asn1 - 私钥信息的ASN.1结构化对象 2. maxline?: number - 可选,每行最大字符数,默认按标准拆分 | PEM |
| publicKeyToPem | 将RSA公钥对象转换为X.509标准公钥PEM格式字符串,支持指定每行最大长度 | 1. key: PublicKey - RSA公钥对象 2. maxline?: number - 可选,每行最大字符数,默认按标准拆分 | PEM |
| publicKeyToRSAPublicKeyPem | 将RSA公钥对象转换为PKCS#1格式公钥PEM字符串,支持指定每行最大长度 | 1. key: PublicKey - RSA公钥对象 2. maxline?: number - 可选,每行最大字符数,默认按标准拆分 | PEM |
| publicKeyFromPem | 从PEM格式字符串中解析并获取RSA公钥对象 | pem: PEM - X.509或PKCS#1格式的公钥PEM字符串 | rsa.PublicKey |
| privateKeyFromPem | 从无加密PEM格式字符串中解析并获取RSA私钥对象 | pem: PEM - 无加密的RSA私钥PEM字符串(PKCS#1或PKCS#8格式) | rsa.PrivateKey |
| decryptPrivateKeyInfo | 使用密码解密私钥信息的ASN.1对象,获取明文私钥ASN.1结构 | 1. obj: asn1.Asn1 - 加密后的私钥信息ASN.1对象 2. password: string - 解密密码 | asn1.Asn1 |
| encryptPrivateKeyInfo | 使用密码加密私钥信息的ASN.1对象,支持自定义加密选项 | 1. obj: asn1.Asn1 - 明文私钥信息ASN.1对象 2. password: string - 加密密码 3. options?: EncryptionOptions - 可选,加密配置(如加密算法、迭代次数等) | asn1.Asn1 |
| encryptedPrivateKeyFromPem | 从加密私钥PEM格式字符串中解析出加密私钥的ASN.1对象 | pem: PEM - 加密的RSA私钥PEM字符串(如PKCS#8加密私钥) | asn1.Asn1 |
| encryptedPrivateKeyToPem | 将加密私钥的ASN.1对象转换为加密私钥PEM格式字符串 | obj: asn1.Asn1 - 加密后的私钥信息ASN.1对象 | PEM |
| decryptRsaPrivateKey | 使用密码解密加密私钥PEM字符串,获取RSA私钥对象 | 1. pem: PEM - 加密的RSA私钥PEM字符串 2. password: string - 解密密码 | rsa.PrivateKey |
| encryptRsaPrivateKey | 使用密码加密RSA私钥对象,生成加密私钥PEM格式字符串,支持自定义加密选项 | 1. privateKey: PrivateKey - 明文RSA私钥对象 2. password: string - 加密密码 3. options?: EncryptionOptions - 可选,加密配置(如加密算法、迭代次数等) | PEM |
| privateKeyFromAsn1 | 从私钥ASN.1对象中解析并获取RSA私钥对象 | privateKey: asn1.Asn1 - 明文私钥的ASN.1结构化对象 | rsa.PrivateKey |
| privateKeyToAsn1 | 将RSA私钥对象转换为私钥ASN.1结构化对象 | privateKey: PrivateKey - RSA私钥对象 | asn1.Asn1 |
| publicKeyFromAsn1 | 从公钥ASN.1对象中解析并获取RSA公钥对象 | publicKey: asn1.Asn1 - 公钥的ASN.1结构化对象(如SubjectPublicKeyInfo) | rsa.PublicKey |
| publicKeyToAsn1 | 将RSA公钥对象转换为X.509标准公钥ASN.1对象(SubjectPublicKeyInfo) | publicKey: PublicKey - RSA公钥对象 | asn1.Asn1 |
| publicKeyToRSAPublicKey | 将RSA公钥对象转换为PKCS#1格式的公钥数据(兼容旧版格式) | publicKey: PublicKey - RSA公钥对象 | any(PKCS#1格式公钥数据) |
| setRsaPublicKey | 为RSA公钥对象设置模(n)和公钥指数(e)参数,初始化公钥 | 继承自pki.rsa.setPublicKey,参数为模和公钥指数(具体同rsa.setPublicKey) | void(无返回值,直接修改对象) |
| setRsaPrivateKey | 为RSA私钥对象设置完整私钥参数,初始化私钥 | 继承自pki.rsa.setPrivateKey,参数为模、指数、私钥指数等(具体同rsa.setPrivateKey) | void(无返回值,直接修改对象) |
| wrapRsaPrivateKey | 将PKCS#1格式私钥ASN.1对象包装为PKCS#8格式私钥ASN.1对象 | privateKey: asn1.Asn1 - PKCS#1格式私钥ASN.1对象 | asn1.Asn1(PKCS#8格式私钥对象) |
| getPublicKeyFingerprint | 生成公钥指纹,返回字节缓冲区格式(默认SHA-1算法) | 1. publicKey: PublicKey - RSA公钥对象 2. options: 配置项,选择一种: • 【ByteBufferFingerprintOptions】:可选,指纹配置(算法、编码等),返回字节缓冲区 • 【HexFingerprintOptions】:必选,指纹配置(指定返回十六进制格式) • 【BinaryFingerprintOptions】:必选,指纹配置(指定返回字节字符串格式) | util.ByteStringBuffer | Hex | Bytes |
十八、 util.ByteStringBuffer
| 函数名 | 函数说明 | 参数说明 | 返回值类型 |
|---|---|---|---|
| length | 获取缓冲区中字节数据的总长度 | 无参数 | number(字节长度) |
| isEmpty | 判断缓冲区是否为空(无有效字节数据) | 无参数 | boolean(空返回true,非空返回false) |
| putByte | 向缓冲区末尾写入一个字节数据 | byte: Byte - 待写入的单个字节(0-255整数) | ByteStringBuffer(当前实例,支持链式调用) |
| fillWithByte | 向缓冲区末尾写入指定数量的重复字节 | 1. byte: Byte - 填充的字节值 2. n: number - 填充的字节数量 | ByteStringBuffer(当前实例,支持链式调用) |
| putBytes | 向缓冲区末尾写入一组字节字符串数据 | bytes: Bytes - 待写入的字节字符串 | ByteStringBuffer(当前实例,支持链式调用) |
| putString | 向缓冲区末尾写入普通字符串(按字符编码转换为字节) | str: string - 待写入的普通字符串 | ByteStringBuffer(当前实例,支持链式调用) |
| putInt16 | 向缓冲区末尾写入16位大端序整数 | int: number - 待写入的16位整数 | ByteStringBuffer(当前实例,支持链式调用) |
| putInt24 | 向缓冲区末尾写入24位大端序整数 | int: number - 待写入的24位整数 | ByteStringBuffer(当前实例,支持链式调用) |
| putInt32 | 向缓冲区末尾写入32位大端序整数 | int: number - 待写入的32位整数 | ByteStringBuffer(当前实例,支持链式调用) |
| putInt16Le | 向缓冲区末尾写入16位小端序整数 | int: number - 待写入的16位整数 | ByteStringBuffer(当前实例,支持链式调用) |
| putInt24Le | 向缓冲区末尾写入24位小端序整数 | int: number - 待写入的24位整数 | ByteStringBuffer(当前实例,支持链式调用) |
| putInt32Le | 向缓冲区末尾写入32位小端序整数 | int: number - 待写入的32位整数 | ByteStringBuffer(当前实例,支持链式调用) |
| putInt | 向缓冲区末尾写入指定位数的无符号整数 | 1. int: number - 待写入的整数 2. numOfBits: number - 整数的位数(如8、16、32等) | ByteStringBuffer(当前实例,支持链式调用) |
| putSignedInt | 向缓冲区末尾写入指定位数的有符号整数 | 1. int: number - 待写入的有符号整数 2. numOfBits: number - 整数的位数(如8、16、32等) | ByteStringBuffer(当前实例,支持链式调用) |
| putBuffer | 向缓冲区末尾写入另一个字节字符串缓冲区的数据 | buffer: ByteStringBuffer - 待写入的其他ByteStringBuffer实例 | ByteStringBuffer(当前实例,支持链式调用) |
| getByte | 从缓冲区当前读取位置读取一个字节数据,并推进读取偏移量 | 无参数 | number(读取的字节值,0-255) |
| getInt16 | 从缓冲区当前读取位置读取16位大端序整数,并推进读取偏移量 | 无参数 | number(读取的16位整数) |
| getInt24 | 从缓冲区当前读取位置读取24位大端序整数,并推进读取偏移量 | 无参数 | number(读取的24位整数) |
| getInt32 | 从缓冲区当前读取位置读取32位大端序整数,并推进读取偏移量 | 无参数 | number(读取的32位整数) |
| getInt16Le | 从缓冲区当前读取位置读取16位小端序整数,并推进读取偏移量 | 无参数 | number(读取的16位整数) |
| getInt24Le | 从缓冲区当前读取位置读取24位小端序整数,并推进读取偏移量 | 无参数 | number(读取的24位整数) |
| getInt32Le | 从缓冲区当前读取位置读取32位小端序整数,并推进读取偏移量 | 无参数 | number(读取的32位整数) |
| getInt | 从缓冲区当前读取位置读取指定位数的无符号整数,并推进读取偏移量 | numOfBits: number - 待读取整数的位数(如8、16、32等) | number(读取的无符号整数) |
| getSignedInt | 从缓冲区当前读取位置读取指定位数的有符号整数,并推进读取偏移量 | numOfBits: number - 待读取整数的位数(如8、16、32等) | number(读取的有符号整数) |
| getBytes | 从缓冲区当前读取位置读取指定数量的字节字符串,并推进读取偏移量 | count?: number - 可选,读取的字节数量(不传则读取剩余所有字节) | Bytes(读取的字节字符串) |
| bytes | 读取缓冲区中指定数量的字节字符串(不改变读取偏移量,与getBytes区别) | count?: number - 可选,读取的字节数量(不传则读取所有字节) | Bytes(读取的字节字符串) |
| at | 获取缓冲区中指定索引位置的字节数据(不改变读取偏移量) | index: number - 字节索引(从0开始) | Byte(指定位置的字节值,0-255) |
| setAt | 修改缓冲区中指定索引位置的字节数据 | 1. index: number - 字节索引(从0开始) 2. byte: number - 新的字节值(0-255) | ByteStringBuffer(当前实例,支持链式调用) |
| last | 获取缓冲区中最后一个字节数据(不改变读取偏移量) | 无参数 | Byte(最后一个字节值,0-255) |
| copy | 复制当前缓冲区的完整数据,创建一个新的ByteStringBuffer实例 | 无参数 | ByteStringBuffer(新的实例副本) |
| compact | 压缩缓冲区,移除已读取的字节数据,优化内存占用 | 无参数 | ByteStringBuffer(当前实例,支持链式调用) |
| clear | 清空缓冲区中的所有数据,重置读取偏移量 | 无参数 | ByteStringBuffer(当前实例,支持链式调用) |
| truncate | 截断缓冲区,保留未读取的字节数据,重置读取偏移量 | 无参数 | ByteStringBuffer(当前实例,支持链式调用) |
| toHex | 将缓冲区中的字节数据转换为十六进制字符串 | 无参数 | Hex(十六进制格式字符串) |
| toString | 将缓冲区中的字节数据转换为普通字符串(按字符编码解析) | 无参数 | string(解析后的普通字符串) |
十九、工具函数
1.forge.util
| 函数名 | 函数说明 | 参数说明 | 返回值类型 |
|---|---|---|---|
| fillString | 生成由指定字符重复指定次数组成的字符串 | 1. char: string - 用于填充的单个字符 2. count: number - 字符重复的次数 | string |
| xorBytes | 对两个字节字符串进行按位异或运算,返回指定长度的结果字节字符串 | 1. bytes1: string - 第一个字节字符串 2. bytes2: string - 第二个字节字符串 3. count: number - 需要进行异或运算的字节长度 | string(字节字符串) |
| hexToBytes | 将十六进制字符串转换为字节字符串 | hex: Hex - 待转换的十六进制字符串 | Bytes |
| bytesToHex | 将字节字符串转换为十六进制字符串 | bytes: Bytes - 待转换的字节字符串 | Hex |
| int32ToBytes | 将32位整数转换为对应的字节字符串(大端序) | int: number - 待转换的32位整数 | Bytes |
| encode64 | 将字节字符串编码为Base64格式字符串,支持指定每行最大长度 | 1. bytes: Bytes - 待编码的字节字符串 2. maxline?: number - 可选,每行最大字符数(用于格式化输出,默认无换行) | Base64 |
| decode64 | 将Base64格式字符串解码为字节字符串 | encoded: Base64 - 待解码的Base64字符串 | Bytes |
| encodeUtf8 | 将普通字符串编码为UTF-8格式字符串 | str: string - 待编码的普通字符串 | Utf8 |
| decodeUtf8 | 将UTF-8格式字符串解码为普通字符串 | encoded: Utf8 - 待解码的UTF-8字符串 | string |
| createBuffer | 创建一个空的字节缓冲区对象 | 无参数 | ByteBuffer |
| createBuffer | 根据输入数据和编码格式创建字节缓冲区对象,支持多种输入格式 | input: 用于初始化字节缓冲区的原始数据,支持字节字符串、数组缓冲区、缓冲区视图或字节字符串缓冲区格式 encoding: 可选,输入数据的编码格式,用于正确解析原始数据 | ArrayBuffer |
2.forge.util.binary
| 函数名 | 函数说明 | 参数说明 | 返回值类型 |
|---|---|---|---|
| binary.raw.encode | 将Uint8Array类型数据编码为字节字符串(Bytes) | x: Uint8Array - 待编码的Uint8Array二进制数据 | Bytes |
| binary.raw.decode | 将字节字符串(Bytes)解码为Uint8Array,支持指定输出缓冲区和偏移量 | 1. str: Bytes - 待解码的字节字符串 2. output?: Uint8Array - 可选,输出缓冲区(复用内存) 3. offset?: number - 可选,输出缓冲区的写入偏移量 | Uint8Array |
| binary.hex.encode | 将二进制数据编码为十六进制字符串(Hex),支持多种输入格式 | bytes: Bytes | ArrayBuffer | ArrayBufferView | ByteStringBuffer - 待编码的二进制数据 | ArrayBuffer |
| binary.hex.decode | 将十六进制字符串(Hex)解码为Uint8Array,支持指定输出缓冲区和偏移量 | 1. hex: Hex - 待解码的十六进制字符串 2. output?: Uint8Array - 可选,输出缓冲区(复用内存) 3. offset?: number - 可选,输出缓冲区的写入偏移量 | Uint8Array |
| binary.base64.encode | 将Uint8Array类型数据编码为Base64字符串,支持指定每行最大长度 | 1. input: Uint8Array - 待编码的Uint8Array二进制数据 2. maxline?: number - 可选,每行最大字符数(用于格式化输出,默认无换行) | Base64 |
| binary.base64.decode | 将Base64字符串解码为Uint8Array,支持指定输出缓冲区和偏移量 | 1. input: Base64 - 待解码的Base64字符串 2. output?: Uint8Array - 可选,输出缓冲区(复用内存) 3. offset?: number - 可选,输出缓冲区的写入偏移量 | Uint8Array |
3.forge.util.text
| 函数名 | 所属命名空间 | 函数说明 | 参数说明 | 返回值类型 |
|---|---|---|---|---|
| text.utf8.encode | text.utf8 | 将普通字符串编码为UTF-8格式的Uint8Array二进制数据,支持指定输出缓冲区和偏移量 | 1. str: string - 待编码的普通字符串 2. output?: Uint8Array - 可选,输出缓冲区(复用内存,避免重复创建) 3. offset?: number - 可选,输出缓冲区的写入偏移量(从该位置开始写入编码后的数据) | Uint8Array |
| ext.utf8.decode | text.utf8 | 将UTF-8格式的Uint8Array二进制数据解码为UTF-8字符串 | bytes: Uint8Array - 待解码的UTF-8格式二进制数据 | Utf8 |
| text.utf16.encode | text.utf16 | 将普通字符串编码为UTF-16格式的Uint8Array二进制数据,支持指定输出缓冲区和偏移量 | 1. str: string - 待编码的普通字符串 2. output?: Uint8Array - 可选,输出缓冲区(复用内存,避免重复创建) 3. offset?: number - 可选,输出缓冲区的写入偏移量(从该位置开始写入编码后的数据) | Uint8Array |
| text.utf16.decode | text.utf16 | 将UTF-16格式的Uint8Array二进制数据解码为普通字符串 | bytes: Uint8Array - 待解码的UTF-16格式二进制数据 | string |