11.13. Pairing dan bonding

Semua yang telah dibahas sejauh ini memindahkan byte melalui radio secara terbuka. Siapa pun yang memiliki laptop berkemampuan BLE di ruangan yang sama dapat mendengarkan pada saluran advertising, mengikuti urutan hopping dari koneksi terbuka, dan membaca setiap operasi read, write, dan notifikasi yang melintas. Untuk sebagian besar data sensor publik (tingkat baterai, suhu ambient) hal ini tidak menjadi masalah. Untuk hal-hal yang ingin dijaga kerahasiaannya oleh dua endpoint -- register kontrol yang mengaktifkan relay, kata sandi, pengukuran yang tidak boleh disebarluaskan -- link perlu dienkripsi, dan idealnya kamera perlu mengetahui dengan siapa ia berkomunikasi.

BLE menyediakan keduanya melalui pairing dan bonding.

11.13.1. Pairing, bonding, enkripsi

Tiga konsep yang saling berkaitan erat:

  • Enkripsi adalah tujuan utama. Setelah link dienkripsi, setiap paket pada saluran data hanya dapat diuraikan oleh dua endpoint; penyadap hanya melihat kebisingan.

  • Pairing adalah prosedur yang dijalankan dua endpoint untuk menyepakati kunci yang digunakan enkripsi. Ini adalah pertukaran satu kali yang menghasilkan materi kunci bersama yang dipasang oleh link layer ke dalam mesin enkripsinya.

  • Bonding adalah pilihan untuk menyimpan kunci ke penyimpanan non-volatile setelah pairing selesai, sehingga koneksi berikutnya antara dua perangkat yang sama melewati pairing dan langsung menuju enkripsi.

Dalam bahasa sederhana: pairing berarti "berkenalan"; bonding berarti "ingat perkenalan ini"; enkripsi berarti "berbicara secara pribadi mulai sekarang".

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

Alur pairing di atas koneksi BLE terbuka. Setelah pertukaran kunci selesai, link layer mengenkripsi setiap paket berikutnya. Bonding adalah langkah tambahan untuk menulis kunci ke flash.

11.13.2. LE Secure Connections

Pertukaran kunci modern yang digunakan oleh BLE adalah LE Secure Connections, yang dibangun di atas Elliptic Curve Diffie-Hellman. Kedua sisi menghasilkan pasangan kunci sementara, menukar separuh publik, dan menggabungkan hasilnya dengan kunci privat mereka sendiri untuk mencapai rahasia bersama yang sama -- rahasia yang tidak dapat dihitung oleh penyadap bahkan dengan rekaman lengkap pertukaran tersebut.

Metode LE Legacy yang lebih lama kurang aman (penyadap dengan pertukaran lengkap biasanya dapat memulihkan kunci) dan hanya ada untuk kompatibilitas mundur dengan periferal lama. Default aioble adalah metode modern (le_secure=True); pertahankan pengaturan ini.

11.13.3. Memulai pairing

Sebuah central melakukan pairing dengan memanggil aioble.DeviceConnection.pair() pada koneksi yang sudah terbuka:

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

Setelah pair mengembalikan nilai, atribut encrypted, authenticated, bonded, dan key_size pada koneksi mencerminkan apa yang telah dinegosiasikan.

Empat argumen kata kunci yang paling berguna:

  • bond=True -- simpan kunci hasil ke flash sehingga koneksi berikutnya antara dua perangkat yang sama melewati handshake pairing. Default True.

  • le_secure=True -- gunakan LE Secure Connections. Default True. Biarkan tetap aktif.

  • mitm=False -- apakah perlu mengharuskan perlindungan man-in-the-middle. Ini memerlukan saluran out-of-band (kode numerik yang ditampilkan di satu sisi dan dikonfirmasi di sisi lain, passkey yang diketikkan, ...) sehingga pengguna dapat memverifikasi bahwa dua perangkat dalam handshake pairing adalah perangkat yang mereka pikir. Defaultnya adalah False (tidak ada perlindungan MITM -- penyadap pasif tidak dapat membaca link, tetapi penyerang yang secara aktif mengalihkan koneksi dapat memasangkan diri mereka). Atur ke True untuk hal-hal yang sensitif, tetapi perlu diingat bahwa hal ini memerlukan periferal untuk benar-benar mendukung kemampuan IO.

  • io=3 -- kemampuan IO yang diklaim perangkat. Spesifikasi Bluetooth mendefinisikan lima: 0 hanya tampilan, 1 tampilan + ya/tidak, 2 hanya keyboard, 3 tanpa input tanpa output, 4 keyboard + tampilan. Kamera tanpa UI biasanya melaporkan 3; jika kamera sendiri memiliki layar, aplikasi dapat menampilkan konfirmasi numerik dan menggunakan 1. Kombinasi kemampuan IO kedua sisi menentukan apakah perlindungan MITM nyata dapat dicapai.

