Строка или беззнаковый символ для uint8_t

esp8266 string eeprom platformio

Я пытаюсь сохранить строку в EEPROM радиостанции ESP8266, а затем прочитать ее обратно, прежде чем зашифровать данные (в конечном итоге я хотел бы сохранить зашифрованные данные, но сейчас я упрощаю ситуацию). Вот исходный код:

#include <Arduino.h>
extern "C" 
{
    #include "cryptoauthlib.h"
}
#include "aes_cbc.h"
#include <EEPROM.h>
// Номер слота ключа
uint8_t KEY_SLOT = (uint8_t)9;

ATCAIfaceCfg cfg;
ATCA_STATUS status;

void writeStringToEEPROM(int addrOffset, const String &strToWrite)
{
  byte len = strToWrite.length();
  EEPROM.write(addrOffset, len);
  for (int i = 0; i < len; i++)
  {
    EEPROM.write(addrOffset + 1 + i, strToWrite[i]);
  }
}

String readStringFromEEPROM(int addrOffset)
{
  int newStrLen = EEPROM.read(addrOffset);
  char data[newStrLen + 1];
  for (int i = 0; i < newStrLen; i++)
  {
    data[i] = EEPROM.read(addrOffset + 1 + i);
  }
  data[newStrLen] = '\0'; 
  return String(data);
}


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

    // Инициализируем конструктор библиотеки
    cfg.iface_type = ATCA_I2C_IFACE;  // Тип связи -> режим I2C
    cfg.devtype = ATECC608A;          // Тип чипа
    cfg.atcai2c.slave_address = 0X30; // I2C-адрес платы Adafruit Breakout Board
    cfg.atcai2c.bus = 1;
    cfg.atcai2c.baud = 100000;
    cfg.wake_delay = 1500; // Задержка пробуждения (1500 мс)
    cfg.rx_retries = 20;
    atca_trace_config(stdout);
}

void loop()
{
    ATCA_STATUS status = atcab_init(&cfg);
    if (status != ATCA_SUCCESS)
    {
        Serial.println(F("atcab_init() failed : Code -> 0x"));
        Serial.println(status, HEX);
    }
    writeStringToEEPROM(0, "test");
    String retrievedString = readStringFromEEPROM(0);
    uint8_t plaintext = atoi(retrievedString.substring(1,3).c_str());
    uint8_t iv[IV_LENGTH_CBC];
    uint8_t cypherdata[sizeof(plaintext)];

    Serial.println("Beginning of the encryption !");
    status = aes_cbc_encrypt(&cfg, plaintext, sizeof(plaintext), iv, cypherdata, KEY_SLOT);
    if (status == ATCA_SUCCESS)
    {
        Serial.println("encrypted");
    }
    else
    {
        // См. файл atca_status.h для ошибки кода
        Serial.print(F("Impossible do the encryption | Code Error 0x"));
        Serial.println(status, HEX);
        return;
    }
}

и вот сообщение об ошибке:

РЕДАКТИРОВАНИЕ**: Обнаружил, что кнопка «Сохранить в EEPROM» часть моего кода не работала, поэтому я это исправил. Вот новый код:

#include <Arduino.h>
extern "C" 
{
    #include "cryptoauthlib.h"
}
#include "aes_cbc.h"
#include <EEPROM.h>
// Номер слота ключа
uint8_t KEY_SLOT = (uint8_t)9;

ATCAIfaceCfg cfg;
ATCA_STATUS status;

void setup()
{
    Serial.begin(74880);
    // Инициализируем конструктор библиотеки
    cfg.iface_type = ATCA_I2C_IFACE;  // Тип связи -> режим I2C
    cfg.devtype = ATECC608A;          // Тип чипа
    cfg.atcai2c.slave_address = 0X30; // I2C-адрес платы Adafruit Breakout Board
    cfg.atcai2c.bus = 1;
    cfg.atcai2c.baud = 100000;
    cfg.wake_delay = 1500; // Задержка пробуждения (1500 мс)
    cfg.rx_retries = 20;
    atca_trace_config(stdout);
}

void loop()
{
    ATCA_STATUS status = atcab_init(&cfg);
    if (status != ATCA_SUCCESS)
    {
        Serial.println(F("atcab_init() failed : Code -> 0x"));
        Serial.println(status, HEX);
    }
    uint addr = 0;
    struct 
    { 
      uint val = 0;
      char str[16] = "";
    } data;

    EEPROM.begin(512);// фиксируем 512 байт флэш-памяти ESP8266 (для эмуляции "EEPROM")
    strcpy(data.str,"test");
    EEPROM.put(addr,data);
    EEPROM.commit();  
    EEPROM.get(addr,data);
    Serial.println(String(data.str));

    uint8_t plaintext = atoi(data.str);
    //uint8_t Plaintext[16] = "тест";
    uint8_t iv[IV_LENGTH_CBC];
    uint8_t cypherdata[sizeof(plaintext)];
    uint8_t decryptdata[sizeof(plaintext)];

    Serial.println("Beginning of the encryption !");
    status = aes_cbc_encrypt(&cfg, &plaintext, sizeof(plaintext), iv, cypherdata, KEY_SLOT);
    if (status == ATCA_SUCCESS)
    {
        Serial.println("encrypted");
        status = aes_cbc_decrypt(&cfg, cypherdata, sizeof(cypherdata), iv, decryptdata, KEY_SLOT);
        if (status == ATCA_SUCCESS)
        {
            Serial.print("Decrypted text is : ");
            for (size_t i = 0; i < sizeof(decryptdata); i++)
            {
                Serial.print((char)decryptdata[i]);
            }
            Serial.println("");
        }
    }
    else
    {
        // См. файл atca_status.h для ошибки кода
        Serial.print(F("Impossible do the encryption | Code Error 0x"));
        Serial.println(status, HEX);
        return;
    }
    delay(1000);
}

Теперь я вижу это в терминале (при компиляции ошибок нет!):

encrypted
ERROR Decrypt : ATCA_BAD_PARAMI2C send 1 bytes to addr 0x30: 01

Когда я меняю (функция aes_cbc_encrypt ожидает длину 16)

sizeof(plaintext)

в

16

Я вижу:

Decrypted text is : ␀␀␀␀␀␀␀␀l��?���?

Когда я доказал, что часть моего кода, шифрующая/дешифрующая, работает, вот что "открытый текст" было:

 uint8_t plaintext[16] = "test";

, 👍0

Обсуждение

Пожалуйста, не используйте текст как изображение. Вы можете скопировать сообщение об ошибке в виде текста в свой вопрос и отформатировать его так же, как код., @chrisl

Функция ожидает указатель на данные. Попробуйте передать его по ссылке как & Plaintext. Хотя я не уверен, действительно ли ты этого хочешь. Имя переменной plaintext предполагает, что это должен быть текст. Хотя это просто число (8-битное целое число без знака), @chrisl

Опять же, вы, кажется, думаете, что «открытый текст» содержит текстовое сообщение. Это не. sizeof(plaintext) всегда равен 1, поскольку plaintext имеет только 1 байт. Вы шифруете один «символ», хотя на самом деле это не символ, а двоичное представление числа. Для меня не имеет никакого смысла шифровать один байт. Почему вы используете atoi() при назначении plaintext? Закомментированная строка предполагает, что это должен быть массив, содержащий строку ac., @chrisl

Крисл, В другом рабочем коде у меня было uint8_t Plaintext[16] = "тест"; Без бита EEPROM это сработало. Когда я пытаюсь заменить «test» на data.str, компиляция выдает ошибку. Если мне нужно вызвать что-то кроме открытого текста, хорошо. Я специалист по аппаратному обеспечению, который изо всех сил старается стать лучше в прошивке, поэтому извините, если я не разбираюсь в простых вещах., @PhippsTech


1 ответ


Лучший ответ:

0

Функция atoi() пытается интерпретировать строку как текстовый представление числа, записанного в десятичной форме. Например, atoi("42") возвращает целое число 42. Здесь:

uint8_t plaintext = atoi(data.str);

Вы просите его интерпретировать "test", который не похож на число. В таком случае atoi() возвращает ноль. Я не знаю, что было ваше намерение, но, вероятно, это было не это.

Далее у вас есть

uint8_t cypherdata[sizeof(plaintext)];
uint8_t decryptdata[sizeof(plaintext)];

Учитывая, что plaintext представляет собой один байт, его длина равна единице. Таким образом, это объявление двух массивов длиной один. Опять же, вы, вероятно, что-то имели в виду еще.


Из вашего комментария я понял, что вы хотите, чтобы plaintext представлял строку "test" как массив uint8_t. Поскольку и char, и uint8_t представляют байты, преобразование не выполняется. нужный. Вы можете просто использовать адрес исходного массива char и «представьте», что это адрес массива uint8_t:

uint8 *plaintext = (uint8_t *) data.str;
,

Я просто храню строку «test» в EEPROM, а затем преобразую ее в uint, чтобы ее можно было поместить в функцию aes_cbc_encrypt. Я изменил команду atoi на toInt и все равно получаю то же самое. Я отредактирую сообщение, чтобы объяснить, что в исходном примере aes_ebc_encrypt я использовал uint8 Plaintext[16] = "test"; и это работало., @PhippsTech

в этом есть смысл. Это сработало, и я просто поставил 16 для размера (открытый текст). На данный момент это должно сработать. Спасибо!, @PhippsTech