Background information:

I am not a computer scientist. However, in a research project I am currently building a ESP32-based sensor. Multiple sensors of this type are going to be used by multiple users.

Every time a user wants to utilize a sensor, the sensor needs to get the WiFi credentials of this specific user so that the ESP32 can connect to the WiFi (for publishing the sensor data in a dashboard). In order to deliver these WiFi credentials, the ESP32 will be set up as a WiFi access point (AP) during configuration phase. Each user shall be able to use his/her smartphone to connect to the ESP, which runs a small HTTP server and delivers a login form to the user's smartphone. After entering the credentials, they are sent via HTTP to the ESP32, which then can use this to login to the WiFi of my institute. Obviously, transferring the WiFi credentials via HTTP is not safe and, thus, they need to be encrypted.

Although it would be possible with a few workarounds, I don't want to use HTTPS for the communication between smartphone and ESP32, since it seems to involve a lot of implementation inconveniences. I also don't want to use a separate smartphone app, but want to stay with the browser-based approach, if possible.

The idea:

I found the following blog post which demonstrate how one can achieve a Curve25519-based Diffie-Hellman (DH) key exchange between a Node-JS Server and an ESP8266. Additionally, I stumbled across WebCrypto yesterday. This led me to the following idea:

My ESP32 might deliver a WebCrypto code together with the login form, which it sends to the user's smartphone. Since WebCrypto seems to be supported by most of the modern smartphone browsers, the smartphone could locally generate a key pair via WebCrypto. The ESP32 could generate it's own key pair via the Crypto library mentioned in the link. Then both devices can do a Diffie-Hellman key exchange, the smartphone can encrypt the WiFi password, sent it to the ESP32, which can then decrypt it and use it.


I have absolutely no experience with encryption, coding Diffie-Hellman key exchange, or using WebCrypto. Obviously, there is a lot that can be implemented in a wrong way and cause a false security feeling. Furthermore, WebCrypto seems to have no implementation of Curve25519. Therefore, I have a few questions:

  1. Is there a simpler approach to achieve a secure WiFi credential transfer from the smartphone to the ESP32?

  2. Is the proposed idea realistic and safe?

  3. What are the biggest security pitfalls which I need to consider during implementation of this idea?

  4. If you have experience with WebCrypto, what alternatives to the Curve25519 key generation would be the best?

  5. At the end of the aforementioned link, the author mentioned that ensuring device identity is a problem which is not solved in their example. What does that mean?

  • The Web Crypto API does not support EC Curve25519. However, EC P256 is supported, which is probably fine for your application. Notwithstanding, WRT, "I don't want to use HTTPS for the communication between smartphone and ESP32, since it seems to involve a lot of implementation inconveniences" - I think what you are trying to do is going to involve a lot more implementation inconveniences. HTTPS is designed specifically for what you are trying to do (transfer information securely between a client and a server, with secrecy, integrity and authentication). Why reinvent the wheel?
    – mti2935
    Apr 18, 2021 at 14:47
  • Thanks for the hint to EC P256, I will look it up! The problem with HTTPS is all the handling of the certificates on a local area network without internet access (i.e., the connection between smartphone and ESP32). While it is possible to do that, handling and keeping the certificates up to date on multiple sensors manually seems a bit too time-consuming. A flexible key generation may take some time during implementation, but then I don't need to touch the system again.
    – reg.cs
    Apr 18, 2021 at 14:53
  • OP, i understand. But, you are going to have the same problem if you build this from scratch with the web crypto API, because your client must have some way to authenticate that the public key that it receives from the server is authentic. The client can not just accept the public key on blind faith, otherwise this opens the door to a man-in-the-middle (MITM) attack. This is why authenticity is important. See security.stackexchange.com/questions/248175/… for more info and possible solutions.
    – mti2935
    Apr 18, 2021 at 15:02
  • You might want to consider creating a self-signed certificate for the server, with a very long expiration date (e.g. 50 years), and pinning this certificate on the client. This way, you can use tried and true HTTPS (instead of reinventing the wheel), your client authenticates the server (as it should in any secure system) using the pinned cert, and you don't have to worry about updating certificates (until 2071).
    – mti2935
    Apr 18, 2021 at 15:06
  • Ok, that seems to be connected to question (3) and (5) of my post. I understand that my approach is lacking the authenticity. But if I use a self-signed certificate and ask the user to dismiss the browser warning popping up, how does that prevent a MITM attack? I mean, couldn't the MITM also deliver a self-signed certificate to the client without the user noticing it? Or worse ... since the sensor/ESP32 containing the certificate could fall into the hands of an attacker, couldn't one extract the certificate?
    – reg.cs
    Apr 18, 2021 at 15:20


You must log in to answer this question.

Browse other questions tagged .