在数据库中存储 MD5 时 BINARY(16) 和 CHAR(32) 的区别

Posted

技术标签:

【中文标题】在数据库中存储 MD5 时 BINARY(16) 和 CHAR(32) 的区别【英文标题】:Difference between BINARY(16) and CHAR(32) when storing MD5 in database 【发布时间】:2013-10-04 20:55:02 【问题描述】:

根据 What data type to use for hashed password field and what length? 等各种建议,我可以将 md5 存储为 CHAR(32) 或 BINARY(16)。但是当我使用 BINARY(16) 执行此操作时,存储的值与 CHAR(32) 存储结果的前 16 个字符以及 SELECT MD5() 结果的前 16 个字符相同。后面的 16 个字符有什么意义,它们在二进制列中不存在会导致数据丢失吗?

CREATE  TABLE test (id INT NOT NULL AUTO_INCREMENT, value VARCHAR(6), md5_char CHAR(32) NOT NULL, md5_binary BINARY(16) NOT NULL, PRIMARY KEY (id)) ENGINE = InnoDB;
INSERT INTO test(value,md5_char,md5_binary) VALUES("one!",md5("one!"),md5("one!"));
INSERT INTO test(value,md5_char,md5_binary) VALUES("two%",md5("two%"),md5("two%"));
INSERT INTO test(value,md5_char,md5_binary) VALUES("three~",md5("three~"),md5("three~"));
SELECT value,md5(value),md5_char,md5_binary FROM test;
DROP TABLE test;

+--------+----------------------------------+----------------------------------+------------------+
| value  | md5(value)                       | md5_char                         | md5_binary       |
+--------+----------------------------------+----------------------------------+------------------+
| one!   | 633c8403325f1cf963809e6eb224d77e | 633c8403325f1cf963809e6eb224d77e | 633c8403325f1cf9 |
| two%   | 48bbec047b4451a2018e0f652807b7d0 | 48bbec047b4451a2018e0f652807b7d0 | 48bbec047b4451a2 |
| three~ | fee453bb4eb68dcdfee07575e75c8cc5 | fee453bb4eb68dcdfee07575e75c8cc5 | fee453bb4eb68dcd |
+--------+----------------------------------+----------------------------------+------------------+

【问题讨论】:

【参考方案1】:

目前您在使用BINARY(16) 时会丢失一半的校验和。当您将 MD5 校验和存储在 BINARY(16) 中时,您应该将其存储为二进制数据, 以十六进制编码。那就是:

INSERT INTO test (md5_binary) VALUES(UNHEX(md5("one!")));

如果您想用眼球将其与另一个校验和进行比较,您可以使用 HEX 函数将其再次编码为十六进制:

SELECT HEX(md5_binary) FROM test;

使用 BINARY 存储校验和而不是十六进制文本的好处是需要一半的存储空间。

【讨论】:

感谢 Joni,类似的,基于 Blowfish 的 bcrypt 需要 CHAR(60) 来存储它。如果我使用UNHEX(),我可以使用 BINARY(30) 吗? 存储优势与数据类型无关。您可以将十六进制存储在二进制中,将非十六进制数据存储在 char 列中。 但是二进制总是需要 char 的一半数字吗? 刚刚意识到您的帖子指出“需要一半的存储空间”。谢谢 @Andomar,不建议将二进制数据存储在 CHAR 列中:然后数据库会将数据解释为具有特定的字符编码,除非您知道自己在做什么,否则您可能会损坏数据(即使用单字节编码和二进制排序规则)

以上是关于在数据库中存储 MD5 时 BINARY(16) 和 CHAR(32) 的区别的主要内容,如果未能解决你的问题,请参考以下文章

加快我在 MySQL 中的索引 - CRC 还是 MD5?

用户登录模块————账户安全问题

MD5加密加盐

登录系统中密码用MD5加密有何作用?防谁呢?

小文件的存储

C#ASP.NET MD5加密