## Secrets v IoT #### ako bezpečne ukladať heslá na mikrokontroléroch [Mirek Biňas](https://bletvaska.github.io) / [**OSS Conf Žilina 2026**](https://ossconf.fri.uniza.sk/)
> The _S_ in _IoT_ Stands for Security. notes: - neda mi nezacat inac, ako standardnym vtipom na tuto temu a sice, ze oblast bezpecnosti v IoT je stale velmi problematicka
## Čo sú to Secrets?
## Secrets * **citlivé údaje**, ktoré **umožňujú prístup** k systémom, službám alebo dátam * **musia byť bezpečne uložené a chránené pred neoprávneným prístupom** * napr.: heslá, API kľúče, tokeny alebo certifikáty
[![](images/owasp.iot.top.ten.png)](https://wiki.owasp.org/index.php/OWASP_Internet_of_Things_Project#tab=IoT_Top_10) notes: * jednym z jej projektov je vsak aj OWASP IoT Top 10 * zoznam 10 najvacsich hrozieb v oblasti IoT
### #1 Weak, guessable or hard coded passwords
> Use of easily bruteforced, publicly available, or unchangeable credentials, including backdoors in firmware or client software that grants unauthorized access to deployed systems.
![](images/students-js1.jpg) notes: * staticka (hardcoded passwords) konfiguracia pre mqtt pripojenie * TUYA like - posiela to na cinske servery
![](images/students-js2.jpg) notes: * to iste, len zapisane inac * co sa stane, ak dojde k vyzradeniu loginu a hesla a admini prijmu strasne rozhodnutie, ze credentials zmenia?
![](images/students-python1.jpg) notes: * to iste, ale pre zmenu v pythone
![](images/students-python2.jpg) notes: * opat defaults pre mqtt a databazu
![](images/students-python3.jpg)
![](images/students-python4.jpg)
## Ďalšie zdroje * tutoriály - [Random Nerd Tutorials](https://randomnerdtutorials.com/micropython-mqtt-esp32-esp8266/) * knihy * čo na to AI?
## Kde do $I&^% je problém?
## Secrets sú súčasťou kódu! * hodnoty sú uložené v (globálnych) premenných * nedajú sa zmeniť bez zmeny kódu * sú čitateľné * nie sú šifrované
## Čo s tým?
1. **Izolácia** Secrets uložíme do samostatného súboru. 2. **Šifrovanie** Zašifrujeme uložené údaje, aby boli čitateľné iba s kľúčom. 3. **Binárny bytecode** Kód pracujúci so secrets preložíme do binárneho bytecode, čím sťažíme jeho analýzu. notes: * Preklad do .mpy (MicroPython bytecode) sťažuje analýzu zdrojového kódu, ale nie je to bezpečnostný mechanizmus porovnateľný so šifrovaním. Skôr ide o obfuskáciu alebo sťaženie reverzného inžinierstva.
## Krok 1. Izolácia * secrets uložíme do samostatného súboru * použijeme formát, ktorý umožňuje jednoduché čítanie aj zápis * vystačíme si s formátom JSON * priama podpora v jazyku MicroPython * umožňuje vnáranie * výhodné je použiť dataclass pre validáciu * `/data/settings.json`
```python import json SETTINGS_FILE = '/data/settings.py' # content of settings settings = { "ssid": "OSS Conf 2026", "password": "Linux.Rocks!", } # write settings with open(SETTINGS_FILE, 'w') as file: json.dump(settings, file) # read settings with open(SETTINGS_FILE, 'r') as file: settings = json.load(file) ```
![Encoding vs Hashing vs Encryption](images/encoding.vs.hashing.vs.encryption.png) notes: * https://devcookies.medium.com/encoding-vs-hashing-vs-encryption-explained-with-examples-d92b423a4584 * este predtym ako sa posunieme ku kroku 2 mi neda jedno kratke pedagogicko-terminologicke okienko * encoding - kódovanie * hashing - hašovanie * encryption - šifrovanie
## Krok 2. Šifrovanie * problém MCU pri šifrovaní - obmedzené zdroje mikrokontrolérov * výpočtový výkon * malá pamäť * spotreba energie * bezpečné ukladanie údajov (TrustZone) * odolnosť voči fyzickým útokom * generovanie náhodných čísiel
[![ATECC 608](images/atecc.608.jpg)](https://www.adafruit.com/product/4314) notes: * mozeme si pomoct napr. tak, ze k nasmu rieseniu pridame externý šifrovací koprocesor (crypto-koprocesor), ako napr ATECC608 * kľúč tak nikdy neopustí čip
[`cryptolib`](https://docs.micropython.org/en/latest/library/cryptolib.html)
## AES Advanced Encryption Standard * **symetrická bloková šifra** * pracuje s blokmi o dĺžke 128 bitov / 16 bytov * podporuje kľúče s dĺžkou 128, 192 alebo 256 bitov
![](images/aes.webp) notes: - https://nordlayer.com/blog/aes-encryption/
### Get Ready! ```python # inštancia šifry AES >>> import cryptolib # konštruktor AES šifry potrebuje: # kľúč (16/24/32 bytov) >>> key = 'SuperTajnyKluc!!' # inicializačný vektor (vždy 16 bytov) >>> iv = '1234567890123456' # vytvorenie objektu šifry >>> cipher = cryptolib.aes(key, 2, iv) # mode 2 = CBC ```
### Šifrovanie textu ```python # majme nasledujúci text # dĺžka musí byť násobkom 16 (PKCS#7 padding) >>> text = 'Hello, Pico 2 W!' # zašifrovanie textu >>> encrypted = cipher.encrypt(text) # výsledok bude zašifrovaný >>> print(encrypted) b'\xa4`\xa1\xd1(w\xe3\xe2\x13\xb4\xc8$\x04\xac\xbf\xe0' ```
### Dešifrovanie textu ```python # pre dešifrovanie potrebujeme opäť vytvoriť objekt šifry # (zmenil sa vnútorný stav a zmenil sa iv) >>> cipher = cryptolib.aes(key, 2, iv) # dešifrujeme >>> decrypted = cipher.decrypt(bytearray(encrypted)) # výsledok je ako pole bytov >>> decrypted b'Hello, Pico 2 W!' # spravíme z toho reťazec >>> decrypted.decode('utf8') 'Hello, Pico 2 W!' ```
> A cryptosystem should be secure, even if everything about the system, **except the key**, is public knowledge. > > -- [Auguste Kerckhoffs](https://en.wikipedia.org/wiki/Kerckhoffs%27s_principle) ![Auguste Kerckhoffs](images/kerckhoffs.jpg)
### Kľúčový problém - ako zabezpečíme kľúč?
## Krok 3. Binárny bytecode * kľúč zostavíme ako kompozíciu z: * `salt` - náhodne vygenerované pole bytov, ktoré budú viazané na inštaláciu * `unique_id` - viazané na hardvér * na šifrovanie/dešifrovanie vytvoríme vlastný modul `crypto.py` * preložíme ho - vznikne binárny bytecode
### Vytvorenie salt ```python import os SALT_FILE = '/data/.salt' def create_salt(salt_path: str) -> None: with open(salt_path, 'wb') as file: file.write(os.urandom(16)) ```
### Vytvorenie kľúča ```python import machine import hashlib def create_key(salt_path: str = SALT_FILE) -> bytes: with open(salt_path, 'rb') as file: salt = file.read() hasher = hashlib.sha256() # adding data to hash hasher.update(machine.unique_id()) hasher.update(salt) # return hash return hasher.digest()[:16] # AES-128 ```
### Funkcia na šifrovanie ```python import cryptolib import binascii def encrypt(plaintext: str, salt_path: str = SALT_FILE) -> str | None: if plaintext is None: return None key = create_key(salt_path) iv = os.urandom(16) data = plaintext.encode('utf-8') pad = 16 - (len(data) % 16) data = bytearray(data + bytes([pad] * pad)) cipher = cryptolib.aes(key, 2, iv) encrypted = cipher.encrypt(data) return binascii.hexlify( bytearray(iv) + bytearray(encrypted) ).decode('ascii') ```
### Funkcia na dešifrovanie ```python def decrypt(ciphertext: str, salt_path: str = SALT_FILE) -> str | None: if ciphertext is None: return None key = create_key(salt_path) raw = binascii.unhexlify(ciphertext) iv = raw[:16] data = bytearray(raw[16:]) cipher = cryptolib.aes(key, 2, iv) decrypted = cipher.decrypt(data) pad = decrypted[-1] return bytes(decrypted[:-pad]).decode('utf-8') ```
## [mpy-cross](https://gitlab.com/alelec/mpy_cross ) the micropython cross compiler utility
```bash # najprv nainštalujeme (venv) $ pip install mpy-cross # overíme verziu: (venv) $ mpy-cross --version MicroPython v1.27.0 on 2025-12-13; mpy-cross emitting mpy v6.3 # preložíme modul crypto.py (venv) $ mpy-cross crypto.py ```
## Otázky?
![qr code](https://api.qrserver.com/v1/create-qr-code/?data=https://bit.ly/4wnlBVO&size=300x300) (**https://bit.ly/4wnlBVO**)