SQL Server數據庫加密


參考文獻:

細說SQL Server中的加密

Transparent Data Encryption (TDE)

Database Encryption Key (DEK) management

SQL Server中的加密簡介

  在SQL Server2000和以前的版本,是不支持加密的。所有的加密操作都需要在程序中完成。這導致一個問題,數據庫中加密的數據僅僅是對某一特定程序有意義,而另外的程序如果沒有對應的解密算法,則數據變得毫無意義。舉個例子來說,我以前寫過一個web應用程序(參考博客:自定義SqlMembershipProvider方法),想讓用戶信息中的密碼字段用密文保存,我是在程序中將用戶的明文密碼加密以后保存到數據庫中的。

  到了SQL Server2005,引入了列級加密。使得加密可以對特定列執行,這個過程涉及4對加密和解密的內置函數。

  SQL Server 2008時代,則引入的了透明數據加密(TDE),所謂的透明數據加密,就是加密在數據庫中進行,但從程序的角度來看就好像沒有加密一樣,和列級加密不同的是,TDE加密的級別是整個數據庫。使用TDE加密的數據庫文件或備份在另一個沒有證書的實例上是不能附加或恢復的。

對稱加密與非對稱加密

  通常來說,加密可以分為兩大類,對稱(Symmetric)加密和非對稱(Asymmetric)加密。

  對稱加密是那些加密和解密使用同一個密鑰的加密算法,就是加密密鑰=解密密鑰。對稱加密通常來說會比較羸弱,因為使用數據時不僅僅需要傳輸數據本身,還是要通過某種方式傳輸密鑰,這很有可能使得密鑰在傳輸的過程中被竊取。

  非對稱加密是那些加密和解密使用不同密鑰的加密算法,就是加密密鑰!=解密密鑰。用於加密的密鑰稱之為公鑰,用於解密的密鑰稱之為私鑰。因此安全性相比對稱加密來說會大大提高。當然有一長必有一短,非對稱加密的方式通常算法會相比對稱密鑰來說復雜許多,因此會帶來性能上的損失。

  因此,一種折中的辦法是使用對稱密鑰來加密數據,而使用非對稱密鑰來加密對稱密鑰。這樣既可以利用對稱密鑰的高性能,還可以利用非對稱密鑰的可靠性。

證書與密鑰的創建

每個數據庫有且只有一個數據庫主密鑰(master key),這是一個數據庫級別的密鑰。可以用於為創建數據庫級別的證書或非對稱密鑰提供加密。通過T-SQL語句創建,如代碼1所示。

View Code
--創建證書,對稱與非對稱密鑰需要master key
--創建master key
CREATE MASTER KEY ENCRYPTION BY PASSWORD ='P@ssw0rd';

--刪除master key
drop MASTER KEY ; 

如果要查看數據庫是否有master key,可以通過下面的T-SQL語句查詢

View Code
--在SSMS中沒有查看master key的地方,但是可以在sys.databases中查看到數據庫是否有master key
select name,is_master_key_encrypted_by_server from sys.databases

我的查詢結果如下圖所示:

從上圖中我們可以看到master和TESTDB4這兩個數據庫含有master key,而且數據庫沒有。所以說master並不是只在master數據庫下面的,如果我們要在TESTDB4中創建證書與密鑰,那么就必須為TESTDB4這個數據庫創建master key。

下面給出創建證書、對稱密鑰、非對稱密鑰的T-SQL代碼

View Code
use TESTDB3;

--創建證書
CREATE CERTIFICATE CertTest 
with SUBJECT = 'Test Certificate'
GO

--創建非對稱密鑰
CREATE ASYMMETRIC KEY TestAsymmetric
    WITH ALGORITHM = RSA_2048 
    ENCRYPTION BY PASSWORD = 'P@ssw0rd'; 
GO

--創建對稱密鑰
CREATE SYMMETRIC KEY TestSymmetric
    WITH ALGORITHM = AES_256
    ENCRYPTION BY PASSWORD = 'P@ssw0rd';
GO

創建完以后我們可以在SSMS中找到我們創建的證書與密鑰,如下圖所示:

上面創建的證書、對稱密鑰、非對稱密鑰都是由固定的對稱密鑰P@ssw0rd加密的。其實創建的證書、對稱密鑰、非對稱密鑰的時候,也可以使用證書、對稱密鑰、非對稱密鑰加密,T-SQL代碼如下:

