// ref: https://techtutorialsx.com/2018/01/25/esp32-arduino-applying-the-hmac-sha-256-mechanism/
// HMAC: Hash based Message Authentication Code
// HMAC use the SHA-256 function --> 32 bytes HMAC code
// The sender generate HMAC code --> send it with the message
// ---> The recipient calculate the HMAC from the message to verify (matched or not?)
// This case Using `shared key`
// key length --> cryptographic strength of the HMAC
/* HMAC uses:
+ shared key;
+ for authentication;
+ for check the integrity of the message
*/
/* Useful links:
- https://cpp4arduino.com/2018/11/21/eight-tips-to-use-the-string-class-efficiently.html
*/
/*
Note:
- Tách xác nhận chữ ký số thành hàm tiện ích (rsa_pki.h)
- ... đầu vào: con trỏ chữ ký, con trỏ khóa PK, con trỏ tới dữ liệu
- ... Sử dụng function overloading (dựa trên function signature)
- Dự án khác: sử dụng semver.c --> so sánh ver trong thông điệp với version hiện tại của config, firmware ...
- Main program: tải file config (size <= 2048) lưu vào mảng động/tĩnh
- Kiểm tra chữ ký số (tải file pub.key)
- (version OK & sign OK) ==> Next steps: Cập nhận firmware; Cập nhật thông số cấu hình thiết bị (device config) vào NVS ;
...
*/
#include "rsa_pub_key.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include "rsa_pki.h"
#include "http_utilities.h"
namespace
{
constexpr const char* ssid = "Wokwi-GUEST";
constexpr const char* password = "";
constexpr const char* data_url = "https://github.com/tuan-karma/fota_firmware_test/raw/main/config.json";
constexpr const char* sign_url = "https://github.com/tuan-karma/fota_firmware_test/raw/main/config.sign";
}
inline void setup_wifi()
{
WiFi.begin(ssid, password, 6); // channel 6 --> ~4s faster scanning
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("OK! IP=");
Serial.println(WiFi.localIP());
}
inline void get_sign(String& sign_buffer) {
HTTPClient http;
int contentLength = HTTP::get_length(http, sign_url);
if (contentLength == 512) {
sign_buffer = http.getString();
}
else {
Serial.printf("Error with HTTP %d\n", -contentLength);
}
http.end();
}
void setup() {
Serial.begin(115200);
setup_wifi();
String signature;
signature.reserve(512);
get_sign(signature);
bool result = false;
{ // GET data stream --> verify the signature
HTTPClient http;
int contentLength = HTTP::get_length(http, data_url);
if (contentLength > 0) {
RSA_PKI rsa(rsa_pub_key, sizeof(rsa_pub_key));
result = rsa.verify_signature(http.getString(), signature);
}
else {
Serial.printf("Error with HTTP %d\n", -contentLength);
}
http.end();
}
Serial.println(result ? "Signature verified!" : "Signature verification was failed");
}
void loop() {
// put your main code here, to run repeatedly:
delay(10); // this speeds up the simulation
}