From 5f7612ca57acc3d4d84ae5ef730b8aa62b138605 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 30 Mar 2020 20:09:57 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../src/main/java/com/tangem/CardManager.kt | 6 +-- .../personalization/PersonalizeCommand.kt | 15 +++--- .../personalization/util/CardIdCreator.kt | 49 +++++++++++++++++++ .../com/tangem/tangemtest/MainActivity.kt | 4 +- 4 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 tangem-core/src/main/java/com/tangem/commands/personalization/util/CardIdCreator.kt diff --git a/tangem-core/src/main/java/com/tangem/CardManager.kt b/tangem-core/src/main/java/com/tangem/CardManager.kt index f5d064d4e9..fb97714bc6 100644 --- a/tangem-core/src/main/java/com/tangem/CardManager.kt +++ b/tangem-core/src/main/java/com/tangem/CardManager.kt @@ -262,14 +262,12 @@ class CardManager( * during personalization. * @param cardId this parameter will set up CID, Unique Tangem card ID. */ - fun personalize(config: CardConfig, - cardId: String, - callback: (result: TaskEvent) -> Unit) { + fun personalize(config: CardConfig, callback: (result: TaskEvent) -> Unit) { if (this.config.issuer == null) { callback(TaskEvent.Completion(TaskError.IssuerIsRequired())) return } - val personalizationCommand = PersonalizeCommand(config, cardId) + val personalizationCommand = PersonalizeCommand(config) val task = SingleCommandTask(personalizationCommand) task.performPreflightRead = false runTask(task, callback = callback) diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt index 6bcdd815a5..7e118ae9f0 100644 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt @@ -4,6 +4,7 @@ import com.tangem.commands.Card import com.tangem.commands.CardData import com.tangem.commands.CommandSerializer import com.tangem.commands.personalization.entities.Issuer +import com.tangem.commands.personalization.util.CardIdCreator import com.tangem.common.CardEnvironment import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction @@ -27,7 +28,7 @@ import com.tangem.tasks.TaskError * during personalization. * @param cardId this parameter will set up CID, Unique Tangem card ID. */ -class PersonalizeCommand(private val config: CardConfig, private val cardId: String) : CommandSerializer() { +class PersonalizeCommand(private val config: CardConfig) : CommandSerializer() { override fun serialize(cardEnvironment: CardEnvironment): CommandApdu { if (cardEnvironment.issuer == null || cardEnvironment.manufacturerKeyPair == null) { @@ -36,9 +37,8 @@ class PersonalizeCommand(private val config: CardConfig, private val cardId: Str return CommandApdu( Instruction.Personalize, serializePersonalizationData( - cardId, config, - cardEnvironment.issuer, cardEnvironment.manufacturerKeyPair.privateKey, - cardEnvironment.acquirerKeyPair?.publicKey), + config, cardEnvironment.issuer, + cardEnvironment.manufacturerKeyPair.privateKey, cardEnvironment.acquirerKeyPair?.publicKey), encryptionKey = devPersonalizationKey ) } @@ -99,13 +99,14 @@ class PersonalizeCommand(private val config: CardConfig, private val cardId: Str ) } - private fun serializePersonalizationData(cardId: String, config: CardConfig, - issuer: Issuer, manufacturerPrivateKey: ByteArray, + private fun serializePersonalizationData(config: CardConfig, issuer: Issuer, + manufacturerPrivateKey: ByteArray, acquirePublicKey: ByteArray? ): ByteArray { + val cardId = CardIdCreator.create(config.series, config.startNumber) + ?: throw TaskError.SerializeCommandError() val tlvBuilder = TlvBuilder() tlvBuilder.append(TlvTag.CardId, cardId) - tlvBuilder.append(TlvTag.CurveId, config.curveID) tlvBuilder.append(TlvTag.MaxSignatures, config.maxSignatures) tlvBuilder.append(TlvTag.SigningMethod, config.signingMethod) diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/util/CardIdCreator.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/util/CardIdCreator.kt new file mode 100644 index 0000000000..a95e6f9cfc --- /dev/null +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/util/CardIdCreator.kt @@ -0,0 +1,49 @@ +package com.tangem.commands.personalization.util + +/** +[REDACTED_AUTHOR] + */ +internal class CardIdCreator { + + companion object { + private val Alf = "ABCDEF0123456789" + + fun create(nsSeries: String?, number: Long): String? { + val series = nsSeries ?: return null + if (number <= 0 || (series.length != 2 && series.length != 4)) return null + if (!checkSeries(series)) return null + + val tail = if (series.length == 2) String.format("%013d", number) else String.format("%011d", number) + val cardId = series + tail + return completeCardID(cardId) + } + + private fun checkSeries(series: String): Boolean { + val containsList = series.filter { Alf.contains(it) } + return containsList.length == series.length + } + + private fun completeCardID(imCardId: String): String? { + var cardId = imCardId + cardId = cardId.replace(" ", "") + if (cardId.length != 15 || Alf.indexOf(cardId[0]) == -1 || Alf.indexOf(cardId[1]) == -1) + return null + + cardId += "0" + val length = cardId.length + var sum = 0 + for (i in 0 until length) { + // get digits in reverse order + var digit: Int + val cDigit = cardId[length - i - 1] + digit = if (cDigit in '0'..'9') cDigit - '0' else cDigit - 'A' + + // every 2nd number multiply with 2 + if (i % 2 == 1) digit *= 2 + sum += if (digit > 9) digit - 9 else digit + } + val lunh = (10 - sum % 10) % 10 + return cardId.substring(0, 15) + String.format("%d", lunh) + } + } +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/MainActivity.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/MainActivity.kt index 1a294a8897..402ef369db 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/MainActivity.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/MainActivity.kt @@ -154,9 +154,7 @@ class MainActivity : AppCompatActivity() { } btn_read_write_user_data?.setOnClickListener { startActivity(Intent(this, TestUserDataActivity::class.java)) } btn_personalize?.setOnClickListener { _ -> - cardManager.personalize( - CardConfig.init(application), "BB00000000000395" - ) { + cardManager.personalize(CardConfig.init(application)) { when (it) { is TaskEvent.Completion -> { if (it.error != null) runOnUiThread { tv_card_cid?.text = it.error!!::class.simpleName }