A secure smartcard system with a terminal interface and a verification server.
- Python 3.10+ 🐍
- JavaCard-compatible smartcard 💳
pipfor Python dependencies 📦
The server verifies transactions from terminals.
cd server
pip install -r requirements.txt
python verification_server.py- Runs on
localhost:5000🌐 - Blocks the shell while listening for requests 🛑
The terminal interacts with the smartcard and server 💳➡️🖥️
cd terminal
pip install -r requirements.txt
python terminal.py- Run multiple terminals in separate shells 🔄
Python unittest
cd test
pip install -r requirements.txt
python main.pyMake sure the smartcard is plugged in 💳⚡
Or, using an emulated smartcard:
./gradlew clean test
- 🔑 Smartcard Applet – Generates keys & handles transactions
- 💳 Terminal Interface – Payment device simulator
- 🖥️ Verification Server – Validates transaction requests
- ✅ Testing Suite – Unit tests
build.sh– Build smartcard appletupload.sh– Upload applets to smartcardtest-card.sh– Pytest-based card testslist-applets.sh– List installed applets
- Smartcard must be connected for terminal & test usage 💳
- Server must be running before terminal(s) 🚦
- Tested with Python 3.10+, JavaCard 2.1.1 SDK ✅
-
Start the verification server
-
With the physical smartcard inserted in the reader, run the terminal
-
On startup the terminal performs "Updating public key" and calls /api/card/register automatically (the terminal uses INS_SEND_PUB_KEY).
-
Verify registration on the server:
- Check the key file:
ls -l server/card_public_keys/
- Check the key file:
-
With the server running, run terminal.py and choose "Send Transaction".
- Enter PIN when prompted (default in applet is
0000). - Select items to buy in the interactive prompt.
- Enter PIN when prompted (default in applet is
-
Terminal flow (what happens):
- Builds the transaction bytes from selected items.
- Sends INS_RECEIVE_TRANSACTION to the real card.
- Receives back transaction || signature.
- POSTs JSON to /api/transaction.
-
Expected server response in terminal:
- "Transaction signed by card"
- "Transaction verified and stored: tx_..." printed after verification success.
-
Manual verification (server side):
- List stored files:
ls server/stored_transactions - Inspect a saved transaction:
cat server/stored_transactions/tx_*.json | jq .
Expected: JSON with transaction_id, card_id, items array and verified: true.
- List stored files:
-
Query server endpoint to list stored transactions: curl -s http://localhost:5000/api/transactions | jq .
-
Expected JSON shape:
{ "success": true, "transactions": [ { "transaction_id": "tx_1617181920", "card_id": "card_001", "timestamp": "2025-01-01T12:00:00", "verified": true, "items": [["Coca-Cola",2],["Sandwich",5]] }, ... ], "count": N }