Skip to content

Instantly share code, notes, and snippets.

@bluzky
Created August 20, 2021 03:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bluzky/68e3c0e698e74e9b54edbeccf9ebb735 to your computer and use it in GitHub Desktop.
Save bluzky/68e3c0e698e74e9b54edbeccf9ebb735 to your computer and use it in GitHub Desktop.
Elixir encrypt/decrypt using Erlang :crypto module
defmodule Magik.Crypto do
@moduledoc """
Provide some basic encrypt/decrypt function
"""
@aad "AES256GCM"
@block_size 16
@doc """
`generate_secret`
Generates a random 16 byte and encode base64 secret key.
"""
def generate_secret do
:crypto.strong_rand_bytes(@block_size)
|> :base64.encode()
end
@doc """
Encrypt data using `:aes_128_cbc` mode, and return base64 encrypted string
key = generate_secret()
encrypt("hello", key)
"""
@spec encrypt(String.t(), String.t()) :: String.t()
def encrypt(plaintext, secret_key) do
secret_key = :base64.decode(secret_key)
iv = :crypto.strong_rand_bytes(@block_size)
plaintext = pad(plaintext, @block_size)
ciphertext = :crypto.crypto_one_time(:aes_128_cbc, secret_key, iv, plaintext, true)
:base64.encode(iv <> ciphertext)
end
@doc """
Decode cipher data which encrypted using `encrypt/2`
key = generate_secret()
cipher = encrypt("hello", key)
decrypt(cipher, key)
"""
def decrypt(ciphertext, secret_key) do
secret_key = :base64.decode(secret_key)
ciphertext = :base64.decode(ciphertext)
<<iv::binary-@block_size, ciphertext::binary>> = ciphertext
:crypto.crypto_one_time(:aes_128_cbc, secret_key, iv, ciphertext, false)
|> unpad
end
@doc """
Encrypt data using `:aes_128_cbc` mode, and return base64 encrypted string
key = generate_secret()
encrypt_aead("hello", key)
"""
def encrypt_aead(plaintext, secret_key) do
secret_key = :base64.decode(secret_key)
iv = :crypto.strong_rand_bytes(@block_size)
{ciphertext, ciphertag} =
:crypto.crypto_one_time_aead(:aes_128_gcm, secret_key, iv, plaintext, @aad, true)
(iv <> ciphertag <> ciphertext)
|> :base64.encode()
end
@doc """
Decode cipher data which encrypted using `encrypt/2`
key = generate_secret()
cipher = encrypt_aead("hello", key)
decrypt_aead(cipher, key)
"""
def decrypt_aead(ciphertext, secret_key) do
secret_key = :base64.decode(secret_key)
ciphertext = :base64.decode(ciphertext)
<<iv::binary-@block_size, tag::binary-@block_size, ciphertext::binary>> = ciphertext
:crypto.crypto_one_time_aead(:aes_128_gcm, secret_key, iv, ciphertext, @aad, tag, false)
end
defp pad(data, block_size) do
to_add = block_size - rem(byte_size(data), block_size)
data <> :binary.copy(<<to_add>>, to_add)
end
defp unpad(data) do
to_remove = :binary.last(data)
:binary.part(data, 0, byte_size(data) - to_remove)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment