如何设置字段级别的加密特性_结合MySQL内置加密功能的特殊列设计模式

星枫姑娘_9641

星枫姑娘_9641

2026-04-02

783人浏览

原创

能,但必须用VARBINARY或BLOB存储密文,否则因字符集转换导致解密失败;密钥需UNHEX(SHA2())转二进制,IV须随机且单独存;WHERE中直接解密会导致全表扫描,应改用确定性哈希索引辅助查询。

MySQL 5.7+ 的 AES_ENCRYPT() 和 AES_DECRYPT() 能直接用于字段加密吗?

能,但必须配合 varbinary 或 blob 类型,不能用 varchar 存密文——否则解密时大概率报 invalid key or data length。mysql 的 aes 函数输出是二进制,如果存进字符类型,会经历隐式字符集转换(比如 utf8mb4 → latin1),字节被截断或乱码,后续 aes_decrypt() 就失效。

实操建议:

  • 加密列必须定义为 VARBINARY(255)(长度按明文预估 × 1.33 + 16 字节 IV 开销)
  • 密钥不要硬编码在 SQL 里,用 SHA2('your-secret-key', 256) 生成 32 字节密钥,避免短口令导致密钥不足长
  • IV(初始向量)必须随机且每次加密不同,推荐用 RANDOM_BYTES(16) 生成,并和密文一起存入同一行(比如额外加一列 iv VARBINARY(16))
  • 别在 WHERE 条件里直接对加密列做 AES_DECRYPT() 查询——全表扫描 + 每行解密,性能崩得很快

为什么不能把加密逻辑全丢给应用层?

因为 MySQL 的 AES_ENCRYPT() 默认用的是 AES-128-CBC,而多数语言 SDK(如 Python 的 cryptography、Java 的 Cipher.getInstance("AES/CBC/PKCS5Padding"))默认填充方式、IV 处理、密钥派生规则不一致。常见现象是:应用加密后,MySQL 解不出来;或者反过来,MySQL 加密的,应用解密时报 ValueError: Invalid padding bytes。

关键差异点:

  • MySQL 不支持 PKCS#5/PKCS#7 填充,它用的是零填充(zero-padding),且不校验——所以你得在应用层手动补零、去零
  • MySQL 的 AES_ENCRYPT(data, key) 实际等价于 AES_ENCRYPT(data, key, iv)(隐式 IV=0),但显式传 IV 时必须用 AES_ENCRYPT(data, key, iv) 形式,否则行为不一致
  • 密钥长度必须严格为 16/24/32 字节;SHA2('key', 256) 输出 64 字符 hex,需用 UNHEX() 转成二进制才能当密钥用

WHERE 查询加密字段时性能掉得厉害,怎么查才不慢?

没法“高效查密文”,这是确定性加密的天然限制。如果你真需要按加密字段检索(比如查身份证号),唯一靠谱的路是引入确定性加密 + 盐值哈希索引,而不是用 AES_ENCRYPT()。

具体做法:

  • 新增一列 id_card_hash CHAR(64) GENERATED ALWAYS AS (SHA2(CONCAT('salt123', id_card), 256)) STORED,加索引
  • 写入时:先算 SHA2(CONCAT('salt123', '11010119900307231X'), 256),再存进 id_card_hash;密文另存在 id_card_enc VARBINARY(255)
  • 查询时:WHERE id_card_hash = SHA2(CONCAT('salt123', ?), 256),走索引;再用 AES_DECRYPT() 取出原始值做最终校验
  • 注意盐值(salt)必须固定且保密,不能每行一个随机 salt,否则无法索引

MySQL 8.4 的 ENCRYPTION='Y' 表级加密和字段加密冲突吗?

完全不冲突,但容易误解:ENCRYPTION='Y' 是 InnoDB 表空间的透明数据加密(TDE),保护的是磁盘文件,对 SQL 层不可见;而字段级加密是你自己用函数处理的业务数据,属于应用逻辑层。两者是正交的:TDE 防止硬盘被盗后数据裸奔,字段加密防止 DBA 或 SQL 注入后看到明文。

不过有个坑得卡住:

  • TDE 开启后,mysqldump 备份出来的仍是加密后的 SQL(含 AES_ENCRYPT() 调用),恢复到没开 TDE 的实例也能跑,但字段密文本身没变——也就是说,TDE 不影响你字段加密的逻辑,但备份恢复链路上,密钥管理必须同步迁移,否则恢复后解不开
  • 别指望 ENCRYPTION='Y' 能替代字段加密:它防不了有权限的用户 SELECT *,也防不了应用直连数据库读明文

真正要命的是密钥轮换——MySQL 没提供密文重加密机制,换密钥=全表扫描 + 解密 + 重新加密 + 更新,期间字段不可读,这事得在应用层兜底,不是加个配置就能搞定的。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4263

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

891

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1109

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6181

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3023

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6160

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8301

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1130

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

992

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.7万人学习