SM9 算法

一、简介

SM9 是由中国国家密码管理局发布的商用密码标准,属于基于身份的标识密码算法(IBC)。
它的核心特点是身份即公钥。用户的公钥可以直接从手机号、邮箱或身份证号等唯一标识中推导出来,彻底省去了传统 PKI 体系中复杂的数字证书申请和管理环节。

核心工作原理

SM9 的数学基础是椭圆曲线上的双线性对映射,其运行机制主要包含以下三个关键点:

  1. 密钥生成中心(KGC):系统中存在一个受信任的中心,负责保管系统主私钥。
  2. 私钥下发:当用户加入时,KGC 利用主私钥和用户的身份标识(ID),计算出唯一的用户私钥并安全下发。
  3. 无感加密与验签:发送方只需知道接收方的 ID,结合系统公开参数就能完成加密;验证方也可以直接用发送方的 ID 验证数字签名,全程无需交换证书。

相比传统密码体制的优势

  1. 极简密钥管理:不需要维护庞大的数字证书库,也免去了证书更新、吊销列表(CRL)查询等繁琐流程。
  2. 部署成本极低:通信双方无需预先交换公钥证书,直接通过对方已知的标识即可建立安全通信通道。
  3. 轻量化适配:由于去除了证书处理的开销,非常契合计算和存储资源受限的终端设备。

典型应用场景

  1. 物联网(IoT)安全:海量传感器或智能终端可直接使用设备 ID 作为标识,解决大规模设备接入时的认证和通道加密难题。
  2. 政务与企业办公:在电子政务内网或大型企业中,员工可用工号直接登录系统或签署电子公文,实现“一网通办”与统一身份认证。
  3. 安全电子邮件:直接使用对方的电子邮箱地址作为公钥进行邮件加密,无需事先获取对方的数字证书。
  4. 区块链隐私保护:利用 SM9 构造可链接环签名,可在保障交易可追溯的前提下,有效隐藏交易双方的地址隐私。

二、安装GmSSL

GmSSL
或者wget直接下载源码包。我这边已经liunx x86 系统案例为安装
wget https://github.com/guanzhi/GmSSL/releases/download/v3.2.0/GmSSL-3.2.0-Linux-x86_64.tar.gz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tar -zxvf  GmSSL-3.2.0-Linux-x86_64.tar.gz

cd GmSSL-3.2.0-Linux-x86_64/bin

cp gmssl /usr/local/bin/

##验证
gmssl version

##输出 GmSSL 3.2.0

## 选择秘钥文件存放目录 (这个自己决定)

mkdir /usr/local/gmssl

SM9签名秘钥生成

SM9 数字签名全流程示意图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
┌───────────────┐
│ KGC │
│ (密钥生成中心) │
└───────────────┘
│ 1. sm9setup

┌───────────────┐ ┌───────────────┐
│ 主私钥 master │ │ 主公钥 mpk │
│ msk.pem │ │ mpk.pem │
│ (绝对保密) │ │ (公开分发) │
└───────────────┘ └───────────────┘
│ 2. sm9keygen -id bob@company

┌───────────────────────┐
│ Bob 的签名私钥 │
│ bob_sign.pem │
│ (仅 Bob 持有) │
└───────────────────────┘

──────────── 实际业务阶段 ────────────

Bob Verifier(任何人)
│ │
│ 3. sm9sign │
│ -id bob@company │
│ -key bob_sign.pem │
│──────────────────────────────▶│
│ │ 4. sm9verify
│ │ -id bob@company
│ │ -pubkey mpk.pem
│ │
│ ▼
│ ✅ 验签成功

一、生成 SM9 签名主密钥对

1
2
3
4
5
6
7
8

cd /usr/local/gmssl/sign

# 签名主密钥
# 该命令完成 SM9 KGC(密钥生成中心)初始化,生成签名场景下的主密钥对。
# 会在 /usr/local/gmssl/sign 目录下 生成 sm9_sign_msk.pem 与 sm9_sign_mpk.pem 文件
gmssl sm9setup -alg sm9sign -pass 123456 -out sm9_sign_msk.pem -pubout sm9_sign_mpk.pem

参数 含义
sm9setup SM9 系统初始化接口,用于生成主密钥对(Master Key Pair)。
-alg sm9sign 指定算法用途为 SM9 数字签名。可选值还有 sm9enc(加密)、sm9exchange(密钥交换)。
-pass 123456 设置主私钥 PEM 文件的加密口令,用于对生成的 sm9_sign_msk.pem进行对称加密保护。(123456 是可以定义的)
-out sm9_sign_msk.pem 输出的 SM9 主私钥文件(Master Secret Key)。必须严格保密,不能泄露。
-pubout sm9_sign_mpk.pem 输出的 SM9 主公钥文件(Master Public Key)。可公开分发,用于用户私钥生成或验签。

二、为用户生成 SM9 签名私钥

1
2
3
4
5
6
7
8

cd /usr/local/gmssl/sign

# 用户生成 SM9 签名私钥
# KGC 使用主私钥,根据用户 ID bob@company,生成 Bob 的 SM9 签名私钥。
# 会在 /usr/local/gmssl/sign 目录下 生成 bob_sign.pem 用户签名私钥文件
gmssl sm9keygen -alg sm9sign -in sm9_sign_msk.pem -inpass 123456 -id bob@company -out bob_sign.pem -outpass 123456

参数 含义
sm9keygen SM9 用户私钥生成命令(由 KGC 执行)。
-alg sm9sign 指定生成的是 SM9 签名私钥,必须与 sm9setup使用的算法一致。
-in sm9_sign_msk.pem 输入 SM9 主私钥文件,用于派生用户私钥。
-inpass 123456 主私钥 PEM 文件的解密口令,与 sm9setup -pass对应。
-id bob@company 用户的 身份标识(ID)。SM9 中公钥 = ID,私钥由主私钥 + ID 派生。ID 可以是邮箱、手机号、证书序列号等字符串。
-out bob_sign.pem 输出的 用户签名私钥文件(Bob 的签名私钥)。
-outpass 123456 对用户私钥 PEM 文件进行加密保护的口令。

三、SM9 中的关键概念对照

概念 对应文件/参数
主私钥(KGC 私钥) sm9_sign_msk.pem
主公钥(系统公钥) sm9_sign_mpk.pem
用户身份 -id bob@company
用户私钥 bob_sign.pem
用户“公钥” 不需要单独文件,就是 ID(bob@company)

四、后续常见操作示例(补充)

1️⃣ 使用 Bob 私钥签名

1
2
gmssl sm9sign  -in message.txt -key bob_sign.pem -pass 123456 -out sig.der
## 即会生成 sig.der 文件

2️⃣ 使用主公钥验签

1
2
gmssl sm9verify -id bob@company -in message.txt -pubmaster sm9_sign_mpk.pem -sig sig.der
## 成功会返回 sm9verify success
SM9 签名做「身份认证 / 登录 / 签名」时
1
2
3
4
5
6
7
8
9
KGC(只建一次)
└─ sm9setup ← 只执行【一次】,生成:
├─ sm9_sign_msk.pem (主私钥,KGC 保管)
└─ sm9_sign_mpk.pem (主公钥,所有人可拿)

然后:
Alice → sm9keygen -id alice@company → alice_sign.pem
Bob → sm9keygen -id bob@company → bob_sign.pem
Carol → sm9keygen -id carol@company → carol_sign.pem

✔ 系统主密钥只生成 1 次​

✔ 每个需要签名/认证的人,由 KGC 生成 1 份自己的 SM9 用户签名私钥

验证方(比如登录服务器)连用户私钥都不需要,只要:

1
2
3
主公钥 mpk.pem
用户ID(如 alice@company)
签名值

SM9 登录认证整体时序图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
┌────┐                              ┌────┐                              ┌────┐
│用户│ │网关│ │KGC │
│Bob │ │Server│ │ │
└────┘ └────┘ └────┘
│ │ │
│ 1. 请求登录 │ │
│---------------------------------->│ │
│ │ │
│ 2. 返回随机挑战 nonce │ │
│<----------------------------------│ │
│ │ │
│ 3. 用 SM9 私钥对 nonce 签名 │ │
│ sm9sign -id bob@company ... │ │
│ │ │
│ 4. 提交 ID + nonce + sig │ │
│---------------------------------->│ │
│ │ 5. sm9verify │
│ │ -id bob@company │
│ │ -pubkey mpk.pem │
│ │ -sig sig.der │
│ │───────────────────────────────────│
│ │ │
│ 6. 验签成功 → 登录成功 │ │
│<----------------------------------│ │

五、注意事项(很重要)

主私钥 sm9_sign_msk.pem一旦泄露,整个系统安全性失效。
-pass -inpass -outpass仅用于 PEM 文件加密,不参与密码学运算。
ID 区分大小写,bob@company≠ Bob@Company
签名与加密的主密钥不能混用,必须分别 sm9setup

SM9 加密主密钥生成

一、生成 SM9 加密主密钥

1
2
3
4
5
6
7

cd /usr/local/gmssl/encryption

##生成 SM9 标识密码(IBC)加密场景下的主密钥对:
##主私钥(Master Secret Key, MSK)
##主公钥(Master Public Key, MPK)
gmssl sm9setup -alg sm9encrypt -pass 123456 -out sm9_enc_msk.pem -pubout sm9_enc_mpk.pem
参数 含义
sm9setup GMSSL 中用于生成 SM9 系统参数的命令
-alg sm9encrypt 指定算法用途为 SM9 加密(区别于签名 sm9sign)
-pass 123456 给生成的 主私钥文件​ 设置 PEM 加密口令(对称加密保护私钥)
-out sm9_enc_msk.pem 输出的 主私钥文件(保密,仅 KGC 持有)
-pubout sm9_enc_mpk.pem 输出的 主公钥文件(可公开,用于用户私钥生成和加密)

📌 说明

  1. 主私钥 sm9_enc_msk.pem:绝对不能泄露
  2. 主公钥 sm9_enc_mpk.pem:可以分发给所有用户
  3. -pass只是保护私钥文件的口令,不是 SM9 算法本身的密钥

二、生成用户加密私钥

1
2
3
4
5
6

cd /usr/local/gmssl/encryption

##使用 主私钥,为身份 alice@company生成对应的 SM9 加密用户私钥。
gmssl sm9keygen -alg sm9encrypt -in sm9_enc_msk.pem -inpass 123456 -id alice@company -out alice_enc.pem -outpass 123456

参数 含义
sm9keygen 从主私钥生成用户私钥的命令
-alg sm9encrypt 指定生成的是 加密用途​ 的用户私钥
-in sm9_enc_msk.pem 输入的主私钥文件
-inpass 123456 主私钥文件的口令(与 -pass对应)
-id alice@company 用户标识(ID),SM9 的核心特性:ID = 公钥
-out alice_enc.pem 输出的用户私钥文件
-outpass 123456 给用户私钥文件设置的 PEM 加密口令

📌 关键点

  1. alice@company就是 Alice 的公钥
  2. 私钥由 KGC(掌握主私钥的一方)生成后安全下发
  3. 用户只需要:ID, 自己的私钥文件, 系统主公钥 sm9_enc_mpk.pem
1
2
3
主私钥 (MSK) ──→ 生成 ──→ 用户私钥 (alice_enc.pem)
主公钥 (MPK) ─────────────→ 所有人可用
用户 ID (alice@company) ───→ 等价于公钥

四、常见补充说明

✅ SM9 是 国密标识密码算法

✅ 不需要证书,ID 即公钥

✅ 加密:sm9encrypt

✅ 签名:sm9sign(主密钥和私钥要重新生成)

❗ 主私钥一旦泄露,整个系统安全性失效

五、 SM9 加密 & 解密完整示例

  1. 环境确认

    1
    gmssl version
  2. 生成主密钥,用户加密私钥

1
2
3
4
5
##生成主密钥
gmssl sm9setup -alg sm9encrypt -pass 123456 -out sm9_enc_msk.pem -pubout sm9_enc_mpk.pem

## 生成 Alice 的加密私钥
gmssl sm9keygen -alg sm9encrypt -in sm9_enc_msk.pem -inpass 123456 -id alice@company -out alice_enc.pem -outpass 123456
  1. 使用 Bob(或其他人)加密消息给 Alice
1
2
## 准备明文
echo "Hello SM9 Encryption" > plaintext.txt
1
2
3
4
5
6
7
8
## 加密(用 Alice 的 ID + 系统主公钥)
gmssl sm9encrypt -in plaintext.txt -pubmaster sm9_enc_mpk.pem -id alice@company -out ciphertext.sm9


#📌 说明:
# -pubmaster:系统主公钥
# -id:接收者 ID(就是公钥)
# 不需要 Alice 的私钥
  1. 对 Alice用户消息 解密
    1
    2
    3
    4
    5
    gmssl sm9decrypt  -in ciphertext.sm9 -key alice_enc.pem -id alice@company -pass 123456 -out decrypted.txt

    ## 查看结果
    cat decrypted.txt
    ## ✅ 输出应为: Hello SM9 Encryption