byron

byron

Need to decrypt an AES encrypted string that was encrypted in flutter https://pub.dev/packages/encrypt

Hi guys,

I battling to decrypt a string that was encrypted using this
encrypt | Dart package. link in flutter.

AES Encryption

privateKEY = “%8R=&PfC5SXT:pRF2vF[5zCTy}M7CX]J”
privateINV = “}Lq5Wu~nkr\Vdfm~”
Encrypted string = “rMCS4wiyvQH7nXx6slP6rA==”
Actual massage should be = “Fantastic”

The flutter code to encrypt is

Using this library to encrypt text only.


import 'package:encrypt/encrypt.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

class EncryptAESData {
  static Encrypted encrypted;
  static var decrypted;

  static String encryptAES(data) {
    final key = Key.fromUtf8(dotenv.env['privateKEY']);
    final iv = IV.fromUtf8(dotenv.env['privateINV']);
    final encrypter = Encrypter(AES(key));
    encrypted = encrypter.encrypt(data, iv: iv);
    return encrypted.base64;
  }

  static decryptAES(data) {
    final key = Key.fromUtf8(dotenv.env['privateKEY']);
    final iv = IV.fromUtf8(dotenv.env['privateINV']);
    final encrypter = Encrypter(AES(key));
    String decrypted = "";
    if (data != "") {
      try {
        decrypted = encrypter.decrypt(Encrypted.fromBase64(data), iv: iv);
      } catch (exception) {
        decrypted = data;
      }
    }
    return decrypted;
  }
}

I’m getting nothing back and i suspect the :crypto.crypto_one_time function i’m using is getting the wrong binary arguments

Here is an example of how i’m getting the binary from the string, if thats even what i’m supposed to do

b_password = :crypto.hash(:md5, privateKEY)

First Post!

ChristopheBelpaire

ChristopheBelpaire

It should work with something like :

secret = "%8R=&PfC5SXT:pRF2vF[5zCTy}M7CX]J"
iv = "}Lq5Wu~nkr\Vdfm~"
payload = Base.decode64!("rMCS4wiyvQH7nXx6slP6rA==")
:crypto.crypto_one_time(:aes_128_cbc, secret, iv, payload, false)

but your iv length is 15 bytes, and it should be 16 :

iex(20)> :crypto.crypto_one_time(:aes_256_cbc, secret, iv, payload, false)
** (ErlangError) Erlang error: {:badarg, {'api_ng.c', 310}, 'Bad iv size'}:

  * 3rd argument: Bad iv size

    crypto.erl:967: :crypto.crypto_one_time(:aes_256_cbc, "%8R=&PfC5SXT:pRF2vF[5zCTy}M7CX]J", "}Lq5Wu~nkrVdfm~", <<172, 192, 146, 227, 8, 178, 189, 1, 251, 157, 124, 122, 178, 83, 250, 172>>, false)
    iex:20: (file)

Most Liked

al2o3cr

al2o3cr

:crypto.hash is definitely digging in the wrong spot.

The post from @ChristopheBelpaire almost has it, but the cipher + mode need to match the defaults that encrypt is using:

  • it appears to pick the block size based on the key, so a 32-byte key → AES-256
  • the default AESMode is SIC, also known as CTR

In addition, the given IV has an explicit \ in it, so it needs to be written as \\ inside ".

Putting it all together:

secret = "%8R=&PfC5SXT:pRF2vF[5zCTy}M7CX]J"

iv = "}Lq5Wu~nkr\\Vdfm~"

payload = Base.decode64!("rMCS4wiyvQH7nXx6slP6rA==")

:crypto.crypto_one_time(:aes_256_ctr, secret, iv, payload, false)

# result: "Fantastic\a\a\a\a\a\a\a"

HOWEVER

Using a fixed IV in CTR mode is BAD. Real bad. The original code you posted gets the IV from dotenv, which leads me to believe the same value is used for every encryption.

Reusing an IV for CTR mode means that an attacker that knows ONE plaintext and the corresponding ciphertext can read ANY shorter ciphertext, because the “key stream” is identical for every encryption operation.

A demonstration:

defmodule CompareStream do
  def to_bytes(s) do
    for <<x::8 <- s>>, do: x
  end

  def xor(s1, s2) do
    [to_bytes(s1), to_bytes(s2)]
    |> Enum.zip()
    |> Enum.map(fn {b1, b2} -> Bitwise.bxor(b1, b2) end)
  end
end

secret = "%8R=&PfC5SXT:pRF2vF[5zCTy}M7CX]J"

iv = "}Lq5Wu~nkr\\Vdfm~"

payload = Base.decode64!("rMCS4wiyvQH7nXx6slP6rA==")

message = :crypto.crypto_one_time(:aes_256_ctr, secret, iv, payload, false)

other_message = "lolwut\a\a\a\a\a\a\a\a\a\a"

other_payload = :crypto.crypto_one_time(:aes_256_ctr, secret, iv, other_message, true)

CompareStream.xor(message, payload) |> IO.inspect(label: "first key stream")

CompareStream.xor(other_message, other_payload) |> IO.inspect(label: "second key stream")

This prints:

first key stream: [234, 161, 252, 151, 105, 193, 201, 104, 152, 154, 123, 125, 181, 84, 253, 171]
second key stream: [234, 161, 252, 151, 105, 193, 201, 104, 152, 154, 123, 125, 181, 84, 253, 171]

Generally, you want to use a mode like CTR with an IV that is sent along with the encrypted result and “never” reused. I put “never” in quotes because most implementations settle for something like a 128-bit cryptographically-random number, which could technically repeat if you collected about 2^64 of them but is close enough to “never” for most purposes.

Last Post!

voltone

voltone

That’s PKCS#7 padding, to make the message length a multiple of the block size. You can strip it by passing encrypt: false, padding: :pkcs_padding instead of just false as the last argument.

Where Next?

Popular in Questions 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
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
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
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

Other popular topics Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
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
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement