尝试使用ESP32(PlatformIO)加密通信。esp_aes_crypt_ecb在最后一个块上失败。

huangapple go评论107阅读模式
英文:

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 &lt;stdio.h&gt;
#include &quot;freertos/FreeRTOS.h&quot;
#include &quot;freertos/task.h&quot;
#include &quot;esp_log.h&quot;
#include &quot;esp_system.h&quot;
#include &quot;esp_spi_flash.h&quot;
#include &quot;mbedtls/aes.h&quot;
#include &quot;esp_log.h&quot;
#include &quot;aes/esp_aes.h&quot;
#include &quot;mbedtls/base64.h&quot;
#define ESP_AES_ENCRYPT 1
esp_aes_context aes;
unsigned char key[33] = {&#39;d&#39;, &#39;v&#39;, &#39;i&#39;, &#39;z&#39;, &#39;d&#39;, &#39;u&#39;, &#39;m&#39;, &#39;c&#39;, &#39;s&#39;, &#39;m&#39;, &#39;v&#39;, &#39;l&#39;, &#39;v&#39;, &#39;f&#39;, &#39;d&#39;, &#39;v&#39;, &#39;b&#39;, &#39;j&#39;, &#39;s&#39;, &#39;v&#39;, &#39;d&#39;, &#39;u&#39;, &#39;i&#39;, &#39;a&#39;, &#39;s&#39;, &#39;r&#39;, &#39;u&#39;, &#39;i&#39;, &#39;a&#39;, &#39;e&#39;, &#39;u&#39;, &#39;y&#39;, &#39;\0&#39;};
unsigned char encrypted[255] = {0};
void crypto_aes_ecb(char *input){
static const char *TAG = &quot;CryptTest&quot;;
bool doEncrypt = true;
uint16_t blockIndex = 0;
uint16_t inputIndex = 0;
uint16_t outputIndex = 0;
//    unsigned char input[64] = {&#39;T&#39;, &#39;e&#39;, &#39;s&#39;, &#39;t&#39;, &#39;i&#39;, &#39;n&#39;, &#39;g&#39;, &#39; &#39;, &#39;e&#39;, &#39;n&#39;, &#39;c&#39;, &#39;r&#39;, &#39;y&#39;, &#39;p&#39;, &#39;t&#39;, &#39;i&#39;, &#39;o&#39;, &#39;n&#39;, &#39;.&#39;, &#39;.&#39;, &#39;.&#39;, &#39; &#39;, &#39;T&#39;, &#39;e&#39;, &#39;s&#39;, &#39;t&#39;, &#39;i&#39;, &#39;n&#39;, &#39;g&#39;, &#39; &#39;, &#39;e&#39;, &#39;n&#39;, &#39;c&#39;, &#39;r&#39;, &#39;y&#39;, &#39;p&#39;, &#39;t&#39;, &#39;i&#39;, &#39;o&#39;, &#39;n&#39;, &#39;.&#39;, &#39;.&#39;, &#39;.&#39;, &#39;\0&#39;};
unsigned char inputBlock[16] = {0};
unsigned char output[17] = {0};
esp_aes_init(&amp;aes);
esp_aes_setkey(&amp;aes, (const unsigned char*) key, 256);
inputIndex = 0;
while(doEncrypt){
for (blockIndex = 0; blockIndex &lt; 16; blockIndex++){
inputBlock[blockIndex] = input[blockIndex + (inputIndex * 16)];
if(input[blockIndex + (inputIndex * 16)] == &#39;\0&#39;){
for (; blockIndex &lt; 16; blockIndex++){inputBlock[blockIndex] = 0;}
doEncrypt = false;
break;
}
}
inputIndex++;
inputBlock[16] = &#39;\0&#39;;
ESP_LOGI(TAG, &quot;inputBlock = &#39;%s&#39;&quot;, inputBlock);
esp_aes_crypt_ecb(&amp;aes, ESP_AES_ENCRYPT, (const unsigned char *)inputBlock, output);
for (blockIndex = 0; blockIndex &lt; 16; blockIndex++){
encrypted[blockIndex + (outputIndex * 16)] = output[blockIndex];
}
outputIndex++;
}
ESP_LOGW(TAG, &quot;-----------------------------------------------------------------------------------&quot;);
ESP_LOGW(TAG, &quot;Key     : &#39;%s&#39;&quot;, key);
ESP_LOGW(TAG, &quot;Input   : &#39;%s&#39;&quot;, input);
//    ESP_LOGW(TAG, &quot;Output  : &#39;%s&#39;&quot;, encrypted);
ESP_LOG_BUFFER_HEXDUMP(TAG, encrypted, 128, ESP_LOG_WARN);
esp_aes_free(&amp;aes);
}
void app_main(){
crypto_aes_ecb(&quot;Testing encryption... Testing encryption...&quot;);
}

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 &lt;stdio.h&gt;
#include &quot;freertos/FreeRTOS.h&quot;
#include &quot;freertos/task.h&quot;
#include &quot;esp_log.h&quot;
#include &quot;esp_system.h&quot;
#include &quot;esp_spi_flash.h&quot;
#include &quot;mbedtls/aes.h&quot;
#include &quot;esp_log.h&quot;
#include &quot;aes/esp_aes.h&quot;
#include &quot;mbedtls/base64.h&quot;
#define ESP_AES_ENCRYPT 1
esp_aes_context aes;
unsigned char key[33] = {&#39;d&#39;, &#39;v&#39;, &#39;i&#39;, &#39;z&#39;, &#39;d&#39;, &#39;u&#39;, &#39;m&#39;, &#39;c&#39;, &#39;s&#39;, &#39;m&#39;, &#39;v&#39;, &#39;l&#39;, &#39;v&#39;, &#39;f&#39;, &#39;d&#39;, &#39;v&#39;, &#39;b&#39;, &#39;j&#39;, &#39;s&#39;, &#39;v&#39;, &#39;d&#39;, &#39;u&#39;, &#39;i&#39;, &#39;a&#39;, &#39;s&#39;, &#39;r&#39;, &#39;u&#39;, &#39;i&#39;, &#39;a&#39;, &#39;e&#39;, &#39;u&#39;, &#39;y&#39;, &#39;\0&#39;};
unsigned char encoded[1024] = {0};
void crypto_aes_ecb(char *input){
static const char *TAG = &quot;CryptTest&quot;;
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(&amp;aes);
esp_aes_setkey(&amp;aes, (const unsigned char*) key, 256);
inputIndex = 0;
while(doEncrypt){
for (blockIndex = 0; blockIndex &lt; 16; blockIndex++){
inputBlock[blockIndex] = input[blockIndex + (inputIndex * 16)];
if(input[blockIndex + (inputIndex * 16)] == &#39;\0&#39;){
for (; blockIndex &lt; 16; blockIndex++){inputBlock[blockIndex] = &#39;\0&#39;;}
doEncrypt = false;
break;
}
}
if(input[blockIndex + (inputIndex * 16)] == &#39;\0&#39;){doEncrypt = false;}
inputBlock[16] = &#39;\0&#39;;
ESP_LOGI(TAG, &quot;inputBlock = &#39;%s&#39;&quot;, inputBlock);
esp_aes_crypt_ecb(&amp;aes, ESP_AES_ENCRYPT, (const unsigned char *)inputBlock, outputBlock);
for (blockIndex = 0; blockIndex &lt; 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), &amp;encodedLength, encrypted_raw, encryptedLength);
encoded[encodedLength] = &#39;\0&#39;;
ESP_LOGW(TAG, &quot;-----------------------------------------------------------------------------------&quot;);
ESP_LOGI(TAG, &quot;Key     : &#39;%s&#39;&quot;, key);
ESP_LOGI(TAG, &quot;Input   : &#39;%s&#39;&quot;, input);
ESP_LOGI(TAG, &quot;Output  : &#39;%s&#39;&quot;, encoded);
esp_aes_free(&amp;aes);
}
void app_main(){
crypto_aes_ecb(&quot;Testing encryption... Testing encryption...&quot;);
}

--- Result ---

I (325) CryptTest: -----------------------------------------------------------------------------------
I (335) CryptTest: Key     : &#39;dvizdumcsmvlvfdvbjsvduiasruiaeuy&#39;
I (335) CryptTest: Input   : &#39;Testing encryption... Testing encryption...&#39;
I (345) CryptTest: Output  : &#39;6pnKOStiWM5xWnVi/qy38CkWDB4g9bpvsH7H7gvrOuOJUfSEl2FL6GYieHJgDz4t&#39;

--- PHP side ---

&lt;?php
$cryptoKey = &quot;dvizdumcsmvlvfdvbjsvduiasruiaeuy&quot;;
$base64 = &quot;6pnKOStiWM5xWnVi/qy38CkWDB4g9bpvsH7H7gvrOuOJUfSEl2FL6GYieHJgDz4t&quot;;
$intRes = openssl_decrypt($base64, &#39;AES-256-ECB&#39;, $cryptoKey,  OPENSSL_ZERO_PADDING);
$decrypted = rtrim($intRes, &quot;\0&quot;);
echo &quot;&lt;html&gt;\n&lt;body&gt;\n&quot;;
echo &quot;Key       : &#39;&quot; . $cryptoKey . &quot;&#39;&lt;br /&gt;\n&quot;;
echo &quot;Input     : &#39;&quot; . $base64 . &quot;&#39;&lt;br /&gt;\n&quot;;
echo &quot;Decrypted : &#39;&quot; . $decrypted . &quot;&#39;&lt;br /&gt;\n&quot;;
echo &quot;&lt;/body&gt;\n&lt;/html&gt;\n&quot;;
?&gt;

--- Result ---

Key : &#39;dvizdumcsmvlvfdvbjsvduiasruiaeuy&#39;
Input : &#39;6pnKOStiWM5xWnVi/qy38CkWDB4g9bpvsH7H7gvrOuOJUfSEl2FL6GYieHJgDz4t&#39;
Decrypted : &#39;Testing encryption... Testing encryption...&#39;

huangapple
  • 本文由 发表于 2023年7月31日 22:44:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76804720.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定