提问



目前据说MD5部分不安全。考虑到这一点,我想知道用于密码保护的机制。


这个问题,双重哈希密码是否比仅仅哈希一次更安全?
建议多次散列可能是一个好主意,而如何实现单个文件的密码保护?建议使用盐。


我使用的是PHP。我想要一个安全快速的密码加密系统。一百万次密码可能更安全,但也更慢。如何在速度和安全性之间取得良好的平衡?另外,我更喜欢结果具有恒定数量的字符。



  1. 散列机制必须在PHP中可用

  2. 一定是安全的

  3. 它可以使用盐(在这种情况下,所有的盐都同样好吗?有没有办法产生好的盐?)



另外,我应该在数据库中存储两个字段(例如,一个使用MD5,另一个使用SHA)?它会使它更安全或更不安全吗?


如果我不够清楚,我想知道使用哪种散列函数以及如何选择好的盐以便拥有安全快速的密码保护机制。


相关问题并不完全涵盖我的问题:


PHP中SHA和MD5的区别是什么?
简单密码加密

安装密钥的安全方法,asp.net的密码

你将如何在Tomcat 5.5中实现盐渍密码

最佳参考



  免责声明:这个答案写于2008年。

  
  从那时起,PHP给了我们password_hashpassword_verify,并且,自从他们的介绍,他们是推荐的密码哈希&检查方法。[37] [38]

  
  答案的理论仍然是一个很好的阅读。



TL; DR



唐TS




  • 不要限制用户可以输入密码的字符。只有白痴才能这样做。

  • 不要限制密码的长度。如果您的用户想要一个带有supercalifragilisticexpialidicious的句子,请不要阻止他们使用它。

  • 切勿以纯文本格式存储用户密码。

  • 永远不要将密码通过电子邮件发送给您的用户,除非他们丢失了密码,并且您发送了一个临时密码。

  • 永远不要以任何方式记录密码。

  • 绝不使用SHA1或MD5甚至SHA256哈希密码!现代黑客可以分别超过60和1800亿哈希/秒(
  • )
  • 不要混淆bcrypt和hash()的 raw 输出,要么使用十六进制输出,要么使用base64_encode它。(这适用于任何可能有流氓\0的输入它会严重削弱安全性。)



待办事项




  • 尽可能使用scrypt; bcrypt,如果你不能。

  • 如果您不能使用带有SHA2哈希值的bcrypt或scrypt,请使用PBKDF2。

  • 在数据库遭到入侵时重置所有人的密码。

  • 实现合理的8-10个字符的最小长度,另外需要至少1个大写字母,1个小写字母,数字和符号。这将改善密码的熵,从而使其更难破解。 (请参阅什么是一个好的密码?部分进行一些辩论。)



为什么哈希密码呢?



哈希密码背后的目标很简单:通过破坏数据库来防止恶意访问用户帐户。因此,密码散列的目标是通过花费太多时间或金钱来计算明文密码来阻止黑客或黑客。时间/成本是你军火库中最好的威慑力量。[39] [40] [41]


您希望在用户帐户上使用良好,健壮的哈希的另一个原因是为您提供足够的时间来更改系统中的所有密码。如果您的数据库遭到入侵,则需要足够的时间来最少锁定系统,如果不更改数据库中的每个密码。


Whitehat Security首席技术官Jeremiah Grossman在最近的密码恢复后在他的博客上表示,他需要暴力破解他的密码保护:[42]



  有趣的是,在实现这个噩梦的过程中,我学到了很多关于密码破解,存储和复杂性的知识。 我开始意识到为什么密码存储比密码复杂性更重要。如果您不知道密码是如何存储的,那么您真正依赖的就是复杂性。这可能是密码和加密专业人员的常识,但对于普通的InfoSec或Web安全专家,我非常怀疑它。



(强调我的。)


究竟是什么使好的密码?



熵。 (并不是说我完全赞同兰德尔的观点。)[43]


简而言之,熵是密码内的变化程度。当密码只是小写罗马字母时,只有26个字符。这不是很大的变化。字母数字密码更好,有36个字符。但允许使用符号的大写和小写大约是96个字符。这比信件要好得多。一个问题是,为了让我们的密码令人难忘,我们插入模式 - 这会减少熵。哎呀!


密码熵很容易近似。使用全范围的ascii字符(大约96个可键入的字符)产生每个字符6.6的熵,对于未来的安全性,密码的8个字符仍然太低(52.679位的熵)。但好消息是:更长的密码和带有unicode字符的密码确实增加了密码的熵,使其更难破解。[44]


在Crypto StackExchange网站上对密码熵的讨论时间较长。一个好的谷歌搜索也会产生很多结果。[45]


在我与@popnoodles谈过的评论中,他指出强制执行 X长度的密码策略,X多个字母,数字,符号等,实际上可以通过使密码方案更具可预测性来减少熵。我同意。 Randomess尽可能真正随机,始终是最安全但最难忘的解决方案。


据我所知,制作世界上最好的密码是Catch-22。它不是难忘的,太可预测的,太短的,太多的unicode字符(难以在Windows/移动设备上键入),太长时间等等。没有密码对我们的目的来说真的足够好,所以我们必须像他们一样保护他们在诺克斯堡。


最佳做法



Bcrypt和scrypt是目前的最佳实践。 Scrypt会比bcrypt及时更好,但它还没有被Linux/Unix或网络服务器采用为标准,并且还没有对其发布的算法进行过深入的评论。但是,算法的未来确实看起来很有希望。如果您正在使用Ruby,那么有一个scrypt gem可以帮助您,Node.js现在有自己的scrypt包。您可以通过Scrypt扩展或Libsodium扩展在PHP中使用Scrypt(两者都在PECL中提供)。[46] [47] [48] [49] [50] [51]


我强烈建议您阅读crypt函数的文档,如果您想了解如何使用bcrypt,或者找到一个好的包装器或使用类似PHPASS的东西来实现更多的遗留实现。我建议至少12轮bcrypt,如果不是15到18。[52] [54] [55]


当我得知bcrypt只使用河豚的关键时间表,并使用可变成本机制时,我改变了主意使用bcrypt。后者让你通过增加河豚已经很昂贵的关键时间表来增加暴力破解密码的成本。


平均做法



我几乎无法想象这种情况.PHPASS支持PHP 3.0.18到5.3,所以它几乎可用于所有可以想象的安装 - 并且如果你不知道某些你应该使用它环境支持bcrypt。[56]


但是假设您根本不能使用bcrypt或PHPASS。然后怎样呢?


尝试使用您的环境/应用程序/用户感知可以容忍的最大轮数来实现PDKBF2。我推荐的最低数字是2500轮。此外,如果可以使操作更难以重现,请确保使用hash_hmac()。[57] [58] [59]


未来实践



进入PHP 5.5是一个完整的密码保护库,它抽象出使用bcrypt的任何痛苦。虽然我们大多数人在大多数常见环境(特别是共享主机)中都坚持使用PHP 5.2和5.3,但@ircmaxell已经为即将推出的API向PHP 5.3.7构建了一个兼容层。[60] [61]]]


密码学回顾&声明



实际破解散列密码所需的计算能力并不存在。计算机破解密码的唯一方法是重新创建密码并模拟用于保护密码的散列算法。哈希与其强制攻击的能力线性相关。更糟糕的是,大多数哈希算法可以很容易地并行化以便更快地执行。这就是为什么像bcrypt和scrypt这样昂贵的方案如此重要的原因。


您无法预见所有威胁或攻击途径,因此您必须尽最大努力保护您的用户预先。如果你不这样做,那么你甚至可能会错过这样一个事实:你被攻击直到为时已晚...... 并且你负有责任。为了避免这种情况,首先要采取偏执行为。攻击您自己的软件(内部)并尝试窃取用户凭据,或修改其他用户的帐户或访问他们的数据。如果您不测试系统的安全性,那么除了您自己之外,您不能责怪任何人。


最后:我不是密码学家。无论我说的是我的意见,但我碰巧认为它基于良好的常识......和大量的阅读。记住,尽可能偏执,使事情尽可能难以入侵,并且然后,如果您仍然担心,请联系白帽黑客或密码学家,看看他们对您的代码/系统的看法。

其它参考1


一个更短更安全的答案 - 根本不编写自己的密码机制,使用久经考验的机制。



  • PHP 5.5或更高版本:password_hash()质量很好,是PHP核心的一部分。

  • 较旧的PHP版本:OpenWall的phpass库比大多数自定义代码要好得多 - 用于WordPress,Drupal等。



大多数程序员都没有专业知识来安全地编写加密相关代码而不会引入漏洞。[62] [63]


快速自检:什么是密码拉伸以及您应该使用多少次迭代?如果您不知道答案,则应使用password_hash(),因为密码机制的关键特性是密码机制的一个关键特性,因为CPU速度更快,并且使用GPU和FPGA以数十亿的猜测率破解密码每秒(使用GPU)。[64] [65]


例如,您可以使用5台台式机中安装的25个GPU在6小时内破解所有8个字符的Windows密码。这是强制性的,即枚举和检查每个8个字符的Windows密码,包括特殊字符,并且不是字典攻击。那是在2012年,从2018年开始,您可以使用更少的GPU,或者使用25个GPU更快地破解。[66]


对于在普通CPU上运行且非常快的Windows密码,还有许多彩虹表攻击。所有这一切都是因为即使在Windows 10中,Windows 仍然不会对其密码进行限制或扩展 - 不会像微软那样犯同样的错误![67] [68]


另见:



  • 关于为什么password_hash()phpass是最佳方式的更多答案。

  • 好的博客文章给出了主要算法的推荐工作因素(迭代次数),包括bcrypt,scrypt和PBKDF2。


其它参考2


我不会以两种不同的方式存储密码哈希值,因为那时系统至少与使用中最弱的哈希算法一样弱。 [70]

其它参考3


从PHP 5.5开始,PHP具有简单,安全的函数,用于散列和验证密码,password_hash()和password_verify()[71] [72]


$password = 'anna';
$hash = password_hash($password, PASSWORD_DEFAULT);
$expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20));

password_verify('anna', $hash); //Returns true
password_verify('anna', $expensiveHash); //Also returns true
password_verify('elsa', $hash); //Returns false


当使用password_hash()时,它会生成一个随机盐并将其包含在输出的散列中(连同使用的成本和算法。)password_verify()然后读取该散列并确定使用的盐和加密方法,并根据提供的纯文本密码进行验证。


提供PASSWORD_DEFAULT指示PHP使用已安装的PHP版本的默认哈希算法。究竟哪种算法意味着在未来版本中随时间变化,因此它将始终是最强大的可用算法之一。


增加成本(默认为10)会使哈希更难以暴力,但也意味着生成哈希并验证密码对您的服务器的CPU来说将更有用。


请注意,即使默认哈希算法可能会更改,旧哈希将继续验证,因为所使用的算法存储在哈希中,password_verify()会在其上选择。

其它参考4


虽然这个问题已得到解答,但我只想重申,用于散列的盐应该是随机的,而不是像第一个答案中建议的电子邮件地址。


