第2章:常见加密算法在数据库中的应用:AES、RSA、SM4对比归纳总结

聊到数据库加密,很多朋友第一反应就是「用什么算法?」。我见过不少项目,选型阶段就在AES、RSA、SM4之间反复横跳,一会儿说AES标准,一会儿说RSA能签名,一会儿又听说SM4是国标。说白了,没有一种算法是万能的。我个人习惯是先明确场景,再看参数,最后敲定方案。

先给你一张对比总表,读完本章再回来看,会很有感觉。

常见加密算法在数据库中的应用对比 对称加密 AES (高级加密标准) 参数配置 密钥长度: 128/192/256-bit 工作模式: ECB / CBC / GCM 填充方案: PKCS7 / NoPadding 应用: 列加密 / TDE / 备份加密 SM4 (国密对称) 参数配置 密钥长度: 128-bit 分组长度: 128-bit 轮数: 32轮 应用: 商密合规 / 政务数据库 非对称加密 RSA (公钥加密) 参数配置 密钥长度: 2048/4096-bit 填充方案: OAEP / PKCS1v1.5 应用: 密钥传输 / 数字签名 注意: 不加密大数据 核心对比维度 安全性 性能 密钥管理 合规性 数据库适配 性能摘要 AES / SM4 硬件加速可达数 Gbps | RSA 4096-bit 签名约 5,000 ops/sec 选择要点 数据加密 → AES/SM4 | 密钥分发 → RSA | 国密合规 → SM4 | 混合方案最常见

2.1 AES:数据库加密的默认选择

AES是目前数据库领域使用最广泛的对称加密算法。为什么?说白了就是快、稳、支持完善。我测过,AES-128比AES-256快大约40%,但安全强度在大多数场景下已经足够。

我记得有一次帮客户调优加密审计日志,他们一开始用的是AES-256-CBC。查询加密字段时,页面加载要等十几秒。我一查,问题出在密钥推导上——每次查询都重新算一遍密钥。加了个密钥缓存层,速度直接翻了3倍。

AES关键参数表

参数项 推荐值 说明
密钥长度 128-bit / 256-bit 128-bit足够防暴力破解;256-bit应对更高安全等级
工作模式 GCM(推荐)/ CBC GCM自带认证,防篡改;CBC需要额外做完整性校验
填充方案 PKCS7 GCM模式下不需要填充
硬件加速 AES-NI指令集 现代CPU普遍支持,务必启用

在数据库里怎么用AES?以MySQL为例,直接用内置函数就行:

-- 加密写入
INSERT INTO audit_log (encrypted_data)
VALUES (AES_ENCRYPT('敏感审计内容', 'your-encryption-key'));

-- 解密查询
SELECT AES_DECRYPT(encrypted_data, 'your-encryption-key')
FROM audit_log WHERE id = 123;

避坑提示: 用AES_ENCRYPT时一定要处理好密钥的存储。我建议用密钥管理服务(KMS),而不是直接把密钥硬编码在SQL脚本里。

你可能会问:AES-KDF(密钥派生函数)要不要用?我个人建议,如果密钥是从用户口令生成的,用PBKDF2或bcrypt做一次KDF,能把暴力破解的难度提升好几个数量级。

2.2 RSA:非对称加密的扛把子

RSA不走寻常路,它用一对密钥(公钥+私钥)。公钥加密,私钥解密,反之亦然。这玩意儿在数据库里一般不用来加密大量数据——性能太差了。你想想看,RSA加密1KB数据的时间,AES能加密几十MB了。

那RSA在数据库加密里的正确用法是什么?我碰到过不少新人,直接用RSA加密整张表,结果查询性能直接崩盘。正确的打开方式是用RSA来加密AES的密钥。这个方案叫做混合加密,在实际项目中百试百灵。

性能警示: RSA 4096-bit在单核上约5,000次/秒签名。如果你要加密10万行审计日志,用RSA直接加密,对数据库来说是噩梦。

我在项目中遇到过这么一个场景:审计日志需要跨系统传输。发送方用RSA公钥加密AES密钥,再用AES密钥加密日志数据。接收方用RSA私钥解出AES密钥,再用AES密钥解密日志。整个过程公钥在网上传输也不怕,因为只有私钥能解开。

