From f77b96ebcc1fd8c267fef6a9b03cbcd5b69346a5 Mon Sep 17 00:00:00 2001 From: ahtlon Date: Thu, 21 May 2026 19:19:27 +0200 Subject: [PATCH] use complex text from desfire lib --- test.py | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 139 insertions(+), 7 deletions(-) diff --git a/test.py b/test.py index 63e2db3..efa32ed 100644 --- a/test.py +++ b/test.py @@ -1,8 +1,44 @@ +""" +This is a more involved example that performs initial configuration (often called personalization) of a DESFire card. + +It performs the following steps: +1. Authenticate with the default DES key +3. Change the default key +2. Create an application +4. Change the application master key +6. Create a read and write key (diversified) +7. Create an encrypted file +8. Write the UID to the encrypted file + +""" + +import logging + from smartcard.CardRequest import CardRequest from smartcard.CardType import AnyCardType from smartcard.Exceptions import CardRequestTimeoutException -from desfire import DESFire, DESFireKey, PCSCDevice, to_hex_string +from desfire import DESFire, DESFireKey, PCSCDevice, diversify_key, get_list, to_hex_string +from desfire.enums import DESFireCommunicationMode, DESFireFileType, DESFireKeySettings, DESFireKeyType +from desfire.schemas import FilePermissions, FileSettings, KeySettings + +from dotenv import load_dotenv +# Please make sure to yet your own keys here before running this script +load_dotenv() + +MIFARE_APP_MASTER_KEY = os.getenv('MIFARE_APP_MASTER_KEY') +MIFARE_ACL_READ_BASE_KEY = os.getenv('MIFARE_ACL_READ_BASE_KEY') +MIFARE_ACL_WRITE_BASE_KEY = os.getenv('MIFARE_ACL_WRITE_BASE_KEY') + +# Constants +MIFARE_APP_ID = "DEAFFE" # 7 bytes +MIFARE_ACL_READ_BASE_KEY_ID = 0x1 +MIFARE_ACL_WRITE_BASE_KEY_ID = 0x2 +MIFARE_SYS_ID = "FF0000" # 3 bytes, can essentially be anything +MIFARE_ENCRYPTED_FILE_ID = 0x1 + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) cardtype = AnyCardType() cardrequest = CardRequest(timeout=30, cardType=cardtype) @@ -12,20 +48,116 @@ try: cardservice = cardrequest.waitforcard() except CardRequestTimeoutException: print("No tag detected within the timeout.") - exit(0) - + raise cardservice.connection.connect() -# Create Desfire object, which allows further communication with then card +# Create Desfire object desfire = DESFire(PCSCDevice(cardservice.connection.component)) -# Authenticate with default DES key by retrieving the key settings from the card, -# providing the default key and then authenticate against the master key 0x0 +# Create Key objects +AES_NULL_KEY_DATA = "00" * 16 +aes_keysettings = KeySettings( + key_type=DESFireKeyType.DF_KEY_AES, +) +aes_null_key = DESFireKey(aes_keysettings, AES_NULL_KEY_DATA) + +# Authenticate with default DES key +print("Authenticating with default DES key...") key_settings = desfire.get_key_setting() mk = DESFireKey(key_settings, "00" * 8) desfire.authenticate(0x0, mk) # Get real UID +print("Getting real UID...") uid = desfire.get_real_uid() -print(to_hex_string(uid)) \ No newline at end of file +print(" - UID: ", to_hex_string(uid)) + +# Set default key +print("Setting default key...") +desfire.change_default_key(aes_null_key, 0x0) + +# Create application +print("Creating application...") +app_settings = KeySettings( + settings=[ + DESFireKeySettings.KS_ALLOW_CHANGE_MK, + DESFireKeySettings.KS_LISTING_WITHOUT_MK, + DESFireKeySettings.KS_CREATE_DELETE_WITHOUT_MK, + DESFireKeySettings.KS_CONFIGURATION_CHANGEABLE, + ], + key_type=DESFireKeyType.DF_KEY_AES, +) +desfire.create_application(MIFARE_APP_ID, app_settings, 4) + +# Verify application creation +applications = desfire.get_application_ids() +assert len(applications) == 1 +assert applications[0] == get_list(MIFARE_APP_ID) +print(" - Application created successfully.") + +# Select application +print("Selecting application...") +desfire.select_application(MIFARE_APP_ID) + +# Authenticate with AES key, as this has been set as the default key +print("Authenticating with AES key...") +# Create a new one as key data would be overriden by session data +aes_null_auth_key = DESFireKey(aes_keysettings, AES_NULL_KEY_DATA) +desfire.authenticate(0x0, aes_null_auth_key) + +# Change Application master key +print("Changing application master key (AMK)...") +aes_app_mk = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY) +desfire.change_key(0x0, aes_null_key, aes_app_mk, 0x1) + +# Re-Authenticate with new AES key +print("Re-authenticating with new AES key...") +desfire.authenticate(0x0, aes_app_mk) + +# Change file read and write keys (diversified) +diversification_data = [0x01] + uid + get_list(MIFARE_APP_ID) + get_list(MIFARE_SYS_ID) +read_div_key_bytes = diversify_key(get_list(MIFARE_ACL_READ_BASE_KEY), diversification_data, pad_to_32=False) +write_div_key_bytes = diversify_key(get_list(MIFARE_ACL_WRITE_BASE_KEY), diversification_data, pad_to_32=False) + +print("Changing file read key...") +aes_file_read_key = DESFireKey(aes_keysettings, read_div_key_bytes) +desfire.change_key(MIFARE_ACL_READ_BASE_KEY_ID, aes_null_key, aes_file_read_key, 0x1) + +print("Changing file write key...") +aes_file_write_key = DESFireKey(aes_keysettings, write_div_key_bytes) +desfire.change_key(MIFARE_ACL_WRITE_BASE_KEY_ID, aes_null_key, aes_file_write_key, 0x1) + +print("Create encrypted file containing UID...") +file_settings = FileSettings( + file_size=8, + encryption=DESFireCommunicationMode.ENCRYPTED, + permissions=FilePermissions( + read_key=MIFARE_ACL_READ_BASE_KEY_ID, + write_key=MIFARE_ACL_WRITE_BASE_KEY_ID, + ), + file_type=DESFireFileType.MDFT_STANDARD_DATA_FILE, +) +desfire.create_standard_file(MIFARE_ENCRYPTED_FILE_ID, file_settings) + +print("Read and verify file settings again...") +file_data = desfire.get_file_settings(MIFARE_ENCRYPTED_FILE_ID) +assert file_data.file_size == 8 +assert file_data.encryption == DESFireCommunicationMode.ENCRYPTED +assert file_data.permissions is not None +assert file_data.permissions.read_access == MIFARE_ACL_READ_BASE_KEY_ID +assert file_data.permissions.write_access == MIFARE_ACL_WRITE_BASE_KEY_ID +assert file_data.file_type == DESFireFileType.MDFT_STANDARD_DATA_FILE +print(" - File created successfully.") + +print("Writing UID to encrypted file...") +data = [0x0] + uid +assert len(data) == 8 +desfire.write_file_data(MIFARE_ENCRYPTED_FILE_ID, 0x0, file_data.encryption, get_list(data)) + +print("Reading from encrypted file...") +rdata = desfire.read_file_data(MIFARE_ENCRYPTED_FILE_ID, file_data) +assert rdata == data +print(" - Data written successfully.") + +print("Personalization finished.") \ No newline at end of file