Шифрование в PHP, дешифрование в Arduino на ESP32
- Войдите на сайт для отправки комментариев
Пт, 15/02/2019 - 15:17
Здравствуйте,
Не могу разобраться, поэтому прощу помощи или подсказок у знающих людей.
На ESP32 я хочу дешифровать данные, зашифрованные на странице сервера при помощи openssl в PHP.
PHP
<?php // Используемый метод шифрования $cipher_method = 'AES-128-ECB'; // Шифруемая строка $string_to_be_ciphered = 'My sensitive information I want to cipher'; // Ключ 16 байт (128 бит) $key = 'My_cipher_key___'; // Зашифрованная строка $ciphered_text = openssl_encrypt($string_to_be_ciphered, $cipher_method, $key); // Кодирование в base64 $base64_text = base64_encode($ciphered_text); echo '<b>ciphered_text: </b><br>' . $ciphered_text . '<br><br>'; echo '<b>base64_text: </b><br>' . $base64_text . '<br>'; ?>
В результате получаю это:
ciphered_text:
qg4dnkyIKEyj3AXut8OJVebK/gS1IyT+2BwCbZXjLSuOV7G8pEnozuJUfjS1YP39
base64_text:
cWc0ZG5reUlLRXlqM0FYdXQ4T0pWZWJLL2dTMUl5VCsyQndDYlpYakxTdU9WN0c4cEVub3p1SlVmalMxWVAzOQ==
ARDUINO
#include "mbedtls/aes.h"
extern "C" {
#include "crypto/base64.h"
}
char stringToBeCiphered[] = "My sensitive information I want to cipher";
char key[] = "My_cipher_key___";
char cipheredText[] = "qg4dnkyIKEyj3AXut8OJVebK/gS1IyT+2BwCbZXjLSuOV7G8pEnozuJUfjS1YP39";
char base64CipheredText[] = "cWc0ZG5reUlLRXlqM0FYdXQ4T0pWZWJLL2dTMUl5VCsyQndDYlpYakxTdU9WN0c4cEVub3p1SlVmalMxWVAzOQ==";
// Буферы для хранения данные достаточно большие, чтобы вместить все необходимое
unsigned char cipherTextOutput[100+1];
unsigned char decipheredTextOutput[100+1];
size_t outputLength;
#define BAUDS 115200
void encrypt(char * stringToBeCiphered, char * key, unsigned char * outputBuffer){
// Создаю контекст алгоритма
mbedtls_aes_context aes;
// Инициализирую этот контекст
mbedtls_aes_init(&aes);
// Задаю ключ шифрования
mbedtls_aes_setkey_enc(&aes, (const unsigned char*) key, strlen(key) * 8);
// Применяю шифрование ECB
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, (const unsigned char*)stringToBeCiphered, outputBuffer);
// Очищаю контекст для следующего использования
mbedtls_aes_free(&aes);
}
void decrypt(unsigned char * chipherText, char * key, unsigned char * outputBuffer){
// Создаю контекст алгоритма
mbedtls_aes_context aes;
// Инициализирую этот контекст
mbedtls_aes_init(&aes);
// Задаю ключ дешифрования
mbedtls_aes_setkey_dec(&aes, (const unsigned char*) key, strlen(key) * 8);
// Применяю дешифрование ECB
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, (const unsigned char*)chipherText, outputBuffer);
// Очищаю контекст для следующего использования
mbedtls_aes_free(&aes);
}
void setup() {
Serial.begin(BAUDS);
// 1. Шифрую исходный текст
encrypt(stringToBeCiphered, key, cipherTextOutput);
Serial.println(F("\nOriginal text to be ciphered:"));
Serial.println(stringToBeCiphered);
Serial.println(F("\nCiphered text by mbedtls/aes in Arduino:"));
for (byte i = 0; i < 16; i++) {
char str[3];
sprintf(str, "%02x", (int)cipherTextOutput[i]);
Serial.print(str);
}
Serial.println("\n");
// 2. Декодирую base64 (для визуального контроля)
unsigned char * decoded = base64_decode((const unsigned char *)base64CipheredText, strlen(base64CipheredText), &outputLength);
Serial.print("Length of decoded message: ");
Serial.println(outputLength);
Serial.print("Decoded base64: ");
Serial.printf("%.*s", outputLength, decoded);
free(decoded); // Освобождаю занятую память
Serial.println("\n");
// 3. Расшифровываю закодированный текст
Serial.print(F("cipheredText (by openssl in PHP): ")); Serial.println(cipheredText);
byte cipheredTextLength = strlen(cipheredText);
Serial.print(F("cipheredTextLength: ")); Serial.println(cipheredTextLength);
Serial.println();
decrypt((unsigned char *)cipheredText, key, decipheredTextOutput);
Serial.println(F("Deciphered text by mbedtls/aes in Arduino:"));
for (byte j = 0; j < cipheredTextLength; j++) {
Serial.print((char)decipheredTextOutput[j]);
}
Serial.println(F("\n--------------\n"));
}
void loop() {
// put your main code here, to run repeatedly:
}
В результате получаю это:
Original text to be ciphered:
My sensitive information I want to cipher
Ciphered text by mbedtls/aes in Arduino:
aa0e1d9e4c88284ca3dc05eeb7c38955
Length of decoded message: 64
Decoded base64: qg4dnkyIKEyj3AXut8OJVebK/gS1IyT+2BwCbZXjLSuOV7G8pEnozuJUfjS1YP39
cipheredText (by openssl in PHP): qg4dnkyIKEyj3AXut8OJVebK/gS1IyT+2BwCbZXjLSuOV7G8pEnozuJUfjS1YP39
cipheredTextLength: 64
Deciphered text by mbedtls/aes in Arduino:
⸮@⸮c⸮d⸮⸮⸮l⸮⸮⸮`⸮
Чего я не понял в использовании AES в Arduino?
Результат шифрования Arduino не совпадает с результатом шифрования openssl:
aa0e1d9e4c88284ca3dc05eeb7c38955 (Arduino)
qg4dnkyIKEyj3AXut8OJVebK/gS1IyT+2BwCbZXjLSuOV7G8pEnozuJUfjS1YP39 (openssl)
Естественно, что дальше ничего тоже совпасть не может.
Как получить идентичные строки?
aa0e1d9e4c88284ca3dc05eeb7c38955 (Arduino)
qg4dnkyIKEyj3AXut8OJVebK/gS1IyT+2BwCbZXjLSuOV7G8pEnozuJUfjS1YP39 (openssl)
Естественно, что дальше ничего тоже совпасть не может.
Как получить идентичные строки?
пых-пых выполняя openssl_encrypt получил данные уже закодированные в бейс64, потому как не сказали верни OPENSSL_RAW_DATA
зачем то ещё раз результат кодируете на base64_encode и выводите два результата.
если декодируете из бейс64 то что вернул openssl_encrypt (тот который называется ciphered_text) получите
Теперь посмотрите на то что получилось на ардуине0xaa, 0x0e, 0x1d, 0x9e, 0x4c, 0x88, 0x28, 0x4c, 0xa3, 0xdc, 0x05, 0xee, 0xb7, 0xc3, 0x89, 0x55,
0xe6, 0xca, 0xfe, 0x04, 0xb5, 0x23, 0x24, 0xfe, 0xd8, 0x1c, 0x02, 0x6d, 0x95, 0xe3, 0x2d, 0x2b,
0x8e, 0x57, 0xb1, 0xbc, 0xa4, 0x49, 0xe8, 0xce, 0xe2, 0x54, 0x7e, 0x34, 0xb5, 0x60, 0xfd, 0xfd
aa0e1d9e4c88284ca3dc05eeb7c38955
первый бок совпадает,
mbedtls_aes_crypt_ecb немножко шифрует блоками
This function performs an AES single-block encryption or decryption operation.
если собираетесь шифровать остальные блоки, не забудте про паддинг последнего блока.
верни OPENSSL_RAW_DATA
зачем то ещё раз результат кодируете на base64_encode и выводите два результата.
Да, об OPENSSL_RAW_DATA - это точно подмечено. Спасибо.
Теперь буду читать о блоках.
Конкретно для своего случая я разобрался. Но дальше копать не стал. Сделал только для ECB метода. Да, он не фонтан и у него есть ограничения, но для не очень требовательных задач может подойти. В общем, кому пригодится, то правильно это работает вот так.
Итак, пытаюсь зашифровать сообщение Some_secret_data. Длина этого сообщения не должна превышать 16 байт, потому что ECB на Arduino вернет только первые 16 байт. Возможно, я просто не до конца разобрался, но в этом исполнении это именно так.
PHP
На выходе в PHP получаю L0+zSw7zBTphOCGNtPDbiVx7SNvH7A+530X0Xw3a0QU=
Это и есть зашифрованный текст.
ARDUINO
#include "mbedtls/aes.h" extern "C" { #include "crypto/base64.h" } // Ключ к шифру char key[] = "My_cipher_key___"; // Тот же самый ключ, что и в PHP, иначе ничего не получится. Это еще одно ограничение для этого метода шифрования // Шифр, сгенерированный в PHP char base64CipheredText[] = "L0+zSw7zBTphOCGNtPDbiVx7SNvH7A+530X0Xw3a0QU="; // Буфер для хранения данных достаточно большой, чтобы вместить все необходимое unsigned char decipheredTextOutput[100]; size_t outputLength; #define BAUDS 115200 // Дешифрование в ECB void decrypt(unsigned char * chipheredText, char * key, unsigned char * outputBuffer){ // Создаю контекст алгоритма mbedtls_aes_context aes; // Инициализирую этот контекст mbedtls_aes_init(&aes); // Задаю ключ дешифрования mbedtls_aes_setkey_dec(&aes, (const unsigned char*) key, 128); // 128 бит // Применяю дешифрование ECB mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, (const unsigned char*)chipheredText, outputBuffer); // Очищаю контекст для следующего использования mbedtls_aes_free(&aes); } void setup() { Serial.begin(BAUDS); // Декодирую base64, поскольку входящее сообщение пришло закодированным в base64 unsigned char * decoded = base64_decode((const unsigned char *)base64CipheredText, strlen(base64CipheredText), &outputLength); free(decoded); // Освобождаю занятую память // Расшифровываю декодированный текст decrypt((unsigned char *)decoded, key, decipheredTextOutput); Serial.println(F("Deciphered text by mbedtls/aes in Arduino:")); for (byte j = 0; j < strlen(base64CipheredText) / 2; j++) { Serial.print((char)decipheredTextOutput[j]); } } void loop() { }На выходе Arduino получаю ту самую фразу Some_secret_data
Теперь все работает правильно.
Конкретно для своего случая я разобрался. Но дальше копать не стал. Сделал только для ECB метода. Да, он не фонтан и у него есть ограничения, но для не очень требовательных задач может подойти.
выполняем дешифрацию каждого блока
0xaa, 0x0e, 0x1d, 0x9e, 0x4c, 0x88, 0x28, 0x4c, 0xa3, 0xdc, 0x05, 0xee, 0xb7, 0xc3, 0x89, 0x55,
0xe6, 0xca, 0xfe, 0x04, 0xb5, 0x23, 0x24, 0xfe, 0xd8, 0x1c, 0x02, 0x6d, 0x95, 0xe3, 0x2d, 0x2b,
0x8e, 0x57, 0xb1, 0xbc, 0xa4, 0x49, 0xe8, 0xce, 0xe2, 0x54, 0x7e, 0x34, 0xb5, 0x60, 0xfd, 0xfd
получаем
00000000 | 4d 79 20 73 65 6e 73 69 74 69 76 65 20 69 6e 66 | My sensitive inf
00000010 | 6f 72 6d 61 74 69 6f 6e 20 49 20 77 61 6e 74 20 | ormation I want
00000020 | 74 6f 20 63 69 70 68 65 72 07 07 07 07 07 07 07 | to cipher.......
в последнем блоке видим стандартный падиинг для pkcs#7