Remove modulo bias from generated IDs
This commit is contained in:
@@ -510,17 +510,34 @@ func generateUniqueID() (string, error) {
|
||||
return "", fmt.Errorf("failed to generate unique ID after %d retries", maxRetries)
|
||||
}
|
||||
|
||||
// generateID returns a random ID drawn uniformly from idCharset. Bytes landing
|
||||
// in the last, partial repetition of the charset within a byte's range are
|
||||
// discarded rather than folded in with a bare modulo: 256 = 7*36 + 4, so
|
||||
// folding would make "a" through "d" about 14% more likely than the other 32
|
||||
// characters. Only 4 of 256 values are rejected, so a second read is rarely
|
||||
// needed.
|
||||
func generateID() string {
|
||||
bytes := make([]byte, idLength)
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
const unbiasedLimit = byte(256 - 256%len(idCharset))
|
||||
|
||||
id := make([]byte, 0, idLength)
|
||||
buf := make([]byte, idLength)
|
||||
for len(id) < idLength {
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for i, b := range bytes {
|
||||
bytes[i] = idCharset[int(b)%len(idCharset)]
|
||||
for _, b := range buf {
|
||||
if b >= unbiasedLimit {
|
||||
continue
|
||||
}
|
||||
id = append(id, idCharset[int(b)%len(idCharset)])
|
||||
if len(id) == idLength {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string(bytes)
|
||||
return string(id)
|
||||
}
|
||||
|
||||
func getHost(r *http.Request) string {
|
||||
|
||||
Reference in New Issue
Block a user