由 ENCRYPTBYPASSPHRASE() 加密的数据是否受服务主密钥保护?

Aar*_*and 4 sql-server encryption

在最近的一个问题中,服务主密钥保护什么?,建议服务主密钥保护由 加密的数据等ENCRYPTPASSPHRASE()。这是真的?

Aar*_*and 8

不,这不是真的,而且有一个简单的证明。在一台服务器上,创建一个数据库,并使用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)

  • 通过密码加密/解密正是如此。只有密码短语是解密密钥所必需的。向要加密的数据(和/或密码短语)添加“盐”值,并且从不存储加密期间使用的实际密码短语,以保证在没有大规模计算能力的情况下无法解密加密数据的实际目的。 (2认同)