CryptDB代碼分析1-lua與加密庫

之前的文章 ”CryptDB原理概述“ 介紹了CryptDB的基本原理,接下來從代碼的角度介紹其實(shí)現(xiàn)原理食铐。本文首先關(guān)注mysql-proxy的lua腳本與CryptDB加密庫的交互過程裙戏。

前期準(zhǔn)備

在進(jìn)行源碼閱讀和調(diào)試之前公浪,首先需要進(jìn)行CryptDB的安裝姆打。 之前已經(jīng)對CryptDB在ubuntu 16.04上的安裝做過介紹沧卢。也可以使用我在github上共享的項目:https://github.com/yiwenshao/Practical-Cryptdb,里面對原始的安裝腳本做了小改嫩实,在ubuntu16.04只要執(zhí)行INSTALL.sh 就可以完成全部的安裝工作刽辙。

安裝完成以后,首先執(zhí)行如下的命令:

mkdir shadow
mysql-proxy --defaults-file=./mysql-proxy.cnf --proxy-lua-script=wrapper.lua

啟動mysql-proxy[1]甲献,然后就可以通過MySQL的客戶端連接mysql-proxy來完成數(shù)據(jù)庫操作宰缤。 所有SQL語句首先經(jīng)過mysql-proxy的加密處理, 然后轉(zhuǎn)發(fā)給MySQL服務(wù)器晃洒。 對于MySQL服務(wù)器的返回結(jié)果慨灭, 也是先轉(zhuǎn)發(fā)給mysql-proxy, 經(jīng)過解密處理以后返回給客戶端球及。

mysql-proxy通過lua腳本調(diào)用CryptDB的加密庫來完成SQL語句的加密操作氧骤,而上面建立的shadow目錄則是為了保存一個embedded模式的MySQL數(shù)據(jù)庫, 里面存儲了密鑰以及加密洋蔥的結(jié)構(gòu)的等相關(guān)信息吃引。

所以筹陵,接下來,我們先從lua腳本的入口出發(fā)镊尺,看一個SQL語句在加密過程中會經(jīng)過哪些模塊朦佩。

mysql-proxy的與CryptDB的交互

mysql-proxy提供了如下幾個函數(shù), 在客戶端執(zhí)行SQL的不同階段庐氮, 會調(diào)用這幾個函數(shù)语稠, 這些函數(shù)實(shí)現(xiàn)在 wrapper.lua 中:

  • read_auth()
  • disconnect_client()
  • read_query(packet)
  • read_query_result(inj)

在上面的四個函數(shù)的實(shí)現(xiàn)中,調(diào)用了CryptDB的加密庫中的幾個函數(shù)弄砍,這些函數(shù)實(shí)現(xiàn)在 mysqlproxy/ConnectWrapper.cc 中仙畦,分別是:

  • connect
  • disconnect
  • rewrite
  • next

所以,所有的CryptDB操作音婶,都是以上面的8個函數(shù)為基礎(chǔ)的慨畸。對于CryptDB加密庫而言,里面的connect以及disconnect 只在客戶端建立連接和客戶端離開的時候被調(diào)用桃熄,所有的加解密功能都是通過rewritenext這兩個函數(shù)來完成先口,這兩個函數(shù)就是CryptDB所有功能的入口型奥。

回到mysql-proxy的lua腳本中的四個函數(shù)瞳收,可以分以下三個階段來介紹。

客戶端建立連接

在這個階段厢汹,lua腳本中的函數(shù)read_auth被調(diào)用螟深,其內(nèi)部調(diào)用CryptDB的函數(shù)connect. 在這個階段,需要為每個客戶端建立一個WrapperState結(jié)構(gòu)來保存相關(guān)的信息烫葬。不同的客戶端通過ip+port來標(biāo)識界弧,多個客戶端的信息則通過一個如下的map結(jié)構(gòu)來進(jìn)行保存:


std::map<std::string, WrapperState*> clients;

要使用加密庫凡蜻,還需要進(jìn)行適當(dāng)?shù)某跏蓟⑶叶鄠€client之間有共享狀態(tài)垢箕。所以划栓,如果當(dāng)前連接進(jìn)來的是第一個客戶端,則需要對這個共享狀態(tài)進(jìn)行初始化条获,其對應(yīng)的是一個變量:

SharedProxyState * shared_ps//多個client的共享狀態(tài)

客戶端離開

當(dāng)客戶端關(guān)閉的時候忠荞,lua腳本中的disconnect_client函數(shù)被調(diào)用。其內(nèi)部調(diào)用CryptDB的disconnect函數(shù)帅掘。這個階段會把map中保存的客戶端的信息刪除委煤。

客戶端的命令執(zhí)行流程

