MySQL latin1字符集mediumblob字段AES_DECRYPT返回NULL排查
根本原因定位
第三张表手动解密返回NULL、但Hibernate侧可正常读取,核心是三个配置不匹配问题,和字段类型、UNHEX操作无关:
- 加密块参数不匹配:MySQL 8.0.22之后版本默认AES块加密模式为
aes-256-cbc,会严格校验块填充合法性,填充不匹配直接返回NULL不抛错;MySQL 5.x默认是aes-128-ecb无严格校验。JDBC驱动连接时会自动给AES加解密函数匹配和驱动版本一致的模式、初始化向量参数,手动写SQL时未携带这些参数的情况下,前两张表数据长度短刚好碰对默认参数可正常解密,第三张是大体积序列化JSON,块长度校验不通过直接返回NULL。 - 字符集隐式转码损坏密文:第三张表mediumblob字段绑定了latin1字符集,如果手动连接数据库时客户端字符集设置为utf8/utf8mb4,MySQL会自动对存储的二进制密文做字符集转码,直接破坏原始密文字节。前两张表一个是存十六进制文本的VARCHAR、一个是绑定utf8字符集的blob,转码不会破坏原始字节,因此可正常解密。
- 密钥传参类型不匹配:手动执行SQL时传入空字符串
''作为密钥,但Hibernate配置中如果密钥是字节数组(byte[])类型,JDBC传参的字节序列和字符串类型的空字符串完全不一致,解密自然失败。小体积数据对密钥校验容错性高,大体积数据校验严格直接返回NULL。
正确解密SQL写法
按以下步骤操作即可拿到明文:
- 先执行
SHOW VARIABLES LIKE 'block_encryption_mode';确认当前数据库默认加密模式,和JDBC连接串中配置的connectionBlockEncryptionMode参数对齐,无特殊配置时Java MySQL驱动默认使用aes-128-ecb模式。 - 执行解密前先切换客户端字符集为binary,避免隐式转码破坏密文:
SET NAMES binary; - 替换SQL中对应的表名、字段名、实际加密密钥后执行即可:
SET NAMES binary; SELECT CONVERT( AES_DECRYPT( <third_table_encrypted_column>, '<your_actual_encrypt_key>', -- 如果是CBC模式需要补充对应初始化向量,ECB模式删除该行即可 -- '<your_iv_value>' ) USING utf8mb4) AS decrypted_json FROM <third_table_name>;
补充提示:90%以上空密钥解密返回NULL的场景,本质是手动写SQL时漏填了Hibernate配置中实际的加密密钥,生产环境几乎不会使用空字符串作为AES加密密钥。
内容的提问来源于stack exchange,提问作者n0ahz
相关产品推荐
相关产品推荐

