Skip to content

SM2/SM3 cryptography TypeScript implementation based on Bouncy Castle Java - Zero dependencies, fully compatible, browser & Node.js support

License

Notifications You must be signed in to change notification settings

lihongjie0209/sm-js-bc

Repository files navigation

SM-JS-BC

SM2/SM3 TypeScript implementation based on Bouncy Castle Java

License: MIT TypeScript Node.js

一比一复刻 Bouncy Castle Java 的 SM2、SM3 和 SM4 算法的 TypeScript 实现。

✨ 特性

  • 🔐 SM2 - 椭圆曲线公钥密码算法(数字签名、公钥加密、密钥交换��

  • 🔒 SM3 - 密码杂凑算法(256位消息摘要)

  • 🔑 SM4 - 分组密码算法(128位对称加密)

  • 🎯 零运行时依赖 - 纯 TypeScript 实现

  • 🔒 完全兼容 - 与 Bouncy Castle Java 完全互操作

  • 📦 多格式输出 - 支持 CommonJS、ESM 和 IIFE

  • 🧪 双重验证 - 自闭环测试 + GraalVM 跨语言测试

  • 📚 完整文档 - 详细的 API 文档和使用指南

  • 高质量 - >90% 测试覆盖率

  • 🌐 浏览器支持 - 可在浏览器和 Node.js 中使用

📦 安装

npm install sm-js-bc

🚀 快速开始

💡 提示: 以下是基础用法示例。想要完整的可运行代码?直接跳转到 📚 完整示例 章��,所有示例都可以直接运行!

以下代码片段展示了各算法的基本用法:

SM3 哈希

import { SM3Digest } from 'sm-js-bc';

const digest = new SM3Digest();
const data = new TextEncoder().encode('Hello, SM3!');
digest.update(data, 0, data.length);

const hash = new Uint8Array(digest.getDigestSize());
digest.doFinal(hash, 0);

console.log('SM3 Hash:', Buffer.from(hash).toString('hex'));

📖 完整示例: example/sm3-hash.mjs

SM2 密钥对生成

import { SM2 } from 'sm-js-bc';

const keyPair = SM2.generateKeyPair();
console.log('Private key:', keyPair.privateKey.toString(16));
console.log('Public key X:', keyPair.publicKey.x.toString(16));
console.log('Public key Y:', keyPair.publicKey.y.toString(16));

📖 完整示例: example/sm2-keypair.mjs

SM2 数字签名

import { SM2 } from 'sm-js-bc';

const keyPair = SM2.generateKeyPair();

// 签名
const message = 'Hello, SM2!';
const signature = SM2.sign(message, keyPair.privateKey);

// 验签
const isValid = SM2.verify(message, signature, keyPair.publicKey);
console.log('Signature valid:', isValid);

📖 完整示例: example/sm2-sign.mjs

SM2 公钥加密

import { SM2 } from 'sm-js-bc';

const keyPair = SM2.generateKeyPair();

// 加密
const plaintext = new TextEncoder().encode('Secret message');
const ciphertext = SM2.encrypt(plaintext, keyPair.publicKey);

// 解密
const decrypted = SM2.decrypt(ciphertext, keyPair.privateKey);
console.log('Decrypted:', new TextDecoder().decode(decrypted));

📖 完整示例: example/sm2-encrypt.mjs

SM4 对称加密

import { SM4 } from 'sm-js-bc';

// 生成密钥并加密
const key = SM4.generateKey();
const plaintext = new TextEncoder().encode('Hello, SM4!');
const ciphertext = SM4.encrypt(plaintext, key);

// 解密
const decrypted = SM4.decrypt(ciphertext, key);
console.log('Decrypted:', new TextDecoder().decode(decrypted));

⚠️ 安全提示: 上述示例使用 ECB 模式,仅用于演示。生产环境请使用 CBC、CTR 或 GCM 模式。

📖 完整示例:

SM2 密钥交换

import { 
  SM2, 
  SM2KeyExchange,
  SM2KeyExchangePrivateParameters,
  SM2KeyExchangePublicParameters,
  ECPrivateKeyParameters,
  ECPublicKeyParameters
} from 'sm-js-bc';

// 获取SM2域参数
const domainParams = SM2.getParameters();
const curve = domainParams.getCurve();

// Alice 生成密钥对(静态 + 临时)
const aliceStatic = SM2.generateKeyPair();
const aliceEphemeral = SM2.generateKeyPair();

const aliceStaticPriv = new ECPrivateKeyParameters(aliceStatic.privateKey, domainParams);
const aliceStaticPub = new ECPublicKeyParameters(
  curve.createPoint(aliceStatic.publicKey.x, aliceStatic.publicKey.y), 
  domainParams
);
const aliceEphemeralPriv = new ECPrivateKeyParameters(aliceEphemeral.privateKey, domainParams);
const aliceEphemeralPub = new ECPublicKeyParameters(
  curve.createPoint(aliceEphemeral.publicKey.x, aliceEphemeral.publicKey.y), 
  domainParams
);

// Bob 生成密钥对(静态 + 临时)
const bobStatic = SM2.generateKeyPair();
const bobEphemeral = SM2.generateKeyPair();

const bobStaticPriv = new ECPrivateKeyParameters(bobStatic.privateKey, domainParams);
const bobStaticPub = new ECPublicKeyParameters(
  curve.createPoint(bobStatic.publicKey.x, bobStatic.publicKey.y), 
  domainParams
);
const bobEphemeralPriv = new ECPrivateKeyParameters(bobEphemeral.privateKey, domainParams);
const bobEphemeralPub = new ECPublicKeyParameters(
  curve.createPoint(bobEphemeral.publicKey.x, bobEphemeral.publicKey.y), 
  domainParams
);

// Alice 初始化密钥交换(发起方)
const aliceExchange = new SM2KeyExchange();
const alicePrivParams = new SM2KeyExchangePrivateParameters(
  true,  // initiator
  aliceStaticPriv,
  aliceEphemeralPriv
);
aliceExchange.init(alicePrivParams);

// Alice 计算共享密钥
const bobPubParams = new SM2KeyExchangePublicParameters(bobStaticPub, bobEphemeralPub);
const aliceSharedKey = aliceExchange.calculateKey(128, bobPubParams);

// Bob 初始化密钥交换(响应方)
const bobExchange = new SM2KeyExchange();
const bobPrivParams = new SM2KeyExchangePrivateParameters(
  false,  // responder
  bobStaticPriv,
  bobEphemeralPriv
);
bobExchange.init(bobPrivParams);

// Bob 计算共享密钥
const alicePubParams = new SM2KeyExchangePublicParameters(aliceStaticPub, aliceEphemeralPub);
const bobSharedKey = bobExchange.calculateKey(128, alicePubParams);

// 验证双方密钥一致
console.log('Keys match:', 
  Buffer.from(aliceSharedKey).equals(Buffer.from(bobSharedKey))
);

💡 提示: SM2 密钥交换涉及多个参数类和步骤,建议查看完整示例了解详细用法。

📖 完整示例: example/sm2-keyexchange.mjs


📚 完整示例

所有算法都提供了完整的可运行示例,位于 example 目录:

示例文件 说明 演示内容
sm3-hash.mjs SM3 哈希计算 基本哈希、分段更新、空数据处理
sm2-keypair.mjs SM2 密钥对生成 生成密钥对、查看公私钥
sm2-sign.mjs SM2 数字签名 签名、验签、错误验证
sm2-encrypt.mjs SM2 公钥加密 加密、解密、不同长度消息
sm2-keyexchange.mjs SM2 密钥交换 ECDH 协议、密钥协商
sm4-ecb-simple.mjs SM4 基础加密 ECB 模式、PKCS7 填充
sm4-modes.mjs SM4 多种模式 ECB/CBC/CTR/GCM 对比

🚀 运行示例

# 进入示例目录
cd example

# 安装依赖
npm install

# 运行单个示例
npm run sm3-hash           # SM3 哈希
npm run sm2-keypair        # SM2 密钥对生成
npm run sm2-sign           # SM2 数字签名
npm run sm2-encrypt        # SM2 公钥加密
npm run sm2-keyexchange    # SM2 密钥交换
npm run sm4-ecb-simple     # SM4 基础加密
npm run sm4-modes          # SM4 多种模式

# 运行所有示例
npm run all

详细说明请查看 example/README.md

�📖 文档

详细文档请查看 docs 目录:

🧪 测试

本项目采用双重验证策略,包含 TypeScript 单元测试和 Java GraalVM 跨语言互操作测试,总计 1077+ 个测试用例,确保代码质���和跨语言兼容性。

测试覆盖

Java GraalVM 集成测试 (1077 tests)

完整的跨语言互操作测试套件:

算法 测试类别 测试数量 说明
SM3 参数化测试 77 不同长度、字符集、标准向量
属性测试 720 72个属性 × 10次迭代
互操作测试 5 Java ↔ JavaScript 一致性
小计 802
SM2 签名 参数化测试 25 不同消息、密钥对、错误处理
属性测试 100 10个属性 × 10次迭代
互操作测试 4 Java签名 ↔ JS验证
小计 125
SM2 加密 参数化测试 39 多种大小、跨语言、边界情况
属性测试 100 10个属性 × 10次迭代
互操作测试 4 Java加密 ↔ JS解密
小计 139
跨语言测试 简化测试 3 SM3 基础互操作
总计 1077 全部通过 ✅

测试类型说明

  • 参数化测试 - 使用 JUnit 5 @ParameterizedTest,覆盖各种输入场景
  • 属性测试 - 使用 @RepeatedTest,验证数学和安全属性
  • 互操作测试 - 通过 GraalVM Polyglot API 确保 Java ↔ JavaScript 完全兼容

运行测试

一键运行所有测试

# 运行所有测试(JavaScript + Java)
node test-all.mjs

# 详细输出模式
node test-all.mjs --verbose

# 仅运行 JavaScript 测试
node test-all.mjs --skip-java

# 仅运行 Java 测试
node test-all.mjs --skip-js

# 查看帮助
node test-all.mjs --help

JavaScript 单元测试

# 运行所有单元测试
npm test

# 监听模式
npm run test:watch

# 测试覆盖率
npm run test:coverage

# 测试 UI
npm run test:ui

Java GraalVM 互操作测试

# 前置条件:安装 Maven 和 GraalVM (推荐 21+)

# 运行所有 Java 测试
cd test/graalvm-integration/java
mvn test

# 运行特定测试类
mvn test -Dtest=SM3ParameterizedTest
mvn test -Dtest=SM2SignaturePropertyTest
mvn test -Dtest=SM2EncryptionParameterizedTest

# 编译并运行
mvn clean test

测试环境要求

  • JavaScript 测试: Node.js >= 20.0.0
  • Java 测试:
    • JDK >= 17 (推荐 GraalVM 21+)
    • Maven >= 3.8.0
    • Bouncy Castle >= 1.70

测试架构

test/
├── unit/                          # TypeScript 单元测试
│   ├── crypto/                    # 密码学算法测试
│   ├── math/                      # 数学库测试
│   └── util/                      # 工具类测试
│
└── graalvm-integration/           # 跨语言互操作测试
    ├── java/                      # Java 测试项目
    │   ├── src/test/java/
    │   │   ├── base/              # 测试基类
    │   │   ├── interop/           # 互操作测试
    │   │   ├── parameterized/     # 参数化测试
    │   │   └── property/          # 属性测试
    │   └── pom.xml                # Maven 配置
    │
    └── BUG_FIX_SUMMARY.md         # 已知问题和修复

🏗️ 项目结构

sm-js-bc/
├── src/                    # 源代码
│   ├── crypto/            # 密码学算法
│   │   ├── digests/       # 摘要算法(SM3)
│   │   ├── engines/       # 加密引擎(SM2)
│   │   ├── signers/       # 签名算法(SM2)
│   │   ├── agreement/     # 密钥交换
│   │   └── params/        # 参数类
│   ├── math/              # 数学运算
│   │   ├── ec/            # 椭圆曲线
│   │   └── field/         # 有限域
│   ├── util/              # 工具类
│   └── exceptions/        # 异常类
├── test/                  # 测试
│   ├── unit/              # 单元测试
│   └── graalvm-integration/ # 互操作测试
├── docs/                  # 文档
└── dist/                  # 编译输出

🔧 开发

环境要求

  • Node.js >= 20.0.0
  • TypeScript >= 5.3.0
  • Java >= 17(仅互操作测试需要,推荐 GraalVM 21+)

开发流程

# 克隆项目
git clone <repository-url>
cd sm-js-bc

# 安装依赖
npm install

# 开发模式(监听文件变化)
npm run dev

# 运行测试
npm run test:watch

# 构建
npm run build

提交规范

使用 Conventional Commits:

feat: 新功能
fix: 修复 bug
docs: 文档更新
test: 测试相关
refactor: 重构
perf: 性能优化
chore: 构建/工具相关

🤝 贡献

欢迎贡献!请遵循以下步骤:

  1. Fork 本项目
  2. 创建特性分支 (git checkout -b feature/AmazingFeature)
  3. 提交更改 (git commit -m 'feat: Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 开启 Pull Request

请确保:

  • ✅ 所有测试通过
  • ✅ 代码覆盖率 >90%
  • ✅ 遵循代码规范
  • ✅ 更新相关文档

📜 许可证

MIT License

🔗 相关链接

🙏 致谢

  • Bouncy Castle 项目提供了优秀的参考实现
  • 所有为国密算法标准化做出贡献的专家学者

❓ 常见问题

为什么要实现这个库?

为了在 JavaScript/TypeScript 生态中提供一个与 Bouncy Castle Java 完全兼容的 SM2/SM3 实现,确保跨语言互操作性。

与其他 JavaScript SM2/SM3 库的区别?

  • ✅ 基于 Bouncy Castle Java 一比一复刻,保证兼容性
  • ✅ 通过 GraalVM 跨语言测试验证互操作性
  • ✅ 零运行时依赖,纯 TypeScript 实现
  • ✅ 完整的类型定义和文档

性能如何?

JavaScript 引擎(V8/Node.js)的性能已经非常接近 JVM。对于加密算法这类计算密集型任务,性能差异在可接受范围内,通常在同一数量级。

可以在生产环境使用吗?

项目目前处于开发阶段。建议等到 v1.0.0 正式版发布并经过充分测试后再用于生产环境。


如有问题或建议,欢迎提出 IssuePull Request

About

SM2/SM3 cryptography TypeScript implementation based on Bouncy Castle Java - Zero dependencies, fully compatible, browser & Node.js support

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published