dimitarvp

dimitarvp

One-off encryption?

Hey all,
I am looking for a way to encode and then encrypt a payload that will later be passed to a webhook in the web app.

We’re talking something like “put these two options in your config/config.exs and then call these two functions”.

What’s a very quick and low-friction way to encrypt a binary (and subsequently decrypt it)? I am not looking for the best security here; I am looking for something to discourage a potential attacker that might be able to sniff an HTTP request with an encoded parameter in it.

Marked As Solved

lud

lud

Why not just generate a random string, store it in the database and send that ? (or a hash like @derek-zhou said.)

So even if someone sniffs it, it is meaningless. Is there a fundamental problem to send a value that is also stored in the database, it the value is just a one-time key for fetching?

Also Liked

hauptbenutzer

hauptbenutzer

Hi! I see two scenarios (sorry if I’m misreading your post):

  1. You do not care about the encoded information being read but just want to make sure it was not tempered with. In this case signing might be sufficient and you can use Phoenix.Token — Phoenix v1.6.2 or similar which is low-friciton if you’re already using phoenix.
  2. If you want the encoded data to be safe from prying eyes use something like GitHub - danielberkompas/cloak: Elixir encryption library designed for Ecto which implements best practices around erlang crypto so you don’t need to worry about the details (like IVs). This is very close to "put these two options in your config/config.exs and then call these two functions”
hauptbenutzer

hauptbenutzer

Well you can certainly choose to use :crypto directly but you’ll have to take care of IVs and padding yourself. We ended up doing something like this (note that this has a hardcoded IV size of 16):

defmodule CryptoOneTime do
  require Logger 
  
  def encrypt_binary(data) when is_binary(data) do
    initialization_vector = :crypto.strong_rand_bytes(16)
    plaintext = pad(data, 16)
    encrypted_text = :crypto.crypto_one_time(:aes_128_cbc, secret_key(), initialization_vector, plaintext, true)

    :base64.encode(initialization_vector <> encrypted_text)
  end

  def decrypt_binary(ciphertext) when is_binary(ciphertext) do
    <<initialization_vector::binary-16, ciphertext::binary>> = Base.decode64!(ciphertext)

    plaintext =
      :aes_128_cbc
      |> :crypto.crypto_one_time(secret_key(), initialization_vector, ciphertext, false)
      |> unpad()

    {:ok, plaintext}
  rescue
    error in ArgumentError ->
      Logger.error(Exception.format(:error, error, __STACKTRACE__))
      :error
  end

  def decrypt_binary(_non_binary_value), do: :error

  defp secret_key do
    # this needs to be 128 bits of class-a randomness
  end

  defp unpad(data) do
    :binary.part(data, 0, byte_size(data) - :binary.last(data))
  end

  defp pad(data, block_size) do
    padding = block_size - rem(byte_size(data), block_size)
    data <> :binary.copy(<<padding>>, padding)
  end
end
derek-zhou

derek-zhou

The best way to keep something secret is not to transmit it, encrypted or not. I would put said payload in a database, get the sequence id and just send the id with hashids

This way you send a very short string regardless how large is the payload.

hauptbenutzer

hauptbenutzer

The IV is computed for every encrypt so that encrypting the same payload twice yields different results (similar idea as a salt). It’s prepended to the encrypted payload, so that it can be read and used for decryption. So you only need to keep the secret key in your config.exs (or runtime.exs more likely :slight_smile:)

derek-zhou

derek-zhou

Hashid is not very secure. to add extra protection on tempering, you can append a sha3 hash.

Where Next?

Popular in Questions Top

polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement