国密算法在数据加密中的应用:对称与非对称的实现
做数据保护,算法选择是第一步。国密算法到底怎么用?说白了,就是两个流派:对称加密,非对称加密。我刚开始接触时也迷糊过,今天咱们把这层窗户纸捅破。
对称加密:SM4 的实战玩法
对称加密,加密和解密用同一把钥匙。国密里,SM4 是主力。我个人习惯在存储加密场景首选它,速度快,硬件开销小。
SM4 的核心参数
| 参数 | 值 | 说明 |
|---|---|---|
| 密钥长度 | 128 位 | 16 字节,完全够用 |
| 分组长度 | 128 位 | 和 AES 一样,数据按块处理 |
| 密码结构 | Feistel 结构 | 32 轮迭代,安全性有保障 |
| 工作模式 | ECB / CBC / CTR / GCM | 推荐 GCM,自带认证 |
小技巧:ECB 模式虽然简单,但不适合加密重复数据块。我在早期项目里踩过这个坑,后来全部改成 CBC 或 GCM。
SM4 代码示例(CBC 模式)
下面是用 GMSSL 库实现 SM4-CBC 加密的例子。记住,IV 必须随机生成,不能写死。
#include <openssl/evp.h>
#include <string.h>
void sm4_cbc_encrypt_example() {
EVP_CIPHER_CTX *ctx;
unsigned char key[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
unsigned char iv[16];
unsigned char plaintext[32] = "Hello, 国密合规!";
unsigned char ciphertext[48];
int len, ciphertext_len;
// 随机生成 IV
RAND_bytes(iv, 16);
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_sm4_cbc(), NULL, key, iv);
EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, strlen(plaintext));
ciphertext_len = len;
EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
ciphertext_len += len;
printf("加密完成!密文长度: %d\n", ciphertext_len);
EVP_CIPHER_CTX_free(ctx);
}
避坑指南:我曾经见过有团队把 IV 设置成全零,结果密文模式泄露,被攻击者猜出了明文分组之间的关联。IV 必须每次加密重新生成,并且和密文一起存储。
非对称加密:SM2 的签名和加密
SM2 是基于椭圆曲线的算法。你想想看,对称加密的密钥分发一直是个难题,SM2 就解决了这个痛点。它用公钥加密会话密钥,私钥只在服务端保存。
SM2 与传统算法的对比
我经常被问到:“SM2 和 RSA 比怎么样?” 咱们直接看表。
| 维度 | SM2 | RSA-2048 | 效果对比 |
|---|---|---|---|
| 密钥长度 | 256 位 | 2048 位 | SM2 短得多 |
| 签名速度 | 快 | 慢 | SM2 性能好 3-5 倍 |
| 加密速度 | 慢(用于密钥包裹) | 更慢 | 都不适合大量数据 |
| 安全性 | 256 位对标 AES-128 | 2048 位 | 当前都安全 |
| 国密合规 | 符合 GM/T | 不推荐 | 商用密码必须用 SM2 |
重点:SM2 的 256 位密钥提供的安全强度,和 RSA-3072 相当。但密钥长度只有后者的 1/12,在嵌入式设备上优势很明显。
混合加密架构:SM2 + SM4
实际项目中,加密大文件只用非对称加密?算了吧,性能扛不住。我的做法是:
- 用 SM2 公钥加密一个随机生成的 SM4 会话密钥。
- 用这个 SM4 会话密钥加密实际数据(比如 100MB 的文件)。
- 把加密后的会话密钥 + 加密后的文件一起发送。
这就是混合加密。RSA 时代就这么玩,国密时代也一样,只是把算法换成了 SM2 + SM4。
代码实现:混合加密流程
// 伪代码,展示混合加密核心逻辑
void hybrid_encrypt(const char *plaintext, size_t len) {
// 1. 生成 SM4 会话密钥
unsigned char session_key[16];
RAND_bytes(session_key, 16);
// 2. 使用接收方 SM2 公钥加密会话密钥
SM2_public_encrypt(session_key, 16, encrypted_key, recipient_pubkey);
// 3. 使用 SM4 加密实际数据
SM4_cbc_encrypt(plaintext, len, ciphertext, session_key, iv);
// 4. 输出:encrypted_key + iv + ciphertext
write_output(encrypted_key, iv, ciphertext);
}
经验之谈:很多刚入行的同学会忘记签名认证。混合加密里,先用 SM2 签名对数据哈希签名,再加密。这样接收方可以先验证签名,确认数据没被篡改,再解密。两步操作,缺一不可。
关键区别速查表
做个总结,方便你查阅。
| 对比维度 | SM4(对称) | SM2(非对称) |
|---|---|---|
| 密钥数量 | 1 个对称密钥 | 1 对:公钥 + 私钥 |
| 加解密速度 | 快,纳秒级 | 慢,毫秒级 |
| 适用数据量 | 任意大小 | 仅适合短数据(几百字节) |
| 密钥分发 | 需要安全信道(用 SM2 分发) | 公钥可公开,私钥本地保存 |
| 主要用途 | 数据加密 / 存储加密 | 签名 / 密钥协商 / 数字证书 |
| 国密版本 | GM/T 0002-2012 | GM/T 0003-2012 |
| 合规要求 | 必选算法 | 必选算法 |
注意:不管用哪种国密算法,密钥生命周期管理必须合规。我曾经有一个项目,算法用对了,但密钥存储在 /tmp 目录下,泄露了。安全不只是算法的事,是体系的事。
嗯,以上就是对称和非对称在国密场景下的实现要点。记住:SM4 管速度,SM2 管安全,两者配合才能构建合规又高效的数据保护方案。