3

こんにちは、ご存じかもしれませんが、PHP は最近password_hash、最新バージョンのビルトインを導入しました。ドキュメントには次のように記載されています。

省略した場合、ランダムなソルトが作成され、デフォルトのコストが使用されます。

問題は、塩を加えるためにどのような方法を使用するかです。

ソルトがランダムに作成され、ハッシュ化されたパスワードを保存するときに常に一意になるかどうかを知りたいので、興味があります。

4

1 に答える 1

8

塩はランダムに作成されます。それらは統計的に一意である必要があります。

方法については、C ソース コードを参照してください。

Windows ではphp_win32_get_random_bytes()、ソルトの生成に使用しようとします。

BYTE *iv_b = (BYTE *) buffer;
if (php_win32_get_random_bytes(iv_b, raw_length) == SUCCESS) {
    buffer_valid = 1;
}

Linux では/dev/urandom、salt を生成するために読み取りを試みます。

int fd, n;
size_t read_bytes = 0;
fd = open("/dev/urandom", O_RDONLY);
if (fd >= 0) {
    while (read_bytes < raw_length) {
        n = read(fd, buffer + read_bytes, raw_length - read_bytes);
        if (n < 0) {
            break;
        }
        read_bytes += (size_t) n;
    }
    close(fd);
}
if (read_bytes >= raw_length) {
    buffer_valid = 1;
}

次に、これら 2 つの後、バッファーが有効でない場合 (いっぱいではない、部分的である可能性がある)、rand() を使用してそれを埋めます。実際には、これは決して起こらないことに注意してください。これは単なるフォールバックです。

if (!buffer_valid) {
    for (i = 0; i < raw_length; i++) {
        buffer[i] ^= (char) (255.0 * php_rand(TSRMLS_C) / RAND_MAX);
    }
}

さて、C が好みでない場合は、同じロジックとアルゴリズムが私の互換ライブラリの PHP に実装されています。

$buffer = '';
$raw_length = (int) ($required_salt_len * 3 / 4 + 1);
$buffer_valid = false;
if (function_exists('mcrypt_create_iv')) {
    $buffer = mcrypt_create_iv($raw_length, MCRYPT_DEV_URANDOM);
    if ($buffer) {
        $buffer_valid = true;
    }
}
if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
    $buffer = openssl_random_pseudo_bytes($raw_length);
    if ($buffer) {
        $buffer_valid = true;
    }
}
if (!$buffer_valid && is_readable('/dev/urandom')) {
    $f = fopen('/dev/urandom', 'r');
    $read = strlen($buffer);
    while ($read < $raw_length) {
        $buffer .= fread($f, $raw_length - $read);
        $read = strlen($buffer);
    }
    fclose($f);
    if ($read >= $raw_length) {
        $buffer_valid = true;
    }
}
if (!$buffer_valid || strlen($buffer) < $raw_length) {
    $bl = strlen($buffer);
    for ($i = 0; $i < $raw_length; $i++) {
        if ($i < $bl) {
            $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
        } else {
            $buffer .= chr(mt_rand(0, 255));
        }
    }
}

唯一の違いは、PHP バージョンが使用するmcryptopenssl、どちらかがインストールされている場合...

于 2013-02-13T15:55:11.700 に答える