identity: add pkg for random id generation
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>docker-18.09
parent
d3c69bcd5b
commit
fa82d4bf5b
|
@ -0,0 +1,53 @@
|
||||||
|
package identity
|
||||||
|
|
||||||
|
import (
|
||||||
|
cryptorand "crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// idReader is used for random id generation. This declaration allows us to
|
||||||
|
// replace it for testing.
|
||||||
|
idReader = cryptorand.Reader
|
||||||
|
)
|
||||||
|
|
||||||
|
// parameters for random identifier generation. We can tweak this when there is
|
||||||
|
// time for further analysis.
|
||||||
|
const (
|
||||||
|
randomIDEntropyBytes = 17
|
||||||
|
randomIDBase = 36
|
||||||
|
|
||||||
|
// To ensure that all identifiers are fixed length, we make sure they
|
||||||
|
// get padded out or truncated to 25 characters.
|
||||||
|
//
|
||||||
|
// For academics, f5lxx1zz5pnorynqglhzmsp33 == 2^128 - 1. This value
|
||||||
|
// was calculated from floor(log(2^128-1, 36)) + 1.
|
||||||
|
//
|
||||||
|
// While 128 bits is the largest whole-byte size that fits into 25
|
||||||
|
// base-36 characters, we generate an extra byte of entropy to fill
|
||||||
|
// in the high bits, which would otherwise be 0. This gives us a more
|
||||||
|
// even distribution of the first character.
|
||||||
|
//
|
||||||
|
// See http://mathworld.wolfram.com/NumberLength.html for more information.
|
||||||
|
maxRandomIDLength = 25
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewID generates a new identifier for use where random identifiers with low
|
||||||
|
// collision probability are required.
|
||||||
|
//
|
||||||
|
// With the parameters in this package, the generated identifier will provide
|
||||||
|
// ~129 bits of entropy encoded with base36. Leading padding is added if the
|
||||||
|
// string is less 25 bytes. We do not intend to maintain this interface, so
|
||||||
|
// identifiers should be treated opaquely.
|
||||||
|
func NewID() string {
|
||||||
|
var p [randomIDEntropyBytes]byte
|
||||||
|
|
||||||
|
if _, err := io.ReadFull(idReader, p[:]); err != nil {
|
||||||
|
panic(fmt.Errorf("failed to read random bytes: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
p[0] |= 0x80 // set high bit to avoid the need for padding
|
||||||
|
return (&big.Int{}).SetBytes(p[:]).Text(randomIDBase)[1 : maxRandomIDLength+1]
|
||||||
|
}
|
Loading…
Reference in New Issue