Skip to content

Instantly share code, notes, and snippets.

@Bolukan
Created May 4, 2020 22:38
Show Gist options
  • Save Bolukan/177082d4c40f45e6bce23c8d4ccc7eb2 to your computer and use it in GitHub Desktop.
Save Bolukan/177082d4c40f45e6bce23c8d4ccc7eb2 to your computer and use it in GitHub Desktop.
Root Certificate Example for Brian
#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