13

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

根据在 mysql 中有效存储 md5 哈希的最佳实践,如果该列始终包含 MD5 哈希并且从不为 NULL,则首选 BINARY(16),而 CHAR(32) 是下一个最佳选择。由于我的大多数帐户都处于活动状态,因此大多数列值将为 NULL,我是否最好使用不同的数据类型,例如 VARCHAR(32)?

4

3 回答 3

26

使用 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 不占用空间。

(强调我的)

于 2013-09-27T18:45:46.943 回答
3

注: 更新时间:2019 年 5 月 11 日

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

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

与 SQL 结合使用的安全方法password_verify()是在“伪”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)
?>
于 2013-09-27T18:12:10.813 回答
-10

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

于 2013-09-27T18:48:15.593 回答