如何在Python中计算BLE Passkey Entry模式的配对确认值
蓝牙低功耗(BLE)配对确认值生成(Passkey认证场景)
背景说明
我正在Python中实现BLE相关功能,配对流程里需要按照《蓝牙核心规范5.3》第1604页和1562f节的定义生成Pairing Confirm Value。已有f4函数,当认证方式为“Password Entry”时,需将6位验证码纳入计算,给定该验证码后需要生成对应的确认值(存在多个对应值)。
已有可用函数
已实现generateConfirmValue函数,代码如下:
def generateConfirmValue( self, keyX=None, remoteKeyX=None, localNonce=None, rbi=b"\x00" ): """ 生成配对确认值的类方法 :param rbi: Passkey字节 :type rbi: Byte :return: 确认值 :rtype: Bytes """ if not (keyX and remoteKeyX and localNonce): if self.keyX == None or self.remoteKeyX == None: io.warning("请先生成DH密钥") return if self.localNonce == None: io.warning("请先生成本地随机数(Nonce)") return keyX = self.keyX remoteKeyX = self.remoteKeyX localNonce = self.localNonce localConfirm = BLECryptoSC.f4(keyX, remoteKeyX, localNonce, rbi) return CryptoUtils.reverseOrder(localConfirm.hex())
需要实现的函数
目标是实现generateConfirmValueForPasskey函数,将6位Passkey转换为f4函数所需的rbi参数:
def generateConfirmValueForPasskey(self, keyX, remoteKeyX, localNonce, passkey, counter): passkeyByteForF4 = ... return generateConfirmValue(keyX, remoteKeyX, localNonce, rbi=passkeyByteForF4)
参考反向逻辑(翻译整理)
找到一个与需求逻辑相反的函数,其功能是从rbi字节还原对应的Passkey数字位,原逻辑翻译整理后代码如下:
def extract_passkey_digit(rbi, counter): # 将rbi字节转换为无符号整数(小端序) rbi_int = int.from_bytes(rbi, byteorder='little') # 根据counter定位Passkey对应位:counter=0对应个位,counter=1对应十位,直到counter=5对应十万位 digit = (rbi_int // (10 ** counter)) % 10 return digit
该逻辑的核心是:把rbi转成小端序整数后,通过整除10的counter次方再取模10,得到Passkey对应位置的数字。反向推导可知,我们需要为Passkey的每一位生成对应范围的rbi字节——对于6位Passkey的第counter位,rbi的取值范围是digit * 10^counter到min((digit+1)*10^counter - 1, 0xFF)之间的任意单字节值(单字节上限为0xFF,部分高位的取值范围会被限制)。
最终实现代码
基于上述反向逻辑,generateConfirmValueForPasskey的实现如下:
def generateConfirmValueForPasskey(self, keyX, remoteKeyX, localNonce, passkey, counter): # 校验Passkey合法性:必须是000000到999999之间的整数 if not (0 <= passkey <= 999999): raise ValueError("Passkey必须是6位数字(范围000000-999999)") # 提取Passkey对应counter位置的数字 digit = (passkey // (10 ** counter)) % 10 # 计算rbi的基础值 base = digit * (10 ** counter) # 计算rbi的最大有效值(不超过单字节上限0xFF) max_rbi = min(base + (10 ** counter) - 1, 0xFF) # 生成对应rbi字节(示例取基础值,也可选择范围内任意合法值) passkeyByteForF4 = base.to_bytes(1, byteorder='little') return self.generateConfirmValue(keyX, remoteKeyX, localNonce, rbi=passkeyByteForF4)
内容的提问来源于stack exchange,提问作者Pascal Rockenstiehl
相关产品推荐
相关产品推荐

