当我想在 MySQL 数据库中存储 SHA1散列的结果时,出现了一个简单的问题:
存储散列结果的 VARCHAR字段应该存储多长时间?
SHA1散列长度为40个字符!
我会使用 VARCHAR的可变长度的数据,但不与固定长度的数据。因为 SHA-1值是 一直都是160位长,所以 VARCHAR只会浪费 固定长度字段长度的附加字节。
VARCHAR
我也不会存储 SHA1返回的值。因为每个字符只使用4位,因此需要160/4 = 40个字符。但是如果每个字符使用8位,那么只需要一个160/8 = 20个字符长的字段。
SHA1
因此,我建议您使用 BINARY(20)和 UNHEX功能将 SHA1值转换为二进制值。
BINARY(20)
UNHEX
我比较了 BINARY(20)和 CHAR(40)的存储需求。
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引擎。
binary(20)
char(40)
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。
参考文献:
下面是散列算法及其所需位大小的列表:
创建了一个需要 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) );