存储 MD5 哈希或 NULL 的最佳 MySQL 数据类型

Posted

技术标签:

【中文标题】存储 MD5 哈希或 NULL 的最佳 MySQL 数据类型【英文标题】:Best MySQL data type to store MD5 hash or NULL 【发布时间】:2013-10-04 02:45:25 【问题描述】:

我有一个 php 应用程序,它将所有帐户都存储在一个表中,无论它们是否处于活动状态。该表有一个名为“active”的列,它要么为 NULL,表示帐户处于活动状态,要么包含 MD5 哈希,表示帐户处于非活动状态。

根据Best practices for efficiently storing md5 hashes in mysql,如果列始终包含 MD5 散列且从不为 NULL,则首选 BINARY(16),而 CHAR(32) 是次佳选择。由于我的大多数帐户都处于活动状态,因此大多数列值为 NULL,我是否最好使用不同的数据类型,例如 VARCHAR(32)?

【问题讨论】:

是的,你可以。VARCHAR(32) 更可取。 MySQL: what data type to use for hashed password field and what length?的可能重复 【参考方案1】:

使用 VARCHAR 毫无意义。 MD5 哈希值始终为 128 位,因此 CHAR(32) 保存十六进制数字字符串,或 BINARY(16) 在 UNHEX() 十六进制数字之后保存字节字符串。

使用 NULL 与数据类型选择无关。 MySQL 可以存储 NULL 来代替字符串,CHAR 或 VARCHAR。但实际上,在 InnoDB 的默认行格式中,MySQL 根本不存储 NULL,对于为 NULL 的列它什么也不存储。


参考:http://dev.mysql.com/doc/internals/en/innodb-field-contents.html

关于 NULL 的有用说明:

对于第三行,我在 FIELD2 和 FIELD3 中插入​​了 NULL。因此,在字段起始偏移中,这些字段的最高位是打开的(值是 94 十六进制,94 十六进制,而不是 14 十六进制,14 十六进制)。 而且行更短,因为 NULL 不占用空间。

(强调我的)

【讨论】:

谢谢比尔,所以根据你的回答,我知道如果我使用 CHAR(32) 或 BINARY(16),并且存储的值为 NULL,那么我的开销不会大于使用 VARCHAR( 32)。谢谢,我希望你是对的! +1 Bill 和 @user1032531 Bill 表示您应该使用 CHAR(32) 或 BINARY(16) 。是的,当您使用 VARCHAR 时,您的开销会更大,因为 MySQL 需要额外保存两条短裤才能知道您的 VARCHAR 有多大。当您定义 ascii_bin 字符集时,CHAR 列上的精确查找键应该更快。【参考方案2】:

注意: 更新日期:2019 年 5 月 11 日

理想情况下,您不应该再使用 MD5 来散列密码。 PHP 手册在 4 - 5 年前添加了一个 Safe Password Hashing 部分,现在我相信 password_hash()password_verify() 的解释以及为什么 MD5 / SHA1 不适合..

请记住,因为大多数 RDMS 旨在提供非常稳定的时间,因为大多数 RDMS 缓冲区数据在内存中和/或索引中,当password 列位于WHERE 子句中时,这使得定时攻击很可能发生

password_verify() 与 SQL 结合使用的安全方法是在“伪”PHP 代码中。

$row = prepare("SELECT password FROM users WHERE username = :username").execute().fetch(); 
if (password_verify($_POST['password'], $row->password))  
  // password correct
 else 
  // password incorrect..

在文件 strings/ctype-bin.c 的 MySQL 源代码中,定义了 BINARY 类型。

这看起来像是默认的基于 C ascii 的字符集转换为二进制。理论上,这应该比带有 ascii_bin 字符集的 CHAR(32) 更快。

因为写入/读取二进制文件所需的时间更少,索引和内存占用的磁盘空间更少,而且 CHAR(32) 数据类型大 16 个字节

如果你想使用这个,你应该使用这个 php 代码

<?php
  md5 ( "password", true ); // true returns the binary what is 16 bytes long  MySQl BINARY(16)
?>

【讨论】:

【参考方案3】:

可以使用php函数md5(); 效率更高,如果有人可以在您发送到数据库时捕获数据,则该数据已经加密。

【讨论】:

这如何回答这个问题?

以上是关于存储 MD5 哈希或 NULL 的最佳 MySQL 数据类型的主要内容,如果未能解决你的问题,请参考以下文章

哈希密码的最佳实践

如何迁移密码哈希?

在mysql中存储密码......使用哈希对吗?但是您如何向用户发送忘记的密码?

我应该使用什么哈希算法来存储密码?

如何哈希密码

PHP漏洞 (转)