目标:拥有基于令牌/cookie 的身份验证,不需要在服务器上保持会话
TL;DR:如果有的话,解决 BCrypt 的 72 个字符限制的公认机制是什么?
长版:
阅读此答案后,我尝试使用 BCrypt 作为散列算法和旋转服务器端机密在基于 REST 的服务器上实现身份验证。基本思想是,在使用用户名和密码成功进行身份验证后,服务器将设置一个包含基于以下连接的哈希的 cookie:
- 服务器端的秘密
- 用户ID和用户所属的组
- 发出令牌的时间
然后将使用盐对其进行散列,结果将进入 cookie,由服务器读取和验证(可能是因为用户 ID、组和日期由客户端以明文形式传输,而服务器端秘密在内存中,秘密用作保证客户端没有自己制作所有其他值)。
这一切都很好,直到我意识到 BCrypt 对被散列的明文有 72 个字符的限制(这 72 个字符之后的任何内容都不会影响输出散列)。
这是一个问题,因为上述数据超过 72 个字符,并且允许时间、用户 ID、组或密钥在输入中是“最后一个”而不影响输出,这会在系统的安全性中打开漏洞(无论是旧的令牌是无限有效的,或者人们可以任意修改他们的用户 ID/角色)。
具有讽刺意味的是,当我最终弄清楚为什么我的系统会根据不同的输入生成相同的哈希值并四处搜索时,似乎有些人预见到了这种情况。
无论如何,问题是:如果有的话,解决 BCrypt 的 72 个字符限制的公认机制是什么?
一些先发制人的想法:只要我记得,我就一直在警告我,自己对标准加密算法进行变体,所以我不能 100% 确定什么是最好的行动方案。
明显的选项包括:
- 分块输入并依次和/或以级联方式将 BCrypt 应用于每个输入;
- 在输入上使用另一个(非加密?)散列来减小其大小
- 使用纯压缩(但对于这么少的纯文本可能无效)
- 切换到另一种算法(例如,最近完成了 SHA-3)。
(上述想法可能还有其他问题,在这种情况下,我当然很乐意得到纠正!)