【发布时间】:2010-10-11 11:57:15
【问题描述】:
当我想将 SHA1 哈希的结果存储在 MySQL 数据库中时,我遇到了一个简单的问题:
我存储哈希结果的 VARCHAR 字段应该多长时间?
【问题讨论】:
-
如果你只是用谷歌搜索 sha1 点击我感觉很幸运,你应该在维基百科上找到它总是 160 位。
标签: mysql database-design hash sha1
当我想将 SHA1 哈希的结果存储在 MySQL 数据库中时,我遇到了一个简单的问题:
我存储哈希结果的 VARCHAR 字段应该多长时间?
【问题讨论】:
标签: mysql database-design hash sha1
Reference taken from this blog:
以下是哈希算法列表及其所需位大小:
创建了一个需要 CHAR(n) 的示例表:
CREATE TABLE tbl_PasswordDataType
(
ID INTEGER
,MD5_128_bit CHAR(32)
,SHA_160_bit CHAR(40)
,SHA_224_bit CHAR(56)
,SHA_256_bit CHAR(64)
,SHA_384_bit CHAR(96)
,SHA_512_bit CHAR(128)
);
INSERT INTO tbl_PasswordDataType
VALUES
(
1
,MD5('SamplePass_WithAddedSalt')
,SHA1('SamplePass_WithAddedSalt')
,SHA2('SamplePass_WithAddedSalt',224)
,SHA2('SamplePass_WithAddedSalt',256)
,SHA2('SamplePass_WithAddedSalt',384)
,SHA2('SamplePass_WithAddedSalt',512)
);
【讨论】:
我会将VARCHAR 用于可变长度数据,但不能用于固定长度数据。因为 SHA-1 值总是 160 位长,所以VARCHAR 只会浪费an additional byte for the length of the fixed-length field。
我也不会存储 SHA1 返回的值。因为它每个字符只使用 4 位,因此需要 160/4 = 40 个字符。但是如果你使用每个字符 8 位,你只需要一个 160/8 = 20 个字符长的字段。
所以我建议您使用BINARY(20) 和UNHEX function 将SHA1 值转换为二进制。
我比较了BINARY(20) 和CHAR(40) 的存储要求。
CREATE TABLE `binary` (
`id` int unsigned auto_increment primary key,
`password` binary(20) not null
);
CREATE TABLE `char` (
`id` int unsigned auto_increment primary key,
`password` char(40) not null
);
百万条记录binary(20) 需要 44.56M,而char(40) 需要 64.57M。
InnoDB 引擎。
【讨论】:
UNHEX() 手动添加到 sql 时才有效。
如果您需要在 sha1 列上建立索引,出于性能原因,我建议使用 CHAR(40)。 在我的情况下,sha1 列是一个电子邮件确认令牌,因此在登录页面上,查询仅使用令牌输入。 在这种情况下,我认为带有 INDEX 的 CHAR(40) 是最好的选择:)
如果要采用这种方式,记得留$raw_output = false。
【讨论】:
在您不总是为用户存储哈希值的情况下(即验证帐户/忘记登录 url),您可能仍希望使用 VARCHAR。一旦用户验证/更改了他们的登录信息,他们就不应该能够使用哈希并且应该没有理由这样做。您可以创建一个单独的表来存储临时哈希 -> 可以删除的用户关联,但我认为大多数人不会费心这样做。
【讨论】:
所以长度介于 10 个 16 位字符和 40 个十六进制数字之间。
在任何情况下,确定您要存储的格式,并根据该格式使字段大小固定。 这样您就不会浪费任何空间。
【讨论】:
sha1 的输出大小为 160 位。即 160/8 == 20 个字符(如果您使用 8 位字符)或 160/16 = 10(如果您使用 16 位字符)。
【讨论】:
SHA1 哈希的长度为 40 个字符!
【讨论】: