使用SQL Server 2016的Always Encrypt功能防止系統管理員讀取私密性資料
黃家瑞 Jerry Huang
- 精誠資訊/恆逸教育訓練中心-資深講師
- 技術分類:程式設計
在企業中,資訊的讀取是分層級有不同的權限,例如:人事部門主管才能檢視公司員工的人事薪資資料,其他像是產品的成本、客戶資料、廠商資料依據企業屬性不同,常會限制可以讀取或是修改的人員,必須是一定職位的人員才有權限。以往在沒有資訊系統的時代,這些資訊以各種方式進行保護,避免不在該職位的人員窺探這些資訊,然而在導入資訊系統後,這些資料在資料庫管理員(例如:SQL Server 具有sysadmin角色的login user)眼前卻都可以一覽無遺。
資料庫中可以設計密碼機制,讓密碼以密文方式存入資料庫中,使用者驗證時以相同的加密機制,驗證使用者身分的正確性。像是MD5加密的機制便是利用此一理論基礎。但是薪資、員工資料、產品價格、公司資料,這些需要運算或是解密的資訊,如以密文存入資料庫,運算時必須進行解密的運算,除了讓計算效率變得很不理想,也增加使用者的不便性(例如:計算公司薪資時,必須請人事主管輸入加密的密碼,運算時逐筆將薪資的數字解密再做加總)所有資料庫中的彙總函數,合計(SUM)、平均(AVG)、筆數(COUNT)、最大值(MAX)、最小值(MIN)等函數都必須以程式逐筆計算。不僅增加程式設計師的工作負荷,寫出來的系統效能也很差。
SQL Server 2016加入了一項新的功能Always Encrypt,用以解決這個問題:
首先準備兩台機器,這裡我以兩部在Hyper-V上的虛擬機器作為範例說明:
- 機器一、DB-Server
- 機器二、AP-Server
- DB-Server
- 防火牆 TCP:1433 Port開啟
- SSCM中TCP/IP通訊協定啟用中
- SSCM SQL Server Browser啟用中
- SQL Server 2016: (為方便講解,使用SQL Server 以及 Windows混合式驗證)
- SSMS 18.0(SSMS 16.5之前的版本僅支援查詢加密的資料,但不支援寫入加密欄位)
- AP-Server
- Visual Studio 2017
步驟一、在DB-Server上建立資料庫
利用以下T-SQL語法建立資料庫db01,新增資料表:
確認資料可以正常讀取。
步驟二、利用SSMS在使用Always Encrypt
展開Object Explorer => Databases => db01上右鍵 => Encrypt Columns…
直接按Next
Encryption Type(加密方式)的設定上,分別在
- employee_name => Randomized
- address => Deterministic
- phone => Randomized
- salary => Deterministic
(Randomized加密方式,資料即使是相同的內容也會產撐出不同的加密文字。Deterministic加密方式,會對相相同料得到相同加密文字。因此,Deterministic的加密欄位還是可以使用DISTINCT、GROUP BY等語法統計有多少不相同資料,Randomized欄位則不支援這些SQL語法。)
在驚嘆號的圖示下可以看一下文字欄位被改為SQL_Latin1_General_CP1_CI_AS定序。
SSMS會自動在伺服器上建立憑證,以Master Key Configuration建立成Windows的憑證,接著按一下Next。
按一下Next執行
SSMS彙總出要執行的動作,按一下Finish開始執行。
跑一段時間之後,出現綠色完成的圖示代表完成設定。
步驟三、用SSMS測試一下
在查詢介面中再一次查詢資料。
此時所看到的文字,就已被加密了。
在SSMS的文字編輯器上按右鍵 => Change Connection => Connection
=> Change Connection
切換到Options >>
在Additional Connection Parameters的頁籤上加入「Column Encryption Setting = Enabled」,按下 Connect 重新連線。
在執行一次查詢的語法
這時又可以看到完整的資訊
可是如果是新增的語法,以下面語法做測試
會看到以下的錯誤訊息
文字編輯器上按右鍵=>Query Options…
點選 Execution => Advanced 勾選 Enable Parameterization for Always Encrypted
使用以下語法執行
此時再一次查詢
資料已經寫入
步驟四、從DB-Server匯出憑證
在DB-Server虛擬機器上,按下Windows鍵 + Q(快速搜尋),鍵入 cmd 在Command Prompt上按右鍵,執行Run asadministrator。
鍵入 certmgr 按 Enter
點選Certificates – Current User => Personal,在 Always Encrypted Auto Certificates上按右鍵=> All Tasks => Export… 匯出憑證
跳出歡迎畫面,直接按 Next 下一步
選擇 Yes, export the private key 按 Next 跳下一頁
勾選Export all extended properties,按一下 Next
勾選Password,鍵入密碼,按一下 Next
選取檔案位置,將憑證匯出到檔案
按 Finish 完成
將憑證從 DB-Server上刪除
步驟五、在AP-Server上匯入憑證
在AP-Server上,按下Windows鍵 + Q(快速搜尋),鍵入 cmd 在Command Prompt上按右鍵,執行Run as administrator。
鍵入 certmgr 按 Enter
點選Certificates – Current User => Personal 上按右鍵=> All Tasks => Import…
直接按 Next
匯入由DB-Server憑證匯出的檔案
輸入密碼,按 Next
匯入儲存所在的位置 Personal(預設),按 Next
按下 Finish 完成匯入
步驟六、C#程式讀寫資料
撰寫一個簡易的Windows介面程式,畫面設計:
- Button: btnLoad, btnInsert
- DataGridView: drvData
- TextBox: txtID, txtName, txtAddress, txtPhone, txtSalary
程式碼如下:
注意到連線字串
加入 Column Encryption Setting=Enabled,寫入的SQL語法中
參數的資料型別必須使用和資料表定義中的型別一致。
SQL Server 2016中新增的Always Encrypt讓資料僅能在應用程式端透過權限設計機制讓使用者讀取,避免資料庫管理員可以從資料庫伺服器中直接以T-SQL語法窺探私密性資料。