有关更多说明,请访问http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/[73]



  最近我讨论了密码哈希是否随机腌制
  位比使用可猜测或已知的盐更安全
  盐。让我们看看:如果系统存储密码被泄露为
  以及存储随机盐的系统,攻击者将会
  有权访问哈希和盐,所以盐是随机的还是
  不,没关系。攻击者可以生成预先计算的
  彩虹表破解哈希。这是有趣的部分
  生成预先计算的表并不是那么简单。让我们举个例子
  WPA安全模型。您的WPA密码实际上从未发送过
  无线接入点。相反,它是用您的SSID(
  网络名称 - 如Linksys,Dlink等)。一个很好的解释如何
  这项工作就在这里。为了从哈希中检索密码,你会
  需要知道密码以及salt(网络名称)。教堂
  Wifi已经预先计算了具有前1000个SSID和的散列表
  大约100万个密码。所有表的大小约为40 GB。
  正如您可以在他们的网站上阅读的那样,有人在3天内使用了15个FGPA阵列
  生成这些表。假设受害者正在使用SSID
  a387csf3和密码为123456,会被那些人破解
  表?没有! .. 这不可以。即使密码很弱,表也是如此
  没有SSID a387csf3的哈希值。这就是拥有的美
  随机盐。它将阻止那些在预先计算中茁壮成长的破解者
  表。能阻止坚定的黑客吗?可能不会。但是使用
  随机盐确实提供了额外的防御层。我们在的时候
  这个主题,让我们讨论存储随机的额外优势
  在单独的系统上的盐。场景#1:存储密码哈希值
  在系统X上,用于散列的盐值存储在系统Y上。
  这些盐值是可猜测的或已知的(例如用户名)场景#2:
  密码哈希存储在系统X和用于的盐值上
  散列存储在系统Y上。这些盐值是随机的。以防万一
  系统X已被破坏,你可以猜测,有一个巨大的
  在单独的系统上使用随机盐的优势(场景#2)。
  攻击者需要猜测附加值才能破解
  哈希值。如果使用32位盐,则2 ^ 32=4,294,967,296(约4.2
  猜测的每个密码都需要迭代。


其它参考5


我只想指出PHP 5.5包含一个密码散列API,它提供了crypt()的包装。此API显着简化了散列,验证和重新散列密码哈希的任务。作者还发布了一个兼容包(以单个password.php文件的形式,您只需require使用),对于那些使用PHP 5.3.7及更高版本的用户,现在想要使用它。[74] [75]


它现在只支持BCRYPT,但它的目的是很容易扩展到包含其他密码散列技术,并且因为技术和成本存储为散列的一部分,对你喜欢的散列技术/成本的更改不会使当前散列无效,框架将自动化,在验证时使用正确的技术/成本。如果您没有明确定义自己的盐,它还会处理生成安全盐。


API公开了四个功能:



  • password_get_info() - 返回有关给定哈希的信息

  • password_hash() - 创建密码哈希

  • password_needs_rehash() - 检查给定的哈希值是否与给定的选项匹配。有用的检查哈希是否符合您当前的技术/成本方案,允许您在必要时重新进行重组

  • password_verify() - 验证密码是否与哈希匹配



目前这些函数接受PASSWORD_BCRYPT和PASSWORD_DEFAULT密码常量,这些密码常量目前是同义词,不同之处在于,当支持更新,更强大的哈希算法时,PASSWORD_DEFAULT可能会在较新的PHP版本中发生变化。在登录时使用PASSWORD_DEFAULT和password_needs_rehash()(并在必要时进行重新散列)应确保您的哈希值对蛮力攻击具有相当的弹性,几乎没有工作。


编辑:我刚刚意识到罗伯特K的回答中简要提到了这一点。我将在这里留下这个答案,因为我认为它提供了更多关于它是如何工作的信息以及它为那些不提供的人提供的易用性。知道安全。

其它参考6


我正在使用Phpass,它是一个简单的单文件PHP类,几乎可以在每个PHP项目中轻松实现。另见The H. [76] [77]


默认情况下,它使用Phpass中实现的最强可用加密,bcrypt并回退到MD5以外的其他加密,以向Wordpress等框架提供向后兼容性。


返回的哈希可以按原样存储在数据库中。生成哈希的示例用法是:


$t_hasher = new PasswordHash(8, FALSE);
$hash = $t_hasher->HashPassword($password);


要验证密码,可以使用:


$t_hasher = new PasswordHash(8, FALSE);
$check = $t_hasher->CheckPassword($password, $hash);

其它参考7


要记住的事情


关于PHP的密码加密已经说了很多,其中大部分是非常好的建议,但在你开始使用PHP进行密码加密的过程之前,请确保你已经实现了以下内容或准备好实现。


服务器


PORTS


无论您的加密有多好,如果您没有正确保护运行PHP和DB的服务器,您所有的努力都毫无价值。大多数服务器的功能都相同,它们分配了端口,允许您通过ftp远程访问它们确保您更改了您所处于Activity状态的远程连接的默认端口。通过不执行此操作,您实际上已使攻击者在访问系统时减少了一步。


USERNAME


对于世界上所有好的,不要使用用户名admin,root或类似的东西。此外,如果您使用的是基于unix的系统,请不要使root帐户登录可访问,它应该始终只是sudo。


PASSWORD


您告诉您的用户制作好的密码以避免被黑客入侵,同样做。当后门敞开时,通过锁定前门的所有努力有什么意义。


DATABASE


SERVER 的


理想情况下,您希望将DB和APPLICATION放在不同的服务器上。由于成本原因,这并不总是可行的,但它确实允许一定的安全性,因为攻击者必须通过两个步骤才能完全访问系统。


USER 的


始终让您的应用程序拥有自己的帐户来访问数据库,并且只为其提供所需的权限。


然后为您提供一个单独的用户帐户,该帐户不存储在服务器上的任何位置,甚至不存储在应用程序中。


像往常一样,不要使这个根或类似的东西。


PASSWORD


跟着一样所有好密码的准则。也不要在同一系统上的任何SERVER或DB帐户上重复使用相同的密码。


PHP


PASSWORD


永远不要在你的数据库中存储密码,而是存储哈希和唯一的盐,我将在后面解释原因。


HASHING


一种方式哈希!!!!!!!,永远不要以可以反转的方式哈希密码,哈希应该是一种方式,这意味着你不要反转它们并将它们与密码进行比较,而是对输入的密码进行哈希处理以同样的方式比较两个哈希值。这意味着即使攻击者可以访问数据库,他也不知道实际的密码是什么,只是它产生的哈希值。这意味着在最糟糕的情况下为您的用户提供更高的安全性。


那里有很多好的散列函数(password_hashhash等......)但是你需要选择一个好的算法来使散列有效。 (bcrypt和类似它的是不错的算法。)


当散列速度是关键时,对Brute Force攻击的抵抗力越强。


散列中最常见的错误之一是散列并非用户独有。这主要是因为盐不是唯一产生的。


盐析


在散列之前,密码应该总是被腌制。 Salting在密码中添加了一个随机字符串,因此类似的密码在DB中看起来不一样。但是如果盐对每个用户来说并不是唯一的(即:你使用的是硬编码的盐),那么你的盐就会变得毫无价值因为一旦攻击者找到一个密码盐,他就会为所有人提供盐。


创建salt时,请确保它对于密码是唯一的,然后将完成的散列和salt存储在数据库中。这样做是为了让攻击者在获得访问权限之前必须单独破解每个盐和哈希值。这意味着攻击者需要做更多的工作和时间。


用户创建密码


如果用户通过前端创建密码,则意味着必须将密码发送到服务器。这会打开一个安全问题,因为这意味着将未加密的密码发送到服务器,如果攻击者能够监听并访问,那么PHP中的所有安全性都毫无价值。总是安全地传输数据,这是通过SSL完成的,但是即使SSL也没有完美无缺(OpenSSL的Heartbleed漏洞就是这样的一个例子)。


同时让用户创建一个安全的密码,它很简单,应该永远完成,用户最终会感激它。


最后,无论您采取的安全措施是否100%安全,保护技术越先进,攻击就越先进。但是,遵循这些步骤将使您的网站更安全,而且不太可能让攻击者追求。


这是一个PHP类,可以轻松地为密码创建哈希和salt


http://git.io/mSJqpw[78]

其它参考8


谷歌称PHP可以使用SHA256。


你绝对应该使用盐。我建议使用随机字节(而不是限制自己的字符和数字)。通常,你选择的时间越长,越安全,越慢。我想64字节应该没问题。

其它参考9


我在这里找到了关于这个问题的完美主题:https://crackstation.net/hashing-security.htm,我希望你能从中受益,这里的源代码也能防止基于时间的攻击。[79]


<?php
/*
 * Password hashing with PBKDF2.
 * Author: havoc AT defuse.ca
 * www: https://defuse.ca/php-pbkdf2.htm
 */

// These constants may be changed without breaking existing hashes.
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTES", 24);
define("PBKDF2_HASH_BYTES", 24);

define("HASH_SECTIONS", 4);
define("HASH_ALGORITHM_INDEX", 0);
define("HASH_ITERATION_INDEX", 1);
define("HASH_SALT_INDEX", 2);
define("HASH_PBKDF2_INDEX", 3);

function create_hash($password)
{
    // format: algorithm:iterations:salt:hash
    $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" . 
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTES,
            true
        ));
}

