diff --git a/src/cryptographic-practices/pseudo-random-generators.md b/src/cryptographic-practices/pseudo-random-generators.md index 165bd71..4434be5 100644 --- a/src/cryptographic-practices/pseudo-random-generators.md +++ b/src/cryptographic-practices/pseudo-random-generators.md @@ -9,46 +9,15 @@ let's discuss "random numbers". Cryptography relies on some randomness, but for the sake of correctness, what most programming languages provide out-of-the-box is a pseudo-random number -generator: for example, [Go's math/rand][1] is not an exception. +generator: for example, [Go's math/rand/v2][1] is not an exception. Note that +the older `math/rand` is not either a cryptographically secure number generator. -You should carefully read the documentation when it states that "_Top-level -functions, such as Float64 and Int, use a default shared Source that produces a -**deterministic sequence** of values each time a program is run._" ([source][2]) +You should carefully read the documentation when it states that "_This package's +outputs might be easily predictable regardless of how it's seeded_" ([source][2]). +The `math/rand/v2` package's random values are not as random as values provided +by `crypto/rand` ([source][3]). -What exactly does that mean? Let's see: - -```go -package main - -import "fmt" -import "math/rand" - -func main() { - fmt.Println("Random Number: ", rand.Intn(1984)) -} -``` - -Running this program several times will lead exactly to the same -number/sequence, but why? - -```bash -$ for i in {1..5}; do go run rand.go; done -Random Number: 1825 -Random Number: 1825 -Random Number: 1825 -Random Number: 1825 -Random Number: 1825 -``` - -Because [Go's math/rand][1] is a deterministic pseudo-random number generator. -Similar to many others, it uses a source, called a Seed. This Seed is **solely** -responsible for the randomness of the deterministic pseudo-random number -generator. If it is known or predictable, the same will happen to generated -number sequence. - -We could "fix" this example quite easily by using the -[math/rand Seed function][3], getting the expected five different values for -each program execution. But because we're on Cryptographic Practices section, we +But because we're on Cryptographic Practices section, we should follow to [Go's crypto/rand package][4]. ```go @@ -68,10 +37,10 @@ func main() { } ``` -You may notice that running [crypto/rand][4] is slower than [math/rand][1], but +You may notice that running [crypto/rand][4] is slower than [math/rand/v2][1], but this is expected since the fastest algorithm isn't always the safest. Crypto's rand is also safer to implement. An example of this is the fact that you -_CANNOT_ seed crypto/rand, since the library uses OS-randomness for this, +_CANNOT_ seed `crypto/rand`, since the library uses OS-randomness for this, preventing developer misuse. ```bash @@ -85,12 +54,13 @@ Random Number: 1378 If you're curious about how this can be exploited just think what happens if your application creates a default password on user signup, by computing the -hash of a pseudo-random number generated with [Go's math/rand][1], as shown in -the first example. +hash of a pseudo-random number generated with the [Go's math/rand][5] package's +now deprecated Seed function. Yes, you guessed it, you would be able to predict the user's password! -[1]: https://golang.org/pkg/math/rand/ -[2]: https://golang.org/pkg/math/rand/#pkg-overview -[3]: https://golang.org/pkg/math/rand/#Seed +[1]: https://pkg.go.dev/math/rand/v2 +[2]: https://pkg.go.dev/math/rand/v2#pkg-overview +[3]: https://go.dev/blog/chacha8rand [4]: https://golang.org/pkg/crypto/rand/ +[5]: https://pkg.go.dev/math/rand