Writing, deleting don

This commit is contained in:
2026-05-22 08:28:35 +02:00
parent 61cce57401
commit b81b6954ef
3 changed files with 84 additions and 30 deletions

View File

@@ -6,7 +6,7 @@ from ..model.models import Card
from ..services.database import engine, get_session, add_and_refresh
from ..services.auth import auth_is_admin
import uuid as gen_uuid
from app.services.scanner import WriteNewCard
from app.services.scanner import WriteNewCard, DeleteCard
card_router = APIRouter(prefix="/cards", tags=["Card"])
@@ -23,14 +23,15 @@ def add_card(*, db: Session = Depends(get_session), group_id: int, admin: bool =
card = register_card(group_id)
return add_and_refresh(db, card)
@card_router.delete("/{card_id}")
def del_card(*, db: Session = Depends(get_session), card_id: int, admin: bool = Depends(auth_is_admin)):
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"}
@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
@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)):

View File

@@ -7,6 +7,7 @@ import secrets
from typing import Optional
from sqlmodel import Session
from dotenv import load_dotenv
from fastapi import HTTPException, status
from smartcard.CardRequest import CardRequest
from smartcard.CardType import AnyCardType
@@ -15,6 +16,7 @@ from smartcard.Exceptions import CardRequestTimeoutException
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
import desfire.exceptions as desExceptions
#ENV vars
@@ -34,14 +36,62 @@ MIFARE_ENCRYPTED_FILE_ID = 0x1
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
if MIFARE_APP_MASTER_KEY == None:
logger.critical("NO MASTER KEY LOADED")
#exit(1)
##ADD DELETING APP
##
def checkForKey():
if MIFARE_APP_MASTER_KEY == None:
logger.critical("NO MASTER KEY LOADED")
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="No key loaded! Check application.")
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
return cardservice
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))
# 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_master_key = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY)
desfire.authenticate(0x0, aes_null_key)
applications = desfire.get_application_ids()
logger.debug(f"Applications: {applications}")
if len(applications) == 0:
raise HTTPException(status_code=status.HTTP_410_GONE, detail="No applications on card")
desfire.select_application(MIFARE_APP_ID)
desfire.authenticate(0x0, aes_master_key)
try:
desfire.delete_application(MIFARE_APP_ID)
except Exception:
pass
scannerThread.start()
except Exception 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}")
def WriteNewCard():
try:
checkForKey()
from app.main import scanner as scannerThread
scannerThread.stop()
@@ -66,19 +116,19 @@ def WriteNewCard():
)
aes_null_key = DESFireKey(aes_keysettings, AES_NULL_KEY_DATA)
aes_master_key = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY)
keysetting = desfire.get_key_setting()
desKey = DESFireKey(keysetting, "00" * 8)
# 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)
desfire.authenticate(0x0, desKey)
#get uid
uid = desfire.get_real_uid()
# Set default key
print("Setting default key...")
desfire.change_default_key(aes_master_key, 0x0)
desfire.change_default_key(aes_null_key, 0x0)
# Create application
print("Creating application...")
@@ -100,16 +150,16 @@ def WriteNewCard():
print(" - Application created successfully.")
# Select application
print("Selecting application...")
desfire.select_application(MIFARE_APP_ID)
#Auth again as 0key
desfire.authenticate(0x0, mk)
#change to master
desfire.change_key(0x0, mk, aes_master_key, 0x1)
aes_null_auth_key = DESFireKey(aes_keysettings, AES_NULL_KEY_DATA)
desfire.authenticate(0x0, aes_null_auth_key)
# Authenticate with AES key, as this has been set as the default key
print("Authenticating with master key...")
desfire.authenticate(0x0, aes_master_key)
aes_app_mk = DESFireKey(aes_keysettings, MIFARE_APP_MASTER_KEY)
desfire.change_key(0x0, aes_null_key, aes_app_mk, 0x1)
print("new key auth")
desfire.authenticate(0x0, aes_app_mk)
#generate div data
diversification_data = [0x01] + uid + get_list(MIFARE_APP_ID) + get_list(MIFARE_SYS_ID)
@@ -118,15 +168,15 @@ def WriteNewCard():
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_master_key, aes_file_read_key, 0x1)
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_master_key, aes_file_write_key, 0x1)
desfire.change_key(MIFARE_ACL_WRITE_BASE_KEY_ID, aes_null_key, aes_file_write_key, 0x1)
print("Create encrypted file containing UUID...")
file_settings = FileSettings(
file_size=32,
file_size=16,
encryption=DESFireCommunicationMode.ENCRYPTED,
permissions=FilePermissions(
read_key=MIFARE_ACL_READ_BASE_KEY_ID,
@@ -152,12 +202,14 @@ def WriteNewCard():
print("Reading from encrypted file...")
rdata = desfire.read_file_data(MIFARE_ENCRYPTED_FILE_ID, file_data)
assert rdata == key
assert rdata == get_list(key)
print(" - Data written successfully.")
scannerThread.start()
return key
except Exception as e:
logger.error(f"Error in write function: {e}", exc_info=True)
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Error: {e}")
class BackgroundScanner:
@@ -231,7 +283,7 @@ class BackgroundScanner:
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=True)
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")

View File

@@ -13,6 +13,7 @@ It performs the following steps:
"""
import logging
import os
from smartcard.CardRequest import CardRequest
from smartcard.CardType import AnyCardType