私はセキュリティで働いており、多くのエンコーディングおよび暗号化アルゴリズムで使用されるモジュラス(モジュロ)を見てきました。しかし、今日、私の友人は次のようにmoduloを使用すると述べています:
unsigned long int result = some_CSPRNG_output % 556600;
「CSPRNGのセキュリティ効果を制限します。」
Cに精通していない場合、疑似コードには基本的に、Linuxシステムの/dev/urandom
などの暗号的に安全な乱数ジェネレーターの出力(556600を法とする正の整数に絞ったもの)が割り当てられていることが記載されています。変数「result」に。
彼の議論の背後にある考えは、モジュラスが可能な出力の数を制限するため、エントロピーの強さが弱まるということです。たとえば、CSPRNG出力があり、それを2を法として計算すると、結果の可能性が少なくなるため、エントロピーが弱くなると述べました。
これは本当ですか?その理由またはそうでない理由を説明してください。
モジュロ演算は、特定の範囲内の数値を取得するのに役立ちます。あなたの例では、出力は常に[0, 556600)
になります。
これにより、生成された乱数の分布にいくつかの変更が生じる可能性があります。
主なもの:可能な値の小さいプール:
/dev/urandom
から読み取られた元のバイト数が〜2.5を超える場合、単に範囲が小さいという事実のため、結果の数値よりも範囲が大きく、エントロピーが高くなっています。
極端な例は2を法とするものです。可能な値の膨大な範囲から0 or 1
に移動できます。
これ自体は問題ではありません。 2つの選択肢からランダムに選択する必要がある場合、これは正しいことです。どちらかといえば、これはPRNGのいくつかの不均衡を滑らかにします。
厄介なもの:不均一な分布:
係数の厄介な副作用の1つは、範囲のサイズが係数の倍数でない場合です。
例:% 2
の範囲[0, 2]
。元の可能な値のうち2つは0
にマッピングされ、1つだけが1
にマッピングされます。元の分布が均一である場合、最終的な分布は0
に向かって大きく歪んでいます。
範囲がモジュラスと比較して大きければ大きいほど、これが引き起こすバイアスは少なくなります。
元の例では、最初に/dev/urandom
から4バイトを読み取る場合、範囲は7716.43
の係数(2^32 / 556600
)の倍数ですが、倍数ではありませんが、影響が少ないほど十分に大きいです。 。バイアスが役立つかどうかは、アプリケーションによって異なります。
この部分は問題になる可能性があります:2つの選択肢の間で選択する必要があり、66%の時間で最初の選択肢を選択する場合、問題があります。
概要:
あなたの友人は、エントロピーがモジュロ演算を介して変化すると言いましたが、間違った理由で部分的に正しかったです。可能な値の数を制限しても、必ずしもエントロピーが変わるわけではありません。しかし、最終的な分布に偏りがあるかもしれません。