frankcohen / EleksTubeIPSHack

Hacking the Elekstube IPS ESP32 TFT based clock
GNU General Public License v3.0
69 stars 22 forks source link

HTTPS service #6

Open frankcohen opened 3 years ago

frankcohen commented 3 years ago

I have in mind a new feature that uses the browser WebRTC API to capture a still images from a video stream from your mobile phone or laptop camera, then uploads it in JPG format to the clock's SPIFFS file system. Unfortunately, Chrome only allows this over an HTTPS connection.

I found ESP32 HTTPS Server by Frank Hessel fhessel, v1.0.0. It's just what is says it is. I am going to remove the ESP32 Webserver library and add Hessel's library. I'm not sure how I am going to handle the server-side certificates - one possibility is to self-generate a certificate on start-up.

This will also help to transmit form data - for example, Wifi passwords - securely.

frankcohen commented 3 years ago

So complete and total SSL noob here... I generated a public and root certificates using ESP32 HTTPS Server and OpenSSL on my Macbook Pro. And I am able to serve static content over HTTPS. Am I not supposed to commit these certificates to the repository? If so, how do I get them into the clock to be used by the HTTPS Server? -Frank

koshisan commented 3 years ago

A root certificate is a bit of an overkill here. SSL certificates do two things:

Firstly, they are used for encryption: Basically, every certificate has a public and a private part. The private part (gernerally called "key" is needed for actions like signing sub certificates or securing a server with a certificate. The public part (=certificate) is - well - exactly that: public. It's the part the client receives when connecting to a site with HTTPS. The client can use that certificate to encrypt information in a way that can only be decrypted with the private key - which is only known to the server. This way an encrypted session is established. The other thing certificates can do is to establish a trust chain. If a certificate is used to sign another (sub-) certificate, a client can check if the subcertificate was really signed by the certificate it claims - without requiring the private key. This check is also used to verify some additional information encoded in the certificate like the name of the server it is meant to secure, some validity dates and other stuff. Note that the client has no means to check if that information is really correct/trustworthy - it can only check if it is unaltered from what was originally encoded when it was signed. So if you can trust a certificate depends on if you can trust its root certificate. To make SSL certificates usable over the internet in a meaningful way some companies have established a trusted public key infrastructure. On one hand there are some Certificate Authorities like DigiCert, etc. which are selling signed certificates for money. They have established various processes to check if the information supplied to them is really legit. On the other hand there are Operating System/Browser manufactures, who include the root certificates of those CAs in their software and mark them as trusted by default. That is the reason why you can browser to https://www.google.com without issue, while other, smaller websites often display the warning that the connection is not trusted, because the certificate isn't. The security layer is exactly the same - it's your computer manufacturer who decided to trust one CA and not trust the other one.

So - thats the theory. What does this mean for small DIY projects? Well - unfortunately it is impossible to establish a "trusted" connection to such a device. Not only because you would need to pay money to an "official" CA for a certificate (and update it every year) but also because you cannot provide any information that could be encoded in the certificate to tie it to - most commonly a FQDN - because it will be different for every user. However - this is not a problem at all, since we basically only want encryption, not trust. In this case what you normally do is generate only one certificate (not a chain with a root and a sub one) - this is often called "self-signed". Since it is baked into the firmware and cannot be updated, it needs to have a validity in years that exeeds the suspected life-span of the device. Ideally, the private key still needs to be protected, since an attacker with access to the key could fake the clock server - but that of course would mean that evey person who wants to compile the project would have to generate their own certificate and embedd it into the source code... From my perspective just including a self-signed certificate and make it easily changeable should be enough for starters.

You already found Frank Hessel's library, which seems to be the easiest approach.

I believe Mac OS does include OpenSSL, so basically a single openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 10950 should be all you need...

frankcohen commented 3 years ago

Thank you for the complete explanation of SSL and security keys. I finished making the changes to use Hessel's library and it works. Chrome gives me access to the WebRTC APIs. My code creates self-signed certificates at setup. The only downside I see is it slows the setup time - it can take up to a minute to generate the certificates. I need to see how to generate the self-signed certs once at compile time and reuse them.