Aar*_*and 4 sql-server encryption
在最近的一个问题中,服务主密钥保护什么?,建议服务主密钥保护由 加密的数据等ENCRYPTPASSPHRASE()
。这是真的?
不,这不是真的,而且有一个简单的证明。在一台服务器上,创建一个数据库,并使用ENCRYPTBYPASSPHRASE()
以下命令存储一些数据:
CREATE DATABASE blat;
GO
USE blat;
GO
CREATE TABLE dbo.mort(floob INT, splunge VARBINARY(64));
GO
INSERT dbo.mort VALUES
(1, ENCRYPTBYPASSPHRASE(N'kerplunk', N'secret')),
(2, ENCRYPTBYPASSPHRASE(N'kerplunk', N'hidden'));
Run Code Online (Sandbox Code Playgroud)
现在,备份数据库:
BACKUP DATABASE blat TO DISK = 'C:\wherever\blat.bak' WITH INIT;
Run Code Online (Sandbox Code Playgroud)
现在,在不同域中的不同服务器上,或者在您认为没有隐藏的某些服务主密钥的附件的任何地方,恢复数据库:
RESTORE DATABASE blat FROM DISK = 'C:\wherever\blat.bak'
WITH REPLACE, RECOVERY,
MOVE 'blat' TO 'C:\somepath\blat.mdf',
MOVE 'blat' TO 'C:\somepath\blat.ldf';
Run Code Online (Sandbox Code Playgroud)
最后,从恢复的副本中检索数据,并观察您仍然可以解密它:
USE blat;
GO
SELECT floob, prying_eyes = CONVERT(NVARCHAR(4000),
DECRYPTBYPASSPHRASE(N'kerplunk', splunge))
FROM dbo.mort;
Run Code Online (Sandbox Code Playgroud)
结果应该是:
floob prying_eyes
----- -----------
1 secret
2 hidden
Run Code Online (Sandbox Code Playgroud)
因此,这意味着如果用户获取您的数据并知道密码短语(例如,如果您将其存储在同一个数据库中的某处),他们就可以解密所有数据,而无需担心密钥或其他任何事情。您可能由此推断,这ENCRYPTBYPASSPHRASE()
不是一种非常安全的密码存储方式,除非您从不存储用户输入的密码短语,或者除非您在此基础上使用其他工具和方法(范围蔓延)。
作为旁注,我承认我完全不知道ENCRYPTBYPASSPHRASE()
内部实际是如何工作的,除了它使用三重 DES (3DES) 加密这一事实。它是不确定的 - 所以它可能会使用类似NEWID()
或RAND()
内部的东西- 你的猜测和我的一样好。我确实知道,如果您运行以下命令,每次都会得到不同的二进制值,如果您采用任何单个输出值并DECRYPTBYPASSPHRASE()
针对该值运行,您最终仍会返回原始值:
SELECT ENCRYPTBYPASSPHRASE(N'banana', N'turkey');
GO 5
Run Code Online (Sandbox Code Playgroud)
事实上,你可以在你自己的系统上试试这个。这是我生成的二进制值之一,如果你颠倒这个过程,你也应该得到turkey
:
SELECT CONVERT(NVARCHAR(4000), DECRYPTBYPASSPHRASE(N'banana',
0x010000007854E155CEE338D5E34808BA95367D506B97C63FB5114DD4CE687FE457C1B5D5))
Run Code Online (Sandbox Code Playgroud)