Cara Membuat Hash Data Sensor ESP32 dan Memverifikasinya

Bayangkan skenario ini: sebuah sensor suhu di lini produksi mencatat 72°C pada pukul 14.00, tapi tiga bulan kemudian ada pihak yang mengklaim angka aslinya adalah 68°C dan data di sistem sudah diubah. Tanpa bukti integritas yang kuat, sengketa semacam ini sulit diselesaikan — siapa pun dengan akses admin ke database secara teknis bisa saja mengubah angka historis. Artikel ini adalah panduan praktis membuat hash data sensor ESP32 dan memverifikasinya, sehingga manipulasi semacam ini bisa terdeteksi. Untuk pemahaman soal kenapa arsitektur ini dipisah menjadi off-chain dan on-chain, baca dulu arsitektur on-chain vs off-chain untuk IoT — artikel ini fokus ke implementasinya.
Kebutuhan dan Prasyarat
Untuk mengikuti panduan ini, Anda memerlukan board ESP32 (dengan Arduino core), sensor apa pun yang sudah bisa dibaca ESP32 (DHT22, BME280, atau sensor analog 4-20mA), broker MQTT (bisa memakai Mosquitto atau HiveMQ), dan Python 3 dengan library paho-mqtt di sisi backend untuk verifikasi. Panduan ini mengasumsikan Anda sudah familiar dengan dasar pemrograman ESP32 dan pengiriman data lewat MQTT — kalau belum, ada baiknya mempelajari itu dulu sebelum masuk ke bagian integritas data ini.
Konsep Format Kanonik
Sebelum masuk ke kode, ada satu konsep yang sering jadi penyebab kegagalan verifikasi paling umum: format kanonik. Hash dihitung dari representasi teks/byte tertentu dari data. Kalau ESP32 menghitung hash dari string "72.5,1699999999" tapi backend Python menghitung ulang dari "72.50,1699999999" (beda jumlah desimal) atau dari urutan field yang berbeda, hasil hash-nya akan berbeda meski nilainya “terlihat sama” bagi manusia. Solusinya: tetapkan satu format string yang persis sama di kedua sisi — termasuk jumlah desimal, urutan field, dan pemisah — dan dokumentasikan formatnya sebagai bagian dari kontrak data antara firmware dan backend.

