From de05b019ef24f15d324600942f69760595c9faa8 Mon Sep 17 00:00:00 2001 From: Jan Wachsmuth Date: Wed, 21 Jan 2026 00:41:49 +0100 Subject: [PATCH 1/4] Update card_version.py Fix in output for "Hardware Version" --- src/desfire/schemas/card_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/desfire/schemas/card_version.py b/src/desfire/schemas/card_version.py index 6db1dbb..bafcf1e 100644 --- a/src/desfire/schemas/card_version.py +++ b/src/desfire/schemas/card_version.py @@ -31,7 +31,7 @@ def __init__(self, data: list[int]): def __repr__(self) -> str: temp = "--- Desfire Card Details ---\r\n" - temp += f"Hardware Version: {self.hardware_minor_version}.{self.hardware_minor_version}\r\n" + temp += f"Hardware Version: {self.hardware_major_version}.{self.hardware_minor_version}\r\n" temp += f"Software Version: {self.software_major_version}.{self.software_minor_version}\r\n" temp += f"EEPROM size: {1 << (self.hardware_storage_size - 1)} bytes\r\n" temp += f"Production: week {self.production_date_cw:X}, year 20{self.production_date_year:02X}\r\n" From 879f8b113f5349dcb2c134e02c4a7ec292f74661 Mon Sep 17 00:00:00 2001 From: Jan Wachsmuth Date: Wed, 21 Jan 2026 02:53:09 +0100 Subject: [PATCH 2/4] Correction in size calculation Fix to memory size calculation. --- .DS_Store | Bin 0 -> 6148 bytes src/desfire/schemas/card_version.py | 28 +++++++++++- tests/tests_test_card_version_repr.py | 61 ++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 .DS_Store create mode 100644 tests/tests_test_card_version_repr.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b465c387be8449b8241873ef65f6516a17b3700f GIT binary patch literal 6148 zcmeHKyG{c^3>-rck!Vsx$;q)(qERtiV~DIf);fE4&$0dKIh`BkE#6p#W^;7bAjJ~X;xFB}u& z)4>oU0C7e-jO&;sh|LLNFB}ue&@4-dS!y+6SeBD-mDdZ$#4Lx!%{-@Wwwh2ZZYSR& z9o7>SrGOMTR^U9h3-AAH`VaH}aglaXKnnaT1#GsuT`l=a)mtYo=e@Sk@9Ca%pu2G$ oB@EGyiP4U^@pgP2NtxGt&F8&vOpJ2!QBKs)fa@ZY0)MT*ClxsxIRF3v literal 0 HcmV?d00001 diff --git a/src/desfire/schemas/card_version.py b/src/desfire/schemas/card_version.py index bafcf1e..449c70f 100644 --- a/src/desfire/schemas/card_version.py +++ b/src/desfire/schemas/card_version.py @@ -33,7 +33,33 @@ def __repr__(self) -> str: temp = "--- Desfire Card Details ---\r\n" temp += f"Hardware Version: {self.hardware_major_version}.{self.hardware_minor_version}\r\n" temp += f"Software Version: {self.software_major_version}.{self.software_minor_version}\r\n" - temp += f"EEPROM size: {1 << (self.hardware_storage_size - 1)} bytes\r\n" + + # EEPROM size calculation according to NXP documentation, + # see https://www.nxp.com/docs/en/application-note/AN10833.pdf + # formula is in Figure 1 on page 4, lower right corner of the table, + # . examples are in the table itself, below some card types, e.g. MIFARE DESFire + # see also https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.pdf + # on page 36, Table 28 and notes below + # + # Meaning and encoding of 'hardware_storage_size': + # Bit 0 (LSB) indicates size encoding method + # Bit 1..7 are the 'size' value used in the formula below + # + # Ultralight Family has bit 0 = 1, e.g. 0x0B (for 48 Byte) or 0x0E (128 Byte) + # MIFARE DESFire Family has bit 0 = 0, e.g. 0x16: 2K, 0x18: 4K, 0x1A: 8K, 0x1C: 16K, 0x1E: 32K + # + # Formula: + # if bit 0 = 1, then storageBytes = 2^(size // 2) up to storageBytes = 2^(size // 2 + 1) + # if bit 0 = 0, then storageBytes = 2^(size // 2) + + # LSB indicates size encoding method + if (self.hardware_storage_size & 0x01) == 0x01: # typical for Ultralight C, and EV1 + temp += ( + f"EEPROM size: {1 << (self.hardware_storage_size >> 1)} up to " + f"{1 << ((self.hardware_storage_size >> 1) + 1)} bytes\r\n" + ) + else: # typical for DESFire EV1, EV2, and EV3 + temp += f"EEPROM size: {1 << (self.hardware_storage_size >> 1)} bytes\r\n" temp += f"Production: week {self.production_date_cw:X}, year 20{self.production_date_year:02X}\r\n" temp += f"UID no: {to_hex_string(self.uid)}\r\n" temp += f"Batch no: {to_hex_string(self.batch_no)}\r\n" diff --git a/tests/tests_test_card_version_repr.py b/tests/tests_test_card_version_repr.py new file mode 100644 index 0000000..3ce3e52 --- /dev/null +++ b/tests/tests_test_card_version_repr.py @@ -0,0 +1,61 @@ +from desfire.schemas.card_version import CardVersion + + +def test_card_version_repr_hardware_major_minor(): + # Prepare data for real MIFARE DESFire EV1 card with 4K from 2013 + data = [ + 0x04, # first block, hardware vendor id + 0x01, + 0x01, + 0x01, + 0x00, + 0x18, + 0x05, + 0x04, # second block, software vendor id + 0x01, + 0x01, + 0x01, + 0x04, + 0x18, + 0x05, + 0x04, # third block, starts with UID + 0x4D, + 0x70, + 0xBA, + 0x5F, + 0x35, + 0x80, + 0xBA, + 0x44, + 0x97, + 0xD6, + 0x70, + 0x28, + 0x13, + ] + cv = CardVersion(data) + s = repr(cv) + assert "Hardware Version: 1.0" in s + assert "Software Version: 1.4" in s + print(s) + + +""" +output with current code was: +--- Desfire Card Details --- +Hardware Version: 0.0 +Software Version: 1.4 +EEPROM size: 8388608 bytes +Production: week 28, year 2013 +UID no: 04 4D 70 BA 5F 35 80 +Batch no: BA 44 97 D6 + +new code produces output like: +--- Desfire Card Details --- +Hardware Version: 1.0 +Software Version: 1.4 +EEPROM size: 4096 bytes +Production: week 28, year 2013 +UID no: 04 4D 70 BA 5F 35 80 +Batch no: BA 44 97 D6 +""" From 18364d67783889b563cf62b94f991c29cc504708 Mon Sep 17 00:00:00 2001 From: Jan Wachsmuth Date: Wed, 21 Jan 2026 02:57:25 +0100 Subject: [PATCH 3/4] Update .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 496070c..5e109db 100644 --- a/.gitignore +++ b/.gitignore @@ -175,3 +175,7 @@ cython_debug/ # Docs site public/ + +# MacOS +.DS_Store +**/.DS_Store From 62a6301587eb4f18f439b7a7fe2a266d9dc059a4 Mon Sep 17 00:00:00 2001 From: Jan Wachsmuth Date: Wed, 21 Jan 2026 18:27:16 +0100 Subject: [PATCH 4/4] Review of explanations --- src/desfire/schemas/card_version.py | 15 ++++++++------- tests/tests_test_card_version_repr.py | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/desfire/schemas/card_version.py b/src/desfire/schemas/card_version.py index 449c70f..1f770e0 100644 --- a/src/desfire/schemas/card_version.py +++ b/src/desfire/schemas/card_version.py @@ -36,22 +36,23 @@ def __repr__(self) -> str: # EEPROM size calculation according to NXP documentation, # see https://www.nxp.com/docs/en/application-note/AN10833.pdf - # formula is in Figure 1 on page 4, lower right corner of the table, - # . examples are in the table itself, below some card types, e.g. MIFARE DESFire + # Formula is in Figure 1 on page 4, lower right corner of the table, but a bit unclear. + # . Examples are in the table itself below some card types, e.g. MIFARE DESFire # see also https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.pdf # on page 36, Table 28 and notes below # # Meaning and encoding of 'hardware_storage_size': - # Bit 0 (LSB) indicates size encoding method + # Bit 0 (LSB) indicates the size encoding method # Bit 1..7 are the 'size' value used in the formula below # - # Ultralight Family has bit 0 = 1, e.g. 0x0B (for 48 Byte) or 0x0E (128 Byte) - # MIFARE DESFire Family has bit 0 = 0, e.g. 0x16: 2K, 0x18: 4K, 0x1A: 8K, 0x1C: 16K, 0x1E: 32K - # # Formula: # if bit 0 = 1, then storageBytes = 2^(size // 2) up to storageBytes = 2^(size // 2 + 1) # if bit 0 = 0, then storageBytes = 2^(size // 2) - + # + # Examples: + # Ultralight Family, e.g. Ultralight C has bit 0 = 1, e.g. 0x0B (for 48 Byte) or 0x0E (128 Byte) + # MIFARE DESFire Family has bit 0 = 0, e.g. 0x16: 2K, 0x18: 4K, 0x1A: 8K, 0x1C: 16K, 0x1E: 32K + # # LSB indicates size encoding method if (self.hardware_storage_size & 0x01) == 0x01: # typical for Ultralight C, and EV1 temp += ( diff --git a/tests/tests_test_card_version_repr.py b/tests/tests_test_card_version_repr.py index 3ce3e52..f6a5603 100644 --- a/tests/tests_test_card_version_repr.py +++ b/tests/tests_test_card_version_repr.py @@ -50,7 +50,7 @@ def test_card_version_repr_hardware_major_minor(): UID no: 04 4D 70 BA 5F 35 80 Batch no: BA 44 97 D6 -new code produces output like: +new code produces following output: --- Desfire Card Details --- Hardware Version: 1.0 Software Version: 1.4