Upgrade from an earlier version of Keyple


This guide is intended to help a user of a previous version of Keyple Java to upgrade his application to a new version of the library.

Upgrade from:



Upgrade from “2.+” to “3.+”

This major release follows the adoption of Keypop APIs in place of CNA Terminal APIs.

We recommend that you follow the steps below in the order suggested:

  1. Update the project dependencies management
  2. Perform a global text search & replace across the entire project
  3. Apply the changes to the card/SAM selection manager
  4. Apply the changes to the card transaction manager
  5. Apply the changes to the signatures management (PSO or basic) during card transactions
  6. Apply the changes to the SAM resource service
All deprecated methods have been removed. If your project contains such methods, please check the changelogs for replacement methods.

Dependencies management

Replace the legacy Keyple dependencies with the latest versions. To do this, use the configuration wizard to correctly import the new artifacts into your project.

Renaming

Search and replace (in “case-sensitive” and “whole-word” mode) in the following order the following strings when present:

  1. org.calypsonet.terminal.calypso => org.eclipse.keypop.calypso.card
  2. org.calypsonet.terminal => org.eclipse.keypop
  3. card.sam => crypto.legacysam.sam
  4. Reader => CardReader
  5. ObservableReader => ObservableCardReader
  6. ReaderEvent => CardCardReader
  7. CalypsoSam => LegacySam
  8. CardSelection => CardSelectionExtension
  9. CalypsoApiProperties => CalypsoCardApiProperties
  10. SamIOException => CryptoIOException
  11. CalypsoCardSelection => CalypsoCardSelectionExtension
  12. GenericCardSelection => GenericCardSelectionExtension
  13. CardSecuritySetting => SymmetricCryptoSecuritySetting
  14. createCardSecuritySetting => createSymmetricCryptoSecuritySetting
  15. processCommands(true) => processCommands(ChannelControl.CLOSE_AFTER)
  16. processCommands(false) => processCommands(ChannelControl.KEEP_OPEN)
  17. processApdusToByteArrays(true) => processApdusToByteArrays(ChannelControl.CLOSE_AFTER)
  18. processApdusToByteArrays(false) => processApdusToByteArrays(ChannelControl.KEEP_OPEN)
  19. processApdusToHexStrings(true) => processApdusToHexStrings(ChannelControl.CLOSE_AFTER)
  20. processApdusToHexStrings(false) => processApdusToHexStrings(ChannelControl.KEEP_OPEN)
  21. createCardSelectionManager() => getReaderApiFactory().createCardSelectionManager()
  22. createCardSelection() =>
    • Calypso card extension: getCalypsoCardApiFactory().createCalypsoCardSelectionExtension()
    • Generic card extension: createGenericCardSelectionExtension()
  23. createCardTransactionWithoutSecurity => getCalypsoCardApiFactory().createFreeTransactionManager
  24. createSearchCommandData => getCalypsoCardApiFactory().createSearchCommandData
  25. prepareComputeSignature => getCryptoExtension(CardTransactionLegacySamExtension.class).prepareComputeSignature
  26. prepareVerifySignature => getCryptoExtension(CardTransactionLegacySamExtension.class).prepareVerifySignature

Card selection

Prepare a Calypso card selection case

  • 2.+
CalypsoCardSelection calypsoCardSelection = 
    CalypsoExtensionService.getInstance().createCardSelection()
        .filterByDfName(...)
        .setFileOccurrence(...)
        .setFileControlInformation(...);

cardSelectionManager.prepareSelection(calypsoCardSelection);
  • 3.+
IsoCardSelector isoCardSelector =
    SmartCardServiceProvider.getService().getReaderApiFactory().createIsoCardSelector()
        .filterByDfName(...)
        .setFileOccurrence(...)
        .setFileControlInformation(...);

CalypsoCardSelectionExtension calypsoCardSelectionExtension =
    CalypsoExtensionService.getInstance().getCalypsoCardApiFactory().createCalypsoCardSelectionExtension();

cardSelectionManager.prepareSelection(isoCardSelector, calypsoCardSelectionExtension);

Prepare a Calypso SAM selection case

  • 2.+
CalypsoSamSelection CalypsoSamSelection = 
    CalypsoExtensionService.getInstance().createSamSelection()
        .filterByProductType(productType)
        .filterBySerialNumber(serialNumber);

