An ESP32 garage-door remote sends its commands as plain HTTP to a NodeJS server over open Wi-Fi. What has to change on the server, on the ESP32 and on a laptop client to protect the traffic end to end with TLS?
The server gets a private key and a certificate and serves HTTPS. Every client (the ESP32 firmware and the laptop's curl) gets a copy of that certificate as its trust anchor and refuses any server that cannot prove it holds the matching key.
* The certificate is public and goes to every client; the key never leaves the server. *
"End to end" means the protection runs from the device's program to the server's program, so nothing between them (the open Wi-Fi, the access point, anyone who has joined the network) can read or change the commands. The work, in order:
- Make an identity for the server.
opensslgenerates a key pair and a self-signed certificate that binds the public key to the server's address. - Server: load the key and the certificate and listen with TLS. In Node.js that is
https.createServer({ key, cert }, app)instead ofhttp.createServer(app). The routes, such asPOST /opengaragedoor, stay the same. - ESP32 client: embed the certificate in the firmware, switch the URL from
http://tohttps://, and hand the certificate to the HTTP client so it can verify the server. Then rebuild and flash, because the certificate is now part of the image. - Laptop client: tell curl to trust that same certificate:
curl --cacert garagedoor.cert -X POST https://<server>:8080/opengaragedoor. - Check with Wireshark that the captured packets now show a TLS handshake and encrypted records instead of readable HTTP.
Nothing about the buttons, the FreeRTOS tasks or the door logic changes. TLS sits between TCP and HTTP, so the application keeps sending the same requests and the library underneath encrypts them.
Go deeper:
Node.js — HTTPS —
https.createServer()with a key and certificate read from files.ESP-IDF — ESP HTTP Client — HTTPS requests from the ESP32 and the
cert_pemfield for verifying the server.