{"id":16241649,"url":"https://github.com/tve/esp32-secure-base","last_synced_at":"2025-08-09T13:04:52.608Z","repository":{"id":56020015,"uuid":"182324654","full_name":"tve/esp32-secure-base","owner":"tve","description":"Base project for the esp32 focused on security using MQTTS","archived":false,"fork":false,"pushed_at":"2020-11-30T21:03:56.000Z","size":58,"stargazers_count":7,"open_issues_count":2,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-03T04:51:12.894Z","etag":null,"topics":["esp32","esp32-arduino","mqtt","mqtts","ota-update"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tve.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-19T20:55:19.000Z","updated_at":"2023-09-11T07:53:04.000Z","dependencies_parsed_at":"2022-08-15T11:31:24.585Z","dependency_job_id":null,"html_url":"https://github.com/tve/esp32-secure-base","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tve/esp32-secure-base","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tve%2Fesp32-secure-base","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tve%2Fesp32-secure-base/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tve%2Fesp32-secure-base/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tve%2Fesp32-secure-base/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tve","download_url":"https://codeload.github.com/tve/esp32-secure-base/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tve%2Fesp32-secure-base/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269579976,"owners_count":24441444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-09T02:00:10.424Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["esp32","esp32-arduino","mqtt","mqtts","ota-update"],"created_at":"2024-10-10T14:08:13.918Z","updated_at":"2025-08-09T13:04:52.557Z","avatar_url":"https://github.com/tve.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"ESP32 Base Project with Secure MQTT and OTA\n===========================================\n\n__WARNING__: this project is still work-in-progress, see the open issues\n\nThis project contains a relatively simple Arduino base firmware for the ESP32 that is\ncentered around MQTT and that attempts to be reasonably secure.\nIt almost exclusively uses MQTTS (MQTT over TLS) for communication.\nOTA updates are triggered over MQTTS but download the\nfirmware using HTTP and then check the MD5 checksum to ensure no tampering occurred\n(but this does expose the firmware in the clear).\nInitial configuration is done using ESPAsyncWiFiManager, i.e., by running an access point and a web\nserver.\n\nDisclaimer: I hesitated to call this firmware \"secure\" because I'm sure it can be hacked.\nAlso, the initial configuration is not as bullet proof as I wish it were, it just gets painful real\nquick.\nThe firmware also hasn't been put under serious scrutiny (and there are open issues, see below).\nSo... why bother?\nThe goal here is to start with something reasonable as opposed to defaulting to wide-open\ninsecure unencrypted stuff.\nThat being said, if you see a flaw, I'd love to hear about it (kindly) and I'd love even\nmore to merge a fix!\n\nFeatures\n--------\n\n- Initial configuration via web server over WiFi AP, includes configuration of MQTT server\n  and authentication (PSK)\n- Asynchronous MQTT client supporting QoS 0-2 and supporting PSK TLS cipher suites\n  (https://github.com/tve/async-mqtt-client)\n- OTA triggered by MQTT message, pulls firmware using HTTP and checks it using MD5\n  (uses https://github.com/tve/AsyncTCP)\n\nOpen issues\n-----------\n\n- The initial configuration is not as secure as I'd like it to be: the AP is open and the web server\n  is on HTTP (unencrypted). I'd like to move to a secured AP with a default passwordi (which can be\n  changed in the first config run). Using the default password the communication can still be\n  cracked but the hurdle is much higher than currently.\n- The ESPAsyncWiFiManager does not seem to shut down the AP once Wifi is connected, this\n  should be forced.\n- The \"reconfiguration\" (i.e., starting up the AP even though the configured WiFi network can be\n  joined) is broken due to a bug in AsyncTCP.\n- I'd like to add a command line configuration so I don't need to mess with my laptop's WiFi to join\n  the AP and figure out how to cut\u0026paste the MQTT PSK.\n- This base project does not deal with the physical security of the esp32. The chip contains\n  features to encrypt the firmware and make it tamper-proof but this base project does not make any\n  use of that and it may not work with the Arduino framework anyhow.\n\nMQTT provisioning\n-------------------\n\nAt boot, if there is no config saved in flash an mqtt identity is generated (it is the same as the\nWifi access point SSID) and a random PSK is also generated. Both are stored in the new config and will\npersist, unless they're changed via the portal UI.\n\nThe idea is that the ident/psk can be entered into the MQTT server config, or custom ident/psk can\nbe generated and configured using the portal.\n\n### Example\n\nErasing the entire flash to get a clean slate starting point:\n```\nesptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset erase_flash\n```\nFlashing and running the secure base example:\n```\ncd examples/basic\npio run -e usb -t upload -t monitor\n```\nWhen it finally boots up, this is what happens:\n```\n===== ESP32 Secure Base Example =====\nE (55) SPIFFS: mount failed, -10025\n[E][SPIFFS.cpp:52] begin(): Mounting SPIFFS failed! Error: -1\n** Formatting fresh SPIFFS, takes ~20 seconds\nE (60) SPIFFS: mount failed, -10025\nFormat took 19s\nNo config file, initializing mqtt ident/psk\nMQTT ident=ESP-C44F330A9C35 psk=b9d4e59d1b55028d2d9ea49235dca5fa\n```\nThe psk is not printed on subsequence boots, so it's important to capture it here.\nAlternatively, it is available through the portal UI.\n\nWifi Observations\n-----------------\n\nThe esp32-arduino WiFi class contains a number of reconnect features:\n- By default the STA config is saved to flash (this can be disabled with `WiFi.persistent(false)`)\n- By default the STA reconnects automatically after a disconnect (this can be disabled with\n  `WiFi.autoConnect(false)`), this happens in `WiFiGenericClass::_eventCallback`.\n- Need to verify that once disconnected the firmware keeps scanning to try to reconnect. (__TODO__)\n\nThere are a couple of security issues that need to be considered when using the ESPAsyncWiFiManager:\n- The configuration portal must have a password otherwise an attacker can do a simple denial of\n  service attack on the AP, wait for the config portal to come up and then hack the system.\n  It's probably best to force setting the password using an extra parameter in the config.\n- The configuration portal should take some time to come up to make attacking the portal a tad\n  harder, this can be controlled using `setConnectTimeout`.\n\nThe use of the ESPAsyncWiFiManager class falls into two main use-cases: systems that are not useful\nwithout Wifi where configuration can be blocking and where failure is best dealt with by reset, and\nsystems that need to operate with or without Wifi where configuration should not be blocking and\nfailure should not cause a reset.\n\nSystems that cannot meaningfully operate without Wifi should:\n- Set an upper bound to the configuration portal using\n`ESPAsyncWiFiManager.setConfigurationPortalTimeout` and reset the system if no connection can be\nestablished. This ensures the system doesn't get stuck. A value of 5-10 minutes\nshould be a reasonable compromise between usability and ensuring that the system doesn't get stuck\nif unattended. If `ESPAsyncWiFiManager.autoConnect` returns false (not connected) then reset.\n\nSystems that must operate even without Wifi should turn on the STA using `WiFi.mode(WIFI_STA)` and\nthen check periodically whether a connection has been established. If not, use\n`ESPAsyncWiFiManager.setupConfigPortalModeless` to start the configuration portal.\nOnce connected, the portal should be shut down.\n\nAn alternative for systems that must operate even without Wifi is to use the blocking\n`autoConnect` with an acceptable `setConnectTimeout` and accept the fact that the system won't\noperate for a few minutes if the AP cannot be contacted after a reset.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftve%2Fesp32-secure-base","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftve%2Fesp32-secure-base","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftve%2Fesp32-secure-base/lists"}