2、SM4接口参数概览:密钥、IV、模式、填充、数据格式
我第一次接触SM4的时候,以为只要把数据丢进去就能加密完成。结果呢?五个参数配错一个,要么解密失败,要么安全等级直接归零。说白了,SM4就像一把锁,而这些参数就是你的钥匙和开锁方式。搞懂它们,才算真正会用这把锁。
2.1 密钥(Key)—— 锁芯里的那根针
密钥是整个加密的根基。SM4的密钥长度固定为128位,也就是16个字节。别想着搞个32字节的密钥想让它更安全,接口根本不认。
我个人习惯用os.urandom(16)或者硬件熵源来生成密钥。为什么?因为弱随机数生成器产生的密钥会被暴力破解,这是我在一次安全评审中亲眼见过的。
| 参数名称 | 值 | 说明 |
|---|---|---|
| 密钥长度 | 128 bit (16 byte) | 固定,不可变 |
| 常见格式 | 字节数组 / Hex / Base64 | 接口需统一 |
| 注意事项 | 必须随机生成 | 不要用硬编码或人工输入 |
2.2 初始向量(IV)—— 加盐的“种子”
IV不是所有的模式都需要,但CBC、CTR、CFB、OFB这些模式都必须要有。长度同样是128位,与密钥一样长。
IV的关键要求:必须随机、必须唯一。你用同一个IV加密同样的明文,得到的密文是一样的,这就相当于没加密。
我记得有一次,一个老系统为了省事把IV设成全零。攻击者通过观察两个加密结果的异同,直接推断出明文的部分内容。嗯,那之后我们花了一周重写整个加密模块。
常见的错误还有:用固定IV加密所有会话。正确的做法是每次加密都生成新的IV,并把它和密文一起传输(明文传输即可,因为它不需要保密)。
2.3 加密模式(Mode)—— 怎么拧动锁芯
模式决定了加密算法如何处理长数据块。我把常见的模式列了个表,方便你对比选择。
| 模式 | 特点 | 安全性 | 推荐场景 |
|---|---|---|---|
| ECB | 简单、可并行 | 低(有模式攻击) | 不推荐,除非你懂它的风险 |
| CBC | 引入IV,前一个密文影响后一个 | 中(需注意填充攻击) | 通用数据加密 |
| CTR | 流式,可并行,不需要填充 | 中(需保证IV唯一) | 高性能场景 |
| GCM | 认证加密(AEAD) | 高(自带完整性校验) | 网络传输、需要防篡改的场景 |
我个人最推荐GCM。为什么?因为它整合了加密和认证,一把解决数据保密和完整性两个问题。代价就是多了12字节的额外开销(nonce+tag)。但如果你的设备算力有限,CBC+MAC也可以搞定。
2.4 填充方式(Padding)—— 让数据对齐分组
SM4是分块加密,每块16字节。但明文长度不一定正好是16的倍数。这时候就需要填充。最常见的填充是PKCS7——缺多少字节就补多少字节,每个字节的值等于缺的字节数。
举个例子:明文最后一块只差3个字节,就补三个0x03。解密后根据最后一个字节的值就知道要扔掉几个填充字节。
其他填充方式:
- Zero Padding:补0,但无法区分数据里的0,不推荐。
- ISO 10126:随机字节加最后一个表示长度。现在已废弃。
- NOPADDING:适用于CTR、GCM等流式模式,不需要填充。
2.5 数据格式(Data Format)—— 加密前的最后一道手续
SM4接口接收和输出的都是字节数组,但你在业务层可能看到的是Hex字符串、Base64、甚至直接是文本。这中间存在编码转换。
我建议标准化为:输入统一用UTF-8编码为字节数组,输出密文用Base64编码方便传输。为什么?因为Base64比Hex省空间,且没有特殊字符。我曾经在HTTP调用里传Hex字符串,结果被URL编码搞出各种转义问题。
注意:如果密文要存在数据库里,优先用BLOB类型;如果非要存字符串,用Base64。
| 格式类型 | 优缺点 | 推荐使用场景 |
|---|---|---|
| 字节数组 (byte[]) | 直接,无额外开销 | 内部API调用 |
| Hex字符串 | 可读性好,但长度翻倍 | 日志、调试 |
| Base64字符串 | 比Hex短25%,含特殊字符 | 网络传输、存储 |
2.6 参数组合建议 —— 别瞎配
没有一套参数打天下的方案。我根据经验总结了一个速查表:
- 通用安全场景:密钥+随机IV + GCM模式 + 无填充 + 输出Base64
- 嵌入式低算力:密钥(硬件生成)+CBC + PKCS7 + 输出Hex(因为芯片可能不支持Base64库)
- 存量系统升级:确认原有填充方式,尽量保持一致,只改密钥和IV生成方式
最后,记住一点:参数之间是相互影响的。选错了模式,即使密钥再强也没用;填充不匹配,解密直接失败。
参数配置没有万能方案,要根据你的安全等级、计算资源、传输环境来权衡。别指望一把万能钥匙能开所有的锁,SM5也不行。