Блог

Baby Monitor Timmy-ийн аюулгүй хослуулалт

ECDH, SAS дугаар болон шифрлэсэн дохиолол хэрхэн хамт ажилладгийг тайлбарлая.

Baby Monitor Timmy аудио, видео дамжуулахаас өмнө хоёр төхөөрөмж бие биеэ олж, харилцан итгэх хэрэгтэй. Энэ хослуулах алхам нь бүх үйл явцын хамгийн чухал мөч юм. Энд Timmy хэрхэн хослуулдаг, үүний ард ямар криптографи байдгийг, мөн ойр байгаа халдагч яагаад холболтыг анзаарагдалгүй эзэлж авч чаддаггүйг тайлбарлана.

Асуудал: Миний төхөөрөмж хэнтэй холбогдож байгаагаа яаж мэдэх вэ?

Хоёр төхөөрөмж анх удаа холбогдох үед гол асуулт нь: A төхөөрөмж үнэхээр B төхөөрөмжтэй холбогдож байна уу, эсвэл дунд нь хэн нэгэн байна уу? Криптографид үүнийг дундын этгээдийн халдлага (MITM) гэдэг.

Timmy үүнийг Elliptic Curve Diffie-Hellman (ECDH) түлхүүр солилцоо г Firebase-ээр хийж, хэрэглэгч хоёр төхөөрөмж дээрх мэдээллийг нүдээр харьцуулан баталгаажуулах аргыг хослуулснаар шийддэг..

Дараах схем хослуулах бүх явцыг нэг дор харуулна:

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
      

Хослуулах протоколын бүрэн дараалал — засварлаж болох эх сурвалж: docs/diagrams/pairing-sequence.mmd

Алхам 1: Төхөөрөмж бүр түлхүүрийн хос үүсгэнэ

Хослуулах дэлгэцийг нээхэд төхөөрөмж бүр түр зуурын ECDH түлхүүрийн хос -ыг P-256 (secp256r1) муруйн дээр үүсгэнэ:

Түлхүүрүүдийг криптографийн хувьд аюулгүй санамсаргүй тоо үүсгэгчээр (Random.secure()) үүсгэх бөгөөд зөвхөн энэ удаагийн хослуулах оролдлогод хүчинтэй. Шинэ оролдлого бүрт шинэ түлхүүрүүд үүснэ.

Алхам 2: Нийтийн түлхүүрүүдийг Firebase-ээр солилцох

Хоёр төхөөрөмж бие биеэ олохын тулд Timmy 4 тэмдэгттэй код -ыг хоёр төхөөрөмж бие биеэ олоход ашигладаг. Энэ кодыг Nearby Connections (Bluetooth Low Energy)-ээр автоматаар илрүүлэх эсвэл гараар оруулах боломжтой. Энэ нь өөрөө криптографийн хамгаалалт болдоггүй; зөвхөн хоёр төхөөрөмжийг Firebase Firestore дахь нэг баримттай холбодог.

Хоёр төхөөрөмж кодыг мэдмэгцээ тус бүр нийтийн ECDH түлхүүрээ хамтын Firestore баримт-д бичнэ. Дараа нь төхөөрөмж бүр нөгөө төхөөрөмжийн нийтийн түлхүүрийг тэр баримтаас уншина.

Чухал нь: зөвхөн нийтийн түлхүүр илгээгддэг. Хувийн түлхүүр төхөөрөмжөөс хэзээ ч гардаггүй. Firebase-ийн урсгалыг харж буй хэн ч нийтийн түлхүүрүүдийг харна, гэхдээ тэдгээрээс хамтын нууцыг тооцоолж чадахгүй . Энэ нь эллиптик муруйн дискрет логарифмын бодлого (ECDLP)-ын хүндрэлд тулгуурладаг.

Алхам 3: Хамтын нууцыг тооцоолох

Хоёр төхөөрөмж бие биеийнхээ нийтийн түлхүүрийг олсны дараа адилхан хамтын нууц:

sharedSecret = ECDH(myPrivateKey, remotePublicKey)
             → 32 bytes (identical on both devices)

-ыг тус тусдаа тооцоолно. Эллиптик муруйн математик нь төхөөрөмж бүр зөвхөн өөрийн хувийн түлхүүр болон нөгөө талын нийтийн түлхүүрийг мэддэг байсан ч хоёр тооцоолол ижил үр дүн өгөхийг баталгаажуулдаг.

Алхам 4: Баталгаажуулалтын дугаар (SAS)

Хамтын нууцаас Богино баталгаажуулалтын мөр (SAS) гарган авдаг — энэ нь хоёр төхөөрөмж дээр хоёуланд нь харагдах хоёр оронтой дугаар юм:

hash   = SHA-256("sas:" + sort(pubkeyA, pubkeyB) + sharedSecret)
number = (hash[0] × 256 + hash[1]) mod 100   → 00 to 99

Хоёр төхөөрөмж дээр ижил дугаар харагдана — жишээлбэл, 42. Хэрэглэгч хоёр дэлгэц дээрх дугаарууд таарч байгаа эсэхийг нүдээр харьцуулж шалгаад тус бүрийн төхөөрөмж дээр баталгаажуулна.

Яагаад халдагч үүнийг хуурамчаар үйлдэж чадахгүй вэ

Дундын этгээдийн халдагч Firebase дэх түлхүүр солилцоог таслан авах хэрэгтэй болно. Тодруулбал, халдагч:

  1. Firestore баримтад хадгалсан жинхэнэ нийтийн түлхүүрүүдийг өөрийн нийтийн түлхүүрүүдээр солих
  2. Төхөөрөмж тус бүртэй тусдаа хамтын нууц тогтоох
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)
      

SAS дугаарууд зөрөхөд дундын этгээдийн халдлагыг илрүүлэх нь — засварлаж болох эх сурвалж: docs/diagrams/mitm-detection.mmd

Энэ тохиолдолд халдагч A төхөөрөмжтэй нэг хамтын нууц, B төхөөрөмжтэй S_A өөр хамтын нууц S_B тооцоолно. Иймээс S_A ≠ S_B, төхөөрөмжүүд өөр баталгаажуулалтын дугаар.

тооцоолно. Халдагч дугааруудыг тааруулж чадахгүй. Учир нь:

Хэрэглэгч дэлгэцүүд дээр өөр дугааруудыг хараад хослуулахыг цуцална. Тэр үед халдлага ил болсон байна.

Алхам 5: Хослуулалтыг дуусгах

Хэрэглэгч хоёр төхөөрөмж дээр баталгаажуулсны дараа л хослуулалт дуусна:

  1. Нэг 64 тэмдэгттэй хослуулах түлхүүр (256 бит) -ийг хамтын нууцаас гарган авна: SHA-256("pair:" + sharedSecret) → pairingKey
  2. Баримтын түлхүүрийг SHA-256("doc:" + pairingKey) гэж гарган авч, Firestore баримтын түлхүүр болгон ашиглана
  3. Шифрлэлтийн түлхүүрийг SHA-256("enc:" + pairingKey) гэж гарган авч, шифрлэсэн дохиоллын AES-256-GCM түлхүүр болгоно
  4. Хоёр төхөөрөмж ижил хослуулах түлхүүрийг хадгалж, горим сонгох хэсэг рүү шилжинэ

Энэ үеэс цааших бүх холболтын оролдлого (Firestore дохиолол, WebRTC тохируулга) хамтын AES-256-GCM түлхүүрээр шифрлэгдэнэ. Хослуулах түлхүүрийг серверийн арын хэсэг рүү хэзээ ч илгээдэггүй; зөвхөн SHA-256 хэшийг нь баримтын танигч болгон ашигладаг.

Системийн архитектур

Дараах схем хослуулах болон харилцаанд оролцдог бүрэлдэхүүнүүдийг харуулна:

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

Системийн архитектурын тойм — засварлаж болох эх сурвалж: docs/diagrams/pairing-architecture.mmd

Харилцааны сувгуудыг дэлгэрэнгүй үзвэл:

Нөөц хувилбар: Кодыг гараар оруулах

Bluetooth ашиглах боломжгүй бол (жишээ нь, хуучин төхөөрөмжүүд дээр) 4 тэмдэгттэй кодыг гараар оруулж болно. Гараар оруулахад ижил ECDH түлхүүр солилцоо, ижил SAS баталгаажуулалт автомат хослуулалтын адил ашиглагдана. Ялгаа нь кодыг BLE-ээр илрүүлэхийн оронд хэрэглэгч уншиж, шивж оруулдагт л оршино.

Аль ч тохиолдолд ECDH түлхүүр солилцоо Firebase-ээр хийгддэг тул аюулгүй байдал нь ижил. 4 тэмдэгттэй кодыг зөвхөн хоёр төхөөрөмж бие биеэ олоход ашигладаг; жинхэнэ шифрлэлт нь ECDH-ээс гарган авсан 256 битийн түлхүүрт тулгуурладаг.

Товч дүгнэлт

Аюулгүй байдлын механизм Юунаас хамгаалдаг вэ
ECDH түлхүүр солилцоо (P-256) Түлхүүр солилцооны урсгалыг чагнах
Түр зуурын түлхүүрийн хос Урагш нууцлал — өмнөх хослуулалтууд аюулгүй хэвээр үлдэнэ
Нүдээр шалгах баталгаажуулалтын дугаар (SAS) Түлхүүр солилцооны үеийн дундын этгээдийн халдлага (MITM)
Баримтын түлхүүр болгон ашиглах SHA-256 хэш Firestore-оос код гарган авах
AES-256-GCM шифрлэлт Дохиоллын өгөгдлийг чагнах
Хоёр талын баталгаажуулалт Хэрэглэгч мэдэлгүйгээр нэг талаас хослуулах
DTLS-SRTP (WebRTC) Аудио/видеог чагнах

Эдгээр давхаргууд хамтдаа ажиллана: ECDH нь түлхүүр солилцоог, баталгаажуулалтын дугаар нь MITM халдлагаас, AES-256-GCM нь дохиоллыг, WebRTC нь медиаг хамгаална. Халдагч төхөөрөмжүүд эсвэл эцэг эхчүүд анзаарахгүйгээр энэ гинжийг хэд хэдэн цэгт эвдэх хэрэгтэй болно.


Илүү олон нийтлэл