Zakładamy, że mamy już własny certyfikat SSL (CA i dla hosta) oraz działającego hosta z tym certyfikatem.

Do weryfikacji czy połączyliśmy się z właściwym hostem wykorzystać możemy dodatkowo odcisk jego ceryfikatu. Odcisk uzyskać możemy wydając polecenie: openssl x509 -noout -in server.crt -fingerprint

Na początku musimy dodać bibliotekę ESP8266WiFi.h

#include <ESP8266WiFi.h>

Dodajemy stałe przechowujące parametry logowania do sieci WiFi

const char* ssid = "SSID";
const char* pass = "PASS";

Umieszczamy odcisk naszego certyfikatu w kodzie programu

const char* ca_fingerprint = "C4:39:F9:E7:09:24:57:5D:FB:60:51:AE:F9:D3:34:51:0E:30:3D:F9";

Dobrze jest przynajmniej w fazie testów wiedzieć co się dzieje - dodamy więc kilka komunikatów które polecą na port szeregowy

Serial.begin(9600);
Serial.println();
Serial.print("connecting to ");

Uruchamiamy WiFi w ESP8266

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);

Dodajemy kolejne komunikaty pozwalające sprawdzić stan połączenia

while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

Po uzyskaniu połączenia musimy zadbać o to, by nasz kontroler wiedział jaki jest bieżący czas - jest to niezbędne by mógł zweryfikować czy certyfikaty są ważne.

Serial.print("Ustawianie czasu przy użyciu SNTP");
configTime(8 * 3600, 0, "pool.ntp.org", "time.nist.gov");
time_t now = time(nullptr);
while (now < 8 * 3600 * 2) {
  delay(500);
  Serial.print(".");
  now = time(nullptr);
}

Serial.println("");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Serial.print("Aktualny czas: ");
Serial.print(asctime(&timeinfo));

Tworzymy obiekt WiFiClientSecure który pozwala nawiązać bezpieczne połączenie z użyciem SSL. Zanim jednak zestawimy połączenie musimy dodać do naszego programu certyfikat CA na podstawie którego będzie weryfikowana poprawność certyfikatu hosta z którym będziemy się łączyć.

const char* ca_cert PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDPzCCAiegAwIBAgIUKMEAPaSs6uPNyhs+4WV/HqzlaLAwDQYJKoZIhvcNAQEL
BQAwLzELMAkGA1UEBhMCUEwxEzARBgNVBAgMClNvbWUtU3RhdGUxCzAJBgNVBAoM
Am1xMB4XDTIwMDkyNzEyMTYzNFoXDTQ4MDIxMjEyMTYzNFowLzELMAkGA1UEBhMC
UEwxEzARBgNVBAgMClNvbWUtU3RhdGUxCzAJBgNVBAoMAm1xMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAufbgml7+2ZxT4flxfcasdwZjcoHlwEvzjR9f
kDUy0+cvtjODOa1TDwAvn90hMdw8kYXwSKZDYKB+B82miuU6UqVIFtrU3f+5irJU
NgAE7m3LDACQJB0OyEj8qg2bK7gPQrxuTXwDR4fAY/lTrwk60MCJoR4OuQSPbl+d
+C19UbsOtBzn1O8/rlJhnVfSOmsLFvJVkqB7VHn+M76JeDJqgsRjRRKzrjsB9RfY
jPZQolUFEIEhHvGIAEaf84ktFQCqlTT1elN98kqoYdREKGyJwa4tFrz4JXVoj70j
a3we5/nTxNL3Gqk7LpkdEp3A81dtMxaqRZwbfgOf5gfANbGRIQIDAQABo1MwUTAd
BgNVHQ4EFgQUmpHdWQfELBrWaJTSWdIHlfTdWlUwHwYDVR0jBBgwFoAUmpHdWQfE
LBrWaJTSWdIHlfTdWlUwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
AQEAUee2dQgfmLiLzZP0ma8b4eFupqIFwM7pu4s8e85kLChYESxIiGC8HL0gIrKL
grQSAcMHgRyTu+Zc6Bv50c9KgOGczkO21gdlbCj9sEu5zee7Uf+bQGjeKuekcfCM
uSPJ/gn66lfkgWo9Gl7q1Njyfzip3A2Lw47akikLS8g5Ufi4sqiiRUY3zbob/csi
T8IhcQstLipozK7+vAy4Ole+vNX1EXIA74/Xd9z3NGIuPNzFGl0v9V+ByCZETd73
1GUZM0GvNi2mIvtWhzKH65V0jx0luDmqDUAuR8uHY2o9wwsQiJ75Bf1M8tCso+hK
5byPp/2P+hjDCsSPwHewxAYndw==
-----END CERTIFICATE-----
)EOF";

Dodajemy powyższy certyfikat do naszego "składu certyfikatów"

X509List caCertX509(caCert);

Jeżeli zajdzie potrzeba dodania kolejnych certyfikatów do listy certyfikatów można użyć funkcji .append(const char *pemX509)

Tworzymy klasę klienta która nawiąże zaszyfrowane połączenie

WiFiClientSecure espClient;

Ważnym jest by pozwolić obiektowi espClient na weryfikację własnych certyfikatów i wskazać nasz skład certyfikatów

espClient.allowSelfSignedCerts();
espClient.setTrustAnchors(&caCertX509);

W razie potrzeby można nakazać naszemu klientowi ignorowanie sprwadzenia certyfikatów ale takie działanie sprawdza się najwyżej do celów testowych. By uzyskać taki efekt zamiast powyższego należy wywołać funkcję espClient.setInsecure(); Teraz możemy nakazać wykonanie połączenia...

if (!espClient.connect("111.222.255.255", 443)) {
    Serial.print("connection failed :");
    return;
}

... i zweryfikować czy odcisk certyfikatu się zgadza

if (espClient.verify(ca_fingerprint, "111.222.255.255")) {
  Serial.println("certificate matches");
} else {
  Serial.println("certificate doesn't match");
}

Poprzedni wpis Następny wpis