function validate_password($password, $good_hash)
{
    $params = explode(":", $good_hash);
    if(count($params) < HASH_SECTIONS)
       return false; 
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
    $diff = strlen($a) ^ strlen($b);
    for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
    {
        $diff |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $diff === 0; 
}

/*
 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
 * $algorithm - The hash algorithm to use. Recommended: SHA256
 * $password - The password.
 * $salt - A salt that is unique to the password.
 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
 * $key_length - The length of the derived key in bytes.
 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
 * Returns: A $key_length-byte key derived from the password and salt.
 *
 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
 *
 * This implementation of PBKDF2 was originally created by https://defuse.ca
 * With improvements by http://www.variations-of-shadow.com
 */
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }

    if($raw_output)
        return substr($output, 0, $key_length);
    else
        return bin2hex(substr($output, 0, $key_length));
}
?>

其它参考10


最后,数学上的双重散列不会带来任何好处。然而,在实践中,它对于防止基于彩虹表的攻击是有用的。换句话说,它与使用salt进行散列相比没有什么好处,因为在您的应用程序或服务器上占用的处理器时间要少得多。

其它参考11


我通常使用SHA1和salt与用户ID(或其他一些用户特定的信息),有时我还使用恒定的盐(所以我有2份盐)。


SHA1现在也被认为有些受到损害,但程度远远低于MD5。通过使用盐(任何盐),你防止使用通用彩虹表来攻击你的哈希(有些人甚至通过搜索哈希使用谷歌作为一种彩虹表成功。)可以想象一个攻击者使用您的盐生成彩虹表,这就是为什么您应该包含用户特定的盐。这样,他们将不得不为系统中的每个记录生成彩虹表,而不仅仅是整个系统的一个!有了这种腌制,即使是MD5也是相当安全的。[80]

