Kabla Baby Monitor Timmy haijaanza kutuma sauti na video, vifaa viwili vinahitaji kuonana na kuaminiana. Hatua hii ya kuunganisha ndiyo wakati muhimu zaidi katika mchakato mzima. Hapa ninaeleza Timmy huunganisha vipi, kriptografia inayotumika, na kwa nini mshambulizi wa karibu hawezi kuchukua muunganisho bila kugundulika.
Tatizo: Kifaa changu kinajuaje kinazungumza na nani?
Vifaa viwili vinapounganishwa kwa mara ya kwanza, swali kuu ni: je, Kifaa A kweli kinazungumza na Kifaa B, au kuna mtu katikati? Katika kriptografia, hilo huitwa shambulizi la mtu-katikati (MITM).
Timmy hutatua hili kwa ubadilishanaji wa funguo wa Elliptic Curve Diffie-Hellman (ECDH) kupitia Firebase, pamoja na uthibitishaji wa kuona na mtumiaji.
Mchoro ufuatao unaonyesha mchakato kamili wa kuunganisha kwa mtazamo mmoja:
sequenceDiagram
autonumber
participant A as 📱 Device A
participant F as ☁️ Firebase
participant B as 📱 Device B
Note over A,B: Phase 1 — Discovery
A->>A: Generate ECDH key pair (P-256)
B->>B: Generate ECDH key pair (P-256)
alt Auto-Pairing (Nearby BLE)
A-->>B: BLE broadcast: SBM:XKQM
B-->>A: BLE broadcast: SBM:R7NP
Note over A,B: Lower code wins → determines creator/joiner
else Manual Pairing
A->>A: Display 4-char code
Note right of A: User reads code
B->>B: User enters code
end
Note over A,B: Phase 2 — ECDH Key Exchange
A->>F: Write public key (PubA) to meeting doc
B->>F: Write public key (PubB) to meeting doc
F-->>B: Read PubA
F-->>A: Read PubB
Note over A,B: Phase 3 — Shared Secret
A->>A: sharedSecret = ECDH(privA, PubB)
B->>B: sharedSecret = ECDH(privB, PubA)
Note over A,B: Both compute identical 32-byte secret
A->>A: SAS = SHA-256("sas:" + sort(PubA,PubB) + secret) → 2-digit number
B->>B: SAS = SHA-256("sas:" + sort(PubA,PubB) + secret) → 2-digit number
Note over A,B: Phase 4 — Visual Verification
A->>A: Display SAS: 42
B->>B: Display SAS: 42
Note over A,B: 👤 User compares numbers on both screens
A->>A: User confirms ✓
B->>B: User confirms ✓
Note over A,B: Phase 5 — Key Derivation
A->>A: pairingKey = SHA-256("pair:" + secret)
B->>B: pairingKey = SHA-256("pair:" + secret)
A->>A: docKey = SHA-256("doc:" + pairingKey)
A->>A: encKey = SHA-256("enc:" + pairingKey)
Note over A,B: ✅ Paired — all future signaling encrypted with AES-256-GCM
Mfuatano kamili wa itifaki ya kuunganisha — chanzo kinachoweza kuhaririwa: docs/diagrams/pairing-sequence.mmd
Hatua ya 1: Kila kifaa hutengeneza jozi ya funguo
Kila kifaa kinapofungua skrini ya kuunganisha, hutengeneza jozi ya muda ya funguo za ECDH kwenye mkunjo eliptiki wa P-256 (secp256r1):
- Ufunguo wa faragha — hubaki kwenye kifaa pekee
- Ufunguo wa umma — hubadilishwa kupitia Firebase
Funguo hutengenezwa kwa kutumia jenereta ya namba nasibu iliyo salama kikriptografia (Random.secure())
na ni halali kwa jaribio hili moja tu la kuunganisha. Funguo mpya hutengenezwa
kwa kila jaribio jipya.
Hatua ya 2: Kubadilishana funguo za umma kupitia Firebase
Ili vifaa viwili viweze kuonana, Timmy hutumia msimbo wa vibambo 4 kama sehemu ya kukutania. Msimbo huu unaweza kugunduliwa kiotomatiki kupitia Nearby Connections (Bluetooth Low Energy) au kuingizwa mwenyewe. Hauna thamani ya kriptografia; unawezesha tu vifaa vyote viwili kupata hati ileile ya Firebase Firestore.
Vifaa vyote viwili vikishajua msimbo, kila kimoja huandika ufunguo wake wa umma wa ECDH kwenye hati ya Firestore. Kisha kila kifaa husoma ufunguo wa umma wa kifaa kingine kutoka kwenye hati hiyo.
Muhimu: ni ufunguo wa umma tu unaotumwa. Ufunguo wa faragha hauondoki kamwe kwenye kifaa. Mtu yeyote anayetazama trafiki ya Firebase huona funguo za umma, lakini hawezi kuhesabu siri ya pamoja kutokana nazo. Hii hutegemea ugumu wa Tatizo la Logaritimu Diskriti kwenye Mkunjo Eliptiki (ECDLP).
Hatua ya 3: Kuhesabu siri ya pamoja
Vifaa vyote viwili vikishagundua ufunguo wa umma wa kila kimoja, kila kimoja huhesabu kwa kujitegemea siri ileile ya pamoja:
sharedSecret = ECDH(myPrivateKey, remotePublicKey)
→ 32 bytes (identical on both devices)
Hisabati ya mikunjo eliptiki huhakikisha kuwa hesabu zote mbili zinatoa matokeo sawa, ingawa kila kifaa kinajua tu ufunguo wake wa faragha na ufunguo wa umma wa kifaa kingine.
Hatua ya 4: Namba ya uthibitishaji (SAS)
Kutoka kwenye siri ya pamoja, Short Authentication String (SAS) hutolewa — namba ya tarakimu mbili inayoonyeshwa kwenye vifaa vyote viwili:
hash = SHA-256("sas:" + sort(pubkeyA, pubkeyB) + sharedSecret)
number = (hash[0] × 256 + hash[1]) mod 100 → 00 to 99
Vifaa vyote viwili huonyesha namba ileile — kwa mfano, 42. Mtumiaji huangalia kwa macho kama namba kwenye skrini zote mbili zinafanana, kisha huthibitisha kwenye kila kifaa kivyake.
Kwa nini mshambulizi hawezi kughushi hili
Mtu-katikati angehitaji kuingilia ubadilishanaji wa funguo kwenye Firebase. Hasa, angehitaji:
- Kubadilisha funguo halisi za umma zilizohifadhiwa kwenye hati ya Firestore kwa zake
- Kuanzisha siri tofauti za pamoja na kila kifaa
sequenceDiagram
autonumber
participant A as 📱 Device A
participant M as 🕵️ Attacker (MITM)
participant B as 📱 Device B
Note over A,B: Attacker intercepts the Firebase key exchange
A->>A: Generate key pair (privA, PubA)
B->>B: Generate key pair (privB, PubB)
M->>M: Generate TWO key pairs (privM1, PubM1) + (privM2, PubM2)
A->>M: Write PubA to Firebase
M->>M: Replace PubA with PubM1
M->>B: B reads PubM1 (thinks it is PubA)
B->>M: Write PubB to Firebase
M->>M: Replace PubB with PubM2
M->>A: A reads PubM2 (thinks it is PubB)
Note over A,B: Each device computes a DIFFERENT shared secret
A->>A: secret_A = ECDH(privA, PubM2)
M->>M: secret_A = ECDH(privM2, PubA)
M->>M: secret_B = ECDH(privM1, PubB)
B->>B: secret_B = ECDH(privB, PubM1)
Note over A,M: secret_A ≠ secret_B
A->>A: SAS_A = SHA-256("sas:" + sort(PubA,PubM2) + secret_A) → 73
B->>B: SAS_B = SHA-256("sas:" + sort(PubM1,PubB) + secret_B) → 18
rect rgb(255, 230, 230)
Note over A,B: ❌ User sees DIFFERENT numbers!
A->>A: Display: 73
B->>B: Display: 18
Note over A,B: 👤 User notices mismatch → cancels pairing
end
Note over A,B: 🛡️ Attack detected — MITM cannot force SAS match (P = 1/100)
Ugunduzi wa mtu-katikati kupitia namba za SAS zisizolingana — chanzo kinachoweza kuhaririwa: docs/diagrams/mitm-detection.mmd
Katika hali hii, mshambulizi huhesabu siri ya pamoja S_A na Kifaa A na
siri tofauti ya pamoja S_B na Kifaa B. Kwa kuwa S_A ≠ S_B,
vifaa huhesabu namba tofauti za uthibitishaji.
Mshambulizi hawezi kufanya namba zilingane kwa sababu:
- Hajui funguo za faragha za vifaa
- Mchakato wa SHA-256 hauwezi kugeuzwa ili kupata data ya awali
- Uwezekano wa namba kulingana kwa bahati ni 1 kati ya 100
Mtumiaji huona namba tofauti kwenye skrini na kughairi kuunganisha. Wakati huo, shambulizi limeonekana.
Hatua ya 5: Kukamilisha kuunganisha
Ni baada tu ya mtumiaji kuthibitisha namba ya uthibitishaji kwenye vifaa vyote viwili ndipo kuunganisha kunakamilika:
- Ufunguo wa kuunganisha wenye vibambo 64 (biti 256) hutolewa kutoka kwenye siri ya pamoja:
SHA-256("pair:" + sharedSecret) → pairingKey - Ufunguo wa hati hutolewa kama
SHA-256("doc:" + pairingKey)na hutumika kama ufunguo wa hati ya Firestore - Ufunguo wa usimbaji hutolewa kama
SHA-256("enc:" + pairingKey)na hutoa ufunguo wa AES-256-GCM kwa uashiriaji uliosimbwa kwa njia fiche - Vifaa vyote viwili huhifadhi ufunguo uleule wa kuunganisha na kwenda kwenye uteuzi wa hali
Kuanzia hapa, majaribio yote ya baadaye ya kuunganisha (uashiriaji wa Firestore, usanidi wa WebRTC) husimbwa kwa ufunguo wa pamoja wa AES-256-GCM. Ufunguo wa kuunganisha hautumwi kamwe kwenye mfumo wa nyuma; ni hashi yake ya SHA-256 tu inayotumika kama kitambulisho cha hati.
Muundo wa mfumo
Mchoro ufuatao unaonyesha vipengele vinavyohusika katika kuunganisha na mawasiliano:
flowchart TB
BABY["📱 Baby Phone
Baby Mode"]
PARENT["📱 Parent Phone
Parent Mode"]
BABY <==>|"🔒 WebRTC Peer-to-Peer · DTLS-SRTP
Audio · Video · DataChannel"| PARENT
BABY -.-|"🔵 Bluetooth LE · Nearby
Auto-Discovery"| PARENT
subgraph FIREBASE["☁️ Firebase (Google Cloud)"]
direction LR
AUTH["🪪 Anonymous
Authentication"]
FS["📄 Firestore
Pairing + Signaling"]
CF["⚡ Cloud Functions
getTurnCredentials"]
end
BABY <-->|"🔐 AES-256-GCM encrypted
SDP · ICE · ECDH keys"| FS
FS <-->|"🔐 AES-256-GCM encrypted
SDP · ICE · ECDH keys"| PARENT
BABY -.->|Token| AUTH
PARENT -.->|Token| AUTH
STUN["📡 STUN server
stun.cloudflare.com:3478"]
TURN["🔄 TURN relay
local or Cloudflare"]
BABY & PARENT -->|Short-lived credentials| CF
CF -->|local first, Cloudflare fallback| TURN
BABY & PARENT -.->|NAT Traversal| STUN
BABY -.->|"Relay Fallback"| TURN
TURN -.->|"Relay Fallback"| PARENT
style BABY fill:#FBF6F0,stroke:#B5734A,stroke-width:2px
style PARENT fill:#FBF6F0,stroke:#B5734A,stroke-width:2px
style FIREBASE fill:#fff5f5,stroke:#E9B44C,stroke-width:2px
style AUTH fill:#E9B44C,stroke:#2B2D42
style FS fill:#E9B44C,stroke:#2B2D42
style CF fill:#E9B44C,stroke:#2B2D42
style STUN fill:#F6E3D2,stroke:#B5734A
style TURN fill:#7BC47F,stroke:#2B2D42
Muhtasari wa muundo wa mfumo — chanzo kinachoweza kuhaririwa: docs/diagrams/pairing-architecture.mmd
Njia za mawasiliano kwa undani:
- WebRTC rika-kwa-rika (mstari mnene): Sauti, video na DataChannel hupita moja kwa moja kati ya vifaa — zimesimbwa kwa DTLS-SRTP. Hakuna seva inayoona data hii.
- Firebase Firestore (mstari thabiti): Data ya kuunganisha (funguo za ECDH) na uashiriaji (SDP/ICE) hupitia Firestore — zikiwa zimesimbwa kwa njia fiche kutoka mwanzo hadi mwisho kwa AES-256-GCM. Firebase haiwezi kusimbua data hiyo.
- Seva ya STUN: Vifaa vyote viwili hugundua anwani yao ya IP ya umma ili muunganisho wa moja kwa moja wa rika-kwa-rika uweze kuanzishwa.
- Relay ya TURN: Ikiwa muunganisho wa moja kwa moja hauwezekani (kwa mfano, unapotumia data ya simu), seva iliyochaguliwa ya TURN ya ndani au ya Cloudflare hupitisha data ya sauti na video iliyosimbwa kwa njia fiche. Taarifa za uthibitishaji za muda mfupi (saa 24) hupatikana kupitia Firebase Cloud Functions.
- Bluetooth LE (mstari wa nukta): Nearby Connections hugundua vifaa vilivyo karibu kiotomatiki — msimbo wa kukutania pekee ndio unaotumwa; hakuna data yoyote ya funguo inayotumwa.
Njia mbadala: Kuingiza msimbo mwenyewe
Ikiwa Bluetooth haipatikani (kwa mfano, kwenye vifaa vya zamani), msimbo wa vibambo 4 unaweza pia kuingizwa mwenyewe. Kuingiza msimbo mwenyewe hutumia ubadilishanaji uleule wa funguo za ECDH na uthibitishaji uleule wa SAS kama kuunganisha kiotomatiki. Tofauti pekee ni kuwa msimbo husomwa na kuandikwa na mtumiaji badala ya kugunduliwa kupitia BLE.
Kwa kuwa ubadilishanaji wa funguo za ECDH hutokea kupitia Firebase katika hali zote mbili, usalama ni uleule. Msimbo wa vibambo 4 ni sehemu ya kukutania tu; usimbaji halisi unategemea ufunguo wa biti 256 unaotokana na ECDH.
Muhtasari
| Mbinu ya usalama | Hulinda dhidi ya |
|---|---|
| Ubadilishanaji wa funguo za ECDH (P-256) | Kusikiliza trafiki ya ubadilishanaji wa funguo |
| Jozi za funguo za muda | Usiri wa mbele — miunganisho ya zamani hubaki salama |
| Namba ya uthibitishaji wa kuona (SAS) | Mtu-katikati (MITM) wakati wa ubadilishanaji wa funguo |
| Hashi ya SHA-256 kama ufunguo wa hati | Kutoa msimbo kutoka Firestore |
| Usimbaji wa AES-256-GCM | Kusikiliza data ya uashiriaji |
| Uthibitishaji wa pande zote mbili | Kuunganisha upande mmoja bila mtumiaji kujua |
| DTLS-SRTP (WebRTC) | Kusikiliza sauti/video |
Tabaka hizi zinafanya kazi pamoja: ECDH hulinda ubadilishanaji wa funguo, namba ya uthibitishaji hulinda dhidi ya MITM, AES-256-GCM hulinda uashiriaji, na WebRTC hulinda media. Mshambulizi angelazimika kuvunja mnyororo huu katika sehemu kadhaa bila vifaa au wazazi kugundua.