Cybertec PostgreSQL透明加密解析
目前PostgreSQL官方并未推出透明加密功能,但是cybertec開源了一個分支,支持透明加密。感興趣的同學可以參考:
https://www.cybertec-postgresql.com/en/products/postgresql-transparent-data-encryption/
它支持對數據和WAL進行透明加密。本文主要介紹WAL的透明加密功能及原理。
WAL透明加密架構
WAL加密主要由一個緩沖來完成,該緩沖未encrypt_buf_xlog,該緩沖大小是8個頁大小,在啟動時創建,由函數setup_encryption完成,其堆棧如下:
PostgresMain->setup_encryption::encrypt_buf_xlog = (char *) MemoryContextAlloc(TopMemoryContext, ENCRYPT_BUF_XLOG_SIZE);加密時將WAL數據加密到該緩沖中,然后刷寫到磁盤。恢復回放時從磁盤上讀取加密的WAL日志,然后進行in place解密,之后讀取其中wal record進行回放。
加密
在XLogWrite刷寫日志時進行加密:
首先會先計算有多少頁需要刷寫,然后將這些頁一頁一頁的進行加密,時間線+段文件號+日志偏移作為向量和密鑰encryption_key一起對頁進行加密,將WAL加密到加密緩沖encrypt_buf_xlog中,然后將加密緩沖中的WAL刷寫磁盤。
恢復時解密
重啟時,將日志讀取到緩沖中進行解密。由函數XLogPageRead完成。首先需要創建一個XLogReaderState即xlogreader,使用XLogPageRead函數讀取WAL日志。然后讀取checkpoint和WAL RECORD進行回放。讀取WAL RECORD的函數是ReadRecord,從下面代碼可以看出,其實真正讀取是由XLogPageRead函數來完成的,也就是將磁盤上加密的WAL日志讀取到xlogreader的readBuf中,該緩沖1個頁大小。
然后,對readBuf中的WAL記錄進行解密。可以看出是in place解密。
流復制場景
主上執行start replication命令開啟流復制,即函數StartReplication完成的功能:
WalSndLoop不斷循環,調用XLogSendPhysical函數從磁盤中將加密的WAL日志讀取到encrypt_buf_xlog中,然后進行in plcace解密。將解密后的明文拷貝到output_message.data[]中,用于流復制傳輸。備機接收后將該日志持久化到磁盤。
備機receiver進程接收日志并寫入磁盤,寫入函數為XLogWalRcvWrite,這里可以看到它并沒有加密。那么恢復時需要將磁盤上的日志加載到內存,這個流程認為磁盤上的WAL日志是加密的,恢復前需要先解密。但從代碼上看,這個流程就存在矛盾了!
另外,Start replication命令支持對復制流加密,如下結構體:
上述中,XLogRead函數中的decrypt來源如下,在start replication命令中指定解密。若沒有指定解密的話,傳輸的即為加密的日志流。此時,備機接收后寫入磁盤為加密的日志。那么,回放時加載加密的WAL,然后解密,最后回放,這樣流程是合理的。
也就是說,流復制場景下,WAL流為解密的情況下,有bug!使用時需注意。
總結
以上是生活随笔為你收集整理的Cybertec PostgreSQL透明加密解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 获取本机局域网IP地址
- 下一篇: 数据库设计-UML模型