(对于这个问题,假设我只需要支持 SQL Server 2008 及更高版本。或者为了让这个问题过时,比如说最近的、当前的和近期的版本。)
该声明的文档CREATE LOGIN
说(强调我的):
HASHED 仅
适用于 SQL Server 登录。指定在 PASSWORD 参数之后输入的密码已经过散列。如果未选择此选项,则作为密码输入的字符串在存储到数据库之前会经过哈希处理。此选项应仅用于将数据库从一台服务器迁移到另一台服务器。不要使用 HASHED 选项来创建新的登录。HASHED 选项不能与 SQL Server 7 或更早版本创建的哈希一起使用。
没有解释为什么不应该使用这个选项来创建新的登录,如果有原因,这并不明显(至少对我来说)。
该文档引用了 KB918992,虽然有点不清楚,但描述了指示旧版(2000-2008 R2)密码哈希自动升级的步骤。因此,我可以获取在 2000-2008 R2 和CREATE LOGIN ... WITH PASSWORD ... HASHED
2012(+?)上生成的密码哈希,并在主体第一次登录时将哈希转换为 2012 格式。我测试过这确实像描述的那样工作。
密码哈希本身似乎有一个 6 字节的签名/元数据标头,由我认为是 2 字节的标签/版本和 4 字节的盐组成。升级哈希时,标签/版本会增加,而盐保持不变。
那么问题是:如果微软已经融入了这种未来的兼容性(我认为未来需要维护),那么有什么理由不应该使用这种方法来创建新的登录名?
散列方法可能是一个实现细节,在未来的版本中可能会或可能不会改变(因为它至少已经有一次)。如果您尝试在较新或较旧的版本上运行它们,他们告诉您不要这样做,以免除自己破坏脚本/自动化的责任。部分支持纯粹是为了允许迁移登录。
在此过程中的某个时刻,您将不得不使用明文密码来生成散列密码,所以我不确定您是否真的通过提供预散列密码获得了很多收益。
作为记录,SQL Server 2012 哈希格式为:0x200<4 byte salt><hash result>
哈希结果本质上是:
SQL Server 2005 到 2008 R2 是相同的,只是它们使用 SHA-1 而不是 SHA-512。
不使用之前的哈希密码的一些原因是您共享盐(让攻击者获得大量密码而无需做更多工作),并且您正在共享密码(对于攻击者来说,每个破解密码都会带来更多的好处,因为这将直接回到他们的破解字典中),如果攻击者破解了较弱的版本,他们也会自动获得更强版本的密码(一旦他们使用先前破解的密码重新运行他们的软件。
理想情况下,完全使用不同的密码;但是,如果不出意外,至少要确保它在每个地方都是不同的盐,这样攻击者实际上不得不费心用先前破解的密码执行后续的破解运行,而不是简单地看到哈希是相同的,所以如果你破解它一次,你就完成了。