关于安全:PHP密码的安全哈希和salt

Secure hash and salt for PHP passwords

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

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

我正在使用PHP。我想要一个安全快速的密码加密系统。将密码散列一百万次可能更安全,但也更慢。如何在速度和安全之间取得良好的平衡?另外,我希望结果有一个常量字符。

  • 哈希机制必须在PHP中可用
  • 它必须是安全的
  • 它可以用盐(在这种情况下,所有的盐都一样好吗?有没有办法产生好的盐?)
  • 另外,我应该在数据库中存储两个字段吗(例如,一个使用MD5,另一个使用SHA)?它会使它更安全还是不安全?

    如果我不够清楚,我想知道要使用哪个哈希函数,以及如何选择一个好的盐,以便有一个安全和快速的密码保护机制。

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

    在PHP中sha和md5有什么区别简单密码加密存储ASP.NET密钥和密码的安全方法如何在Tomcat5.5中实现salted密码?


    DISCLAIMER: This answer was written in 2008.

    Ok.

    Since then, PHP has given us password_hash and password_verify and, since their introduction, they are the recommended password hashing & checking method.

    Ok.

    The theory of the answer is still a good read though.

    Ok.

    DR不应该做的

    • 不要限制用户可以输入的密码字符。只有白痴才会这么做。
    • 不要限制密码的长度。如果你的用户想要一个包含超级脆弱性的句子,不要阻止他们使用它。
    • 不要以纯文本形式存储用户密码。
    • 除非用户的密码丢失,并且您发送了一个临时密码,否则不要向用户发送电子邮件。
    • 永远不要以任何方式记录密码。
    • 不要用sha1或md5甚至sha256散列密码!现代的饼干可以超过每秒600亿和1800亿个哈希。
    • 不要将bcrypt和hash()的原始输出混合使用,要么使用十六进制输出,要么使用base64_编码。(这适用于任何可能包含恶意\0的输入,这会严重削弱安全性。)

    DOS

    • 如果可以,可以使用scrypt;如果不能,请使用bcrypt。
    • 如果不能将bcrypt或scrypt与sha2哈希一起使用,请使用pbkdf2。
    • 当数据库被破坏时,重置所有人的密码。
    • 实现一个合理的8-10字符最小长度,再加上至少需要1个大写字母、1个小写字母、一个数字和一个符号。这将提高密码的熵,从而使其更难破解。(参见"什么是好密码?"进行辩论。)

    为什么还要散列密码?

    哈希密码背后的目标很简单:通过危害数据库来防止恶意访问用户帐户。因此,密码散列的目标是通过花费大量的时间或金钱来计算纯文本密码来阻止黑客或破解者。时间/成本是你的武器库中最好的威慑力。好的。

    另一个你想要一个好的、健壮的用户帐户哈希的原因是给你足够的时间来更改系统中的所有密码。如果数据库受到破坏,您将需要足够的时间至少锁定系统,如果不更改数据库中的每个密码。好的。

    Jeremiah Grossman,Whitehat Security的首席技术官,在最近一次密码恢复后在他的博客上说,这需要暴力破解他的密码保护:好的。

    Interestingly, in living out this nightmare, I learned A LOT I didn’t know about password cracking, storage, and complexity. I’ve come to appreciate why password storage is ever so much more important than password complexity. If you don’t know how your password is stored, then all you really can depend upon is complexity. This might be common knowledge to password and crypto pros, but for the average InfoSec or Web Security expert, I highly doubt it.

    Ok.

    (强调我的)好的。什么样的密码才是好密码?

    熵。(我并不完全赞同兰德尔的观点。)好的。

    简而言之,熵就是密码中的变化量。当密码只有小写罗马字母时,只有26个字符。变化不大。字母数字密码更好,有36个字符。但是,允许使用带符号的大小写大约是96个字符。这比写信好多了。一个问题是,为了让密码更容易记住,我们插入了减少熵的模式。哎呀!好的。

    密码熵很容易估计。使用完整的ASCII字符范围(大约96个可打印字符),每个字符的熵为6.6,对于未来的安全性来说,密码的8个字符的熵仍然太低(52.679位熵)。但好消息是:更长的密码和使用Unicode字符的密码确实会增加密码的熵,使其更难破解。好的。

    密码熵在加密堆栈交换站点上的讨论时间更长。一个好的谷歌搜索也会产生很多结果。好的。

    在评论中,我和@popowdeade谈过,他指出,使用x长x多个字母、数字、符号等密码策略,实际上可以通过使密码方案更具可预测性来降低熵。我同意。随机性,尽可能的随机性,总是最安全但最难记住的解决方案。好的。

    据我所知,世界上最好的密码是catch-22。要么它不值得记忆,要么太容易预测,要么太短,要么太多Unicode字符(在Windows/Mobile设备上很难键入),要么太长,等等。没有真正适合我们的密码,所以我们必须像在诺克斯堡一样保护它们。好的。最佳实践

    Bcrypt和Scrypt是当前的最佳实践。在时间上,scrypt将比bcrypt更好,但它还没有将Linux/Unix或WebServers作为标准来采用,也没有对其算法进行深入的评论。但尽管如此,该算法的未来还是有希望的。如果您使用Ruby,那么有一个scrypt gem可以帮助您解决问题,node.js现在有自己的scrypt包。您可以通过scrypt扩展或libnadium扩展在php中使用scrypt(两者都可以在pecl中使用)。好的。

    如果您想了解如何使用bcrypt,或者找到一个好的包装器,或者使用phpass之类的东西来实现更遗留的实现,我强烈建议您阅读crypt函数的文档。如果不是15到18发,我建议至少12发BCRYPT。好的。

    当我了解到BCRYPT只使用河豚的关键计划时,我改变了使用BCRYPT的想法,它有一个可变的成本机制。后者允许您通过增加河豚已经很昂贵的密钥调度来增加强制密码的成本。好的。一般做法

    我几乎再也无法想象这种情况了。phpass支持php 3.0.18到5.3,因此它可以用于几乎所有可能的安装,如果您不确定您的环境是否支持bcrypt,应该使用它。好的。

    但是假设您根本不能使用bcrypt或phpass。那么呢?好的。

    尝试使用环境/应用程序/用户感知所能容忍的最大轮数来实现PDKBF2。我推荐的最低数量是2500发。此外,如果hash_hmac()可用于使操作更难重现,请确保使用它。好的。未来的实践

    进入php 5.5是一个完整的密码保护库,它抽象了使用bcrypt的任何痛苦。虽然我们中的大多数人在最常见的环境中,特别是共享主机中都坚持使用php 5.2和5.3,但@ircmaxell已经为即将到来的API构建了一个兼容层,该层向后兼容php 5.3.7。好的。密码学摘要和免责声明

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

    您不可能预见到所有的威胁或攻击途径,因此您必须尽最大努力保护您的用户。如果你不这样做,那么你可能会错过被攻击的事实,直到为时已晚…你有责任。为了避免这种情况,首先要表现得多疑。攻击您自己的软件(内部)并尝试窃取用户凭据,或修改其他用户的帐户或访问其数据。如果你不测试你的系统的安全性,那么你不能责怪任何人,除了你自己。好的。

    最后:我不是密码学家。我所说的一切都是我的观点,但我碰巧认为这是基于良好的常识…还有大量的阅读。记住,尽可能的偏执,使事情尽可能的难以侵入,然后,如果你仍然担心,联系一个白帽黑客或密码学家,看看他们怎么说你的代码/系统。好的。好啊。


    一个更简短、更安全的答案——根本不要编写自己的密码机制,使用一个经过考验的机制。

    • php 5.5或更高版本:password_hash()质量好,是php核心的一部分。
    • 旧的PHP版本:OpenWall的phpass库比大多数用于WordPress、Drupal等的自定义代码要好得多。

    大多数程序员只是没有专业知识来安全地编写与加密相关的代码而不引入漏洞。

    快速自我测试:什么是密码扩展,应该使用多少次迭代?如果你不知道答案,你应该使用password_hash(),因为密码扩展现在是密码机制的一个关键特性,因为CPU更快,并且使用gpus和fpgas以每秒数十亿次的速度破解密码(使用gpus)。

    例如,您可以使用安装在5台台式电脑中的25 gpu在6小时内破解所有8个字符的Windows密码。这是一种野蛮的强制操作,即枚举和检查每个8个字符的Windows密码,包括特殊字符,而不是字典攻击。那是在2012年,到2018年,你可以用更少的GPU,或者用25个GPU更快地破解。

    在普通CPU上运行的Windows密码也有很多彩虹表攻击,而且速度非常快。所有这些都是因为Windows仍然不会修改或扩展其密码,即使是在Windows10中,也不要像微软那样犯同样的错误!

    参见:

    • 回答得很好,更多的是为什么password_hash()phpass是最好的方式。
    • 好的博客文章为主要算法(包括bcrypt、scrypt和pbkdf2)推荐了"工作因子"(迭代次数)。


    我不会以两种不同的方式存储散列的密码,因为这样的话,系统至少和使用中的散列算法中最弱的一样弱。


    从php5.5开始,php具有简单、安全的密码散列和验证函数、密码_hash()和密码_verify()。

    1
    2
    3
    4
    5
    6
    7
    $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()时,它生成一个随机的salt,并将其包含在输出的哈希(连同使用的成本和算法)中。password_verify()然后读取该哈希并确定使用的salt和加密方法,并根据提供的明文密码对其进行验证。

    提供PASSWORD_DEFAULT指示php使用安装的php版本的默认散列算法。准确地说,在未来的版本中,这意味着哪种算法会随着时间的推移而改变,因此它将始终是最强大的可用算法之一。

    增加成本(默认值为10)会使哈希更难强制执行,但也意味着生成哈希并根据它们验证密码对服务器的CPU来说将更为有效。

    注意,尽管默认的哈希算法可能会改变,但旧的哈希将继续验证,因为所使用的算法存储在哈希中,并且password_verify()会接受它。


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

    更多解释请访问-http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/

    Recently I had a discussion whether password hashes salted with random
    bits are more secure than the one salted with guessable or known
    salts. Let’s see: If the system storing password is compromised as
    well as the system which stores the random salt, the attacker will
    have access to hash as well as salt, so whether the salt is random or
    not, doesn’t matter. The attacker will can generate pre-computed
    rainbow tables to crack the hash. Here comes the interesting part- it
    is not so trivial to generate pre-computed tables. Let us take example
    of WPA security model. Your WPA password is actually never sent to
    Wireless Access Point. Instead, it is hashed with your SSID (the
    network name- like Linksys, Dlink etc). A very good explanation of how
    this works is here. In order to retrieve password from hash, you will
    need to know the password as well as salt (network name). Church of
    Wifi has already pre-computed hash tables which has top 1000 SSIDs and
    about 1 million passwords. The size is of all tables is about 40 GB.
    As you can read on their site, someone used 15 FGPA arrays for 3 days
    to generate these tables. Assuming victim is using the SSID as
    "a387csf3″ and password as"123456″, will it be cracked by those
    tables? No! .. it cannot. Even if the password is weak, the tables
    don’t have hashes for SSID a387csf3. This is the beauty of having
    random salt. It will deter crackers who thrive upon pre-computed
    tables. Can it stop a determined hacker? Probably not. But using
    random salts does provide additional layer of defense. While we are on
    this topic, let us discuss additional advantage of storing random
    salts on a separate system. Scenario #1 : Password hashes are stored
    on system X and salt values used for hashing are stored on system Y.
    These salt values are guessable or known (e.g. username) Scenario#2 :
    Password hashes are stored on system X and salt values used for
    hashing are stored on system Y. These salt values are random. In case
    system X has been compromised, as you can guess, there is a huge
    advantage of using random salt on a separate system (Scenario #2) .
    The attacker will need to guess addition values to be able to crack
    hashes. If a 32 bit salt is used, 2^32= 4,294,967,296 (about 4.2
    billion) iterations will can be required for each password guessed.


    我只想指出,php 5.5包含一个密码散列API,它提供了一个围绕crypt()的包装。此API显著简化了哈希、验证和重新刷新密码哈希的任务。作者还为那些使用php 5.3.7及更高版本的用户发布了一个兼容性包(以单个password.php文件的形式,您只需使用require即可),并希望现在就使用它。

    它目前只支持bcrypt,但是它的目标是很容易扩展到包含其他密码散列技术,并且由于技术和成本存储在散列中,对首选散列技术/成本的更改不会使当前散列失效,框架将自动,在验证时使用正确的技术/成本。如果您没有明确定义自己的盐,它还处理生成"安全"盐。

    API公开了四个函数:

    • password_get_info()—返回给定哈希的信息
    • password_hash()-创建密码哈希
    • password_needs_rehash()-检查给定哈希是否与给定选项匹配。有助于检查哈希是否符合您当前的技术/成本方案,允许您在必要时重新刷新
    • password_verify()—验证密码是否与哈希匹配

    目前,这些函数接受密码crypt和密码u默认密码常量,这是目前的同义词,区别在于密码u默认值"在支持更新的、更强的哈希算法时,可能会在更新的PHP版本中发生更改。"在登录时使用密码u默认值和密码u需要u rehash()(如果需要,还需要重新刷新)SSARY)应该确保您的散列能够合理地抵御蛮力攻击,而对您来说几乎没有工作。

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


    我使用的是phpass,它是一个简单的单文件php类,可以很容易地在几乎每个php项目中实现。也见H。

    默认情况下,它使用了在phpass中实现的最强的可用加密,即bcrypt,并返回到其他加密中,最后返回到md5,以提供对WordPress等框架的向后兼容性。

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

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

    要验证密码,可以使用:

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

    要记住的东西好的。

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

    服务器好的。

    端口好的。

    不管你的加密有多好,如果你没有正确地保护运行php和db的服务器,你所有的努力都是毫无价值的。大多数服务器的运行方式相对相同,它们都分配了端口,允许您通过ftp或shell远程访问它们。确保更改了远程连接的默认端口。不这样做实际上使攻击者在访问系统时少做一步。好的。

    用户名好的。

    对于世界上所有好的东西,不要使用用户名admin、root或类似的东西。另外,如果您使用的是基于Unix的系统,那么不要让根帐户登录成为可访问的,它应该始终是sudo-only。好的。

    密码好的。

    你告诉你的用户要做好密码以避免被黑客攻击,也要这样做。当你的后门敞开的时候,通过锁前门的所有努力有什么意义呢?好的。

    数据库好的。

    服务器好的。

    理想情况下,您希望数据库和应用程序位于不同的服务器上。由于成本原因,这并不总是可能的,但它允许一些安全性,因为攻击者必须通过两个步骤才能完全访问系统。好的。

    用户好的。

    始终让您的应用程序拥有自己的帐户来访问数据库,并且只授予它所需的特权。好的。

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

    就像永远不要做这个根或类似的东西。好的。

    密码好的。

    遵循与所有好密码相同的准则。同样,不要在同一系统上的任何服务器或数据库帐户上重复使用相同的密码。好的。

    PHP好的。

    密码好的。

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

    哈希好的。

    单向散列!!!!!!!!!!,不要以可以反转的方式散列密码,散列应该是一种方式,也就是说,不要反转密码并将其与密码进行比较,而是以相同的方式散列输入的密码并比较这两个散列。这意味着,即使攻击者能够访问数据库,他也不知道实际密码是什么,只知道其结果散列值。这意味着在最坏的情况下,您的用户可以获得更高的安全性。好的。

    有很多很好的散列函数(password_hashhash等),但是您需要选择一个好的算法才能使散列有效。(Bcrypt和类似的算法都是不错的算法。)好的。

    当散列速度是关键时,越慢,对蛮力攻击的抵抗力就越强。好的。

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

    腌制好的。

    密码应该在散列之前被加盐。Salting为密码添加了一个随机字符串,这样类似的密码在数据库中就不会出现相同的情况。但是,如果盐对每个用户都不是唯一的(即,使用硬编码的盐),那么您的盐就几乎没有价值了。因为一旦攻击者发现一个密码salt,他就拥有所有密码的salt。好的。

    当您创建一个salt时,请确保它对密码是唯一的,它是salt,然后将完成的hash和salt都存储在数据库中。这样做的目的是使攻击者在获得访问权限之前必须单独破解每个salt和hash。这意味着攻击者需要更多的工作和时间。好的。

    用户创建密码好的。

    如果用户通过前端创建密码,则意味着必须将其发送到服务器。这就打开了一个安全问题,因为这意味着未加密的密码将被发送到服务器,如果攻击者能够监听和访问,那么您在PHP中的所有安全都是无用的。始终安全地传输数据,这是通过ssl完成的,但即使ssl也不是完美无缺的(openssl令人心碎的缺陷就是一个例子)。好的。

    还可以让用户创建一个安全的密码,它很简单,应该总是这样做,最终用户会感激它的。好的。

    最后,无论您采取什么样的安全措施都是100%安全的,保护技术越先进,攻击就越先进。但是,遵循这些步骤将使您的站点更安全,而且攻击者更不希望攻击您的站点。好的。

    下面是一个PHP类,它可以轻松地为密码创建哈希和salt好的。

    网址:http://git.io/msjqpw好的。好啊。


    谷歌表示,Sha256可用于PHP。

    你一定要用盐。我建议使用随机字节(不要把自己局限于字符和数字)。通常,你选择的时间越长,越安全,速度越慢。我想64字节应该可以。


    我在这里找到了这个问题的完美主题:https://crackstation.net/hashing-security.htm,我想让您从中受益,这里还有源代码,它还提供了防止基于时间的攻击的功能。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    <?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));
    }
    ?>


    最后,从数学上讲,双重散列没有任何好处。然而,在实践中,它对于防止基于彩虹表的攻击很有用。换句话说,它只不过是使用salt进行散列,这样在应用程序或服务器上花费的处理器时间要少得多。


    我通常将sha1和salt与用户ID(或其他一些特定于用户的信息)一起使用,有时我还使用常量salt(所以我对salt有两个部分)。

    Sha1现在也被认为是有所妥协,但程度远低于MD5。通过使用salt(任何salt),您将阻止使用通用彩虹表攻击哈希(有些人甚至通过搜索哈希成功地将google用作彩虹表)。攻击者可能会使用您的salt生成一个彩虹表,因此您应该包含一个特定于用户的salt。这样,他们就必须为系统中的每个记录生成一个彩虹表,而不仅仅是整个系统的一个记录!有了这种类型的盐渍,即使MD5也相当安全。


    在可预见的将来,sha1和salt应该足够了(当然,这取决于您是为诺克斯堡编写代码,还是为您的购物清单编写登录系统)。如果sha1不适合您,请使用sha256。

    可以说,盐的概念是把散列结果抛到一边。例如,已知空字符串的MD5哈希是d41d8cd98f00b204e9800998ecf8427e。因此,如果有足够好的内存的人会看到这个散列,并知道它是空字符串的散列。但是,如果字符串是加盐的(例如,使用字符串"EDOCX1"(1)),则"空字符串"(即"EDOCX1"(1))的散列将变为aeac2612626724592271634fb14d3ea6,因此不明显可进行回溯。我想说的是,用盐总比不用盐好。因此,知道使用哪种盐并不太重要。

    实际上,有些网站就是这样做的——你可以给它输入一个(md5)散列,然后它输出一个已知的明文来生成特定的散列。如果您可以访问存储普通MD5散列的数据库,那么您只需输入散列,管理员就可以登录到这样的服务。但是,如果密码被加盐,这样的服务将变得无效。

    此外,由于二次散列会减少结果空间,因此通常认为它是一种糟糕的方法。所有流行的哈希都是固定长度的。因此,您只能有一个固定长度的有限值,并且结果的变化会更小。这可以看作是另一种盐腌方式,但我不推荐。


    好啊我们需要盐盐必须是独一无二的所以让我们生成它

    1
    2
    3
    4
    5
    6
    7
    8
    9
       /**
         * Generating string
         * @param $size
         * @return string
         */

        function Uniwur_string($size){
            $text = md5(uniqid(rand(), TRUE));
            RETURN substr($text, 0, $size);
        }

    我们还需要土豆泥我用的是sha512它是最好的,而且是用PHP编写的

    1
    2
    3
    4
    5
    6
    7
    8
       /**
         * Hashing string
         * @param $string
         * @return string
         */

        function hash($string){
            return hash('sha512', $string);
        }

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 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变量保存到数据库中。

    对于授权,我们将使用相同的步骤…

    这是保护客户密码的最佳方法…

    另外,对于最后两个步骤,您可以使用自己的算法…但请确保以后可以生成这个哈希密码当您需要授权用户时…