# Expose encrypted serial ID in Elixir

I'm working on a Phoenix/Absinthe application and I thought to expose encrypted sequential IDs instead of UUIDs since these are a bit shorter. Encryption on Elixir/Erlang seems very hard, so I think I'll use UUIDs eventually.

Anyway I'd like to know how bad, from security perspective, is the solution I came up with:

defmodule MyAppWeb.GraphQL.Types.EncId do
use Absinthe.Schema.Notation

defp secret_key(len \\ 32) do
Application.get_env(:my_app, MyAppWeb.Endpoint)
|> Keyword.get(:secret_key_base, "")
|> String.slice(0, len)
end

defp pad_bytes(binary, block \\ 16) do
case rem(byte_size(binary), block) do
0 -> 0
r -> (block - r) * 8
end

end

defp encrypt(raw_binary) do

end

defp decrypt(raw_enc) do
:crypto.crypto_one_time(:aes_256_ecb, secret_key(), raw_enc, false)
|> :erlang.binary_to_term()
end

def serialize(id) do
id
|> :erlang.term_to_binary()
|> encrypt()
end

def parse(%{value: enc_id}) do
try do
{:ok, raw_enc} = Base.url_decode64(enc_id, padding: false)
{:ok, decrypt(raw_enc)}
rescue
_ -> :error
end
end

scalar :enc_id, name: "EncId" do
serialize(&__MODULE__.serialize/1)

parse(&__MODULE__.parse/1)
end
end


I don't understand why encryption would be "hard" - the code above looks straightforward enough although I'm not sure you need the padding (never tried the new crypto APIs).

Do note that if you want to secure your UUIDs (why?), you probably want to add a random IV to your UUIDs otherwise you'll probably expose too much information - UUIDs have some bits very static. Generally speaking, rolling your own crypto protocol is fraught with error; I would use an existing library like Hashids (https://hexdocs.pm/hashids/Hashids.html) because that protocol has been analyzed and you're probably better off with the mild known weaknesses in such a library than some huge unknown weakness lurking in roll-your-own :).

But for all practical purposes, generating v4 UUIDs using a cryptographically strong RNG should be all you need.