-
Star
(105)
You must be signed in to star a gist -
Fork
(26)
You must be signed in to fork a gist
-
-
Save dopey/c69559607800d2f2f90b1b1ed4e550fb to your computer and use it in GitHub Desktop.
How to generate secure random strings in golang with crypto/rand.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/rand" | |
"encoding/base64" | |
"fmt" | |
"io" | |
"math/big" | |
) | |
// Adapted from https://elithrar.github.io/article/generating-secure-random-numbers-crypto-rand/ | |
func init() { | |
assertAvailablePRNG() | |
} | |
func assertAvailablePRNG() { | |
// Assert that a cryptographically secure PRNG is available. | |
// Panic otherwise. | |
buf := make([]byte, 1) | |
_, err := io.ReadFull(rand.Reader, buf) | |
if err != nil { | |
panic(fmt.Sprintf("crypto/rand is unavailable: Read() failed with %#v", err)) | |
} | |
} | |
// 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 securely generated random string. | |
// 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 GenerateRandomString(n int) (string, error) { | |
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-" | |
ret := make([]byte, n) | |
for i := 0; i < n; i++ { | |
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) | |
if err != nil { | |
return "", err | |
} | |
ret[i] = letters[num.Int64()] | |
} | |
return string(ret), nil | |
} | |
// GenerateRandomStringURLSafe returns a URL-safe, base64 encoded | |
// securely generated random string. | |
// 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 GenerateRandomStringURLSafe(n int) (string, error) { | |
b, err := GenerateRandomBytes(n) | |
return base64.URLEncoding.EncodeToString(b), err | |
} | |
func main() { | |
// Example: this will give us a 44 byte, base64 encoded output | |
token, err := GenerateRandomStringURLSafe(32) | |
if err != nil { | |
// Serve an appropriately vague error to the | |
// user, but log the details internally. | |
panic(err) | |
} | |
fmt.Println(token) | |
// Example: this will give us a 32 byte output | |
token, err = GenerateRandomString(32) | |
if err != nil { | |
// Serve an appropriately vague error to the | |
// user, but log the details internally. | |
panic(err) | |
} | |
fmt.Println(token) | |
} |
Maybe give this a shot and improve it for others to use as well ? I had similar usecase sometime ago https://pkg.go.dev/github.com/imusmanmalik/randomizer
thanks
Can't you just do rand.read and get random bytes, then encode it to base64?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@kyle-aoki added. thanks!