在MySQL上存储BCrypt哈希值的正确方式

9
寻找在MySQL中存储BCrypt哈希的正确方法,我发现了这个问题,但它只让我更加困惑。
接受的答案指出我们应该使用:CHAR(60) BINARY or BINARY(60)。但其他人在评论中提出相反的意见,认为我们应该使用:CHAR(60) CHARACTER SET latin1 COLLATE latin1_bin,甚至是:COLLATE latin1_general_cs
我不是数据库专家,所以有谁能解释一下所有这些选项之间的区别,哪一个是真正更适合存储BCrypt哈希?

据我所知,加密哈希是一串比特流(即二进制),但通常表示为纯文本。您需要存储什么格式? - Álvaro González
你的问题非常接近于“有人能否请阅读MySQL数据类型文档并为我做出执行摘要?” - Tomalak
@ÁlvaroGonzález 是的,哈希是一串比特流,而且它被编码为纯文本,但是所有这些存储选项都会导致数据库上不同类型的行为。 - Michel Feinstein
@Tomalak,这真的不是我的意图。我已经阅读了有关BINARY和CHAR以及_bin类型的排序差异的文档,但是我无法看到它们各自的好处以及它们如何比较,它们的注意事项和惊喜。因此,我的意图实际上是询问比我更有经验的人这两个选项如何比较。 - Michel Feinstein
@mFeinstein 你应该提供赏金。我认为这是一个重要的问题。 - Tek
是的,我想我会...但如果你想帮忙的话,点赞和收藏这个问题也有助于它的推广 :) - Michel Feinstein
1个回答

9
我的回答是关于“正确”而不是“可行”的。
不要使用 latin1。当加密字符串不是文本时,宣称加密字符串是文本是很丑陋的。
同样的情况也适用于CHAR...。
如果长度固定,只需使用 BINARY(...),如果长度可变,则使用 VARBINARY(...)。
然而,需要注意的是...你使用的BCrypt是谁的?它返回二进制数据吗?还是十六进制字符串?或者甚至是Base64?
我的上面的回答假设它返回二进制数据。
如果它返回60个十六进制数字,则将 UNHEX(60_hex_digits) 存储到 BINARY(30) 中以便更小地压缩。
如果它是Base64,则 CHARACTER SET ascii COLLATE ascii_bin 就是“正确”的方式。(也可以使用支持大小写的latin1。)
如果是二进制,则再次使用 BINARY(60) 是“正确”的方式。
您提供的链接看起来像是Base64编码的,但是它是吗?并且是否最多有60个字符?那么我会使用
VARCHAR(60) CHARACTER SET ascii COLLATE ascii_bin

明确指定列的字符集/校对规则,从而覆盖数据库和/或表格的“默认”设置。

所有Base64字符(以及$)都是ASCII码;不需要更复杂的字符集。使用..._bin进行排序意味着“精确比较字节”,更具体地说是“不进行大小写转换”。由于Base64依赖于区分大小写的字母,因此不希望进行大小写转换。


我认为我们不能将bcrypt视为纯粹的base64字符串,因为它总是带有前缀"$2a$"、"$2b$"或"$2y$",这在协议的任何未来更新中都可能发生变化,还有成本参数(类似于$10$)。目前,哈希值长度为60个字符,盐和哈希值是base64编码的,但前缀不是。 - Michel Feinstein
@mFeinstein - 没关系。我的建议仍然适用(在我修复了一个打字错误后!) - Rick James
你能详细说明一下使用ascii_bin排序规则的优点吗?我不是数据库专家,所以不清楚它提供的所有好处和保护措施。 - Michel Feinstein
我添加了一个段落。 - Rick James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接