11.13. Párosítás és kötés

Az eddig tárgyaltak mindegyike titkosítatlanul, nyílt formában mozgatja a bájtokat a rádión keresztül. Bárki, akinek BLE-képes laptopja van ugyanabban a helyiségben, hallgathatja a hirdetési csatornákat, követheti egy nyílt kapcsolat ugrási sorozatát, és kiolvashat minden olvasást, írást és értesítést, ami áthalad rajta. A legtöbb nyilvános érzékelőadat (akkumulátorszint, környezeti hőmérséklet) esetében ez rendben van. Bármi olyasmihez, amit a két végpont titokban szeretne tartani – egy vezérlőregiszter, amely élesít egy relét, egy jelszó, egy mérés, amelyet nem szabad széles körben sugározni –, a kapcsolatnak titkosítottnak kell lennie, és ideális esetben a kamerának tudnia kell, hogy kivel beszél.

A BLE mindkettőt biztosítja a párosítás és a kötés révén.

11.13.1. Párosítás, kötés, titkosítás

Három szorosan összefüggő fogalom:

  • A titkosítás a végső cél. Amint a kapcsolat titkosítva van, az adatcsatornákon minden csomag csak a két végpont számára fejthető meg; egy lehallgató csak zajt lát.

  • A párosítás az az eljárás, amelyet a két végpont lefuttat, hogy megállapodjon a kulcsokról, amelyeket a titkosítás használ. Ez egy egyszeri csere, amely közös kulcsanyagot hoz létre, amelyet a kapcsolati réteg a titkosítómotorjába illeszt.

  • A kötés az a döntés, hogy a kulcsokat a párosítás befejezése után megőrizze nem felejtő tárolóban, így a következő kapcsolat ugyanazon két eszköz között kihagyja a párosítást, és egyenesen a titkosításhoz lép.

Egyszerűen fogalmazva: a párosítás „mutatkozzatok be”; a kötés „jegyezzétek meg ezt a bemutatkozást”; a titkosítás „mostantól négyszemközt beszéljünk”.

Két oszlop "Central" és "Peripheral" felirattal. Egy szaggatott vonal felül "BLE connection open (unencrypted)" felirattal. Alatta három nyíl: "pairing request" a centraltól a peripheral felé, "key exchange" mindkét irányban, "pairing complete" előre. Egy második szaggatott vonal alatta "link encrypted" felirattal. Két vastag kétirányú nyíl szállítja az "encrypted GATT traffic" forgalmat. Egy opcionális "store keys to flash" doboz az oldalon, "bonding" felirattal.

A párosítási folyamat egy nyílt BLE-kapcsolat tetején. Amint a kulcscsere befejeződik, a kapcsolati réteg minden további csomagot titkosít. A kötés az a plusz lépés, amely a kulcsokat a flash memóriába írja.

11.13.2. LE Secure Connections

A BLE által használt modern kulcscsere az LE Secure Connections, amely az Elliptic Curve Diffie-Hellman algoritmusra épül. Mindkét fél generál egy ideiglenes kulcspárt, kicserélik a nyilvános feleket, és az eredményt a saját privát kulcsaikkal kombinálják, hogy ugyanahhoz a közös titokhoz jussanak – olyan titokhoz, amelyet egy lehallgató még a csere teljes feljegyzésével sem tud kiszámítani.

A régebbi LE Legacy módszer kevésbé biztonságos (egy lehallgató, aki a teljes cserét megszerzi, általában vissza tudja fejteni a kulcsot), és csak a régi perifériákkal való visszafelé kompatibilitás miatt létezik. Az aioble alapértelmezése a modern módszer (le_secure=True); tartsd meg.

11.13.3. Párosítás kezdeményezése

Egy central úgy párosít, hogy meghívja az aioble.DeviceConnection.pair() metódust egy már nyitott kapcsolaton:

async with await device.connect() as connection:
    await connection.pair(bond=True, le_secure=True, mitm=False)
    # ... GATT work, now over an encrypted link ...

Miután a pair visszatér, a kapcsolaton lévő encrypted, authenticated, bonded és key_size attribútumok tükrözik a megtárgyaltakat.

A négy leghasznosabb kulcsszó argumentum:

  • bond=True – elmenti a keletkező kulcsokat a flash memóriába, így a következő kapcsolat ugyanazon két eszköz között kihagyja a párosítási kézfogást. Alapértelmezés True.

  • le_secure=True – LE Secure Connections használata. Alapértelmezés True. Hagyd bekapcsolva.

  • mitm=False – hogy szükséges-e man-in-the-middle védelem. Ehhez egy sávon kívüli csatornára van szükség (egy numerikus kód, amelyet az egyik oldalon megjelenítenek és a másikon megerősítenek, egy begépelt jelszó, …), hogy a felhasználó ellenőrizhesse, a párosítási kézfogásban szereplő két eszköz valóban az, aminek gondolja őket. Alapértelmezése False (nincs MITM-védelem – egy passzív lehallgató nem tudja olvasni a kapcsolatot, de egy támadó, aki aktívan átirányítja a kapcsolatokat, be tudná párosítani magát). Bármi érzékenyhez állítsd True értékre, de vedd figyelembe, hogy ehhez a perifériának ténylegesen támogatnia kell egy IO-képességet.

  • io=3 – az IO-képesség, amelyet az eszköz bejelent. A Bluetooth-specifikáció ötöt definiál: 0 csak kijelző, 1 kijelző + igen/nem, 2 csak billentyűzet, 3 se bemenet se kimenet, 4 billentyűzet + kijelző. Egy felhasználói felület nélküli kamera általában 3 értéket jelent; ha magának a kamerának van kijelzője, az alkalmazás megjeleníthetné a numerikus megerősítést és használhatná az 1 értéket. A két oldal IO-képességeinek kombinációja dönti el, hogy elérhető-e valódi MITM-védelem.

