发布部分 sha() 明文字符串安全吗?

Is publishing parts of sha() cleartext string safe?

我正在尝试轻松生成取消订阅 link,而无需每个用户的秘密。我的建议是发送 sha512(email + shared_secret) 作为“退订令牌”。

鉴于用户知道 emailsha512(email) 的明文,这是否安全,或者是否让攻击者更容易猜测 shared_secret

如果没有必要,永远不要发布甚至是加密的秘密。与不发送加密密钥和发送加密密钥相比,不发送加密密钥显然更好。想象一下,如果用户注册了多个帐户并取消了所有帐户的订阅。 He/she 可能会猜出您输入的公式,如果是这样,he/she 将知道结果值仅在其输入的电子邮件中有所不同。通过改变电子邮件,也许 100 封电子邮件,这可能会导致更接近黑客攻击你。相反,我建议生成令牌,以某种方式唯一标识用户并将该令牌发送给用户。令牌不应依赖于您不打算共享的信息。它可以依赖于 id、电子邮件和盐。

想想你想要达到的目标。您生成了一个令牌,当您从不受信任的来源收到它时,您想要确保该令牌实际上是您生成的,而不是您自己存储的。

用于此的加密工具是消息验证码,例如 HMAC。无需过多介绍,HMAC 是关于使用包含的秘密对数据进行哈希处理,类似于您提出的建议,但实际上可以抵御各种攻击。因此,在一个仍然天真的实现中,您可以生成一个 HMAC(email, shared_secret) 并将其作为您的取消订阅令牌发送。

但是,如果实施不当,HMAC 的常见问题是重播。此令牌仅取决于用户的电子邮件地址,与其他无关。如果此电子邮件地址曾经取消订阅并收到令牌(也可能会被泄露),则该令牌永远有效以取消订阅该电子邮件地址,即。可以被攻击者重放。如果在一个不是很关键的应用程序中直接取消订阅 link,这可能是一个可以接受的风险,或者您可以更好地实施它。例如,您可以将时间戳(例如 unixtime)也添加到组合中并生成代码作为 [timestamp, HMAC(email + timestamp, secret)],即。您将在代码中包含时间戳,并将其添加到您的取消订阅 link 明文中。当服务器收到取消订阅请求时,它可以重新生成 HMAC,检查它是否相同,并检查时间戳,以免它太旧。这样做的好处是它仍然是无状态的,并且对于大多数应用程序来说相当安全。

或者您可以只为您的用户存储一个唯一的令牌,这当然是最安全的,原因有很多(主要是因为复杂性较低和攻击面最小),但有状态。