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”.

Two columns labelled "Central" and "Peripheral". A dashed line near the top labelled "BLE connection open (unencrypted)". Below it, three arrows: "pairing request" from central to peripheral, "key exchange" both directions, "pairing complete" forward. A second dashed line below labelled "link encrypted". Two thick bidirectional arrows carry "encrypted GATT traffic". An optional "store keys to flash" box on the side, labelled "bonding".

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.