Защита SSL-сертификата Arduino MKR wifi 1010
Я использую Arduino IDE v2.1.1 и Arduino MKR wifi 1010. Все работает нормально, и в данный момент мне нужно защитить Wi-Fi-соединение с помощью SSL-сертификата. Я сгенерировал сертификат SSL с помощью инструмента openssl, и теперь у меня есть следующие файлы, которые необходимо установить в контроллере:
- ca.crt
- client.crt
- client.key
Как мне установить эти три файла на MKR wifi 1010, чтобы включить связь, защищенную сертификатом SSL? Мне не удалось найти руководство или пример в Интернете.
Позвольте мне объяснить, как я это делаю в данный момент. У меня есть действительный самозаверяющий сертификат ЦС, и я пытаюсь установить соединение SSL/TLS, используя только сертификат ЦС. Это мой код, который, к сожалению, не работает:
#include <WiFiNINA.h>
#include <ArduinoJson.h>
#include <ArduinoMqttClient.h>
#include <ArduinoBearSSL.h>
#include <ArduinoECCX08.h>
#include "secrets.h"
char wifiSsid[] = SECRET_WiFi_SSID;
char wifiPass[] = SECRET_WiFi_PASS;
char mqttUserId[] = MQTT_USERID;
char mqttPass[] = MQTT_PASS;
int status = WL_IDLE_STATUS;
const char* rootCAcertificate = \
"-----BEGIN CERTIFICATE-----\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"-----END CERTIFICATE-----\n";
bool dev_debug_mode = IS_DEBUG;
WiFiClient wifiClient; // Используется для соединения через сокет TCP
BearSSLClient bearSslClient(wifiClient); // Используется для соединения SSL/TLS, интегрируется с ECCX08
MqttClient mqttClient(bearSslClient); // Используется для использования протокола MQTT
const char mqttBroker[] = MQTT_BROKER_HOST;
int mqttPort = 8883;
const char deviceRegisterTopic[] = "device/register";
//устанавливаем интервал отправки сообщений Observation (измерение с датчика) (миллисекунды)
const long interval = 3000;
unsigned long previousMillis = 0;
bool deviceIsRegistered = false;
void setup() {
//Инициализируем последовательный порт и ждем открытия порта:
Serial.begin(9600);
while (dev_debug_mode && !Serial) {
; // ждем подключения последовательного порта. Требуется только для собственного USB-порта — режим разработки. Его необходимо удалить при выпуске вживую!!!
}
// Проверяем наличие модуля крипточипа (необходим для BearSSL)
if (!ECCX08.begin()) {
Serial.println("No ECCX08 present!");
while (1);
}
bearSslClient.setEccSlot(0, rootCAcertificate); // вставляем сертификат в слот 0 (ноль)
// ================ НАСТРОЙКА SSL ================
// Устанавливаем обратный вызов для получения текущего времени
// (используется для проверки сертификата сервера)
ArduinoBearSSL.onGetTime(getTime);
// попытка подключения к сети Wi-Fi
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to network: ");
Serial.println(wifiSsid);
// Подключаемся к сети WPA/WPA2:
status = WiFi.begin(wifiSsid, wifiPass);
Serial.print("Attempt status: ");
Serial.println(status);
if(status != WL_CONNECTED) {
// ожидание 10 секунд перед попыткой подключения, если это необходимо:
delay(10000);
}
}
// Соединение с сетью Wi-Fi установлено! отправка некоторых сообщений на консоль
Serial.println("You're connected to the network");
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(mqttBroker);
Serial.println(mqttPort);
mqttClient.setId(mqttUserId);
// добавляем первый уровень защиты с использованием имени пользователя и пароля MQTT-брокера
mqttClient.setUsernamePassword(mqttUserId, mqttPass);
delay(30000);
while (!mqttClient.connect(mqttBroker, mqttPort)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
delay(10000);
}
// Соединение MQTT-брокера установлено! отправка некоторых сообщений на консоль
Serial.println("You're connected to the MQTT broker!");
Serial.println();
}
void loop() {
// регулярно вызываем poll(), чтобы библиотека могла отправлять сообщение MQTT в активное состояние, что
// позволяет избежать отключения брокером
mqttClient.poll();
// если это текущее устройство еще не зарегистрировано, регистрируем устройство впервые
if(!deviceIsRegistered) {
Serial.print("Sending Device Register message to topic: ");
Serial.println(deviceRegisterTopic);
// СДЕЛАЙ ЧТО-НИБУДЬ
}
unsigned long currentMillis = millis();
// отправка фактических данных измерений на сервер FHIR через некоторый интервал времени, например несколько секунд. Будет определено позже.
if (currentMillis - previousMillis >= interval) {
// сохраняем последний раз, когда было отправлено сообщение
previousMillis = currentMillis;
Serial.println();
}
}
// ================================= Вспомогательные функции ============ ======================
unsigned long getTime() {
Serial.print("Current WiFi time:");
Serial.println(WiFi.getTime());
// Получаем текущее время от модуля WiFi
return WiFi.getTime();
}
в приведенном выше коде я использую BearSSLClient, и сертификат устанавливается вручную (я предпочитаю этот способ, поскольку для меня он более прозрачен) bearSslClient.setEccSlot(0, certificate );
— так устанавливается сертификат. Также я делаю следующий вызов: ArduinoBearSSL.onGetTime(getTime); - чтобы успеть. Сертификат CA проверяется с помощью инструмента openssl. Это действительный самозаверяющий корневой сертификат. Пожалуйста, любая помощь очень ценится. Я действительно в замешательстве, так как это должно работать, поскольку сертификат является действительным самозаверяющим сертификатом, и он подтверждается и проверяется с помощью инструмента openssl. Когда что-то должно работать, но не работает, и у меня нет никаких подробностей, кроме сообщения об ошибке -2, это сводит меня с ума ((((
@b1n3t спасибо чуваку за помощь. Я ценю это. Позвольте мне начать с одного: я занимаюсь разработкой программного обеспечения более 16 лет, но с аппаратным обеспечением, таким как микроконтроллеры и оборудование на базе архитектуры i8086, я работал более 10 лет назад. Я никогда глубоко не исследовал проблемы SSL/TLS. Теперь я рассмотрю ваши вопросы один за другим: да, я уверен, что внутренние часы Arduino точны, потому что я настроил себе взаимное соединение TLS с брокером MQTT AWS (Amazon) с включенными этими часами, и все работает нормально. Закрытый ключ может быть неправильно сохранен в ECC608. Это может быть проблемой, поскольку я не уверен на 100%, что сделал это правильно. Да, я проверил, что домен и порт брокера Mosquitto MQTT доступны с устройства, поскольку оно успешно подключается без взаимного TLS. Я могу отправить сообщение обратно и принудительно с устройства на сервер брокера Mosquitto MQ TT без взаимного TLS и без SSL. Да, я настроил Linux-сервер, чтобы разрешить 8883 внешнее соединение. Я использовал инструмент MQTT Explorer для установления взаимного соединения TLS с использованием корневого сертификата CA, сертификатов клиента и сервера с другого физического устройства в моей сети LAN, все работает гладко, он подключается через CA и сертификат клиента к серверу брокера MQTT и Я могу отправлять и получать сообщения. Здесь все хорошо. Позвольте мне захватить журналы и вернуться. Брокер настроен на доверие к ЦС, однако все сертификаты являются самоподписанными. Я боролся с этим уже около пяти дней и понял несколько важных вещей: ECC608 по умолчанию (с завода) находится в разблокированном состоянии, его нельзя использовать, пока он не заблокирован (вручную из кода) . Запрос на подпись сертификата должен быть сгенерирован на устройстве MRK WiFi 1010, а закрытый ключ хранится внутри устройства MKR WiFi 1010, это очень важная деталь. После этого CSR должен быть передан поставщику сертификации, и сертификат sercret должен быть сгенерирован на основе этого CSR (запрос подписи сертификата). Еще одна очень важная деталь заключается в том, что самозаверяющий сертификат, который я использую для разработки, может быть проблемой, поскольку он ВСЕГДА помечен как недействительный только потому, что он самоподписанный.
1 ответ
Похоже, вы добились значительного прогресса. Честно говоря, я считаю, что проблема заключается в том, что ваш закрытый ключ не хранится в ECC608.
Если закрытый ключ не будет правильно сохранен в ECC608, рукопожатие TLS завершится неудачно. Вы упомянули, что ECC608 разблокирован по умолчанию. Вы правы: чтобы использовать безопасные функции чипа, его необходимо заблокировать. Однако, насколько я знаю, если он заблокирован, его нельзя разблокировать. Убедитесь, что вы выполнили необходимые шаги для сохранения вашего закрытого ключа в ECC608, а затем заблокировали его, чтобы защитить ключ. Я думаю, вы можете использовать библиотеку ArduinoECCX08
, поскольку она, похоже, имеет ECCX08.begin()
, ECCX08.lock()
, ECCX08. генерироватьPrivateKey(slot)
. Ваш подход к созданию CSR непосредственно на устройстве MKR WiFi 1010 вполне уместен. Этот метод гарантирует, что закрытый ключ никогда не покинет устройство. Следовательно, в ЦС отправляется только публичная часть, даже если она самоподписанная. С помощью CSR получите сертификат вашего устройства. Этот сертификат в сочетании с закрытым ключом, надежно хранящимся в ECC608, должен облегчить установление связи TLS.
TL;DR: убедитесь, что вы правильно сохранили закрытый ключ в ECC608. Прежде чем блокировать ECC608, проверьте, работает ли закрытый ключ должным образом. Проверьте журналы брокера MQTT для дальнейшей отладки (если они будут предоставлены и когда у меня будет для этого время, я сделаю все возможное, чтобы точно определить ошибку) и попробуйте использовать WireShark для захвата SSL-трафика.
Насколько мне известно, удачи вам. Надеюсь, я смогу помочь, чувак.
привет. Не могли бы вы взглянуть на обновления в моем сегодняшнем вопросе? Эта проблема с SSL/TLS до сих пор не решена, и я понятия не имею, как с ней справиться., @Semen Shekhovtsov
@SemenShekhotsov я немного занят пару дней, когда будет время, постараюсь помочь., @b1n3t
- Как подключиться к Arduino с помощью WiFi?
- ESP8266 не подключается к Wi-Fi
- В чем разница между вариантами RF (wifi, xbee, NRF24L01)
- Как подключить Wi-Fi Shield ESP-12E-ESP8266-UART-WIFI-Wireless-Shield к Arduino
- Можно ли отключить WiFi на ESP8266?
- WebSocketsServer.h: No such file or directory
- Как отключить или остановить точку доступа в ESP8266?
- ESP8266 — действительно ли у него по умолчанию плохой радиус действия Wi-Fi?
Можете ли вы предоставить мне следующую информацию? Недавно я также рассмотрел сообщение -2, так что оно может помочь в устранении неполадок. Вы уверены, что внутренние часы Arduino точны? Вы храните свой закрытый ключ внутри ECC608? Ошибка -2 означает проблему с соединением на уровне сокета. Убедились ли вы, что домен и порт вашего MQTT-брокера доступны с устройства? Вы убедились, что порт 8883 открыт и брандмауэр не блокирует трафик MQTT через SSL? Можете ли вы поделиться своими журналами MQTT Broker? Можете ли вы захватывать SSL-трафик с помощью WireShark и делиться им? Настроен ли брокер доверять ЦС?, @b1n3t
@ b1n3t очень ценю ваш вклад, не могу ответить в комментариях, потому что количество символов ограничено, поэтому я обновил пост ответами., @Semen Shekhovtsov