Skip to content

Migrate to math/rand/v2 #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 15 additions & 45 deletions src/cryptographic-practices/pseudo-random-generators.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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