於Azure SQL Database使用Always Encrypted

  • 871
  • 0
  • 2016-02-04

把企業重要或機密性的資料放在雲端平台,擔心被平台的管理者偷看?或想避免傳輸過程中被攔截而導致資料外洩嗎?試試看Always Encrypted,在某些情境中可以幫您解除上述顧慮。

本文將介紹如何於Azure SQL Database上使用Always Encrypted來保護資料避免被特權使用者給偷看或遭駭客中途攔截。

截至本文撰寫為止,Azure SQL Database所支援的Always Encrypted功能尚在預覽階段。

準備工作

開始之前必須具備下列環境:

  • Azure SQL Database V12
    • 要在Azure SQL Database上使用Always Encrypted功能,必須先確定所使用的版本為目前最新版的V12,不論該資料庫所使用的服務層(基本、標準及高階)為何都支援這項功能。
  • .NET Framework 4.6
    • 因為只有這個版本的ADO.NET才支援Always Encrypted,所以必須在應用程式端安裝.NET Framework 4.6。
  • SQL Server Management Studio 2015 十月份預覽版13.0.700.242以上
    • 只有這個版本的SSMS才支援設定Always Encrypted所需的相關組態。

假設您知道如何透過Microsoft Azure管理入口網站或PowerShell建立Azure SQL Database V12的伺服器及資料庫,開啟SSMS連接到SQL Database V12的SQL Database伺服器,接著依照下列步驟完成設定。

建立Column Master Key

Column Master Key(CMK)主要是用來保護用來加密資料的Column Encryption Key(CEK),屬於資料庫層級的安全性物件,因此需在物件總管展開使用Always Encrypted的資料庫,點選Security > Always Encrypted Keys > Column Master Keys後按滑鼠右鍵,選擇New Column Master Key。

在New Cloumn Master Key視窗輸入Column Master Key的名稱並選擇金鑰存放位置,您可以視需求來選擇要將金鑰存放在本機的Windows Certificate Store或是Azure Key Vault(金要保存庫)服務,本文以Windows Certificate Store為範例,接著按下方的Genterate Certificate來產生加密所需要的憑證,建立成功後即可以在下圖4的地方看到憑證已經順利被建立於目前使用者的憑證儲存區。

按下OK建立Column Master Key就可以看到如下圖的結果。

建立Column Encryption Keys

Column Encryption Key(CEK)是將來要放在開發環境或應用程式所在之伺服器的金鑰,用來加密機敏資料所使用,和CMK一樣是屬於資料庫層級的安全性物件,因此在已經存在CMK的資料庫中點選Security > Always Encrypted Keys > Column Encryption Keys後按滑鼠右鍵,選擇New Column Encryption Key。

於New Column Encryption Key視窗輸入Column Encryption Key的名稱及選擇前一步驟所建立的Column master Key,按下OK來建立Column Encryption Key。

完成後可以看到如下圖的結果。

建立加密資料表

以下列T-SQL建立薪資資料表(Salary),示範將員工編號(StaffNo)及薪資金額(Amount)資料行加密,使用Always Encrypted時需考量該資料行將來可能被拿來做什麼樣的處理來決定使用的加密方式,其中員工編號示範使用的加密方式為Deterministic,相同的明文會被加密成相同的密文,因此若不想被猜出或是找出明文(例如地區北、中、南),應避免使用Deterministic,並且使用Deterministic強制該資料行的定序必須採*BIN2;薪資金額的部分則是採用另一種加密方式Randomized,使用這種方式加密資料行時,加密後的密文不容易被猜測其規則,相較於Deterministic更為安全,但無法將該資料行用來做等於、群組、索引和JOIN等運算。

CREATE TABLE dbo.Salary(
	StaffNo char(8) COLLATE Chinese_Taiwan_Stroke_BIN2 
	ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, 
					ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256',
					COLUMN_ENCRYPTION_KEY = MyCEK) NOT NULL,
	SalaryMonth char(5) NOT NULL,
	PayNo tinyint NOT NULL,
	PayTypeNo tinyint NOT NULL,
	Amount int 
	ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED,
					ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', 
					COLUMN_ENCRYPTION_KEY = MyCEK) NOT NULL,
	UpdateDate smalldatetime NOT NULL,
	Memo nvarchar(512) NULL,
	CONSTRAINT [PK_Salary] PRIMARY KEY CLUSTERED (
	StaffNo ASC,
	SalaryMonth ASC
)
)

