国密算法库性能提升 25 倍的秘密

32 阅读6分钟

🚀 sm-crypto 全面升级:国密算法库性能提升 25 倍的秘密

摘要:从 JavaScript 到 TypeScript,从 jsbn 到原生 BigInt,sm-crypto-v2 如何在不破坏 API 兼容性的前提下,实现国密算法性能的质的飞跃?本文将深度解析两代库的核心差异,并给出选型建议。

国密算法架构图


一、背景:国密算法的前端之路

在金融、政务等关键领域,国密算法(SM2/SM3/SM4) 已成为合规标配。中办 2018 年 36 号文件明确要求,金融、电子政务、教育等领域必须全面推进自主可控密码技术的应用 。

对于前端开发者而言,sm-crypto 一直是 JavaScript 生态中国密算法的事实标准。但随着业务对性能要求的不断提升,原版基于 jsbn(JavaScript Big Number)的实现逐渐暴露出性能瓶颈:

  • SM2 签名验签慢:在移动端设备上尤为明显
  • 缺乏类型支持:TypeScript 项目需要额外声明文件
  • 包体积较大:jsbn 依赖增加了不必要的体积
  • 随机数安全:使用 Math.random() 存在潜在风险

于是,sm-crypto-v2 应运而生。

TypeScript vs JavaScript


二、架构重构:从底层开始的革新

2.1 大数运算的范式转移

sm-crypto (原版)

// 依赖 jsbn 库进行大数运算
const BigInteger = require('jsbn').BigInteger;
// 所有椭圆曲线运算都基于 jsbn

sm-crypto-v2

// 原生 BigInt 支持,无需第三方依赖
const k = BigInt('0x' + privateKey);
// 基于 noble-curves 抽象层重构 SM2

核心改进

  • 完全移除 jsbn 依赖,包体积从 未压缩 34kb → 压缩后仅 17kb
  • 自动选择最优随机数实现,告别 Math.random()Date.now() 的临时方案

2.2 现代模块系统的拥抱

// sm-crypto-v2 同时支持 ESM 和 CJS
import { sm2 } from 'sm-crypto-v2'; // ES Module ✅
const { sm2 } = require('sm-crypto-v2'); // CommonJS ✅

三、性能实测:数字说话

Apple M2 芯片环境下进行的基准测试(使用 benchmark.js):

操作sm-cryptosm-crypto-v2性能提升
SM2 生成密钥对148 ops/sec3,452 ops/sec23.3x 🚀
SM2 签名150 ops/sec3,829 ops/sec25.5x 🚀
SM2 验签76 ops/sec306 ops/sec4x
SM2 加密76 ops/sec304 ops/sec4x
SM3 Hash322 ops/sec519 ops/sec1.6x
SM3 HMAC244 ops/sec518 ops/sec2.1x
SM4 解密143,430 ops/sec237,247 ops/sec1.7x

关键发现

  • SM2 运算 是最大赢家,得益于 noble-curves 的优化实现
  • 内存占用 减少 11.3MB,运行结束后垃圾回收更彻底
  • SM4 本身已接近硬件极限,提升相对温和

四、功能增强:不只是性能

4.1 新增 API

// 1. SM2 密钥交换(ECDHE)
const { sm2 } = require('sm-crypto-v2');
const keyPair = sm2.generateKeyPairHex();
const sharedSecret = sm2.computeSharedSecret(
  keyPair.privateKey, 
  otherPublicKey
);

// 2. SM4 GCM 模式(提供认证加密)
const { sm4 } = require('sm-crypto-v2');
const encrypted = sm4.encryptGCM(plaintext, key, iv, aad);
const decrypted = sm4.decryptGCM(encrypted, key, iv, aad, tag);

4.2 类型安全

// sm-crypto-v2 提供完整的 TypeScript 类型定义
import { sm2, sm3, sm4 } from 'sm-crypto-v2';

// 类型提示和检查
const cipherMode: number = 1; // 1 = C1C2C3, 0 = C1C3C2
const signature: string = sm2.doSignature(msg, privateKey, {
  cipherMode,
  hash: true,
  der: true
});

五、实战迁移指南

5.1 安装升级

# 原版(维护模式)
npm install sm-crypto

# 新版(推荐)
npm install sm-crypto-v2

5.2 代码兼容

好消息sm-crypto-v2 完全兼容原版 API,历史单元测试全部通过!

// 以下代码在两个版本中完全一致
const { sm2, sm3, sm4 } = require('sm-crypto-v2');

// SM2 签名验签
let sigValueHex = sm2.doSignature(msg, privateKey, {
  hash: true,
  der: true
});
let verifyResult = sm2.doVerifySignature(msg, sigValueHex, publicKey, {
  der: true
});

// SM3 哈希
const hash = sm3(msg);

// SM4 加密(CBC模式)
const encryptData = sm4.encrypt(msg, key, { mode: 'cbc', iv });

5.3 何时升级?

场景建议
新项目直接使用 sm-crypto-v2
使用 TypeScript升级以获得完整类型支持
SM2 运算性能瓶颈升级可获 20x+ 性能提升
需要 SM4 GCM 模式v2 独有功能
老项目稳定运行可暂不升级,但建议规划迁移
对包体积极度敏感v2 体积更小

六、应用场景:国密算法在金融科技中的实践

根据央行《金融领域密码应用指导意见》,支付系统需在 2025 年前完成国密改造 。以下是典型应用场景:

6.1 网银支付 - SM2 数字签名

  • 前端使用 SM2 私钥对交易指令签名
  • 后端验签确保交易不可否认性

6.2 用户认证 - SM3 密码哈希

  • 前端 SM3(msg + salt) 处理密码
  • 防御彩虹表攻击,符合等保 2.0

6.3 数据传输 - SM4 通道加密

  • 结合国密 SSL 证书(SM2 + SM4 + SM3)
  • 替代传统 RSA/AES 方案

七、技术细节:为什么 BigInt 更快?

jsbn 的局限

  • 纯 JavaScript 实现的大数库
  • 使用数组存储数字位,运算需要循环遍历
  • 每个操作都有函数调用开销

原生 BigInt 的优势

  • 引擎级优化:V8 等引擎针对 BigInt 进行专门优化
  • 内存布局:连续内存存储,CPU 缓存友好
  • 算法优化:底层使用更快的乘法/模幂算法

此外,sm-crypto-v2 的 SM2 实现基于 noble-curves 库的 Abstract API,该库是密码学领域的现代标杆实现,经过形式化验证和广泛审计。


八、总结与展望

维度sm-cryptosm-crypto-v2
语言JavaScriptTypeScript
底层实现jsbn原生 BigInt + noble-curves
性能基准SM2 提升 25x,整体显著提升
包体积较大17kb (压缩后)
模块系统CommonJSESM + CJS 双支持
新特性基础功能SM2 密钥交换、SM4 GCM
维护状态维护模式积极开发中

选型建议

  • 新项目:无脑选 sm-crypto-v2,更好的性能 + 类型安全
  • 存量项目:评估 SM2 使用场景的性能压力,适时升级
  • 合规项目:两个版本均通过国家密码标准测试,均可放心使用

随着国产自主可控战略的推进,国密算法在前端生态中的地位将越来越重要。sm-crypto-v2 的出现,不仅是一次性能升级,更是国密算法库现代化的重要里程碑。


参考链接


💡 提示:如果你在使用过程中遇到问题,欢迎在评论区交流。对于 SM2 性能优化、SM4 GCM 模式使用等话题,后续可以单独开篇详聊。