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'));
现在,备份数据库:
BACKUP DATABASE blat TO DISK = 'C:\wherever\blat.bak' WITH INIT;
现在,在不同域中的不同服务器上,或者在您认为某些服务主密钥没有隐藏附件的任何地方,恢复数据库:
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';
最后,从恢复的副本中检索数据,并观察您仍然可以解密它:
USE blat;
GO
SELECT floob, prying_eyes = CONVERT(NVARCHAR(4000),
DECRYPTBYPASSPHRASE(N'kerplunk', splunge))
FROM dbo.mort;
作为旁注,我承认我完全不知道ENCRYPTBYPASSPHRASE()内部实际上是如何工作的,除了它使用三重 DES (3DES) 加密这一事实。它是不确定的——所以它可能使用类似NEWID()或RAND()内部的东西——你的猜测和我的一样好。我确实知道,如果您运行以下命令,每次都会得到不同的二进制值,如果您采用任何单独的输出值并DECRYPTBYPASSPHRASE()针对该值运行,您最终仍会返回原始值:
SELECT ENCRYPTBYPASSPHRASE(N'banana', N'turkey');
GO 5
不,这不是真的,而且有一个简单的证明。在一台服务器上,创建一个数据库,并使用以下方式存储一些数据
ENCRYPTBYPASSPHRASE()
:现在,备份数据库:
现在,在不同域中的不同服务器上,或者在您认为某些服务主密钥没有隐藏附件的任何地方,恢复数据库:
最后,从恢复的副本中检索数据,并观察您仍然可以解密它:
结果应该是:
因此,这意味着如果用户获取您的数据并且知道密码短语(例如,如果您将其存储在同一个数据库中的某个位置),他们可以解密所有数据,而无需担心密钥或其他任何事情。您可能会从中推断出
ENCRYPTBYPASSPHRASE()
存储密码的方法不是很安全,除非您从未存储用户输入的密码短语,或者除非您在此基础上使用其他工具和方法(范围蔓延)。作为旁注,我承认我完全不知道
ENCRYPTBYPASSPHRASE()
内部实际上是如何工作的,除了它使用三重 DES (3DES) 加密这一事实。它是不确定的——所以它可能使用类似NEWID()
或RAND()
内部的东西——你的猜测和我的一样好。我确实知道,如果您运行以下命令,每次都会得到不同的二进制值,如果您采用任何单独的输出值并DECRYPTBYPASSPHRASE()
针对该值运行,您最终仍会返回原始值:事实上,您可以在自己的系统上进行尝试。这是我生成的二进制值之一,如果你反转这个过程,你也应该得到
turkey
: