Skip to content

Commit ca3c2e9

Browse files
committed
Document cryptographically secure random number generation
- Mention which PRNG Godot internally uses.
1 parent 1e2867c commit ca3c2e9

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

tutorials/math/random_number_generation.rst

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,19 @@ Godot.
99

1010
After giving you a brief overview of useful functions that generate random
1111
numbers, you will learn how to get random elements from arrays, dictionaries,
12-
and how to use a noise generator in GDScript.
12+
and how to use a noise generator in GDScript. Lastly, we'll take a look at
13+
cryptographically secure random number generation and how it differs from
14+
typical random number generation.
1315

1416
.. note::
1517

1618
Computers cannot generate "true" random numbers. Instead, they rely on
1719
`pseudorandom number generators
1820
<https://en.wikipedia.org/wiki/Pseudorandom_number_generator>`__ (PRNGs).
1921

22+
Godot internally uses the `PCG Family <https://www.pcg-random.org/>`__
23+
of pseudorandom number generators.
24+
2025
Global scope versus RandomNumberGenerator class
2126
-----------------------------------------------
2227

@@ -34,6 +39,14 @@ the RandomNumberGenerator class.
3439
The randomize() method
3540
----------------------
3641

42+
.. note::
43+
44+
Since Godot 4.0, the random seed is automatically set to a random value when
45+
the project starts. This means you don't need to call ``randomize()`` in
46+
``_ready()`` anymore to ensure that results are random across project runs.
47+
However, you can still use ``randomize()`` if you want to use a specific
48+
seed number, or generate it using a different method.
49+
3750
In global scope, you can find a :ref:`randomize()
3851
<class_@GlobalScope_method_randomize>` method. **This method should be called only
3952
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
473486
GD.Print(_noise.GetNoise1D(i));
474487
}
475488
}
489+
490+
Cryptographically secure pseudorandom number generation
491+
-------------------------------------------------------
492+
493+
So far, the approaches mentioned above are **not** suitable for
494+
*cryptographically secure* pseudorandom number generation (CSPRNG). This is fine
495+
for games, but this is not sufficient for scenarios where encryption,
496+
authentication or signing is involved.
497+
498+
Godot offers a :ref:`class_Crypto` class for this. This class can perform
499+
asymmetric key encryption/decryption, signing/verification, while also
500+
generating cryptographically secure random bytes, RSA keys, HMAC digests, and
501+
self-signed :ref:`class_X509Certificate`\ s.
502+
503+
The downside of :abbr:`CSPRNG (Cryptographically secure pseudorandom number generation)`
504+
is that it's much slower than standard pseudorandom number generation. Its API
505+
is also less convenient to use. As a result,
506+
:abbr:`CSPRNG (Cryptographically secure pseudorandom number generation)`
507+
should be avoided for gameplay elements.
508+
509+
Example of using the Crypto class to generate 2 random integers between ``0``
510+
and ``2^32 - 1`` (inclusive):
511+
512+
::
513+
514+
var crypto := Crypto.new()
515+
# Request as many bytes as you need, but try to minimize the amount
516+
# of separate requests to improve performance.
517+
# Each 32-bit integer requires 4 bytes, so we request 8 bytes.
518+
var byte_array := crypto.generate_random_bytes(8)
519+
520+
# Use the ``decode_u32()`` method from PackedByteArray to decode a 32-bit unsigned integer
521+
# from the beginning of `byte_array`. This method doesn't modify `byte_array`.
522+
var random_int_1 := byte_array.decode_u32(0)
523+
# Do the same as above, but with an offset of 4 bytes since we've already decoded
524+
# the first 4 bytes previously.
525+
var random_int_2 := byte_array.decode_u32(4)
526+
527+
prints("Random integers:", random_int_1, random_int_2)
528+
529+
.. seealso::
530+
531+
See :ref:`class_PackedByteArray`'s documentation for other methods you can
532+
use to decode the generated bytes into various types of data, such as
533+
integers or floats.

0 commit comments

Comments
 (0)