From 107cd8bdaf99400ca9961daa1a3eff252c28fbef Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Mon, 4 Dec 2023 16:23:57 +0100 Subject: [PATCH] feat: switch to Keypop API (#20) --- CHANGELOG.md | 15 +++ client/android/app/build.gradle.kts | 14 +-- .../reload/remote/data/ReaderRepository.kt | 6 +- .../demo/reload/remote/di/ReaderModule.kt | 19 ++-- .../reload/remote/domain/TicketingService.kt | 26 +++-- .../reload/remote/ui/AbstractCardActivity.kt | 8 +- .../reload/remote/ui/CardReaderActivity.kt | 14 +-- .../remote/ui/PersonalizationActivity.kt | 13 +-- .../demo/reload/remote/ui/ReloadActivity.kt | 16 ++- client/android/gradle.properties | 2 +- .../domain/api/MainServiceApiAdapter.cs | 8 +- server/build.gradle.kts | 18 +-- server/dashboard-app/package.json | 2 +- server/gradle.properties | 3 +- .../remote/server/card/CardConfigurator.java | 24 ++-- .../remote/server/card/CardController.java | 4 +- .../remote/server/card/CardRepository.java | 107 +++++++++--------- .../remote/server/card/CardService.java | 7 +- 18 files changed, 163 insertions(+), 143 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e36b82b..9932747 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Upgraded +- Calypsonet Terminal Reader API `1.3.0` -> Keypop Reader API `2.0.0` +- Calypsonet Terminal Calypso API `1.8.0` -> Keypop Calypso Card API `2.0.0` +- Keyple Service Library `2.3.1` -> `3.0.0` +- Keyple Service Resource Library `2.1.1` -> `3.0.0` +- Keyple Calypso Card Library `2.3.5` -> `3.0.0` +- Keyple Util Library `2.3.0` -> `2.3.1` +- Keyple Distributed Local Library `2.2.0` -> `2.3.0` +- Keyple Distributed Network Library `2.2.0` -> `2.3.0` +- Keyple Distributed Remote Library `2.2.1` -> `2.3.0` + +### Added +New dependencies +- Keypop Crypto Legacy SAM API `0.3.0` +- Keyple Calypso Crypto LegacySAM Library `0.4.0` ## [2023.05.31] ### Added diff --git a/client/android/app/build.gradle.kts b/client/android/app/build.gradle.kts index c53998b..9983892 100644 --- a/client/android/app/build.gradle.kts +++ b/client/android/app/build.gradle.kts @@ -98,20 +98,20 @@ dependencies { implementation("org.calypsonet.keyple:keyple-demo-common-lib:2.0.0-SNAPSHOT") { isChanging = true } // Keyple core - implementation("org.calypsonet.terminal:calypsonet-terminal-reader-java-api:1.3.0") - implementation("org.calypsonet.terminal:calypsonet-terminal-calypso-java-api:1.8.0") + implementation("org.eclipse.keypop:keypop-reader-java-api:2.0.0") + implementation("org.eclipse.keypop:keypop-calypso-card-java-api:2.0.0") implementation("org.eclipse.keyple:keyple-common-java-api:2.0.0") - implementation("org.eclipse.keyple:keyple-util-java-lib:2.3.0") - implementation("org.eclipse.keyple:keyple-service-java-lib:2.3.1") - implementation("org.eclipse.keyple:keyple-card-calypso-java-lib:2.3.5") + implementation("org.eclipse.keyple:keyple-util-java-lib:2.3.1") + implementation("org.eclipse.keyple:keyple-service-java-lib:3.0.0") + implementation("org.eclipse.keyple:keyple-card-calypso-java-lib:3.0.0") // Keyple reader plugins implementation("org.eclipse.keyple:keyple-plugin-android-nfc-java-lib:2.0.1") implementation("org.eclipse.keyple:keyple-plugin-android-omapi-java-lib:2.0.1") // Keyple distributed - implementation("org.eclipse.keyple:keyple-distributed-network-java-lib:2.2.0") - implementation("org.eclipse.keyple:keyple-distributed-local-java-lib:2.2.0") + implementation("org.eclipse.keyple:keyple-distributed-network-java-lib:2.3.0") + implementation("org.eclipse.keyple:keyple-distributed-local-java-lib:2.3.0") // Network implementation("org.java-websocket:Java-WebSocket:1.3.9") diff --git a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/data/ReaderRepository.kt b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/data/ReaderRepository.kt index f04295e..a4f7ef5 100644 --- a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/data/ReaderRepository.kt +++ b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/data/ReaderRepository.kt @@ -12,11 +12,11 @@ package org.calypsonet.keyple.demo.reload.remote.data import kotlin.jvm.Throws -import org.calypsonet.terminal.reader.CardReader -import org.calypsonet.terminal.reader.ObservableCardReader -import org.calypsonet.terminal.reader.ReaderCommunicationException import org.eclipse.keyple.core.common.KeyplePluginExtensionFactory import org.eclipse.keyple.core.service.SmartCardServiceProvider +import org.eclipse.keypop.reader.CardReader +import org.eclipse.keypop.reader.ObservableCardReader +import org.eclipse.keypop.reader.ReaderCommunicationException import timber.log.Timber /** diff --git a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/di/ReaderModule.kt b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/di/ReaderModule.kt index 209a735..0af3354 100644 --- a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/di/ReaderModule.kt +++ b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/di/ReaderModule.kt @@ -29,17 +29,14 @@ class ReaderModule { fun provideLocalServiceClient( keypleSyncEndPointClient: KeypleSyncEndPointClient ): LocalServiceClient { - if (!SmartCardServiceProvider.getService() - .isDistributedLocalServiceRegistered("localService")) { - SmartCardServiceProvider.getService() - .registerDistributedLocalService( - LocalServiceClientFactoryBuilder.builder("localService") - .withSyncNode(keypleSyncEndPointClient) - .build()) - } - return SmartCardServiceProvider.getService() - .getDistributedLocalService("localService") - .getExtension(LocalServiceClient::class.java) + val smartCardService = SmartCardServiceProvider.getService() + val localService = + smartCardService.getDistributedLocalService("localService") + ?: smartCardService.registerDistributedLocalService( + LocalServiceClientFactoryBuilder.builder("localService") + .withSyncNode(keypleSyncEndPointClient) + .build()) + return localService.getExtension(LocalServiceClient::class.java) } @Provides diff --git a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/domain/TicketingService.kt b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/domain/TicketingService.kt index 6afd93c..c34694f 100644 --- a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/domain/TicketingService.kt +++ b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/domain/TicketingService.kt @@ -18,25 +18,26 @@ import kotlin.jvm.Throws import org.calypsonet.keyple.demo.common.constant.CardConstant import org.calypsonet.keyple.demo.reload.remote.data.ReaderRepository import org.calypsonet.keyple.demo.reload.remote.di.scopes.AppScoped -import org.calypsonet.terminal.calypso.card.CalypsoCard -import org.calypsonet.terminal.calypso.transaction.CardTransactionManager import org.eclipse.keyple.card.calypso.CalypsoExtensionService import org.eclipse.keyple.core.service.SmartCardServiceProvider +import org.eclipse.keypop.calypso.card.card.CalypsoCard @AppScoped class TicketingService @Inject constructor(private var readerRepository: ReaderRepository) { /** Select card and retrieve CalypsoPO */ @Throws(IllegalStateException::class, Exception::class) - fun getTransactionManager( + fun getCalypsoCard( readerName: String, aidEnums: ArrayList, protocol: String? - ): CardTransactionManager { + ): CalypsoCard { with(ReaderRepository.getReader(readerName)) { if (isCardPresent) { val smartCardService = SmartCardServiceProvider.getService() + val readerApiFactory = smartCardService.readerApiFactory + val reader = ReaderRepository.getReader(readerName) /** Get the generic card extension service */ @@ -45,23 +46,25 @@ class TicketingService @Inject constructor(private var readerRepository: ReaderR /** Verify that the extension's API level is consistent with the current service. */ smartCardService.checkCardExtension(calypsoExtension) - val cardSelectionManager = smartCardService.createCardSelectionManager() + val cardSelectionManager = readerApiFactory.createCardSelectionManager() aidEnums.forEach { /** * Generic selection: configures a CardSelector with all the desired attributes to make * the selection and read additional information afterwards */ - val cardSelection = + val cardSelector = if (protocol != null) { - calypsoExtension - .createCardSelection() + readerApiFactory + .createIsoCardSelector() .filterByDfName(it) .filterByCardProtocol(protocol) } else { - calypsoExtension.createCardSelection().filterByDfName(it) + readerApiFactory.createIsoCardSelector().filterByDfName(it) } - cardSelectionManager.prepareSelection(cardSelection) + cardSelectionManager.prepareSelection( + cardSelector, + calypsoExtension.calypsoCardApiFactory.createCalypsoCardSelectionExtension()) } val selectionResult = cardSelectionManager.processCardSelectionScenario(reader) @@ -72,8 +75,7 @@ class TicketingService @Inject constructor(private var readerRepository: ReaderR aidEnums[selectionResult.activeSelectionIndex], calypsoCard.dfName)) { throw IllegalStateException("Unexpected DF name") } - return calypsoExtension.createCardTransactionWithoutSecurity( - reader, selectionResult.activeSmartCard as CalypsoCard) + return calypsoCard } else { throw IllegalStateException("Selection error: AID not found") } diff --git a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/AbstractCardActivity.kt b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/AbstractCardActivity.kt index 939b6bf..44300da 100644 --- a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/AbstractCardActivity.kt +++ b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/AbstractCardActivity.kt @@ -20,10 +20,6 @@ import org.calypsonet.keyple.demo.reload.remote.data.model.AppSettings import org.calypsonet.keyple.demo.reload.remote.data.model.CardReaderResponse import org.calypsonet.keyple.demo.reload.remote.data.model.DeviceEnum import org.calypsonet.keyple.demo.reload.remote.data.model.Status -import org.calypsonet.terminal.reader.ConfigurableCardReader -import org.calypsonet.terminal.reader.ObservableCardReader -import org.calypsonet.terminal.reader.spi.CardReaderObservationExceptionHandlerSpi -import org.calypsonet.terminal.reader.spi.CardReaderObserverSpi import org.eclipse.keyple.core.service.KeyplePluginException import org.eclipse.keyple.distributed.LocalServiceClient import org.eclipse.keyple.plugin.android.nfc.AndroidNfcPlugin @@ -33,6 +29,10 @@ import org.eclipse.keyple.plugin.android.nfc.AndroidNfcSupportedProtocols import org.eclipse.keyple.plugin.android.omapi.AndroidOmapiPlugin import org.eclipse.keyple.plugin.android.omapi.AndroidOmapiPluginFactoryProvider import org.eclipse.keyple.plugin.android.omapi.AndroidOmapiReader +import org.eclipse.keypop.reader.ConfigurableCardReader +import org.eclipse.keypop.reader.ObservableCardReader +import org.eclipse.keypop.reader.spi.CardReaderObservationExceptionHandlerSpi +import org.eclipse.keypop.reader.spi.CardReaderObserverSpi import timber.log.Timber abstract class AbstractCardActivity : diff --git a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/CardReaderActivity.kt b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/CardReaderActivity.kt index 9cc4e7c..9f5195d 100644 --- a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/CardReaderActivity.kt +++ b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/CardReaderActivity.kt @@ -38,10 +38,10 @@ import org.calypsonet.keyple.demo.reload.remote.data.model.* import org.calypsonet.keyple.demo.reload.remote.di.scopes.ActivityScoped import org.calypsonet.keyple.demo.reload.remote.domain.TicketingService import org.calypsonet.keyple.demo.reload.remote.ui.cardsummary.CardSummaryActivity -import org.calypsonet.terminal.reader.CardReaderEvent -import org.calypsonet.terminal.reader.ReaderCommunicationException import org.eclipse.keyple.core.service.KeyplePluginException import org.eclipse.keyple.core.util.HexUtil +import org.eclipse.keypop.reader.CardReaderEvent +import org.eclipse.keypop.reader.ReaderCommunicationException import timber.log.Timber @ActivityScoped @@ -128,15 +128,15 @@ class CardReaderActivity : AbstractCardActivity() { ) { withContext(Dispatchers.IO) { try { - val transactionManager = - ticketingService.getTransactionManager(selectedDeviceReaderName, aidEnums, protocol) + val calypsoCard = + ticketingService.getCalypsoCard(selectedDeviceReaderName, aidEnums, protocol) val analyseContractsInput = AnalyzeContractsInputDto(pluginType) // un-mock for run val compatibleContractOutput = localServiceClient.executeRemoteService( RemoteServiceId.READ_CARD_AND_ANALYZE_CONTRACTS.name, selectedDeviceReaderName, - transactionManager.calypsoCard, + calypsoCard, analyseContractsInput, AnalyzeContractsOutputDto::class.java) @@ -154,7 +154,7 @@ class CardReaderActivity : AbstractCardActivity() { changeDisplay( CardReaderResponse( status, "", contracts.size, buildCardTitles(contracts), arrayListOf(), ""), - HexUtil.toHex(transactionManager.calypsoCard.applicationSerialNumber), + HexUtil.toHex(calypsoCard!!.applicationSerialNumber), finishActivity) } } // success, @@ -165,7 +165,7 @@ class CardReaderActivity : AbstractCardActivity() { launchInvalidCardResponse( String.format( getString(R.string.card_invalid_structure), - HexUtil.toHex(transactionManager.calypsoCard.applicationSubtype))) + HexUtil.toHex(calypsoCard!!.applicationSubtype))) } // card rejected 3 -> { launchInvalidCardResponse(getString(R.string.card_not_personalized)) diff --git a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/PersonalizationActivity.kt b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/PersonalizationActivity.kt index 30be74f..73f9550 100644 --- a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/PersonalizationActivity.kt +++ b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/PersonalizationActivity.kt @@ -32,8 +32,8 @@ import org.calypsonet.keyple.demo.reload.remote.data.model.DeviceEnum import org.calypsonet.keyple.demo.reload.remote.data.model.Status import org.calypsonet.keyple.demo.reload.remote.di.scopes.ActivityScoped import org.calypsonet.keyple.demo.reload.remote.domain.TicketingService -import org.calypsonet.terminal.reader.CardReaderEvent import org.eclipse.keyple.core.util.HexUtil +import org.eclipse.keypop.reader.CardReaderEvent import timber.log.Timber @ActivityScoped @@ -126,14 +126,14 @@ class PersonalizationActivity : AbstractCardActivity() { ) { withContext(Dispatchers.IO) { try { - val transactionManager = - ticketingService.getTransactionManager(selectedDeviceReaderName, aidEnums, protocol) + val calypsoCard = + ticketingService.getCalypsoCard(selectedDeviceReaderName, aidEnums, protocol) val cardIssuanceInput = CardIssuanceInputDto(pluginType) val cardIssuanceOutput = localServiceClient.executeRemoteService( RemoteServiceId.PERSONALIZE_CARD.name, selectedDeviceReaderName, - transactionManager.calypsoCard, + calypsoCard, cardIssuanceInput, CardIssuanceOutputDto::class.java) when (cardIssuanceOutput.statusCode) { @@ -141,8 +141,7 @@ class PersonalizationActivity : AbstractCardActivity() { runOnUiThread { changeDisplay( CardReaderResponse(Status.SUCCESS, "", 0, arrayListOf(), arrayListOf(), ""), - applicationSerialNumber = - HexUtil.toHex(transactionManager.calypsoCard.applicationSerialNumber), + applicationSerialNumber = HexUtil.toHex(calypsoCard!!.applicationSerialNumber), finishActivity = true) } } // success, @@ -153,7 +152,7 @@ class PersonalizationActivity : AbstractCardActivity() { launchInvalidCardResponse( String.format( getString(R.string.card_invalid_structure), - HexUtil.toHex(transactionManager.calypsoCard.applicationSubtype))) + HexUtil.toHex(calypsoCard!!.applicationSubtype))) } // card rejected } } catch (e: IllegalStateException) { diff --git a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/ReloadActivity.kt b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/ReloadActivity.kt index 3661442..9e0c4e4 100644 --- a/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/ReloadActivity.kt +++ b/client/android/app/src/main/kotlin/org/calypsonet/keyple/demo/reload/remote/ui/ReloadActivity.kt @@ -37,8 +37,8 @@ import org.calypsonet.keyple.demo.reload.remote.data.model.DeviceEnum import org.calypsonet.keyple.demo.reload.remote.data.model.Status import org.calypsonet.keyple.demo.reload.remote.di.scopes.ActivityScoped import org.calypsonet.keyple.demo.reload.remote.domain.TicketingService -import org.calypsonet.terminal.reader.CardReaderEvent import org.eclipse.keyple.core.util.HexUtil +import org.eclipse.keypop.reader.CardReaderEvent import timber.log.Timber @ActivityScoped @@ -102,11 +102,9 @@ class ReloadActivity : AbstractCardActivity() { withContext(Dispatchers.IO) { try { val readCardSerialNumber = intent.getStringExtra(CARD_APPLICATION_NUMBER) - - val transactionManager = - ticketingService.getTransactionManager(selectedDeviceReaderName, aidEnums, protocol) - if (HexUtil.toHex(transactionManager.calypsoCard.applicationSerialNumber) != - readCardSerialNumber) { + val calypsoCard = + ticketingService.getCalypsoCard(selectedDeviceReaderName, aidEnums, protocol) + if (HexUtil.toHex(calypsoCard!!.applicationSerialNumber) != readCardSerialNumber) { // Ticket would have been bought for the Card read at step one. // To avoid swapping we check thant loading is done on the same card throw IllegalStateException("Not the same card") @@ -117,7 +115,7 @@ class ReloadActivity : AbstractCardActivity() { localServiceClient.executeRemoteService( RemoteServiceId.READ_CARD_AND_ANALYZE_CONTRACTS.name, selectedDeviceReaderName, - transactionManager.calypsoCard, + calypsoCard, analyseContractsInput, AnalyzeContractsOutputDto::class.java) @@ -133,7 +131,7 @@ class ReloadActivity : AbstractCardActivity() { localServiceClient.executeRemoteService( RemoteServiceId.READ_CARD_AND_WRITE_CONTRACT.name, selectedDeviceReaderName, - transactionManager.calypsoCard, + calypsoCard, writeContractInputDto, WriteContractOutputDto::class.java) @@ -153,7 +151,7 @@ class ReloadActivity : AbstractCardActivity() { launchInvalidCardResponse( String.format( getString(R.string.card_invalid_structure), - HexUtil.toHex(transactionManager.calypsoCard.applicationSubtype))) + HexUtil.toHex(calypsoCard!!.applicationSubtype))) } // card rejected } } catch (e: IllegalStateException) { diff --git a/client/android/gradle.properties b/client/android/gradle.properties index 4ffdf5c..5eedbbb 100644 --- a/client/android/gradle.properties +++ b/client/android/gradle.properties @@ -1,4 +1,4 @@ -version = 2023.05.31 +version = 2023.12.04 archivesBaseName = keyple-demo-remote-client-android # Project-wide Gradle settings. diff --git a/client/dotnet/domain/api/MainServiceApiAdapter.cs b/client/dotnet/domain/api/MainServiceApiAdapter.cs index 6a26422..e06998f 100644 --- a/client/dotnet/domain/api/MainServiceApiAdapter.cs +++ b/client/dotnet/domain/api/MainServiceApiAdapter.cs @@ -369,15 +369,15 @@ private CardResponse ProcessCardRequest(CardRequest cardRequest, ChannelControl throw new UnexpectedStatusWordException($"Unexpected status word: {apduResponse.StatusWord:X}"); } } - catch (ReaderIOException ex) + catch (ReaderIOException) { _reader.ClosePhysicalChannel(); - throw ex; + throw; } - catch (CardIOException ex) + catch (CardIOException) { _reader.ClosePhysicalChannel(); - throw ex; + throw; } } diff --git a/server/build.gradle.kts b/server/build.gradle.kts index a8f07e3..0fb7a60 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -46,16 +46,18 @@ dependencies { implementation("org.calypsonet.keyple:keyple-demo-common-lib:2.0.0-SNAPSHOT") { isChanging = true } // Keyple dependencies - implementation("org.calypsonet.terminal:calypsonet-terminal-reader-java-api:1.3.0") - implementation("org.calypsonet.terminal:calypsonet-terminal-calypso-java-api:1.8.0") + implementation("org.eclipse.keypop:keypop-reader-java-api:2.0.0") + implementation("org.eclipse.keypop:keypop-calypso-card-java-api:2.0.0") + implementation("org.eclipse.keypop:keypop-calypso-crypto-legacysam-java-api:0.3.0") implementation("org.eclipse.keyple:keyple-common-java-api:2.0.0") - implementation("org.eclipse.keyple:keyple-service-java-lib:2.3.1") - implementation("org.eclipse.keyple:keyple-service-resource-java-lib:2.1.1") - implementation("org.eclipse.keyple:keyple-distributed-network-java-lib:2.2.0") - implementation("org.eclipse.keyple:keyple-distributed-remote-java-lib:2.2.1") - implementation("org.eclipse.keyple:keyple-card-calypso-java-lib:2.3.5") + implementation("org.eclipse.keyple:keyple-service-java-lib:3.0.0") + implementation("org.eclipse.keyple:keyple-service-resource-java-lib:3.0.0") + implementation("org.eclipse.keyple:keyple-distributed-network-java-lib:2.3.0") + implementation("org.eclipse.keyple:keyple-distributed-remote-java-lib:2.3.0") + implementation("org.eclipse.keyple:keyple-card-calypso-java-lib:3.0.0") + implementation("org.eclipse.keyple:keyple-card-calypso-crypto-legacysam-java-lib:0.4.0") implementation("org.eclipse.keyple:keyple-plugin-pcsc-java-lib:2.1.2") - implementation("org.eclipse.keyple:keyple-util-java-lib:2.3.0") + implementation("org.eclipse.keyple:keyple-util-java-lib:2.3.1") // Quarkus implementation(enforcedPlatform("io.quarkus:quarkus-universe-bom:1.8.1.Final")) implementation("io.quarkus:quarkus-resteasy-jsonb") diff --git a/server/dashboard-app/package.json b/server/dashboard-app/package.json index c5e007c..2d742df 100644 --- a/server/dashboard-app/package.json +++ b/server/dashboard-app/package.json @@ -1,6 +1,6 @@ { "name": "dashboard-app", - "version": "2023.05.31", + "version": "2023.12.04", "private": true, "dependencies": { "@material-ui/core": "^4.11.3", diff --git a/server/gradle.properties b/server/gradle.properties index e9c7377..468dcd5 100644 --- a/server/gradle.properties +++ b/server/gradle.properties @@ -1,4 +1,5 @@ -version = 2023.05.31 +# don't forget to keep the version string in server/dashboard-app/src/package.json synchronized with the following +version = 2023.12.04 title = "Keyple Reload Demo - Remote Server" archivesBaseName = keyple-demo-remote-server diff --git a/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardConfigurator.java b/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardConfigurator.java index a53fffb..7231dcb 100644 --- a/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardConfigurator.java +++ b/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardConfigurator.java @@ -19,11 +19,8 @@ import org.calypsonet.keyple.demo.common.dto.CardIssuanceInputDto; import org.calypsonet.keyple.demo.common.dto.SelectAppAndIncreaseContractCounterInputDto; import org.calypsonet.keyple.demo.common.dto.WriteContractInputDto; -import org.calypsonet.terminal.calypso.card.CalypsoCard; -import org.calypsonet.terminal.calypso.sam.CalypsoSam; -import org.calypsonet.terminal.reader.CardReader; -import org.calypsonet.terminal.reader.spi.CardReaderObservationExceptionHandlerSpi; -import org.eclipse.keyple.card.calypso.CalypsoExtensionService; +import org.eclipse.keyple.card.calypso.crypto.legacysam.LegacySamExtensionService; +import org.eclipse.keyple.card.calypso.crypto.legacysam.LegacySamUtil; import org.eclipse.keyple.core.service.*; import org.eclipse.keyple.core.service.resource.*; import org.eclipse.keyple.core.service.resource.spi.CardResourceProfileExtension; @@ -35,6 +32,10 @@ import org.eclipse.keyple.distributed.RemoteReaderServer; import org.eclipse.keyple.plugin.pcsc.PcscPluginFactoryBuilder; import org.eclipse.keyple.plugin.pcsc.PcscReader; +import org.eclipse.keypop.calypso.card.card.CalypsoCard; +import org.eclipse.keypop.calypso.crypto.legacysam.sam.LegacySam; +import org.eclipse.keypop.reader.CardReader; +import org.eclipse.keypop.reader.spi.CardReaderObservationExceptionHandlerSpi; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -87,13 +88,16 @@ private void setupCardResourceService(Plugin plugin) { plugin.getName(), samReaderFilter, SAM_RESOURCE_PROFILE_NAME); + // Create a card resource extension expecting a SAM "C1". CardResourceProfileExtension samResourceProfileExtension = - CalypsoExtensionService.getInstance() - .createSamResourceProfileExtension( - CalypsoExtensionService.getInstance() - .createSamSelection() - .filterByProductType(CalypsoSam.ProductType.SAM_C1)); + LegacySamExtensionService.getInstance() + .createLegacySamResourceProfileExtension( + LegacySamExtensionService.getInstance() + .getLegacySamApiFactory() + .createLegacySamSelectionExtension(), + LegacySamUtil.buildPowerOnDataFilter(LegacySam.ProductType.SAM_C1, null)); + // Create a minimalist configuration (no plugin/reader observation) CardResourceService cardResourceService = CardResourceServiceProvider.getService(); cardResourceService diff --git a/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardController.java b/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardController.java index a9b3d41..4bbce3a 100644 --- a/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardController.java +++ b/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardController.java @@ -17,12 +17,12 @@ import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.calypsonet.terminal.reader.CardReader; -import org.calypsonet.terminal.reader.ReaderCommunicationException; import org.eclipse.keyple.core.service.SmartCardServiceProvider; import org.eclipse.keyple.distributed.MessageDto; import org.eclipse.keyple.distributed.RemotePluginServer; import org.eclipse.keyple.distributed.SyncNodeServer; +import org.eclipse.keypop.reader.CardReader; +import org.eclipse.keypop.reader.ReaderCommunicationException; @Path("/card") public class CardController { diff --git a/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardRepository.java b/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardRepository.java index 6d1b073..e692926 100644 --- a/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardRepository.java +++ b/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardRepository.java @@ -27,19 +27,22 @@ import org.calypsonet.keyple.demo.common.parser.ContractStructureParser; import org.calypsonet.keyple.demo.common.parser.EnvironmentHolderStructureParser; import org.calypsonet.keyple.demo.common.parser.EventStructureParser; -import org.calypsonet.terminal.calypso.WriteAccessLevel; -import org.calypsonet.terminal.calypso.card.CalypsoCard; -import org.calypsonet.terminal.calypso.card.FileData; -import org.calypsonet.terminal.calypso.sam.CalypsoSam; -import org.calypsonet.terminal.calypso.transaction.CardSecuritySetting; -import org.calypsonet.terminal.calypso.transaction.CardTransactionManager; -import org.calypsonet.terminal.reader.CardReader; -import org.calypsonet.terminal.reader.selection.CardSelectionManager; -import org.calypsonet.terminal.reader.selection.CardSelectionResult; import org.eclipse.keyple.card.calypso.CalypsoExtensionService; -import org.eclipse.keyple.core.service.SmartCardService; +import org.eclipse.keyple.card.calypso.crypto.legacysam.LegacySamExtensionService; import org.eclipse.keyple.core.service.SmartCardServiceProvider; import org.eclipse.keyple.core.service.resource.CardResource; +import org.eclipse.keypop.calypso.card.CalypsoCardApiFactory; +import org.eclipse.keypop.calypso.card.WriteAccessLevel; +import org.eclipse.keypop.calypso.card.card.CalypsoCard; +import org.eclipse.keypop.calypso.card.card.FileData; +import org.eclipse.keypop.calypso.card.transaction.ChannelControl; +import org.eclipse.keypop.calypso.card.transaction.SecureRegularModeTransactionManager; +import org.eclipse.keypop.calypso.card.transaction.SymmetricCryptoSecuritySetting; +import org.eclipse.keypop.calypso.crypto.legacysam.sam.LegacySam; +import org.eclipse.keypop.reader.CardReader; +import org.eclipse.keypop.reader.ReaderApiFactory; +import org.eclipse.keypop.reader.selection.CardSelectionManager; +import org.eclipse.keypop.reader.selection.CardSelectionResult; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,39 +55,38 @@ public class CardRepository { private static final String CALYPSO_SESSION_CLOSED = "Calypso Session Closed."; private static CardSelectionManager createCardSelectionManager() { - SmartCardService smartCardService = SmartCardServiceProvider.getService(); - - CalypsoExtensionService calypsoCardService = CalypsoExtensionService.getInstance(); - - CardSelectionManager cardSelectionManager = smartCardService.createCardSelectionManager(); + ReaderApiFactory readerApiFactory = SmartCardServiceProvider.getService().getReaderApiFactory(); + CardSelectionManager cardSelectionManager = readerApiFactory.createCardSelectionManager(); + CalypsoCardApiFactory calypsoCardApiFactory = + CalypsoExtensionService.getInstance().getCalypsoCardApiFactory(); cardSelectionManager.prepareSelection( - calypsoCardService - .createCardSelection() - .acceptInvalidatedCard() - .filterByDfName(CardConstant.Companion.getAID_KEYPLE_GENERIC())); + readerApiFactory + .createIsoCardSelector() + .filterByDfName(CardConstant.Companion.getAID_KEYPLE_GENERIC()), + calypsoCardApiFactory.createCalypsoCardSelectionExtension().acceptInvalidatedCard()); cardSelectionManager.prepareSelection( - calypsoCardService - .createCardSelection() - .acceptInvalidatedCard() - .filterByDfName(CardConstant.Companion.getAID_CALYPSO_LIGHT())); + readerApiFactory + .createIsoCardSelector() + .filterByDfName(CardConstant.Companion.getAID_CALYPSO_LIGHT()), + calypsoCardApiFactory.createCalypsoCardSelectionExtension().acceptInvalidatedCard()); cardSelectionManager.prepareSelection( - calypsoCardService - .createCardSelection() - .acceptInvalidatedCard() - .filterByDfName(CardConstant.Companion.getAID_CD_LIGHT_GTML())); + readerApiFactory + .createIsoCardSelector() + .filterByDfName(CardConstant.Companion.getAID_CD_LIGHT_GTML()), + calypsoCardApiFactory.createCalypsoCardSelectionExtension().acceptInvalidatedCard()); cardSelectionManager.prepareSelection( - calypsoCardService - .createCardSelection() - .acceptInvalidatedCard() - .filterByDfName(CardConstant.Companion.getAID_NORMALIZED_IDF())); + readerApiFactory + .createIsoCardSelector() + .filterByDfName(CardConstant.Companion.getAID_NORMALIZED_IDF()), + calypsoCardApiFactory.createCalypsoCardSelectionExtension().acceptInvalidatedCard()); return cardSelectionManager; } - public CalypsoCard selectCard(CardReader cardReader) { + CalypsoCard selectCard(CardReader cardReader) { CardSelectionManager cardSelectionManager = createCardSelectionManager(); // Actual card communication: run the selection scenario. CardSelectionResult selectionResult = @@ -99,10 +101,10 @@ public CalypsoCard selectCard(CardReader cardReader) { return (CalypsoCard) selectionResult.getActiveSmartCard(); } - public Card readCard(CardReader cardReader, CalypsoCard calypsoCard, CardResource samResource) { + Card readCard(CardReader cardReader, CalypsoCard calypsoCard, CardResource samResource) { int contractCount = getContractCount(calypsoCard); - CardTransactionManager cardTransactionManager = + SecureRegularModeTransactionManager cardTransactionManager = initCardTransactionManager(cardReader, calypsoCard, samResource); logger.info("Open Calypso Session (LOAD)..."); @@ -114,16 +116,16 @@ public Card readCard(CardReader cardReader, CalypsoCard calypsoCard, CardResourc CardConstant.SFI_CONTRACTS, 1, contractCount, CardConstant.CONTRACT_RECORD_SIZE_BYTES) .prepareReadCounter(CardConstant.SFI_COUNTERS, contractCount) .prepareCloseSecureSession() - .processCommands(false); + .processCommands(ChannelControl.KEEP_OPEN); logger.info(CALYPSO_SESSION_CLOSED); return parse(calypsoCard); } - public int writeCard( + int writeCard( CardReader cardReader, CalypsoCard calypsoCard, CardResource samResource, Card card) { - CardTransactionManager cardTransactionManager = + SecureRegularModeTransactionManager cardTransactionManager = initCardTransactionManager(cardReader, calypsoCard, samResource); logger.info("Open Calypso Session (LOAD)..."); @@ -157,15 +159,15 @@ public int writeCard( new EventStructureParser().generate(buildEvent(card.getEvent(), card.getContracts()))); } - cardTransactionManager.prepareCloseSecureSession().processCommands(false); + cardTransactionManager.prepareCloseSecureSession().processCommands(ChannelControl.KEEP_OPEN); logger.info(CALYPSO_SESSION_CLOSED); return 0; } - public void initCard(CardReader cardReader, CalypsoCard calypsoCard, CardResource samResource) { + void initCard(CardReader cardReader, CalypsoCard calypsoCard, CardResource samResource) { - CardTransactionManager cardTransactionManager = + SecureRegularModeTransactionManager cardTransactionManager = initCardTransactionManager(cardReader, calypsoCard, samResource); logger.info("Open Calypso Session (PERSONALIZATION)..."); @@ -192,27 +194,30 @@ public void initCard(CardReader cardReader, CalypsoCard calypsoCard, CardResourc cardTransactionManager.prepareUpdateRecord( CardConstant.SFI_COUNTERS, 1, new byte[contractCount * 3]); - cardTransactionManager.prepareCloseSecureSession().processCommands(false); + cardTransactionManager.prepareCloseSecureSession().processCommands(ChannelControl.KEEP_OPEN); logger.info(CALYPSO_SESSION_CLOSED); } @NotNull - private CardTransactionManager initCardTransactionManager( + private SecureRegularModeTransactionManager initCardTransactionManager( CardReader cardReader, CalypsoCard calypsoCard, CardResource samResource) { - - CardSecuritySetting cardSecuritySetting = - CalypsoExtensionService.getInstance() - .createCardSecuritySetting() + CalypsoCardApiFactory calypsoCardApiFactory = + CalypsoExtensionService.getInstance().getCalypsoCardApiFactory(); + SymmetricCryptoSecuritySetting cardSecuritySetting = + calypsoCardApiFactory + .createSymmetricCryptoSecuritySetting( + LegacySamExtensionService.getInstance() + .getLegacySamApiFactory() + .createSymmetricCryptoCardTransactionManagerFactory( + samResource.getReader(), (LegacySam) samResource.getSmartCard())) .enableMultipleSession() .assignDefaultKif( WriteAccessLevel.PERSONALIZATION, CardConstant.DEFAULT_KIF_PERSONALIZATION) .assignDefaultKif(WriteAccessLevel.LOAD, CardConstant.DEFAULT_KIF_LOAD) - .assignDefaultKif(WriteAccessLevel.DEBIT, CardConstant.DEFAULT_KIF_DEBIT) - .setControlSamResource( - samResource.getReader(), (CalypsoSam) samResource.getSmartCard()); + .assignDefaultKif(WriteAccessLevel.DEBIT, CardConstant.DEFAULT_KIF_DEBIT); - return CalypsoExtensionService.getInstance() - .createCardTransaction(cardReader, calypsoCard, cardSecuritySetting); + return calypsoCardApiFactory.createSecureRegularModeTransactionManager( + cardReader, calypsoCard, cardSecuritySetting); } private EnvironmentHolderStructure buildEnvironmentHolderStructure() { diff --git a/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardService.java b/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardService.java index 8f7f899..975e011 100644 --- a/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardService.java +++ b/server/src/main/java/org/calypsonet/keyple/demo/reload/remote/server/card/CardService.java @@ -26,11 +26,11 @@ import org.calypsonet.keyple.demo.common.model.type.VersionNumber; import org.calypsonet.keyple.demo.reload.remote.server.activity.Activity; import org.calypsonet.keyple.demo.reload.remote.server.activity.ActivityService; -import org.calypsonet.terminal.calypso.card.CalypsoCard; -import org.calypsonet.terminal.reader.CardReader; import org.eclipse.keyple.core.service.resource.CardResource; import org.eclipse.keyple.core.service.resource.CardResourceServiceProvider; import org.eclipse.keyple.core.util.HexUtil; +import org.eclipse.keypop.calypso.card.card.CalypsoCard; +import org.eclipse.keypop.reader.CardReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,9 +43,6 @@ public class CardService { private static final String SECURED_READ = "SECURED READ"; private static final String RELOAD = "RELOAD"; private static final String ISSUANCE = "ISSUANCE"; - private static final String AID = "315449432E49434131"; - private static final String AN_ERROR_OCCURRED_WHILE_READING_THE_CARD_CONTENT = - "An error occurred while reading the card content: {}"; private static final String AN_ERROR_OCCURRED_WHILE_INCREASING_THE_CONTRACT_COUNTER = "An error occurred while increasing the contract counter: {}"; private static final String AN_ERROR_OCCURRED_WHILE_ANALYZING_THE_CONTRACTS =