【问题标题】:Mysql encrypt sometimes returns nullMysql encrypt 有时会返回 null
【发布时间】:2017-03-14 23:15:06
【问题描述】:

为什么第一个和最后一个命令行返回null??

$ mysql -u root -ppass -Bse "SELECT ENCRYPT('p@ssW0rd', 'ñsñsñsñ');"
NULL
$ mysql -u root -ppass -Bse "SELECT ENCRYPT('p@ssW0rd', 'dafdadsfe');"
dac0rB9hTC86M
$ mysql -u root -ppass -Bse "SELECT ENCRYPT('p@ssW0rd', 'dafdadsfeñññ');"
dac0rB9hTC86M
$ mysql -u root -ppass -Bse "SELECT ENCRYPT('p@ssW0rd', CONCAT('6', SUBSTRING(SHA(RAND()), -16)));"
63YRpxd2B8u1A
$ mysql -u root -ppass -Bse "SELECT ENCRYPT('p@ssW0rd', CONCAT('$6', SUBSTRING(SHA(RAND()), -16)));"
c7hTUIQiUwO02
$ mysql -u root -ppass -Bse "SELECT ENCRYPT('p@ssW0rd', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16)));"
NULL

我也执行过:

$ mysql -u root -ppass -Bse "SELECT CONCAT('$6$', SUBSTRING(SHA(RAND()), -16));"
$7b07151fc5373796

然后魔法就来了:

MariaDB [(none)]> SELECT ENCRYPT('p@ssW0rd', 'ñsñsñsñ');
+------------------------------------+
| ENCRYPT('p@ssW0rd', 'ñsñsñsñ')     |
+------------------------------------+
| NULL                               |
+------------------------------------+
1 row in set (0.00 sec)

MariaDB [(none)]> SELECT ENCRYPT('p@ssW0rd', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16)));
+------------------------------------------------------------------------------------------------------------+
| ENCRYPT('p@ssW0rd', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16)))                                            |
+------------------------------------------------------------------------------------------------------------+
| $6$0edfe4f3541e5035$kYDyVhQ2sEHDlZE2GsNX0s2Xstg8z7Mj.D3ly.A0DzItg/5WIGoZldKQ0uSiaW9X/ljmmjGbWkMJwsY/WZ4/p. |
+------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

这很烦人,因为我想从命令行插入密码字段不为空的表中:

$ mysql -u root -ppass  -Bse "INSERT INTO servermail.virtual_users (id, domain_id, password , email) VALUES ('1', '1', ENCRYPT('s1perP@$$', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'new@user.com');"
ERROR 1048 (23000) at line 1: Column 'password' cannot be null
$ "INSERT INTO servermail.virtual_users (id, domain_id, password , email) VALUES ('1', '1', ENCRYPT('s1perP@$$', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'new@user.com');" | mysql -u root -ppass
ERROR 1048 (23000) at line 1: Column 'password' cannot be null

【问题讨论】:

  • 我在一个循环中执行了大约 6000 次 SELECT ENCRYPT("p@ssW0rd", CONCAT("$6$", SUBSTRING(SHA(RAND()), -16))) 并且从不一个空值。这是不可能的,因为 RAND() 不应该返回 null。
  • 你是在bash命令行还是mysql命令行中执行的?就我而言,Ubuntu 16.04 LTS Mariadb 15.1,每次都返回 null

标签: mysql passwords mariadb digital-ocean crypt


【解决方案1】:

首先:不要使用 MySQL ENCRYPT() 函数。通过使用它,您会将未加密的密码发送到您的数据库服务器,这可能会使它们受到威胁(特别是如果您的数据库服务器位于远程计算机上)。它在 MySQL 的未来版本中将不再可用,因此在新应用程序中使用它是不明智的。

第二:如果你不顾我的警告而使用ENCRYPT() 函数,你需要了解它是如何使用salt 参数的。随机选择的值不太可能是有效的,特别是如果它们包含非 ASCII 字符,如ñ,并且会导致函数返回 NULL。如果您没有盐,请忽略该参数以使用随机生成的盐,而不是尝试自己生成盐。

【讨论】:

  • 谢谢。我正在按照digitalocean.com/community/tutorials/… 的教程安装 dovecot 和 postfix。所以密码要被dovecot使用。是否有另一种加密密码的方法,以便 dovecot 可以读取它们?另一个问题是我在最后一种情况下随机生成密码(不包含ñ)。如果不随机生成,dovecot能匹配密码吗(留下mysql生成的salt)?
  • @duskwuff: MySQL encryt() 正在使用 Unix crypt() - 离开 salt 参数会导致 crypt() 创建一个现在完全不安全的旧式 DES 哈希密码。您必须通过 $6$ 来指示 SHA2-512 哈希。 SELECT 应该没问题。
【解决方案2】:

@David 指向正确的方向:您的问题与 MySQL 无关 - 您只是没有正确使用 Shell 转义!

"crypt('$6', ..." 由 Shell 评估为 "crypt('', ..." 以及 "crypt('6', ..." 被视为传统的DES盐。

"crypt('$6$', ..." 被评估为 "crypt('$', ..." 给出 NULL,因为 "$" 不是盐的有效字符。

对于第一个例子,如果盐不是以“$”开头的,它被认为是传统的DES盐,只取前两个字符。它们必须是 [a-zA-Z0-9./]。因此,第一个特殊字符给出 NULL,但在第三个示例中它们无关紧要。

有关盐的更多信息,请参见 crypt(3) 手册页。

[编辑:] 编写命令的更好方法: a) 引用 $ 字符:

  mysql -Bse "SELECT ENCRYPT('p@ssW0rd', CONCAT('\$6\$', SUBSTRING(SHA(RAND()), -16)));"

b) 在 shell 中使用单引号,在 SQL 中使用双引号,即使这对 SQL 标准并不严格(MySQL 接受它,Postgres 不会)

  mysql -Bse 'SELECT ENCRYPT("p@ssW0rd", CONCAT("$6$", SUBSTRING(SHA(RAND()), -16)));'

c) 将 SQL 写入文件并使用

   mysql < my.sql

【讨论】:

  • 好点!你知道正确的 shell 表达式是怎样的吗?谢谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 2012-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
相关资源
最近更新 更多