【やさしく解説】PHP8上級試験の模擬問題(19)

PHP
スポンサーリンク

PHP8 上級/準上級試験の認定模擬問題として、プライム・ストラテジー様のPRIME STUDYが認定されているようです。ただ、この模擬問題には解説がありませんので解説をまとめていこうと思います。シリーズ第19回目です。

PHP初級レベルから脱却して中級/上級レベルにいきたい人にピッタリの内容ですね。

PRIME STUDY認定模擬問題のリンクはこちらです → https://study.prime-strategy.co.jp/ 

問題文

推測困難なトークン に関する説明の中で、誤っているものを1つ選びなさい。
また、すべてのコードには下記のコードが適切な箇所に書かれているものとする。

declare(strict_types=1);
error_reporting(-1);
下記はマニュアルから一部引用した内容である。

uniqid ( string $prefix = “” , bool $more_entropy = false ) : string
警告:この関数が生成する値は、暗号学的に安全ではありません。そのため、これを暗号として使ってはいけません。暗号学的に安全な値が必要な場合は、random_int() か random_bytes() あるいは openssl_random_pseudo_bytes() を使いましょう。

mt_rand ( ) : int
mt_rand ( int $min , int $max ) : int
警告:この関数が生成する値は、暗号学的に安全ではありません。そのため、これを暗号として使ってはいけません。暗号学的に安全な値が必要な場合は、random_int() か random_bytes() あるいは openssl_random_pseudo_bytes() を使いましょう。

mt_rand ( ) : int
mt_rand ( int $min , int $max ) : int
警告:この関数が生成する値は、暗号学的に安全ではありません。そのため、これを暗号として使ってはいけません。暗号学的に安全な値が必要な場合は、random_int() か random_bytes() あるいは openssl_random_pseudo_bytes() を使いましょう。

(1)
CSRF 等でも使われる事がある、秘密情報としての「推測(予測)困難なトークン」を作る場合において、random_bytes() は「暗号論的に安全な、疑似ランダムなバイト列を生成する」事が出来る。

そのため、以下のコード

var_dump( bin2hex( random_bytes(24) ) );


は正しく実行でき、結果は

string(48) "e5c471cbf4502eb90dbfbd2480f06a2d6af69ce4b0722b31"


となる (乱数の値は実行毎に変わる)。この値は「暗号論的にランダムなバイト列 (の 16 進表現)」なので、長さが十分であれば「推測 (予測) 困難なトークン」となり得る。

(2)
CSRF 等でも使われる事がある、秘密情報としての「推測(予測)困難なトークン」を作る場合において、openssl_random_pseudo_bytes() は「疑似ランダムなバイト文字列を生成する」事が出来る。

古いシステムでない限り暗号学的に強いアルゴリズムを使って疑似乱数が生成される事が多いが、古いシステムなどでは「暗号学的に強くない」文字列である可能性もあり、それは第二引数によって知る事が出来る。

そのため、以下のコード

var_dump( base64_encode( openssl_random_pseudo_bytes(24, $flg) ) );
var_dump($flg);


は正しく実行でき、結果は

string(32) "OFUw6O7WR785Kg5YZbGZOKDwJzXRn60J"
bool(true)


となる (乱数の値は実行毎に変わる)。この値は、第二引数で与えた $flg の値が true であるため「暗号論的にランダムなバイト列 (の 16 進表現)」なので、長さが十分であれば「推測 (予測) 困難なトークン」となり得る。

(3)
CSRF等でも使われる事がある、秘密情報としての「推測(予測)困難なトークン」を作る場合において。

そのため、以下のコード

var_dump( uniqid((string)mt_rand(), true) );


は正しく実行でき、結果は

string(33) "17821489405e874a50df8b89.86544478"


となる (乱数の値は実行毎に変わる)。uniqid() 関数と mt_rand() 関数を組み合わせているため、この値は「暗号論的にランダムな文字列」なので「推測 (予測) 困難なトークン」となり得る。

(4)
CSRF 等でも使われる事がある、秘密情報としての「推測(予測)困難なトークン」を作る場合において、mt_rand() は乱数を生成するが、

とあるため、これを使用しても推測(予測)困難なトークンを作成する事は出来ない。

そのため、以下のコード

var_dump( mt_getrandmax() );
var_dump( mt_rand() );


は正しく実行でき、結果は

int(2147483647)
int(248780506)


となるが (乱数の値は実行毎に変わる)、この値は「暗号論的にランダムな文字列」ではないので「推測 (予測) 困難なトークン」となり得ない。

解説

選択肢1の解説

正しいです。
random_bytes() は暗号論的に安全な乱数を生成するため、推測困難なトークンとして使用することができます。

選択肢2の解説

正しいです。
openssl_random_pseudo_bytes() も暗号論的に強い疑似乱数を生成することができ、引数で「暗号学的に強くない」かどうかを判定できます。

選択肢3の解説

誤りです。
uniqid() と mt_rand() を組み合わせた値は暗号学的に安全ではなく、推測困難なトークンとしては不適切です。

選択肢4の解説

正しいです。
mt_rand() は暗号学的に安全ではないため、推測困難なトークンを生成するためには使用できません。

正解選択肢

以上より選択肢3が正解となります。

コメント

タイトルとURLをコピーしました