A perifériák maguk nem hívják meg a pair metódust – arra reagálnak, amit a central kezdeményez. Hogy egy adott karakterisztikához szükséges-e titkosítás, az annak a GATT-adatbázisban való deklarálási módjának a tulajdonsága; a titkosítást igénylő hozzáférési bitek az alacsony szintű bluetooth API részei, és jelenleg nincsenek elérhetővé téve az aioble karakterisztika-konstruktoron keresztül.

11.13.4. Kötés – és hol élnek a kulcsok

Amikor bond=True, az aioble a kulcsokat egy JSON-fájlba írja a helyi fájlrendszeren. Az alapértelmezett fájlnév a ble_secrets.json, amelyet az aktuális munkakönyvtárhoz képest ír ki. Egy frissen elindított kamerán a _boot.py már kiválasztotta ezt a könyvtárat: /sdcard, ha kártya van csatlakoztatva, egyébként /flash – így a fájl a /sdcard/ble_secrets.json vagy a /flash/ble_secrets.json helyre kerül. A fájl tartalmazza azokat a bejegyzéseket, amelyek a kapcsolat újratitkosításához szükségesek, amikor a kötött társ legközelebb újracsatlakozik, beleértve a társ identitáscímét is.

Egy aszimmetriát érdemes szem előtt tartani: a mentés automatikusan megtörténik a kulcsok változásakor, de a fájl betöltése a következő indításkor nem. Hívd meg az aioble.security.load_secrets() függvényt egyszer az indításkor (bármilyen párosítás vagy hirdetés előtt), hogy a korábban kötött társakat felismerje:

import aioble
aioble.security.load_secrets()        # default path: ble_secrets.json

Ezután, amikor egy kötött társ legközelebb megjelenik, az aioble újrahasznosítja a tárolt kulcsokat, és a kapcsolat további kézfogás nélkül titkosítottá válik.

A kulcsok flash memórián való tárolásának két gyakorlati következménye:

  • Egy eszköz elfelejtése. Töröld a ble_secrets.json fájlt (vagy távolítsd el a megfelelő bejegyzést) az összes kötött társ elfelejtéséhez, majd párosíts újra a nulláról.

  • A fizikai hozzáférés kiszivárogtatja a kulcsokat. Bárki, aki hozzáfér a kamera fájlrendszeréhez, el tudja olvasni a JSON-t. Ez ugyanaz a fajta korlát, amely a hálózati oldalon a TLS-kulcsoknál merült fel (Üzemeltetés: kulcsok, lejárat és hibaelhárítás): használj eszközönkénti kulcsokat, kezelj minden tárolt kulcsot helyreállíthatóként, és a visszavonás képességére támaszkodj (itt a kötés eltávolítására a central oldalon), nem pedig arra, hogy a kulcs titokban marad.

11.13.5. Mit garantál a titkosítás – és mit nem

Egy párosítás-majd-titkosítás kapcsolat erősség szerinti sorrendben a következőket adja:

  • Bizalmasság. Mindig. Egy lehallgató nem tudja elolvasni a bájtokat.

  • Integritás. Mindig. A módosított csomagok megbuknak a kapcsolati réteg hitelesített-titkosítás ellenőrzésén, és eldobódnak.

  • Hitelesítés. Csak mitm=True és egy alkalmas IO esetén. Enélkül egy man-in-the-middle, amely elfogta az eredeti párosítási cserét, beilleszthette volna magát; MITM-védelem nélkül a két oldal nem tudhatja meg.

A legtöbb kamerahasználati esethez – egy telefon, amely egyszer párosodik a kamerával, majd később újra csatlakozik – a mitm=False általában elegendő, mert az eredeti párosítás kontrollált környezetben történik (a felhasználó mindkét eszközt ugyanabban a helyiségben tartja). Olyan alkalmazásoknál, ahol egy párosított eszköz először nagy távolságon vagy egy nem megbízható közvetítőn keresztül találkozhat a kamerával, a MITM a helyes beállítás.

11.13.6. Amikor a párosítás a rossz válasz

A párosításnak valós ára van: néhány másodperc csere az első csatlakozáskor, tartós flash-használat minden kötött eszköznél, és a „felejtsd el a kötést” helyreállítási történet, ha valami balul sül el. A valóban nyilvános adatokhoz – jelzőfényként közzétett környezeti érzékelőértékek, egy nevét megjelenítő tábla, bármi, ami nem változtatja meg a világot azzal, hogy elolvassák vagy beleírnak –, a helyes válasz az, hogy egyáltalán ne titkosítsuk, és hagyjuk, hogy bármely közeli szkenner elolvassa az értékeket.

Minden máshoz a central oldali connection.pair(bond=True) az az egysoros kiegészítés, amely a kapcsolatot nyilvános csatornából priváttá alakítja.