【问题标题】:mysql sha1 encryption for whole password column整个密码列的mysql sha1加密
【发布时间】:2014-03-26 23:24:36
【问题描述】:

我在 phpmyadmin 中有一个包含用户名和密码的表,但密码字段未加密。我想将密码字段的整个列加密为 SHA1 格式。知道该怎么做吗?

【问题讨论】:

    标签: php mysql sha1


    【解决方案1】:

    首先,请阅读How to securely hash passwords?

    然后您可以寻找要使用的 PHP PBKDF2、Bcrypt 或 Scrypt 实现。

    在数据库中,您需要:

    • 盐的列 - 可能是 BINARY(16) 用于 128 位盐。请参阅What is the correct way to make a password salt? - Adnan 的回答特别包括 PHP 函数,但如果您使用 bin2hex,则需要一个 CHAR(32) 列来存储 32 个十六进制字符(与 16 个二进制字节相同)。
    • 迭代计数(工作因子)列。 INT UNSIGNED 应该可以工作。
      • 如果您坚持单次迭代(即 sha1(password)),则不再需要这样做,但您没有使用安全密码存储机制。不要那样做。
      • 可以对此进行硬编码,但以后很难增加它。通过列,您可以在数据库中拥有许多不同的迭代计数/工作因素,并在用户登录时透明地增加它们。
      • 对于 PBKDF2,从数万开始,然后逐步完善。对于所有这些,增加直到略低于您将收到投诉/受 CPU 约束的预期增长。购买新硬件时增加。
    • 结果哈希本身的列。
      • 对于 PBKDF2-HMAC-SHA-1,BINARY(20) 是 SHA-1 的本机大小
      • 对于 PBKDF2-HMAC-SHA-512,BINARY(64) 是 SHA-512 的原始大小。
        • BINARY(20) 仍将优于 PBKDF2-HMAC-SHA-1 中的相同 20,因为 SHA-512 需要 64 位操作,目前这会降低攻击者的 GPU 对 CPU 的优势幅度。李>
      • 或者,对于使用 bin2hex 的任何这些 CHAR(二进制存储大小的两倍)
      • 永远不要为 PBKDF2 使用大于本机哈希大小(如上所列)的输出大小,否则这是对防御者的免费奖励。
    • 可选:您正在使用的密码保护的“版本”列,以便您以后可以轻松升级到另一个版本。 TINYINT UNSIGNED 应该很好用,在这里。

    如果你真的喜欢(并且不推荐),你可以创建一个类似PBKDF2 的 MySQL 实现,并且由于 MySQL 5.5.5 及更高版本有一个SHA-512 function,你也许可以使用一个@以 987654326@ 为例,但请务必对照known test vectors 进行验证。

    【讨论】:

      【解决方案2】:

      此时甚至不要单独使用 SHA-1 哈希,它本身被认为不够安全。

      查看来自 OWASP 的Password Storage Cheat Sheet。除了为每个用户使用唯一的盐对密码进行加盐之外,您还应该使用更强大的加密功能。

      如果你有 PHP 5.5,你可以使用 PHP 的 password_hash() 函数,它使用 bcrypt 算法,或者如果你没有 PHP 5.5,你可以使用 ircmaxell 的 PHP implementation

      如果此时您只使用 SHA-1,您甚至不必费心,因为您数据库中的大多数密码可能已经在 SHA-1 彩虹表中。

      要更新您的数据库,请编写一个简短的 PHP 脚本来读取数据库中的每个密码,应用散列函数,然后使用新的散列密码更新该行。然后修改您的注册和登录函数以在将输入的密码与存储在数据库中的密码进行比较时使用新的哈希函数。

      【讨论】:

        【解决方案3】:

        你也应该对你的密码加盐:https://crackstation.net/hashing-security.htm

        【讨论】:

          【解决方案4】:

          对于今天的安全标准,我会这样做:

          1. 向表中添加 4 个字段(哈希、盐、迭代、算法)
          2. 使用来自crackstation 的代码来散列和验证您的密码

          用法很简单:

          $plain_password="messi";
          
          $hash=create_hash($plain_password);
          

          $hash 是一个数组,包含您需要保存到数据库的所有数据

          array(4) {
            [0]=>
            string(6) "sha256"
            [1]=>
            string(4) "1000"
            [2]=>
            string(32) "wJnwu2uA4rVdW8Momz3CgS8W7MdEmaLH"
            [3]=>
            string(32) "0g2b0ZrpnObAx6z1L/8g8PPNbTG+92BI"
          }
          

          将其保存到数据库中,下次您必须将这些值检索为:

          SELECT 
          CONCAT(password_algo, ":" ,password_iteration,":" , password_salt,":" , password_hash)
          FROM users WHERE userEmail='messi@argentina.com';
          

          在验证函数中使用字符串结果

          validate_password($password_to_validate, $stored_hash_from_db)
          

          如果有效,您将得到 True,否则为 False。

          【讨论】:

            【解决方案5】:
            update mytable set password=sha1(password)
            

            您至少应该验证列定义是否能够容纳 40 个字符,否则会使情况变得更糟。

            我希望您知道,从那时起,您还应该在发送和/或与数据库比较之前重写您的代码以加密密码。

            【讨论】:

            • 感谢您的帮助。
            • 这只是个坏建议。我对糟糕的安全建议毫不留情。这比没有建议更糟糕,因为它会让你直接陷入不安全的 tdwtf 值得代码的狮子巢穴。
            • 是的,我以前见过这种赞助。 “我不会回答你的问题,因为我的神秘知识在新手手中是不安全的”。这有助于营造友好用户群的氛围,不是吗?
            猜你喜欢
            • 2011-03-03
            • 2012-06-26
            • 1970-01-01
            • 1970-01-01
            • 2015-08-26
            • 2015-08-05
            • 1970-01-01
            • 1970-01-01
            • 2019-09-09
            相关资源
            最近更新 更多