View Code
--由證書加密對稱密鑰
CREATE SYMMETRIC KEY SymmetricByCert
    WITH ALGORITHM = AES_256
    ENCRYPTION BY CERTIFICATE CertTest;
GO

--由對稱密鑰加密對稱密鑰
OPEN SYMMETRIC KEY TestSymmetric
    DECRYPTION BY PASSWORD='P@ssw0rd'
--必須先open 了TestSymmetric以后才可以用TestSymmetric來加密
CREATE SYMMETRIC KEY SymmetricBySy
    WITH ALGORITHM = AES_256
    ENCRYPTION BY SYMMETRIC KEY TestSymmetric;
GO

--由非對稱密鑰加密對稱密鑰
CREATE SYMMETRIC KEY SymmetricByAsy
    WITH ALGORITHM = AES_256
    ENCRYPTION BY ASYMMETRIC KEY TestASymmetric;
GO

創建完以后我們在Symmetric Key中可以看到我們查詢的結果:

 列級加密

  在列級加密中我們將使用AdventureWorks2008R2這個樣例數據庫,在Sales.CreditCard這張表中我們可以看到CardNumber列是明文的,如下圖所示:

在實際生產環境中,如果用戶的信用卡號是明文的是非常不安全的, 我們在這項想將這個CardNumber使用列級加密。需要注意的是,進行加密或者解密的列必須是Varbinary類型。

首先我們創建不帶數據的CreditCard的表結構,並且CardNumber這個列是Varbinary類型,T-SQL代碼如下:

View Code
--創建不帶數據的表結構,有where 1<>1來控制
SELECT CreditCardID, 
CardType,
CardNumber_encrypt = CONVERT(varbinary(500), CardNumber), 
ExpMonth, 
ExpYear, 
ModifiedDate
INTO CreditCard_Encrypt 
FROM AdventureWorks2008R2.Sales.CreditCard
WHERE 1<>1

在創建表結構以后,我們將數據導入到這張表中去:

View Code
--打開之前創建的由證書加密的對稱密鑰
OPEN SYMMETRIC KEY SymmetricByCert DECRYPTION BY CERTIFICATE CertTest;

--利用這個密鑰加密CardNumber這個數據列,插入新建的表中,使用了EncryptByKey這個函數
insert CreditCard_encrypt (
CardType,
CardNumber_encrypt, 
ExpMonth, 
ExpYear, 
ModifiedDate
) 
select top 10
CardType,
CardNumber_encrypt = EncryptByKey(KEY_GUID('SymmetricByCert'), CardNumber),
ExpMonth,
ExpYear, 
ModifiedDate
from AdventureWorks2008R2.Sales.CreditCard

查詢CreditCard_encrypt這個表,我們可以發現CardNumber列是密文了,如下圖所示:

但是我們可以通過對稱密鑰來解密CardNumber這個列

View Code
--打開之前創建的由證書加密的對稱密鑰
OPEN SYMMETRIC KEY SymmetricByCert DECRYPTION BY CERTIFICATE CertTest;
--查看CardNumber_encrypt
select convert(nvarchar(25), DecryptByKey(CardNumber_encrypt)) from CreditCard_Encrypt;

使用這條語句查詢出來的結果就是CardNuber的明文了。 注意這里需要OPEN SYMMETRIC KEY,如果不打開這個對稱私鑰的話查詢結果是null。如果之前打開過這個私鑰,那么此處可以不用再次打開。

