この質問は、PHP のcrypt()
. この質問では、salt の最初の 7 文字はカウントされないため、salt ' $2a$07$a
' は、salt の 1 文字とメタデータの 7 文字のみであるため、長さ 1 であると言われます。
22 文字を超えるソルト文字列を使用する場合、生成されるハッシュ (つまり、切り捨て) に変更はありません。また、21 文字より短い文字列を使用する場合、ソルトは自動的にパディングされます (' $
' 文字が表示されます)。これはかなり簡単です。ただし、20 文字のソルトと 21 文字のソルトが指定された場合、21 文字の長さのソルトの最後の文字を除いて 2 つが同一である場合、両方のハッシュされた文字列は同一になります。22 文字の長さのソルトは、最後の文字を除いて 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.
です。ただし、生成される文字列には、ハッシュ、ソルト、およびソルトを生成するための指示 (つまり$2a$07$
) が含まれることに注意することが重要です。違いが生じる部分は、実際にはまだ塩です。実際のハッシュは変更されていませんUxGYN739wLkV5PGoR1XA4EvNVPjwylG
。
したがって、これは実際には、生成されたハッシュの違いではなく、ハッシュを格納するために使用されるソルトの違いであり、これがまさに当面の問題です: 2 つのソルトが同じハッシュを生成しています。
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)
お役に立てれば。