This project offers a demonstration of an Apple Home Key Reader built in Python. It includes:
It's intended for makers and developers interested in building practical and user-friendly applications using this example.
Feel free to give it a try! :)
Running this project requires the following:
When using a PC, connect the PN532 to a UART adapter, and then connect the adapter to the PC as follows:
Code has been tested using Python 3.9
, 3.10
, 3.11
on macOS
and Linux
. Windows support status is unknown.
Other OS + Python version combos were not verified but may still work.
(Optionally). Create and activate a venv:
python3 -m venv ./venv
source ./venv/bin/activate
python3 -m pip install -r requirements.txt
Configure the application via the text editor of choice:
nano configuration.json
3.1. Find NFC device port:
# linux
ls /dev/*
# macOS
ls /dev/tty.*
3.2. Copy the port without the tty.
part, insert it into port
field;
3.3. If you don't use a PN532, set broadcast
to false and driver
to appropriate value, otherwise leave as is.
python3 main.py
Configuration is done via a JSON file configuration.json
, with the following 4 blocks configurable:
logging
:
nfc
: configuration of the NFC frontend used:
port
: path to serial port of the connected NFC module;driver
: nfcpy driver to use with your device. Implementation was only tested for PN532, other modules have to be verified separately (if supported by nfcpy);broadcast
: configures if to use broadcast frames and ECP. If this parameter is true but used NFC device is not based on PN532, will cause an exception to be raised, set to false only if such problems occur;hap
: configuration of the HAP-python library, better left unchanged;
port
: network port of the virtual accessory;persist
: file to store HAP-python pairing data in.default
: default state of the virtual lock accessory;locked
unlocked
. Value locked
is default;homekey
:
persist
: file to save endpoint and issuer configuration data in;express
: configures if to trigger express mode on devices that have it enabled. If set to false
, bringing a device to the reader will display the key on the screen while asking for biometric authentication. Beware that this doesn't increase security as express mode is disabled on ECP level, so a would-be attacker could always 'excite' the device with express ECP frame and bring it to the reader;finish
: color of the home key art to display on your device.
Usually, finish of the first NFC lock added to your home defines which color the keys are going to be, even if more locks are added;black
tan
gold
silver
;flow
: minimum viable digital key transaction flow to do. By default, reader attempts to do as least actions as possible, with fallback to next level of authentication only happening if the previous one failed. Setting this setting to standard
or attestation
will force protocol to fall back to those flows even if they're not required for successful auth.fast
standard
attestation
.Project is split into following primary modules:
main.py
- initialize and start all primary classes, configure device ports, etc;accessory.py
- service definitions for HAP, contains no logic, with it forwarded to service.py
;service.py
- implements core application functionality, parsing HAP messages and generating responses to them, initiating NFC communication.homekey.py
- homekey NFC part of the protocol implementation; Other modules:
repository.py
- implements homekey configuration state storage;bfclf.py
- implementation of Broadcast frames for pn532;entity.py
- entity definitions;util/*
- protocol implementations, data structures, cryptography, other utility methods.Two files will be created as the result of you running the application, assuming no settings were changed:
hap.state
: contains pairing data needed for HAP-python;homekey.json
: contains all lock configuration data formatted in a human-readable form.hap
, meaning that the Endpoint was added via HAP, or attestation
, meaning that endpoint was enrolled via NFC attestation flow.The project is quite far from ideal since most of the codebase remains unchanged from my original local project, which was primarily utilized during the reverse-engineering phase.
As a result, there are numerous opportunities for enhancement:
remove_device_credential
;get_nfc_access_control_point
- no idea what it should do;In case you're planning on tackling one of those, feel free to raise an issue to discuss potential solution and approach.
Codebase is formatted with default black
and isort
configurations, linted with pylint
.
Before making a contribution, verify that they were used for best code diffs and quality;
This project would have been impossible without the contributions of:
Special thanks to: