弱い PRNG
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
OWASP カテゴリ: MASVS-CRYPTO: 暗号
概要
疑似乱数ジェネレータ(PRNG)とは、シードと呼ばれる開始値に基づいて予測可能な数列を生成するアルゴリズムのことです。PRNG によって生成される数列は、真の乱数列とおおよそ同じプロパティを持ちますが、より高速に、より低い計算コストで生成できます。
言い換えると、PRNG は、弱い RNG(java.math.Random
など)と比べてエントロピー分布の均一性の点で高い信頼性を持ち、真の乱数列をエミュレートできます。真の乱数を生成するには専用の機器が必要であり、多くの場合、これは通常の開発の範囲外です。この記事では真の乱数生成については説明しません。実際に使用されている標準の手法である PRNG のみに焦点を当てます。
弱い PRNG の脆弱性は、暗号技術の利用に際し、暗号的にセキュアな PRNG(CSPRNG)ではなく、通常の PRNG をデベロッパーが使用している場合に発生します。CSPRNG には厳格な要件があり、シードが不明な場合、その出力数列と真の乱数列を攻撃者が区別するための手がかりはほとんどありません。
PRNG または CSPRNG の初期化に予測可能なシード(デベロッパーがハードコードしたものなど)を使用していると、生成された数列を攻撃者に推測される場合もあります。シードを推測できることで、PRNG が生成する出力も予測できるためです。
影響
暗号的にセキュアではない PRNG が認証などのセキュリティ コンテキストで使用されている場合、攻撃者はランダムに生成された番号を推測して、特権データや機能にアクセスできる可能性があります。
リスクの軽減
全般
java.security.SecureRandom
セキュリティ関連の用途に推奨されます。Linux カーネル バージョンが 5.17 以降の場合、またはスレッドのブロックが許容される場合は、十分なエントロピーが蓄積されるのを待ってから、乱数を生成します(つまり /dev/random
を使用します)。そのためには、getInstanceStrong()
を呼び出します。
Kotlin
val rand = SecureRandom.getInstanceStrong()
Java
SecureRandom rand = SecureRandom.getInstanceStrong();
Linux カーネル バージョンが 5.17 より前で、乱数生成時のスレッドのブロックもできない場合は、SecureRandom
コンストラクタを直接呼び出す必要があります。
Kotlin
import java.security.SecureRandom
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = SecureRandom()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
// Use rand_int for security & authentication
}
}
Java
import java.security.SecureRandom;
public class generateRandom {
public static void main(String args[])
{
// Create instance of SecureRandom class
SecureRandom rand = new SecureRandom();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
// Use rand_int for security & authentication
}
}
SecureRandom
は /dev/urandom
からデフォルトのシードを取得し、オブジェクトが構築または取得されたときに自動的に使用されるため、PRNG を明示的にシードする必要はありません。一般的に、SecureRandom の決定論的使用は推奨されません(特に、シード値のハードコーディングをすることになる場合。アプリを逆コンパイルすることでシード値を確認できてしまう)。再現可能な擬似ランダム出力を生成するデベロッパーは、HMAC、HKDF、SHAKE などのより適切なプリミティブを使用する必要があります。
java.util.Random
セキュリティや認証の目的で使用しないでください。他の目的には使用できます。
Kotlin
import java.util.Random
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = Random()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
}
}
Java
import java.util.Random;
public class generateRandom {
public static void main(String args[])
{
// Create instance of Random class
Random rand = new Random();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
}
}
参考資料
このページのコンテンツやコードサンプルは、コンテンツ ライセンスに記載のライセンスに従います。Java および OpenJDK は Oracle および関連会社の商標または登録商標です。
最終更新日 2024-02-23 UTC。
[[["わかりやすい","easyToUnderstand","thumb-up"],["問題の解決に役立った","solvedMyProblem","thumb-up"],["その他","otherUp","thumb-up"]],[["必要な情報がない","missingTheInformationINeed","thumb-down"],["複雑すぎる / 手順が多すぎる","tooComplicatedTooManySteps","thumb-down"],["最新ではない","outOfDate","thumb-down"],["翻訳に関する問題","translationIssue","thumb-down"],["サンプル / コードに問題がある","samplesCodeIssue","thumb-down"],["その他","otherDown","thumb-down"]],["最終更新日 2024-02-23 UTC。"],[],[],null,["# Weak PRNG\n\n\u003cbr /\u003e\n\n**OWASP category:** [MASVS-CRYPTO: Cryptography](https://mas.owasp.org/MASVS/06-MASVS-CRYPTO)\n\nOverview\n--------\n\nA pseudorandom number generator (PRNG) is an algorithm that generates\npredictable number sequences based on a starting value called a *seed* . A\nPRNG-generated number sequence has **approximately** the same properties as a\ntruly random number sequence, but is faster and less computationally expensive\nto create.\n\nIn other words, PRNGs have higher assurances than weak RNGs (e.g.\n`java.math.Random`) in terms of evenness of entropy distribution, which emulate\ntruly random number sequences. Truly random number generation requires\nspecialized equipment and is often outside the scope of normal development. This\ndocument does not cover truly random number generation, and focuses only on\nPRNGs as they are the standard methodology in use.\n\nWeak PRNG vulnerabilities occur when developers use a regular PRNG for\ncryptographic purposes, instead of a cryptographically-secure PRNG (CSPRNG).\nCSPRNGs have stricter requirements, and when the seed is unknown, they must give\nan attacker only an insignificant advantage in differentiating an output\nsequence from an actual random sequence.\n\nAttackers may also be able to guess the generated number sequence when\npredictable seeds -- such as those hard coded by the developer -- are used to\ninitialize a PRNG or CSPRNG, as the attacker can guess the seed and thus predict\nthe output generated by the PRNG.\n\nImpact\n------\n\nIf a non-cryptographically secure PRNG is used in a security context like\nauthentication, an attacker may be able to guess the randomly-generated numbers\nand gain access to privileged data or features.\n\nMitigations\n-----------\n\n### General\n\n- Use [`java.security.SecureRandom`](/reference/java/security/SecureRandom) when there are *security implications*\n- Use [`java.util.Random`](/reference/java/util/Random) for any other cases\n- **Never** use [`Math.random`](/reference/java/lang/Math#random())!\n\n### java.security.SecureRandom\n\n**Recommended** for security uses. If the Linux kernel version is 5.17+ *or*\nblocking the thread is acceptable, wait for enough entropy to accumulate before\nyou generate the random numbers (i.e. use `/dev/random`). To do so, call\n`getInstanceStrong()`: \n\n### Kotlin\n\n val rand = SecureRandom.getInstanceStrong()\n\n### Java\n\n SecureRandom rand = SecureRandom.getInstanceStrong();\n\nOtherwise, on Linux kernel versions prior to 5.17 when blocking the thread is\nunacceptable when generating random numbers, then the `SecureRandom` constructor\nshould be called directly: \n\n### Kotlin\n\n import java.security.SecureRandom\n\n object generateRandom {\n @JvmStatic\n fun main(args: Array\u003cString\u003e) {\n // Create instance of SecureRandom class\n val rand = SecureRandom()\n\n // Generate random integers in range 0 to 999\n val rand_int = rand.nextInt(1000)\n\n // Use rand_int for security & authentication\n }\n }\n\n### Java\n\n import java.security.SecureRandom;\n\n public class generateRandom {\n\n public static void main(String args[])\n {\n // Create instance of SecureRandom class\n SecureRandom rand = new SecureRandom();\n\n // Generate random integers in range 0 to 999\n int rand_int = rand.nextInt(1000);\n\n // Use rand_int for security & authentication\n }\n }\n\n`SecureRandom` gets the default seed from `/dev/urandom`, and is automatically\nused when the object is constructed or obtained, so there is no need to\nexplicitly seed the PRNG. In general, any deterministic usage of `SecureRandom`\nis discouraged (especially if this leads to hard coding a seed value, which\nanyone decompiling the app can see). Developers who want to generate\nreproducible pseudorandom output should use more appropriate primitives such as\nHMAC, HKDF, and SHAKE.\n\n### java.util.Random\n\n**Avoid** for security / authentication purposes, acceptable to use for anything\nelse. \n\n### Kotlin\n\n import java.util.Random\n\n object generateRandom {\n @JvmStatic\n fun main(args: Array\u003cString\u003e) {\n // Create instance of SecureRandom class\n val rand = Random()\n\n // Generate random integers in range 0 to 999\n val rand_int = rand.nextInt(1000)\n }\n }\n\n### Java\n\n import java.util.Random;\n\n public class generateRandom {\n\n public static void main(String args[])\n {\n // Create instance of Random class\n Random rand = new Random();\n\n // Generate random integers in range 0 to 999\n int rand_int = rand.nextInt(1000);\n }\n }\n\nResources\n---------\n\n- [java.security.SecureRandom](/reference/java/security/SecureRandom)\n- [java.util.Random](/reference/java/util/Random)\n- [Math.random](/reference/java/lang/Math#random())\n- [Predictable Seed CWE](https://cwe.mitre.org/data/definitions/337.html)\n- [Cryptographically Weak PRNG CWE](https://cwe.mitre.org/data/definitions/338.html)\n- [Java Secure Random](https://www.baeldung.com/java-secure-random)\n- [Java Random versus SecureRandom](https://www.geeksforgeeks.org/random-vs-secure-random-numbers-java/)\n- [How to use SecureRandom](https://tersesystems.com/blog/2015/12/17/the-right-way-to-use-securerandom/)\n- [Python PRNG security guidance](https://rules.sonarsource.com/python/RSPEC-2245)\n- [OWASP Cryptographic Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation)\n- [CVE-2013-6386: Weak PRNG vuln in Drupal](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-6386)\n- [CVE-2006-3419: Weak PRNG vuln in Tor](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-3419)\n- [CVE-2008-4102: Predictable Seed in Joomla](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-4102)\n- [Linux Kernel random patch](https://lwn.net/Articles/884875/)"]]