Avoid modulo bias.
This commit is contained in:
parent
ecf15fa52a
commit
958b406e0e
21
uniuri.go
21
uniuri.go
@ -45,12 +45,25 @@ func NewLen(length int) string {
|
|||||||
// of the provided byte slice of allowed characters (maximum 256).
|
// of the provided byte slice of allowed characters (maximum 256).
|
||||||
func NewLenChars(length int, chars []byte) string {
|
func NewLenChars(length int, chars []byte) string {
|
||||||
b := make([]byte, length)
|
b := make([]byte, length)
|
||||||
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
r := make([]byte, length+(length/4)) // storage for random bytes.
|
||||||
|
clen := byte(len(chars))
|
||||||
|
maxrb := byte(256 - (256 % len(chars)))
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
if _, err := io.ReadFull(rand.Reader, r); err != nil {
|
||||||
panic("error reading from random source: " + err.String())
|
panic("error reading from random source: " + err.String())
|
||||||
}
|
}
|
||||||
alen := byte(len(chars))
|
for _, c := range r {
|
||||||
for i, c := range b {
|
if c >= maxrb {
|
||||||
b[i] = chars[c%alen]
|
// Skip this number to avoid modulo bias.
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
b[i] = chars[c%clen]
|
||||||
|
i++
|
||||||
|
if i == length {
|
||||||
return string(b)
|
return string(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user