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
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
Hi! I see two scenarios (sorry if I’m misreading your post):
- 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.
- 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.exsand then call these two functions”
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
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #podcasts
- #code-sync
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








