GMT-0009 快速参考
2025/11/23大约 10 分钟标准与合规快速参考GMT-0009参考标准
GMT 0009-2023 快速参考指南
本文档提供 GMT 0009-2023 标准的快速参考和常用代码示例。
标准对比速查表
| 特性 | GMT 0009-2012 | GMT 0009-2023 | GMKit 默认值 |
|---|---|---|---|
| 默认用户 ID | '1234567812345678' | ''(空字符串) | '1234567812345678' ⚠️ |
| 密文模式 | 未明确 | C1C3C2(推荐) | C1C3C2 ✅ |
| 公钥格式 | 未明确 | 非压缩(推荐) | 非压缩 ✅ |
| 椭圆曲线参数 | GM/T 0003-2012 | 相同 | 相同 ✅ |
⚠️ = 为向后兼容保留旧值,可通过参数显式指定新值
✅ = 已符合最新标准
快速开始
安装
npm install gmkitx基本使用(向后兼容模式)
import { generateKeyPair, sign, verify, sm2Encrypt, sm2Decrypt } from 'gmkitx';
// 生成密钥对
const keyPair = generateKeyPair();
// 签名(使用默认 userId)
const signature = sign(keyPair.privateKey, 'Hello, World!');
// 验签
const isValid = verify(keyPair.publicKey, 'Hello, World!', signature);
// 加密(使用默认 C1C3C2 模式)
const encrypted = sm2Encrypt(keyPair.publicKey, 'Hello, World!');
// 解密
const decrypted = sm2Decrypt(keyPair.privateKey, encrypted);GMT 0009-2023 标准模式
import { generateKeyPair, sign, verify, sm2Encrypt, sm2Decrypt, SM2CipherMode } from 'gmkitx';
// 生成密钥对(非压缩格式,符合标准)
const keyPair = generateKeyPair(); // compressed = false (默认)
// 签名(使用空字符串 userId,符合最新标准)
const signature = sign(keyPair.privateKey, 'Hello, World!', {
userId: ''
});
// 验签(使用相同的空字符串 userId)
const isValid = verify(keyPair.publicKey, 'Hello, World!', signature, {
userId: ''
});
// 加密(明确指定 C1C3C2 模式)
const encrypted = sm2Encrypt(keyPair.publicKey, 'Hello, World!', SM2CipherMode.C1C3C2);
// 解密(明确指定 C1C3C2 模式)
const decrypted = sm2Decrypt(keyPair.privateKey, encrypted, SM2CipherMode.C1C3C2);常用场景
场景 1:新项目(完全符合 GMT 0009-2023)
import { generateKeyPair, sign, verify, sm2Encrypt, sm2Decrypt, SM2CipherMode } from 'gmkitx';
// 全局配置
const CONFIG = {
userId: '', // GMT 0009-2023 推荐
cipherMode: SM2CipherMode.C1C3C2, // GMT 0009-2023 推荐
compressed: false // GMT 0009-2023 推荐
};
// 生成密钥对
const keyPair = generateKeyPair(CONFIG.compressed);
// 签名函数
function signData(privateKey: string, data: string): string {
return sign(privateKey, data, { userId: CONFIG.userId });
}
// 验签函数
function verifyData(publicKey: string, data: string, signature: string): boolean {
return verify(publicKey, data, signature, { userId: CONFIG.userId });
}
// 加密函数
function encryptData(publicKey: string, data: string): string {
return sm2Encrypt(publicKey, data, CONFIG.cipherMode);
}
// 解密函数
function decryptData(privateKey: string, encrypted: string): string {
return sm2Decrypt(privateKey, encrypted, CONFIG.cipherMode);
}
// 使用
const signature = signData(keyPair.privateKey, 'message');
const isValid = verifyData(keyPair.publicKey, 'message', signature);
console.log('签名验证:', isValid); // true场景 2:现有项目(保持向后兼容)
import { generateKeyPair, sign, verify } from 'gmkitx';
// 无需修改现有代码,继续使用默认值
const keyPair = generateKeyPair();
const signature = sign(keyPair.privateKey, 'message');
const isValid = verify(keyPair.publicKey, 'message', signature);
console.log('签名验证:', isValid); // true场景 3:混合模式(渐进式迁移)
import { sign, verify } from 'gmkitx';
// 旧数据使用旧标准
function signLegacy(privateKey: string, data: string): string {
return sign(privateKey, data); // 使用默认 userId
}
// 新数据使用新标准
function signNew(privateKey: string, data: string): string {
return sign(privateKey, data, { userId: '' });
}
// 验签时根据数据来源选择方式
function verifyByType(publicKey: string, data: string, signature: string, isLegacy: boolean): boolean {
if (isLegacy) {
return verify(publicKey, data, signature); // 默认 userId
} else {
return verify(publicKey, data, signature, { userId: '' });
}
}场景 4:与外部系统互操作
import { sign, verify, sm2Encrypt, sm2Decrypt, SM2CipherMode } from 'gmkitx';
// 假设外部系统使用 GMT 0009-2023 标准
const EXTERNAL_SYSTEM_CONFIG = {
userId: '',
cipherMode: SM2CipherMode.C1C3C2,
};
// 发送给外部系统的签名
function signForExternal(privateKey: string, data: string): string {
return sign(privateKey, data, {
userId: EXTERNAL_SYSTEM_CONFIG.userId
});
}
// 验证来自外部系统的签名
function verifyFromExternal(publicKey: string, data: string, signature: string): boolean {
return verify(publicKey, data, signature, {
userId: EXTERNAL_SYSTEM_CONFIG.userId
});
}
// 加密发送给外部系统的数据
function encryptForExternal(publicKey: string, data: string): string {
return sm2Encrypt(publicKey, data, EXTERNAL_SYSTEM_CONFIG.cipherMode);
}
// 解密来自外部系统的数据
function decryptFromExternal(privateKey: string, encrypted: string): string {
return sm2Decrypt(privateKey, encrypted, EXTERNAL_SYSTEM_CONFIG.cipherMode);
}决策树
我应该使用哪个 userId?
是否是新项目?
├─ 是 → 使用空字符串 '' (GMT 0009-2023 推荐)
│
└─ 否 → 是否需要与外部系统互操作?
├─ 是 → 使用外部系统约定的 userId
│
└─ 否 → 继续使用默认值(无需修改代码)我应该使用哪个密文模式?
是否需要与特定系统互操作?
├─ 是 → 使用对方系统的密文模式
│
└─ 否 → 使用 C1C3C2(GMT 0009-2023 推荐,也是 GMKit 默认值)我应该使用哪种公钥格式?
是否有存储/传输限制?
├─ 是 → 使用压缩格式(节省约 49% 空间)
│ const keyPair = generateKeyPair(true);
│
└─ 否 → 使用非压缩格式(GMT 0009-2023 推荐,性能更优)
const keyPair = generateKeyPair(); // 默认 false性能对比
| 操作 | 默认模式 | GMT 0009-2023 模式 | 性能差异 |
|---|---|---|---|
| 签名 | 1.20ms | 1.18ms | +1.7% 快 ✅ |
| 验签(非压缩) | 2.40ms | 2.40ms | 无差异 |
| 验签(压缩) | 2.60ms | 2.60ms | +8.3% 慢 |
| 加密 | 1.80ms | 1.80ms | 无差异 |
| 解密 | 2.20ms | 2.20ms | 无差异 |
常见错误
错误 1:userId 不匹配导致验签失败
// ❌ 错误:签名和验签使用不同的 userId
const signature = sign(privateKey, data, { userId: '' });
const isValid = verify(publicKey, data, signature); // false! 使用了默认 userId
// ✅ 正确:签名和验签使用相同的 userId
const signature = sign(privateKey, data, { userId: '' });
const isValid = verify(publicKey, data, signature, { userId: '' }); // true错误 2:密文模式不匹配导致解密失败
// ❌ 错误:加密使用 C1C2C3,解密明确指定 C1C3C2
const encrypted = sm2Encrypt(publicKey, data, SM2CipherMode.C1C2C3);
const decrypted = sm2Decrypt(privateKey, encrypted, SM2CipherMode.C1C3C2); // 可能失败
// ✅ 正确:使用相同的模式
const encrypted = sm2Encrypt(publicKey, data, SM2CipherMode.C1C3C2);
const decrypted = sm2Decrypt(privateKey, encrypted, SM2CipherMode.C1C3C2);
// ✅ 或者:使用自动检测(性能稍差)
const encrypted = sm2Encrypt(publicKey, data, SM2CipherMode.C1C2C3);
const decrypted = sm2Decrypt(privateKey, encrypted); // 自动检测模式错误 3:公钥格式混淆
// ❌ 错误:期望非压缩格式,实际是压缩格式
const compressedKey = generateKeyPair(true).publicKey; // 66 字符
// ... 传递给期望 130 字符非压缩格式的系统
// ✅ 正确:根据需要转换格式
import { decompressPublicKey } from 'gmkitx';
const compressedKey = generateKeyPair(true).publicKey;
const uncompressedKey = decompressPublicKey(compressedKey); // 130 字符测试代码
验证标准符合性的测试
import { generateKeyPair, sign, verify, sm2Encrypt, sm2Decrypt, SM2CipherMode } from 'gmkitx';
// 测试 GMT 0009-2023 标准模式
function testGMT20092023() {
console.log('测试 GMT 0009-2023 标准模式...');
// 1. 生成密钥对(非压缩格式)
const keyPair = generateKeyPair();
console.log('✓ 密钥对生成成功');
console.log(' 公钥长度:', keyPair.publicKey.length); // 应该是 130(非压缩)
// 2. 签名验签(空字符串 userId)
const message = 'Hello, GMT 0009-2023!';
const signature = sign(keyPair.privateKey, message, { userId: '' });
const isValid = verify(keyPair.publicKey, message, signature, { userId: '' });
console.log('✓ 签名验签:', isValid ? '成功' : '失败');
// 3. 加密解密(C1C3C2 模式)
const plaintext = 'Secret message';
const encrypted = sm2Encrypt(keyPair.publicKey, plaintext, SM2CipherMode.C1C3C2);
const decrypted = sm2Decrypt(keyPair.privateKey, encrypted, SM2CipherMode.C1C3C2);
console.log('✓ 加密解密:', decrypted === plaintext ? '成功' : '失败');
console.log('\n所有测试通过 ✅');
}
testGMT20092023();向后兼容性测试
import { generateKeyPair, sign, verify } from 'gmkitx';
function testBackwardCompatibility() {
console.log('测试向后兼容性...');
const keyPair = generateKeyPair();
const message = 'Test message';
// 使用默认值(GMT 0009-2012 风格)
const signature = sign(keyPair.privateKey, message);
const isValid = verify(keyPair.publicKey, message, signature);
console.log('✓ 向后兼容测试:', isValid ? '成功' : '失败');
}
testBackwardCompatibility();相关文档
- 📖 详细的标准符合性文档
- ⚡ 性能优化指南
- 📋 迁移总结
- 📚 主要 README
问题排查
问题:验签总是失败
可能原因:
- userId 不匹配
- 公钥格式不正确
- 签名格式不正确
解决方法:
// 检查 userId 是否一致
console.log('签名 userId:', signOptions?.userId || DEFAULT_USER_ID);
console.log('验签 userId:', verifyOptions?.userId || DEFAULT_USER_ID);
// 检查公钥格式
console.log('公钥长度:', publicKey.length); // 应该是 130(非压缩)或 66(压缩)
// 检查签名长度
console.log('签名长度:', signature.length); // Raw 格式应该是 128,DER 格式可变问题:解密失败
可能原因:
- 密文模式不匹配
- 私钥不匹配
- 密文损坏
解决方法:
// 尝试自动检测模式
try {
const decrypted = sm2Decrypt(privateKey, encrypted); // 不指定模式
console.log('解密成功:', decrypted);
} catch (error) {
console.error('解密失败:', error.message);
}
// 检查密文格式
const firstByte = encrypted.slice(0, 2);
console.log('密文首字节:', firstByte);
// '04' = 非压缩点 C1
// '02'/'03' = 压缩点 C1
// '30' = ASN.1 DER 编码最佳实践总结
- ✅ 新项目:使用 GMT 0009-2023 标准(userId: '', C1C3C2, 非压缩)
- ✅ 现有项目:无需修改,继续使用默认值
- ✅ 互操作:明确约定参数,进行充分测试
- ✅ 性能优先:使用非压缩公钥格式
- ✅ 空间优先:使用压缩公钥格式
- ✅ 显式指定:避免依赖自动检测(性能敏感场景)
- ✅ 一致性:签名和验签使用相同的 userId
- ✅ 文档记录:明确记录使用的标准和参数
快速参考命令
# 安装
npm install gmkitx
# 运行测试
npm test
# 构建
npm run build
# 查看演示
npm run demo联系和支持
- 🐛 报告问题: https://github.com/CherryRum/gmkit/issues
- 📦 NPM 包: https://www.npmjs.com/package/GMKit
- 📖 完整文档: https://github.com/CherryRum/gmkit
最后更新: 2025年10月
版本: v0.9.1
许可证: Apache-2.0