Encrypted Advertising methods
Encrypted advertising is a feature that allows you to encrypt an Advertisement Data (AD) element. This new Encrypted Advertisement Data (EAD) element can be included in the advertisement payload using any of the provided advertisement methods.
Key material used for the EAD is stored in a read-only GATT characteristic(UUID 0x2B88) that is only readable after a connection is authenticated. This protects from anyone reading the encryption key and viewing the data. See Bluetooth Core Specification v5.4 Vol 3, Part C, Section 12.6 for more details on encrypted advertising specification.
As long as the key is known from an authenticated connection with the advertiser, you may decrypted an encrypted advertisement from that advertiser. Encrypted advertising can be used to share senstive data with an observer without the need to establish a connection and read services and characteristics.
set_encryption_key()
Set the necessary components of the key material for performing encryption or decryption of advertisement data.
ble.set_encryption_key(session_key=None, iv=None)
<session_key>
The <session_key> is a 128 bit key used during encryption. Optionally, this can be set to None or left empty to randomly generate a key for encryption.
<iv>
The <iv> is a 64 bit initialization vector used during encryption. Optionally, this can be set to None or left empty to randomly generate an iv for encryption.
gatt_write_key()
Write the encryption key material set when calling set_encryption_key() to the Encrypted Data Key Material characteristic (UUID 0x2B88). This characteristic is defined in Bluetooth Core Specification v5.4 Vol 3, Part C, Section 12.6. In order to read from this characteristic, you must first establish an authenticated connection.
ble.gatt_write_key()
encrypt_adv_data()
Encrypt advertisement payload and form an Encrypted Advertisement Data (EAD) element.
ead_element = ble.encrypt_adv_data(data)
<data>
This is the payload that will be encrypted and formed into an EAD. <data> can be a bytes or bytearray object up to 180 bytes in length.
Return value
If the encryption operation is successful, an EAD element will be returned as bytes.
An EAD consists of a length byte, a data type byte, a five byte randomizer, one or more bytes of encrypted data, and a four byte message integrity check (MIC). For more information on the standard used for EAD, see the Bluetooth Core Specification Supplement v11, Part A Section 1.23. The randomizer is chosen by Digi to ensure that proper entropy is used to better protect the host. The MIC is used to authenticate that the data sent is same data that was received.
Example of EAD element:
Length | AD Type | Randomizer | Encrypted Data | MIC
0xA 0x31 0xAABBCCDDEE (b'Digi XBee') 0x11223344
Example:
ble.set_encryption_key() # Sets random key material using hardware entropy.
ble.write_gatt_key()
ead_element = ble.encrypt_adv_data(b'Digi XBee')
# ead_element will contain a valid Encrypted Advertisement Data (EAD) element
# ready for advertisement
# You can prepend/append additional EAD or Advertisement Data (AD) elements as needed.
ble.gap_advertise(500000, ead_element)
If the encryption process is unable to finish, an error will be returned. OSError EMSGSIZE means the EAD exceeds the max size of 255. OSError EIO means the encryption operation failed. This can be due to the encryption key material not being set before performing the decryption.
decrypt_adv_data()
Decrypt an Encrypted Advertisement Data (EAD) element.
You can only decrypt one EAD at a time. The Advertisement Data (AD) Type for an EAD element is 0x31. This can be used when parsing an advertisement payload to find the encrypted elements.
<enc_data>
This is the full Encrypted Advertisement Data (EAD) element from the advertisement that we want to decrypt.
Return value
If the decryption is successful, the decrypted data portion of the EAD will be returned as bytes.
Example:
# session_key and iv can either be known before or read from advertiser GATT
# characteristic. see write_gatt_key().
ble.set_encryption_key(session_key, iv)
# ead_element is pulled from an advertisement payload.
clear_text = ble.decrypt_adv_data(ead_element)
# Print out the decrypted advertisement message.
print(clear_text)
If the decryption operation failed, an error will be raised. An OSError EMSGSIZE means that the EAD exceeded the max size of 255. An OSError EIO means the decryption operation failed for an unspecified reason. This can be due to the encryption key material not being set before decryption or the passed in <enc_data> is not formatted following the guidelines for an EAD element (see encrypt_adv_data() for more information on EAD format).
PDF
