-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
identity: add pkg for random id generation
Signed-off-by: Tonis Tiigi <[email protected]>
- Loading branch information
1 parent
d3c69bc
commit fa82d4b
Showing
1 changed file
with
53 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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] | ||
} |