Random Number Generation in Go: From Basics to Cryptography


Random number generation is a crucial aspect of many applications, from simple games to complex simulations and cryptographic operations. In this blog post, we'll explore three main methods of generating random numbers in Go: the very basic way using rand.Intn, the math/rand package with proper seeding, and cryptographically secure random number generation with crypto/rand. We'll also address the deprecation of rand.Seed in Go 1.20 and demonstrate the modern approach to seeding.

Basic Random Number Generation

The simplest way to generate a random number in Go is by using the rand.Intn function from the math/rand package:

package main

import (
    "fmt"
    "math/rand"
)

func main() {
    // Generate a random number between 1 and 12
    randomNumber := rand.Intn(12) + 1

    // Print the result
    fmt.Println(randomNumber)
}

Thread Safety

The rand.Intn function uses a global source of random numbers which is not safe for concurrent use by multiple goroutines. If you need to generate random numbers in a concurrent application, you should create a new rand.Rand instance with a local source.

Random Number Generation with math/rand

The math/rand package provides more controlled functionalities for random number generation. Starting from Go 1.20, rand.Seed is deprecated. Instead, we should use rand.New and rand.NewSource to create a new random number generator with a specific seed.

Here’s an example of generating a random number between 1 and 12 using math/rand:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    // Create a new random source and random generator
    source := rand.NewSource(time.Now().UnixNano())
    random := rand.New(source)

    // Generate a random number between 1 and 12
    randomNumber := random.Intn(12) + 1

    // Print the result
    fmt.Println(randomNumber)
}

Thread Safety

Creating a new rand.Rand instance with a local source is thread-safe, as each goroutine can have its own instance without any contention.

Cryptographically Secure Random Numbers with crypto/rand

For cryptographic applications or when high-quality randomness is required, the crypto/rand package should be used. This package provides functions that generate cryptographically secure random numbers.

Here’s an example of generating a secure random number between 1 and 12:

package main

import (
    "crypto/rand"
    "fmt"
    "math/big"
)

// generateSecureRandomNumber generates a secure random number between 1 and 12
func generateSecureRandomNumber() (int64, error) {
    // Define the maximum value (12) as a *big.Int
    max := big.NewInt(12)

    // Generate a cryptographically secure random number in the range [0, 11]
    n, err := rand.Int(rand.Reader, max)
    if err != nil {
        return 0, err
    }

    // Add 1 to shift the range to [1, 12]
    randomNumber := n.Int64() + 1

    return randomNumber, nil
}

func main() {
    randomNumber, err := generateSecureRandomNumber()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Println(randomNumber)
}

Thread Safety

The crypto/rand package is inherently thread-safe. Functions like rand.Int that use rand.Reader can be safely called from multiple goroutines concurrently.

Why Use crypto/rand?

The crypto/rand package is designed to generate random numbers that are suitable for cryptographic use, ensuring high entropy and unpredictability. This is crucial for applications where security is a concern, such as generating cryptographic keys, tokens, or other sensitive data.

Conclusion

In this post, we covered three main methods of generating random numbers in Go: using the rand.Intn function for basic random number generation, the math/rand package with proper seeding for more controlled randomness, and the crypto/rand package for cryptographically secure random numbers. We also discussed the deprecation of rand.Seed and demonstrated the modern approach to seeding with rand.New and rand.NewSource.

By understanding these techniques, you can choose the appropriate random number generation method for your application, ensuring that you balance simplicity, security, and thread safety according to your needs. Whether you're developing a simple game or a secure cryptographic application, Go provides robust tools to help you generate random numbers effectively.

Tags: #Go, #RandomNumberGeneration, #Cryptography, #ThreadSafety

10
Subscribe to my newsletter

Read articles from Manoj Parvathaneni directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Manoj Parvathaneni
Manoj Parvathaneni