我认为你计划中的缺陷是你的陈述
H0 对黑客来说是未知的,但仍然可以被服务器验证。
不是这种情况。请记住,哈希是一种方式。服务器从您那里收到的所有信息都是 H1,它们已将其转换为 H2(现在已被入侵)。服务器不知道生成 H1(即 H0)的输入是什么。此外,假设服务器只保留了 H2 而没有保留 H1。如果他们保留了 H1,那么是的,他们可以拥有 H0 并与 H1 进行比较,但他们保留了 H2。
如果您考虑一下,虽然 H1 是您最初发送到服务器的内容,但从服务器的角度来看,它只是一个密码 - 一个可能很长的密码,但仍然只是一个密码。然后,服务器需要对该密码进行哈希处理以存储它(创建 H2)。我们也希望服务器没有 H1 的记录。当您进行身份验证时,您发送 H1,服务器对其进行哈希处理以获取 H2。为了使您的方案正常工作,服务器还需要保留 H1,这就像保留纯文本密码一样。一旦黑客掌握了 H1 哈希数据库,他们就可以以与该哈希关联的用户身份访问服务器,而无需执行任何其他操作。
另一个稍微掩盖了您可能需要更多思考的部分建议是
修补客户端现在发送(和服务器现在需要)哈希 H0。
这是一个潜在的问题,或者至少可能与更改密码一样多。如果您要自动允许这种路径,从而减少/避免用户采取行动的需要,那么您将打开另一个潜在的安全问题 - 如何/谁将启动该修补程序以及您将如何防止未经授权的修补程序。如果您希望用户进行修补,则可能需要花费更多的努力才能做到正确,而不仅仅是让他们更改密码。
编辑:正如评论中所指出的,您可以通过将 H0 哈希两次 H0 -> H1 -> H2 并与服务器拥有的 H2 进行比较来验证 H0 哈希。所以也许等式的那一部分可能会起作用。
然而,从使用 H1 到使用 H0 的修补或协调仍然是 IMO 的问题。“正常”更新/补丁机制将不起作用,因为此类机制依赖于单一信任“事实来源”。例如,如果您在 Windows 上信任 Windows 更新服务,如果您在 OSX 上信任 OSX 更新服务。但就网站而言,我们正在处理分散的基础设施。
考虑一个环境,该方案已被所有 Web 服务器的全部或部分子集采用。如果 Web 服务器受到攻击,那么该服务器有必要以某种方式通知客户端他们现在需要发送 H0 而不是 H1。此时,事情开始变得非常复杂,复杂性是安全的天敌。
您不能在全局范围内进行更改,即现在要求所有使用此方案的站点使用 H0 而不是 H1,因为这会导致协调问题 - 您需要以某种方式告诉所有使用该方案的服务器切换到 H0 -> H1 -> h2 方法。现在您必须更新服务器和客户端并协调该更改,否则某些站点将停止工作。
因此,您需要在每个站点的基础上执行此操作。这意味着您需要在您的方案中内置一些机制,允许服务器告诉客户端它想要哪个哈希进行身份验证 - H0 或 H1。现在你有另一个问题。您如何防范要求 H0 的流氓服务器?
鉴于任何密码方案的最大问题之一是人们倾向于在多个站点上使用相同的密码。我们知道这是不好的做法,但人们还是会这样做。如果你要访问一个坏的服务器,它可能会要求 H0。现在该服务器具有 H0 并且可以对其进行哈希处理以获取 H1 并使用该哈希来访问您可能使用的其他服务器,这些服务器仍然依赖原始 H1 作为密码。这甚至可能是对受感染主机的另一个攻击向量的一部分——一旦你破坏了一个主机,你就可以开始询问 H0 哈希值。
这里真正的问题是我们正在增加额外的复杂性,这将增加无法预料的“漏洞”,这只会增加最小可能的额外安全性,并且无法修复使用密码保护访问的基本(并且可能无法修复)方法 - 底线是密码他们自己的访问控制从根本上被破坏了。真正需要的是一种方便的方法,可以在身份验证过程中添加额外的因素,并摆脱依赖简单密码的方法