web-dev-qa-db-ja.com

暗号的に安全なトークンの生成

APIにアクセスするための32文字のトークンを生成するために、現在次を使用しています。

$token = md5(uniqid(mt_Rand(), true));

この方法はシステムクロックに基づいているため、暗号的に安全ではなく、openssl_random_pseudo_bytesは予測が難しいため、より良いソリューションになると読みました。

この場合、同等のコードはどのようになりますか?

私はこのようなことを推測しますが、これが正しいかどうかわかりません...

$token = md5(openssl_random_pseudo_bytes(32));

また、関数に渡す必要がある長さは何ですか?

72
fire

正しい解決策は次のとおりです。

$token = bin2hex(openssl_random_pseudo_bytes(16));

# or in php7
$token = bin2hex(random_bytes(16));
166
fire

Openssl_random_pseudo_bytesを使用する場合は、CrytoLibの実装を使用するのが最適です。これにより、すべての英数字を生成できるようになります。

Path/to /をcryptolib.phpファイルを置いた場所に置き換えます(GitHubで見つけることができます: https://github.com/IcyApril/CryptoLib

<?php
  require_once('path/to/cryptolib.php');
  $token = CryptoLib::randomString(16);
?>

完全なCryptoLibドキュメントは、 https://cryptolib.ju.je/ で入手できます。他の多くのランダムな方法、カスケード暗号化、ハッシュの生成と検証をカバーしています。必要な場合はそこにあります。

10
mjsa

暗号で保護された乱数ジェネレーターを使用している場合、その出力をハッシュする必要はありません。実際には、したくない。ただ使う

$token  = openssl_random_pseudo_bytes($BYTES,true)

ただし、$ BYTESは必要なデータのバイト数です。 MD5には128ビットのハッシュがあるため、16バイトで十分です。

サイドノートとして、元のコードで呼び出す関数はどれも暗号的に安全ではなく、ほとんどは安全な他の関数と組み合わせても、1つだけを使用しても安全ではないほど有害です。 MD5にはセキュリティの問題があります(ただし、このアプリケーションには関連性がない場合があります)。 Uniqidは、デフォルトで暗号的にランダムなバイトを生成しないだけでなく(システムクロックを使用するため)、渡すエントロピーは、暗号的に安全ではない線形合同ジェネレータを使用して結合されます。実際、サーバークロックの値がわからなくても、いくつかのAPIキーにアクセスすることですべてのAPIキーを推測できる可能性があります。最後に、余分なエントロピーとして使用するmt_Rand()は、安全な乱数ジェネレーターでもありません。

8
imichaelmiers