Переглянути джерело

Merge pull request #8346 from Calinou/random-number-generation-csprng

Document cryptographically secure random number generation
Max Hilbrunner 1 рік тому
батько
коміт
b4ffc06afc
1 змінених файлів з 59 додано та 1 видалено
  1. 59 1
      tutorials/math/random_number_generation.rst

+ 59 - 1
tutorials/math/random_number_generation.rst

@@ -9,7 +9,9 @@ Godot.
 
 
 After giving you a brief overview of useful functions that generate random
 After giving you a brief overview of useful functions that generate random
 numbers, you will learn how to get random elements from arrays, dictionaries,
 numbers, you will learn how to get random elements from arrays, dictionaries,
-and how to use a noise generator in GDScript.
+and how to use a noise generator in GDScript. Lastly, we'll take a look at
+cryptographically secure random number generation and how it differs from
+typical random number generation.
 
 
 .. note::
 .. note::
 
 
@@ -17,6 +19,9 @@ and how to use a noise generator in GDScript.
     `pseudorandom number generators
     `pseudorandom number generators
     <https://en.wikipedia.org/wiki/Pseudorandom_number_generator>`__ (PRNGs).
     <https://en.wikipedia.org/wiki/Pseudorandom_number_generator>`__ (PRNGs).
 
 
+    Godot internally uses the `PCG Family <https://www.pcg-random.org/>`__
+    of pseudorandom number generators.
+
 Global scope versus RandomNumberGenerator class
 Global scope versus RandomNumberGenerator class
 -----------------------------------------------
 -----------------------------------------------
 
 
@@ -34,6 +39,14 @@ the RandomNumberGenerator class.
 The randomize() method
 The randomize() method
 ----------------------
 ----------------------
 
 
+.. note::
+
+    Since Godot 4.0, the random seed is automatically set to a random value when
+    the project starts. This means you don't need to call ``randomize()`` in
+    ``_ready()`` anymore to ensure that results are random across project runs.
+    However, you can still use ``randomize()`` if you want to use a specific
+    seed number, or generate it using a different method.
+
 In global scope, you can find a :ref:`randomize()
 In global scope, you can find a :ref:`randomize()
 <class_@GlobalScope_method_randomize>` method. **This method should be called only
 <class_@GlobalScope_method_randomize>` method. **This method should be called only
 once when your project starts to initialize the random seed.** Calling it
 once when your project starts to initialize the random seed.** Calling it
@@ -473,3 +486,48 @@ terrain. Godot provides :ref:`class_fastnoiselite` for this, which supports
             GD.Print(_noise.GetNoise1D(i));
             GD.Print(_noise.GetNoise1D(i));
         }
         }
     }
     }
+
+Cryptographically secure pseudorandom number generation
+-------------------------------------------------------
+
+So far, the approaches mentioned above are **not** suitable for
+*cryptographically secure* pseudorandom number generation (CSPRNG). This is fine
+for games, but this is not sufficient for scenarios where encryption,
+authentication or signing is involved.
+
+Godot offers a :ref:`class_Crypto` class for this. This class can perform
+asymmetric key encryption/decryption, signing/verification, while also
+generating cryptographically secure random bytes, RSA keys, HMAC digests, and
+self-signed :ref:`class_X509Certificate`\ s.
+
+The downside of :abbr:`CSPRNG (Cryptographically secure pseudorandom number generation)`
+is that it's much slower than standard pseudorandom number generation. Its API
+is also less convenient to use. As a result,
+:abbr:`CSPRNG (Cryptographically secure pseudorandom number generation)`
+should be avoided for gameplay elements.
+
+Example of using the Crypto class to generate 2 random integers between ``0``
+and ``2^32 - 1`` (inclusive):
+
+::
+
+    var crypto := Crypto.new()
+    # Request as many bytes as you need, but try to minimize the amount
+    # of separate requests to improve performance.
+    # Each 32-bit integer requires 4 bytes, so we request 8 bytes.
+    var byte_array := crypto.generate_random_bytes(8)
+
+    # Use the ``decode_u32()`` method from PackedByteArray to decode a 32-bit unsigned integer
+    # from the beginning of `byte_array`. This method doesn't modify `byte_array`.
+    var random_int_1 := byte_array.decode_u32(0)
+    # Do the same as above, but with an offset of 4 bytes since we've already decoded
+    # the first 4 bytes previously.
+    var random_int_2 := byte_array.decode_u32(4)
+
+    prints("Random integers:", random_int_1, random_int_2)
+
+.. seealso::
+
+    See :ref:`class_PackedByteArray`'s documentation for other methods you can
+    use to decode the generated bytes into various types of data, such as
+    integers or floats.