数据库里怎么管理RSA密钥?

-- 生成RSA密钥对(示例用OpenSSL生成证书)
-- 私钥:用于解密传输来的加密密钥
-- 公钥:分发给各业务系统

-- 数据库侧存储公钥(用于验证签名)
CREATE TABLE trusted_public_keys (
    id INT PRIMARY KEY,
    key_name VARCHAR(64),
    public_key_pem TEXT,
    created_at TIMESTAMP
);

-- 使用公钥验证数据完整性(伪代码)
SELECT VERIFY_RSA_SIGNATURE(data_blob, signature, trusted_public_key_pem)
FROM audit_log;

经验分享: RSA密钥长度至少2048位。4096位更安全,但性能下降约4倍。我个人的平衡点:核心审计数据用4096位,普通日志用2048位。

2.3 SM4:国密合规的必修课

SM4是咱们国家的商用密码标准。说实话,刚接触SM4时,我觉得它跟AES差不多——都是对称加密,密钥128位,分组128位。但有几个关键差异你需要知道。

SM4最独特的地方是它的S盒设计和32轮迭代结构。我在项目中对比过SM4和AES的加解密速度,在纯软件实现下,SM4比AES慢大概15%-20%。但一旦启用了硬件加速(现在主流国产CPU都支持),差距基本可以忽略。

我曾经在金融项目里碰到一个硬性要求:所有存储个人金融信息的数据库字段,必须使用SM4加密。这是合规要求,没什么可商量的。当时我们改造了Oracle数据库的透明数据加密(TDE),把底层加密算法从AES换成了SM4,配合硬件安全模块,性能损失控制在5%以内。

SM4 vs AES核心差异速览

维度 SM4 AES-128
密钥长度 128位 128/192/256位
分组长度 128位 128位
轮数 32轮 10轮
S盒 自定义S盒 GF(2^8)求逆S盒
硬件加速 国产CPU支持 AES-NI广泛支持
合规场景 国密标准(GM/T 0002) 国际标准(FIPS 197)

在MySQL里怎么用SM4?原生MySQL不支持,你可以通过自定义函数或插件来实现。我常用的做法是使用OpenSSL的SM4接口封装一个MySQL UDF。

-- 通过自定义插件实现SM4加密(伪代码)
-- 假设已安装 sm4_udf.so 插件
CREATE FUNCTION sm4_encrypt RETURNS STRING SONAME 'sm4_udf.so';
CREATE FUNCTION sm4_decrypt RETURNS STRING SONAME 'sm4_udf.so';

-- 加密审计日志
INSERT INTO audit_log (encrypted_msg)
VALUES (sm4_encrypt('审计内容', '128-bit-hex-key'));

-- 解密查询时注意性能
SELECT sm4_decrypt(encrypted_msg, '128-bit-hex-key')
FROM audit_log 
WHERE sm4_decrypt(encrypted_msg, '128-bit-hex-key') LIKE '%敏感%';

避坑指南: 我曾经踩过一个坑——SM4的ECB模式跟AES的ECB模式在分组处理上不一样。在跨系统对接时,双方必须确认工作模式、填充方式完全一致,否则解密出来就是乱码。

2.4 三种算法如何抉择?我的实践心得

说了这么多,到底怎么选?我个人的经验是这样的:

  • 数据加密(量大、高频) → 选AES-256-GCM。性能好,安全性高,有认证加密,无需额外做完整性校验。
  • 密钥传输、身份认证 → 选RSA-2048或RSA-4096。保持密钥短小精悍,只加密AES密钥。
  • 国密合规审查 → 选SM4。别挣扎,合规硬性要求没得选。
  • 混合加密(最推荐) → RSA加密AES/SM4密钥,AES/SM4加密业务数据。既兼顾性能,又解决了密钥分发问题。

你想想看,这三个算法各有定位,但不要硬套。比如你在一个纯内网、无合规要求的审计系统里,强行上SM4+RSA双重加密,除了增加维护成本和延迟,什么好处都没有。

好了,这节课就到这。记住一句话:加密算法本身不会成为性能瓶颈,选错算法+用错方式才是。