除了使用CREATE TABLE敘述在建立資料表的同時,就設定需要加密的資料行,您也可以透過Always Encrypted精靈的圖形化介面來完成資料行加密的設定,依照想要設定資料行加密的物件,在想要資料庫、資料表或是資料行上按滑鼠右鍵選擇【Encrypt Column】。

選擇要加密的資料行及加密方式及加密金鑰,就可以輕鬆完成所需的設定(下圖示範在資料表上選擇Encrypt Column)。

執行結果如下圖,資料行加密操作順利完成,若發生失敗可以點選下方的Always Encrypted Wizard Log Report來查看錯誤發生的原因。

建立使用Always Encrypted的應用程式

本文示範以Visual Studio 2015建立使用.NET Framework 4.6(含以上)的ASP.NET MVC應用程式。

建立實體資料模型時於連接屬性視窗點選進階,設定Column Encryption Setting為Enabled。

接著建立控制器及檢視並撰寫存取薪資資料表的程式碼(本文重點在於介紹Always Encrypted功能,有關ASP.NET MVC程式開發就不在此贅述),例如下圖新增薪資資料的頁面。

儲存成功後使用SSMS預設只會看到加密後的結果,即使是DBA或系統管理員也沒辦法看到實際的資料內容,而應用程式則因為具有Column Master Key而且啟用Column Encryption Setting,才得以顯示解密後的明文。

使用SSMS查詢啟用Always Encrypted功能的資料表

若您想要在非當初建立Column Master Key的電腦上使用SQL Server Management Studio(SSMS)查詢已經利用Always Encrypted加密的資料表,必須先將前面步驟用來建立Cloumn Master Key的憑證匯出來,然後安裝到想要解密資料的電腦之中。

接著開啟SSMS連接至Azure SQL Database,在Connect to Database Engine視窗點選Additional Connection Parameters,輸入【Column Encryption Setting = Enabled】後按Connect。

下圖上半部是一般透過SSMS查詢加密資料表的結果,可以看出員工編號和薪資金額欄位都是密文,下半部則是在匯入憑證後並使用Column Encryption Setting = Enabled參數所得到的結果。

將現有資料表啟用Always Encrypted

假設要將Northwind資料庫中已經存有資料的Customers資料表啟用Always Encrypted功能,必須先將要使用Deterministic加密方式的資料行定序改成BIN2,如下列T-SQL:

ALTER TABLE dbo.Customers
ALTER COLUMN ContactName nvarchar(30) COLLATE Chinese_Taiwan_Stroke_BIN2

GO

ALTER TABLE dbo.Customers
ALTER COLUMN Address nvarchar(60) COLLATE Chinese_Taiwan_Stroke_BIN2

GO

在Customers資料表上按滑鼠右鍵選擇Encrypt Columns,於Always Encrypted視窗的Column Selection選擇加密資料行及方式如下圖,並依照精靈的提示完成設定。

加密設定成功後查詢該資料表就可以看到ContactName、Address和Phone資料行的內容已經成功被加密。

除了上述方式外,也可以透依照下列步驟來將未加密的資料表移轉成啟用Always Encrypted,這次示範的是將Employees資料表以移轉的方式來將員工的生日(BirthDate)和地址(Address)資料行做加密,首先以下列T-SQL來建立儲存加密內容的資料表:

CREATE TABLE [dbo].[EmployeesEncrypted](
	[EmployeeID] [int] IDENTITY(1,1) NOT NULL,
	[LastName] [nvarchar](20) NOT NULL,
	[FirstName] [nvarchar](10) NOT NULL,
	[Title] [nvarchar](30) NULL,
	[TitleOfCourtesy] [nvarchar](25) NULL,
	[BirthDate] [datetime] ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, 
					ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256',
					COLUMN_ENCRYPTION_KEY = MyCEK) NULL,
	[HireDate] [datetime] NULL,
	[Address] [nvarchar](60) COLLATE Chinese_Taiwan_Stroke_BIN2 
	ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, 
					ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256',
					COLUMN_ENCRYPTION_KEY = MyCEK) NULL,
	[City] [nvarchar](15) NULL,
	[Region] [nvarchar](15) NULL,
	[PostalCode] [nvarchar](10) NULL,
	[Country] [nvarchar](15) NULL,
	[HomePhone] [nvarchar](24) NULL,
	[Extension] [nvarchar](4) NULL,
	[Photo] [image] NULL,
	[Notes] [ntext] NULL,
	[ReportsTo] [int] NULL,
	[PhotoPath] [nvarchar](255) NULL,
 CONSTRAINT [PK_EmployeesEncrypted] PRIMARY KEY CLUSTERED 
