メインコンテンツまでスキップ

MicroPythonでBLEのIRKを取得する手順

iPhoneがBLEで送信するアドレスはランダムに変更されるため、端末を特定するにはIRK(Identity Resolving Key)の取得が必要です
ここではmicropythonでIRKを取得するための手順を、コードを含めて解説します

概要

しくみとしては、ESP32を仮想BLEキーボードデバイスとしてアドバタイズさせて これをiPhoneからペアリングさせる過程で通知されるIRKを取得します

前提事項

以下の手順は、micropythonの環境設定とmpremoteの導入が前提となります
手順は以下の記事を参照ください
ESP32 Dev Board KitへのMicroPython実行環境設定手順

参照ライブラリの登録

以下の手順はMicroPythonBLEHIDをライブラリとして利用します

MicroPythonBLEHIDから以下の2ファイルをダウンロードしてください

ダウンロードしたら以下のコマンドでESP32へアップロードします
(ここで使うmpremoteの導入は前提事項を参照ください)
(コマンドはダウンロードファイルを保存したフォルダで実行してください)

mpremote cp hid_keystores.py :hid_keystores.py
mpremote cp hid_services.py :hid_services.py
image image

IRK取得コード

IRK取得のコードを記載します
以下のコードをirk_getter.pyとして保存してください

import time
from machine import SoftSPI, Pin
from hid_services import Keyboard
from micropython import const

_IO_CAPABILITY_NO_INPUT_OUTPUT = const(3)
_IRQ_GATTS_READ_REQUEST = const(4)

_IRQ_GET_SECRET = const(29)
_IRQ_SET_SECRET = const(30)

_GATTS_NO_ERROR = const(0x00)
_GATTS_ERROR_INVALID_HANDLE = const(0x01)
_GATTS_ERROR_READ_NOT_PERMITTED = const(0x02)
_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION = const(0x05)
_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION = const(0x08)
_GATTS_ERROR_INSUFFICIENT_ENCRYPTION = const(0x0f)

class dummy_Keyboard(Keyboard):

def __init__(self, name="Dummy Keyboard"):
super(dummy_Keyboard, self).__init__(name)
self.stop = False

def notify_hid_report(self):
pass

def ble_irq(self, event, data):
if event == _IRQ_SET_SECRET:
sec_type, key, value = data
if value is None: # If value is empty, and
if self.secrets.has_secret(sec_type, key): # If key is known then
self.secrets.remove_secret(sec_type, key) # Forget key
self.secrets.save_secrets()
return True
else:
return False
else:
self.secrets.add_secret(sec_type, key, value) # Remember key/value

if(sec_type == 2):
irk_bytes = bytes(value)[41:57]
irk_bytes_reverse = bytes(list(reversed(irk_bytes)))
irk = irk_bytes_reverse.hex()
print(f"irk:{irk}")

self.stop = True

return True
elif event == _IRQ_GATTS_READ_REQUEST:
conn_handle, attr_handle = data
description, val = self.characteristics.get(attr_handle, (None, None))
if conn_handle != self.conn_handle: # If different connection, return no permission.
return _GATTS_ERROR_READ_NOT_PERMITTED
elif description == None: # If the handle is unknown, return invalid handle.
return _GATTS_ERROR_INVALID_HANDLE
elif self.bond and not self.bonded: # If we wish to bond but are not bonded, return insufficient authorization.
return _GATTS_ERROR_INSUFFICIENT_AUTHORIZATION
elif self.io_capability > _IO_CAPABILITY_NO_INPUT_OUTPUT and not self.authenticated: # If we can authenticate but the client hasn't authenticated, return insufficient authentication.
return _GATTS_ERROR_INSUFFICIENT_AUTHENTICATION
elif self.le_secure and (not self.encrypted or self.key_size < 16): # If we wish for a secure connection but it is unencrypted or not strong enough, return insufficient encryption.
return _GATTS_ERROR_INSUFFICIENT_ENCRYPTION
else: # Otherwise, return no error.
return _GATTS_NO_ERROR
elif event == _IRQ_GET_SECRET:
None
else:
return super(dummy_Keyboard, self).ble_irq(event, data)

class IrkGetter:
def __init__(self):
# Define state
self.key0 = 0x00
self.key1 = 0x00
self.key2 = 0x00
self.key3 = 0x00

# Define buttons
self.pin_forward = Pin(5, Pin.IN)
self.pin_reverse = Pin(23, Pin.IN)
self.pin_right = Pin(19, Pin.IN)
self.pin_left = Pin(18, Pin.IN)

self.keyboard = dummy_Keyboard("IRK getter")
self.keyboard.set_state_change_callback(self.keyboard_state_callback)
self.keyboard.start()

# Function that catches device status events
def keyboard_state_callback(self):
if self.keyboard.get_state() is Keyboard.DEVICE_IDLE:
return
elif self.keyboard.get_state() is Keyboard.DEVICE_ADVERTISING:
return
elif self.keyboard.get_state() is Keyboard.DEVICE_CONNECTED:
return
else:
return

def advertise(self):
self.keyboard.start_advertising()

def stop_advertise(self):
self.keyboard.stop_advertising()

def main_logic(self):
while True:
self.key0 = 0x1A

if (self.key0 != 0x00) or (self.key1 != 0x00) or (self.key2 != 0x00) or (self.key3 != 0x00):
if self.keyboard.get_state() is Keyboard.DEVICE_CONNECTED:
self.keyboard.set_keys(self.key0, self.key1, self.key2, self.key3)
self.keyboard.notify_hid_report()
elif self.keyboard.get_state() is Keyboard.DEVICE_IDLE:
self.keyboard.start_advertising()
i = 10
while i > 0 and self.keyboard.get_state() is Keyboard.DEVICE_ADVERTISING:
time.sleep(3)
i -= 1
if self.keyboard.get_state() is Keyboard.DEVICE_ADVERTISING:
self.keyboard.stop_advertising()

if self.keyboard.get_state() is Keyboard.DEVICE_CONNECTED:
time.sleep_ms(20)
else:
time.sleep(2)

if self.keyboard.stop:
break

if __name__ == "__main__":
d = IrkGetter()
d.main_logic()

IRK取得の実行

IRK取得処理を実行します (ここで使うmpremoteの導入は前提事項を参照ください)
(コマンドは上記irk_getter.pyを保存したフォルダで実行してください)

mpremote run irk_getter.py
image

👆こんな感じでStarted advertisingと出力されたら準備完了です

image

👆検出したいiPhoneのBluetooth設定からIRK Getterを見つけます

image

👆IRK Getterをペアリングします

image

👆IRK Getterが接続済みになります

image

👆このタイミングでコンソールにIRKが出力されるのでコピーして控えてください

👇関連記事

👇参考URL

MicroPythonBLEHID

本記事へのリンク

https://docs.saurus12.com/device/irk_get_code

[keywords]
ESP32 BLE IRK

MicroPythonでBLEのIRKを取得する手順

更新日:2026年04月26日

ITとソフトウェアの人気オンラインコースHP Directplus -HP公式オンラインストア-