OptimusHash (OptimusHash v0.2.0) View Source

OptimusHash is a small library to do integer hashing based on Knuth's multiplicative hashing algorithm. The algorithm is fast, reversible and has zero collisions.

This comes in very handy when you have e.g. integer-based primary keys in your database and you don't want to expose them to the outside world.

Usage

To get started, you will need three values: a prime number, the modular multiplicative inverse of that prime number, and a random number. There is a built-in task to generate those values for you—see the section about seeding.

Warning: Before you use this library in production, you should think about the largest possible ID you will have. OptimusHash supports IDs up to 2,147,483,647 by default. If you need larger IDs, you will need to pass the max_size option to new/1. Since this change will affect the results of encode/2 and decode/2 you have to plan ahead.

Seeding

This package comes with a Mix task to generate the required configuration values for you. The task requires the openssl binary to be installed on your system. If you don't want to or can't install it, you will have to calculate or find a prime number yourself. A good starting point is the the list of the first fifty million primes.

$ mix optimus_hash.seed
Configuration:

  - prime: 2120909159
  - mod_inverse: 1631586903
  - random: 1288598321
  - max_size: 31

Code:

```
OptimusHash.new(
  prime: 2_120_909_159,
  mod_inverse: 1_631_586_903,
  random: 1_288_598_321,
  max_size: 31
)
```

Please do not use the example values used in this documentation for your production environment. That would be silly.

You can set the size of the largest possible by passing --bits=40. If you already have a prime number you can pass it in as the first argument: mix optimus_hash.seed --bits=62 3665010176750768309.

Link to this section Summary

Functions

Decodes the given number and returns the result.

Encodes the given number and returns the result.

Creates a new struct containing the configuration options for OptimusHash. This struct must be passed as the first argument to encode/2 and decode/2.

Link to this section Types

Specs

t() :: %OptimusHash{
  max_id: non_neg_integer(),
  mod_inverse: non_neg_integer(),
  prime: non_neg_integer(),
  random: non_neg_integer()
}

Link to this section Functions

Specs

decode(t(), non_neg_integer()) :: non_neg_integer()

Decodes the given number and returns the result.

iex> OptimusHash.decode(o, 458_047_115)
1

Specs

encode(t(), non_neg_integer()) :: non_neg_integer()

Encodes the given number and returns the result.

iex> OptimusHash.encode(o, 1)
458_047_115

Specs

new(Keyword.t()) :: t()

Creates a new struct containing the configuration options for OptimusHash. This struct must be passed as the first argument to encode/2 and decode/2.

NOTE: Keep this configuration values secret.

Options

  • :prime - A prime number which is smaller than :max_id.
  • :mod_inverse - The modular multiplicative inverse of the provided prime number. Must fulfill the constraint (prime * mod_inverse) & max_id == 1
  • :random - A random integer smaller than :max_id
  • :max_size (optional) - The maximum number of bits for the largest id. Defaults to 31
  • :validate (optional) - Flag to toggle prime number and mod inverse validation. Defaults to true

Examples

iex> OptimusHash.new([prime: 1580030173, mod_inverse: 59260789, random: 1163945558])
%OptimusHash{prime: 1580030173, mod_inverse: 59260789, random: 1163945558, max_id: 2147483647}