Introduction

Developers often start Java Card development in emulators, but moving to real hardware exposes layers of protocol, key management, and command formatting that are easy to overlook. This walkthrough documents the complete process of taking a simple applet from source code to a physical card, step by step.

What Happened

The article follows a hands-on journey beginning with environment setup, cloning a repository, installing a Python virtual environment, and connecting a smart card reader. Key steps include identifying the card via card_id.py, opening a secure channel with SCP02, and loading the applet through a series of APDU commands. Particular attention is paid to the LOAD command's block formatting, where different card vendors (NXP J3R150 vs Mikron) accepted different TLV boundaries, and to the INSTALL command's data field, where a malformed payload silently blocked deployment for days.

  • Setting up the Python PC/SC environment and performing card identification.
  • Authenticating via SCP02 secure channel before any installation.
  • Navigating LOAD command block boundaries and TLV length encoding pitfalls.
  • Overcoming INSTALL data formatting issues that prevent applet installation.
  • Using the jCardSim emulator to catch bugs before touching physical hardware.

Why This Matters

Java Card development on real hardware teaches engineers the hidden complexity of APDU command formatting, secure channel establishment, and card lifecycle management. A single misplaced byte in an INSTALL command or an incorrect block boundary in a LOAD command can cause repeated failures, wasting significant time. The article serves as a practical reference for engineers transitioning from simulation to deployment, emphasizing documentation, key management, and thorough testing.

Key Takeaways

  • Always verify ISD keys and Java Card version before purchasing a development card.
  • Use jCardSim early to identify code bugs without consuming EEPROM write cycles.
  • Pay close attention to LOAD command block formatting and TLV length encoding across different card families.
  • Secure channel setup via SCP02 is non-negotiable for installation.
  • Personalization is one-shot and locks the card's EEPROM; it cannot be reset.
  • Keep detailed logs of APDU exchanges and card responses for debugging.
  • A malformed INSTALL data field will block deployment regardless of which keyset is active.
  • Resetting the card often resolves transient PC/SC connection issues.

Conclusion

Moving a Java Card applet from source to silicon is a multi-layered process that rewards patience, precise command crafting, and a solid grasp of GlobalPlatform and Java Card specifications. The hardware half becomes manageable once the software pipeline is understood, and the insights shared here should help developers avoid common pitfalls and get their code running on real cards faster.