Scanner write-read-delete workflow working!

This commit is contained in:
2026-05-23 00:30:03 +02:00
parent 30b86dad5e
commit 495535a6de
2 changed files with 83 additions and 78 deletions

View File

@@ -1,6 +1,7 @@
from fastapi import APIRouter, Depends, HTTPException, status
from sqlmodel import Session, select
from typing import List
from sqlalchemy.exc import NoResultFound
from ..model.models import Card
from ..services.database import engine, get_session, add_and_refresh
@@ -26,13 +27,16 @@ def add_card(*, db: Session = Depends(get_session), group_id: int, admin: bool =
@card_router.get("/delete")
def del_card(*, db: Session = Depends(get_session), admin: bool = Depends(auth_is_admin)):
key = DeleteCard()
# card = db.get(Card, card_id)
# if card is None:
# raise HTTPException(status_code=404, detail="Card not found")
# db.delete(card)
# db.commit()
# return {"message": "Card deleted successfully"}
##TBH not a big fan of having creation using group_id but deletion using card_id
print(key)
try:
card = db.exec(select(Card).where(Card.uuid == key)).one()
except NoResultFound:
print(f"The key:'{key}' was not found in db!")
raise HTTPException(status_code=500, detail="Key on card not found in DB. Please tell an admin about this. KEY={key}")
db.delete(card)
db.commit()
return {"message": "Card deleted successfully"}
@card_router.get("/{group_id}", response_model=List[Card])
def get_cards(*, db: Session = Depends(get_session), group_id: int, admin: bool = Depends(auth_is_admin)):
cards = db.exec(select(Card).where(Card.group_id == group_id)).all()

View File

@@ -44,34 +44,80 @@ def checkForKey():
def getCardService(timeout: int = 10):
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=timeout, cardType=cardtype)
print("Please present DESfire tag...")
try:
cardservice = cardrequest.waitforcard()
except CardRequestTimeoutException:
logger.error("No tag detected within the timeout.")
raise Exception("No tag detected within the timeout.")
cardservice = cardrequest.waitforcard()
cardservice.connection.connect()
return cardservice
def readFileOnCard(desfire: DESFire):
#create keys
#desfire = DESFire(PCSCDevice(cardservice.connection.component))
aes_keysettings = KeySettings(key_type=DESFireKeyType.DF_KEY_AES)
keysettings = desfire.get_key_setting()
desKey = DESFireKey(keysettings, "00" * 8)
# Get real UID
desfire.authenticate(0x0, desKey)
#To get the uid you have to auth with an empty (default) key
uid = desfire.get_real_uid()
applications = desfire.get_application_ids()
try:
assert len(applications) == 1
assert applications[0] == get_list(MIFARE_APP_ID)
except AssertionError:
logger.error("No application found!")
time.sleep(4)
return
#Then use the key derivation with that uid, the appid, the sysid
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)
#Log in with derived read key
logger.info("Start auth")
aes_app_read_key = DESFireKey(aes_keysettings, read_div_key_bytes)
desfire.select_application(MIFARE_APP_ID)
desfire.authenticate(MIFARE_ACL_READ_BASE_KEY_ID, aes_app_read_key)
logger.info("Read data")
file_data = desfire.get_file_settings(MIFARE_ENCRYPTED_FILE_ID)
rdata = desfire.read_file_data(MIFARE_ENCRYPTED_FILE_ID, file_data)
#convert list of int to str
rdata = to_hex_string(rdata).replace(" ", "").lower()
logger.info(f"Data on card: {rdata}")
return rdata
def DeleteCard():
try:
checkForKey()
from app.main import scanner as scannerThread
scannerThread.stop()
cardservice = getCardService(15)
cardservice.connection.connect()
# Create Desfire object
desfire = DESFire(PCSCDevice(cardservice.connection.component))
rdata = readFileOnCard(desfire=desfire)
# Create Key objects
AES_NULL_KEY_DATA = "00" * 8
aes_keysettings = KeySettings(
key_type=DESFireKeyType.DF_KEY_AES,
)
key_settings = desfire.get_key_setting()
aes_null_key = DESFireKey(key_settings, AES_NULL_KEY_DATA)
aes_keysettings = KeySettings(key_type=DESFireKeyType.DF_KEY_AES)
des_keysettings = KeySettings(key_type=DESFireKeyType.DF_KEY_2K3DES)
desKey = DESFireKey(des_keysettings, "00" * 8)
aes_master_key = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY)
desfire.authenticate(0x0, aes_null_key)
aes_null_key = DESFireKey(aes_keysettings, "00" * 16)
desfire.select_application(0x0)
try:
try:
logger.info("Auth1")
desfire.authenticate(0x0, desKey)
except:
logger.info("Auth2")
desfire.authenticate(0x0, aes_null_key)
except:
logger.info("Auth3")
desfire.authenticate(0x0, aes_master_key)
applications = desfire.get_application_ids()
logger.debug(f"Applications: {applications}")
if len(applications) == 0:
@@ -79,13 +125,15 @@ def DeleteCard():
desfire.select_application(MIFARE_APP_ID)
desfire.authenticate(0x0, aes_master_key)
try:
desfire.delete_application(MIFARE_APP_ID)
logger.info("App deleted!")
except Exception:
pass
scannerThread.start()
except Exception as e:
return rdata
except(Exception, AssertionError) as e:
logger.error(f"Error in deletion function: {e}", exc_info=True)
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Error: {e}")
@@ -96,7 +144,6 @@ def WriteNewCard():
scannerThread.stop()
cardservice = getCardService(20)
cardservice.connection.connect()
desfire = DESFire(PCSCDevice(cardservice.connection.component))
@@ -104,8 +151,7 @@ def WriteNewCard():
aes_keysettings = KeySettings(key_type=DESFireKeyType.DF_KEY_AES)
aes_null_key = DESFireKey(aes_keysettings, "00" * 16)
aes_master_key = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY)
keysetting = desfire.get_key_setting()
desKey = DESFireKey(keysetting, "00" * 8)
desKey = DESFireKey(desfire.get_key_setting(), "00" * 8)
# Authenticate with default DES key
print("Authenticating with default DES key...")
@@ -162,7 +208,7 @@ def WriteNewCard():
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 UUID...")
print("Create encrypted file containing key...")
file_settings = FileSettings(
file_size=16,
encryption=DESFireCommunicationMode.ENCRYPTED,
@@ -173,16 +219,7 @@ def WriteNewCard():
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 == 16
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...")
key = secrets.token_hex(16)
@@ -226,7 +263,7 @@ class BackgroundScanner:
try:
card_content = self._read_card()
if card_content:
logger.info(to_hex_string(card_content))
logger.info(f"content: {card_content}")
time.sleep(5)
logger.debug("READY after success")
#self._check_db(card_content)
@@ -239,53 +276,17 @@ class BackgroundScanner:
time.sleep(6)
def _read_card(self):
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=5, cardType=cardtype)
time.sleep(0.5)
try:
cardservice = cardrequest.waitforcard()
cardservice = getCardService(3)
except CardRequestTimeoutException:
logger.debug("No tag detected within the timeout.")
return
# Create Desfire object
desfire = DESFire(PCSCDevice(cardservice.connection.component))
try:
cardservice.connection.connect()
# Create Desfire object
desfire = DESFire(PCSCDevice(cardservice.connection.component))
aes_keysettings = KeySettings(
key_type=DESFireKeyType.DF_KEY_AES,
)
# Get real UID
mk = DESFireKey(desfire.get_key_setting(), "00" * 8)
desfire.authenticate(0x0, mk)
#To get the uid you have to auth with an empty (default) key
uid = desfire.get_real_uid()
applications = desfire.get_application_ids()
try:
assert len(applications) == 1
assert applications[0] == get_list(MIFARE_APP_ID)
except AssertionError:
logger.error("No application found!")
time.sleep(4)
return None
#Then use the key derivation with that uid, the appid, the sysid
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)
#Log in with derived read key
logger.info("Start auth")
aes_app_read_key = DESFireKey(aes_keysettings, read_div_key_bytes)
desfire.select_application(MIFARE_APP_ID)
desfire.authenticate(MIFARE_ACL_READ_BASE_KEY_ID, aes_app_read_key)
logger.info("Read data")
file_data = desfire.get_file_settings(MIFARE_ENCRYPTED_FILE_ID)
logger.info(f"File settings: {file_data}")
rdata = desfire.read_file_data(MIFARE_ENCRYPTED_FILE_ID, file_data)
rdata = readFileOnCard(desfire=desfire)
return rdata
except Exception as e:
logger.error(f"something went wrong: {e}")
time.sleep(5)