Closed ofthesea-io closed 6 years ago
I figured out the problem that I was having with regards to the block size when turning the encipher array into a base 64 strings to send across the wire. My buffer sizes wasn't in multiples of 16.
Are you planning on bringing in other features such as padding modes or is this project laid to rest? :)
I'll try to add an AES example when I get chance, unless you've got one you can contribute.
I currently have no plans to add padding modes since my project doesn't need them. I'm open to contributions for padding modes if other people have a requirement.
@intrbiz Yeah, I have done an example with one that decodes/encodes into base64 before doing the encryption. I will do a pull request from your branch as soon as I get a moment free, you can review it.
Hi @ThePaceMaker and @intrbiz !
Some one can help me ? Im try to use this lib in EPS8266, and i try to encrypt from a PC with openssl, and decrypt with ESP8266, and vice-versa. Using the openssl, i provide my IV and KEY used in the library, but i can't decrypt the message in ESP8266, i think it's because the KEY is not the same. The key and the iv in this library, must be a Hex ? @ThePaceMaker , can you post your example ? Tks !
Make sure that your buffer is in multiples of 16 byte chunks when processing the encrypted string. eg. length = (i / 16 + 1) * 16. I over looked that, when testing the lib.
as for the IV and the key , I have the data type set to uint8_t, which is essentially just a byte
uint8_t key[BLOCK_SIZE] = { 0x1C,0x3E,0x4B,0xAF,0x13,0x4A,0x89,0xC3,0xF3,0x87,0x4F,0xBC,0xD7,0xF3, 0x31, 0x31 };
uint8_t iv[BLOCK_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
as for the IV, the library allows you to generate a different IV for each request.
Hi @ThePaceMaker ,
My data is multiple of 16 (in my case it's 32).
What is my test:
Build in ESP8266 a crypto block, pass it to HEX. Get this Hex and pass to ASCII again, put in a file and decrypt with openssl.
In my Example, the key and iv is:
uint8_t key[32] = { 0x1E, 0xF4, 0x18, 0xD7, 0x1A, 0x70, 0x38, 0x85, 0x11, 0x7B, 0xB0, 0x70, 0x09, 0x30, 0xA3, 0x3B, 0xC2, 0x80, 0x77, 0x0C, 0x0B, 0x33, 0xB7, 0x76, 0x12, 0xFB, 0x4B, 0x38, 0xCF, 0x65, 0x32, 0x66 };
uint8_t iv[16] = {0x51, 0x68, 0x55, 0x67, 0x68, 0x48, 0x48, 0x48, 0x49, 0x54, 0x52, 0x48, 0x69, 0x48, 0x70, 0x70};
bool Utils::isValidCrypt(String auth) {
uint8_t out[50];
uint8_t old[50];
AES enc(key, iv, AES::AES_MODE_256, AES::CIPHER_ENCRYPT);
AES dec(key, iv, AES::AES_MODE_256, AES::CIPHER_DECRYPT);
enc.process((const uint8_t *)auth.c_str(), out, 32);
Serial.print("*Debug: CRYPTO [");
for (int i = 0; i < 32; i++) {
Serial.printf("%02X ", out[i]);
}
Serial.println("]");
dec.process(out, old, 32);
Serial.print("*Debug: OLD [");
for (int i = 0; i < 32; i++) {
Serial.printf("%c", old[i]);
}
Serial.println("]");
}
I set 32 and 16, following what is writen in the Crypto.cpp. I Fixed 32 in process function, because my "string" has 32 bytes, excluding the NULL terminator.
In this example, works OK, but if i got the HEX generate bellow enc.process, and try to decrypt in openssl, i got a "bad decrypt" error.
To do the decrypt in openssl, i do the following:
echo -n "<HEX STRING>" | xxd -p -r > file.enc
and them:
KEY="1EF418D71A703885117BB0700930A33BC280770C0B33B77612FB4B38CF653266"
IV="51685567684848484954524869487070"
openssl enc -d -nosalt -aes-256-cbc -in file.enc -K $KEY -iv $IV
With this, i got the "bad decrypt" error in openssl, i don't know if the Crypto.cpp lib is using correctly the key and iv that i set.
Here is a quick and dirty example. I used the following lib to base64 encode and decode the string - https://github.com/adamvr/arduino-base64
#include "crypto.h"
#include "base64.h"
#define BLOCK_SIZE 16
uint8_t key[BLOCK_SIZE] = { 0x1C,0x3E,0x4B,0xAF,0x13,0x4A,0x89,0xC3,0xF3,0x87,0x4F,0xBC,0xD7,0xF3, 0x31, 0x31 };
uint8_t iv[BLOCK_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
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];
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];
base64_encode(encoded, (char*)enciphered, encrypted_size);
strcpy(output, encoded);
}
void decrypt(char* enciphered, char* output, int length)
{
length = length + 1; //re-adjust
int decodedLen = base64_dec_len(enciphered, length);
char decoded[length];
base64_decode(decoded, enciphered, length);
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(115200);
while (!Serial) {
; //wait
}
char plain_text[] = "this can be text of any length or information you want it to be";
// encrypt
int length = 0;
bufferSize(plain_text, length);
char encrypted[length];
encrypt(plain_text, encrypted, length);
Serial.println(encrypted);
// decrypt
length = strlen(encrypted);
char decrypted[length];
decrypt(encrypted, decrypted, length);
Serial.println(decrypted);
}
void loop()
{
}
Disclaimer. Its not pretty, but it works. I was able to encipher/decipher 5000 random sentences ever 200th of a second without any fall overs.
Well done to @adamvr and @intrbiz!
Tks @ThePaceMaker !
You are using 128 bits, i'm using 256. so my BLOCK_SIZE must be 32, and the IV_BLOCK 16.
Can you try to decrypt the result, with openssl ? I can't now, my ESP8266 it is in my Home.
Hi all ! @ThePaceMaker and @intrbiz
I Found my error, its my script in openssl, it's missing the -nopad argument. Now its Ok, i can reverse the Crypto in AES256 normally.
If you need, i can post my script using openssl to check if all the encrypt and decrypt its working.
Tks !!
If I use the AES example from @ThePaceMaker, I'll get a weird behaviour/output from the decrypt-function:
plain_text[]= "1234567890ABCDEF1234567890ABCDEF";
decryptred text:
1234567890ABCDEF1234567890ABCDEF⸮U?⸮⸮ގ⸮⸮SE4⸮⸮⸮O⸮⸮⸮⸮⸮ r⸮~⸮Lƽ5⸮E⸮⸮⸮$⸮uOX2⸮
plain_text[] = "1234567890ABCDEF"
decrypted text:
;1234567890ABCDEF⸮⸮g^=]⸮⸮ ⸮MY⸮E,⸮⸮⸮O⸮⸮⸮⸮⸮ r⸮~⸮L
Here is the code:
#include "Crypto.h"
#include "Base64.h"
#define BLOCK_SIZE 16
uint8_t key[BLOCK_SIZE] = { 0x1C,0x3E,0x4B,0xAF,0x13,0x4A,0x89,0xC3,0xF3,0x87,0x4F,0xBC,0xD7,0xF3, 0x31, 0x31 };
uint8_t iv[BLOCK_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
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];
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];
base64_encode(encoded, (char*)enciphered, encrypted_size);
strcpy(output, encoded);
}
void decrypt(char* enciphered, char* output, int length)
{
length = length + 1; //re-adjust
int decodedLen = base64_dec_len(enciphered, length);
char decoded[length];
base64_decode(decoded, enciphered, length);
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(115200);
while (!Serial) {
; //wait
}
// char plain_text[] = "this can be text of any length or information you want it to be";
char plain_text[] = "1234567890ABCDEF1234567890ABCDEF";
// encrypt
int length = 0;
bufferSize(plain_text, length);
char encrypted[length];
encrypt(plain_text, encrypted, length);
Serial.println(encrypted);
// decrypt
length = strlen(encrypted);
char decrypted[length];
decrypt(encrypted, decrypted, length);
Serial.println(decrypted);
}
void loop()
{
}
Any ideas why it produces such an output??
It could have something to do with the buffer size, as its adding another block. Im unable to debug it at the moment, but try adding more text to the plain_text array and see if it decrypts correctly.
I think it has something to do with the length of the plaintext (the samples above are always a multiple of 16). If you are over or lower than *16 it decrypts correctly.
length = (buf <= i) ? buf + BLOCK_SIZE : buf;
in line 13 fixed it for me
Thank you to @intrbiz, @ThePaceMaker, @DiegoSVilla and everyone else who has contributed thus far! I ran into some trouble getting my sketch to compile using @adamvr Base64 library, so I ended up using base64 v1.1.0 by @Densaugeo (https://github.com/Densaugeo/base64_arduino) which is working for me.
I also randomized the initialization vector and put the sample encryption/decryption in loop() with a 5 second delay to show that the encrypted message changes but still decrypts to the original text. Now I just have to figure out how to get decryption working on a remote device.
#include <Crypto.h>
#include <base64.hpp>
#define BLOCK_SIZE 16
uint8_t key[BLOCK_SIZE] = { 0x1C,0x3E,0x4B,0xAF,0x13,0x4A,0x89,0xC3,0xF3,0x87,0x4F,0xBC,0xD7,0xF3, 0x31, 0x31 };
uint8_t iv[BLOCK_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
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(115200);
while (!Serial) {
; //wait
}
}
void loop() {
char plain_text[] = "1234567890ABCDEF1234567890ABCDEF";
// 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);
}
Hey, I got a notification somebody is using my old library! Let me know if you run into any issues/room for improvement.
@intrbiz I've adopted pkcs7 padding routines from https://github.com/spaniakos/AES and created an example with AES and SHA256/HMAC. I will submit a pull request for you to review :)
@Densaugeo your old library is working very well. Thanks again.
AES Example has been added to the main readme
Hi all ! @ThePaceMaker and @intrbiz
I Found my error, its my script in openssl, it's missing the -nopad argument. Now its Ok, i can reverse the Crypto in AES256 normally.
If you need, i can post my script using openssl to check if all the encrypt and decrypt its working.
Tks !!
Hi all ! @ThePaceMaker and @intrbiz
I Found my error, its my script in openssl, it's missing the -nopad argument. Now its Ok, i can reverse the Crypto in AES256 normally.
If you need, i can post my script using openssl to check if all the encrypt and decrypt its working.
Tks !!
Hi alexwbaule , please can you help me with decryption in arduino when encryption is done using openssl in php.. and using thesame code sample below
uint8_t key[BLOCK_SIZE] = { 0x1C, 0x3E, 0x4B, 0xAF, 0x13, 0x4A, 0x89, 0xC3, 0xF3, 0x87, 0x4F, 0xBC, 0xD7, 0xF3, 0x31, 0x31 };
uint8_t iv[BLOCK_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
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(115200); while (!Serial) { ; //wait } }
void loop() { char plain_text[] = "1221";
// 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); }
thanks
Please can you add an example on how to use the AES encryption part of your library?