Puid (puid v1.1.2)

Define modules for the efficient generation of cryptographically strong probably unique identifiers (<strong>puid</strong>s, aka random strings) of specified entropy from various character sets

Examples

The simplest usage of Puid requires no options. The library adds a generate/0 function for generating puids:

iex> defmodule(Id, do: use(Puid))
iex> Id.generate()
"p3CYi24M8tJNmroTLogO3b"

By default, Puid modules generate puids with at least 128 bits of entropy, making the puids suitable replacements for uuids.

Character Set

The default character set for Puid modules is the Base64 URL and file system safe character set specified in RFC 3548. Any of the pre-defined character sets from Puid.CharSet can easily be specified using the charset option:

iex> defmodule(HexId, do: use(Puid, charset: :hex))
iex> HexId.generate()
"a60dec6d0b71355aa9579bb46c001700"

Custom Characters

Any sequence of unique, printable characters can be used to generate puids.

iex> defmodule(DingoSkyId, do: use(Puid, chars: "dingosky"))
iex> DingoSkyId.generate()
"yoisknoydoknkoikgoknynkinoknkygdiikoosksyni"

iex> defmodule(UnicodeId, do: use(Puid, chars: "ŮήιƈŏδεĊħąŕαсτəř"))
iex> UnicodeId.generate()
"αήήδħƈĊŕąąιŏήąŕħƈδəəήιττδδŕąĊδŕι"

Specific Entropy

Bits

The bits option can be used to specify desired entropy bits.

iex> defmodule Password, do: use Puid, bits: 96, charset: :printable_ascii
iex> Password.generate()
"0&pu=w+T#~o)N=E"

Since the total entropy bits of a puid must be a multiple of the entropy bits per character used, the actual puid bits will be equal to or greater than specified. In the example above, the entropy bits of a Password generated puid is actually 98.32.

Total and Risk

The amount of entropy can be intuitively specified through the total and risk options. For example, to generate a total of 10 million puids with a 1 in a quadrillion risk of repeat using :safe32 characters:

iex> defmodule(Safe32Id, do: use(Puid, total: 1.0e7, risk: 1.0e15, charset: :safe32))
iex> Safe32Id.generate()
"hjM7md2R9j8D7PNTjBPB"

The actual Safe32Id puid entropy bits is 100.

Custom Randomness

Puid generates puids using bytes from the function specified with the rand_bytes option. If rand_bytes is not specified, Puid defaults to :crypto.strong_rand_bytes/1.

iex> defmodule(MyRandBytesId, do: use(Puid, bits: 96, charset: :safe32, rand_bytes: &MyRand.bytes/1))
iex> MyRandBytesId.generate()
"G2jrmPr3mQPBt2gGB3T4"

The MyRand.bytes/1 function must be of the form (non_neg_integer) -> binary()

Module Functions

Puid adds the following 2 functions to each created module:

FunctionDescription
generate/0function for generating a puid
info/0Puid.Info struct of module information

The Puid.Info struct has the following fields:

FieldDescription
charssource character set
charsetpre-defined Puid.Charset or :custom
entropy_bitsentropy bits for generated puids
entropy_bits_per_charentropy bits per character for generated puids
erepuid entropy string representation efficiency
lengthpuid string length
rand_bytesentropy source function
iex> defmodule(AlphanumId, do: use(Puid, total: 10e06, risk: 1.0e15, charset: :alphanum))
iex> AlphanumId.info()
%Puid.Info{
  chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
  charset: :alphanum,
  entropy_bits: 107.18,
  entropy_bits_per_char: 5.95,
  ere: 0.74,
  length: 18,
  rand_bytes: &:crypto.strong_rand_bytes/1
}