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");
}