How to use self-signed certificate on esp8266

I'm trying to make request from esp8266 to my Flask app running on localhost.

I'm able to send http request from my esp6288 when the Flask app is running on http with:

app.run(host="0.0.0.0", debug=True)

Now I'm trying to run Flask app locally on https using self-signed certificate, and requests from browser works.

app.run(host="0.0.0.0", ssl_context=('https_keys/cert.pem', 'https_keys/key.pem'), debug=True)

But requests from esp8266 fail on my app but work on another online website (with appropriate certificate).
Here is my code:

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>

const char* ssid = "mySSID";     // Replace with your WiFi SSID
const char* password = "password"; // Replace with your WiFi password

// Initialize BearSSL
BearSSL::WiFiClientSecure client;

// Root certificate for howsmyssl.com
const char IRG_Root_X1 [] PROGMEM = R"CERT(
-----BEGIN CERTIFICATE-----
MIIF4zCCA8ugAwIBAgIUfjixYjpiV7ZKTGaO+uHCHY8PokowDQYJKoZIhvcNAQEL
BQAwgYAxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhOZXcgWW9yazERMA8GA1UEBwwI
TmV3IFlvcmsxDTALBgNVBAoMBFRvdG8xDTALBgNVBAsMBHVuaXQxDTALBgNVBAMM
BG5hbWUxHjAcBgkqhkiG9w0BCQEWD290b3RAaXJ3ZW9yLmNvbTAeFw0yNDAxMTYw
OTE2MjhaFw0yNTAxMTUwOTE2MjhaMIGAMQswCQYDVQQGEwJVUzERMA8GA1UECAwI
TmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMQ0wCwYDVQQKDARUb3RvMQ0wCwYD
VQQLDAR1bml0MQ0wCwYDVQQDDARuYW1lMR4wHAYJKoZIhvcNAQkBFg9vdG90QGly
d2Vvci5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDMxtq54xdb
X49eSc431LVyv0hoQxj3v0nft08TSM5yvpVKdyO9ICZiz2OMD04Rb2fV5NHStSVr
11vJ2bZDiwwazkaEzb3EcM85iKk2gIMQP/3wLybqyNGQvocGbk6jc9aaNWpMvaEe
lii7SM1Y8TDx060SyWEKDTMFibfZsStc4W2N+4a/2mm6IzWMydqKyUkjujO5AzgO
SNZeFpMESCg42cukcNB+qMAww+zrvPeE7v/mrYH2N5XsjD7zbH4NJcq2hwVPFuHE
CIBDjeFpjz+Ee+7MAdwvPjB+X4oR98kigEemXzl26tljR466oXFz8nbQbEACxufg
JqCeoB6NeZRt3Ie5TXbWKsPQdG2lBsIUgeLhK7OK0FQt5/Q8DkeVHDPkNP1Zbinz
gqutO1x+NxQEbw9Jc9naeahSOXWHM/xD8O0dBBTi58zaBpbK4Ku2e8xnDqJMQacf
I4bxNZxl9MEm4dZr1kvLVHLS7Mttq2SJd4UGCAm6wfZTXDSCmUJ/S743hkRnuQ86
b9VWcv9fj1rdS8uutWC5fSqzM3AmEIg8gmrt5ZQKZxkAO6Uz9xbSMsCSzeDV3GhC
G50+veQ1GKK9mDL+coB1l4xpqVlGHYdllyfbtKALoGQcTztukNQgyOgg9nGOhawb
9L7KzyODD8u6SY+/hTgx/M9kkIlH8LQOAwIDAQABo1MwUTAdBgNVHQ4EFgQUhl13
43LzmDgL8EWs9/W088L7Fp0wHwYDVR0jBBgwFoAUhl1343LzmDgL8EWs9/W088L7
Fp0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAcx1qoFmPWcOX
GHroTTGgu3SWodtfTEMvsvf+p95P6Yuteua7SjgK8ymNkskQr53yZV7eZ3FI3feF
Us9/71bhC+EuLIzNMIAs4gbTYJz3P9m6XRkolIcLSgtq6apZczpBgolchgj8e6RD
pt7K1i74TKQOCe+rE5B38nFsJTUuzqWobV1K7VXszoMN9bCPZg4ed/Zrp3t2DeYu
gEk9XwGllh+fRQj08t8VrNENrRHYJvG228VpVLMvoKF8/ZsFrtLNQnuWkdTAnkYt
ah8rDEv5bUiWiTx8o9//XZ2UctkeKgSbqKv+dql6mPbdMNZNGxPT/zUKFq+zzAeW
MJu7Zy8BR/9WZj49ye27nXHsZ9IS7d8A2W9jQIK1H2Vgtekilp5lHZXOQNYoJhi5
4fndG0S4LGLGTcPj9nFDB8HpTfWNbS09cx7mK06kN8XdH1Mn64xDrEyibeBU75dV
T4VVvI58HvLp9Z6tMjSmZTxantjCI9djfevnNp9s3P20oe5veDEo67Cmz7xhhC41
TGKODRzkBrm11dNx/51tCRUSfw08mwlOBHZA3TAsfmXgtyAPLWpoGi0nl7o+fMyf
3ZytEJ+/PKDTwPrUdyb/Gitg5zC1xxwAyYPszmijW68iBB1UqJXDm/uRm488/U9n
z2PtWkpdpzknAt8S0vBNV+clk6pZOfU=
-----END CERTIFICATE-----
)CERT";

