11.13. 페어링 및 본딩¶
여기까지 다룬 모든 것은 바이트를 암호화되지 않은 상태로 무선을 통해 전송합니다. 같은 방에 BLE 지원 노트북을 가진 사람이라면 누구나 광고 채널을 도청하고, 열린 연결의 호핑 시퀀스를 따라가며, 오가는 모든 읽기, 쓰기, 알림을 읽어낼 수 있습니다. 대부분의 공개 센서 데이터(배터리 잔량, 주변 온도)에는 이것이 괜찮습니다. 하지만 두 엔드포인트가 비공개로 유지하고자 하는 것 – 릴레이를 작동시키는 제어 레지스터, 비밀번호, 널리 방송되어서는 안 되는 측정값 – 의 경우 링크가 암호화되어야 하며, 이상적으로는 카메라가 자신이 누구와 통신하고 있는지 알아야 합니다.
BLE는 페어링(pairing) 과 본딩(bonding) 을 통해 이 두 가지를 모두 제공합니다.
11.13.1. 페어링, 본딩, 암호화¶
밀접하게 관련된 세 가지 개념:
암호화(Encryption) 가 궁극적인 목표입니다. 일단 링크가 암호화되면 데이터 채널의 모든 패킷은 두 엔드포인트만 해독할 수 있으며, 도청자에게는 잡음으로만 보입니다.
페어링(Pairing) 은 두 엔드포인트가 암호화에 사용할 키에 합의하기 위해 실행하는 절차입니다. 이는 일회성 교환으로, 링크 계층이 암호화 엔진에 입력하는 공유 키 자료를 생성합니다.
본딩(Bonding) 은 페어링이 끝난 후 키를 비휘발성 저장소에 영구 저장하기로 하는 선택으로, 동일한 두 장치 간의 다음 연결에서는 페어링을 건너뛰고 곧바로 암호화로 진행하도록 합니다.
쉽게 말해 페어링은 “서로 소개하기”, 본딩은 “이 소개를 기억하기”, 암호화는 “지금부터 비공개로 대화하기”입니다.
열린 BLE 연결 위에서 진행되는 페어링 흐름. 키 교환이 완료되면 링크 계층은 이후의 모든 패킷을 암호화합니다. 본딩은 키를 플래시에 기록하는 추가 단계입니다.¶
11.13.2. LE Secure Connections¶
BLE가 사용하는 최신 키 교환 방식은 LE Secure Connections 로, Elliptic Curve Diffie-Hellman을 기반으로 합니다. 양측은 임시 키 쌍을 생성하고 공개 절반을 교환한 다음, 그 결과를 자신의 개인 키와 결합하여 동일한 공유 비밀에 도달합니다. 이 비밀은 도청자가 교환 전체를 기록하더라도 계산할 수 없습니다.
구형 LE Legacy 방식은 덜 안전하며(전체 교환을 확보한 도청자는 보통 키를 복구할 수 있습니다) 오래된 peripheral과의 하위 호환성을 위해서만 존재합니다. aioble 의 기본값은 최신 방식(le_secure=True)이므로 그대로 두십시오.
11.13.3. 페어링 시작하기¶
central은 이미 열려 있는 연결에서 aioble.DeviceConnection.pair() 를 호출하여 페어링합니다:
async with await device.connect() as connection:
await connection.pair(bond=True, le_secure=True, mitm=False)
# ... GATT work, now over an encrypted link ...
pair 가 반환된 후에는 연결의 encrypted, authenticated, bonded, key_size 속성이 협상된 내용을 반영합니다.
가장 유용한 네 가지 키워드 인수:
bond=True– 결과 키를 플래시에 저장하여 동일한 두 장치 간의 다음 연결에서 페어링 핸드셰이크를 건너뛰도록 합니다. 기본값은True입니다.le_secure=True– LE Secure Connections를 사용합니다. 기본값은True입니다. 켜진 상태로 두십시오.mitm=False– 중간자(man-in-the-middle) 보호를 요구할지 여부입니다. 이를 위해서는 대역 외 채널(한쪽에 표시되고 다른 쪽에서 확인하는 숫자 코드, 입력되는 패스키 등)이 필요하며, 이를 통해 사용자는 페어링 핸드셰이크에 참여한 두 장치가 실제로 자신이 생각하는 장치인지 확인할 수 있습니다. 기본값은False입니다(MITM 보호 없음 – 수동적 도청자는 링크를 읽을 수 없지만, 연결을 능동적으로 가로채는 공격자는 자신을 페어링에 끼워 넣을 수 있습니다). 민감한 것이라면True로 설정하되, peripheral이 실제로 IO 기능을 지원해야 한다는 점에 유의하십시오.io=3– 장치가 주장하는 IO 기능입니다. Bluetooth 사양은 다섯 가지를 정의합니다:0디스플레이만,1디스플레이 + 예/아니오,2키보드만,3입력도 출력도 없음,4키보드 + 디스플레이. UI가 없는 카메라는 일반적으로3을 보고하며, 카메라 자체에 디스플레이가 있다면 애플리케이션이 숫자 확인을 표시하고1을 사용할 수 있습니다. 양측의 IO 기능 조합이 실제 MITM 보호가 가능한지를 결정합니다.
peripheral은 pair 를 직접 호출하지 않으며, central이 시작하는 것에 응답할 뿐입니다. 특정 characteristic에 암호화가 필요한지는 GATT 데이터베이스에서 그것이 어떻게 선언되었는지에 따른 속성입니다. 암호화 필수 액세스 비트는 저수준 bluetooth API의 일부이며 현재 aioble characteristic 생성자를 통해 노출되지 않습니다.
11.13.4. 본딩 – 그리고 키가 저장되는 위치¶
bond=True 일 때 aioble 은 로컬 파일 시스템의 JSON 파일에 키를 기록합니다. 기본 파일명은 ble_secrets.json 이며 현재 작업 디렉터리를 기준으로 기록됩니다. 갓 부팅된 캠에서는 _boot.py 가 이미 해당 디렉터리를 선택해 두었습니다: 카드가 마운트되어 있으면 /sdcard, 그렇지 않으면 /flash 이므로, 파일은 /sdcard/ble_secrets.json 또는 /flash/ble_secrets.json 에 저장됩니다. 이 파일은 본딩된 피어가 다음에 다시 연결할 때 링크를 재암호화하는 데 필요한 항목들을 보유하며, 여기에는 피어의 신원 주소가 포함됩니다.
유념해야 할 한 가지 비대칭성: 키가 변경될 때 저장 은 자동으로 일어나지만, 다음 부팅 시 파일을 불러오는 것은 그렇지 않습니다. 이전에 본딩된 피어가 인식되도록 시작 시(페어링이나 광고를 시작하기 전에) aioble.security.load_secrets() 를 한 번 호출하십시오:
import aioble
aioble.security.load_secrets() # default path: ble_secrets.json
그 후에는 본딩된 피어가 다음에 나타날 때 aioble 이 저장된 키를 재사용하며, 추가 핸드셰이크 없이 링크가 암호화됩니다.
키를 플래시에 저장하는 데 따르는 두 가지 실질적 결과:
장치 잊기.
ble_secrets.json을 삭제하거나(또는 해당 항목을 제거하여) 모든 본딩된 피어를 잊은 다음, 처음부터 다시 페어링하십시오.물리적 접근은 키를 노출시킵니다. 카메라의 파일 시스템에 접근할 수 있는 사람은 누구나 그 JSON을 읽을 수 있습니다. 이는 TLS 키와 관련하여 네트워킹 측면에서 등장했던 제약과 같은 종류입니다(운영: 키, 만료, 그리고 문제 해결): 장치별 키를 사용하고, 저장된 모든 키는 복구 가능한 것으로 취급하며, 키가 비밀로 유지되는 것이 아니라 폐기할 수 있는 능력(여기서는 central 측에서 본드를 제거하는 것)에 의존하십시오.
11.13.5. 암호화가 보장하는 것 – 그리고 보장하지 않는 것¶
페어링 후 암호화하는 링크는 강도가 높은 순서로 다음을 제공합니다:
기밀성(Confidentiality). 항상. 도청자는 바이트를 읽을 수 없습니다.
무결성(Integrity). 항상. 수정된 패킷은 링크 계층의 인증된 암호화 검사를 통과하지 못하고 폐기됩니다.
인증(Authentication).
mitm=True와 충분한 IO 기능이 있을 때만 가능합니다. 그것이 없으면, 원래의 페어링 교환을 가로챈 중간자가 자신을 끼워 넣었을 수 있으며, MITM 보호가 없으면 양측이 이를 알 방법이 없습니다.
대부분의 카메라 사용 사례 – 휴대폰이 카메라와 한 번 페어링한 다음 나중에 다시 연결하는 경우 – 에는 mitm=False 로 보통 충분합니다. 원래의 페어링이 통제된 환경(사용자가 두 장치를 같은 방에서 들고 있음)에서 일어나기 때문입니다. 페어링된 장치가 카메라를 먼 거리에서 또는 신뢰할 수 없는 중개자를 통해 처음 마주칠 수 있는 애플리케이션의 경우, MITM이 올바른 설정입니다.
11.13.6. 페어링이 잘못된 답일 때¶
페어링에는 실제 비용이 따릅니다: 첫 연결 시 수 초의 교환, 본딩된 모든 장치에 대한 지속적인 플래시 사용, 그리고 무언가 잘못되었을 때의 “본드 잊기” 복구 절차입니다. 진정으로 공개적인 데이터 – 비콘으로 게시되는 주변 센서 측정값, 이름을 표시하는 표지판, 읽거나 쓴다고 해서 세상을 바꾸지 않는 모든 것 – 의 경우, 올바른 답은 아예 암호화하지 않고 근처의 모든 스캐너가 값을 읽도록 두는 것입니다.
그 외의 모든 경우에는 central에서의 connection.pair(bond=True) 가 링크를 공개 채널에서 비공개 채널로 바꾸는 한 줄짜리 추가입니다.