Description
Hey,
thanks so much for this library! I was wondering how you'd feel about adding a hash/signature check to the lib as another way to authenticate the new firmware image.
The way I'd see this could be implemented is through a public/private key + digest:
- Create public/private key pair
- public key gets delivered to ESP32 firmware
- Private key creates sha256 digest of the new firmware
- Digest could be placed into .json file (or just use first 512 bytes of the firmware.bin)
- OTA downloads the file, verifies if signature matches, then runs the update.
Only piece I don't know here: how can you make Update.h wait for the signature check after the download is complete?
First you'd create your key-pair:
openssl genrsa -out key.pem 4096
openssl rsa -in key.pem -pubout > key.pub
Creating the firmware.img with the embedded signature would be
# Create signature file
openssl dgst -sign key.pem -keyform PEM -sha256 -out firmware.sign -binary firmware.bin
# throw it all in one file
cat firmware.sign firmware.bin > firmware.img
Signature check on a Linux shell would look like this:
# Create signature file from image
dd if=firmware.img of=firmware.sign bs=512 count=1
# Create OTA update file from image
dd if=firmware.img of=firmware.bin bs=512 skip=1
# Verify signature
openssl dgst -verify key.pub -keyform PEM -sha256 -signature firmware.sign -binary firmware.bin
On the ESP32 this would require an additional library for the signature check, but with an embedded implementation of openssl this should be as simple as running rsa_verify() with the firmware file and the public key.
Embedding the signature into the image is not necessary but seems like it would keep things together (and if you implement the version check through HTTP headers it wouldn't make sense to add it to the .json file).
Finally to the reason I think this would be useful:
In a scenario where your webserver uses a Let's Encrypt certificate the cert would change every 3 months. So it's not a good idea to check the update file solely through the SSL certificate. Even if you use a paid cert, browsers are moving forward to shorter and shorter validity periods, currently 1 year is favoured, that might change in future.
With a pub/private key dedicated just to your specific firmware you will be independent of these constraints. You can even go as far as using a different key for each firmware-branch you deploy.