其它参考12


在可预见的未来,SHA1和一个盐就足够了(当然,取决于您是为Fort Knox编写代码还是为您的购物清单编写登录系统)。如果SHA1不够好,请使用SHA256。[81] [82] [83]


盐的想法是让哈希结果失去平衡,所以说。例如,已知空字符串的MD5哈希是d41d8cd98f00b204e9800998ecf8427e。所以,如果有足够好内存的人会看到那个哈希,并且知道它是空字符串的哈希值。但是如果字符串被盐析(例如,用字符串MY_PERSONAL_SALT),则哈希为空字符串(即MY_PERSONAL_SALT)变为aeac2612626724592271634fb14d3ea6,因此回溯是不明显的。我想说的是,最好使用 any

实际上有网站可以做到这一点 - 你可以提供一个(md5)哈希,并且它会吐出一个生成特定哈希的已知明文。如果您可以访问存储普通md5哈希值的数据库,那么为这样的服务输入管理员的哈希并登录将是微不足道的。但是,如果密码被腌制,这样的服务将成为无效的。[84]


此外,双散列通常被认为是不好的方法,因为它减少了结果空间。所有流行的哈希都是固定长度的。因此,您只能拥有此固定长度的有限值,并且结果变得不那么多变。这可以被视为另一种形式的腌制,但我不推荐它。

其它参考13



在适合我们需要盐
盐必须是独一无二的
所以让它生成吧


   /**
     * Generating string
     * @param $size
     * @return string
     */
    function Uniwur_string($size){
        $text = md5(uniqid(rand(), TRUE));
        RETURN substr($text, 0, $size);
    }


我们也需要哈希
我正在使用sha512
它是最好的,它是在PHP中


   /**
     * Hashing string
     * @param $string
     * @return string
     */
    function hash($string){
        return hash('sha512', $string);
    }


所以现在我们可以使用这个函数来生成安全密码


// generating unique password
$password = Uniwur_string(20); // or you can add manual password
// generating 32 character salt
$salt = Uniwur_string(32);
// now we can manipulate this informations

// hashin salt for safe
$hash_salt = hash($salt);
// hashing password
$hash_psw = hash($password.$hash_salt);


现在我们需要在数据库中保存$ hash_psw变量值和$ salt变量


并且为了授权,我们将使用相同的步骤......


这是保护客户密码的最佳方式......


附:对于最后两个步骤,您可以使用自己的算法......
但请确保您将来可以生成此哈希密码
当你需要授权用户时......