Google have released their cryptography specification for a new privacy-preserving Bluetooth protocol. This could alert Bob that he is in contact with Alice, and who has been tested positive for COVID-19. The privacy rights of this type of system, of course, are to the forefront. This page outlines the method [article]:
COVID-19 Contact Tracker |
Theory
Google's core focus is on key scheduling and Bluetooth Advertisements. Overall there are three main encryption keys.
Tracing Key. This is a randomly generated key that is stored on the device. It is generated as:Key_Tr= Random(32)
and which creates a random 32-byte (256-bit) value. Some sample code to generate this is:
from pbkdf2 import PBKDF2 import os import binascii import hashlib import time import datetime K_track = os.urandom(32) # 256-bit key for phone print ("\nTracing key: "+binascii.hexlify(K_track).decode())
Daily Tracing Key. This key is generated every 24 hours when there is contract tracing. The tracing key is used to generate the Daily Tracking Key (Key_dtk_i) through a 16-byte KDF (Key Derivation Function):
Key_dtk_i =HKDF(Key_Tr , NUL L, (UTF8("CT-DTK") || D_i),16)
and where D_i is the DayNumber for the broadcast. If the user tests positive, this key is broadcast from the device, but when proven healthy, it will never leave the device. Some sample code is:
DayNumber = str(int(time.time()/(60*60*24))) print ("\nDay number: "+DayNumber) D_i = "CT-DTK" + DayNumber Key_day_i = PBKDF2(K_track, D_i).read(16) print ("Daily key: "+binascii.hexlify(Key_day_i).decode())
Rolling Proximity Identifiers. This is an identifier which is used to identify the promixity of a device and is sent out with Bluetooth Advertisements. These are generated from the Daily Tracing Key through a Message Authentication Code. A change in the Bluetooth MAC address, causes a new identifier to be generated. It is generated as:
RPIi, j ← Truncate(HMAC(d k ti, (UTF8("CT-RPI") | |TINj)),16)
TINj is the interval time that the Bluetooth MAC address changes. We can thus code:
today = datetime.date.today() seconds_since_midnight = time.time() - time.mktime(today.timetuple()) TINj=str(int(seconds_since_midnight //(60*10))) print ("\nTINj (Time interval number): "+TINj) TINj_str = "CT-RPI" + TINj rpi = hashlib.pbkdf2_hmac('sha256', Key_day_i, TINj_str.encode() , 10000)[:16] print ("Rolling ID: "+binascii.hexlify(rpi).decode())
The basic use case is where Alice has been identified as having COVIT-19. Her device will then send the daily key to Trent. Trent will then be able to trace every one of the rolling ID keys that Bob might send. On a new day, if Alice does not send the daily key, then Trent will not be able to trace any of the new rolling ID keys back to Alice.
The final code is:
# https://medium.com/asecuritysite-when-bob-met-alice/contact-tracing-the-most-amazing-and-scariest-technology-of-the-21st-century-9fb86d7869e5?source=friends_link&sk=2e2b25269f9d72f08eed2f57d9199bfe from pbkdf2 import PBKDF2 import os import binascii import hashlib import time import datetime ## K_track K_track = os.urandom(32) # 256-bit key for phone print ("\nTracing key: "+binascii.hexlify(K_track).decode()) ## HKDF(Key, Salt, Info, OutputLength) # DayNumber = Number of Seconds since Epoch/ (60 * 60 * 24) DayNumber = str(int(time.time()/(60*60*24))) print ("\nDay number: "+DayNumber) D_i = "CT-DTK" + DayNumber Key_day_i = PBKDF2(K_track, D_i).read(16) print ("Daily key: "+binascii.hexlify(Key_day_i).decode()) # TimeNumberInterval ← Seconds Since Start of DayNumber/(60 * 10) today = datetime.date.today() seconds_since_midnight = time.time() - time.mktime(today.timetuple()) TINj=str(int(seconds_since_midnight //(60*10))) print ("\nTINj (Time interval number): "+TINj) TINj_str = "CT-RPI" + TINj rpi = hashlib.pbkdf2_hmac('sha256', Key_day_i, TINj_str.encode() , 10000)[:16] print ("Rolling ID: "+binascii.hexlify(rpi).decode())
A sample run is:
Tracing key: d963e39f270c6aca6b04bfbb111260d4f47210abeb45765c796f079f9c54b7d1 Day number: 18363 Daily key: f64afd1fb9cc4b5ebd5efa2f3f640d87 TINj (Time interval number): 83 Rolling ID: 7e48d72392b29849b4508f24eced9793