cardSelectionManager.prepareSelection(CalypsoSamSelection);
  • 3.+
String powerOnDataFilter = LegacySamUtil.buildPowerOnDataFilter(productType, serialNumber);

BasicCardSelector basicCardSelector =
    SmartCardServiceProvider.getService().getReaderApiFactory().createBasicCardSelector()
        .filterByPowerOnData(powerOnDataFilter);

LegacySamSelectionExtension legacySamSelectionExtension =
    LegacySamExtensionService.getInstance().getLegacySamApiFactory().createLegacySamSelectionExtension();

cardSelectionManager.prepareSelection(basicCardSelector, legacySamSelectionExtension);

Prepare a Generic card selection case

  • 2.+
GenericCardSelection genericCardSelection =
    GenericExtensionService.getInstance().createCardSelection()
        .filterByDfName(...)
        .setFileOccurrence(...)
        .setFileControlInformation(...);

cardSelectionManager.prepareSelection(genericCardSelection);
  • 3.+
IsoCardSelector isoCardSelector =
    SmartCardServiceProvider.getService().getReaderApiFactory().createIsoCardSelector()
        .filterByDfName(...)
        .setFileOccurrence(...)
        .setFileControlInformation(...);

GenericCardSelectionExtension genericCardSelectionExtension =
    GenericExtensionService.getInstance().createGenericCardSelectionExtension();

cardSelectionManager.prepareSelection(isoCardSelector, genericCardSelectionExtension);

Schedule a card selection scenario

  • 2.+
cardSelectionManager.scheduleCardSelectionScenario(
    observableCardReader,
    detectionMode,
    notificationMode);
  • 3.+
cardSelectionManager.scheduleCardSelectionScenario(
    observableCardReader,
    notificationMode);

Card Transaction

Create a card transaction manager without security

  • 2.+
CardTransactionManager cardTransactionManager =
    CalypsoExtensionService.getInstance()
        .createCardTransactionWithoutSecurity(cardReader, card);
  • 3.+
FreeTransactionManager cardTransactionManager =
    CalypsoExtensionService.getInstance()
        .getCalypsoCardApiFactory().createFreeTransactionManager(cardReader, card);

Create a card transaction manager with security (regular mode)

  • 2.+
CardSecuritySetting securitySetting =
    CalypsoExtensionService.getInstance().createCardSecuritySetting()
        .setControlSamResource(samReader, sam);

CardTransactionManager cardTransactionManager =
    CalypsoExtensionService.getInstance()
        .createCardTransaction(cardReader, card, securitySetting)
  • 3.+
SymmetricCryptoCardTransactionManagerFactory cryptoCardTransactionManagerFactory =
    LegacySamExtensionService.getInstance().getLegacySamApiFactory()
        .createSymmetricCryptoCardTransactionManagerFactory(samReader, sam);

SymmetricCryptoSecuritySetting securitySetting =
    CalypsoExtensionService.getInstance().getCalypsoCardApiFactory()
        .createSymmetricCryptoSecuritySetting(cryptoCardTransactionManagerFactory);

SecureRegularModeTransactionManager cardTransactionManager =
    CalypsoExtensionService.getInstance().getCalypsoCardApiFactory()
        .createSecureRegularModeTransactionManager(cardReader, card, securitySetting);

Create a card transaction manager with security (extended mode)

  • 2.+
CardSecuritySetting securitySetting =
    CalypsoExtensionService.getInstance().createCardSecuritySetting()
        .setControlSamResource(samReader, sam);

CardTransactionManager cardTransactionManager =
    CalypsoExtensionService.getInstance()
        .createCardTransaction(cardReader, card, securitySetting)
  • 3.+
SymmetricCryptoCardTransactionManagerFactory cryptoCardTransactionManagerFactory =
    LegacySamExtensionService.getInstance().getLegacySamApiFactory()
        .createSymmetricCryptoCardTransactionManagerFactory(samReader, sam);

SymmetricCryptoSecuritySetting securitySetting =
    CalypsoExtensionService.getInstance().getCalypsoCardApiFactory()
        .createSymmetricCryptoSecuritySetting(cryptoCardTransactionManagerFactory);

SecureExtendedModeTransactionManager cardTransactionManager =
    CalypsoExtensionService.getInstance().getCalypsoCardApiFactory()
        .createSecureExtendedModeTransactionManager(cardReader, card, securitySetting);