Periferal tidak memanggil pair sendiri -- mereka merespons apa pun yang diprakarsai oleh central. Apakah enkripsi diperlukan untuk karakteristik tertentu adalah properti dari bagaimana ia dideklarasikan dalam database GATT; bit akses yang memerlukan enkripsi adalah bagian dari API bluetooth tingkat rendah dan saat ini tidak diekspos melalui konstruktor karakteristik aioble.

11.13.4. Bonding -- dan di mana kunci disimpan

Ketika bond=True, aioble menulis kunci ke file JSON pada filesystem lokal. Nama file default adalah ble_secrets.json, ditulis relatif terhadap direktori kerja saat ini. Pada cam yang baru di-boot, _boot.py telah memilih direktori tersebut: /sdcard ketika kartu terpasang, /flash jika tidak -- sehingga file berada di /sdcard/ble_secrets.json atau /flash/ble_secrets.json. File ini menyimpan entri yang diperlukan untuk mengenkripsi ulang link saat peer yang telah di-bond menghubungkan kembali, termasuk alamat identitas peer.

Satu asimetri yang perlu diingat: penyimpanan terjadi secara otomatis seiring perubahan kunci, tetapi memuat file pada boot berikutnya tidak. Panggil aioble.security.load_secrets() sekali saat startup (sebelum pairing atau advertising apa pun) agar peer yang telah di-bond sebelumnya dikenali:

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

Setelah itu, saat peer yang telah di-bond berikutnya muncul, aioble menggunakan kembali kunci yang tersimpan dan link terenkripsi tanpa handshake lebih lanjut.

Dua konsekuensi praktis dari penyimpanan kunci di flash:

  • Melupakan perangkat. Hapus ble_secrets.json (atau hapus entri yang relevan) untuk melupakan semua peer yang di-bond, lalu lakukan pairing ulang dari awal.

  • Akses fisik membocorkan kunci. Siapa pun yang memiliki akses ke filesystem kamera dapat membaca JSON. Ini adalah jenis batasan yang sama yang muncul di sisi jaringan dengan kunci TLS (Operasi: kunci, kedaluwarsa, dan pemecahan masalah): gunakan kunci per-perangkat, anggap kunci yang tersimpan dapat dipulihkan, dan andalkan kemampuan untuk mencabut (di sini, menghapus bond di sisi central) daripada mengandalkan kunci yang tetap rahasia.

11.13.5. Apa yang dijamin enkripsi -- dan apa yang tidak

Link pair-lalu-enkripsi memberikan, berurutan dari yang paling kuat:

  • Kerahasiaan. Selalu. Penyadap tidak dapat membaca byte.

  • Integritas. Selalu. Paket yang dimodifikasi gagal dalam pemeriksaan authenticated-encryption di link layer dan dibuang.

  • Autentikasi. Hanya dengan mitm=True dan IO yang mampu. Tanpanya, man-in-the-middle yang mencegat pertukaran pairing asli bisa saja menyisipkan diri mereka; tanpa perlindungan MITM tidak ada cara bagi kedua sisi untuk mengetahuinya.

Untuk sebagian besar kasus penggunaan kamera -- ponsel yang melakukan pairing dengan kamera sekali, kemudian menghubungkan kembali nanti -- mitm=False biasanya sudah cukup, karena pairing asli terjadi di lingkungan yang terkontrol (pengguna memegang kedua perangkat di ruangan yang sama). Untuk aplikasi di mana perangkat yang dipasangkan mungkin pertama kali menemukan kamera dari jarak jauh atau melalui perantara yang tidak dipercaya, MITM adalah pengaturan yang tepat.

11.13.6. Kapan pairing bukan jawaban yang tepat

Pairing memiliki biaya nyata: beberapa detik pertukaran pada koneksi pertama, penggunaan flash yang persisten untuk setiap perangkat yang di-bond, dan cerita pemulihan "lupakan bond" jika ada yang salah. Untuk data yang benar-benar publik -- pembacaan sensor ambient yang diterbitkan sebagai beacon, papan tanda yang menampilkan namanya, apa pun yang tidak mengubah dunia dengan dibaca atau ditulis -- jawaban yang tepat adalah tidak mengenkripsi sama sekali, dan biarkan pemindai di sekitar membaca nilainya.

Untuk semua yang lain, connection.pair(bond=True) pada central adalah tambahan satu baris yang mengubah link dari saluran publik menjadi saluran privat.