2017-01-29 2 views
0

Я уверен, что делаю декодирование и дешифрование ошибочно, но я не знаю, что именно.ESP8266 AES encrypt - decrypt

#include "AES.h" 
#include "Base64.h" 

AES aes; 

// Our AES key. Note that is the same that is used on the Node-Js side but as hex bytes. 
byte key[] = {0x7e, 0x4e, 0x42, 0x38, 0x43, 0x63, 0x4f, 0x4c, 0x23, 0x4a, 0x21, 0x48, 0x3f, 0x7c, 0x59, 0x72}; 

// The unitialized Initialization vector 
byte iv[N_BLOCK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 

// Our message to encrypt. Static for this example. 
String msg = "{\"data\":{\"value\":300}, \"SEQN\":700 , \"msg\":\"IT WORKS!!\" }"; 

uint8_t generate_random_unit8() 
{ 
    uint8_t really_random = *(volatile uint8_t *)0x3FF20E44; 
    return really_random; 
} 

// Generate a random initialization vector 
void generate_iv(byte *vector) 
{ 
    for (int i = 0; i < N_BLOCK; i++) 
    { 
    vector[i] = (byte)generate_random_unit8(); 
    } 
} 

void encrypt() 
{ 
    char b64data[200]; 
    byte cipher[1000]; 
    byte iv[N_BLOCK]; 

    generate_iv(iv); 

    base64_encode(b64data, (char *)iv, N_BLOCK); 
    String IV_base64 = String(b64data); 
    Serial.println(" IV b64: " + IV_base64); 

    int b64len = base64_encode(b64data, (char *)msg.c_str(), msg.length()); 

    Serial.println(" The lenght is: " + String(b64len)); 

    // Encrypt! With AES128, our key and IV, CBC and pkcs7 padding 
    aes.do_aes_encrypt((byte *)b64data, b64len, cipher, key, 128, iv); 

    Serial.println("Cipher size: " + String(aes.get_size())); 

    base64_encode(b64data, (char *)cipher, aes.get_size()); 
    Serial.println("Encrypted data in base64: " + String(b64data)); 

    decrypt(b64data, IV_base64, aes.get_size()); 
} 

void decrypt(String b64data, String IV_base64, int size) 
{ 
    char data_decoded[200]; 
    char iv_decoded[200]; 
    byte out[200]; 
    char temp[200]; 
    b64data.toCharArray(temp, 200); 
    base64_decode(data_decoded, temp, b64data.length()); 
    IV_base64.toCharArray(temp, 200); 
    base64_decode(iv_decoded, temp, IV_base64.length()); 
    aes.do_aes_decrypt((byte *)data_decoded, size, out, key, 128, (byte *)iv_decoded); 
    char message[msg.length()]; 
    base64_decode(message, (char *)out, b64data.length()); 
    printf("Out %s \n", message); 
} 

void setup_aes() 
{ 
    aes.set_key(key, sizeof(key)); // Get the globally defined key 
} 

void setup() 
{ 
    Serial.begin(115200); 
} 

void loop() 
{ 
    encrypt(); 
    delay(1000); 
} 

Декодированное сообщение должно быть {"data":{"value":300}, "SEQN":700 , "msg":"IT WORKS!!". Однако я получаю {"data":{"value":300}, "SEQN":700 , "msg":"IT WORKS!!" }�������������������������. Я бы предположил, что длина символа неверна?

+0

Как указывал рециркулятор, в возвращаемой строке не хватает терминатора. Однако вы можете добавить его только в декодированный буфер с сообщением char [msg.length() + 1]; в расшифровке. Однако я обнаружил, что ваша программа очень запутана. Пожалуйста, избегайте ненужных преобразований (почему сообщение должно быть строкой? Почему вам нужно конвертировать туда и обратно в строки? И самое главное: почему вы преобразовали открытый текст в base64?) – frarugi87

+0

Как вообще-то «generate_random_unit8»? – dandavis

+0

Да, весь этот код испорчен. Скопировал его из блога для PoC. –

ответ

1

Если вы кодируете, вы должны финализировать строку с \ 0, поэтому в декодированных данных, \ 0 также есть, и printf может быть правильно закончен на \ 0.

Исправление будет int b64len = base64_encode(b64data, (char *)msg.c_str(), msg.length()+1); Это гарантирует, что неявный \ 0 байт будет включен. Компилятор автоматически добавляет это в строку msg.

Попробуйте!

0

я, наконец, нашел то, что был неправ ..

base64_decode(message, (char *)out, b64data.length());

должен быть

base64_decode(message, (char *)out, 75); - длина кодированных данных - 1

По крайней мере PoC работает.

0

У меня недавно был такой же вопрос, и я провел несколько часов, пытаясь понять это. Иванов, вы хорошо знаете длину кодированных данных. Основная проблема заключается в основном в том, что функция шифрования AES создает дополнительное дополнение, а функция дешифрования не может ее удалить.

Это не имеет ничего общего с нулевым завершением строки или тем фактом, что ей не хватает терминатора. Проблема фактически решена простым опуском последних 5 дополнений из расшифрованной строки.

Редактировать Это на самом деле больше, чем просто отсутствие 5 символов с конца. Когда я узнал, что количество тарабарщины или отступов варьируется в зависимости от длины вашего оригинального JSON, имеет смысл обрезать строку, обнаружив конец строки JSON.

Я предоставляю свой (обновленный) рабочий код для справки. Надеюсь, это поможет любому, у кого есть эта проблема! Удачи с вашим проектом!

#include "AES.h" 
#include "Base64.h" 

AES aes; 

// Our AES key. Same in NodeJS but in hex bytes 
byte key[] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }; 
// The unitialized Initialization vector (16-bit) 
byte iv[N_BLOCK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 

// NodeMCU side raw message 
String msg = "{\"x\":10, \"y\":20, \"z\":30 \"lamp_stat\":\"ON This is a sentence. Testing testing testing\"}"; 

uint8_t generate_random_unit8() 
{ 
    uint8_t really_random = *(volatile uint8_t *)0x3FF20E44; 
    return really_random; 
} 

// Generate a random initialization vector 
void generate_iv(byte *vector) 
{ 
    for (int i = 0; i < N_BLOCK; i++) 
    { 
    vector[i] = (byte)generate_random_unit8(); 
    } 
} 

void encrypt() 
{ 
    char b64data[200]; 
    byte cipher[1000]; 
    byte iv[N_BLOCK]; 

    generate_iv(iv); 

    base64_encode(b64data, (char *)iv, N_BLOCK); 
    String IV_base64 = String(b64data); 
    Serial.println(" IV b64: " + IV_base64); 

    int b64len = base64_encode(b64data, (char *)msg.c_str(), msg.length()); 

    Serial.println(" The lenght is: " + String(b64len)); 

    // Encrypt! With AES128, our key and IV, CBC and pkcs7 padding 
    aes.do_aes_encrypt((byte *)b64data, b64len, cipher, key, 128, iv); 

    Serial.println("Cipher size: " + String(aes.get_size())); 

    base64_encode(b64data, (char *)cipher, aes.get_size()); 
    Serial.println("Encrypted data in base64: " + String(b64data)); 

    //decrypt(b64data, IV_base64, aes.get_size()); 
} 

void decrypt(String b64data, String IV_base64, int lsize) 
{ 
    char data_decoded[300]; 
    char iv_decoded[300]; 
    byte out[300]; 
    char temp[300]; 
    b64data.toCharArray(temp, 300); 
    base64_decode(data_decoded, temp, b64data.length()); 
    IV_base64.toCharArray(temp, 300); 
    base64_decode(iv_decoded, temp, IV_base64.length()); 
    aes.do_aes_decrypt((byte *)data_decoded, lsize, out, key, 128, (byte *)iv_decoded); 
    char message[msg.length()]; 
    base64_decode(message, (char *)out, aes.get_size()); 
    for (int i = 0; i < aes.get_size(); i++) 
    { 
    char curChar = (char)message[i]; 
    if (curChar != '}') 
     temp[i] = curChar; 
    else 
    { 
     temp[i] = curChar; 
     temp[i+1] = '\0'; 
     break; 
    } 
    } 
    String result = String((char *)temp); 
    Serial.println(result); 
} 

void setup_aes() 
{ 
    aes.set_key(key, sizeof(key)); // Get the globally defined key 
} 

void setup() 
{ 
    Serial.begin(115200); 

} 

void loop() 
{ 
    encrypt(); 
    decrypt("ipYk12VCYyD+aJ7KL7lO8L5zOq71XvsLzp650gKBFgQor7GHs98QpQSjQOZdhCwggq2Ehf4nVNwTeK3VjtqMVJRGBw9YViARXCTOGqctjFc=", "+eNzSlRRPi0YZhrp5ctpnA==", 83); 
    delay(8000); 
}