defmodule SimpleCrypto do require Logger def encrypt(str, key) do Base.encode64( :crypto.crypto_one_time( :aes_ecb, String.slice(pad(key), 0, 32), pad(Integer.to_string(byte_size(str)) <> "|" <> str), true ) ) end def decrypt(str, key) do decrypted = :crypto.crypto_one_time( :aes_ecb, String.slice(pad(key), 0, 32), pad(elem(Base.decode64(str), 1)), false ) case Regex.run(~r/(\d+)\|/, decrypted) do nil -> decrypted [match, len] -> Kernel.binary_part(decrypted, byte_size(match), String.to_integer(len)) end end def sha256(str) do :crypto.hash(:sha256, str) |> Base.encode16() end def hmac(str, key) do :crypto.mac(:hmac, :sha256, key, str) |> Base.encode16() end def rand_str(length) do :crypto.strong_rand_bytes(length) |> Base.url_encode64() |> binary_part(0, length) end def rand_int_str(num_of_digits) do len = :math.pow(10, num_of_digits) |> round() Enum.random(0..len) |> Integer.to_string() |> String.pad_leading(4, "0") end def otp_rand_str(length \\ 16) do String.replace(String.replace(String.upcase(rand_str(length)), ~r([-_]), "N"), ~r(\d), "U") end def id_rand_str(length) do String.replace(rand_str(length), ~r([-_]), "w") end def pad(binary, width \\ 16, char \\ " ") do # TODO: Use String.pad_trailing/2 instead? case rem(width - rem(byte_size(binary), width), width) do 0 -> binary n -> binary <> String.duplicate(char, n) end end end