都是基本示例,更多參考官方文檔:
1. Transact-SQL 函數
2. 資料庫密鑰
3. 證書
4. 非對稱密鑰
5. 對稱密鑰
[sql] view plain copy
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcu82Yp9VRE90Qvw1c0V2czF2LcRXZu5ibkN3YuUGZvN2Lc9CX6MHc0RHaiojIsJye.png)
- -- drop table EnryptTest
- create table EnryptTest
- (
- id int not null primary key,
- EnryptData nvarchar(20),
- )
- insert into EnryptTest
- values(1,N'888888'),(2,N'888888'),(3,N'123456'),(4,N'A');
- select * from EnryptTest;
【Transact-SQL 函數加密】
[sql] view plain copy
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcu82Yp9VRE90Qvw1c0V2czF2LcRXZu5ibkN3YuUGZvN2Lc9CX6MHc0RHaiojIsJye.png)
- -- 使用 TRIPLE DES 算法(128 密鑰位長度)的通行短語加密資料。
- -- 添加測試列
- alter table EnryptTest add PassPhrase varbinary(256)
- alter table EnryptTest add PassPhrase2 varbinary(256)--用于驗證器驗證
- -- 加密(EncryptByPassPhrase)
- -- https://technet.microsoft.com/zh-cn/library/ms190357%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396
- update EnryptTest set PassPhrase = EncryptByPassPhrase('Hello.kk',EnryptData)
- go
- update EnryptTest
- set PassPhrase2 = EncryptByPassPhrase
- (
- 'Hello.kk' --用于生成對稱密鑰的通行短語
- , EnryptData --要加密的明文
- , 1 --訓示是否将驗證器與明文一起加密。如果将添加驗證器,則為 1
- , convert(varbinary,id) --用于派生驗證器的資料(如 主鍵)
- )
- go
- -- 解密(DecryptByPassPhrase)
- -- https://technet.microsoft.com/zh-cn/library/ms188910%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396
- select convert(nvarchar,DecryptByPassphrase('Hello.kk',PassPhrase)) from EnryptTest;
- go
- select convert(nvarchar,DecryptByPassphrase(
- 'Hello.kk' --生成解密密鑰的通行短語
- , PassPhrase2 --要解密的加密文本varbinary
- , 1 --添加驗證器
- , convert(varbinary,id)))--驗證器為主鍵
- from EnryptTest;
- go
- --附:未用驗證器的,資料并不安全
- --如:把所有id的密碼都改為與A一樣,其他密碼的解密與A一樣,别人就有可能登入其他賬号
- update EnryptTest set PassPhrase = (select PassPhrase from EnryptTest where id=4)
- go
- select id,EnryptData,convert(nvarchar,DecryptByPassphrase('Hello.kk',PassPhrase))
- from EnryptTest;
- -- 删除測試列
- alter table EnryptTest drop column PassPhrase
- alter table EnryptTest drop column PassPhrase2
- go
[sql] view plain copy
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcu82Yp9VRE90Qvw1c0V2czF2LcRXZu5ibkN3YuUGZvN2Lc9CX6MHc0RHaiojIsJye.png)
- DECLARE @ENPWD VARBINARY(MAX)
- DECLARE @DEPWD NVARCHAR(100)
- DECLARE @ENSTR NVARCHAR(100)
- SET @ENSTR = 'hello.KK' --加密密碼
- --加密
- SELECT @ENPWD = ENCRYPTBYPASSPHRASE( @ENSTR, N'13500000000')
- SELECT @ENPWD
- --解密
- SELECT @DEPWD =CAST( DECRYPTBYPASSPHRASE(@ENSTR,@ENPWD) AS NVARCHAR(MAX))
- SELECT @DEPWD
- go
【資料庫主密鑰】
[sql] view plain copy
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcu82Yp9VRE90Qvw1c0V2czF2LcRXZu5ibkN3YuUGZvN2Lc9CX6MHc0RHaiojIsJye.png)
- select * from sys.key_encryptions
- select * from sys.crypt_properties
- -- 建立資料庫主密鑰
- -- https://technet.microsoft.com/zh-cn/library/ms174382(v=sql.105).aspx
- create master key encryption by password = N'[email protected]' --必須符合Windows密碼政策要求
- go
- -- 打開目前資料庫的資料庫主密鑰
- -- https://technet.microsoft.com/zh-cn/library/ms186336(v=sql.105).aspx
- open master key decryption by password = N'[email protected]'
- go
- -- 更改資料庫主密鑰的屬性
- -- https://technet.microsoft.com/zh-cn/library/ms186937(v=sql.105).aspx
- alter master key regenerate with encryption by password = N'[email protected]'
- alter master key add encryption by password = N'[email protected]'
- alter master key drop encryption by password = N'[email protected]'
- alter master key add encryption by service master key
- alter master key drop encryption by service master key
- -- 導出資料庫主密鑰
- -- https://technet.microsoft.com/zh-cn/library/ms174387(v=sql.105).aspx
- backup master key
- to file = N'D:\XXDB_MasterKey'
- encryption by password = N'[email protected]'
- go
- -- 從備份檔案中導入資料庫主密鑰
- -- https://technet.microsoft.com/zh-cn/library/ms186336(v=sql.105).aspx
- restore master key
- from file = N'D:\XXDB_MasterKey'
- decryption by password = N'[email protected]'
- encryption by password = N'[email protected]' --New Password
- go
- -- 從目前資料庫中删除主密鑰
- -- https://technet.microsoft.com/zh-cn/library/ms180071(v=sql.105).aspx
- drop master key
- go
【證書】
[sql] view plain copy
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcu82Yp9VRE90Qvw1c0V2czF2LcRXZu5ibkN3YuUGZvN2Lc9CX6MHc0RHaiojIsJye.png)
- -- 證書和非對稱密鑰使用資料庫級的内部公鑰加密資料,并且使用資料庫級内部私鑰解密資料
- -- 當使用資料庫主密鑰對私鑰進行加密時,不需要 ENCRYPTION BY PASSWORD 選項。私鑰使用資料庫主密鑰進行加密
- --(有點難了解,最後給出例子)
- select * from sys.key_encryptions
- select * from sys.crypt_properties
- select * from sys.certificates
- select * from EnryptTest
- -- 添加測試列
- alter table EnryptTest add CertificateCol varbinary(max)
- go
- -- 建立證書
- -- https://technet.microsoft.com/zh-cn/library/ms187798%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396
- create certificate Mycertificate
- encryption by password = N'[email protected]' --加密密碼
- with subject = N'EnryptData certificate', --證書描述
- start_date = N'20150401', --證書生效日
- expiry_date = N'20160401'; --證書到期日
- go
- -- 使用證書的公鑰加密資料
- -- https://msdn.microsoft.com/zh-cn/library/ms188061(v=sql.105).aspx
- update EnryptTest
- set CertificateCol = EncryptByCert(CERT_ID('Mycertificate'),CONVERT(VARCHAR(MAX),EnryptData))
- go
- -- 用證書的私鑰解密資料
- -- https://msdn.microsoft.com/zh-cn/library/ms178601(v=sql.105).aspx
- select *,CONVERT(VARCHAR(MAX ),DECRYPTBYCERT(CERT_ID('Mycertificate'),CertificateCol,N'[email protected]'))
- from EnryptTest;
- go
- -- 修改私鑰密碼
- -- https://msdn.microsoft.com/zh-cn/library/ms189511(v=sql.105).aspx
- alter certificate mycertificate
- with private key (
- decryption by password = N'[email protected]',
- encryption by password = N'[email protected]')
- go
- -- 從證書中删除私鑰
- alter certificate mycertificate remove private key
- go
- -- 備份證書
- -- https://msdn.microsoft.com/zh-cn/library/ms178578(v=sql.105).aspx
- backup certificate mycertificate
- to file = N'D:\mycertificate.cer' --用于加密的證書備份路徑
- with private key (
- file = N'D:\mycertificate_saleskey.pvk' , --用于解密證書私鑰檔案路徑
- decryption by password = N'[email protected]' ,--對私鑰進行解密的密碼
- encryption by password = N'[email protected]' );--對私鑰進行加密的密碼
- go
- -- 建立/還原證書
- create certificate mycertificate
- from file = N'D:\mycertificate.cer'
- with private key (
- file = N'D:\mycertificate_saleskey.pvk',
- decryption by password = '[email protected]');
- go
- -- 删除對稱密鑰
- -- https://msdn.microsoft.com/zh-cn/library/ms182698(v=sql.105).aspx
- drop certificate Mycertificate;
- go
- -- 删除測試列
- alter table EnryptTest drop column CertificateCol;
- go
【非對稱密鑰】
[sql] view plain copy
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcu82Yp9VRE90Qvw1c0V2czF2LcRXZu5ibkN3YuUGZvN2Lc9CX6MHc0RHaiojIsJye.png)
- -- 預設情況下,私鑰受資料庫主密鑰保護
- select * from sys.key_encryptions
- select * from sys.crypt_properties
- select * from sys.certificates
- select * from sys.asymmetric_keys
- select * from sys.openkeys
- select * from EnryptTest
- -- 添加測試列
- alter table EnryptTest add AsymmetricCol varbinary(max)
- go
- -- 建立非對稱密鑰
- -- https://msdn.microsoft.com/zh-cn/library/ms174430(v=sql.105).aspx
- create asymmetric key MyAsymmetric
- with
- algorithm=rsa_512
- encryption by password='[email protected]';
- go
- -- 加密(EncryptByAsymKey)
- -- https://msdn.microsoft.com/ZH-CN/library/ms186950(v=sql.105).aspx
- update EnryptTest
- set AsymmetricCol = EncryptByAsymKey(asymkey_id ('MyAsymmetric'),convert(varchar(max ),EnryptData))
- go
- -- 解密(DecryptByAsymKey)
- -- https://msdn.microsoft.com/ZH-CN/library/ms189507(v=sql.105).aspx
- select *,convert(varchar(max),DecryptByAsymKey(asymkey_id('MyAsymmetric'),AsymmetricCol,N'[email protected]'))
- from EnryptTest
- go
- -- 更改非對稱密鑰屬性
- -- https://msdn.microsoft.com/zh-cn/library/ms187311(v=sql.105).aspx
- -- 更改私鑰密碼
- alter asymmetric key MyAsymmetric
- with private key (
- decryption by password = N'[email protected]',--原私鑰密碼
- encryption by password = N'[email protected]');--新私鑰密碼
- go
- -- 删除私鑰,隻保留公鑰
- -- 如果将非對稱密鑰映射到 EKM 裝置上的可擴充密鑰管理 (EKM) 密鑰并且未指定 REMOVE PROVIDER KEY 選項,
- -- 則會從資料庫中删除該密鑰,但不會從裝置上删除它。這時會發出一條警告。
- alter asymmetric key MyAsymmetric remove private key;
- go
- -- 删除非對稱密鑰
- -- https://msdn.microsoft.com/ZH-CN/library/ms188389(v=sql.105).aspx
- drop symmetric key MyAsymmetric ;
- go
- -- 删除測試列
- alter table EnryptTest drop column AsymmetricCol
- go
【對稱密鑰】
[sql] view plain copy
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcu82Yp9VRE90Qvw1c0V2czF2LcRXZu5ibkN3YuUGZvN2Lc9CX6MHc0RHaiojIsJye.png)
- -- 也稱為單密鑰加密,采用單鑰密碼系統的加密方法,同一個密鑰可以同時用作資訊的加密和解密.
- -- 非對稱密鑰消耗多些系統性能,一般使用對稱密鑰加密資料,使用非對稱密鑰保護對稱密鑰
- select * from sys.key_encryptions
- select * from sys.crypt_properties
- select * from sys.certificates
- select * from sys.asymmetric_keys
- select * from sys.openkeys
- select * from sys.symmetric_keys
- select * from EnryptTest
- -- 添加測試列
- alter table EnryptTest add SymmetricCol varbinary(max)
- go
- -- 建立對稱密鑰
- -- https://msdn.microsoft.com/zh-cn/library/ms188357(v=sql.105).aspx
- create symmetric key MySymmetric --以密碼加密的對稱密鑰
- with
- algorithm=aes_128
- encryption by password='[email protected]';
- go
- create symmetric key MySymmetric --以非對稱密鑰加密的對稱密鑰
- with
- algorithm=aes_128
- encryption by asymmetric key MyAsymmetric
- go
- -- 打開對稱密鑰(打開才能有效使用加密解密函數)
- -- https://msdn.microsoft.com/zh-cn/library/ms190499(v=sql.105).aspx
- open symmetric key MySymmetric decryption by password='[email protected]';
- go
- open symmetric key MySymmetric decryption by asymmetric key MyAsymmetric with password='[email protected]';
- go
- -- 加密資料
- -- https://technet.microsoft.com/zh-cn/library/ms174361%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396
- update EnryptTest set SymmetricCol = encryptbykey(key_guid('MySymmetric'),convert(varchar(max),EnryptData))
- go
- -- 解密資料
- -- https://technet.microsoft.com/zh-cn/library/ms181860(v=sql.105).aspx
- select *,convert(varchar(max ) ,convert (varchar(max ),decryptbykey(SymmetricCol)))
- from EnryptTest
- go
- -- 關閉對稱密鑰,或關閉在目前會話中打開的所有對稱密鑰
- -- https://msdn.microsoft.com/zh-cn/library/ms177938%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396
- -- close all symmetric keys;
- close symmetric key MySymmetric;
- go
- -- alter symmetric 添加或删除新的加密方式(如添加多多個密碼,任何一個密碼都可用)
- -- https://msdn.microsoft.com/zh-cn/library/ms189440(v=sql.105).aspx
- open symmetric key MySymmetric decryption by password='[email protected]';
- alter symmetric key MySymmetric add encryption by password = '[email protected]' --New another Password
- close symmetric key MySymmetric;
- open symmetric key MySymmetric decryption by password='[email protected]'; --Use New Password
- select convert(varchar(max ) ,convert (varchar(max ),decryptbykey(SymmetricCol))) from EnryptTest
- alter symmetric key MySymmetric drop encryption by password = '[email protected]'--Drop the new Password
- close symmetric key MySymmetric;
- go
- -- 删除對稱密鑰
- -- https://msdn.microsoft.com/zh-cn/library/ms182698(v=sql.105).aspx
- drop symmetric key MySymmetric;
- go
- -- 删除測試列
- alter table EnryptTest drop column SymmetricCol
- go
【主密鑰證書示例】
[sql] view plain copy
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcu82Yp9VRE90Qvw1c0V2czF2LcRXZu5ibkN3YuUGZvN2Lc9CX6MHc0RHaiojIsJye.png)
- -- 測試資料
- create table EnryptTest
- (
- id int not null primary key,
- EnryptData nvarchar(20),
- )
- go
- insert into EnryptTest
- values(1,N'888888'),(2,N'888888'),(3,N'123456'),(4,N'A');
- go
- select * from EnryptTest;
- alter table EnryptTest add CertificateCol varbinary(max)
- go
- --建立主密鑰
- create master key encryption by password = N'[email protected]'
- go
- --建立證書,因為預設使用主密鑰加密,此處不需要密碼
- create certificate Mycertificate
- with subject = N'EnryptData certificate',
- start_date = N'20150401',
- expiry_date = N'20160401';
- go
- --加密解密都自動使用服務主密鑰加密了。即使使用“close master key ”也不起作用
- update EnryptTest
- set CertificateCol = EncryptByCert(CERT_ID('Mycertificate'),CONVERT(VARCHAR(MAX),EnryptData))
- go
- select *,CONVERT(VARCHAR(MAX ),DECRYPTBYCERT(CERT_ID('Mycertificate'),CertificateCol))
- from EnryptTest;
- go
- --現在删除“服務主密鑰”
- alter master key drop encryption by service master key
- go
- --再查詢資料,沒有解密出來。不自動使用主密鑰加密解密了
- select *,CONVERT(VARCHAR(MAX ),DECRYPTBYCERT(CERT_ID('Mycertificate'),CertificateCol))
- from EnryptTest;
- go
- --這時需要顯式打開主密鑰,使用主密鑰密碼加密解密
- open master key decryption by password = N'[email protected]'
- go
- --再查詢資料,解密出來了。
- select *,CONVERT(VARCHAR(MAX ),DECRYPTBYCERT(CERT_ID('Mycertificate'),CertificateCol))
- from EnryptTest;
- go
- --最後關閉主密鑰
- close master key
- go
- --檢視主密鑰,少了"ENCRYPTION BY MASTER KEY",沒有了主密鑰進行加密,而是使用密碼進行加密
- select * from sys.key_encryptions
- --删除測試資料
- drop certificate Mycertificate;
- go
- drop master key
- go
- drop table EnryptTest
- go
- 參考:
- 服務主密鑰:https://msdn.microsoft.com/zh-cn/library/ms189060(v=sql.90).aspx
【證書備份還原示例】
[sql] view plain copy
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5Gcu82Yp9VRE90Qvw1c0V2czF2LcRXZu5ibkN3YuUGZvN2Lc9CX6MHc0RHaiojIsJye.png)
- -- drop table EnryptTest
- create table EnryptTest
- (
- id int not null primary key,
- EnryptData nvarchar(20),
- )
- go
- insert into EnryptTest
- values(1,N'888888'),(2,N'888888'),(3,N'123456'),(4,N'A');
- go
- alter table EnryptTest add CertificateCol varbinary(max) --證書加密的列
- go
- select * from EnryptTest;
- --将相關資訊删除
- drop certificate Mycertificate;
- go
- drop master key
- go
- -- 建立以密碼加密的證書
- create certificate Mycertificate
- encryption by password = N'[email protected]'
- with subject = N'EnryptData certificate',
- start_date = N'20150401',
- expiry_date = N'20160401';
- go
- -- 證書加密資料
- update EnryptTest set CertificateCol = EncryptByCert(CERT_ID('Mycertificate'),CONVERT(VARCHAR(MAX),EnryptData))
- go
- -- 解密(正常)
- select *,convert(varchar(max ),decryptbycert(cert_id('Mycertificate'),CertificateCol,N'[email protected]'))
- from EnryptTest;
- go
- -- 備份證書
- backup certificate mycertificate
- to file = N'D:\mycertificate.cer'
- with private key (
- file = N'D:\mycertificate_saleskey.pvk' ,
- decryption by password = N'[email protected]' ,
- encryption by password = N'[email protected]' );
- go
- -- 删除證書
- drop certificate Mycertificate;
- go
- -- 解密(失敗)
- select *,convert(varchar(max ),decryptbycert(cert_id('Mycertificate'),CertificateCol,N'[email protected]'))
- from EnryptTest;
- go
- -- 還原證書
- create certificate mycertificate
- from file = N'D:\mycertificate.cer'
- with private key (
- file = N'D:\mycertificate_saleskey.pvk',
- decryption by password = N'[email protected]' ,
- encryption by password = N'[email protected]' ); --新證書密碼
- go
- -- 解密(正常)
- select *,convert(varchar(max ),decryptbycert(cert_id('Mycertificate'),CertificateCol,N'[email protected]')) --新證書密碼
- from EnryptTest;
- go
- -- 删除測試資料
- drop certificate Mycertificate;
- go
- drop table EnryptTest
- go
- 沒有資料庫主密鑰情況下,使用密碼加密的證書。證書直接加密解密資料,備份還原後,對之前的加密資料仍正常解密,因為備用還原都是同一個證書。而使用證書加密的對稱密鑰,對稱密鑰不能備份,删除重建後,key_guid不一樣了,之前使用對稱密鑰加密的資料已經不能使用新的對稱密鑰解密了。檢視select * from sys.symmetric_keys,可以看到不一樣了。
加密解密函數:https://msdn.microsoft.com/zh-cn/library/ms173744.aspx
插圖2張:
附錄:
DECRYPTBYCERT (Transact-SQL)
其他版本
用證書的私鑰解密資料。
Transact-SQL 文法約定
文法
DecryptByCert ( certificate_ID , { 'ciphertext' | @ciphertext }
[ , { 'cert_password' | @cert_password } ] )
參數
- certificate_ID
- 資料庫中證書的 ID。certificate_ID 的資料類型為 int。 ciphertext
- 已用證書的公鑰加密的資料的字元串。 @ciphertext
- 包含已使用證書進行加密的資料的 varbinary 類型變量。 cert_password
- 用來加密證書私鑰的密碼。必須為 Unicode 字元。 @cert_password
- 類型為 nchar 或 nvarchar 的變量,其中包含用來加密證書私鑰的密碼。必須為 Unicode 字元。
傳回類型
最大大小為 8,000 個位元組的 varbinary。
注釋
此函數用證書的私鑰解密資料。使用非對稱密鑰進行的加密轉換會消耗大量資源。是以,EncryptByCert 和 DecryptByCert 不适合用于對使用者資料的例行加密。
權限
需要對證書具有 CONTROL 權限。
示例
下面的示例從 [AdventureWorks2008R2].[ProtectedData04] 中選擇标記為 data encrypted by certificate JanainaCert02 的行。此示例使用證書 JanainaCert02 的私鑰對密碼進行解密,首次解密時使用的是證書的密碼 pGFD4bb925DGvbd2439587y。解密後的資料将從 varbinary 轉換為 nvarchar。
SELECT convert(nvarchar(max), DecryptByCert(Cert_Id('JanainaCert02'),
ProtectedData, N'pGFD4bb925DGvbd2439587y'))
FROM [AdventureWorks2008R2].[ProtectedData04]
WHERE Description
= N'data encrypted by certificate '' JanainaCert02''';
GO