From a434c693d58165b881aa1997edb998447f70a508 Mon Sep 17 00:00:00 2001 From: Moon Man Date: Sun, 25 Aug 2024 22:05:24 +0000 Subject: [PATCH] encrypted ids work --- README.md | 3 ++ config/dev.exs | 4 ++- lib/vonbraun/control.ex | 11 +++++++ lib/vonbraun/crypto_id.ex | 63 +++++++++++++++++++++++++++++++++++++++ vm.args | 2 ++ 5 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 lib/vonbraun/control.ex create mode 100644 lib/vonbraun/crypto_id.ex create mode 100644 vm.args diff --git a/README.md b/README.md index 2205244..dc96774 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # vonbraun +Run: + +elixir --erl '-args_file vm.args' -S mix run --no-halt diff --git a/config/dev.exs b/config/dev.exs index 7ae8ef7..940e20f 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -12,4 +12,6 @@ config :vonbraun, nickname: "moonman", domain: "vonbraun.discontent.top", summary: "I am the famous Fediverse Moon", - approve_followers: false + approve_followers: false, + # MUST be 32 + id_key: "53F0CB234DA3DB1A43AE32DE4038516B" diff --git a/lib/vonbraun/control.ex b/lib/vonbraun/control.ex new file mode 100644 index 0000000..653243a --- /dev/null +++ b/lib/vonbraun/control.ex @@ -0,0 +1,11 @@ +defmodule Vonbraun.Control do + def follow(id) when is_binary(id) do + end + + def unfollow(id) when is_binary(id) do + end + + def post_note(content, public?, to \\ []) + when is_binary(content) and is_list(to) and is_boolean(public?) do + end +end diff --git a/lib/vonbraun/crypto_id.ex b/lib/vonbraun/crypto_id.ex new file mode 100644 index 0000000..46a581d --- /dev/null +++ b/lib/vonbraun/crypto_id.ex @@ -0,0 +1,63 @@ +defmodule Vonbraun.CryptoID do + require Logger + + @spec encrypt(integer()) :: String.t() + @spec encrypt(integer(), <<_::128>>) :: String.t() + def encrypt(epoch_milliseconds, <> \\ :crypto.strong_rand_bytes(16)) + when is_integer(epoch_milliseconds) do + key = Application.fetch_env!(:vonbraun, :id_key) |> Base.decode16!() + + encrypted = + :crypto.crypto_one_time(:aes_128_ctr, key, iv, <>, true) + + Logger.debug("bytes length of encrypted: #{byte_size(encrypted)}") + Base.encode16(iv <> encrypted) + end + + def to_milliseconds(<>) do + key = Application.fetch_env!(:vonbraun, :id_key) |> Base.decode16!() + + with {:iv_decode, {:ok, iv}} <- {:iv_decode, Base.decode16(iv_hex)}, + {:decode, {:ok, encrypted_bytes}} <- {:decode, Base.decode16(encrypted_payload)}, + {:decrypt, <>} <- + {:decrypt, :crypto.crypto_one_time(:aes_128_ctr, key, iv, encrypted_bytes, false)} do + {:ok, epoch_milliseconds} + else + {:iv_decode, :error} -> + {:error, :iv_decode} + + {:decode, :error} -> + {:error, :base16_decode} + + {:decrypt, _} -> + {:error, :integer_decrypt} + end + end + + def encrypt_id(epoch_milliseconds) when is_integer(epoch_milliseconds) do + encrypted_milliseconds = encrypt(epoch_milliseconds) + instance = Application.fetch_env!(:vonbraun, :domain) + + "https://#{instance}/id/#{encrypted_milliseconds}" + end + + def now!() do + epoch_milliseconds = System.system_time(:microsecond) + id = encrypt_id(epoch_milliseconds) + + {id, epoch_milliseconds} + end + + def decrypt_id(id) when is_binary(id) do + instance = Application.fetch_env!(:vonbraun, :domain) + prefix = "https://#{instance}/id/" + + with {:prefix, ^prefix <> <>} <- {:prefix, id}, + {:ms, {:ok, milliseconds}} <- {:ms, to_milliseconds(payload)} do + {:ok, milliseconds} + else + {:prefix, _} -> {:error, :prefix_unmatch} + {:ms, {:error, error}} -> {:error, error} + end + end +end diff --git a/vm.args b/vm.args new file mode 100644 index 0000000..72493a8 --- /dev/null +++ b/vm.args @@ -0,0 +1,2 @@ +-name vb@falco +-setcookie cookie