国密算法在数据加密中的应用:对称与非对称的实现

做数据保护,算法选择是第一步。国密算法到底怎么用?说白了,就是两个流派:对称加密,非对称加密。我刚开始接触时也迷糊过,今天咱们把这层窗户纸捅破。

国密算法应用体系图 国密标准|GM/T 对称加密|SM1 / SM4 / SM7 SM4:128位分组|128位密钥 ECB / CBC / CTR / GCM 非对称加密|SM2 SM2:256位椭圆曲线|公钥/私钥 数字签名|密钥协商|加密 典型组合:SM2 + SM4 典型应用场景 金融数据加密传输|政务系统数据安全|密码模块身份认证 SM2 签名+ SM4 加密:先验签名后解密的流程

对称加密: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 比怎么样?” 咱们直接看表。

维度SM2RSA-2048效果对比
密钥长度256 位2048 位SM2 短得多
签名速度快慢SM2 性能好 3-5 倍
加密速度慢(用于密钥包裹)更慢都不适合大量数据
安全性256 位对标 AES-1282048 位当前都安全
国密合规符合 GM/T不推荐商用密码必须用 SM2
重点:SM2 的 256 位密钥提供的安全强度,和 RSA-3072 相当。但密钥长度只有后者的 1/12,在嵌入式设备上优势很明显。

混合加密架构:SM2 + SM4

实际项目中,加密大文件只用非对称加密?算了吧,性能扛不住。我的做法是:

  1. 用 SM2 公钥加密一个随机生成的 SM4 会话密钥。
  2. 用这个 SM4 会话密钥加密实际数据(比如 100MB 的文件)。
  3. 把加密后的会话密钥 + 加密后的文件一起发送。

这就是混合加密。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-2012GM/T 0003-2012
合规要求必选算法必选算法
注意:不管用哪种国密算法,密钥生命周期管理必须合规。我曾经有一个项目,算法用对了,但密钥存储在 /tmp 目录下,泄露了。安全不只是算法的事,是体系的事。

嗯,以上就是对称和非对称在国密场景下的实现要点。记住:SM4 管速度,SM2 管安全,两者配合才能构建合规又高效的数据保护方案。