// Create a list of certificates with the server certificate
X509List cert(IRG_Root_X1);

String serverURL = "https://192.168.1.79:5000/a=455&b=-73";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // Set time via NTP, as required for x.509 validation
  configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

  Serial.print("Waiting for NTP time sync: ");
  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("Current time: ");
  Serial.print(asctime(&timeinfo));
}

void loop() {
  // Example usage of sendHttpRequest function
  sendHttpRequest(serverURL);

  delay(5000);  // Wait for 5 seconds before making the next request
}

void sendHttpRequest(String url) {
  client.setTrustAnchors(&cert);
  //client.setInsecure();

  HTTPClient https;

  Serial.println("URL: " + url);

  // Make a GET request
  https.begin(client, url);
  int httpCode = https.GET();

  if (httpCode > 0) {
    if (httpCode == HTTP_CODE_OK) {
      String payload = https.getString();
      Serial.println("Http request Response:");
      Serial.println(payload);
    }
  } else {
    Serial.printf("[HTTP] GET request failed, error: %s\n", https.errorToString(httpCode).c_str());
  }

  https.end(); // Close connection
}

I got error: "[HTTP] GET request failed, error: connection failed".

What could be the problem?

Thanks

Have tou tried adding the private key (version without a password) and the certificate to the data folder inside the sketch folder then run the data uploader tool (Tools -> ESP8266 LittleFS Data Upload) to install the certificates on the 8266 filesystem ?

When creating the certificate with openssl I did not specify password, I used all default.
No, how to use LittleFS and do I have to use it?
I added my keys on data folder then I see Tools > Upload SSL Root Certificates, but noting to upload.
Screenshot

do you have .pem files ? (I've never tried it)

this might help

Yes I have .pem files.
For LittleFS I find out it's not compatible with my Arduino IDE 2.x, if no choice i may test later with lower version.

I tryed the link provided but got error on:

openssl req -new -sha256 -x509 -days 3560 -subj "/C=GB/ST=DOR/L=Bournemouth/O=z53u40/OU=z53u40 Corporate/CN=z53u40 Root CA" -extensions v3_ca -set_serial 1 -passin pass:password123 -key rootCA_key.pem -out rootCA_certificate.pem -config ext.cfg
Can't open "ext.cfg" for reading, No such file or directory
40D75FDA467F0000:error:80000002:system library:BIO_new_file:No such file or directory:../crypto/bio/bss_file.c:67:calling fopen(ext.cfg, r)
40D75FDA467F0000:error:10000080:BIO routines:BIO_new_file:no such file:../crypto/bio/bss_file.c:75:

one of the reason I'm still using 1.x and not 2.x is the missing tools

Yes that's what i should do.
But I put the certificate on the script file like I did (for testing), things should works same right? in this context it seems LittleFS has only one purpose here, and that's to fetch the certificate file.

Try uncommenting the client.setInsecure(); line in your code and see if it resolves the issue. It means you’re not validating the server’s certificate.

I've got it!
The problem lies in the certificate itself: I only entered the country, state and city, and the other fields were entered by pressing entree.
But in fact, the "Common Name" field should correspond to the IP/domain name of your server, so in short :

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
...
Common Name (e.g. server FQDN or YOUR name) []:192.168.1.79

Glad you solved it

1 Like

Hi,

In my case I have the certificates in .der format and I need my esp8266 to expose endpoints, I am doing it but I would like to encrypt everything with ssl, is it possible to do it with this example shown here ?