SipHash v2.0.0 SipHash

Module for hashing values using the SipHash hash family.

This module makes use of NIFs for better performance and throughput, but this can be disabled by setting the HASH_IMPL environment variable to embedded. This is controlled via the environment rather than a specific function arg as the NIFs are automatically loaded during the start of the application. Please note that the use of NIFs brings a significant performance improvement, and so you should only disable them with good reason.

Summary

Functions

Based on the algorithm as described in https://131002.net/siphash/siphash.pdf, and therefore requires a key alongside the input to use as a seed. This key is required to be 16 bytes, and is measured by Kernel.byte_size/1. An error will be raised if this is not the case. The default implementation is a 2-4 hash, but this can be controlled through the options provided

Wrapper around SipHash.hash/3 to rotate the arguments, allowing for more convenient usage when creating a pipeline (you can rotate key/input as needed)

Types

s :: {number, number, number, number}

Functions

hash(key, input, opts \\ [])

Specs

hash(binary, binary, [{atom, atom}]) :: binary

Based on the algorithm as described in https://131002.net/siphash/siphash.pdf, and therefore requires a key alongside the input to use as a seed. This key is required to be 16 bytes, and is measured by Kernel.byte_size/1. An error will be raised if this is not the case. The default implementation is a 2-4 hash, but this can be controlled through the options provided.

Your input must be a binary. It’s possible to add a catch-all to SipHash.hash/3 which simply wraps the input in Kernel.inspect/2, but such usage is not encourage. It’s better to be more explicit about what is being hashed, and Kernel.inspect/2 does not always perform the fastest available conversion (for example, using Poison to encode Maps is far faster, whilst also being more reliable). In addition, the output of Kernel.inspect/2 is specific to Elixir, making it annoyingly unportable.

By default, all values are returned as numbers (i.e. the result of the hash), but you can set :hex to true as an option to get a hex string output. The reason for this is that converting to hex takes an extra couple of µs, and the default is intended to be the optimal use case. Please note that any of the options related to hex string formatting will be ignored if :hex is not set to true (e.g. :case).

Options

  • :case - either of :upper or :lower, defaults to using :upper
  • :c and :d - the number of compression rounds, default to 2 and 4
  • :hex - when true returns the output as a hex string
  • :padding - when true, pads left with zeroes to 16 chars as necessary

Examples

iex> SipHash.hash("0123456789ABCDEF", "hello")
4402678656023170274

iex> SipHash.hash("0123456789ABCDEF", "hello", hex: true)
"3D1974E948748CE2"

iex> SipHash.hash("0123456789ABCDEF", "abcdefgh", hex: true)
"1AE57886F899E65F"

iex> SipHash.hash("0123456789ABCDEF", "my long strings", hex: true)
"1323400B0804036D"

iex> SipHash.hash("0123456789ABCDEF", "hello", hex: true, case: :lower)
"3d1974e948748ce2"

iex> SipHash.hash("0123456789ABCDEF", "zymotechnics", hex: true, padding: :true)
"09B57037CD3F8F0C"

iex> SipHash.hash("0123456789ABCDEF", "hello", c: 4, d: 8)
14986662229302055855

iex> SipHash.hash("invalid_bytes", "hello")
** (RuntimeError) Key must be exactly 16 bytes.

iex> SipHash.hash("FEDCBA9876543210", %{ "test" => "one" })
** (FunctionClauseError) no function clause matching in SipHash.hash/3
hash_r(input, key_or_state, opts \\ [])

Specs

hash_r(binary, binary | s, [{atom, atom}]) :: binary

Wrapper around SipHash.hash/3 to rotate the arguments, allowing for more convenient usage when creating a pipeline (you can rotate key/input as needed).

Examples

iex> SipHash.hash_r("hello", "0123456789ABCDEF")
4402678656023170274