intrbiz / arduino-crypto

A minimal crypto library for ESP8266 Arduino
Other
140 stars 53 forks source link

Encription AES with python and Encription with Arduino-Cripto do not match #27

Open mlopezpalma opened 4 years ago

mlopezpalma commented 4 years ago

I use your Crypto library for ESP8266, If I work with encrypt and decrypt only in ESP8266 both messages match ; but if I try to encrypt from a HOST in python and decrypt in ESP8266 using the same key and iv the messages do not match .

The routines used in ESP8266 are a copy of the example

void encrypt(char plain_text, char output, int length) { byte enciphered[length]; RNG::fill(iv, BLOCK_SIZE); AES aesEncryptor(key, iv, AES::AES_MODE_128, AES::CIPHER_ENCRYPT); aesEncryptor.process((uint8_t)plain_text, enciphered, length); int encrypted_size = sizeof(enciphered); char encoded[encrypted_size]; encode_base64(enciphered, encrypted_size, (unsigned char)encoded); strcpy(output, encoded); }

void decrypt(char enciphered, char output, int length) { length = length + 1; //re-adjust char decoded[length]; decode_base64((unsigned char)enciphered, (unsigned char)decoded); bufferSize(enciphered, length); byte deciphered[length]; AES aesDecryptor(key, iv, AES::AES_MODE_128, AES::CIPHER_DECRYPT); aesDecryptor.process((uint8_t)decoded, deciphered, length); strcpy(output, (char)deciphered); }

And the routines in python are based https://techtutorialsx.com/2018/04/09/python-pycrypto-using-aes-128-in-ecb-mode/ pycrypto https://pypi.org/project/pycrypto/

the encoder routine

key ="1c3E4BAF134A89C3F3874FBCD7F33131".decode("hex") iv ="00000000000000000000000000000000".decode("hex")

def EncriptKey(data):

aes = AES.new(key, AES.MODE_CBC, iv)

print ("len",len(data)) print ('dataforencript',data)

encd = aes.encrypt(data)

print("encd",encd)

return encd

Unfortunately the result of the encryption in python can not be decoded in Arduino

mealhero commented 4 years ago

I'm also getting different results with AES256 encryption with this library on an ESP8266 versus a Sparkfun Pro Micro (ATmega32U4)

klack commented 3 years ago

Has anyone found a working AES library that can match python's (correct) AES?

jonathan84clark commented 3 years ago

You can try converting this one https://github.com/SergeyBel/AES. I couldn't get it to match the Python library but it didn't crash like this one did. Also you need to make sure you have at least 8KB of SRAM available for it to work. Take out all the dynamic memory allocation.

klack commented 3 years ago

Thanks I will try it! All I want is to have an encrypted payload so passwords are not flying around in plain text when using Arduino OTA. Maybe AES 128 is too strong for that or there is an easier way.

I am going to get a write up together for this repository first to try and be helpful.

klack commented 3 years ago

Reproduction steps:

define BLOCK_SIZE 16

uint8_t key[BLOCK_SIZE] = { 0x06,0xa9,0x21,0x40,0x36,0xb8,0xa1,0x5b,0x51,0x2e,0x03,0xd5,0x34,0x12,0x00,0x06 }; uint8_t iv[BLOCK_SIZE] = { 0x3d,0xaf,0xba,0x42,0x9d,0x9e,0xb4,0x30,0xb4,0x22,0xda,0x80,0x2c,0x9f,0xac,0x41 };

void bufferSize(char text, int &length) { int i = strlen(text); int buf = round(i / BLOCK_SIZE) BLOCK_SIZE; length = (buf <= i) ? buf + BLOCK_SIZE : length = buf; }

void encrypt(char plain_text, char output, int length) { byte enciphered[length]; RNG::fill(iv, BLOCK_SIZE); AES aesEncryptor(key, iv, AES::AES_MODE_128, AES::CIPHER_ENCRYPT); aesEncryptor.process((uint8_t)plain_text, enciphered, length); int encrypted_size = sizeof(enciphered); char encoded[encrypted_size]; encode_base64(enciphered, encrypted_size, (unsigned char)encoded); strcpy(output, encoded); }

void decrypt(char enciphered, char output, int length) { length = length + 1; //re-adjust char decoded[length]; decode_base64((unsigned char)enciphered, (unsigned char)decoded); bufferSize(enciphered, length); byte deciphered[length]; AES aesDecryptor(key, iv, AES::AES_MODE_128, AES::CIPHER_DECRYPT); aesDecryptor.process((uint8_t)decoded, deciphered, length); strcpy(output, (char)deciphered); }

void setup() { Serial.begin(9600); while (!Serial) { ; //wait } }

void loop() { char plain_text[] = "Single block msg";

// encrypt int length = 0; bufferSize(plain_text, length); char encrypted[length]; encrypt(plain_text, encrypted, length);

Serial.println(""); Serial.print("Encrypted: "); Serial.println(encrypted);

// decrypt length = strlen(encrypted); char decrypted[length]; decrypt(encrypted, decrypted, length);

Serial.print("Decrypted: "); Serial.println(decrypted);

delay(5000); }

**Output:**
Encrypted: oOhcUlaFBrzskVnBV2WKZPwThKcug//YFJCceKikVnw=
Decrypted: Single block msg

**Expected Output:**
Cipher: e353779c1079aeb82708942dbe77181a
Base64: 41N3nBB5rrgnCJQtvncYGg==

**Python Example**
```import base64
from Cryptodome.Cipher import AES
from Cryptodome.Util.Padding import pad

str = "Single block msg"
str_bytes = str.encode()
print(f"Input string: {str}")
print(f"String length: {len(str)}")
key = bytearray.fromhex('06a9214036b8a15b512e03d534120006')
print(f"Key length: {len(key)}")
iv = bytearray.fromhex('3dafba429d9eb430b422da802c9fac41')
print(f"IV length: {len(iv)}")
cipher = AES.new(key, AES.MODE_CBC, iv)
ct_bytes = cipher.encrypt(str_bytes)
print(f"Cipher: {ct_bytes.hex()}")
base64_bytes = base64.b64encode(ct_bytes)
print(f"Base64: {base64_bytes.decode()}")

Official Test Vectors https://tools.ietf.org/html/rfc3602#page-6

klack commented 3 years ago

@jonathan84clark Wow thanks so much, got it to match! 4th library I have tried.... and several days later. I appreciate you pointing me in the right direction. Here is the code that matches my python code above

#include <Arduino.h>
#include <AES.h>

void setup() {

  Serial.begin(9600);

  unsigned char plain[] = "Single block msg";
  unsigned char key[] = { 0x06,0xa9,0x21,0x40,0x36,0xb8,0xa1,0x5b,0x51,0x2e,0x03,0xd5,0x34,0x12,0x00,0x06 }; //key example
  unsigned char iv[] = { 0x3d,0xaf,0xba,0x42,0x9d,0x9e,0xb4,0x30,0xb4,0x22,0xda,0x80,0x2c,0x9f,0xac,0x41 }; //iv example

  unsigned int plainLen = 16 * sizeof(unsigned char);  //bytes in plaintext
  unsigned int outLen = 0;  // out param - bytes in сiphertext

  AES aes(128);  //128 - key length, can be 128, 192 or 256
  unsigned char* e = aes.EncryptCBC(plain, plainLen, key, iv, outLen);
  //now variable c contains outLen bytes - ciphertext
  for (int i = 0; i < outLen; i++)
  {
     Serial.print(e[i], HEX); 
     Serial.print(",");
  }

  unsigned char in[] = { 0xe3,0x53,0x77,0x9c,0x10,0x79,0xae,0xb8,0x27,0x08,0x94,0x2d,0xbe,0x77,0x18,0x1a };
  unsigned char* d = aes.DecryptCBC(in, outLen, key, iv);

  Serial.println("Decrypted: ");
  for (int i = 0; i < outLen; i++)
  {
     Serial.print(d[i], HEX); 
     Serial.print(",");
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}
jonathan84clark commented 3 years ago

Awesome! Glad to help!

pedrorodrigues1997 commented 2 years ago

@klack Hi, how did you include that library into the Arduino IDE? Im having trouble doing that... Do we have to mess around the library files?

pedrorodrigues1997 commented 2 years ago

Actually nevermind, i got it. Thanks to both of you for pointing me in the right direction :)

EgHubs commented 1 year ago

Actually nevermind, i got it. Thanks to both of you for pointing me in the right direction :)

sorry, but how did you manage to do that?

pedrorodrigues1997 commented 1 year ago

It was a while ago so I don't really remember the details. But I’d say you have to mess around with the library files. The cpp and others until you get it right. I don’t have the file now so I can’t help much ☹️

EgHubs commented 1 year ago

It was a while ago so I don't really remember the details. But I’d say you have to mess around with the library files. The cpp and others until you get it right. I don’t have the file now so I can’t help much ☹️

Thanks for your reply I really appreciate that actually, I managed to do it I'm using esp-idf env and it was so easy to add the library under the library folder and add it to the makefile but unfortunately, i couldn't add it to the standard Arduino ide and the code had some problems like outLen I solved them and this is the final one

#include <Arduino.h>
#include <AES.h>

void setup() {

  Serial.begin(115200);

  unsigned char plain[] = "Single block msg";
  unsigned char key[] = { 0x06,0xa9,0x21,0x40,0x36,0xb8,0xa1,0x5b,0x51,0x2e,0x03,0xd5,0x34,0x12,0x00,0x06 }; //key example
  unsigned char iv[] = { 0x3d,0xaf,0xba,0x42,0x9d,0x9e,0xb4,0x30,0xb4,0x22,0xda,0x80,0x2c,0x9f,0xac,0x41 }; //iv example

  unsigned int plainLen = 16 * sizeof(unsigned char);  //bytes in plaintext
  unsigned int outLen = 16;  // out param - bytes in сiphertext

  AES aes(AESKeyLength::AES_128);

  unsigned char* e = aes.EncryptCBC(plain, plainLen, key, iv);

  // //now variable c contains outLen bytes - ciphertext
  for (int i = 0; i < outLen; i++)
  {
     Serial.print(e[i], HEX); 
     Serial.print(",");
  }
delay(500);
  unsigned char in[] = { 0xe3,0x53,0x77,0x9c,0x10,0x79,0xae,0xb8,0x27,0x08,0x94,0x2d,0xbe,0x77,0x18,0x1a };

  unsigned char* d = aes.DecryptCBC(in, outLen, key, iv);
delay(500);

  Serial.println(outLen);
  for (int i = 0; i < outLen; i++)
  {
     Serial.print(d[i], HEX); 
    // Serial.print("");
  }
}

void loop() {
      delay(2000);
}
HARSH36954 commented 11 months ago

Hii here unsigned char* e = aes.EncryptCBC(plain, plainLen, key, iv); this function is not inside library please can you help me for that

rustydr34m commented 5 months ago

When I corrected the RNG::get() and RNG::getLong() methods starting at line 876 in the Crypto.cpp file to "return 0;", the issue was resolved.

(ORGINAL)

Screenshot from 2024-04-29 19-44-05

(MODIFIED)

Screenshot from 2024-04-29 19-40-10

(CPP TEST)

Screenshot from 2024-04-29 19-42-12

(PYTHON TEST)

Screenshot from 2024-04-29 19-43-00

EgHubs commented 5 months ago

Hii here unsigned char* e = aes.EncryptCBC(plain, plainLen, key, iv); this function is not inside library please can you help me for that

Use this library it has that function aes.EncryptCBC you can view it here