diff --git a/Gemfile b/Gemfile index 7a118b49be..cdd3a6b349 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,6 @@ source "https://rubygems.org" gem "fastlane" + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/app/build.gradle b/app/build.gradle index a3a738a121..4e81272cfe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,8 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' -apply plugin: 'io.fabric' +apply plugin: 'com.google.firebase.crashlytics' +apply plugin: 'com.google.gms.google-services' static def generateVersionName() { def gitCommitsCount = "git rev-list HEAD --count".execute().text.trim() @@ -29,24 +30,17 @@ android { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.debug - buildConfigField 'boolean', 'CRASHLYTICS', 'Boolean.parseBoolean("false")' - ext.enableCrashlytics = false } debug { debuggable true minifyEnabled false applicationIdSuffix ".dev" signingConfig signingConfigs.debug - buildConfigField 'boolean', 'CRASHLYTICS', 'Boolean.parseBoolean("false")' - ext.enableCrashlytics = false } debug_beta { initWith debug versionNameSuffix "-beta" applicationIdSuffix ".debug" - buildConfigField 'boolean', 'CRASHLYTICS', 'Boolean.parseBoolean("true")' - manifestPlaceholders = [fabric_api_key: properties.hasProperty('fabric_api_key') - ? project.property('fabric_api_key') : '000'] } } flavorDimensions "" @@ -75,7 +69,6 @@ android { repositories { maven { url "https://jitpack.io" } - maven { url 'https://maven.fabric.io/public' } } configurations { all*.exclude group: 'com.google.guava', module: 'listenablefuture' @@ -133,8 +126,8 @@ dependencies { // implementation 'com.github.stellar:java-stellar-sdk:0.4.1' implementation 'net.i2p.crypto:eddsa:0.3.0' - implementation('com.crashlytics.sdk.android:crashlytics:2.9.9') { transitive = true } - implementation('io.fabric.sdk.android:fabric:1.4.0@aar') { transitive = true } + implementation 'com.google.firebase:firebase-analytics:17.2.3' + implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta02' implementation files('libs/ripple-core-0.0.1.jar') //4 dependencies for ripple-core TODO: move to module? diff --git a/app/src/debug_beta/AndroidManifest.xml b/app/src/debug_beta/AndroidManifest.xml index 9f07ca1097..8cf74b318f 100644 --- a/app/src/debug_beta/AndroidManifest.xml +++ b/app/src/debug_beta/AndroidManifest.xml @@ -7,10 +7,6 @@ - - ) -> Unit) { - if (this.config.issuer == null) { - callback(TaskEvent.Completion(TaskError.IssuerIsRequired())) - return - } - val personalizationCommand = PersonalizeCommand(config, cardId) + val personalizationCommand = PersonalizeCommand(config, issuer, manufacturer, acquirer) val task = SingleCommandTask(personalizationCommand) task.performPreflightRead = false runTask(task, cardId, callback = callback) @@ -320,10 +322,7 @@ class CardManager( val terminalKeys = if (config.linkedTerminal) terminalKeysService?.getKeys() else null return CardEnvironment( cardId = cardId, - terminalKeys = terminalKeys, - manufacturerKeyPair = config.manufacturerKeyPair, - acquirerKeyPair = config.acquirerKeyPair, - issuer = config.issuer + terminalKeys = terminalKeys ) } diff --git a/tangem-core/src/main/java/com/tangem/Config.kt b/tangem-core/src/main/java/com/tangem/Config.kt index 2067f61920..2d1193e176 100644 --- a/tangem-core/src/main/java/com/tangem/Config.kt +++ b/tangem-core/src/main/java/com/tangem/Config.kt @@ -1,12 +1,6 @@ package com.tangem -import com.tangem.commands.personalization.entities.Issuer -import com.tangem.common.KeyPair - class Config( val linkedTerminal: Boolean = true, - val issuerPublicKey: ByteArray? = null, - val manufacturerKeyPair: KeyPair? = null, - val acquirerKeyPair: KeyPair? = null, - val issuer: Issuer? = null + val issuerPublicKey: ByteArray? = null ) \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt index ba5954fe01..656c1750f0 100644 --- a/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt @@ -9,9 +9,6 @@ import com.tangem.common.tlv.TlvMapper import com.tangem.common.tlv.TlvTag import com.tangem.tasks.TaskError -/** -[REDACTED_AUTHOR] - */ class ReadUserDataResponse( /** * CID, Unique Tangem card ID number. diff --git a/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt index 804abf6601..ac79cba45c 100644 --- a/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt @@ -9,10 +9,6 @@ import com.tangem.common.tlv.TlvMapper import com.tangem.common.tlv.TlvTag import com.tangem.tasks.TaskError -/** -[REDACTED_AUTHOR] - */ - class WriteUserDataResponse( /** * CID, Unique Tangem card ID number. diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/CardConfig.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/CardConfig.kt deleted file mode 100644 index 15548f9871..0000000000 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/CardConfig.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.tangem.commands.personalization - -import com.tangem.commands.* - -data class NdefRecord( - val type: Type, - val value: String -) { - enum class Type { - URI, AAR, TEXT - } - - val valueInBytes: ByteArray by lazy { value.toByteArray() } -} - -/** - * It is a configuration file with all the card settings that are written on the card - * during [PersonalizeCommand]. - */ -data class CardConfig( - val issuerName: String? = null, - val acquirerName: String? = null, - val series: String? = null, - val startNumber: Long = 0, - val count: Int = 0, - val pin: String, - val pin2: String, - val pin3: String, - val hexCrExKey: String?, - val cvc: String, - val pauseBeforePin2: Int, - val smartSecurityDelay: Boolean, - val curveID: EllipticCurve, - val signingMethod: SigningMethod, - val maxSignatures: Int, - val isReusable: Boolean, - val allowSwapPin: Boolean, - val allowSwapPin2: Boolean, - val useActivation: Boolean, - val useCvc: Boolean, - val useNdef: Boolean, - val useDynamicNdef: Boolean, - val useOneCommandAtTime: Boolean, - val useBlock: Boolean, - val allowSelectBlockchain: Boolean, - val forbidPurgeWallet: Boolean, - val protocolAllowUnencrypted: Boolean, - val protocolAllowStaticEncryption: Boolean, - val protectIssuerDataAgainstReplay: Boolean, - val forbidDefaultPin: Boolean, - val disablePrecomputedNdef: Boolean, - val skipSecurityDelayIfValidatedByIssuer: Boolean, - val skipCheckPIN2andCVCIfValidatedByIssuer: Boolean, - val skipSecurityDelayIfValidatedByLinkedTerminal: Boolean, - - val restrictOverwriteIssuerDataEx: Boolean, - - val requireTerminalTxSignature: Boolean, - val requireTerminalCertSignature: Boolean, - val checkPin3onCard: Boolean, - - val createWallet: Boolean, - - val cardData: CardData, - val ndefRecords: List -) { - - fun getSettingsMask(): SettingsMask { - val builder = SettingsMaskBuilder() - - if (allowSwapPin) builder.add(Settings.AllowSwapPIN) - if (allowSwapPin2) builder.add(Settings.AllowSwapPIN2) - if (useCvc) builder.add(Settings.UseCVC) - if (isReusable) builder.add(Settings.IsReusable) - - if (useOneCommandAtTime) builder.add(Settings.UseOneCommandAtTime) - if (useNdef) builder.add(Settings.UseNdef) - if (useDynamicNdef) builder.add(Settings.UseDynamicNdef) - if (disablePrecomputedNdef) builder.add(Settings.DisablePrecomputedNdef) - - if (protocolAllowUnencrypted) builder.add(Settings.ProtocolAllowUnencrypted) - if (protocolAllowStaticEncryption) builder.add(Settings.ProtocolAllowStaticEncryption) - - if (forbidDefaultPin) builder.add(Settings.ForbidDefaultPIN) - - if (useActivation) builder.add(Settings.UseActivation) - - if (useBlock) builder.add(Settings.UseBlock) - if (smartSecurityDelay) builder.add(Settings.SmartSecurityDelay) - - if (protectIssuerDataAgainstReplay) builder.add(Settings.ProtectIssuerDataAgainstReplay) - - if (forbidPurgeWallet) builder.add(Settings.ForbidPurgeWallet) - if (allowSelectBlockchain) builder.add(Settings.AllowSelectBlockchain) - - if (skipCheckPIN2andCVCIfValidatedByIssuer) builder.add(Settings.SkipCheckPin2andCvcIfValidatedByIssuer) - if (skipSecurityDelayIfValidatedByIssuer) builder.add(Settings.SkipSecurityDelayIfValidatedByIssuer) - - if (skipSecurityDelayIfValidatedByLinkedTerminal) builder.add(Settings.SkipSecurityDelayIfValidatedByLinkedTerminal) - if (restrictOverwriteIssuerDataEx) builder.add(Settings.RestrictOverwriteIssuerDataEx) - - if (requireTerminalTxSignature) builder.add(Settings.RequireTermTxSignature) - - if (requireTerminalCertSignature) builder.add(Settings.RequireTermCertSignature) - - if (checkPin3onCard) builder.add(Settings.CheckPIN3onCard) - - return builder.build() - } - - companion object -} \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/DepersonalizeCommand.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/DepersonalizeCommand.kt index 46239ea4ea..034b28dce5 100644 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/DepersonalizeCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/DepersonalizeCommand.kt @@ -20,8 +20,7 @@ class DepersonalizeCommand : CommandSerializer() { override fun serialize(cardEnvironment: CardEnvironment): CommandApdu { return CommandApdu( - Instruction.Depersonalize, byteArrayOf(), - cardEnvironment.encryptionMode, cardEnvironment.encryptionKey + Instruction.Depersonalize, byteArrayOf() ) } diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/NdefEncoder.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/NdefEncoder.kt index a034d171cb..6c6103556e 100644 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/NdefEncoder.kt +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/NdefEncoder.kt @@ -1,5 +1,6 @@ package com.tangem.commands.personalization +import com.tangem.commands.personalization.entities.NdefRecord import java.io.ByteArrayOutputStream import java.nio.charset.StandardCharsets 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..035963c21a 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 @@ -3,7 +3,7 @@ package com.tangem.commands.personalization 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.entities.* import com.tangem.common.CardEnvironment import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction @@ -23,22 +23,23 @@ import com.tangem.tasks.TaskError * Personalization is an initialization procedure, required before starting using a card. * During this procedure a card setting is set up. * During this procedure all data exchange is encrypted. - * @param config is a configuration file with all the card settings that are written on the card + * @property config is a configuration file with all the card settings that are written on the card * during personalization. - * @param cardId this parameter will set up CID, Unique Tangem card ID. + * @property issuer Issuer is a third-party team or company wishing to use Tangem cards. + * @property manufacturer Tangem Card Manufacturer. + * @property acquirer Acquirer is a trusted third-party company that operates proprietary + * (non-EMV) POS terminal infrastructure and transaction processing back-end. */ -class PersonalizeCommand(private val config: CardConfig, private val cardId: String) : CommandSerializer() { +class PersonalizeCommand( + private val config: CardConfig, + private val issuer: Issuer, private val manufacturer: Manufacturer, + private val acquirer: Acquirer? = null +) : CommandSerializer() { override fun serialize(cardEnvironment: CardEnvironment): CommandApdu { - if (cardEnvironment.issuer == null || cardEnvironment.manufacturerKeyPair == null) { - throw TaskError.SerializeCommandError() - } return CommandApdu( Instruction.Personalize, - serializePersonalizationData( - cardId, config, - cardEnvironment.issuer, cardEnvironment.manufacturerKeyPair.privateKey, - cardEnvironment.acquirerKeyPair?.publicKey), + serializePersonalizationData(config), encryptionKey = devPersonalizationKey ) } @@ -99,20 +100,19 @@ class PersonalizeCommand(private val config: CardConfig, private val cardId: Str ) } - private fun serializePersonalizationData(cardId: String, config: CardConfig, - issuer: Issuer, manufacturerPrivateKey: ByteArray, - acquirePublicKey: ByteArray? - ): ByteArray { + private fun serializePersonalizationData(config: CardConfig): ByteArray { + val cardId = config.createCardId() ?: 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) - tlvBuilder.append(TlvTag.SettingsMask, config.getSettingsMask()) + tlvBuilder.append(TlvTag.SettingsMask, config.createSettingsMask()) tlvBuilder.append(TlvTag.PauseBeforePin2, config.pauseBeforePin2 / 10) tlvBuilder.append(TlvTag.Cvc, config.cvc.toByteArray()) - if (!config.ndefRecords.isNullOrEmpty()) tlvBuilder.append(TlvTag.NdefData, serializeNdef(config.ndefRecords)) + if (!config.ndefRecords.isNullOrEmpty()) + tlvBuilder.append(TlvTag.NdefData, serializeNdef(config)) tlvBuilder.append(TlvTag.CreateWalletAtPersonalize, config.createWallet) @@ -123,25 +123,22 @@ class PersonalizeCommand(private val config: CardConfig, private val cardId: Str tlvBuilder.append(TlvTag.IssuerDataPublicKey, issuer.dataKeyPair.publicKey) tlvBuilder.append(TlvTag.IssuerTransactionPublicKey, issuer.transactionKeyPair.publicKey) - tlvBuilder.append(TlvTag.AcquirerPublicKey, acquirePublicKey) + tlvBuilder.append(TlvTag.AcquirerPublicKey, acquirer?.keyPair?.publicKey) - tlvBuilder.append( - TlvTag.CardData, serializeCardData(cardId, config.cardData, issuer, manufacturerPrivateKey) - ) + tlvBuilder.append(TlvTag.CardData, serializeCardData(cardId, config.cardData)) return tlvBuilder.serialize() } - private fun serializeCardData( - cardId: String, cardData: CardData, - issuer: Issuer, manufacturerPrivateKey: ByteArray): ByteArray { + private fun serializeNdef(config: CardConfig): ByteArray { + return NdefEncoder(config.ndefRecords, config.useDynamicNdef).encode() + } + + private fun serializeCardData(cardId: String, cardData: CardData): ByteArray { val tlvBuilder = TlvBuilder() tlvBuilder.append(TlvTag.Batch, cardData.batchId) tlvBuilder.append(TlvTag.ProductMask, cardData.productMask) - tlvBuilder.append(TlvTag.ManufactureDateTime, cardData.manufactureDateTime) - tlvBuilder.append(TlvTag.IssuerId, issuer.id) - tlvBuilder.append(TlvTag.BlockchainId, cardData.blockchainName) if (cardData.tokenSymbol != null) { @@ -150,15 +147,12 @@ class PersonalizeCommand(private val config: CardConfig, private val cardId: Str tlvBuilder.append(TlvTag.TokenDecimal, cardData.tokenDecimal) } tlvBuilder.append( - TlvTag.CardIdManufacturerSignature, cardId.hexToBytes().sign(manufacturerPrivateKey) + TlvTag.CardIdManufacturerSignature, + cardId.hexToBytes().sign(manufacturer.keyPair.privateKey) ) return tlvBuilder.serialize() } - private fun serializeNdef(ndefRecords: List): ByteArray { - return NdefEncoder(ndefRecords, config.useDynamicNdef).encode() - } - companion object { val devPersonalizationKey = "1234".calculateSha256().copyOf(32) } diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/entities/Acquirer.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/Acquirer.kt new file mode 100644 index 0000000000..cda239b145 --- /dev/null +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/Acquirer.kt @@ -0,0 +1,9 @@ +package com.tangem.commands.personalization.entities + +import com.tangem.common.KeyPair + +data class Acquirer( + val keyPair: KeyPair, + val name: String? = null, + val id: String? = null +) \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfig.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfig.kt new file mode 100644 index 0000000000..bc1a082237 --- /dev/null +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfig.kt @@ -0,0 +1,70 @@ +package com.tangem.commands.personalization.entities + +import com.tangem.commands.CardData +import com.tangem.commands.EllipticCurve +import com.tangem.commands.SigningMethod + +data class NdefRecord( + val type: Type, + val value: String +) { + enum class Type { + URI, AAR, TEXT + } + + val valueInBytes: ByteArray by lazy { value.toByteArray() } +} + +/** + * It is a configuration file with all the card settings that are written on the card + * during [PersonalizeCommand]. + */ +data class CardConfig( + val issuerName: String? = null, + val acquirerName: String? = null, + val series: String? = null, + val startNumber: Long = 0, + val count: Int = 0, + val pin: String, + val pin2: String, + val pin3: String, + val hexCrExKey: String?, + val cvc: String, + val pauseBeforePin2: Int, + val smartSecurityDelay: Boolean, + val curveID: EllipticCurve, + val signingMethod: SigningMethod, + val maxSignatures: Int, + val isReusable: Boolean, + val allowSwapPin: Boolean, + val allowSwapPin2: Boolean, + val useActivation: Boolean, + val useCvc: Boolean, + val useNdef: Boolean, + val useDynamicNdef: Boolean, + val useOneCommandAtTime: Boolean, + val useBlock: Boolean, + val allowSelectBlockchain: Boolean, + val forbidPurgeWallet: Boolean, + val protocolAllowUnencrypted: Boolean, + val protocolAllowStaticEncryption: Boolean, + val protectIssuerDataAgainstReplay: Boolean, + val forbidDefaultPin: Boolean, + val disablePrecomputedNdef: Boolean, + val skipSecurityDelayIfValidatedByIssuer: Boolean, + val skipCheckPIN2andCVCIfValidatedByIssuer: Boolean, + val skipSecurityDelayIfValidatedByLinkedTerminal: Boolean, + + val restrictOverwriteIssuerDataEx: Boolean, + + val requireTerminalTxSignature: Boolean, + val requireTerminalCertSignature: Boolean, + val checkPin3onCard: Boolean, + + val createWallet: Boolean, + + val cardData: CardData, + val ndefRecords: List +) { + companion object +} \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt new file mode 100644 index 0000000000..4d7895f3c4 --- /dev/null +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt @@ -0,0 +1,81 @@ +package com.tangem.commands.personalization.entities + +import com.tangem.commands.Settings +import com.tangem.commands.SettingsMask +import com.tangem.commands.SettingsMaskBuilder + +internal fun CardConfig.createSettingsMask(): SettingsMask { + val builder = SettingsMaskBuilder() + + if (allowSwapPin) builder.add(Settings.AllowSwapPIN) + if (allowSwapPin2) builder.add(Settings.AllowSwapPIN2) + if (useCvc) builder.add(Settings.UseCVC) + if (isReusable) builder.add(Settings.IsReusable) + + if (useOneCommandAtTime) builder.add(Settings.UseOneCommandAtTime) + if (useNdef) builder.add(Settings.UseNdef) + if (useDynamicNdef) builder.add(Settings.UseDynamicNdef) + if (disablePrecomputedNdef) builder.add(Settings.DisablePrecomputedNdef) + + if (protocolAllowUnencrypted) builder.add(Settings.ProtocolAllowUnencrypted) + if (protocolAllowStaticEncryption) builder.add(Settings.ProtocolAllowStaticEncryption) + + if (forbidDefaultPin) builder.add(Settings.ForbidDefaultPIN) + + if (useActivation) builder.add(Settings.UseActivation) + + if (useBlock) builder.add(Settings.UseBlock) + if (smartSecurityDelay) builder.add(Settings.SmartSecurityDelay) + + if (protectIssuerDataAgainstReplay) builder.add(Settings.ProtectIssuerDataAgainstReplay) + + if (forbidPurgeWallet) builder.add(Settings.ForbidPurgeWallet) + if (allowSelectBlockchain) builder.add(Settings.AllowSelectBlockchain) + + if (skipCheckPIN2andCVCIfValidatedByIssuer) builder.add(Settings.SkipCheckPin2andCvcIfValidatedByIssuer) + if (skipSecurityDelayIfValidatedByIssuer) builder.add(Settings.SkipSecurityDelayIfValidatedByIssuer) + + if (skipSecurityDelayIfValidatedByLinkedTerminal) builder.add(Settings.SkipSecurityDelayIfValidatedByLinkedTerminal) + if (restrictOverwriteIssuerDataEx) builder.add(Settings.RestrictOverwriteIssuerDataEx) + + if (requireTerminalTxSignature) builder.add(Settings.RequireTermTxSignature) + + if (requireTerminalCertSignature) builder.add(Settings.RequireTermCertSignature) + + if (checkPin3onCard) builder.add(Settings.CheckPIN3onCard) + + return builder.build() +} + +internal fun CardConfig.createCardId(): String? { + if (series == null) return null + if (startNumber <= 0 || (series.length != 2 && series.length != 4)) return null + + val Alf = "ABCDEF0123456789" + fun checkSeries(series: String): Boolean { + val containsList = series.filter { Alf.contains(it) } + return containsList.length == series.length + } + if (!checkSeries(series)) return null + + val tail = if (series.length == 2) String.format("%013d", startNumber) else String.format("%011d", startNumber) + var cardId = (series + tail).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-core/src/main/java/com/tangem/commands/personalization/entities/Manufacturer.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/Manufacturer.kt new file mode 100644 index 0000000000..bffdde9384 --- /dev/null +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/Manufacturer.kt @@ -0,0 +1,8 @@ +package com.tangem.commands.personalization.entities + +import com.tangem.common.KeyPair + +data class Manufacturer( + val keyPair: KeyPair, + val name: String? = null +) \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/common/CardEnvironment.kt b/tangem-core/src/main/java/com/tangem/common/CardEnvironment.kt index bc507bf9a2..c556f427b3 100644 --- a/tangem-core/src/main/java/com/tangem/common/CardEnvironment.kt +++ b/tangem-core/src/main/java/com/tangem/common/CardEnvironment.kt @@ -1,7 +1,5 @@ package com.tangem.common -import com.tangem.commands.personalization.entities.Issuer - /** * Contains data relating to a Tangem card. It is used in constructing all the commands, @@ -14,10 +12,7 @@ data class CardEnvironment( val terminalKeys: KeyPair? = null, var encryptionMode: EncryptionMode = EncryptionMode.NONE, var encryptionKey: ByteArray? = null, - val cvc: ByteArray? = null, - val manufacturerKeyPair: KeyPair? = null, - val acquirerKeyPair: KeyPair? = null, - val issuer: Issuer? = null + val cvc: ByteArray? = null ) { companion object { diff --git a/tangem-core/src/main/java/com/tangem/tasks/Task.kt b/tangem-core/src/main/java/com/tangem/tasks/Task.kt index b585cd3023..224b163a9a 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/Task.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/Task.kt @@ -141,12 +141,6 @@ sealed class TaskError(val code: Int) : Exception() { * (when the card's requires it), but the counter is missing. */ class MissingCounter : TaskError(7001) - - /** - * This error is returned when [com.tangem.commands.personalization.PersonalizeCommand] is attempted - * without [com.tangem.commands.personalization.entities.Issuer] being set in the [com.tangem.Config]. - */ - class IssuerIsRequired : TaskError(7002) } /** diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/Old_MainActivity.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/Old_MainActivity.kt index 26dc5d312a..b39081b6b0 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/Old_MainActivity.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/Old_MainActivity.kt @@ -4,7 +4,6 @@ import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.tangem.CardManager -import com.tangem.commands.personalization.CardConfig import com.tangem.tangem_sdk_new.extensions.init import com.tangem.tangemtest.extensions.create import com.tangem.tasks.ScanEvent @@ -153,30 +152,6 @@ class Old_MainActivity : AppCompatActivity() { } } btn_read_write_user_data?.setOnClickListener { startActivity(Intent(this, TestUserDataActivity::class.java)) } - btn_personalize?.setOnClickListener { _ -> - cardManager.personalize( - CardConfig.create(application), "BB00000000000395" - ) { - when (it) { - is TaskEvent.Completion -> { - if (it.error != null) runOnUiThread { tv_card_cid?.text = it.error!!::class.simpleName } - } - is TaskEvent.Event -> runOnUiThread { tv_card_cid?.text = it.data.cardId } - } - } - } - btn_depersonalize?.setOnClickListener { _ -> - cardManager.depersonalize(cardId) { - when (it) { - is TaskEvent.Completion -> { - if (it.error != null) runOnUiThread { tv_card_cid?.text = it.error!!::class.simpleName } - } - is TaskEvent.Event -> runOnUiThread { - tv_card_cid?.text = "Depersonalized: ${it.data.success.toString()}" - } - } - } - } } private fun createSampleHashes(): Array { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/CardConfig.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/CardConfig.kt index adda79efbb..c8f68bec9c 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/CardConfig.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/CardConfig.kt @@ -3,8 +3,8 @@ package com.tangem.tangemtest.extensions import android.app.Application import android.content.Context import com.tangem.commands.* -import com.tangem.commands.personalization.CardConfig -import com.tangem.commands.personalization.NdefRecord +import com.tangem.commands.personalization.entities.CardConfig +import com.tangem.commands.personalization.entities.NdefRecord import java.util.* fun CardConfig.Companion.create(application: Application): CardConfig { diff --git a/tangem-demo/src/main/res/layout/activity_main.xml b/tangem-demo/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000000..e69de29bb2