[Solved] :crypto.block_encrypt/decrypt - symmetric?

Hello !

I was expecting :crypto.block_encrypt :aes_ige256 to be symmetric, I don’t get what’s wrong. Can someone enlighten me ?

Here is an example script :

data = <<666::size(256)-unit(8)>>
tmp_aes_key = <<1234567890::size(32)-unit(8)>>
tmp_aes_iv = <<0987654321::size(32)-unit(8)>>

encrypted = :crypto.block_encrypt :aes_ige256, tmp_aes_key, tmp_aes_iv, data
decrypted = :crypto.block_decrypt :aes_ige256, tmp_aes_key, tmp_aes_iv, data

IO.puts "-- Initial Data --"
IO.inspect data
IO.puts "-- Encrypted --"
IO.inspect encrypted
IO.puts "-- Decrypted --"
IO.inspect decrypted

And its output :

-- Initial Data --
<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...>>
-- Encrypted --
<<13, 146, 170, 197, 88, 244, 100, 48, 180, 234, 28, 168, 36, 10, 88, 225, 15,
  232, 33, 201, 90, 37, 54, 105, 155, 70, 166, 40, 128, 12, 107, 11, 234, 61,
  80, 202, 89, 18, 222, 125, 127, 133, 98, 236, 28, 107, 254, 155, 130, 223,
  ...>>
-- Decrypted --
<<200, 243, 4, 223, 10, 44, 240, 101, 171, 77, 103, 159, 39, 239, 138, 91, 108,
  248, 162, 162, 228, 170, 138, 113, 98, 56, 248, 183, 167, 19, 123, 243, 162,
  144, 214, 253, 136, 98, 37, 210, 14, 108, 56, 31, 33, 222, 148, 228, 183, 8,
  ...>>

Thanks !

2 Likes

Shouldn’t data here be encrypted?

3 Likes

Ow, my bad. tired

1 Like

Hehe, happens to us all. ^.^

Also you can click the checkmark on a post to mark that post as the one that resolves the issue. :slight_smile:

2 Likes

For posterity: don’t use :crypto.block_encrypt for anything new you are writing.

Instead, use :crypto:crypto_one_time.

See here for info: http://erlang.org/doc/apps/crypto/new_api.html

1 Like

Hi, I had these 2 methods

  def encode(args) do
    message = format_token_message(args)

    encrypted_message =
      :crypto.block_encrypt(
        :aes_cbc256,
        System.get_env()["SNAP_KEY"],
        System.get_env()["SNAP_IV"],
        message
      )

    Base.url_encode64(encrypted_message)
  end

  def decode(token) do
    encrypted_message = Base.url_decode64!(token)

    message =
      :crypto.block_decrypt(
        :aes_cbc256,
        System.get_env()["SNAP_KEY"],
        System.get_env()["SNAP_IV"],
        encrypted_message
      )

    message |> String.split("|") |> List.delete_at(-1)
  end

I am trying make them work with :crypto:crypto_one_time/4, 5

When I do this

    encrypted_message =
      :crypto:crypto_one_time(
        :aes_cbc256,
        System.get_env()["SNAP_KEY"],
        System.get_env()["SNAP_IV"],
        message,
        true
      )

    Base.url_encode64(encrypted_message)

it says:

# Erlang error: {:badarg, {'api_ng.c', 141}, 'Unknown cipher'}

any clue?

The new API only accepts the algorithm atom values listed in the latest :crypto module docs. So :aes_cbc256 should be :aes_256_cbc.

but how a same module can do encrypt and decrypt both?

just the last flag for true and false will decide ? its ecrypt or decrypt ?

Yes, the last argument is actually an option list, so you could do:

ciphertext = :crypto:crypto_one_time(:aes_256_cbc, key, iv, message, encrypt: true)
plaintext = :crypto:crypto_one_time(:aes_256_cbc, key, iv, ciphertext, encrypt: false)

Passing true or false instead is just a shortcut.

thank you.

IMPORTANT: unless this code is called with a different value in SNAP_IV every time, there is a potential security hole when reusing an IV with CBC:

https://cwe.mitre.org/data/definitions/329.html

SNAP_IV is the same each time.

also the SNAP_KEY.