SipHash v2.0.0 SipHash.State

Module for representing state and state transformations of a digest whilst moving through the hasing pipeline. Note that we use tuples rather than structs due to a ~5 µs/op speedup. This module makes use of NIFs to improve performance.

Summary

Functions

Applies a block (an 8-byte chunk) to the digest, and returns the state after transformation. If a binary chunk is passed in, it’s converted to a number (as little endian) before being passed to the main body. First we XOR v3 before compressing the state twice. Once complete, we then XOR v0, and return the final state

Applies a last-block transformation to the digest. This block may be less than 8-bytes, and if so we pad it left with zeroed bytes (up to 7 bytes). We then add the length of the input as a byte and update using the block as normal

Performs the equivalent of SipRound on the provided state, making sure to mask numbers as it goes (because Elixir precision gets too large). Once all steps are completed, the new state is returned

Provides a recursive wrapper around SipHash.Util.compress/1. Used to easily modify the c-d values of the SipHash algorithm

Finalizes a digest by XOR’ing v2 and performing SipRound d times. After the rotation, all properties of the state are XOR’d from left to right

Loads any NIFs needed for this module, logging out a message depending on whether the load was successful or not. Because we have a valid fallback implementation, we don’t have to exit on failure

Initializes a state based on an input key, using the technique defined in the SipHash specifications. First we take the input key, split it in two, and convert to the little endian version of the bytes. We then create a struct using the magic numbers and XOR them against the two key words created

Rotates an input number val left by shift number of bits. Bits which are pushed off to the left are rotated back onto the right, making this a left rotation (a circular shift)

Types

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

Functions

apply_block(state, m, c)

Specs

apply_block(s, binary | number, number) :: s

Applies a block (an 8-byte chunk) to the digest, and returns the state after transformation. If a binary chunk is passed in, it’s converted to a number (as little endian) before being passed to the main body. First we XOR v3 before compressing the state twice. Once complete, we then XOR v0, and return the final state.

apply_last_block(state, len, c_pass)

Specs

apply_last_block({number, s, number} | s, number, number) :: s

Applies a last-block transformation to the digest. This block may be less than 8-bytes, and if so we pad it left with zeroed bytes (up to 7 bytes). We then add the length of the input as a byte and update using the block as normal.

compress(arg)

Specs

compress(s) :: s

Performs the equivalent of SipRound on the provided state, making sure to mask numbers as it goes (because Elixir precision gets too large). Once all steps are completed, the new state is returned.

Incidentally, this function is named SipHash.State.compress/1 rather than SipHash.State.round/1 to avoid clashing with Kernel.round/1 internally.

As of v2.0.0, this function is overridden with a native implementation when available in order to speed up the translations. This results in a ~10 µs/op speed decrease, and so this should be treated as a fallback state only.

compress(state, n)

Specs

compress(s, number) :: s

Provides a recursive wrapper around SipHash.Util.compress/1. Used to easily modify the c-d values of the SipHash algorithm.

finalize(arg, d)

Specs

finalize(s, number) :: s

Finalizes a digest by XOR’ing v2 and performing SipRound d times. After the rotation, all properties of the state are XOR’d from left to right.

init()

Loads any NIFs needed for this module, logging out a message depending on whether the load was successful or not. Because we have a valid fallback implementation, we don’t have to exit on failure.

initialize(key)

Specs

initialize(binary) :: s

Initializes a state based on an input key, using the technique defined in the SipHash specifications. First we take the input key, split it in two, and convert to the little endian version of the bytes. We then create a struct using the magic numbers and XOR them against the two key words created.

rotate_left(val, shift)

Specs

rotate_left(number, number) :: number

Rotates an input number val left by shift number of bits. Bits which are pushed off to the left are rotated back onto the right, making this a left rotation (a circular shift).

Examples

iex> SipHash.State.rotate_left(8, 3)
64

iex> SipHash.State.rotate_left(3, 8)
768