Блог

Baby Monitor Timmy колдонмосундагы коопсуз жупташтыруу

ECDH, SAS номери жана шифрленген сигналдаштыруу кантип чогуу иштейт.

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) жаратат:

Ачкычтар криптографиялык жактан коопсуз кокустук сандар генератору (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

Мындай учурда чабуулчу А түзмөгү менен 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 медианы коргойт. Чабуулчу түзмөктөр же ата-энелер байкабай тургандай кылып, бул чынжырды бир нече жерден бузушу керек болмок.


Дагы макалалар