Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I generate a random int using the "crypto/rand" package?

Tags:

go

Say I would like to generate a secure random int between 0 and 27 using:

func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) 

in the "crypto/rand" package.

How would I do that?

I do not really understand how this works, why does it not return one of the built in Go ints instead of pointer to some big.Int type?

EDIT:

Would this be considered secure enough for tokens?

func getToken(length int) string {     token := ""     codeAlphabet := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"     codeAlphabet += "abcdefghijklmnopqrstuvwxyz"     codeAlphabet += "0123456789"      for i := 0; i < length; i++ {         token += string(codeAlphabet[cryptoRandSecure(int64(len(codeAlphabet)))])     }     return token }  func cryptoRandSecure(max int64) int64 {     nBig, err := rand.Int(rand.Reader, big.NewInt(max))     if err != nil {         log.Println(err)     }     return nBig.Int64() }  func main() {     fmt.Println(getToken(32)) } 

This would output something like this:

qZDbuPwNQGrgVmZCU9A7FUWbp8eIfn0Z  EwZVoQ5D5SEfdhiRsDfH6dU6tAovILCZ  cOqzODVP0GwbiNBwtmqLA78rFgV9d3VT 
like image 252
Aiden Avatar asked Sep 02 '15 09:09

Aiden


People also ask

How do you get a random number from Rand?

The rand() function generates a pseudo-random integer in the range 0 to RAND_MAX . Use the srand() function before calling rand() to set a seed for the random number generator. If you do not make a call to srand(), the default seed is 1.

What is Rand seed Golang?

In Golang, the rand. Seed() function is used to set a seed value to generate pseudo-random numbers. If the same seed value is used in every execution, then the same set of pseudo-random numbers is generated. In order to get a different set of pseudo-random numbers, we need to update the seed value.


2 Answers

Here is some working code :

package main  import (     "fmt"     "crypto/rand"     "math/big" )  func main() {     nBig, err := rand.Int(rand.Reader, big.NewInt(27))     if err != nil {         panic(err)     }     n := nBig.Int64()     fmt.Printf("Here is a random %T in [0,27) : %d\n", n, n) } 

But to generate a random token, I'd do something like this :

package main  import (     "crypto/rand"     "encoding/base32"     "fmt" )  func main() {     token := getToken(10)     fmt.Println("Here is a random token : ", token) }  func getToken(length int) string {     randomBytes := make([]byte, 32)     _, err := rand.Read(randomBytes)     if err != nil {         panic(err)     }     return base32.StdEncoding.EncodeToString(randomBytes)[:length] } 
like image 154
HectorJ Avatar answered Sep 29 '22 19:09

HectorJ


If you're generating secure tokens for session IDs, OAuth Bearer tokens, CSRF or similar: you want to generate a token of (ideally) 256 bits (32 bytes) or no less than 192 bits (24 bytes).

A token with values between (0-27) can be brute-forced in less than a second and could not be considered secure.

e.g.

package main  import (     "crypto/rand"     "encoding/base64" )  // GenerateRandomBytes returns securely generated random bytes. // It will return an error if the system's secure random // number generator fails to function correctly, in which // case the caller should not continue. func GenerateRandomBytes(n int) ([]byte, error) {     b := make([]byte, n)     _, err := rand.Read(b)     // Note that err == nil only if we read len(b) bytes.     if err != nil {         return nil, err     }      return b, nil }  // GenerateRandomString returns a URL-safe, base64 encoded // securely generated random string. func GenerateRandomString(s int) (string, error) {     b, err := GenerateRandomBytes(s)     return base64.URLEncoding.EncodeToString(b), err }  func main() {     // Example: this will give us a 44 byte, base64 encoded output     token, err := GenerateRandomString(32)     if err != nil {         // Serve an appropriately vague error to the         // user, but log the details internally.     } } 

The base64 output is safe for headers, HTTP forms, JSON bodies, etc.

If you need an integer it may help to explain your use-case, as it would be odd for a system to require tokens as ints.

like image 23
elithrar Avatar answered Sep 29 '22 19:09

elithrar