2025年GreatDB源码分析之表空间加密

GreatDB源码分析之表空间加密概述 GreatDB 或 mysql 服务端支持对表内数据进行加密存储 称之为表空间 table space 加密 使用方法和基本原理参考 MySQL 系列 表空间加密 mysql keyring file data CSDN 博客 https blog csdn

大家好,我是讯享网,很高兴认识大家。

概述

GreatDB(或mysql)服务端支持对表内数据进行加密存储,称之为表空间(table space)加密。使用方法和基本原理参考:

MySQL系列:表空间加密_mysql keyring_file_data-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/wngpenghao/article/details/

GreatDB源代码:GreatSQL: GreatSQL is a MySQL branch originated from GreatDB (gitee.com)icon-default.png?t=N7T8https://gitee.com/GreatSQL/GreatSQL

基本原理

(本节内容摘自上述参考资料,并经过了排版和校对)

从5.7.11开始,mysql开始支持物理表空间的加密,它使用两层加密架构。包括:主密钥(master key) 和 表空间密钥(tablespace key)。

主密钥用于加密表空间密钥,加密后的表空间密钥存储在表空间文件的header中。表空间密钥用于加密数据。当用户想访问加密的表时,innoDB会先用 主密钥 对之前存储在表空间header中被加密的表空间密钥进行解密,得到明文的表空间密钥,再用表空间密钥解密数据信息。

表空间密钥是不会改变的,而主密钥可以通过命令随时改变。

代码结构

表空间加密功能由innodb和keyring插件共同实现。innodb负责使用表空间密钥加/解密表内数据,keyring负责管理主密钥。

Encryption类

innodb中表空间加密功能主要由Encryption类控制,其声明和实现在如下2个文件中:

storage/innobase/include/os0enc.h storage/innobase/os/os0enc.cc
讯享网

表空间密钥的生成

讯享网void Encryption::set_or_generate(Type type, byte *key, byte *iv, Encryption_metadata &metadata) { ut_ad(type != Encryption::NONE); metadata.m_type = type; metadata.m_key_len = Encryption::KEY_LEN; if (key == nullptr && iv == nullptr) { Encryption::random_value(metadata.m_key); Encryption::random_value(metadata.m_iv); } else if (key != nullptr && iv != nullptr) { memcpy(metadata.m_key, key, Encryption::KEY_LEN); memcpy(metadata.m_iv, iv, Encryption::KEY_LEN); } else { ut_error; } }

表空间密钥先在Encryption::set_or_generate生成,存入一个Encryption_metadata结构,再通过Encryption::set_key设置。

加密

对表空间密钥进行加密:

/ Fill the encryption information. @param[in] encryption_metadata encryption metadata (key,iv) @param[in] encrypt_key encrypt with master key @param[out] encrypt_info encryption information @return true if success. */ static bool fill_encryption_info( const Encryption_metadata &encryption_metadata, bool encrypt_key, byte *encrypt_info) noexcept;

对表内数据进行加密:

讯享网 / Encrypt the redo log block. @param[in] type IORequest @param[in,out] src_ptr log block which need to encrypt @param[in,out] dst_ptr destination area @return true if success. */ bool encrypt_log_block(const IORequest &type, byte *src_ptr, byte *dst_ptr) noexcept; / Encrypt the redo log data contents. @param[in] type IORequest @param[in,out] src page data which need to encrypt @param[in] src_len size of the source in bytes @param[in,out] dst destination area @param[in,out] dst_len size of the destination in bytes @return buffer data, dst_len will have the length of the data */ byte *encrypt_log(const IORequest &type, byte *src, ulint src_len, byte *dst, ulint *dst_len) noexcept; / Encrypt the page data contents. Page type can't be FIL_PAGE_ENCRYPTED, FIL_PAGE_COMPRESSED_AND_ENCRYPTED, FIL_PAGE_ENCRYPTED_RTREE. @param[in] type IORequest @param[in,out] src page data which need to encrypt @param[in] src_len size of the source in bytes @param[in,out] dst destination area @param[in,out] dst_len size of the destination in bytes @return buffer data, dst_len will have the length of the data */ [[nodiscard]] byte *encrypt(const IORequest &type, byte *src, ulint src_len, byte *dst, ulint *dst_len) noexcept; 

解密

解密表空间密钥:

/ Decoding the encryption info from the given array of bytes, which are assumed not to be related to any particular tablespace. @param[out] encryption_metadata decoded encryption metadata @param[in] encryption_info encryption info to decode @param[in] decrypt_key decrypt key using master key @return true if success */ static bool decode_encryption_info(Encryption_metadata &encryption_metadata, const byte *encryption_info, bool decrypt_key) noexcept; / Decoding the encryption info from the given array of bytes, which are assumed to be related to a given tablespace (unless space_id == dict_sys_t::s_invalid_space_id). The given tablespace is noted down in s_tablespaces_to_reencrypt if the encryption info became successfully decrypted using the master key and the space_id is not dict_sys_t::s_invalid_space_id. For such tablespaces the encryption info is later re-encrypted using the rotated master key in innobase_dict_recover(). @param[in] space_id Tablespace id @param[in,out] e_key key, iv @param[in] encryption_info encryption info to decode @param[in] decrypt_key decrypt key using master key @return true if success */ static bool decode_encryption_info(space_id_t space_id, Encryption_key &e_key, const byte *encryption_info, bool decrypt_key) noexcept;

解密表内数据:

 / Decrypt the log block. @param[in] type IORequest @param[in,out] src data read from disk, decrypted data will be copied to this page @param[in,out] dst scratch area to use for decryption @return DB_SUCCESS or error code */ dberr_t decrypt_log_block(const IORequest &type, byte *src, byte *dst) noexcept; / Decrypt the log data contents. @param[in] type IORequest @param[in,out] src data read from disk, decrypted data will be copied to this page @param[in] src_len source data length @param[in,out] dst scratch area to use for decryption @return DB_SUCCESS or error code */ dberr_t decrypt_log(const IORequest &type, byte *src, ulint src_len, byte *dst) noexcept; / Decrypt the page data contents. Page type must be FIL_PAGE_ENCRYPTED, FIL_PAGE_COMPRESSED_AND_ENCRYPTED, FIL_PAGE_ENCRYPTED_RTREE, if not then the source contents are left unchanged and DB_SUCCESS is returned. @param[in] type IORequest @param[in,out] src data read from disk, decrypt data will be copied to this page @param[in] src_len source data length @param[in,out] dst scratch area to use for decrypt @param[in] dst_len size of the scratch area in bytes @return DB_SUCCESS or error code */ [[nodiscard]] dberr_t decrypt(const IORequest &type, byte *src, ulint src_len, byte *dst, ulint dst_len) noexcept; 

使用国密算法

GreatDB目前支持国密算法(SM4等),想要表空间加密使用国密算法,需要在cmake阶段加入“-DWITH_SSL_GM=ON”,代码无需改动。编译完成后,无法再通过配置文件或命令换回普通AES。

keyring

未完待续。。。。。。

小讯
上一篇 2025-02-06 16:14
下一篇 2025-03-26 22:48

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/117367.html