I'm implementing some Bluetooth Low Energy functionalities in Python.
In the pairing process there is a Pairing Confirm Value like specified in Bluetooth Core Specs 5.3 page 1604 and 1562f.
I have the f4 function already, but if the Authentication Method is "Password Entry", the 6-digit code is also part of this calculation.
Given the 6-digit-Code, I want to be able to generate the Confirmation Values (I think there should be multiple of those)
I already have this (I guess working) function here:
def generateConfirmValue(
self, keyX=None, remoteKeyX=None, localNonce=None, rbi=b"\x00"
):
"""
This class method can be used to generate a confirm value.
:param rbi: Passkey Byte
:type rbi: Byte
:return: Confirm value
:rtype: Bytes
"""
if not (keyX and remoteKeyX and localNonce):
if self.keyX == None or self.remoteKeyX == None:
io.warning("Please first generate the DH keys")
return
if self.localNonce == None:
io.warning("Please first generate the local Nonce")
return
keyX = self.keyX
remoteKeyX = self.remoteKeyX
localNonce = self.localNonce
localConfirm = BLECryptoSC.f4(keyX, remoteKeyX, localNonce, rbi)
return CryptoUtils.reverseOrder(localConfirm.hex())
from here
and now I wanna have a function like this:
def generateConfirmValueForPasskey(self, keyX, remoteKeyX, localNonce, passkey, counter):
passkeyByteForF4 = ...
return generateConfirmValue(keyX, remoteKeyX, localNonce, rbi=passkeyForF4)
Edit: I found a function which does the exact reverse from what I want to do: Link
After some more time I came up with this answer:
The passkey has to be converted into binary, then reversed.
passkey = int(input("passkey: "))
binary_number = format(passkey, '020b')
self.masterRemoteConfirmPasskeyBitString = binary_number[::-1]
self.masterRemoteConfirmPasskeyBitCounter = 0
Then I have to go through the result bit by bit and set rbi to 0x80 if the bit is 0 or to 0x81 if the bit is 1:
rbi = None
if(self.masterRemoteConfirmPasskeyBitString[self.masterRemoteConfirmPasskeyBitCounter] == '0'):
rbi = b"\x80"
else:
rbi = b"\x81"
self.masterRemoteConfirmPasskeyBitCounter += 1
self.masterLocalNonce = self.masterSCCrypto.generateLocalNonce()
nwOrderConfirmValue = self.masterSCCrypto.generateConfirmValue(rbi=rbi)
As I said, this then has to be done 20 times, because we need 20 different confirm values with the according random values.