首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >[MYSQL] 加密的binlog应该怎么解析?

[MYSQL] 加密的binlog应该怎么解析?

原创
作者头像
大大刺猬
发布2025-09-19 18:42:51
发布2025-09-19 18:42:51
15900
代码可运行
举报
文章被收录于专栏:大大刺猬大大刺猬
运行总次数:0
代码可运行

导读

可能会有极少数的环境会对binlog进行加密, mysql在8.0.14的时候, mysql支持对binlog/relay-log进行加密, 只需要设置参数binlog_encryption为ON就行, 非常的简单.

问题来了, 应该怎么解析呢?

直接使用mysqlbinlog命令解析的话, 会报错ERROR: Reading encrypted log files directly is not supported.

我们查询官网发现, 还是使用的keyring插件方式, 诶, 之前我们不是有解析过kering加密的ibd文件的么, 那这原理应该差不多的.

实际上当时解析keyring file就是参考的人家解析keyring binlog的脚本... 地址:https://mysql.wisborg.dk/2019/01/28/automatic-decryption-of-mysql-binary-logs-using-python/

binlog加密结构

我们先来看看binlog加密之后的结构吧. mysql源码(sql/rpl_log_encryption.h)里面就有相关的文档:

希望国产数据库也能有这么全的文档

MAGIC HEADER: 如果是加密的,则为b'\xfdbin', 未加密的则为:b'\xfebin'

Replication logs encryption version : 固定值为为b'\x01'

Replication Encryption Key ID: 使用1字节的flag:b'\x01', 1字节的b':'表示长度为58, 然后跟上实际长度为58字节的keyid. 一共60字节

Encrypted File Password: 使用1字节的flag:b'\x02', 32字节的password(enc)

IV For Encrypting File Password : 使用1字节的falg:b'\x03', 16字节的iv

Padding: 剩下的就是填充字符(b'\x00'), 使其一共占用512字节.

剩下的当然就是加密了的数据了.

相关的定义如下:

代码语言:c++
复制
  static const char *KEY_TYPE;
  static const int KEY_LENGTH = 32;
  static const int HEADER_SIZE = 512;
  static const int IV_FIELD_SIZE = 16;
  static const int PASSWORD_FIELD_SIZE = 32;

当然, 我们可以使用如下python代码简单查看:

代码语言:python
代码运行次数:0
运行
复制
f = open('/data/mysql_3314/mysqllog/binlog/m3314.000087','rb')
data = f.read(512)
data[:4] # magic
data[4:5]
data[5:6] # flag
data[6:7] # 58
data[7:65]
data[65:66] # flag
data[66:98] # en-password
data[98:99] # flag
data[99:115] # iv

ibd里面的keyring加密信息也是115字节, 真TM的巧呢

binlog的解密过程

加密之后的binlog也不算复杂, 毕竟之前ibd的加密也和这类似, 都是记录key和iv之类的信息.

然后我们来看看是怎么个解密的.

  1. 解析keyring file文件,获取keyid对应的字典信息, 大概如下样子:{'MySQLReplicationKey_b68e2434-cd30-11ec-b536-000c2980c11e_2': {'key': b'\xfb\xa9\x12\xf9X\xbe\xdc\xea\x95\x94\x01\x98\xaa\xea\xd3\xbf2R\x97#\x84\x08\xe7\x07\x14!V\x15{\x18\xb2\xb4', 'key_type': 'AES'}, 'MySQLReplicationKey_b68e2434-cd30-11ec-b536-000c2980c11e': {'key': b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'key_type': 'AES'}, 'MySQLReplicationKey_b68e2434-cd30-11ec-b536-000c2980c11e_last_purged': {'key': b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'key_type': 'AES'}, 'INNODBKey-b68e2434-cd30-11ec-b536-000c2980c11e-1': {'key': b'\x8b\x87\xa2z\x18\x92\x11\xb9\xa9\xae\xa84\x87\x98\xb2\x11\xe7\x1e\x9dB7\xd6\x94?\x80\xb5\xeb\x0e\xb8\xcbr\xf9', 'key_type': 'AES'}}
  2. 获取binlog文件的keyid
  3. 根据上一步的keyid去keyring file中获取相关的key
  4. 获取binlog文件的encrypted_password
  5. 获取binlog文件的iv
  6. 根据key和iv使用cbc解析encrypted_password得到password
  7. 根据password生成key和iv
  8. 根据key和iv使用ctr解析实际的binlog数据

流程就是这么个流程. 我们画个图来表示吧(省略部分flag)

验证

解密过程涉及到的cbc算法,我们之前有讲过,能使用现成的代码; 但是ctr算法我们还没得现成的算法, 故直接使用Jesper Krogh的代码来演示(下载地址:https://mysql.wisborg.dk/wp-content/uploads/2019/01/binlog_decrypt.zip):

代码语言:shell
复制
python3 t20250919_debin.py --keyring_file_data keyring2 binlog/m3314.000087

我测试的binlog没有数据,只有header信息

总结

使用加密的binlog的情况是很少的, 但遇到了也不要慌, 可以使用本文提到的脚本; 或者 man mysqlbinlog中还有一种方法: 就是使用mysql自己去解析,然后把解析后的event发送给mysqlbinlog客户端.

参考:

https://dev.mysql.com/doc/refman/8.0/en/replication-binlog-encryption.html

https://dev.mysql.com/doc/refman/8.0/en/replication-binlog-encryption-key-rotation.html

https://dev.mysql.com/doc/refman/8.0/en/keyring.html

https://www.modb.pro/db/1839571466908610560

https://mysql.wisborg.dk/2019/01/28/automatic-decryption-of-mysql-binary-logs-using-python/

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导读
  • binlog加密结构
  • binlog的解密过程
  • 验证
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档