[v9.5.x] Utils: Reimplement util.GetRandomString to avoid modulo bias (#66970)

Utils: Reimplement util.GetRandomString to avoid modulo bias (#64481)

* reimplement GetRandomString, add tests that results are unbiased

(cherry picked from commit 7e765c870a)

Co-authored-by: Dan Cech <dcech@grafana.com>
This commit is contained in:
Grot (@grafanabot)
2023-05-22 14:55:16 -04:00
committed by GitHub
co-authored by Dan Cech
parent 99c1a4c171
commit 86e6d9d377
2 changed files with 117 additions and 13 deletions
+30 -13
View File
@@ -13,22 +13,39 @@ import (
"golang.org/x/crypto/pbkdf2"
)
// GetRandomString generate random string by specify chars.
// source: https://github.com/gogits/gogs/blob/9ee80e3e5426821f03a4e99fad34418f5c736413/modules/base/tool.go#L58
func GetRandomString(n int, alphabets ...byte) (string, error) {
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
var bytes = make([]byte, n)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
for i, b := range bytes {
if len(alphabets) == 0 {
bytes[i] = alphanum[b%byte(len(alphanum))]
} else {
bytes[i] = alphabets[b%byte(len(alphabets))]
// GetRandomString generates a random alphanumeric string of the specified length,
// optionally using only specified characters
func GetRandomString(n int, alphabets ...byte) (string, error) {
chars := alphanum
if len(alphabets) > 0 {
chars = string(alphabets)
}
cnt := len(chars)
max := 255 / cnt * cnt
bytes := make([]byte, n)
randread := n * 5 / 4
randbytes := make([]byte, randread)
for i := 0; i < n; {
if _, err := rand.Read(randbytes); err != nil {
return "", err
}
for j := 0; i < n && j < randread; j++ {
b := int(randbytes[j])
if b >= max {
continue
}
bytes[i] = chars[b%cnt]
i++
}
}
return string(bytes), nil
}