Langkah 1: Menghitung SHA-256 di ESP32 dengan mbedTLS
ESP32 sudah menyertakan library mbedTLS yang mendukung SHA-256 secara native, jadi tidak perlu library tambahan:
#include <mbedtls/md.h>
String hitungSHA256(String input) {
byte hasil[32];
mbedtls_md_context_t ctx;
mbedtls_md_type_t tipe = MBEDTLS_MD_SHA256;
mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(tipe), 0);
mbedtls_md_starts(&ctx);
mbedtls_md_update(&ctx, (const unsigned char*)input.c_str(), input.length());
mbedtls_md_finish(&ctx, hasil);
mbedtls_md_free(&ctx);
String hashHex = "";
for (int i = 0; i < 32; i++) {
if (hasil[i] < 0x10) hashHex += "0";
hashHex += String(hasil[i], HEX);
}
return hashHex;
}Fungsi ini mengambil satu string input (data kanonik yang sudah diformat), menghitung hash SHA-256-nya, lalu mengembalikannya sebagai string hex 64 karakter. Sifat penting dari SHA-256 yang membuatnya berguna untuk kasus ini: perubahan sekecil apa pun pada input — bahkan satu karakter atau satu digit desimal — akan menghasilkan hash yang sama sekali berbeda, bukan hash yang “mirip”. Sifat ini disebut avalanche effect, dan itulah yang membuat hash bisa dipakai untuk mendeteksi perubahan data sekecil apa pun.
[GAMBAR: ilustrasi satu karakter berubah pada input, hash SHA-256 yang dihasilkan berubah total]
Langkah 2: Membentuk Payload dan Publish ke MQTT
Payload yang dikirim sebaiknya menyertakan data asli, timestamp, dan hash-nya sekaligus, supaya backend bisa langsung memverifikasi tanpa perlu tahu format kanonik secara terpisah:
void kirimData(float suhu, unsigned long timestamp) {
String dataKanonik = String(suhu, 2) + "," + String(timestamp);
String hash = hitungSHA256(dataKanonik);
String payload = "{\"suhu\":" + String(suhu, 2) +
",\"timestamp\":" + String(timestamp) +
",\"hash\":\"" + hash + "\"}";
mqttClient.publish("pabrik/sensor01/suhu", payload.c_str());
}[perlu verifikasi: versi Arduino core ESP32 dan hasil uji di board sebelum dipakai di produksi]
Langkah 3: Verifikasi di Backend Python
Backend menerima payload, menghitung ulang hash dari data kanonik yang sama persis, lalu membandingkannya dengan hash yang dikirim:
import hashlib
import json
def verifikasi_data(payload_json):
data = json.loads(payload_json)
suhu = data["suhu"]
timestamp = data["timestamp"]
hash_diterima = data["hash"]
data_kanonik = f"{suhu:.2f},{timestamp}"
hash_hitung_ulang = hashlib.sha256(data_kanonik.encode()).hexdigest()
if hash_hitung_ulang == hash_diterima:
return True, "Data valid, hash cocok"
else:
return False, "PERINGATAN: hash tidak cocok, data mungkin diubah"Perhatikan bahwa format string f"{suhu:.2f},{timestamp}" di Python ini harus persis sama dengan format String(suhu, 2) + "," + String(timestamp) di kode ESP32 — dua desimal, dipisah koma, tanpa spasi tambahan. Kalau ada perbedaan sekecil apa pun (misalnya satu sisi pakai titik koma, sisi lain pakai koma), verifikasi akan selalu gagal meski datanya sebenarnya identik. Inilah yang dimaksud dengan format kanonik yang dibahas di awal artikel.
Langkah 4: Merkle Root untuk Meringkas Ribuan Hash
Menyimpan setiap hash secara individual di blockchain tetap tidak efisien untuk volume data tinggi. Solusinya adalah menyusun banyak hash ke dalam satu Merkle tree, lalu hanya Merkle root-nya (satu nilai tunggal) yang dicatat secara periodik:
import hashlib
def hitung_merkle_root(daftar_hash):
if len(daftar_hash) == 1:
return daftar_hash[0]
hash_berikutnya = []
for i in range(0, len(daftar_hash), 2):
kiri = daftar_hash[i]
kanan = daftar_hash[i + 1] if i + 1 < len(daftar_hash) else kiri
gabungan = kiri + kanan
hash_berikutnya.append(hashlib.sha256(gabungan.encode()).hexdigest())
return hitung_merkle_root(hash_berikutnya)Cara kerjanya: hash-hash yang berpasangan digabung dan di-hash ulang bersama, berulang kali, sampai tersisa satu nilai tunggal. Kalau data pada salah satu dari ribuan pembacaan yang menyusun root ini diubah walau hanya satu, root yang dihitung ulang akan berbeda total dari root yang tercatat — sehingga perubahan tetap terdeteksi meski Anda tidak menyimpan setiap hash individual di blockchain.
[GAMBAR: diagram merkle tree â 4 hash individual digabung bertahap menjadi 1 root]
Langkah 5: Mencatat Root ke Blockchain
Setelah Merkle root dihitung untuk satu periode (misalnya satu jam), root itulah yang dicatat ke smart contract sebagai bukti integritas. Detail cara menulis dan memanggil smart contract untuk keperluan ini dibahas terpisah di smart contract untuk mencatat hash data sensor IoT.
Yang Perlu Diingat
- Hash bukan bukti sensor membaca dengan benar. Hash hanya membuktikan data tidak diubah setelah dicatat, bukan bahwa sensornya terkalibrasi atau pembacaannya akurat.
- Versioning format kanonik itu penting. Kalau suatu saat format datanya berubah (misalnya menambah field baru), sistem verifikasi lama harus tetap bisa memverifikasi data lama dengan format sebelumnya.
- Blockchain tidak berada di jalur kontrol. Fungsi kontrol, interlock, dan emergency stop tetap di PLC atau sistem safety yang sesuai standar.
- Smart contract tidak boleh menggerakkan aktuator secara langsung tanpa verifikasi dan interlock di sisi PLC/edge.
- Waktu konfirmasi transaksi tidak deterministik, sehingga tidak layak untuk keputusan real-time yang menyangkut keselamatan.
- Perubahan pada sistem produksi mengikuti prosedur manajemen perubahan dan izin pihak berwenang di fasilitas terkait.
Kesimpulan
Membuat hash data sensor di ESP32 dan memverifikasinya di backend adalah langkah paling dasar untuk membangun integritas data IoT yang bisa dipercaya. Kuncinya ada di format kanonik yang konsisten di kedua sisi, dan penggunaan Merkle root untuk meringkas ribuan hash sebelum dicatat ke blockchain secara periodik.
Baca Juga
- Blockchain untuk IoT: fungsi nyata, arsitektur, dan roadmap belajarnya — gambaran umum sebelum masuk ke detail teknis di artikel ini.
- Identitas digital perangkat IoT — lapisan pelengkap yang memastikan hash ini benar-benar berasal dari perangkat yang sah.
- Kirim data sensor dari ESP32 ke MQTT broker — dasar pengiriman data lewat MQTT kalau Anda belum familiar dengan alurnya.
Mau Langsung Praktik?
Materi seperti ini jauh lebih cepat masuk kalau langsung dipraktikkan ke hardware. bisaioti mengadakan training IoT secara online (Zoom) dan offline dengan porsi praktik langsung ke perangkat nyata.
[perlu data training: tema, tanggal & waktu, format online/offline, lokasi, kuota, link pendaftaran]




