github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/identity/randomid.go (about) 1 package identity 2 3 import ( 4 cryptorand "crypto/rand" 5 "fmt" 6 "io" 7 "math/big" 8 ) 9 10 var ( 11 // idReader is used for random id generation. This declaration allows us to 12 // replace it for testing. 13 idReader = cryptorand.Reader 14 ) 15 16 // parameters for random identifier generation. We can tweak this when there is 17 // time for further analysis. 18 const ( 19 randomIDEntropyBytes = 17 20 randomIDBase = 36 21 22 // To ensure that all identifiers are fixed length, we make sure they 23 // get padded out or truncated to 25 characters. 24 // 25 // For academics, f5lxx1zz5pnorynqglhzmsp33 == 2^128 - 1. This value 26 // was calculated from floor(log(2^128-1, 36)) + 1. 27 // 28 // While 128 bits is the largest whole-byte size that fits into 25 29 // base-36 characters, we generate an extra byte of entropy to fill 30 // in the high bits, which would otherwise be 0. This gives us a more 31 // even distribution of the first character. 32 // 33 // See http://mathworld.wolfram.com/NumberLength.html for more information. 34 maxRandomIDLength = 25 35 ) 36 37 // NewID generates a new identifier for use where random identifiers with low 38 // collision probability are required. 39 // 40 // With the parameters in this package, the generated identifier will provide 41 // ~129 bits of entropy encoded with base36. Leading padding is added if the 42 // string is less 25 bytes. We do not intend to maintain this interface, so 43 // identifiers should be treated opaquely. 44 func NewID() string { 45 var p [randomIDEntropyBytes]byte 46 47 if _, err := io.ReadFull(idReader, p[:]); err != nil { 48 panic(fmt.Errorf("failed to read random bytes: %v", err)) 49 } 50 51 p[0] |= 0x80 // set high bit to avoid the need for padding 52 return (&big.Int{}).SetBytes(p[:]).Text(randomIDBase)[1 : maxRandomIDLength+1] 53 }