(
	[EmployeeID] ASC
)
)

執行【C:\Program Files (x86)\Microsoft SQL Server\130\DTS\Binn】路徑下的DTSWizard.exe來啟動SQL Server 匯入和匯出精靈,在選擇資料來源的步驟使用【SQL Server Native Client 11.0】資料來源,輸入伺服器名稱及相關登入資訊。

在選擇目的地的步驟使用【.Net Framework Data Provider for SqlServer】資料來源,並設定【Column Encryption Setting】屬性為Enabled,並輸入連線字串所需資訊。

在選擇來源資料表或檢視的步驟,選擇Employees作為來源,目的資料表則選擇EmployeesEncrypted。

最後依照SQL Server 匯入和匯出精靈的引導就可以開始移轉資料。

利用SSMS查看資料移轉的結果,可以看出生日和地址資料行確實已經被加密,若不需要保留加密前的資料表,再將Employees資料表刪除即可。

將以啟用Always Encrypted的資料表還原

若要將已經使用Always Encrypted加密的資料表還原成明文,做法其實和前一節差不多,只是步驟相反罷了,先以下列T-SQL建立儲存解密後結果的資料表:

CREATE TABLE [dbo].[EmployeesDecrypted](
	[EmployeeID] [int] IDENTITY(1,1) NOT NULL,
	[LastName] [nvarchar](20) NOT NULL,
	[FirstName] [nvarchar](10) NOT NULL,
	[Title] [nvarchar](30) NULL,
	[TitleOfCourtesy] [nvarchar](25) NULL,
	[BirthDate] [datetime] NULL,
	[HireDate] [datetime] NULL,
	[Address] [nvarchar](60) NULL,
	[City] [nvarchar](15) NULL,
	[Region] [nvarchar](15) NULL,
	[PostalCode] [nvarchar](10) NULL,
	[Country] [nvarchar](15) NULL,
	[HomePhone] [nvarchar](24) NULL,
	[Extension] [nvarchar](4) NULL,
	[Photo] [image] NULL,
	[Notes] [ntext] NULL,
	[ReportsTo] [int] NULL,
	[PhotoPath] [nvarchar](255) NULL,
 CONSTRAINT [PK_EmployeesDecrypted] PRIMARY KEY CLUSTERED 
(
	[EmployeeID] ASC
)
)

在選擇資料來源的步驟使用【.Net Framework Data Provider for SqlServer】資料來源,並設定【Column Encryption Setting】屬性為Enabled,並輸入連線字串所需資訊。

在選擇目的地的步驟使用SQL Server Native Client 11.0及輸入相關連接資料庫所需之資訊。

在選擇來源資料表或檢視的步驟,選擇EmployeesEncrypted作為來源,目的資料表則選擇EmployeesDecrypted。最後依照SQL Server 匯入和匯出精靈的引導就可以開始移轉資料。

移轉成功後想必EmployeesDecrypted資料表中的生日和地址資料行存放的就是明文。

Column Master Key Rotate

若您需要更換已經用來加密資料行的金鑰,您必須先建立新的Column Master Key,下圖示範以存放在本機電腦的自我簽署憑證來建立新的Column Master Key。

接著在原有的Column Master Key上按滑鼠右鍵選擇Rotate。

於Column Master Key Rotation視窗的Target欄位選擇新的Column Master Key,接著按OK。

確定加密的資料行正確被加密並且可以使用Column Encryption Setting = Enabled參數來查看解密後的內容後,就可以將舊的Column Master Key進行Cleanup動作,以避免用戶端不知道要使用哪一把金鑰來解密而導致查詢效能受影響。

在Column Master Key Cleanup視窗直接點選OK即可。

最後則是刪除已經被Cleanup的Column Master Key。

參考資料