客戶端發(fā)送命令給mysql-proxy的時候,lua腳本中的read_query(packet)函數(shù)被調(diào)用修档,參數(shù)packet中包含了SQL命令碧绞。MySQL執(zhí)行結(jié)果返回的時候,lua腳本中的read_query_result(inj)函數(shù)被調(diào)用吱窝,參數(shù)inj包含了返回結(jié)果讥邻。

  • 首先來看read_query函數(shù)。

當(dāng)read_query 函數(shù)獲取到客戶端發(fā)送的明文SQL 命令的時候癣诱,會調(diào)用lua腳本中的read_query_real函數(shù)计维,其內(nèi)部首先調(diào)用CryptDB庫中的rewrite函數(shù),完成SQL語句的改寫撕予。改寫后的SQL語句保存在之前介紹過的 clients 結(jié)構(gòu)中鲫惶。然后調(diào)用lua腳本中的next _handler 函數(shù),其內(nèi)部調(diào)用CryptDB庫中的next函數(shù)实抡。在next函數(shù)中欠母,首先執(zhí)行函數(shù)獲得一個參數(shù)result_type,分為三種情況吆寨,根據(jù)不同的結(jié)果選擇不同的執(zhí)行流程赏淌,包含了SQL命令執(zhí)行的所有情況,分別如下:

//mysqlproxy/ConnectWrapper.cc

switch (result_type) {
    case AbstractQueryExecutor::ResultType::QUERY_COME_AGAIN: {
    //返回sql語句給lua腳本啄清,執(zhí)行結(jié)果再次進(jìn)入該函數(shù)處理
    }
    case AbstractQueryExecutor::ResultType::QUERY_USE_RESULTS:{
    //返回sql語句給lua腳本六水,執(zhí)行結(jié)果直接返回客戶端
    }
    case AbstractQueryExecutor::ResultType::RESULTS:{
    //返回解密結(jié)果給lua腳本,并由mysql-proxy返回給客戶端
    }
}

對于一般的SQL語句的執(zhí)行辣卒,分為兩種情況掷贾,第一種是直接進(jìn)入QUERY_USE_RESULTS分支,返回SQL語句給lua腳本荣茫,SQL執(zhí)行的結(jié)果直接返回給客戶端想帅。 第二種是進(jìn)入第一個分支QUERY_COME_AGAIN,返回SQL語句給lua腳本轉(zhuǎn)發(fā)到MySQL執(zhí)行啡莉,返回的結(jié)果再次進(jìn)入next函數(shù)港准,執(zhí)行并且進(jìn)入第三個分支旨剥,返回解密的結(jié)果給客戶端。

另外浅缸,對于有些語句轨帜,并不需要調(diào)用rewrite函數(shù)進(jìn)行加密,在lua腳本的階段直接過濾了衩椒,這些情況就更加簡單阵谚。

  • 然后來看read _query_results階段。

當(dāng)上面介紹的加密SQL語句發(fā)送給MySQL執(zhí)行烟具,并返回執(zhí)行結(jié)果給mysql-proxy的時候梢什,會調(diào)用lua腳本中的read _query_results(inj)函數(shù)。如果在read_query階段進(jìn)入了第二個分支朝聋,那么lua腳本會設(shè)置一個全局變量skip為true嗡午,read_query_results的處理就被跳過,直接返回結(jié)果給客戶端冀痕。如果在read_query階段進(jìn)入了第一個分支荔睹,則會在這里再次調(diào)用next_handler函數(shù),從而進(jìn)入next函數(shù)言蛇,再次執(zhí)行并進(jìn)入switch分支的判斷流程僻他。

兩個執(zhí)行的例子

一些解密的細(xì)節(jié)以及類的介紹將在后續(xù)的文章中給出。在這里腊尚,給出兩個SQL語句執(zhí)行的例子吨拗,用于說明執(zhí)行過程中l(wèi)ua腳本以及CryptDB庫中的幾個函數(shù)的調(diào)用過程,以及幾個主要執(zhí)行分支的含義婿斥。

  • show databases;

該命令的處理流程:
首先進(jìn)入read_query劝篷,內(nèi)部調(diào)用CryptDB的rewrite函數(shù)進(jìn)行加密,然后調(diào)用lua中的next_handler民宿,內(nèi)部調(diào)用CryptDB的next函數(shù)娇妓,根據(jù)上面介紹的,進(jìn)入switch的第二個分支活鹰,表示執(zhí)行命令的結(jié)果不需要處理哈恰,直接返回給客戶端。然后給lua腳本傳遞改寫以后的命令志群。

再次回到lua腳本的next_handler函數(shù)着绷,其處理了query results分支拆撼,將獲得的命令轉(zhuǎn)發(fā)給MySQL執(zhí)行奢人。執(zhí)行完成以后的結(jié)果返回給mysql-proxy的時候,會調(diào)用read_query_result函數(shù)。根據(jù)上面介紹的宾抓,由于在read_query階段進(jìn)入了第二個分支子漩,這里的處理會被跳過,也就是不做任何處理石洗,結(jié)果直接返回給客戶端幢泼。這樣,客戶端就得到了show databases的執(zhí)行結(jié)果讲衫。

  • select * from student;

