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) муруйн дээр үүсгэнэ:
- Нэг хувийн түлхүүр — зөвхөн төхөөрөмж дээр үлдэнэ
- Нэг нийтийн түлхүүр — Firebase-ээр солилцогдоно
Түлхүүрүүдийг криптографийн хувьд аюулгүй санамсаргүй тоо үүсгэгчээр (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 дэх түлхүүр солилцоог таслан авах хэрэгтэй болно. Тодруулбал, халдагч:
- Firestore баримтад хадгалсан жинхэнэ нийтийн түлхүүрүүдийг өөрийн нийтийн түлхүүрүүдээр солих
- Төхөөрөмж тус бүртэй тусдаа хамтын нууц тогтоох
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,
төхөөрөмжүүд өөр баталгаажуулалтын дугаар.
тооцоолно. Халдагч дугааруудыг тааруулж чадахгүй. Учир нь:
- Тэд төхөөрөмжүүдийн хувийн түлхүүрийг мэдэхгүй
- SHA-256-г буцааж хөрвүүлэх боломжгүй
- Санамсаргүйгээр таарах магадлал ердөө 100-д 1
Хэрэглэгч дэлгэцүүд дээр өөр дугааруудыг хараад хослуулахыг цуцална. Тэр үед халдлага ил болсон байна.
Алхам 5: Хослуулалтыг дуусгах
Хэрэглэгч хоёр төхөөрөмж дээр баталгаажуулсны дараа л хослуулалт дуусна:
- Нэг 64 тэмдэгттэй хослуулах түлхүүр (256 бит) -ийг хамтын нууцаас гарган авна:
SHA-256("pair:" + sharedSecret) → pairingKey - Баримтын түлхүүрийг
SHA-256("doc:" + pairingKey)гэж гарган авч, Firestore баримтын түлхүүр болгон ашиглана - Шифрлэлтийн түлхүүрийг
SHA-256("enc:" + pairingKey)гэж гарган авч, шифрлэсэн дохиоллын AES-256-GCM түлхүүр болгоно - Хоёр төхөөрөмж ижил хослуулах түлхүүрийг хадгалж, горим сонгох хэсэг рүү шилжинэ
Энэ үеэс цааших бүх холболтын оролдлого (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
Харилцааны сувгуудыг дэлгэрэнгүй үзвэл:
- WebRTC төхөөрөмж хоорондын шууд холболт (бүдүүн шугам): Аудио, видео, DataChannel нь төхөөрөмжүүдийн хооронд шууд дамжина — DTLS-SRTP-ээр шифрлэгдэнэ. Ямар ч сервер энэ өгөгдлийг хардаггүй.
- Firebase Firestore (тасралтгүй шугам): Хослуулах өгөгдөл (ECDH түлхүүрүүд) болон дохиолол (SDP/ICE) Firestore-оор дамжина — AES-256-GCM-ээр төгсгөлөөс төгсгөл хүртэл шифрлэгдэнэ. Firebase өгөгдлийг тайлж чадахгүй.
- STUN сервер: Шууд төхөөрөмж хоорондын холболт үүсгэхийн тулд хоёр төхөөрөмж хоёулаа нийтийн IP хаягаа олно.
- TURN дамжуулагч: Шууд холболт боломжгүй үед (жишээ нь, мобайл дата ашиглаж байвал) сонгосон дотоод эсвэл Cloudflare TURN сервер шифрлэсэн медиаг дамжуулна. 24 цаг хүчинтэй нэвтрэх мэдээллийг Firebase Cloud Functions-ээр авна.
- Bluetooth LE (цэгэн шугам): Nearby Connections нь ойролцоох төхөөрөмжүүдийг автоматаар илрүүлнэ — зөвхөн холбох код дамжих бөгөөд түлхүүрийн ямар ч өгөгдөл дамжихгүй.
Нөөц хувилбар: Кодыг гараар оруулах
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 нь медиаг хамгаална. Халдагч төхөөрөмжүүд эсвэл эцэг эхчүүд анзаарахгүйгээр энэ гинжийг хэд хэдэн цэгт эвдэх хэрэгтэй болно.