[FIXED] Python AES CTR Mode only encrypts first two bytes

Issue

I want to achieve the same result in Dart and in Python in encryption using AES.
My problem is that my Python version only outputs the first two bytes successfully and nothing else.

In doing so, I (must) start in Dart.

As seen in the code, I generate an IV and a key, which is passed as a parameter.

List<String> aesEncryption(List<int> key, String message) {
  final iv =
      enc.IV.fromLength(16); // IV generation

  final aesKey = enc.Key(Uint8List.fromList(
      key)); // transform the key into the right format

  enc.Encrypter encrypter =
      enc.Encrypter(enc.AES(aesKey, mode: enc.AESMode.ctr));

  final encryptedMessage = encrypter.encrypt(message, iv: iv);

  // Here I send my encrypted message and IV to my Flask app, to use the same IV and to
  // compare the results with eacht other
  return [encryptedMessage.base64, iv.base64];
}

Then, eventually, I just encrypt the message "test" with the following key:
The sha256 Hash of the string "low;high"

I then send this tuple to my Flask app and receive the data as follows:

@app.route("/test", methods=["POST"])
def test():
  values = request.get_json()
  iv = base64.b64decode(values["iv"]) # my IV which was sent of the Dart App
  sig = values["signature"] # just the AES encryption value of the Dart App
  key = values["key"] # the string "low;high"

  aes_key = hashlib.sha256(key.encode('utf-8')).digest() # as mentioned before, I have 
  # to hash the string "low;high" first and I will use this as my aes key
  # I tested if the computed hash values are the same in python and dart, and yes it is so

  # I create a Counter with my IV, I do not completely understand this part, maybe here is my mistake somewhere. 
  counter = Counter.new(128, initial_value=int.from_bytes(iv, byteorder='big'))
  cipher = AES.new(aes_key, AES.MODE_CTR, counter=counter)

  test = "test".encode('utf-8')

  # The output of this print is: b'\xd52\xf8m\x0b\xcb"\xa7\x0e\xf7\xab\x96\x0f\xfc\x9f\n'
  print(base64.b64decode(sig))
  encrypted = cipher.encrypt(test)

  # The output of this print is: b'\xd52\xf8m'
  print(encrypted)

  return "", 200

As you can see only the first two bytes are output of the python AES encryption and unfortunately, I don’t understand why. I hope someone can help me with this because this implementation is essential for me.

Thank you in advance for every helpful answer!

Kind regards,
Bagheera

Solution

I was able to find the error again pretty quickly.

The problem is that automatic PKCS7 padding is used in Dart and not in Python.

So the solution (just for the matter that the encryption values are the same) is the following in Dart:

enc.Encrypter encrypter =
  enc.Encrypter(enc.AES(aesKey, mode: enc.AESMode.ctr, padding: null));

Answered By – Bagheera

Answer Checked By – Katrina (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published