시커는 일반 BR/EDR 또는 BLE 연결 절차를 즉시 호출하는 대신 먼저 키 기반 페어링 특성에 관한 알림을 사용 설정한 후 표 1.1의 데이터를 여기에 씁니다.
빠른 페어링 탐색자의 쓰기 요청을 처리할 때 빠른 페어링 제공자는 다음을 실행해야 합니다.
선택적 공개 키 필드가 있는 경우:
기기가 페어링 모드가 아닌 경우 쓰기를 무시하고 종료합니다.
그렇지 않은 경우 다음 단계를 따릅니다.
수신된 공개 키(secp256r1 타원 곡선의 64바이트 지점), 사전 설치된 스푸핑 방지 비공개 키(secp256r1), 타원 곡선 디피-헬만(Elliptic-Curve Diffie-Hellman) 알고리즘을 사용하여 256비트 AES 키를 생성합니다.
SHA-256을 사용하여 256비트 AES 키를 해싱합니다.
결과의 처음 128비트를 가져옵니다. 이 키는 다음 단계에서 사용되는 스푸핑 방지 AES 키입니다.
AES-128을 사용하여 값 복호화를 시도합니다. 값이 단일 16바이트 AES 블록이므로 IV 또는 다중 블록 암호화 모드가 필요하지 않습니다.
사용할 키:
1단계에서 스푸핑 방지 AES 키를 생성한 경우 이 키를 사용합니다.
그렇지 않으면 유지된 계정 키 목록의 각 키를 사용해 보세요.
키가 값을 성공적으로 복호화하는 경우 이 작업을 중단하고 다음 단계로 진행합니다.
출력이 표 1.2.1 또는 표 1.2.2의 형식과 일치하면(즉, 빠른 페어링 제공업체의 현재 BLE 주소 또는 빠른 페어링 제공업체의 공개 주소가 포함된 경우) 값이 성공적으로 복호화됩니다.
참고: 패킷 끝에 솔트가 첨부되어 있습니다. 가능한 경우 이러한 솔트를 추적해야 하며, 제공업체가 이미 사용된 솔트가 포함된 요청을 받으면 요청을 무시하여 재생 공격을 방지해야 합니다.
솔트 추적의 대안으로, 쓰기에 제공자의 비공개 주소가 포함된 경우 재생 공격을 방지하는 또 다른 방법은 다음 키 기반 페어링 쓰기가 수락되기 전에 순환이 발생하도록 다음으로 확인 가능한 비공개 주소 순환 시간을 가져오는 것입니다.
값을 성공적으로 복호화할 수 있는 키가 없으면 쓰기를 무시하고 종료합니다.
이러한 실패 횟수를 기록합니다. 실패 횟수가 10에 도달하면 모든 새 요청이 즉시 실패합니다. 5분 후, 전원을 켠 후 또는 성공 후 실패 횟수를 재설정합니다.
그 외의 경우에는 성공 키를 K로 저장합니다. 이 K를 이 저전력 링크에서 수신한 패스키 및 맞춤설정된 이름 쓰기를 복호화하는 데 사용할 수 있다고 표시하되 다른 쓰기 또는 다른 링크에 대한 쓰기는 사용하지 않습니다. 페어링이 시작되지 않은 경우 타이머를 시작하여 10초 후에 K를 삭제합니다. 이 저전력 링크 연결이 해제되면 K도 삭제합니다.
표 1.3에 표시된 16바이트 원시 응답을 생성합니다. 유형과 제공자의 BR/EDR 주소를 연결하고 패킷의 나머지 부분을 임의 바이트 블록 (즉, 솔트)으로 채웁니다.
K로 원시 응답을 암호화하여 표 1.4에 표시된 16바이트 암호화 응답을 생성합니다. 키 기반 페어링 특성에 관한 알림을 통해 이를 전송합니다.
요청 플래그를 읽습니다.
요청의 플래그 바이트에 비트 2가 1로 설정된 경우 맞춤설정된 이름으로 추가 데이터 특성을 알립니다.
요청의 플래그 바이트에 비트 1이 1로 설정된 경우:
이는 탐색자가 제공자에게 8~13바이트로 표시되는 탐색자의 BR/EDR 주소와의 결합을 시작하도록 요청하고 있음을 나타냅니다.
탐색자의 BR/EDR 주소로 페어링 요청을 보냅니다. 페어링 요청은 아래 설명과 같이 해야 합니다 ('페어링 중' 단계).
필요한 이유: 제공자가 시작하도록 하면 일부 기기의 문제가 해결됩니다.
요청의 플래그 바이트에 비트 1이 0으로 설정된 경우:
페어링 요청을 위해 최대 10초 동안 기다립니다. 아무것도 수신되지 않으면 종료합니다.
이는 다른 주소(확인 가능한 비공개 주소가 아닌 탐색자의 공개 주소)의 BR/EDR 요청일 수 있습니다.
Google은 페어링 중에 요청 기기에서 K를 소유하고 있음을 다시 확인합니다.
페어링 중:
시커에서 페어링 요청/응답 패킷을 수신한 경우: 요청의 기기 기능이 NoInput/NoOutput인 경우 Just Works 페어링 방법을 사용하지 않도록 페어링을 종료합니다.
제공업체가 전송한 페어링 요청/응답 패킷의 경우 기기 기능 필드를 Display/YesNo로 설정하고 인증 요구사항을 MITM Protection Required로 설정합니다. 이렇게 하면 숫자 비교 페어링 방법 (Android에서 패스키 확인이라고도 함)이 트리거됩니다.
이를 사용하여 요청하는 기기가 실제로 빠른 페어링 시커이고 중간자(MITM)가 없는지 확인합니다. 예를 참고하세요.
필요한 이유: 대역 외 페어링 메서드가 더 적합할 수 있지만 플랫폼에서 원하는 모든 버전의 Android에서 이를 노출하지는 않습니다.
일반적으로 이 페어링 방법을 사용하면 사용자는 각 기기의 화면에 표시되는 패스키가 동일함을 확인합니다. 대신 이 페어링의 경우에만 신뢰할 수 있는 사전 공유 키로 암호화된 BLE를 통해 전송합니다.
이 접근 방식은 MITM 보호를 약간 손상시킬 수 있으므로 화면이나 키보드가 있는 기기에는 사용하면 안 됩니다.
따라서 현재 빠른 페어링은 현재 이러한 기기 유형을 지원하지 않습니다.
패스키가 작성되지 않고 10초 타이머가 만료되면 K를 삭제합니다.
값이 패스키 특성에 기록되는 경우 암호화된 패스키 블록입니다. K로 복호화하여 특성: 패스키>표 2.2 - (유형 = Seeker's Passkey)에 표시된 형식으로 원시 패스키 블록을 생성합니다.
복호화에 실패하면 쓰기를 무시하고 K를 삭제합니다.
그 외의 경우에는 원시 패스키 블록에 6자리 패스키 PSeeker가 포함되며 이는 Seeker가 예상하는 패스키입니다.
PSeeker를 Google의 예상 패스키인 PProvider와 비교합니다.
값이 같으면 확인 내용에 '예'라고 답하세요.
그렇지 않으면 확인 메시지에 '아니요'라고 회신하면 페어링에 실패합니다.
페어링 실패 여부와 관계없이 특성: 패스키>표 2.2에 표시된 형식으로 다른 원시 패스키 블록을 생성하고 여기에는 자체 예상 패스키인 PProvider가 포함됩니다.
블록의 유형이 올바른지 확인합니다 (제공업체의 패스키, 표 참조).
참고: Seeker로부터 받은 패스키 블록의 솔트를 재사용하지 마세요. 새로운 임의의 값을 생성합니다.
K로 원시 패스키 블록을 암호화하고 패스키 특성에 관한 알림을 통해 결과로 얻은 암호화된 패스키 블록을 전송합니다.
탐색자가 올바른 패스키 P를 수신하여 복호화하면 탐색자도 확인 메시지에 '예'라고 응답하고 페어링에 성공합니다.
페어링에 성공하면 K를 이 저전력 링크의 계정 키 쓰기를 복호화하는 데 사용할 수 있는 것으로 표시합니다. 단, 후속 패스키 쓰기나 다른 링크에 대한 쓰기에는 사용할 수 없습니다. 10초 후 K를 삭제하도록 타이머를 시작합니다. 또한 계정 키 작성 시도 후, 그리고 4단계에 따라 저전력 링크 연결이 끊어지면 K를 삭제합니다.
페어링에 실패하면 K를 삭제합니다.
기기 기능 필드를 기본 I/O 기능과 인증 요구사항으로 다시 전환하여 새 페어링이 예상대로 계속 진행되도록 합니다.
결합이 필요하지 않은 제공자의 경우 Seeker가 제공업체에 페어링 요청을 전송하지 않습니다. 즉, 8단계 - 17단계를 건너뜁니다. 또한 'K'는 계정 키 특성에서 사용됩니다.
예
예 1: 페어링 시도 성공(중간자 아님)예 2: 중간자를 사용하여 페어링 시도에 실패했습니다.
[null,null,["최종 업데이트: 2025-08-13(UTC)"],[[["\u003cp\u003eFast Pair utilizes BLE for initial key exchange and then triggers BR/EDR pairing for secure connection.\u003c/p\u003e\n"],["\u003cp\u003eThe Provider verifies the Seeker's authenticity using encryption, a shared secret, and a numeric comparison pairing method.\u003c/p\u003e\n"],["\u003cp\u003eAccount Keys are exchanged securely after successful pairing to enable seamless future connections.\u003c/p\u003e\n"],["\u003cp\u003eThe process includes anti-spoofing measures like public key cryptography and salt tracking to enhance security.\u003c/p\u003e\n"],["\u003cp\u003eThe Provider initiates the BR/EDR pairing to address compatibility issues with certain devices.\u003c/p\u003e\n"]]],[],null,["Fast Pair Procedure\n-------------------\n\n### Procedure\n\n| **Note:** Google recommends implementing the [Cryptographic Test Cases](/nearby/fast-pair/specifications/appendix/cryptotestcases \"Link to the Cryptographic Test Cases.\") to ease verification of these requirements.\n\nInstead of immediately invoking any of the normal BR/EDR or BLE bonding\nprocedures, the Seeker first enables Notifications on the Key-based Pairing\ncharacteristic, and then writes the data in [Table 1.1](/nearby/fast-pair/specifications/characteristics#table1.1 \"table 1.1\") to it.\n\nWhen handling a write request from a Fast Pair Seeker, the Fast Pair Provider\nshall do the following:\n\n1. If the optional Public Key field **is present** :\n 1. If the device is not in pairing mode, ignore the write and exit.\n 2. Otherwise:\n 1. Use the received Public Key (a 64-byte point on the secp256r1 elliptic curve), the pre-installed [Anti-Spoofing Private Key](/nearby/fast-pair/specifications/configuration#antispoofing \"Anti-Spoofing\") - also secp256r1, and the Elliptic-Curve Diffie-Hellman algorithm to generate a 256-bit AES key.\n 2. Use SHA-256 to hash the 256-bit AES key.\n 3. Take the first 128 bits of the result. This is the Anti-Spoofing AES Key, used in the next step.\n2. Using AES-128, attempt to decrypt the value. Since the value is a single\n 16-byte AES block, no IV or multi-block cipher mode is necessary.\n\n 1. Which key to use:\n 1. If an Anti-Spoofing AES Key was generated in step 1, use that key.\n 2. Otherwise, try each key in the persisted Account Key List.\n 2. If a key successfully decrypts the value, break, and continue to the next step.\n 3. The value is decrypted successfully if the output matches the format in\n [Table 1.2.1](/nearby/fast-pair/specifications/characteristics#table1.2.1 \"table 1.2.1\") or [Table 1.2.2](/nearby/fast-pair/specifications/characteristics#table1.2.2 \"table 1.2.2\") - (that is, if it\n contains either the Fast Pair Provider's current BLE address, or the Fast\n Pair Provider's public address).\n\n NOTE: At the end of the packet there is a salt attached. When\n possible, these salts should be tracked, and if the Provider receives a\n request containing an already used salt, the request should be ignored to\n prevent replay attacks.\n 4. As an alternative to tracking salts, if the write includes the Provider's\n private address, another way to prevent replay attacks is to bring\n forward the time of the next resolvable private address rotation so that\n the rotation occurs before the next Key-based Pairing write will be\n accepted.\n\n3. If no key could successfully decrypt the value, ignore the write and exit.\n\n 1. Keep a count of these failures. **When the failure count hits 10, fail\n all new requests immediately. Reset the failure count after 5 minutes,\n after power on, or after a success.**\n4. Otherwise, save the successful key as *K* . Mark this *K* as usable for\n decrypting Passkey and Personalized name writes received on this LE link, but\n not other writes nor any writes on any other link. Start a timer to discard\n *K* after 10 seconds if pairing has not been started. Also discard *K* if\n this LE link disconnects.\n\n5. Produce the 16-byte Raw Response shown in [Table 1.3](/nearby/fast-pair/specifications/characteristics#table1.3 \"table 1.3\"), by\n concatenating the type and the Provider's BR/EDR address, and then filling\n the remainder of the packet with a block of random bytes (that is, a salt).\n\n6. Encrypt the Raw Response with K to produce the 16-byte Encrypted Response\n shown in [Table 1.4](/nearby/fast-pair/specifications/characteristics#table1.4 \"table 1.4\"). Send this via a notify on the Key-based Pairing\n characteristic.\n\n7. Read the request flag:\n\n 1. **If the Request's Flags byte has bit 2 set to 1** , notify [Additional Data characteristic](/nearby/fast-pair/specifications/characteristics#AdditionalData \"Characteristic - Additional Data\") with personalized name.\n 2. **If the Request's Flags byte has bit 1 set to 1:**\n 1. This indicates that the Seeker is requesting the Provider to initiate bonding to the Seeker's BR/EDR address, which is present in bytes 8-13.\n 2. Send a pairing request to the Seeker's BR/EDR address. The pairing request must be as described below (\"During pairing\" step).\n 3. Reason this is needed: Having the Provider initiate works around an issue on some devices.\n 3. **If the Request's Flags byte has bit 1 set to 0:**\n 1. Wait up to 10 seconds for a pairing request. If none is received, exit.\n 2. Note that this might be a BR/EDR request, from a different address (the Seeker's public address, instead of its resolvable private address). We will re-verify during pairing that the requesting device is in possession of *K*.\n8. During pairing:\n\n 1. When a **pairing request/response packet** is received from the Seeker: If the Device Capabilities in the request are NoInput/NoOutput, end pairing, to avoid using the Just Works pairing method.\n 2. For the pairing request/response packet sent by the Provider: Set the Device Capabilities field to **Display/YesNo** and set Authentication Requirements to **MITM Protection Required** . This triggers the Numeric Comparison pairing method (also known as [Passkey Confirmation](https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#PAIRING_VARIANT_PASSKEY_CONFIRMATION) on Android). We rely on this to confirm that the requesting device is in fact the Fast Pair Seeker, and that there is no man-in-the-middle. See [examples](#ProcedureExamples).\n 3. Reason this is needed: The Out-of-Band pairing method would be a better fit, but the platform does not expose it on all desired versions of Android.\n9. When **confirmation of the passkey is needed** , wait up to 10 seconds for a\n write to the [Passkey characteristic](/nearby/fast-pair/specifications/characteristics#Passkey \"passkey\").\n\n 1. Normally, with this pairing method, the user would confirm that the passkeys displayed on each device's screen are identical. Instead, only for this pairing, we transfer them over BLE, encrypted with the trusted pre-shared key.\n 2. Note that this approach should not be taken for devices that have a screen or a keyboard as it makes a slight compromise on MITM protection. Fast Pair currently does not support those device types yet because of this.\n 3. If the 10 second timer expires without a passkey being written, then discard *K*.\n10. When a **value is written to the Passkey characteristic** , this is the\n Encrypted Passkey Block. Decrypt it with K to yield a Raw Passkey Block, with\n format shown in [Characteristic: Passkey](/nearby/fast-pair/specifications/characteristics#Passkey \"passkey\") *\\\u003e* [Table 2.2](/nearby/fast-pair/specifications/characteristics#table2.2 \"table 2.2\") - (type =\n Seeker's Passkey).\n\n11. If decryption fails, ignore the write and discard *K*.\n\n12. Otherwise, the Raw Passkey Block contains a 6-digit passkey\n *P~Seeker~*, which is the passkey that the Seeker expects.\n\n13. Compare *P~Seeker~* with our own expected passkey,\n *P~Provider~*.\n\n 1. If the values are equal, reply \"yes\" to the confirmation.\n 2. Otherwise, reply \"no\" to the confirmation, causing pairing to fail.\n14. Regardless of whether pairing failed, produce another Raw Passkey Block, with\n format shown in [Characteristic: Passkey](/nearby/fast-pair/specifications/characteristics#Passkey \"passkey\") *\\\u003e* [Table 2.2](/nearby/fast-pair/specifications/characteristics#table2.2 \"table 2.2\"),\n containing our own expected passkey, *P~Provider~*.\n\n 1. Ensure the block has the correct type (Provider's Passkey; see table). NOTE: Do not reuse the salt from the Passkey Block received from the Seeker. Generate a new random value.\n15. Encrypt the Raw Passkey Block with *K*, and send the resulting Encrypted\n Passkey Block via a notify on the Passkey characteristic.\n\n16. If the Seeker receives and decrypts the correct passkey *P*, the Seeker will\n also reply \"yes\" to the confirmation, and pairing will succeed.\n\n 1. If the pairing succeeds, then mark *K* as usable for decrypting Account Key writes on this LE link, but not for any subsequent Passkey writes nor any writes on any other link. Start a timer to discard *K* after 10 seconds. Also discard *K* following any attempt to write an Account Key and, as per step 4, if the LE link disconnects.\n 2. If the pairing fails, discard *K*.\n17. Switch the device capabilities field back to default I/O capabilities and\n Authentication Requirements to default so that new\n pairings continue as expected.\n\nNote that for Providers that don't require bonding, the Seeker does not send a\npairing request to the Provider, that is step 8 - step 17 are skipped. Also,\n\"K\" is used in [Account Key characteristic](/nearby/fast-pair/specifications/characteristics#AccountKey \"Account Key\").\n\n##### Examples\n\n***Example 1:** Successful pairing attempt\n(no man-in-the-middle).* ***Example 2:** Failed pairing attempt, with a\nman-in-the-middle.*"]]