특성
빠른 페어링 서비스
빠른 페어링 제공자는 다음 GATT 서비스를 보유해야 합니다.
| 서비스 | UUID |
|---|---|
| 빠른 페어링 서비스 | 0xFE2C |
이 서비스는 다음 특징을 가져야 합니다.
| 빠른 페어링 서비스 특성 | 암호화됨 | 권한 | UUID |
|---|---|---|---|
| 모델 ID | 아니요 | 읽기 | FE2C1233-8366-4814-8EB0-01DE32100BEA |
| 키 기반 페어링 | 아니요 | 작성 및 알림 | FE2C1234-8366-4814-8EB0-01DE32100BEA |
| 패스키 | 아니요 | 작성 및 알림 | FE2C1235-8366-4814-8EB0-01DE32100BEA |
| 계정 키 | 아니요 | 쓰기 | FE2C1236-8366-4814-8EB0-01DE32100BEA |
기기 정보 서비스
빠른 페어링 제공자는 기기 정보 서비스도 지원해야 합니다.
| 서비스 | UUID |
|---|---|
| 기기 정보 서비스 | 0x180A |
빠른 페어링 탐색기는 다음 특성을 사용합니다.
| 이름 | 암호화됨 | 권한 | UUID |
|---|---|---|---|
| 펌웨어 버전 | 아니요 | 읽기 | 0x2A26 |
특성: 모델 ID
이 특성을 사용하면 탐색기가 기기가 검색 가능 모드로 광고하는 경우를 제외하고 필요에 따라 모델 ID를 읽을 수 있습니다. 항상 다음 데이터를 반환해야 합니다.
| 옥텟 | 데이터 유형 | 설명 | 값 |
|---|---|---|---|
| 0~2 | uint24 |
모델 ID | 다양한 가격 |
특성: 키 기반 페어링
이 특성은 키 기반 페어링 절차를 제어합니다. 이 절차에서는 시커와 제공자가 모두 사전 공유 키를 보유하고 있는지 확인하여 특정 수준의 신뢰를 설정합니다. 각 사례에서 키가 다릅니다.
케이스 1: 사전 공유 키는 스푸핑 방지 공개/비공개 키 쌍과 각 페어링 시도마다 변경되는 시커의 자체 공개/비공개 키 쌍을 기반으로 합니다.
- 제공업체가 페어링 모드입니다.
- 시커는 제공자가 스푸핑 방지 비공개 키를 보유하고 있는지 확인합니다.
페어링 모드에 있는 경우 공급자는 빠른 페어링의 키 기반 페어링을 지원하지 않는 기기와 페어링하는 등 일반적인 방식으로 페어링할 수도 있습니다.
케이스 2: 사전 공유 키가 계정 키 중 하나입니다.
- 제공업체는 일반적으로 페어링 모드가 아닙니다. (하지만 이는 요구사항이 아닙니다. 제공업체는 페어링 모드에 있는 경우에도 계정 키 사용을 지원해야 합니다.)
- 시커와 제공자는 서로 계정 키를 소유하고 있는지 확인합니다.
두 사례는 사용되는 사전 공유 키를 제외하고 매우 유사하므로 절차에서 결합됩니다.
데이터 형식
각 형식이 사용되는 방식은 절차를 참고하세요.
| 옥텟 | 데이터 유형 | 설명 | 값 | 필수 여부 |
|---|---|---|---|---|
| 0~15 | uint128 |
암호화된 요청 | 다양한 가격 | 필수 |
| 16~79 | 공개 키 | 다양한 가격 | 선택사항 |
표 1.1: 암호화된 요청, 탐색기가 특성에 작성
| 옥텟 | 데이터 유형 | 설명 | 값 | 필수 여부 |
|---|---|---|---|---|
| 0 | uint8 |
메시지 유형 | 0x00 = 키 기반 페어링 요청 |
필수 |
| 1 | uint8 |
플래그
|
다름 | 필수 |
| 2~7 | uint48 |
다음 중 하나를 충족해야 합니다.
|
다름 | 필수 |
| 8~13 | uint48 |
탐색기의 BR/EDR 주소 | 다름 | 플래그 비트 1 또는 3이 설정된 경우에만 표시됩니다. |
| n - 15 | 임의 값 (솔트) | 다름 | 필수 |
표 1.2.1: 원시 요청 (유형 0x00) 표 1.1의 암호화된 요청에서 복호화되었습니다.
| 옥텟 | 데이터 유형 | 설명 | 값 | 필수 여부 |
|---|---|---|---|---|
| 0 | uint8 |
메시지 유형 | 0x10 = 작업 요청 |
필수 |
| 1 | uint8 |
플래그 | 다름 | 필수 |
| 2~7 | uint48 |
다음 중 하나를 충족해야 합니다.
|
다름 | 필수 |
| 8 | uint8 |
그룹에 메시지 보내기 | 다름 | 플래그 비트 0이 설정된 경우 필수 |
| 9 | uint8 |
메시지 코드 | 다름 | 플래그 비트 0이 설정된 경우 필수 |
| 10 | uint8 |
플래그에 따라 다름:
|
다름 | 플래그 비트 0 또는 1이 설정된 경우 필수 |
| 11 - n | 추가 데이터 | 다름 | 선택사항 | |
| n - 15 | 임의 값 (솔트) | 다름 | 필수 |
표 1.2.2: 원시 요청 (유형 0x10) 표 1.1의 암호화된 요청에서 복호화되었습니다.
| 옥텟 | 데이터 유형 | 설명 | 값 |
|---|---|---|---|
| 0 | uint8 |
메시지 유형 | 0x01 = 키 기반 페어링 응답 |
| 1~6 | uint48 |
제공업체의 공개 (BR/EDR) 주소 | 다름 |
| 7~15 | 임의 값 (솔트) | 다름 |
표 1.3: 원시 응답 암호화되어 표 1.4에 암호화된 응답을 생성합니다.
| 옥텟 | 데이터 유형 | 설명 | 값 |
|---|---|---|---|
| 0~15 | uint128 |
암호화된 응답 | 다름 |
표 1.4: 알림을 통해 제공자가 요청자에게 전송하는 암호화된 응답
특성: 패스키
| 옥텟 | 데이터 유형 | 설명 | 값 |
|---|---|---|---|
| 0~15 | uint128 |
암호화된 패스키 블록 | 다름 |
표 2.1: 암호화된 패스키 블록 사용에 관한 내용은 키 기반 페어링 절차를 참고하세요.
| 옥텟 | 데이터 유형 | 설명 | 값 |
|---|---|---|---|
| 0 | uint8 |
메시지 유형 | 다음 중 하나:
|
| 1~3 | unit32 |
6자리 패스키 | 다름 |
| 4~15 | 임의 값 (솔트) | 다름 |
표 2.2: 원시 패스키 블록 표 2.1의 복호화된 버전
특성: 계정 키
페어링 후 빠른 페어링 탐색기는 계정 키를 빠른 페어링 제공업체에 씁니다.
| 옥텟 | 데이터 유형 | 설명 | 값 |
|---|---|---|---|
| 0~15 | uint128 |
계정 키 (암호화됨) | 다름 |
쓰기 요청을 받으면 빠른 페어링 제공자는 다음을 실행해야 합니다.
- 절차의 4단계에서 생성된 공유 비밀번호를 사용하여 계정 키를 복호화합니다.
- 결합이 필요한 제공업체 (일반적)의 경우:
- 복호화하기 전에 공유 비밀번호가 12단계의 패스키 요청을 복호화하는 데 사용되었는지 확인합니다. 이 단계가 이 시크릿을 사용하여 통과되지 않은 경우 이 쓰기를 무시하고 종료합니다.
- 이 시점에서 공유 비밀 (절차의 K)은 이 페어링에 다시 사용되지 않습니다. 절차를 다시 시작하지 않고 이 키로 암호화된 요청은 거부해야 합니다.
- 결합이 필요한 제공업체 (일반적)의 경우:
- 복호화된 값이
0x04또는0xFF로 시작하는지 확인합니다. 그렇지 않으면 이 쓰기를 무시하고 종료합니다.- 값이
0x04인 경우:- 영구 저장된 계정 키 목록에 새 값을 위한 공간이 있는지 확인합니다.
- 그렇지 않으면 목록에서 가장 오래전에 사용된 값을 삭제합니다.
- 목록에 새 값을 추가합니다.
- 값이
0xFF인 경우:- 이를 임시 페어링 세션으로 처리하고 작업을 실행하지 않습니다.
- 이 문제는 소급하여 계정 키 쓰기 흐름에서 발생할 수 있습니다.
- 키를 저장하지 않고 계정 키 목록, 암호화 또는 MAC 계산에 사용하지 않습니다.
- 결합 삭제는 기능별 이벤트 또는 시간 초과에 의해 트리거됩니다. LE 오디오 공유의 경우 임시 세션 연결이 해제된 후 10분 후에 BLE 결합 및 링크 키를 삭제하는 것이 좋습니다.
- 값이
목록의 계정 키는 키 기반 페어링 중에 사용됩니다.
특성: 펌웨어 버전
이 특성을 통해 시커는 필요에 따라 제공자의 펌웨어 버전을 읽을 수 있습니다. 항상 다음 데이터를 반환해야 합니다.
| 옥텟 | 데이터 유형 | 설명 | 값 |
|---|---|---|---|
| 0 - var | utf8s |
펌웨어 버전 코드 | 다름 |
제공자에 펌웨어가 두 개 이상 (예: 왼쪽 이어폰, 오른쪽 이어폰, 케이스용 펌웨어 3개) 있는 경우에도 단일 utf8 문자열로 캡슐화해야 합니다. 공급자는 특수한 경우에 특정 문자열을 반환할 수도 있습니다.
status-updating: 프로바이더가 현재 새 펌웨어로 업데이트하는 경우 또는 제공업체는 스테이징된 펌웨어 버전을 반환할 수 있습니다.
status-abnormal: 제공업체가 비정상 상태인 경우 예를 들어 펌웨어 업데이트가 실패하여 오작동했습니다. 이 값은 시커가 사용자에게 지금 업데이트해야 한다는 메시지를 표시하도록 합니다.
제공자는 기기 추적을 방지하기 위해 펌웨어 버전 특성에 대한 액세스를 제한해야 합니다. 추천 제한사항:
- 결합된 기기는 언제든지 액세스할 수 있어야 합니다.
- 공급자를 검색할 수 있는 경우 모든 기기에서 액세스할 수 있어야 합니다.
특성: 추가 데이터
이 서비스는 다음과 같은 특징이 있어야 합니다.
| 빠른 페어링 서비스 특성 | 암호화됨 | 권한 | UUID |
|---|---|---|---|
| 데이터 | 아니요 | 작성 및 알림 | FE2C1237-8366-4814-8EB0-01DE32100BEA |
| 이전 빠른 페어링 서비스 특성 (2021년 1월 1일에 지원 중단 예정) | 암호화됨 | 권한 | UUID |
|---|---|---|---|
| 데이터 | 아니요 | 작성 및 알림 | 0x1237 |
이 특성에 쓰거나 알리기 전에 특성 FE2C1234-8366-4814-8EB0-01DE32100BEA를 통해 핸드셰이크가 있어야 공유 비밀번호가 있습니다. AES-CTR은 이 특성을 통해 흐르는 데이터를 암호화하는 데 사용되며, 알고리즘은 아래에 정의되어 있습니다. 이 모드는 단일 16바이트 블록을 초과하는 데이터에서 더 안전합니다. 데이터 무결성을 보장하기 위해 HMAC-SHA256이 사용됩니다. 이는 아래에도 정의되어 있습니다.
| 옥텟 | 설명 | 값 |
|---|---|---|
| 0 - 7 | HMAC-SHA256의 처음 8바이트입니다. | 다름 |
| 8~15 | AES-CTR 암호화에 사용되는 nonce입니다. | 다름 |
| 16 - var | 암호화된 데이터입니다. | 다름 |
표 3.1: 알림을 통해 제공자가 탐색기에 전송하거나 쓰기를 통해 탐색기가 제공자에 전송하는 데이터 패킷
| 옥텟 | 데이터 유형 | 설명 | 값 |
|---|---|---|---|
| 0 - var | byte array |
데이터 | 다름인 경우 표 1.2.2의 데이터 ID에 따라 디코딩합니다.
|
표 3.2: 원시 데이터 표 3.1의 암호화된 데이터에서 복호화되었습니다.
알림이 요청되면 (예: 표 1.2.1의 비트 2를 통해 맞춤 이름 요청) 빠른 페어링 제공자는 다음을 실행해야 합니다.
- Nonce의 암호화 방식으로 무작위 8바이트를 생성합니다.
AES-CTR을 사용하여 데이터를 암호화합니다. 여기서 각 16바이트 블록은 다음을 사용하여 생성됩니다.
encryptedBlock[i] = clearBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))어디서
- AES 키는 절차의 4단계에 나오는 공유 비밀번호입니다.
- clearBlock[i] 는 data[i * 16]에서 시작하는 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바이트 0)으로 생성되고 shared_secret은 절차의 4단계에서 가져옵니다.
- opad는 64바이트 외부 패딩으로,
0x5C값이 지정된 반복 바이트로 구성됩니다. - ipad는
0x36값이 반복되는 바이트로 구성된 64바이트 내부 패딩입니다.
HMAC-SHA256에서 처음 8바이트를 데이터 패킷의 접두사로 사용합니다.
쓰기 요청을 받으면 빠른 페어링 제공자는 다음을 실행해야 합니다.
- HMAC-SHA256의 처음 8바이트를 확인하여 데이터의 무결성을 확인합니다.
AES-CTR을 사용하여 암호화된 데이터를 복호화합니다. 각 블록은 다음을 사용하여 생성됩니다.
clearBlock[i] = encryptedBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))어디서
- encryptedBlock[i] 는 encrypted_data[i * 16]에서 시작하는 16바이트 블록입니다. 마지막 블록은 16바이트 미만일 수 있습니다.
- AES 키는 핸드셰이크에서 생성되거나 식별됩니다(예:
- 명명 흐름 1에서는 ECDH에서 가져오며 이 페어링에 다시 사용되지 않습니다. 절차를 다시 시작하지 않고 이 키로 암호화된 요청은 거부해야 합니다.
- 이름 지정 흐름 2에서는 계정 키입니다.
concat(clearBlock[0], clearBlock[1],…)을 실행하여 원시 데이터를 만듭니다.