3. 加密算法与数据类型的关联

好,咱们直接聊正题。加密算法不是万能的,它对数据类型有自己的脾气。你选错算法,轻则解密失败,重则丢数据。我在项目里见过太多这种事了。今天我就把三种主流算法的数据类型适配问题掰开揉碎了讲。

3.1 对称加密:AES 与 SM4 的二进制游戏

对称加密,说白了就是一把钥匙开一把锁。AES 和 SM4 都是块加密算法,它们操作的是固定长度的二进制数据块。你想想看,要加密的字段可能是文本、数字、甚至是一张图片的二进制流。这些数据怎么喂给算法?

关键点一:输入必须是字节序列

AES 和 SM4 不认“字符串”或“整数”。它们只认 byte[] 。所以每次加密前,你得先把原始数据序列化成字节。我习惯用一个通用函数,根据字段类型做转换:

// 示例:数据类型到字节数组的转换
public byte[] toBytes(Object fieldValue) {
    if (fieldValue instanceof String) {
        return ((String) fieldValue).getBytes(StandardCharsets.UTF_8);
    } else if (fieldValue instanceof Integer) {
        ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
        buffer.putInt((Integer) fieldValue);
        return buffer.array();
    } else if (fieldValue instanceof byte[]) {
        return (byte[]) fieldValue;
    }
    // 其他类型...
}

关键点二:块对齐与填充

AES 块大小固定 16 字节,SM4 也是 16 字节。如果你的数据不是 16 的倍数,就必须填充。填充方式有很多种,我最常用 PKCS7。嗯,这里要注意,填充会使密文比明文长。如果你存储字段长度有严格限制,得提前算好。

经验之谈: 我处理过用户身份证号加密。身份证号是 18 位 ASCII 字符,正好 18 字节。AES 加密后,因为填充变成了 32 字节。数据库字段如果只预留 20 字节,数据就存不进去了。这是一个很常见的坑。

不同类型的字段,加密后的长度增长也不同。我整理了一个常用表:

原始数据类型原始字节长度AES-256 加密后长度SM4 加密后长度
String (10 字符, UTF-8)30 字节32 字节32 字节
Integer4 字节16 字节16 字节
Long8 字节16 字节16 字节
Boolean1 字节16 字节16 字节

你看,对于小字段,加密后的膨胀率很高。所以你在设计库表结构时,密文字段长度要留够余量。

3.2 非对称加密:RSA 与 SM2 的天花板

非对称加密有个硬伤——数据长度限制。这个限制从哪来?RSA 和 SM2 的加密过程基于大数运算。你输入的数据,必须小于模数(N)的字节长度。一旦超过,算法就报错。

RSA 的限制:

  • RSA-2048 的模数 N 是 256 字节。但还需要预留填充空间(OAEP 或 PKCS#1 v1.5)。
  • 实际可加密的最大字节数 = 密钥字节长度 - 填充开销 - 1(OAEP 填充时,最多可加密 190 字节)。
  • 明文超过限制,只能分段加密。但这会大幅降低性能,且需要额外管理分段逻辑。

SM2 的限制:

  • SM2 基于椭圆曲线,它的限制不是模数长度,而是曲线参数。
  • SM2 公钥加密的明文长度上限是曲线阶的字节数,通常是 32 字节左右。
  • 所以 SM2 几乎不能直接加密大数据块。它更常用来加密对称密钥。
避坑指南: 我曾经有一个项目,直接用 RSA-2048 加密一条 300 字节的 JSON 日志。结果运行时报错 “Data too long for RSA modulus”。这就是典型的数据类型感知缺失。正确的做法是:先用对称密钥加密大字段,再用 RSA 加密那个对称密钥。

我把常用的适配规则列一下,方便你对照:

非对称算法密钥长度最大明文长度(OAEP)推荐适配场景
RSA-2048256 字节190 字节加密短字符串、数字签名、对称密钥的加密
RSA-4096512 字节446 字节同上,可处理稍长数据
SM2256 位(等效)约 64 字节密钥交换、数字签名、加密对称密钥

3.3 哈希算法:单向输出的风格

哈希不是加密,它是摘要。它把任意长度的输入,映射成固定长度的输出。你想想看,一个 1GB 的视频和一个 1 字节的字符,经过 SHA-256 处理后,都变成 32 字节的哈希值。这个特性对字段级加密来说,意义重大。

输入特征:几乎无限制

SHA-256、SM3、MD5 这些算法,接受任意长度的二进制数据。你不用操心块对齐和填充。但要注意,输入数据内容哪怕只改动一个比特,输出哈希值就会面目全非。这就是所谓的雪崩效应。

输出特征:固定长度、不可逆

哈希输出长度是固定的。我列几个常见的:

  • MD5: 16 字节(128 位),但现在已不安全。
  • SHA-256: 32 字节(256 位),国密场景经常用。
  • SM3: 32 字节(256 位),国密标准,与 SHA-256 长度一致。
  • SHA-512: 64 字节(512 位),安全性更高,但计算更慢。
实际应用: 哈希在字段级加密中的典型用法是数据完整性校验和“脱敏”场景。比如,用户邮箱的前缀常用哈希值替代,以确保不可逆。我在做用户画像系统时,就用 SM3 对手机号哈希,作为用户组的唯一标识,既防止原始数据泄露,又能做关联查询。

哈希还有一个特性叫“输入不敏感”。意思是,你不能从哈希值反推原始数据。所以它只能用于校验,不能用于“解密”。这一点很多新手会搞混。记得有一次,同事试图用哈希值做登录验证的“密码”,还要我帮他实现“解密功能”……那是不可能的。

3.4 核心知识体系总览

为了让你一眼看清这三类算法的数据适配关系,我画了一张图。它把算法类型、数据输入限制、输出特征串起来了。你多看几遍,心里就有谱了。

加密算法与数据类型适配关系图 对称加密 AES / SM4 非对称加密 RSA / SM2 哈希算法 SHA-256 / SM3 数据输入特征 块对齐 + 填充 | 长度上限(模数/曲线阶) | 无长度限制 输出特征 密文长度 = 块大小倍数 | 密文长度 ≤ 密钥长度 | 固定长度,不可逆 适配策略:小数据直接加密 | 大数据混合加密 | 摘要校验+脱敏 算法类型 数据输入/输出特征 适配策略

记住这张图。对称加密适合大数据块,但要处理好字节序列和填充。非对称加密适合小数据或密钥交换,千万不能超长。哈希算法最适合做完整性校验和脱敏。这三种算法配合起来,才能适配你字段里复杂的业务数据类型。