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.8.8 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 · GitHub 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.

Last Post!

dimitarvp

dimitarvp

We use several systems and our app is the glue + the persistent layer keeping track of it all. Your point is valid and well understood – but happily not critical in this case.

Worst case scenario is that one of those external systems will know we’re sending some numbers back to our webhook. And those numbers expire and are unusable minutes later.

Where Next?

Popular in Questions Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54996 245
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New

We're in Beta

About us Mission Statement