PSO signature management (computation/verification)

  • 2.+
TraceableSignatureComputationData signatureComputationData =
    CalypsoExtensionService.getInstance()
        .createTraceableSignatureComputationData();

cardTransactionManager.prepareComputeSignature(signatureComputationData);
  • 3.+
TraceableSignatureComputationData signatureComputationData =
    LegacySamExtensionService.getInstance()
        .getLegacySamApiFactory().createTraceableSignatureComputationData();

cardTransactionManager.getCryptoExtension(CardTransactionLegacySamExtension.class)
    .prepareComputeSignature(signatureComputationData);

SAM resource service

  • 2.+
CardResourceProfileExtension samResourceProfileExtension =
    CalypsoExtensionService.getInstance()
        .createSamResourceProfileExtension(
            CalypsoExtensionService.getInstance()
                .createSamSelection()
                .filterByProductType(CalypsoSam.ProductType.SAM_C1));
  • 3.+
CardResourceProfileExtension samResourceProfileExtension =
    LegacySamExtensionService.getInstance()
        .createLegacySamResourceProfileExtension(
            LegacySamExtensionService.getInstance()
                .getLegacySamApiFactory()
                .createLegacySamSelectionExtension(),
            LegacySamUtil.buildPowerOnDataFilter(LegacySam.ProductType.SAM_C1, null));

Miscellaneous

Contact reader payload capacity management

  • 2.+
ContextSetting contextSetting = 
    CalypsoExtensionService.getInstance().getContextSetting().setContactReaderPayloadCapacity(...);
  • 3.+
ContextSetting contextSetting = 
    LegacySamExtensionService.getInstance().getContextSetting().setContactReaderPayloadCapacity(...);


Upgrade from “1.+” to “2.+”

Here is a comparative review of the main API changes between Keyple 1.+ and 2.+:

Dependency management

Use the configuration wizard to correctly import the new artifacts into your project.

Initial configuration

Use of a provider to access the smart card service

  • 1.+
SmartCardService smartCardService = SmartCardService.getInstance();
  • 2.+
SmartCardService smartCardService = SmartCardServiceProvider.getService();

Use of builders to instantiate plugin factories

  • 1.+
Plugin plugin = smartCardService.registerPlugin(new PcscPluginFactory(null, new ExceptionHandlerImpl()));
...
((ObservableReader) reader).addObserver(new CardReaderObserver());
  • 2.+
Plugin plugin = smartCardService.registerPlugin(PcscPluginFactoryBuilder.builder().build());
...
((ObservableCardReader) reader).setReaderObservationExceptionHandler(new ExceptionHandlerImpl());
((ObservableCardReader) reader).addObserver(new CardReaderObserver());

Exception handlers are no longer required when registering the plugin but only when starting the observation.

Use of a new interface dedicated to the management of protocols

  • 1.+
reader.activateProtocol(
    PcscSupportedContactlessProtocols.ISO_14443_4.name(), 
    ContactlessCardCommonProtocols.ISO_14443_4.name());
  • 2.+
((ConfigurableCardReader) reader).activateProtocol(
    PcscSupportedContactlessProtocols.ISO_14443_4.name(), 
    CARD_ISO_14443_4);

Use of plugin and reader extensions for specific configurations

The examples below show the evolutions for the configuration of a PC/SC reader but the principle is the same for all plugins and readers.
  • 1.+
reader
    .setContactless(true)
    .setIsoProtocol(PcscReader.IsoProtocol.T1);
  • 2.+
plugin.getReaderExtension(PcscReader.class, reader.getName())
    .setContactless(true)
    .setIsoProtocol(PcscReader.IsoProtocol.T1);

Card selection

Use a manager instead of service for card selection

  • 1.+
CardSelectionsService cardSelectionsService = new CardSelectionsService();
  • 2.+
CardSelectionManager cardSelectionManager = smartCardService.createCardSelectionManager();

A new instance of the card selection manager is provided by the smart card service.

Use of a card extension to create a card selection

  • 1.+
GenericCardSelectionRequest genericCardSelectionRequest =
    new GenericCardSelectionRequest(
        CardSelector.builder()
            .aidSelector(CardSelector.AidSelector.builder().aidToSelect(cardAid).build())
            .build());
  • 2.+
CardSelection cardSelection = GenericExtensionService.getInstance()
    .createCardSelection()
    .filterByDfName(cardAid);
  • The CardSelector class does not exist anymore.
  • A generic card extension is now available.
  • The card extension service is used to configure the card selection.

