本文讨论国密算法,只涉及简单介绍和使用,不研究算法实现。
国密
国密,即“国家商用密码”,主要包括以下算法:
- GM/T 0001 ZUC 祖冲之序列密码算法(对应 GB/T 33133 标准)
- GM/T 0002 SM4 分组密码算法(对应 GB/T 32907 标准)
- GM/T 0003 SM2 椭圆曲线公钥密码算法(对应 GB/T 32918 标准)
- GM/T 0004 SM3 密码杂凑算法(对应 GB/T 32905 标准)
- GM/T 0044 SM9 标识密码算法(对应 GB/T 38635 标准)
它们由国密局和密标委制定发布,属于中华人民共和国密码行业标准。
- 国家密码管理局,简称“国密局”,英文名称 State Cryptography Administration Office of Security Commercial Code Administration (OSCCA)
- 密码行业标准化技术委员会,简称“密标委”,英文名称 Cryptography Standardization Technical Committee (CSTC)
GmSSL JavaScript API
GmSSL 是 OpenSSL 的一个分支项目,支持 SM2/SM3/SM4/SM9/ZUC 等国密算法,不仅实现了类似 OpenSSL 的算法库和命令行工具,还内置了 JS 实现,见 https://github.com/guanzhi/GmSSL/tree/master/js。JS API 比较 low-level,没有封装为 ES 或 CommonJS 模块。
为了方便下面只演示 sm-crypto
和 gm-crypto
的使用(互相验证算法正确性),生产环境推荐使用 API 设计更为良好的 gm-crypto
。
sm-crypto
yarn add sm-crypto
API:
- sm2
sm2.generateKeyPairHex()
生成密钥对sm2.doEncrypt()
加密sm2.doDecrypt()
解密sm2.doSignature()
签名sm2.doVerifySignature()
验签sm2.getPoint()
获取椭圆曲线点
- sm3
sm3()
杂凑
- sm4
sm4.encrypt()
加密sm4.decrypt()
解密
详细文档见 https://www.npmjs.com/package/sm-crypto。
gm-crypto
yarn add gm-crypto
API:
- SM2
SM2.generateKeyPair()
生成密钥对SM2.encrypt(data, key[, options])
加密SM2.decrypt(data, key[, options])
解密
- SM3
SM3.digest(data[, inputEncoding][, outputEncoding])
摘要
- SM4
SM4.encrypt(data, key[, options])
加密SM4.decrypt(data, key[, options])
解密
详细文档见 https://www.npmjs.com/package/gm-crypto。
SM2
SM2 是非对称加密算法,在加解密前需要先生成公钥和私钥,可以使用 GmSSL 提供的命令行工具,或者通过 JS 库。
使用 sm-crypto
生成密钥:
const { writeFile } = require('fs');
const util = require('util');
const { sm2 } = require('sm-crypto');
const writeFileAsync = util.promisify(writeFile);
async function gensm2() {
const { publicKey, privateKey } = sm2.generateKeyPairHex();
await writeFileAsync(`sm2pk.key`, publicKey, 'utf8');
await writeFileAsync(`sm2sk.key`, privateKey, 'utf8');
console.log(`publicKey: ${publicKey}`);
console.log(`privateKey: ${privateKey}`);
}
gensm2();
或者 gm-crypto
:
const { writeFile } = require('fs');
const util = require('util');
const { SM2 } = require('gm-crypto');
const writeFileAsync = util.promisify(writeFile);
async function gensm2() {
const { publicKey, privateKey } = SM2.generateKeyPair();
await writeFileAsync(`sm2pk.key`, publicKey, 'utf8');
await writeFileAsync(`sm2sk.key`, privateKey, 'utf8');
console.log(`publicKey: ${publicKey}`);
console.log(`privateKey: ${privateKey}`);
}
gensm2();
两者的 API 基本一致。
使用 sm-crypto
进行 SM2 加解密:
const { sm2 } = require('sm-crypto');
const publicKey = `047a0c3901d445b5b21a498a2ec148b3aedff9bad42ef2228ee8afd6a389ab92a083cd5dae47381be4e4ff5e26d0eacd3aa716ba137a7dcfac27795b319abf270f`;
const privateKey = `84aa47c525a596264f42e1c6785978f1cc62f8fe6b02768f3f8467b8c840d0c7`;
const plaintext = `keqingrong@outlook.com`;
/* 拼接模式 */
const mode = {
C1C3C2: 1,
C1C2C3: 0
};
const encrypted = sm2.doEncrypt(plaintext, publicKey, mode.C1C3C2); // 加密结果为 16进制格式字符串
const decrypted = sm2.doDecrypt(encrypted, privateKey, mode.C1C3C2);
console.log(decrypted === plaintext); // true
使用 gm-crypto
进行 SM2 加解密:
const { SM2 } = require('gm-crypto');
const publicKey = `047a0c3901d445b5b21a498a2ec148b3aedff9bad42ef2228ee8afd6a389ab92a083cd5dae47381be4e4ff5e26d0eacd3aa716ba137a7dcfac27795b319abf270f`;
const privateKey = `84aa47c525a596264f42e1c6785978f1cc62f8fe6b02768f3f8467b8c840d0c7`;
const plaintext = `keqingrong@outlook.com`;
const encrypted = SM2.encrypt(plaintext, publicKey, {
mode: SM2.constants.C1C3C2,
inputEncoding: 'utf8',
outputEncoding: 'hex' // 支持 hex/base64 等格式
});
const decrypted = SM2.decrypt(encrypted, privateKey, {
mode: SM2.constants.C1C3C2,
inputEncoding: 'hex', // 支持 hex/base64 等格式
outputEncoding: 'utf8'
});
console.log(decrypted === plaintext); // true
SM3
SM3 是消息摘要算法,国家标准中称为“杂凑算法”,其实就是 Hash 算法。
const { sm3 } = require('sm-crypto');
const { SM3 } = require('gm-crypto');
console.log(sm3('keqingrong@outlook.com')); // a78144537f946f03c7eb6164a66a09dddbeddc64481a4e962639dd2c388c3b94
console.log(SM3.digest('keqingrong@outlook.com', 'utf8', 'hex')); // a78144537f946f03c7eb6164a66a09dddbeddc64481a4e962639dd2c388c3b94
SM4
SM4 是对称加密算法,加解密使用同一个密钥。
使用 sm-crypto
进行 SM4 加解密:
const { sm4 } = require('sm-crypto');
/* 密钥,32位十六进制数字 */
const key = '0123456789abcdeffedcba9876543210';
const plaintext = `keqingrong@outlook.com`;
// 默认 ECB 模式
const encrypted = sm4.encrypt(plaintext, key);
const decrypted = sm4.decrypt(encrypted, key);
console.log(encrypted); // 19cfe4742a6b961882f7d7ed1ae29429eafc43c785acaf6ba7a53f49af084308
console.log(decrypted === plaintext); // true
// CBC 模式
/* 初始化向量,32位十六进制数字 */
const iv = '0123456789abcdeffedcba9876543210';
const encrypted2 = sm4.encrypt(plaintext, key, {
iv,
mode: 'cbc'
});
const decrypted2 = sm4.decrypt(encrypted2, key, {
iv,
mode: 'cbc'
});
console.log(encrypted2); // dfca4853b818858ab3dc0ac6875baf41c9cf963c37ad36549611c5c3013410aa
console.log(decrypted2 === plaintext); // true
使用 gm-crypto
进行 SM4 加解密:
const { SM4 } = require('gm-crypto');
/* 密钥,32位十六进制数字 */
const key = '0123456789abcdeffedcba9876543210';
const plaintext = `keqingrong@outlook.com`;
// ECB 模式
const encrypted = SM4.encrypt(plaintext, key, {
mode: SM4.constants.ECB,
inputEncoding: 'utf8',
outputEncoding: 'hex', // 支持 hex/base64 等格式
});
const decrypted = SM4.decrypt(encrypted, key, {
mode: SM4.constants.ECB,
inputEncoding: 'hex', // 支持 hex/base64 等格式
outputEncoding: 'utf8',
});
console.log(encrypted); // 19cfe4742a6b961882f7d7ed1ae29429eafc43c785acaf6ba7a53f49af084308
console.log(decrypted === plaintext); // true
// CBC 模式
const iv = '0123456789abcdeffedcba9876543210';
const encrypted2 = SM4.encrypt(plaintext, key, {
iv,
mode: SM4.constants.CBC,
inputEncoding: 'utf8',
outputEncoding: 'hex',
});
const decrypted2 = SM4.decrypt(encrypted2, key, {
iv,
mode: SM4.constants.CBC,
inputEncoding: 'hex',
outputEncoding: 'utf8',
});
console.log(encrypted2); // dfca4853b818858ab3dc0ac6875baf41c9cf963c37ad36549611c5c3013410aa
console.log(decrypted2 === plaintext); // true
相关链接
- GmSSL
- sm-crypto https://github.com/JuneAndGreen/sm-crypto
- miniprogram-sm-crypto https://github.com/wechat-miniprogram/sm-crypto
- gm-crypto https://github.com/byte-fe/gm-crypto
- gm-crypto vs miniprogram-sm-crypto vs sm-crypto
- 国密
- 国家密码管理局 https://www.oscca.gov.cn/
- 密码行业标准化技术委员会 http://www.gmbz.org.cn/
- 标准规范 https://www.oscca.gov.cn/sca/xxgk/bzgf.shtml