我們假設(shè)已經(jīng)有了一張表缕棵,對其進(jìn)行select操作,其對應(yīng)的執(zhí)行流程如下涉兽。
首先進(jìn)入read_query招驴,內(nèi)部調(diào)用CryptDB的rewrite函數(shù)進(jìn)行SQL語句的加密,返回以后調(diào)用lua中的next_handler函數(shù)枷畏,內(nèi)部調(diào)用CryptDB的next函數(shù)别厘,根據(jù)上面介紹的,進(jìn)入第一個分支:QUERY_COME_AGAIN拥诡。返回加密以后的SQL命令給lua腳本触趴。

在lua腳本中,next_handler處理了again分支渴肉,發(fā)送加密命令給MySQL冗懦,獲得select返回的加密結(jié)果以后,lua腳本中的read_query_results被調(diào)用仇祭。由于在read_query階段進(jìn)入了第一個分支披蕉,這里會繼續(xù)調(diào)用next_handler函數(shù),并進(jìn)入到next函數(shù)乌奇,執(zhí)行獲得result_type嚣艇,然后這次進(jìn)入到RESULTS分支。在lua腳本中华弓,處理了results分支食零,將解密后的結(jié)果返回給客戶端,這樣就完成了整個流程寂屏。

總結(jié)

本文介紹了SQL加密執(zhí)行過程中贰谣,mysql-proxy使用的lua腳本與CryptDB的加密庫的交互過程,其中主要的幾個函數(shù)是lua腳本中的read_query迁霎,read_query_results吱抚,以及CryptDB庫中的rewrite和next。代碼位于wrapper.lua以及mysqlproxy/ConnectWrapper.cc中考廉。

參考文獻(xiàn)

原始鏈接:yiwenshao.github.io/2018/02/26/CryptDB代碼分析1-lua與加密庫/

文章作者:Yiwen Shao

許可協(xié)議: Attribution-NonCommercial 4.0

轉(zhuǎn)載請保留以上信息, 謝謝!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秘豹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子昌粤,更是在濱河造成了極大的恐慌既绕,老刑警劉巖啄刹,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異凄贩,居然都是意外死亡誓军,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門疲扎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昵时,“玉大人,你說我怎么就攤上這事椒丧∫忌” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵壶熏,是天一觀的道長盹廷。 經(jīng)常有香客問我,道長久橙,這世上最難降的妖魔是什么俄占? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮淆衷,結(jié)果婚禮上缸榄,老公的妹妹穿的比我還像新娘。我一直安慰自己祝拯,他們只是感情好甚带,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著佳头,像睡著了一般鹰贵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上康嘉,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天碉输,我揣著相機(jī)與錄音,去河邊找鬼亭珍。 笑死敷钾,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肄梨。 我是一名探鬼主播阻荒,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼众羡!你這毒婦竟也來了侨赡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎羊壹,沒想到半個月后蓖宦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舶掖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了尔店。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眨攘。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嚣州,靈堂內(nèi)的尸體忽然破棺而出鲫售,到底是詐尸還是另有隱情,我是刑警寧澤该肴,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布情竹,位于F島的核電站,受9級特大地震影響匀哄,放射性物質(zhì)發(fā)生泄漏秦效。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一涎嚼、第九天 我趴在偏房一處隱蔽的房頂上張望阱州。 院中可真熱鬧,春花似錦法梯、人聲如沸苔货。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夜惭。三九已至,卻和暖如春铛绰,著一層夾襖步出監(jiān)牢的瞬間诈茧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工捂掰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留若皱,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓尘颓,卻偏偏與公主長得像走触,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子疤苹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,783評論 0 38
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法互广,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法惫皱,異常的語法像樊,線程的語...
    子非魚_t_閱讀 31,622評論 18 399
  • Nginx API for Lua Introduction ngx.arg ngx.var.VARIABLE C...
    吃瓜的東閱讀 5,773評論 0 5
  • 好不容易臨摹完心藍(lán)丫頭這幅花卉,說實(shí)話自己也沒看明白這朵花到底怎么個樣子旅敷,反正依葫蘆畫瓢臨摹下來了生棍,自己覺得不難看...
    LindaC閱讀 317評論 0 0
  • 遙遠(yuǎn)的山 有自己的故事 曾經(jīng)的戀人 化成石頭變?yōu)橛篮?遠(yuǎn)古的樹 彌漫著神秘的顏色 是誰留下的 或許這就是傳說 遠(yuǎn)方...
    長道赫書閱讀 152評論 16 6