代码之家  ›  专栏  ›  技术社区  ›  Dereleased

为什么crypt/blowfish用两种不同的盐生成相同的散列?

  •  30
  • Dereleased  · 技术社区  · 14 年前

    这个问题与PHP的 crypt() . 对于这个问题,salt的前7个字符不计算在内,所以salt的 $2a$07$a

    $ “显然,是人物);这相当简单。但是,如果给定salt 20个字符和salt 21个字符,其中除21长度salt的最后一个字符外,这两个字符是相同的,则两个哈希字符串将是相同的。salt长度为22个字符,除了最后一个字符外,与salt长度为21的字符相同,哈希值也将不同。

    代码中的示例:

    $foo = 'bar';
    $salt_xx = '$2a$07$';
    $salt_19 = $salt_xx . 'b1b2ee48991281a439d';
    $salt_20 = $salt_19 . 'a';
    $salt_21 = $salt_20 . '2';
    $salt_22 = $salt_21 . 'b';
    
    var_dump(
        crypt($foo, $salt_19), 
        crypt($foo, $salt_20), 
        crypt($foo, $salt_21), 
        crypt($foo, $salt_22)
    );
    

    将产生:

    string(60) "$2a$07$b1b2ee48991281a439d$$.dEUdhUoQXVqUieLTCp0cFVolhFcbuNi"
    string(60) "$2a$07$b1b2ee48991281a439da$.UxGYN739wLkV5PGoR1XA4EvNVPjwylG"
    string(60) "$2a$07$b1b2ee48991281a439da2.UxGYN739wLkV5PGoR1XA4EvNVPjwylG"
    string(60) "$2a$07$b1b2ee48991281a439da2O4AH0.y/AsOuzMpI.f4sBs8E2hQjPUQq"
    

    编辑:

    一些用户注意到整个字符串中存在差异,这是事实。在里面 salt_20 ,偏移量(28,4)为 da$. salt_21 ,偏移量(28,4)为 da2. ; 但是,需要注意的是,生成的字符串包括散列、salt以及生成salt的指令(即。 $2a$07$ UxGYN739wLkV5PGoR1XA4EvNVPjwylG .

    因此,这实际上不是产生的散列的差异,而是用于存储散列的盐的差异,这正是当前的问题:两种盐生成相同的散列。

    Rembmer:输出将采用以下格式:

    "$2a$##$saltsaltsaltsaltsaltsaHASHhashHASHhashHASHhashHASHhash"
    //                            ^ Hash Starts Here, offset 28,32
    

    其中##是确定算法运行的迭代次数的log-base-2

    编辑2:

    var_dump(
        PHP_VERSION, 
        PHP_OS, 
        CRYPT_SALT_LENGTH, 
        CRYPT_STD_DES, 
        CRYPT_EXT_DES, 
        CRYPT_MD5, 
        CRYPT_BLOWFISH
    );
    

    生成以下输出:

    string(5) "5.3.0"
    string(5) "WINNT"
    int(60)
    int(1)
    int(1)
    int(1)
    int(1)
    

    希望这有帮助。

    4 回复  |  直到 4 年前
        1
  •  35
  •   Dereleased    14 年前

    经过一些实验,我得出结论,这是由于盐的处理方式。salt不被认为是文本,而是base64编码的字符串,因此22字节的salt数据实际上表示16字节的字符串( floor(22 * 24 / 32) == 16 )盐。“抓住你了!”不过,与Unix crypt一样,这种实现使用的是“非标准”base64字母表。确切地说,它使用以下字母表:

    ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$
    

    第65个字符,' $

    现在 crypt()

    拿一个假想的盐' 1234 '. 这是完全base64一致的,因为它表示24位的数据,即3个字节,并且不携带任何需要丢弃的数据。这是一种盐 Len Mod 4 是零。将任何字符附加到该盐后,它将成为一个5字符的盐,并且 现在为1。但是,此附加字符仅表示六位数据,因此无法转换为另一个完整字节,因此被丢弃。

       Len A Mod 4 == 0 
    && Len B Mod 4 == 1  // these two lines mean the same thing
    && Len B = Len A + 1 // but are semantically important separately
    && A == substr B, 0, Len A
    

    实际使用的盐 地穴() 实际上,计算散列值是相同的。作为证明,我提供了一些可以用来说明这一点的PHP代码示例。盐在一个周期内不断地旋转 半决赛 非随机方式(基于当前时间到微秒的漩涡散列的随机段)和要散列的数据(此处称为 $seed

    $salt = substr(hash('whirlpool',microtime()),rand(0,105),22);
    $seed = time();
    for ($i = 0, $j = strlen($salt); $i <= $j; ++$i) {
        printf('%02d = %s%s%c',
            $i,
            crypt($seed,'$2a$07$' . substr($salt, 0, $i)),
            $i%4 == 0 || $i % 4 == 1 ? ' <-' : '',
            0x0A
        );
    }
    

    00 = $2a$07$$$$$$$$$$$$$$$$$$$$$$.rBxL4x0LvuUp8rhGfnEKSOevBKB5V2. <-
    01 = $2a$07$e$$$$$$$$$$$$$$$$$$$$.rBxL4x0LvuUp8rhGfnEKSOevBKB5V2. <-
    02 = $2a$07$e8$$$$$$$$$$$$$$$$$$$.WEimjvvOvQ.lGh/V6HFkts7Rq5rpXZG
    03 = $2a$07$e89$$$$$$$$$$$$$$$$$$.Ww5p352lsfQCWarRIWWGGbKa074K4/.
    04 = $2a$07$e895$$$$$$$$$$$$$$$$$.ZGSPawtL.pOeNI74nhhnHowYrJBrLuW <-
    05 = $2a$07$e8955$$$$$$$$$$$$$$$$.ZGSPawtL.pOeNI74nhhnHowYrJBrLuW <-
    06 = $2a$07$e8955b$$$$$$$$$$$$$$$.2UumGVfyc4SgAZBs5P6IKlUYma7sxqa
    07 = $2a$07$e8955be$$$$$$$$$$$$$$.gb6deOAckxHP/WIZOGPZ6/P3oUSQkPm
    08 = $2a$07$e8955be6$$$$$$$$$$$$$.5gox0YOqQMfF6FBU9weAz5RmcIKZoki <-
    09 = $2a$07$e8955be61$$$$$$$$$$$$.5gox0YOqQMfF6FBU9weAz5RmcIKZoki <-
    10 = $2a$07$e8955be616$$$$$$$$$$$.hWHhdkS9Z3m7/PMKn1Ko7Qf2S7H4ttK
    11 = $2a$07$e8955be6162$$$$$$$$$$.meHPOa25CYG2G8JrbC8dPQuWf9yw0Iy
    12 = $2a$07$e8955be61624$$$$$$$$$.vcp/UGtAwLJWvtKTndM7w1/30NuYdYa <-
    13 = $2a$07$e8955be616246$$$$$$$$.vcp/UGtAwLJWvtKTndM7w1/30NuYdYa <-
    14 = $2a$07$e8955be6162468$$$$$$$.OTzcPMwrtXxx6YHKtaX0mypWvqJK5Ye
    15 = $2a$07$e8955be6162468d$$$$$$.pDcOFp68WnHqU8tZJxuf2V0nqUqwc0W
    16 = $2a$07$e8955be6162468de$$$$$.YDv5tkOeXkOECJmjl1R8zXVRMlU0rJi <-
    17 = $2a$07$e8955be6162468deb$$$$.YDv5tkOeXkOECJmjl1R8zXVRMlU0rJi <-
    18 = $2a$07$e8955be6162468deb0$$$.aNZIHogUlCn8H7W3naR50pzEsQgnakq
    19 = $2a$07$e8955be6162468deb0d$$.ytfAwRL.czZr/K3hGPmbgJlheoZUyL2
    20 = $2a$07$e8955be6162468deb0da$.0xhS8VgxJOn4skeI02VNI6jI6324EPe <-
    21 = $2a$07$e8955be6162468deb0da3.0xhS8VgxJOn4skeI02VNI6jI6324EPe <-
    22 = $2a$07$e8955be6162468deb0da3ucYVpET7X/5YddEeJxVqqUIxs3COrdym
    

    结论呢?双重的首先,它按预期工作,其次,知道你自己的盐或不滚你自己的盐。

        2
  •  7
  •   Community basarat    7 年前

    回答得很好,解释得很清楚。但在我看来,要么是实现中存在缺陷,要么需要对意图作进一步解释{帖子的评论解释了为什么没有缺陷}。这个 current php documentation 国家:

    返回哈希字符串或短于13个字符的字符串,并保证在失败时与salt不同。

    但正如我在答覆中所说: Dereleased substr(crypt($pw,$salt), 28, 32) ,调用方已经知道完整的salt值,因为它将该字符串作为参数传递。但是很难理解为什么返回值被设计成只能给出128位salt值中的126位。事实上,很难理解为什么它包含输入盐;但是省略其中的两个部分确实是难以理解的。

    这里有一个小片段显示,第22个base64位只为计算中实际使用的salt增加了两位(只生成了4个不同的哈希):

    $alphabet = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $lim = strlen($alphabet);
    $saltprefix = '$2a$04$123456789012345678901'; // 21 base64 digits
    
    
    for ($i = 0; $i < $lim; ++$i ) {
      if ($i = 16 || $i == 32 || $i == 48) echo "\n";
      $salt = $saltprefix . substr($alphabet, $i, 1);
      $crypt = crypt($password, $salt);
      echo "salt ='$salt'\ncrypt='$crypt'\n";
    }
    
    salt ='$2a$04$123456789012345678901.'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901/'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901A'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901B'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901C'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901D'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901E'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901F'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901G'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901H'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901I'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901J'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901K'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901L'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901M'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    salt ='$2a$04$123456789012345678901N'
    crypt='$2a$04$123456789012345678901.YpaB4l25IJ3b3F3H8trjHXj5SC1UbUW'
    
    salt ='$2a$04$123456789012345678901O'
    crypt='$2a$04$123456789012345678901Ots44xXtSV0f6zMrHerQ2IANdsJ.2ioG'
    salty='$2a$04$123456789012345678901P'
    crypt='$2a$04$123456789012345678901Ots44xXtSV0f6zMrHerQ2IANdsJ.2ioG'
    salty='$2a$04$123456789012345678901Q'
    crypt='$2a$04$123456789012345678901Ots44xXtSV0f6zMrHerQ2IANdsJ.2ioG'
      ... 13 more pairs of output lines with same hash
    
    salt ='$2a$04$123456789012345678901e'
    crypt='$2a$04$123456789012345678901e.1cixwQ2qnBqwFeEcMfNfXApRK0ktqm'
      ... 15 more pairs of output lines with same hash
    
    salt ='$2a$04$123456789012345678901u'
    crypt='$2a$04$123456789012345678901u5yLyHIE2JetWU67zG7qvtusQ2KIZhAa'
      ... 15 more pairs of output lines with same hash
    

    也许接口是为了某种兼容性而设计的,也许因为它已经以这种方式发布了,所以不能更改{文章的第一条注释解释了为什么接口是这样的}。但当然,文档应该解释发生了什么。为了防止将来某一天该错误被修复,也许使用以下方法获取哈希值最安全:

    substr(crypt($pw,$salt), -32)
    

    作为最后一个注释,当指定base64位数时,解释为什么哈希值会重复 mod 4 == 1 就为什么代码可能以这种方式运行而言,这是有意义的,但它没有解释为什么以这种方式编写代码是个好主意。在计算散列时,代码可以也可以说应该包含组成部分字节的base64位的位,而不是丢弃它们。如果代码是这样写的,那么输出中丢失salt的第22位数字的问题似乎也不会出现{正如博文的评论所解释的,即使第22位数字被覆盖,覆盖它的散列数字也只是四个可能值中的一个 [.Oeu] ,这些是第22位的唯一有效值。如果第22位不是这四个值中的一个,它将被生成相同哈希的四个值中的一个替换。}

    从评论来看,似乎没有bug,只是令人难以置信的沉默的文档:-)因为我不是一个密码学家,我不能以任何权威说这句话,但在我看来,这是算法的一个弱点,一个21位的salt显然可以产生所有可能的散列值,而22位salt将散列的第一位限制为四个值中的一个。

        3
  •  3
  •   H. Green    14 年前

    看起来输出实际上是不同的(对于盐20和盐21的结果,da$,vs da2)。

        4
  •  0
  •   Walf    12 年前

    根据我的调查,salt似乎总是22个字符,散列偏移量是29个字符,而不是28个,这使得它的长度是31个字符,而不是32个字符。我运行了以下代码:

    $pass = 'foobarbazqux';
    $salt = 'cmfh./TCmc3m0X.MnmHGO';
    $cost = 8;
    $crypt_salt = sprintf('$2a$%02d$%s', $cost, $salt);
    $chars = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    for ($i = 0; $i < strlen($chars); $i++) {
        $hash = crypt($pass, $crypt_salt . $chars[$i]);
        var_dump($crypt_salt . $chars[$i], $hash, crypt($pass, $hash));
    }
    

    结果是:

    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO."
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO/"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO0"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO1"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO2"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO3"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO4"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO5"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO6"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO7"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO8"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGO9"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOA"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOB"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOC"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOD"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOE"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOF"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOH"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOI"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOJ"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOL"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOM"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGON"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGO.t0NzWGmKpRimP4RhjFMg3F020kVKG9S"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOO"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOP"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOQ"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOR"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOS"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOT"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOU"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOV"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOW"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOX"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOY"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOZ"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOa"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOb"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOc"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOd"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOOSYI2wLIE3NElcU7itPPQnj8iW922mwy"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOe"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOf"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOg"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOh"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOi"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOj"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOk"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOl"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOm"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOn"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOo"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOp"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOq"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOr"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOs"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOt"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOeLcyQf2JnDryc7eA43zx3qi1uJKZUtPK"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOu"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOv"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOw"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOx"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOy"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(29) "$2a$08$cmfh./TCmc3m0X.MnmHGOz"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    string(60) "$2a$08$cmfh./TCmc3m0X.MnmHGOutgqolF/BikhkbIM1yMA7HQpkbDxULoG"
    

    crypt() ,并且不要使用最初使用的输入盐。实际上:

    $hash_to_store = crypt($new_password, $formatted_salt);
    

    $verified = $stored_hash == crypt($entered_password, $stored_hash);
    

    地穴() 的输出保持原样。