Когато създаваме устройства с комерсиална цел или работим с поверителна информация, трябва да си даваме сметка, че използването на некриптирани методи за комуникация, като HTTP са лоша идея. От друга страна работата със SSL на устройства с 50 килобайта оперативна е истинско предизвикателство.
Търсейки в интернет ще попаднете на доста подвеждащи примери, които може докарат вашите устройства на ръба на ресурсите и ще направят вашите проекти нестабилни.
Ще използвам примерът от предишната статия:
#include "ESP8266WiFi.h"
#include "ESP8266HTTPClient.h"
// SSID и парола на домашната ви мрежа
const char *ssid = "TechPotWin";
const char *password = "techpotpass";
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Свързване с WiFi");
// задаваме режим клиент на WiFi
WiFi.mode(WIFI_STA);
// задаваме SSID и парола за свързване
WiFi.begin(ssid, password);
// създаваме променлива с която да броим интервали с неуспешните опити за свързване
int retries = 0;
// проверяваме дали WiFi е свързан успешно и дали не сме изчерпали броят на неуспешните интервали
while ((WiFi.status() != WL_CONNECTED) && (retries < 10)) {
// увеличаваме брояча на интервали с едно
retries++;
// изчакваме половин секунда
delay(500);
// извеждаме точка в серийния монитор
Serial.print(".");
}
// извеждаме нова линия в серийния монитор
Serial.println();
// ако сме свързани
if (WiFi.status() == WL_CONNECTED) {
// извеждаме IP адресът получен от DHCP
Serial.println("WiFi свързан!");
Serial.println("IP адрес: ");
Serial.println(WiFi.localIP());
} else {
// иначе извеждаме съобщение за грешка
Serial.println("WiFi свързване НЕУСПЕШНО");
}
}
void loop() {
// проверяваме дали WiFi е свързан
if (WiFi.status() == WL_CONNECTED) {
// създаваме HTTPClient обект
HTTPClient http;
// създаваме WiFiClientSecure обект
BearSSL::WiFiClientSecure ClientSecure;
// не проверяваме валидността на сертификата
ClientSecure.setInsecure();
// проверяваме валидността на отпечатъка
//ClientSecure.setFingerprint("CC 6C 38 F4 DC 16 94 C5 5E 6D 05 1C 6A 52 B3 D2 6B D9 CC 59");
// намаляваме размера на буфера, за да спестим памет (не е съвместимо със всички сървъри)
ClientSecure.setBufferSizes(512, 512);
// задаваме сайт, към който ще правим запитване
http.begin(ClientSecure, "https://esolog.win/eso-current.php?type=load");
// правим запитване
int httpCode = http.GET();
// ако http кодът е 200 (означава "успех")
if (httpCode == 200) {
// тогава извеждаме в серийният монитор резултатът от запитването
Serial.print("Товар на РБ: ");
Serial.print(http.getString());
Serial.println("MW");
}
http.end();
ClientSecure.stop();
}
// изчакваме една секунда
delay(60000);
}
Резултатът:

Дължа малко обяснение:
BearSSL е сравнително нов клас, в който е добавена възможност да намалим размера на буфера при SSL комуникация (разбира се сървъра, с който се свързваме трябва да бъде съвместим).
Чрез ClientSecure.setInsecure(); ние се отказваме от проверка на валидността на сертификата (използваме криптирана връзка, но не проверяваме дали сървърът, който отговаря отсреща е този, който очакваме), което създава вектор за атака. Като алтернатива вместо ClientSecure.setInsecure(); може да използваме ClientSecure.setFingerprint("...");, където вместо ... ще трябва да напишем SHA1 отпечатъка на нашият сертификат. Най-лесният начин да стигнем до отпечатъка е като отворим в браузър даденият интернет адрес, натиснем катинарчето и (при Chrome базираните браузъри) след това натиснем Certificate

Трябва да се има предвид, че при всяко регенериране на сертификат, нашият отпечатък (Fingerprint) се променя. Сертификатите генерирани чрез Let’s Encrypt имат валидност 90 дни, но обичайна практика е да се обновяват на всеки 30 дни, което означава, че трябва да сме подготвени за резервен план (fallback), с който да обновим данните на нашето устройство, което от своя страна обезсмисля цялата гимнастика.
