非对称密钥(Asymmetric Keys)跟对称密钥相对,它使用一对密钥(算法),一个密钥用于加密,另一个密钥用于解密,加密的密钥称为私钥(private key),解密的密钥称为公钥(public key)。私钥由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人——银行才能对你的消息解密。与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。
跟对称密钥相比,非对称密钥提供的安全级别更高,付出的代价是消耗的资源更多。我们建议开发者避免使用非对称密钥对大量的数据进行加密和解密操作,推荐的做法是:对数据进行压缩,使用对称密钥来加密压缩之后的数据,由于对称密钥可能在数据传递过程中被窃取和破译,因此,推荐使用非对称密钥来保护对称密钥。
举个例子,发送方把对称加密的密钥使用非对称加密的公钥进行加密,发送出去;接收方使用私钥进行解密得到对称加密的密钥,这样,双方使用对称加密来进行沟通。
ENCRYPTBYASYMKEY()函数使用非对称密钥来加密数据,该函数加密的数据字节长度是有限度的,根据算法的不同,加密的长度限制不同:
- 对于RSA_512算法,最多加密53bytes;
- 对于RSA_1024算法,最多加密117bytes;
- 对于RSA_2048算法,最多加密245bytes;
在SQL Server中,证书和非对称密钥都使用RSA密钥,是RSA密钥的包装(wrapper)。
非对称密钥是数据库级别的安全实体。 默认情况下,该实体同时包含公共密钥和私有密钥。默认情况下,私钥受数据库主密钥保护。 如果尚未创建数据库主密钥,则需要密码来保护私钥。
一,创建非对称密钥
非对称密钥可以通过文件来导入,也可以在SQL Server中创建。
CREATE ASYMMETRIC KEY asym_key_name [ FROM FILE = 'path_to_strong-name_file' ] [ WITH ALGORITHM = <algorithm> ] [ ENCRYPTION BY PASSWORD = 'password' ] <algorithm> ::= { RSA_4096 | RSA_3072 | RSA_2048 | RSA_1024 | RSA_512 }
参数注释:
FROM FILE = 'path_to_strong-name_file':从文件导入已有的密钥对,或从程序集或DLL文件导入公共密钥。
在不使用FROM子句的情况下执行时,CREATE ASYMMETRIC KEY会生成一个新的密钥对。加密的算法,推荐使用RSA_4096、RSA_3072和RSA_2048,而RSA_1024 和 RSA_512已经过时了。
对于新建的非对称密钥,可以使用密码来保护私钥,这需要在ENCRYPTION BY PASSWORD = 'password' 设置,如果省略该子句,那么使用数据库主密钥来保护私钥。
举个例子,创建一个新的非对称密钥,使用密码保护密钥:
CREATE ASYMMETRIC KEY PacificSales09 WITH ALGORITHM = RSA_2048 ENCRYPTION BY PASSWORD = '<enterStrongPasswordHere>'; GO
二,修改非对称密钥
修改非对称密钥,可以移除密钥的私钥,也可以修改保护私钥的密码。修改非对称密钥的语法如下:
ALTER ASYMMETRIC KEY Asym_Key_Name <alter_option> <alter_option> ::= <password_change_option> | REMOVE PRIVATE KEY <password_change_option> ::= WITH PRIVATE KEY ( <password_option> [ , <password_option> ] ) <password_option> ::= ENCRYPTION BY PASSWORD = 'strongPassword' | DECRYPTION BY PASSWORD = 'oldPassword'
参数注释:
- REMOVE PRIVATE KEY:移除私钥,但是保留公钥
- ENCRYPTION BY PASSWORD ='strongPassword': 用于指定一个新的密钥来保护私钥
- DECRYPTION BY PASSWORD ='oldPassword':用于指定解密私钥的旧密码,如果私钥被DMK保护,那么不需要改子句。
举个例子,修改保护私钥的密码:
ALTER ASYMMETRIC KEY PacificSales09 WITH PRIVATE KEY ( DECRYPTION BY PASSWORD = '<oldPassword>', ENCRYPTION BY PASSWORD = '<enterStrongPasswordHere>'); GO
三,使用非对称密钥来加密和解密数据
用非对称密钥来加密和解密数据,需要用到以下函数:
ASYMKEY_ID ( 'Asym_Key_Name' ) EncryptByAsymKey ( Asym_Key_ID , { 'plaintext' | @plaintext } ) DecryptByAsymKey (Asym_Key_ID , { 'ciphertext' | @ciphertext } [ , 'Asym_Key_Password' ] )
在解密数据时,如果私钥是用密码来保护的,需要提供密码(设置参数'Asym_Key_Password')来解密,如果密钥是用DMK来解密的,那么不需要提供解密私钥的密码。
示例1,用非对称密钥来加密:
EncryptByAsymKey(AsymKey_ID('JanainaAsymKey02'), @cleartext)
示例2,用非对称密钥来解密,密钥用密码来解密。
DecryptByAsymKey( AsymKey_Id('JanainaAsymKey02'), CipherData, N'pGFD4bb925DGvbd2439587y' )
四,举个例子
虽然非对称加密很安全,但是和对称加密比起来,它非常的慢,所以我们还是要用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。为了解释这个过程,请看下面的例子:
(1) Alice需要在银行的网站做一笔交易,她的浏览器首先生成了一个随机数作为对称密钥。
(2) Alice的浏览器向银行的网站请求公钥。
(3) 银行将公钥发送给Alice。
(4) Alice的浏览器使用银行的公钥将自己的对称密钥加密。
(5) Alice的浏览器将加密后的对称密钥发送给银行。
(6) 银行使用私钥解密得到Alice浏览器的对称密钥。
(7) Alice与银行可以使用对称密钥来对沟通的内容进行加密与解密了。
参考文档:
CREATE ASYMMETRIC KEY (Transact-SQL)