Created
May 4, 2020 22:38
-
-
Save Bolukan/177082d4c40f45e6bce23c8d4ccc7eb2 to your computer and use it in GitHub Desktop.
Root Certificate Example for Brian
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if !defined(ESP8266) | |
#error This file is for ESP8266 only | |
#endif | |
#define COMPDATE __DATE__ " " __TIME__ | |
#define APPNAME "Root Certificate Example" | |
#define VERSION "V0.0.2" | |
#include <Arduino.h> | |
#include <ESP8266WiFi.h> // Arduino library - https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/ESP8266WiFi.h | |
#include <WiFiClientSecure.h> // Arduino library - https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/WiFiClientSecure.h | |
#include <time.h> // Arduino library - Secure connections need the right time to know validity of certificate. | |
#include "secrets.h" | |
#ifndef SECRETS_H | |
#define SECRETS_H | |
const char WIFI_SSID[] = "ssid"; | |
const char WIFI_PASSWORD[] = "password"; | |
#endif | |
// *********************************** CONSTANTS ***************************** | |
// time | |
static const int TIME_TIMEZONE_NL = 3600; | |
static const int TIME_DAYLIGHTOFFSET_SEC_NL = 3600; | |
static const char TIME_NTPSERVER_1[] = "nl.pool.ntp.org"; | |
static const char TIME_NTPSERVER_2[] = "pool.ntp.org"; | |
const char HOST_SITE[] = "jsonplaceholder.typicode.com"; | |
const uint16_t POST_SITE = 443; | |
const char PATH_SITE[] = "/todos/1"; | |
// Baltimore CyberTrust Root | |
const char CERTIFICATE_ROOT[] = R"=EOF=( | |
-----BEGIN CERTIFICATE----- | |
MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ | |
RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD | |
VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX | |
DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y | |
ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy | |
VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr | |
mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr | |
IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK | |
mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu | |
XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy | |
dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye | |
jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 | |
BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 | |
DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 | |
9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx | |
jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 | |
Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz | |
ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS | |
R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp | |
-----END CERTIFICATE----- | |
)=EOF="; | |
// Used by spotify: | |
// DigiCert Global Root CA | |
const char CERTIFICATE_ROOT2[] = R"=EOF=( | |
-----BEGIN CERTIFICATE----- | |
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh | |
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 | |
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD | |
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT | |
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j | |
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG | |
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB | |
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 | |
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt | |
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P | |
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 | |
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO | |
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR | |
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw | |
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr | |
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg | |
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF | |
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls | |
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk | |
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= | |
-----END CERTIFICATE----- | |
)=EOF="; | |
// *********************************** VARIABLES ***************************** | |
BearSSL::WiFiClientSecure client; | |
BearSSL::X509List cert(CERTIFICATE_ROOT); | |
BearSSL::Session session; | |
int lastloopminute = 99; | |
bool wifiAvailable = false; | |
bool clientAvailable = false; | |
// *********************************** TIME ********************************** | |
void time_gettime() | |
{ | |
// timezone CET = 3600, daylight CET->CEST = 3600 | |
// void configTime(int timezone, int daylightOffset_sec, const char* server1, const char* server2, const char* server3) | |
configTime(TIME_TIMEZONE_NL, TIME_DAYLIGHTOFFSET_SEC_NL, TIME_NTPSERVER_1, TIME_NTPSERVER_2); | |
// wait for NTP returns value | |
time_t now = time(nullptr); | |
while (now < 24 * 3600) | |
{ | |
delay(100); | |
now = time(nullptr); | |
} | |
// show datetime in Serial | |
struct tm timeinfo; | |
gmtime_r(&now, &timeinfo); | |
Serial.printf("UTC : %s", asctime(&timeinfo)); | |
} | |
// *********************************** WIFI ********************************** | |
// More events: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h | |
void onSTAConnected(WiFiEventStationModeConnected e /*String ssid, uint8 bssid[6], uint8 channel*/) | |
{ | |
Serial.printf("WiFi Connected: SSID %s @ BSSID %.2X:%.2X:%.2X:%.2X:%.2X:%.2X Channel %d\n", | |
e.ssid.c_str(), e.bssid[0], e.bssid[1], e.bssid[2], e.bssid[3], e.bssid[4], e.bssid[5], e.channel); | |
} | |
void onSTADisconnected(WiFiEventStationModeDisconnected e /*String ssid, uint8 bssid[6], WiFiDisconnectReason reason*/) | |
{ | |
Serial.printf("WiFi Disconnected: SSID %s BSSID %.2X:%.2X:%.2X:%.2X:%.2X:%.2X Reason %d\n", | |
e.ssid.c_str(), e.bssid[0], e.bssid[1], e.bssid[2], e.bssid[3], e.bssid[4], e.bssid[5], e.reason); | |
// Reason: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/ESP8266WiFiType.h | |
wifiAvailable = false; | |
} | |
void onSTAGotIP(WiFiEventStationModeGotIP e /*IPAddress ip, IPAddress mask, IPAddress gw*/) | |
{ | |
Serial.printf("WiFi GotIP: localIP %s SubnetMask %s GatewayIP %s\n", | |
e.ip.toString().c_str(), e.mask.toString().c_str(), e.gw.toString().c_str()); | |
wifiAvailable = true; | |
clientAvailable = false; | |
} | |
// *********************************** SETUP ********************************* | |
// Try and connect using a WiFiClientBearSSL to specified host:port and dump HTTP response | |
void fetchURL( | |
BearSSL::WiFiClientSecure *client, | |
const char *host, | |
const uint16_t port, | |
const char *path) | |
{ | |
if (!path) | |
{ | |
path = "/"; | |
} | |
Serial.printf("URL: %s:443%s ... ", host, path); | |
client->connect(host, port); | |
if (!client->connected()) | |
{ | |
Serial.printf("*** Can't connect. ***\n-------\n"); | |
return; | |
} | |
Serial.printf("connected!\n-------\n"); | |
client->write("GET "); | |
client->write(path); | |
client->write(" HTTP/1.0\r\nHost: "); | |
client->write(host); | |
client->write("\r\nUser-Agent: ESP8266\r\n"); | |
// client->write("Authorization\r\n"); | |
client->write("Connection: close\r\n"); | |
client->write("\r\n"); | |
uint32_t to = millis() + 5000; | |
if (client->connected()) | |
{ | |
do | |
{ | |
String line = client->readStringUntil('\n'); | |
if (line == "\r") | |
{ | |
Serial.println("**** END OF HEADERS *****"); | |
break; | |
} | |
Serial.println(line); // print header | |
} while (millis() < to); | |
do | |
{ | |
String line = client->readStringUntil('\n'); | |
Serial.println(line); | |
} while (millis() < to); | |
} | |
client->stop(); | |
Serial.printf("\n-------\n\n"); | |
} | |
// *********************************** SETUP ********************************* | |
void setup() | |
{ | |
// WiFi | |
static WiFiEventHandler e1, e2, e4; | |
// Serial | |
Serial.begin(115200); | |
Serial.println(); | |
Serial.println(APPNAME); | |
Serial.println(VERSION " - " COMPDATE); | |
Serial.println(); | |
// WiFi events | |
e1 = WiFi.onStationModeConnected(onSTAConnected); | |
e2 = WiFi.onStationModeDisconnected(onSTADisconnected); | |
e4 = WiFi.onStationModeGotIP(onSTAGotIP); | |
WiFi.mode(WIFI_STA); | |
WiFi.setAutoConnect(false); // do not automatically connect on power on to the last used access point | |
WiFi.setAutoReconnect(true); // attempt to reconnect to an access point in case it is disconnected | |
WiFi.persistent(false); // Store no SSID/PASSWORD in flash | |
WiFi.begin(WIFI_SSID, WIFI_PASSWORD); | |
} | |
void loop() | |
{ | |
if ((wifiAvailable) && (!clientAvailable)) { | |
Serial.print("Get time: "); | |
time_gettime(); | |
Serial.print("Load certificates: "); | |
// Add certificates to client | |
client.setSession(&session); // certificate session to have more performance with subsequent calls | |
client.setTrustAnchors(&cert); | |
Serial.println("done"); | |
clientAvailable = true; | |
Serial.println(); | |
} | |
time_t now = time(nullptr); | |
struct tm timeinfo; | |
gmtime_r(&now, &timeinfo); | |
if (lastloopminute != timeinfo.tm_min) | |
{ | |
lastloopminute = timeinfo.tm_min; | |
if (clientAvailable) | |
{ | |
Serial.printf("%d:%d Retrieving ", timeinfo.tm_hour, timeinfo.tm_min); | |
fetchURL(&client, HOST_SITE, POST_SITE, PATH_SITE); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment