大家好,欢迎来到IT知识分享网。
概述
GreatDB(或mysql)服务端支持对表内数据进行加密存储,称之为表空间(table space)加密。使用方法和基本原理参考:
GreatDB源码分析之表空间加密
GreatDB源代码:GreatSQL: GreatSQL is a MySQL branch originated from GreatDB (gitee.com)https://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
未完待续。。。。。。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/128714.html