Open mlopezpalma opened 4 years ago
I'm also getting different results with AES256 encryption with this library on an ESP8266 versus a Sparkfun Pro Micro (ATmega32U4)
Has anyone found a working AES library that can match python's (correct) AES?
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.
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.
Reproduction steps:
#include <Crypto.h>
#include <base64.hpp>
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
@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:
}
Awesome! Glad to help!
@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?
Actually nevermind, i got it. Thanks to both of you for pointing me in the right direction :)
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?
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 ☹️
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);
}
Hii here unsigned char* e = aes.EncryptCBC(plain, plainLen, key, iv); this function is not inside library please can you help me for that
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)
(MODIFIED)
(CPP TEST)
(PYTHON TEST)
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