英文:
Trying to encrypt communication with ESP32 (PlatformIO). esp_aes_crypt_ecb fails on the last block
问题
我正在尝试从ESP32加密数据到一个互联网网页。
明文长度为31个字符,需要3个16字符的块。
前两个块可以正常加密,但最后一个失败了。
最后一个块以C/C++字符串标准的0终止。
请查看我的参考代码:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "mbedtls/aes.h"
#include "esp_log.h"
#include "aes/esp_aes.h"
#include "mbedtls/base64.h"
#define ESP_AES_ENCRYPT 1
esp_aes_context aes;
unsigned char key[33] = {'d', 'v', 'i', 'z', 'd', 'u', 'm', 'c', 's', 'm', 'v', 'l', 'v', 'f', 'd', 'v', 'b', 'j', 's', 'v', 'd', 'u', 'i', 'a', 's', 'r', 'u', 'i', 'a', 'e', 'u', 'y', '\0'};
unsigned char encrypted[255] = {0};
void crypto_aes_ecb(char *input){
static const char *TAG = "CryptTest";
bool doEncrypt = true;
uint16_t blockIndex = 0;
uint16_t inputIndex = 0;
uint16_t outputIndex = 0;
// unsigned char input[64] = {'T', 'e', 's', 't', 'i', 'n', 'g', ' ', 'e', 'n', 'c', 'r', 'y', 'p', 't', 'i', 'o', 'n', '.', '.', '.', ' ', 'T', 'e', 's', 't', 'i', 'n', 'g', ' ', 'e', 'n', 'c', 'r', 'y', 'p', 't', 'i', 'o', 'n', '.', '.', '.', '\0'};
unsigned char inputBlock[16] = {0};
unsigned char output[17] = {0};
esp_aes_init(&aes);
esp_aes_setkey(&aes, (const unsigned char*) key, 256);
inputIndex = 0;
while(doEncrypt){
for (blockIndex = 0; blockIndex < 16; blockIndex++){
inputBlock[blockIndex] = input[blockIndex + (inputIndex * 16)];
if(input[blockIndex + (inputIndex * 16)] == '\0'){
for (; blockIndex < 16; blockIndex++){inputBlock[blockIndex] = 0;}
doEncrypt = false;
break;
}
}
inputIndex++;
inputBlock[16] = '\0';
ESP_LOGI(TAG, "inputBlock = '%s'", inputBlock);
esp_aes_crypt_ecb(&aes, ESP_AES_ENCRYPT, (const unsigned char *)inputBlock, output);
for (blockIndex = 0; blockIndex < 16; blockIndex++){
encrypted[blockIndex + (outputIndex * 16)] = output[blockIndex];
}
outputIndex++;
}
ESP_LOGW(TAG, "-----------------------------------------------------------------------------------");
ESP_LOGW(TAG, "Key : '%s'", key);
ESP_LOGW(TAG, "Input : '%s'", input);
// ESP_LOGW(TAG, "Output : '%s'", encrypted);
ESP_LOG_BUFFER_HEXDUMP(TAG, encrypted, 128, ESP_LOG_WARN);
esp_aes_free(&aes);
}
void app_main(){
crypto_aes_ecb("Testing encryption... Testing encryption...");
}
通过使用在线的加密/解密测试工具测试HexDump,它报告“给定的最终块未正确填充。如果在解密过程中使用了错误的密钥,可能会出现此类问题。”
测试明文时,我可以看到最后一个块与我的ESP32不同。
有没有办法解决这个问题?
测试网站:https://www.devglan.com/online-tools/aes-encryption-decryption
从ESP32的Dump:
ea 99 ca 39 2b 62 58 ce 71 5a 75 62 fe ac b7 f0 29 16 0c 1e 20 f5 ba 6f b0 7e c7 ee 0b eb 3a e3 89 51 f4 84 97 61 4b e8 66 22 78 72 60 0f 3e 2d
来自网页的结果:
EA 99 CA 39 2B 62 58 CE 71 5A 75 62 FE AC B7 F0 29 16 0C 1E 20 F5 BA 6F B0 7E C7 EE 0B EB 3A E3 3F 3E 65 3F 78 BA AD 13 AE 74 3E 99 44 1F E1 E5
我已经尝试过Google加密方法,但没有成功。大多数示例都会导致编译错误。
我也尝试了ChatGPT。同样会导致编译错误。
它们警告我使用ECB加密是不安全的。这个警告不适用于我。我的ESP32只会在更新秘密密钥之前发送10-15个块。
英文:
I am trying to encrypt data from ESP32 to an Internet webpage.
The plain text is 31 characters long and will need 3 blocks of 16 characters.
The 2 first blocks encrypts fine, but the last one fails.
The last block is terminated by a 0 in spec for C/C++ string standard.
Please have a look at my code for ref:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "mbedtls/aes.h"
#include "esp_log.h"
#include "aes/esp_aes.h"
#include "mbedtls/base64.h"
#define ESP_AES_ENCRYPT 1
esp_aes_context aes;
unsigned char key[33] = {'d', 'v', 'i', 'z', 'd', 'u', 'm', 'c', 's', 'm', 'v', 'l', 'v', 'f', 'd', 'v', 'b', 'j', 's', 'v', 'd', 'u', 'i', 'a', 's', 'r', 'u', 'i', 'a', 'e', 'u', 'y', '\0'};
unsigned char encrypted[255] = {0};
void crypto_aes_ecb(char *input){
static const char *TAG = "CryptTest";
bool doEncrypt = true;
uint16_t blockIndex = 0;
uint16_t inputIndex = 0;
uint16_t outputIndex = 0;
// unsigned char input[64] = {'T', 'e', 's', 't', 'i', 'n', 'g', ' ', 'e', 'n', 'c', 'r', 'y', 'p', 't', 'i', 'o', 'n', '.', '.', '.', ' ', 'T', 'e', 's', 't', 'i', 'n', 'g', ' ', 'e', 'n', 'c', 'r', 'y', 'p', 't', 'i', 'o', 'n', '.', '.', '.', '\0'};
unsigned char inputBlock[16] = {0};
unsigned char output[17] = {0};
esp_aes_init(&aes);
esp_aes_setkey(&aes, (const unsigned char*) key, 256);
inputIndex = 0;
while(doEncrypt){
for (blockIndex = 0; blockIndex < 16; blockIndex++){
inputBlock[blockIndex] = input[blockIndex + (inputIndex * 16)];
if(input[blockIndex + (inputIndex * 16)] == '\0'){
for (; blockIndex < 16; blockIndex++){inputBlock[blockIndex] = 0;}
doEncrypt = false;
break;
}
}
inputIndex++;
inputBlock[16] = '\0';
ESP_LOGI(TAG, "inputBlock = '%s'", inputBlock);
esp_aes_crypt_ecb(&aes, ESP_AES_ENCRYPT, (const unsigned char *)inputBlock, output);
for (blockIndex = 0; blockIndex < 16; blockIndex++){
encrypted[blockIndex + (outputIndex * 16)] = output[blockIndex];
}
outputIndex++;
}
ESP_LOGW(TAG, "-----------------------------------------------------------------------------------");
ESP_LOGW(TAG, "Key : '%s'", key);
ESP_LOGW(TAG, "Input : '%s'", input);
// ESP_LOGW(TAG, "Output : '%s'", encrypted);
ESP_LOG_BUFFER_HEXDUMP(TAG, encrypted, 128, ESP_LOG_WARN);
esp_aes_free(&aes);
}
void app_main(){
crypto_aes_ecb("Testing encryption... Testing encryption...");
}
Testing the HexDump with an online encrypt / decrypt tester, it reports "Given final block not properly padded. Such issues can arise if a bad key is used during decryption."
Testing the plain text, I can see that the last block is different than my ESP32.
Any idea how to solve this?
Test web site : https://www.devglan.com/online-tools/aes-encryption-decryption
Dump from ESP32 :
ea 99 ca 39 2b 62 58 ce 71 5a 75 62 fe ac b7 f0 29 16 0c 1e 20 f5 ba 6f b0 7e c7 ee 0b eb 3a e3 89 51 f4 84 97 61 4b e8 66 22 78 72 60 0f 3e 2d
Result from web page :
EA 99 CA 39 2B 62 58 CE 71 5A 75 62 FE AC B7 F0 29 16 0C 1E 20 F5 BA 6F B0 7E C7 EE 0B EB 3A E3 3F 3E 65 3F 78 BA AD 13 AE 74 3E 99 44 1F E1 E5
I have tried Googling the encryption method, but no success. Most examples results in compile error.
I have tried ChatGPT. Also results in compile errors.
They warn me of "unsafe" encryption using ECB. The warning does not apply to me. My ESP32 will only send 10-15 blocks before the Secret Key is updated.
答案1
得分: 0
// --- ESP32 侧 ---
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "mbedtls/aes.h"
#include "esp_log.h"
#include "aes/esp_aes.h"
#include "mbedtls/base64.h"
#define ESP_AES_ENCRYPT 1
esp_aes_context aes;
unsigned char key[33] = {'d', 'v', 'i', 'z', 'd', 'u', 'm', 'c', 's', 'm', 'v', 'l', 'v', 'f', 'd', 'v', 'b', 'j', 's', 'v', 'd', 'u', 'i', 'a', 's', 'r', 'u', 'i', 'a', 'e', 'u', 'y', '\0'};
unsigned char encoded[1024] = {0};
void crypto_aes_ecb(char *input){
static const char *TAG = "CryptTest";
bool doEncrypt = true;
uint16_t blockIndex = 0;
uint16_t inputIndex = 0;
uint16_t outputIndex = 0;
uint16_t encryptedLength = 0;
size_t encodedLength = 0;
unsigned char inputBlock[16] = {0};
unsigned char outputBlock[17] = {0};
unsigned char encrypted_raw[1024] = {0};
esp_aes_init(&aes);
esp_aes_setkey(&aes, (const unsigned char*) key, 256);
inputIndex = 0;
while(doEncrypt){
for (blockIndex = 0; blockIndex < 16; blockIndex++){
inputBlock[blockIndex] = input[blockIndex + (inputIndex * 16)];
if(input[blockIndex + (inputIndex * 16)] == '\0'){
for (; blockIndex < 16; blockIndex++){inputBlock[blockIndex] = '\0';}
doEncrypt = false;
break;
}
}
if(input[blockIndex + (inputIndex * 16)] == '\0'){doEncrypt = false;}
inputBlock[16] = '\0';
ESP_LOGI(TAG, "inputBlock = '%s'", inputBlock);
esp_aes_crypt_ecb(&aes, ESP_AES_ENCRYPT, (const unsigned char *)inputBlock, outputBlock);
for (blockIndex = 0; blockIndex < 16; blockIndex++){
encrypted_raw[blockIndex + (outputIndex * 16)] = outputBlock[blockIndex];
}
encryptedLength = blockIndex + (outputIndex * 16);
inputIndex++;
outputIndex++;
}
// encodedLength = mbedtls_base64_encode(encrypted_raw, encryptedLength, encoded, sizeof(encoded));
mbedtls_base64_encode((unsigned char*)encoded, sizeof(encoded), &encodedLength, encrypted_raw, encryptedLength);
encoded[encodedLength] = '\0';
ESP_LOGW(TAG, "-----------------------------------------------------------------------------------");
ESP_LOGI(TAG, "Key : '%s'", key);
ESP_LOGI(TAG, "Input : '%s'", input);
ESP_LOGI(TAG, "Output : '%s'", encoded);
esp_aes_free(&aes);
}
void app_main(){
crypto_aes_ecb("Testing encryption... Testing encryption...");
}
// --- PHP 侧 ---
<?php
$cryptoKey = "dvizdumcsmvlvfdvbjsvduiasruiaeuy";
$base64 = "6pnKOStiWM5xWnVi/qy38CkWDB4g9bpvsH7H7gvrOuOJUfSEl2FL6GYieHJgDz4t";
$intRes = openssl_decrypt($base64, 'AES-256-ECB', $cryptoKey, OPENSSL_ZERO_PADDING);
$decrypted = rtrim($intRes, "\0");
echo "<html>\n<body>\n";
echo "Key : '" . $cryptoKey . "'<br />\n";
echo "Input : '" . $base64 . "'<br />\n";
echo "Decrypted : '" . $decrypted . "'<br />\n";
echo "</body>\n</html>\n";
?>
英文:
So - my solution, if anyone wants a working example:
--- ESP32 side ---
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "mbedtls/aes.h"
#include "esp_log.h"
#include "aes/esp_aes.h"
#include "mbedtls/base64.h"
#define ESP_AES_ENCRYPT 1
esp_aes_context aes;
unsigned char key[33] = {'d', 'v', 'i', 'z', 'd', 'u', 'm', 'c', 's', 'm', 'v', 'l', 'v', 'f', 'd', 'v', 'b', 'j', 's', 'v', 'd', 'u', 'i', 'a', 's', 'r', 'u', 'i', 'a', 'e', 'u', 'y', '\0'};
unsigned char encoded[1024] = {0};
void crypto_aes_ecb(char *input){
static const char *TAG = "CryptTest";
bool doEncrypt = true;
uint16_t blockIndex = 0;
uint16_t inputIndex = 0;
uint16_t outputIndex = 0;
uint16_t encryptedLength = 0;
size_t encodedLength = 0;
unsigned char inputBlock[16] = {0};
unsigned char outputBlock[17] = {0};
unsigned char encrypted_raw[1024] = {0};
esp_aes_init(&aes);
esp_aes_setkey(&aes, (const unsigned char*) key, 256);
inputIndex = 0;
while(doEncrypt){
for (blockIndex = 0; blockIndex < 16; blockIndex++){
inputBlock[blockIndex] = input[blockIndex + (inputIndex * 16)];
if(input[blockIndex + (inputIndex * 16)] == '\0'){
for (; blockIndex < 16; blockIndex++){inputBlock[blockIndex] = '\0';}
doEncrypt = false;
break;
}
}
if(input[blockIndex + (inputIndex * 16)] == '\0'){doEncrypt = false;}
inputBlock[16] = '\0';
ESP_LOGI(TAG, "inputBlock = '%s'", inputBlock);
esp_aes_crypt_ecb(&aes, ESP_AES_ENCRYPT, (const unsigned char *)inputBlock, outputBlock);
for (blockIndex = 0; blockIndex < 16; blockIndex++){
encrypted_raw[blockIndex + (outputIndex * 16)] = outputBlock[blockIndex];
}
encryptedLength = blockIndex + (outputIndex * 16);
inputIndex++;
outputIndex++;
}
// encodedLength = mbedtls_base64_encode(encrypted_raw, encryptedLength, encoded, sizeof(encoded));
mbedtls_base64_encode((unsigned char*)encoded, sizeof(encoded), &encodedLength, encrypted_raw, encryptedLength);
encoded[encodedLength] = '\0';
ESP_LOGW(TAG, "-----------------------------------------------------------------------------------");
ESP_LOGI(TAG, "Key : '%s'", key);
ESP_LOGI(TAG, "Input : '%s'", input);
ESP_LOGI(TAG, "Output : '%s'", encoded);
esp_aes_free(&aes);
}
void app_main(){
crypto_aes_ecb("Testing encryption... Testing encryption...");
}
--- Result ---
I (325) CryptTest: -----------------------------------------------------------------------------------
I (335) CryptTest: Key : 'dvizdumcsmvlvfdvbjsvduiasruiaeuy'
I (335) CryptTest: Input : 'Testing encryption... Testing encryption...'
I (345) CryptTest: Output : '6pnKOStiWM5xWnVi/qy38CkWDB4g9bpvsH7H7gvrOuOJUfSEl2FL6GYieHJgDz4t'
--- PHP side ---
<?php
$cryptoKey = "dvizdumcsmvlvfdvbjsvduiasruiaeuy";
$base64 = "6pnKOStiWM5xWnVi/qy38CkWDB4g9bpvsH7H7gvrOuOJUfSEl2FL6GYieHJgDz4t";
$intRes = openssl_decrypt($base64, 'AES-256-ECB', $cryptoKey, OPENSSL_ZERO_PADDING);
$decrypted = rtrim($intRes, "\0");
echo "<html>\n<body>\n";
echo "Key : '" . $cryptoKey . "'<br />\n";
echo "Input : '" . $base64 . "'<br />\n";
echo "Decrypted : '" . $decrypted . "'<br />\n";
echo "</body>\n</html>\n";
?>
--- Result ---
Key : 'dvizdumcsmvlvfdvbjsvduiasruiaeuy'
Input : '6pnKOStiWM5xWnVi/qy38CkWDB4g9bpvsH7H7gvrOuOJUfSEl2FL6GYieHJgDz4t'
Decrypted : 'Testing encryption... Testing encryption...'
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论