The tutorial demonstrates an elegant approach to secure Java Card applet personalization by relying on the built-in security features of the Issuer Security Domain instead of custom asymmetric cryptography implementations.
Background and Problem Statement
Previous examples using ECDH for session key derivation required significant testing resources and failed to provide authentication, allowing any party knowing the elliptic curve parameters to extract secrets. The new method avoids these issues by delegating security to the GlobalPlatform card manager.
The use case involves an access control system where employee data (name, department, position, validity period) must be written or updated only by authorized parties over a protected channel. Any reader can retrieve the data, but it is returned encrypted with AES-128. The applet must securely receive and periodically update the 16-byte key throughout the card lifecycle.
Applet Implementation Details
The constructor simply allocates a 255-byte buffer for personal information. Heavy cryptographic objects such as AESKey and Cipher are instantiated after installation to avoid 6F00 errors on NXP cards during the INSTALL for install command.
The install method follows GlobalPlatform guidelines by passing the instance AID to register(). The process method handles three proprietary instructions for setting the secret key, writing personal data, and reading personal data, while unknown instructions are routed to mutual authentication.
A helper method determines whether an instruction carries command data, ensuring setIncomingAndReceive is called only when needed. Comprehensive try-catch blocks convert CryptoException reasons into informative status words instead of generic 6F00 errors.
Secure Channel Usage
The applet obtains a SecureChannel instance in select() via GPSystem.getSecureChannel and resets it in deselect(). Unknown APDUs invoke scp02.processSecurity, which handles INITIALIZE UPDATE and EXTERNAL AUTHENTICATE commands according to the negotiated security level.
The update_secret_key method calls unwrap with an adjusted length to account for the CLA offset, then verifies that the security level includes C_DECRYPTION before installing the AES key. The set_person_info method applies a lower requirement of C_MAC only.
Reading personal information simply initializes the AES cipher in encryption mode and returns the ciphertext. All operations are tested using the FunGP Python library, which supports multiple SCP02 security levels configurable at mutual authentication time.