Explicit card selection

  • 1.+
CardSelectionsResult selectionResult = cardSelectionsService.processExplicitSelections(reader);
  • 2.+
CardSelectionResult selectionResult = cardSelectionManager.processCardSelectionScenario(reader);

Note the removal of the “s” in CardSelectionResult.

Scheduled card selection

  • 1.+
((ObservableReader) reader)
    .setDefaultSelectionRequest(
        defaultSelectionsRequest,
        ObservableReader.NotificationMode.MATCHED_ONLY,
        ObservableReader.PollingMode.REPEATING);
((ObservableReader) reader).addObserver(new CardReaderObserver());
  • 2.+
cardSelectionManager.scheduleCardSelectionScenario(
    (ObservableCardReader) reader,
    ObservableCardReader.DetectionMode.REPEATING,
    ObservableCardReader.NotificationMode.MATCHED_ONLY);
((ObservableCardReader) reader).setReaderObservationExceptionHandler(new ExceptionHandlerImpl());
((ObservableCardReader) reader).addObserver(new CardReaderObserver());

The selection data is no longer provided to the observable reader but to the selection manager. It is the observable reader that is provided to the selection manager.

The processing of the result of the selection response has changed

  • 1.+
AbstractSmartCard smartCard =
  defaultSelection
      .processDefaultSelectionsResponse(event.getDefaultSelectionsResponse())
      .getActiveSmartCard();
  • 2.+
SmartCard smartCard =
    cardSelectionManager
        .parseScheduledCardSelectionsResponse(event.getScheduledCardSelectionsResponse())
        .getActiveSmartCard();

AbstractSmartCard was changed to the SmartCard interface.

Calypso Card Extension

Vocabulary

  • PO has been replaced by Card.

SAM management

The SAM resource manager has been replaced by a generic Card Resource Service.

Card transaction

Access to the card transaction manager has changed. It is now done through the card extension service.

  • 1.+
PoTransaction poTransaction =
    new PoTransaction(
        new CardResource<CalypsoPo>(poReader, calypsoPo),
        CalypsoUtils.getSecuritySettings(samResource));
  • 2.+
CardTransactionManager transactionManager = CalypsoExtensionService.getInstance()
    .createCardTransaction(cardReader, calypsoCard, cardSecuritySetting);

Distributed systems

Remote plugin registration

  • 1.+
// Init the remote plugin factory.
RemotePluginServerFactory factory =
    RemotePluginServerFactory.builder()
        .withDefaultPluginName()
        .withSyncNode()
        .withPluginObserver(new RemotePluginServerObserver())
        .usingEventNotificationPool(
            Executors.newCachedThreadPool(r -> new Thread(r, "server-pool")))
        .build();

// Register the remote plugin to the smart card service using the factory.
SmartCardService.getInstance().registerPlugin(factory);
  • 2.+
RemotePluginServerFactory factory =
    RemotePluginServerFactoryBuilder.builder(REMOTE_PLUGIN_NAME)
        .withSyncNode()
        .build();

// Register the remote plugin to the smart card service using the factory.
ObservablePlugin plugin =
    (ObservablePlugin) SmartCardServiceProvider.getService().registerPlugin(factory);

// Init the remote plugin observer.
plugin.setPluginObservationExceptionHandler(new ExceptionHandlerImpl());
plugin.addObserver(new RemotePluginServerObserver());

  • You have to specify the name of the plugin.
  • It is no longer necessary to provide a thread pool.
  • The exception handler must be provided as for any observable plugin before adding an observer.

Local service registration

  • 1.+
// Init the local service using the associated factory.
LocalServiceClientFactory.builder()
    .withDefaultServiceName()
    .withSyncNode(endpointClient)
    .withoutReaderObservation()
    .getService();
  • 2.+
// Init the local service factory.
LocalServiceClientFactory factory =
    LocalServiceClientFactoryBuilder.builder(LOCAL_SERVICE_NAME)
        .withSyncNode(endpointClient)
        .build();

// Init the local service using the associated factory.
SmartCardServiceProvider.getService().registerDistributedLocalService(factory);

  • You have to specify the name of the local service.
  • The local service must be registered with the smart card service.
  • It behaves like a plugin or reader and also provides an extension to access specific settings.
Previous