Baby Monitor Timmy аудио жана видеону өткөрүүдөн мурун, эки түзмөк бири-бирин таап, бири-бирине ишениши керек. Бул жупташтыруу кадамы бүт процесстеги эң маанилүү учур. Бул жерде Timmy түзмөктөрдү кантип жупташтырарын, мунун артында кандай криптография турарын жана жакын жердеги чабуулчу байланышты байкатпай өз көзөмөлүнө ала албай турганын түшүндүрөм.
Маселе: түзмөгүм ким менен сүйлөшүп жатканын кантип билет?
Эки түзмөк биринчи жолу туташканда негизги суроо мындай: А түзмөгү чын эле Б түзмөгү менен сүйлөшүп жатабы, же ортодо башка бирөө барбы? Криптографияда бул ортодогу адамдын чабуулу (MITM) деп аталат.
Timmy муну Firebase аркылуу жүргүзүлгөн эллиптикалык ийри сызыктардагы Диффи—Хеллман (ECDH) ачкыч алмашуусун жана колдонуучунун визуалдык текшерүүсүн айкалыштыруу менен чечет..
Төмөнкү диаграмма жупташтыруунун толук агымын бир караганда көрсөтөт:
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
Мындай учурда чабуулчу А түзмөгү менен 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 медианы коргойт. Чабуулчу түзмөктөр же ата-энелер байкабай тургандай кылып, бул чынжырды бир нече жерден бузушу керек болмок.