DevelopersKeycard SDK
Secure Channel
16 Oct 2026

Communication with the card happens over a Secure Channel. Since applet 4.0 the channel is authenticated by a certificate the card is programmed with at the factory, so there is nothing to pair and nothing to persist. The SDK picks the protocol version automatically from the applet version reported at selection, so the same code works with 4.0 and 3.x cards.

The card proves its identity with a 98-byte certificate returned in the SELECT response. The SDK verifies it during the handshake and throws if it does not check out — you do not call anything explicitly, you only have to tell the SDK which certification authorities you trust.

The default constructor trusts the Keycard production CA, which is the right choice for almost every integration. Pass your own anchors when you also need to accept test cards:

// Production cards only — this is the default
KeycardCommandSet cmdSet = new KeycardCommandSet(cardChannel);
 
// Production cards plus cards from the Keycard test CA
KeycardCommandSet cmdSet = new KeycardCommandSet(cardChannel, Arrays.asList(
    KeycardCommandSet.DEFAULT_CA_PUBLIC_KEY,
    TEST_CA_PUBLIC_KEY));
CACompressed secp256k1 public key (33 bytes, hex)
Keycard production029a9b9ee1e7a71bdf45b3f9c58c99866ff1294d2c1e304e228a86e10c3343501c
Keycard test cards025877220aaae6e54a6f974602d5995c0fe24a3ea7ddabd8644bec795b9da00743

A card built by yourself carries no certificate, or one from a CA you did not add. Rather than adding its CA you can pin the card identity directly, which is usually what you want in a lab:

KeycardCommandSet cmdSet = new KeycardCommandSet(
    cardChannel,
    Collections.emptyList(),
    Arrays.asList(trustedCardPublicKey)); // compressed, 33 bytes

Once a card has been accepted, the SDK pins its identity for the rest of the session, so a substituted card mid-session is rejected.

A session must be opened every time the applet is selected — including after the card leaves the field, since the card forgets the session when it is deselected. After that the SDK handles the channel transparently, encrypting commands and decrypting responses.

cmdSet.autoOpenSecureChannel();

That is the whole call. There is no pairing step before it and no return value to store.

Earlier versions required each client to pair with each card and keep the resulting pairing secret. That is gone on 4.0: no autoPair, no setPairing, no pairing password, and nothing to write to secure storage. Code that still carries a pairing record for a 4.0 card can delete it.

note
When the SDK selects a card running applet 3.x it transparently falls back to the previous protocol, which does need a pairing. If you still support those cards, keep the pairing code path and call autoPair only when cmdSet.getApplicationInfo().getAppVersion() < 0x0400. The underlying differences are described in Secure Channel v1 (legacy).
Last edited
16 Oct 2026