透明數據加密

  在SQL Server 2008中引入了透明數據加密(Transparent Data Encryption ,以下簡稱TDE),之所以叫透明數據加密,是因為這種加密在使用數據庫的程序或用戶看來,就好像沒有加密一樣。TDE加密是數據庫級別的。數據的加密和解密是以頁為單位,由數據引擎執行的。在寫入時進行加密,在讀出時進行解密。客戶端程序完全不用做任何操作。(Encryption of the database file is performed at the page level. The pages in an encrypted database are encrypted before they are written to disk and decrypted when read into memory. TDE does not increase the size of the encrypted database.

  TDE的主要作用是防止數據庫備份或數據文件被偷了以后,偷數據庫備份或文件的人在沒有數據加密密鑰的情況下是無法恢復或附加數據庫的。我將一個encrypted database拷貝到另外的一台服務器上,視圖attach這個database,但是報錯如下:

上述錯誤表明這台服務器沒有相應的證書。這從另一個角度也給我們做了提醒,如果是一個encrypted database的話, 我不單要備份數據庫,還要對證書做備份,如果我們自身證書丟失的話,也會開不開數據庫。

  TDE使用數據加密密鑰(DEK)進行加密。DEK是存在Master數據庫中由服務主密鑰保護,由的保護層級如下圖所示。

使用TDE的四個步驟為:

  1. 創建一個master key(Create a master key)

    • USE master;
      GO
      
      --在master數據庫中創建一個master key
      CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'P@ssw0rd';
      go
  2. 創建或者獲取一個由master key保護的證書(Create or obtain a certificate protected by the master key)

    1. --使用masterkey創建證書MyServerCert
      CREATE CERTIFICATE MyServerCert WITH SUBJECT = 'My DEK Certificate';
      go
  3. 使用證書創建一個database密鑰(Create a database encryption key and protect it by the certificate)

    1. USE TESTDB2;
      GO
      
      --創建數據庫加密key,使用MyServerCert這個證書加密
      CREATE DATABASE ENCRYPTION KEY
      WITH ALGORITHM = AES_128
      ENCRYPTION BY SERVER CERTIFICATE MyServerCert;
      GO

      但是在創建完DATABASE ENCRYPTION KEY(DEK)以后,會報如下警告:

      Warning: The certificate used for encrypting the database encryption key has not been backed up. You should immediately back up the certificate and the private key associated with the certificate.If the certificate ever becomes unavailable or if you must restore or attach the database on another server,you must have backups of both the certificate and the private key or you will not be able to open the database.

      這是因為我們使用了證書來創建DEK,並且加密數據庫,因此我們建議為證書做一個備份,否則如果證書被破壞以后,我們自身都無法打開數據庫。證書備份的方法可以參考:backup certificate,我的T-SQL所示:

      BACKUP CERTIFICATE MyServerCert TO FILE = 'd:\storedcerts\MyServerCert'; --cert的保存地址 

      這里需要注意的是我們的MyServerCert沒有由private key加密,而只是有master key加密。如果使用了private key的話還要為private key進行備份。我們如果對MyServerCert進行備份private key操作會報錯如下:

      No decryption password should be provided because the private key of this certificate is encrypted by a master key.

  4. 將數據庫設置為TDE(Set the database to use encryption)

       最后我們需要做的就是講數據庫設置為加密,T-SQL語句如下所示:

ALTER DATABASE TESTDB2 SET ENCRYPTION ON;

       此時我們也可以右鍵TESTDB2->tasks->manage database encryption中查看加密設置,如下圖所示:

 我們也可以通過T-SQL語句來查看有哪些數據庫進行了TDE加密,T-SQL語句如下:

View Code
/* The value 3 represents an encrypted state 
   on the database and transaction logs. */
SELECT DBName=DB_NAME(database_id),encryption_state 
FROM sys.dm_database_encryption_keys
WHERE encryption_state = 3;
GO

查詢結果顯示tempdb也被透明加密了,原因我們可以在msdn上找到,我把原文摘出來:

Transparent Data Encryption and the tempdb System Database

The tempdb system database will be encrypted if any other database on the instance of SQL Server is encrypted by using TDE. This might have a performance effect for unencrypted databases on the same instance of SQL Server. For more information about the tempdb system database, see tempdb Database.

master key和certificate的備份與還原

View Code
--備份master key
BACKUP MASTER KEY TO FILE = 'd:\storedkeys\masterkey' ENCRYPTION BY PASSWORD = 'P@ssw0rd'
go

--備份證書
BACKUP CERTIFICATE MyServerCert TO FILE = 'd:\storedcerts\MyServerCert'; --cert的保存地址
go

--還原master key
use master
RESTORE MASTER KEY 
    FROM FILE = 'd:\storedkeys\masterkey' 
    DECRYPTION BY PASSWORD = 'P@ssw0rd' 
    ENCRYPTION BY PASSWORD = 'P@ssw0rd';
GO
--因為我這里還留有原來的證書,所以會提示如下信息:The old and new master keys are identical. No data re-encryption is required.

--還原證書
CREATE CERTIFICATE MyServerCert2
    FROM FILE = 'd:\storedcerts\MyServerCert' 
GO 
--因為證書已經存在,所以提示如下信息:--A certificate with name 'MyServerCert2' already exists or this certificate already has been added to the database.
--需要注意的是證書並不是按照證書名來區分的。我原來的證書名叫做MyServerCert,此處創建的證書名為MyServerCert2,但是是來自MyServerCert的一個備份,還是報錯。

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM