ลักษณะเฉพาะ
บริการจับคู่ด่วน
ผู้ให้บริการการจับคู่ด่วนต้องมีบริการ GATT ต่อไปนี้
| บริการ | UUID |
|---|---|
| บริการจับคู่ด่วน | 0xFE2C |
บริการนี้ต้องมีลักษณะต่อไปนี้
| ลักษณะของบริการจับคู่ด่วน | มีการเข้ารหัส | สิทธิ์ | UUID |
|---|---|---|---|
| รหัสโมเดล | ไม่ | อ่าน | FE2C1233-8366-4814-8EB0-01DE32100BEA |
| การจับคู่ตามคีย์ | ไม่ | เขียนและแจ้งเตือน | FE2C1234-8366-4814-8EB0-01DE32100BEA |
| พาสคีย์ | ไม่ | เขียนและแจ้งเตือน | FE2C1235-8366-4814-8EB0-01DE32100BEA |
| คีย์บัญชี | ไม่ | เขียน | FE2C1236-8366-4814-8EB0-01DE32100BEA |
บริการข้อมูลอุปกรณ์
นอกจากนี้ ผู้ให้บริการการจับคู่ด่วนควรจะรองรับบริการข้อมูลอุปกรณ์ด้วย
| บริการ | UUID |
|---|---|
| บริการข้อมูลอุปกรณ์ | 0x180A |
Seeker ของการจับคู่ด่วนใช้ลักษณะต่อไปนี้
| ชื่อ | มีการเข้ารหัส | สิทธิ์ | UUID |
|---|---|---|---|
| การแก้ไขเฟิร์มแวร์ | ไม่ | อ่าน | 0x2A26 |
ลักษณะ: รหัสโมเดล
ลักษณะนี้ช่วยให้ Seeker อ่านรหัสโมเดลได้ตามต้องการนอกเหนือจากกรณีที่อุปกรณ์โฆษณาในโหมดที่ค้นพบได้ โดยควรแสดงข้อมูลต่อไปนี้เสมอ
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า |
|---|---|---|---|
| 0 - 2 | uint24 |
รหัสโมเดล | แปรเปลี่ยน |
ลักษณะ: การจับคู่ตามคีย์
ลักษณะนี้ควบคุมขั้นตอนการจับคู่ตามคีย์ ในขั้นตอนนี้ จะมีการสร้างระดับความน่าเชื่อถือโดยการยืนยันว่าทั้งผู้ขอและ ผู้ให้บริการมีคีย์ที่แชร์ล่วงหน้า คีย์จะแตกต่างกันในแต่ละกรณีดังนี้
กรณีที่ 1: คีย์ที่แชร์ล่วงหน้าอิงตามคู่คีย์สาธารณะ/ส่วนตัวป้องกันการปลอมแปลง และคู่คีย์สาธารณะ/ส่วนตัวของ Seeker เองซึ่งจะเปลี่ยนไปในแต่ละ ความพยายามในการจับคู่
- ผู้ให้บริการอยู่ในโหมดการจับคู่
- ผู้ขอจะยืนยันว่าผู้ให้บริการมี คีย์ส่วนตัวป้องกันการปลอมแปลง
โปรดทราบว่าเมื่ออยู่ในโหมดการจับคู่ ผู้ให้บริการอาจจับคู่ในลักษณะปกติได้เช่นกัน เช่น จับคู่กับอุปกรณ์ที่ไม่รองรับการจับคู่ตามคีย์ของ Fast Pair
กรณีที่ 2: คีย์ที่แชร์ล่วงหน้าเป็นหนึ่งในคีย์บัญชี
- โดยปกติแล้วผู้ให้บริการจะไม่ได้อยู่ในโหมดการจับคู่ (แต่ไม่จำเป็นต้องทำเช่นนี้ ผู้ให้บริการควรรองรับการใช้คีย์บัญชีแม้ว่าจะอยู่ในโหมดการจับคู่ก็ตาม)
- Seeker และ Provider จะยืนยันว่าอีกฝ่ายมี คีย์บัญชี
เนื่องจากทั้ง 2 กรณีมีความคล้ายคลึงกันอย่างมาก ยกเว้นคีย์ที่ให้ใช้ร่วมกันล่วงหน้าที่จะใช้ จึงรวมไว้ในขั้นตอน
รูปแบบข้อมูล
ดูขั้นตอนเกี่ยวกับวิธีใช้แต่ละรูปแบบ
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า | ต้องระบุหรือไม่ |
|---|---|---|---|---|
| 0-15 | uint128 |
คำขอที่เข้ารหัส | แปรเปลี่ยน | บังคับ |
| 16 - 79 | คีย์สาธารณะ | แปรเปลี่ยน | ไม่บังคับ |
ตาราง 1.1: คำขอที่เข้ารหัสซึ่งเขียนลงในลักษณะโดยผู้ค้นหา
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า | ต้องระบุหรือไม่ |
|---|---|---|---|---|
| 0 | uint8 |
ประเภทของข้อความ | 0x00 = คำขอจับคู่ตามคีย์ |
บังคับ |
| 1 | uint8 |
ธง
|
แตกต่างกันไป | บังคับ |
| 2 - 7 | uint48 |
อย่างใดอย่างหนึ่งต่อไปนี้
|
แตกต่างกันไป | บังคับ |
| 8 - 13 | uint48 |
ที่อยู่ BR/EDR ของอุปกรณ์ที่ค้นหา | แตกต่างกันไป | แสดงเฉพาะในกรณีที่ตั้งค่าบิตการแจ้งเตือน 1 หรือ 3 |
| n - 15 | ค่าแบบสุ่ม (Salt) | แตกต่างกันไป | บังคับ |
ตาราง 1.2.1: คำขอแบบดิบ (ประเภท 0x00) ถอดรหัสจากคำขอที่เข้ารหัส ใน ตารางที่ 1.1
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า | ต้องระบุหรือไม่ |
|---|---|---|---|---|
| 0 | uint8 |
ประเภทของข้อความ | 0x10 = คำขอให้ดำเนินการ |
บังคับ |
| 1 | uint8 |
ธง
|
แตกต่างกันไป | บังคับ |
| 2 - 7 | uint48 |
อย่างใดอย่างหนึ่งต่อไปนี้
|
แตกต่างกันไป | บังคับ |
| 8 | uint8 |
กลุ่มข้อความ | แตกต่างกันไป | ต้องระบุหากตั้งค่าบิต 0 ของ Flags |
| 9 | uint8 |
รหัสข้อความ | แตกต่างกันไป | ต้องระบุหากตั้งค่าบิต 0 ของ Flags |
| 10 | uint8 |
ขึ้นอยู่กับฟีเจอร์ที่เปิดใช้:
|
แตกต่างกันไป | ต้องระบุหากตั้งค่าบิต 0 หรือ 1 ของ Flags |
| 11 - n | ข้อมูลเพิ่มเติม | แตกต่างกันไป | ไม่บังคับ | |
| n - 15 | ค่าแบบสุ่ม (Salt) | แตกต่างกันไป | บังคับ |
ตารางที่ 1.2.2: คำขอแบบดิบ (ประเภท 0x10) ถอดรหัสจากคำขอที่เข้ารหัส ใน ตารางที่ 1.1
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า |
|---|---|---|---|
| 0 | uint8 |
ประเภทของข้อความ | 0x01 = การตอบกลับการจับคู่ตามคีย์ |
| 1 - 6 | uint48 |
ที่อยู่สาธารณะ (BR/EDR) ของผู้ให้บริการ | แตกต่างกันไป |
| 7 - 15 | ค่าแบบสุ่ม (Salt) | แตกต่างกันไป |
ตารางที่ 1.3: คำตอบดิบ เข้ารหัสเพื่อสร้างการตอบกลับที่เข้ารหัสใน ตารางที่ 1.4
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า |
|---|---|---|---|
| 0 -15 | uint128 |
คำตอบที่เข้ารหัส | แตกต่างกันไป |
ตาราง 1.4: การตอบกลับที่เข้ารหัสซึ่งผู้ให้บริการส่งไปยังผู้ค้นหาผ่าน notify
ลักษณะ: พาสคีย์
ลักษณะนี้ใช้ในระหว่างขั้นตอน การจับคู่ตามคีย์
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า |
|---|---|---|---|
| 0-15 | uint128 |
บล็อกพาสคีย์ที่เข้ารหัส | แตกต่างกันไป |
ตารางที่ 2.1: บล็อกพาสคีย์ที่เข้ารหัส ดู ขั้นตอนการจับคู่ตามคีย์สำหรับการใช้งาน
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า |
|---|---|---|---|
| 0 | uint8 |
ประเภทของข้อความ | ข้อใดข้อหนึ่งต่อไปนี้
|
| 1 - 3 | unit32 |
พาสคีย์ 6 หลัก | แตกต่างกันไป |
| 4 - 15 | ค่าแบบสุ่ม (Salt) | แตกต่างกันไป |
ตารางที่ 2.2: บล็อกพาสคีย์โดยตรง เวอร์ชันที่ถอดรหัสแล้วของ ตาราง 2.1
ลักษณะ: คีย์บัญชี
หลังจากจับคู่แล้ว ตัวค้นหาการจับคู่ด่วนจะเขียนคีย์บัญชีไปยังผู้ให้บริการการจับคู่ด่วน
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า |
|---|---|---|---|
| 0-15 | uint128 |
คีย์บัญชี (เข้ารหัส) | แตกต่างกันไป |
เมื่อได้รับคำขอเขียน ผู้ให้บริการการจับคู่ด่วนจะต้องดำเนินการต่อไปนี้
- ถอดรหัสคีย์บัญชีโดยใช้ข้อมูลลับที่ใช้ร่วมกันซึ่งสร้างจากขั้นตอนที่ 4 ในกระบวนการ
- สำหรับผู้ให้บริการที่ต้องมีการผูกมัด (พบบ่อย) ให้ทำดังนี้
- ก่อนถอดรหัส ให้ตรวจสอบว่าใช้ข้อมูลลับที่ใช้ร่วมกันเพื่อถอดรหัสคำขอพาสคีย์จากขั้นตอนที่ 12 หากขั้นตอนนี้ไม่ผ่านโดยใช้ secret นี้ ให้ข้ามการเขียนนี้และออก
- ในขั้นตอนนี้ ระบบจะไม่ใช้ข้อมูลลับที่ใช้ร่วมกัน (K ในกระบวนการ) อีกสำหรับการจับคู่นี้ คำขอใดๆ ที่เข้ารหัสด้วยคีย์นี้ โดยไม่ต้องเริ่มกระบวนการใหม่ควรถูกปฏิเสธ
- สำหรับผู้ให้บริการที่ต้องมีการผูกมัด (พบบ่อย) ให้ทำดังนี้
- ตรวจสอบว่าค่าที่ถอดรหัสแล้วขึ้นต้นด้วย
0x04หรือ0xFFหากไม่ โปรดอย่าสนใจข้อความนี้และออก- หากค่าเป็น
0x04ให้ทำดังนี้- ตรวจสอบว่ารายการคีย์บัญชีที่บันทึกไว้มีพื้นที่สำหรับค่าใหม่หรือไม่
- หากไม่ ให้ลบค่าที่ใช้ล่าสุดออกจากรายการ
- เพิ่มค่าใหม่ลงในรายการ
- หากค่าเป็น
0xFFให้ทำดังนี้- ถือว่านี่เป็นเซสชันการจับคู่ชั่วคราวและไม่ต้องดำเนินการใดๆ
- ซึ่งอาจเกิดขึ้นได้ในขั้นตอนการเขียนคีย์บัญชีย้อนหลัง
- อย่าจัดเก็บคีย์และอย่าใช้คีย์ในรายการคีย์บัญชี การเข้ารหัส หรือการคำนวณ MAC
- การนำอุปกรณ์ออกจะเกิดขึ้นเมื่อมีเหตุการณ์หรือการหมดเวลาที่เฉพาะเจาะจงของฟีเจอร์ สำหรับการแชร์เสียง LE ขอแนะนำอย่างยิ่งให้นำการเชื่อมต่อ BLE และคีย์ลิงก์ออก 10 นาทีหลังจากเซสชันชั่วคราวถูกยกเลิกการเชื่อมต่อ
- หากค่าเป็น
ระบบจะใช้คีย์บัญชีในรายการระหว่างการจับคู่ตามคีย์
ลักษณะ: การแก้ไขเฟิร์มแวร์
ลักษณะนี้ช่วยให้ Seeker อ่านการแก้ไขเฟิร์มแวร์ของ Provider ได้ตามต้องการ โดยควรแสดงข้อมูลต่อไปนี้เสมอ
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า |
|---|---|---|---|
| 0 - var | utf8s |
รหัสการแก้ไขเฟิร์มแวร์ | แตกต่างกันไป |
โดยควรห่อหุ้มเป็นสตริง utf8 เดียวแม้ว่าจะมีเฟิร์มแวร์มากกว่า 1 รายการ (เช่น เฟิร์มแวร์ 3 รายการสำหรับหูฟังข้างซ้าย หูฟังข้างขวา และเคส) ในผู้ให้บริการ นอกจากนี้ ผู้ให้บริการยังส่งคืนสตริงที่เฉพาะเจาะจงสำหรับกรณีพิเศษได้ด้วย
status-updating: หากผู้ให้บริการกำลังอัปเดตเป็นเฟิร์มแวร์ใหม่ หรือผู้ให้บริการอาจแสดงเวอร์ชันของเฟิร์มแวร์ที่จัดเตรียมไว้
status-abnormal: หากผู้ให้บริการอยู่ในสถานะผิดปกติ เช่น ทำงานผิดปกติเนื่องจากอัปเดตเฟิร์มแวร์ไม่สำเร็จ ค่านี้จะทําให้ Seeker แสดงข้อความเพื่อแจ้งให้ผู้ใช้ทราบว่าต้องอัปเดตในตอนนี้
ผู้ให้บริการควรจำกัดการเข้าถึงลักษณะการแก้ไขเฟิร์มแวร์เพื่อ ป้องกันการติดตามอุปกรณ์ ข้อจำกัดที่แนะนำ
- อุปกรณ์ที่จับคู่ไว้ควรมีสิทธิ์เข้าถึงได้ทุกเมื่อ
- อุปกรณ์ใดก็ตามควรมีสิทธิ์เข้าถึงเมื่อค้นพบผู้ให้บริการ
ลักษณะ: ข้อมูลเพิ่มเติม
บริการนี้ต้องมีลักษณะต่อไปนี้
| ลักษณะของบริการจับคู่ด่วน | มีการเข้ารหัส | สิทธิ์ | UUID |
|---|---|---|---|
| ข้อมูล | ไม่ | เขียนและแจ้งเตือน | FE2C1237-8366-4814-8EB0-01DE32100BEA |
| ลักษณะบริการการจับคู่ด่วนเวอร์ชันเดิม (กำหนดเลิกใช้งานในวันที่ 1/1/2021) | มีการเข้ารหัส | สิทธิ์ | UUID |
|---|---|---|---|
| ข้อมูล | ไม่ | เขียนและแจ้งเตือน | 0x1237 |
ก่อนที่จะเขียนหรือแจ้งลักษณะนี้ จะต้องมีการ
แฮนด์เชคผ่านลักษณะ FE2C1234-8366-4814-8EB0-01DE32100BEA เพื่อให้มี
ข้อมูลลับที่ใช้ร่วมกัน ระบบจะใช้ AES-CTR เพื่อเข้ารหัสข้อมูลที่ไหลผ่านลักษณะนี้
ซึ่งมีการกำหนดอัลกอริทึมไว้ด้านล่าง โหมดนี้มีความปลอดภัยมากกว่า
ในข้อมูลที่ขยายออกไปนอกเหนือจากบล็อกขนาด 16 ไบต์เดียว HMAC-SHA256 จะ
ใช้เพื่อให้มั่นใจในความสมบูรณ์ของข้อมูล ซึ่งมีการกำหนดไว้ด้านล่างด้วย
| Octet | คำอธิบาย | ค่า |
|---|---|---|
| 0 - 7 | 8 ไบต์แรกของ HMAC-SHA256 | แตกต่างกันไป |
| 8 - 15 | Nonce ที่ใช้โดยการเข้ารหัส AES-CTR | แตกต่างกันไป |
| 16 - var | ข้อมูลที่เข้ารหัส | แตกต่างกันไป |
ตาราง 3.1: แพ็กเก็ตข้อมูลที่ผู้ให้บริการส่งไปยังผู้ค้นหาผ่าน การแจ้งเตือน หรือที่ผู้ค้นหาส่งไปยังผู้ให้บริการผ่านการเขียน
| Octet | ประเภทข้อมูล | คำอธิบาย | ค่า |
|---|---|---|---|
| 0 - var | byte array |
ข้อมูล | แตกต่างกัน ให้ถอดรหัสตามรหัสข้อมูลของตาราง 1.2.2:
|
ตารางที่ 3.2: ข้อมูลดิบ ถอดรหัสจากข้อมูลที่เข้ารหัสใน ตาราง 3.1
เมื่อมีการขอการแจ้งเตือน (เช่น ขอชื่อที่ปรับเปลี่ยนในแบบของคุณผ่านบิต 2 ในตาราง 1.2.1) ผู้ให้บริการจับคู่ด่วนจะต้องดำเนินการต่อไปนี้
- สร้าง Nonce แบบสุ่ม 8 ไบต์ที่เข้ารหัสลับ
เข้ารหัสข้อมูลโดยใช้ AES-CTR ซึ่งสร้างแต่ละบล็อกขนาด 16 ไบต์โดยใช้
encryptedBlock[i] = clearBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))ที่ไหน
- คีย์ AES คือข้อมูลลับที่ใช้ร่วมกันจากขั้นตอนที่ 4 ในกระบวนการ
- clearBlock[i] คือบล็อกขนาด 16 ไบต์ที่เริ่มต้นจาก data[i * 16] บล็อกสุดท้าย อาจมีขนาดน้อยกว่า 16 ไบต์
เรียกใช้ concat(encryptedBlock[0], encryptedBlock[1],...) เพื่อสร้าง ข้อมูลที่เข้ารหัส
สร้าง HMAC-SHA256 โดย
sha256(concat((K ^ opad), sha256(concat((K ^ ipad), concat(nonce, encrypted_data)))))ที่ไหน
- ระบบจะสร้าง K โดยใช้ concat(shared_secret, 48-byte ZEROs) โดย shared_secret มาจากขั้นตอนที่ 4 ในกระบวนการ
- opad คือการเพิ่มพื้นที่ว่างด้านนอก 64 ไบต์ ซึ่งประกอบด้วยไบต์ที่ซ้ำกันซึ่งมีค่า
0x5C - ipad คือการเว้นวรรคภายใน 64 ไบต์ ซึ่งประกอบด้วยไบต์ที่ซ้ำกันซึ่งมีค่า
0x36
ใช้ 8 ไบต์แรกจาก HMAC-SHA256 เป็นคำนำหน้าของ Data packet
เมื่อได้รับคำขอเขียน ผู้ให้บริการการจับคู่ด่วนจะต้องดำเนินการต่อไปนี้
- ยืนยันความสมบูรณ์ของข้อมูลโดยตรวจสอบ 8 ไบต์แรกของ HMAC-SHA256
ถอดรหัสข้อมูลที่เข้ารหัสโดยใช้ AES-CTR ซึ่งแต่ละบล็อกจะสร้างขึ้นโดยใช้
clearBlock[i] = encryptedBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))ที่ไหน
- encryptedBlock[i] คือบล็อกขนาด 16 ไบต์ที่เริ่มต้นจาก encrypted_data[i * 16] บล็อกสุดท้ายอาจมีขนาดน้อยกว่า 16 ไบต์
- สร้างหรือระบุคีย์ AES จากแฮนด์เชค เช่น
- ในขั้นตอนการตั้งชื่อ 1 จะมาจาก ECDH และจะไม่ ใช้สำหรับการจับคู่นี้อีก คำขอที่เข้ารหัส ด้วยคีย์นี้โดยไม่ได้รีสตาร์ทกระบวนการควรถูกปฏิเสธ
- ในขั้นตอนการตั้งชื่อ 2 จะเป็นคีย์บัญชี
เรียกใช้ concat(clearBlock[0], clearBlock[1],...) เพื่อสร้างข้อมูลดิบ