在 MySQL 中存储 SHA1哈希值

当我想在 MySQL 数据库中存储 SHA1散列的结果时,出现了一个简单的问题:

存储散列结果的 VARCHAR字段应该存储多长时间?

117497 次浏览

SHA1散列长度为40个字符!

我会使用 VARCHAR的可变长度的数据,但不与固定长度的数据。因为 SHA-1值是 一直都是160位长,所以 VARCHAR只会浪费 固定长度字段长度的附加字节

我也不会存储 SHA1返回的值。因为每个字符只使用4位,因此需要160/4 = 40个字符。但是如果每个字符使用8位,那么只需要一个160/8 = 20个字符长的字段。

因此,我建议您使用 BINARY(20)UNHEX功能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.56米,而 char(40)需要64.57米。 InnoDB引擎。

Sha1的输出大小为160位。即160/8 = = 20个字符(如果使用8位字符)或160/16 = 10(如果使用16位字符)。

所以长度介于10个16位字符和40个十六进制数字之间。

在任何情况下,决定要存储的格式,并根据该格式将字段设置为固定大小。 这样你就不会浪费空间了。

如果您不总是为用户存储哈希(例如,验证帐户/忘记登录 URL) ,那么您可能仍然需要使用 VARCHAR。一旦用户验证/更改了他们的登录信息,他们就不能使用哈希表,也没有理由使用哈希表。您可以创建一个单独的表来存储可以删除的临时 hash-> 用户关联,但是我不认为大多数人会这样做。

如果需要 sha1列上的索引,出于性能原因,我建议使用 CHAR (40)。 在我的示例中,sha1列是一个电子邮件确认令牌,因此在着陆页面上,查询只使用令牌进入。 在这种情况下,CHAR (40)和 INDEX,在我看来,是最好的选择:)

如果希望采用此方法,请记住保留 $raw _ output = false。

参考文献:

下面是散列算法及其所需位大小的列表:

  • MD5 = 128位散列值。
  • SHA1 = 160位散列值。
  • SHA224 = 224位散列值。
  • SHA256 = 256位散列值。
  • SHA384 = 384位散列值。
  • SHA512 = 512位散列值。

创建了一个需要 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)
);