Blogu

Kuunganisha kwa usalama katika Baby Monitor Timmy

Jinsi ECDH, namba ya SAS na uashiriaji uliosimbwa kwa njia fiche vinavyofanya kazi pamoja.

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):

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:

  1. Kubadilisha funguo halisi za umma zilizohifadhiwa kwenye hati ya Firestore kwa zake
  2. 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:

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:

  1. Ufunguo wa kuunganisha wenye vibambo 64 (biti 256) hutolewa kutoka kwenye siri ya pamoja: SHA-256("pair:" + sharedSecret) → pairingKey
  2. Ufunguo wa hati hutolewa kama SHA-256("doc:" + pairingKey) na hutumika kama ufunguo wa hati ya Firestore
  3. Ufunguo wa usimbaji hutolewa kama SHA-256("enc:" + pairingKey) na hutoa ufunguo wa AES-256-GCM kwa uashiriaji uliosimbwa kwa njia fiche
  4. 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:

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.


Makala zaidi