FeistelCipher
View SourceDatabase functions for Feistel cipher.
This library provides Mix tasks and Ecto migrations to set up and manage Feistel cipher functions and triggers in your PostgreSQL database. Feistel cipher can be used to generate reversible, non-sequential IDs from sequential numbers.
Installation
You can install FeistelCipher using igniter
or by manually adding it to your dependencies.
Using igniter
mix igniter.install feistel_cipher
Manual Installation
Add
feistel_cipher
to your list of dependencies inmix.exs
:def deps do [ {:feistel_cipher, "~> 0.1.0"} ] end
Fetch the dependencies:
mix deps.get
Run the installer to generate the initial migration files:
mix feistel_cipher.install
This command will generate a migration file in your
priv/repo/migrations
directory. You can customize the installation with the following options:-
--repo
or-r
: Specify the Ecto repo for FeistelCipher to use (e.g.,MyApp.Repo
). Defaults toYourApp.Repo
. -
--prefix
or-p
: Specify a schema prefix for the FeistelCipher functions (e.g.,my_app_prefix
). Defaults topublic
.
-
Example Ecto Schema
Below is an example of an Ecto schema for a table that uses a Feistel cipher. In this common setup:
- The
seq
column is aBIGSERIAL
(auto-incrementing integer) in the database, serving as the source for the Feistel cipher. - The
id
column is aBIGINT
primary key, and its value is automatically generated by a database trigger using theseq
column.
defmodule MyApp.MyTable do
use Ecto.Schema
# Defines `id` as the primary key (typically BIGINT in the DB).
# `autogenerate: true` indicates that its value is set by a database trigger
# based on the Feistel cipher of the `seq` column, not by a DB sequence directly on `id`.
@primary_key {:id, :id, autogenerate: true}
@foreign_key_type :id # For foreign keys referencing this table's `id`.
schema "my_table" do
# `seq` is the source for the Feistel cipher. In the database, this is typically a BIGSERIAL column.
# Ecto's `:id` type with `autogenerate: true` here reflects the auto-incrementing nature
# of a BIGSERIAL column when mapped in Ecto for a non-primary key field.
field :seq, :id, autogenerate: true
# The `id` field itself (the primary key) is implicitly defined by @primary_key.
# Its value will be populated by the Feistel cipher trigger.
timestamps()
end
end
When creating the actual database table via a migration:
- You would define
seq
asBIGSERIAL
. - You would define
id
asBIGINT
and set it as the primary key. The Ecto schema above reflects how Ecto maps these PostgreSQL types and their behaviors. Thefeistel_cipher
trigger will take the auto-generatedseq
value and populate theid
column with the Feistel-ciphered value.
Creating Triggers for Tables
To automatically encrypt a source column into a target column for a specific table, you can create a database trigger. The FeistelCipher.Migration.up_sql_for_table/2
function helps generate the necessary SQL.
For example, if you have a table named posts
with a seq
column (source) and you want to store the Feistel ciphered ID in an id
column (target):
# Example: priv/repo/migrations/YYYYMMDDHHMMSS_add_posts_feistel_trigger.exs
defmodule MyApp.Repo.Migrations.AddPostsFeistelTrigger do
use Ecto.Migration
def up do
# Default bits: 62
execute FeistelCipher.Migration.up_sql_for_table("posts", bits: 40, source: "seq", target: "id")
end
def down do
execute FeistelCipher.Migration.down_sql_for_table("posts", bits: 40, source: "seq", target: "id")
end
end
Then run mix ecto.migrate
to apply the migration.
The up_sql_for_table/2
function accepts the following options:
-
table
: (String, required) The name of the table. -
source
: (String, required) The name of the source column containing thebigint
integer (typically from aBIGSERIAL
column likeseq
). -
target
: (String, required) The name of the target column to store the encrypted integer (typically theBIGINT
primary key likeid
). -
bits
: (Integer, optional) The number of bits for the Feistel cipher. Must be an even number, 62 or less. Defaults to62
.
The trigger will automatically populate the target
column when a new row is inserted. It also prevents manual modification of the target
column on update.
License
MIT