From f426fba287dfa302eb0e878685f9726df0c619e4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 13 Nov 2019 12:50:26 +0300 Subject: [PATCH 1/5] Updated on 2026-08-14 --- .../src/main/java/com/tangem/common/apdu/Instruction.kt | 3 ++- .../src/main/java/com/tangem/common/apdu/StatusWord.kt | 3 ++- tangem-core/src/main/java/com/tangem/common/tlv/TlvTag.kt | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tangem-core/src/main/java/com/tangem/common/apdu/Instruction.kt b/tangem-core/src/main/java/com/tangem/common/apdu/Instruction.kt index 8ce911e5c6..e4669e620b 100644 --- a/tangem-core/src/main/java/com/tangem/common/apdu/Instruction.kt +++ b/tangem-core/src/main/java/com/tangem/common/apdu/Instruction.kt @@ -18,6 +18,7 @@ enum class Instruction(var code: Int) { companion object { - fun byCode(code: Int): Instruction = values().find { it.code == code } ?: Unknown + private val values = values() + fun byCode(code: Int): Instruction = values.find { it.code == code } ?: Unknown } } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt b/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt index 34a0153d49..4cbc0d2a81 100644 --- a/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt +++ b/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt @@ -15,7 +15,8 @@ enum class StatusWord (val code: Int, val description: String){ NeedPause(0x9789, "SW_NEED_PAUSE"); companion object { - fun byCode(code: Int): StatusWord = values().find { it.code == code } ?: InvalidParams + private val values = values() + fun byCode(code: Int): StatusWord = values.find { it.code == code } ?: Unknown } } diff --git a/tangem-core/src/main/java/com/tangem/common/tlv/TlvTag.kt b/tangem-core/src/main/java/com/tangem/common/tlv/TlvTag.kt index 33ecc7a0a2..71eb6d009f 100644 --- a/tangem-core/src/main/java/com/tangem/common/tlv/TlvTag.kt +++ b/tangem-core/src/main/java/com/tangem/common/tlv/TlvTag.kt @@ -108,9 +108,9 @@ enum class TlvTag(val code: Int) { } } - companion object { - fun byCode(code: Int): TlvTag = values().find { it.code == code } ?: Unknown + private val values = values() + fun byCode(code: Int): TlvTag = values.find { it.code == code } ?: Unknown } } From ff4c151e90d1bc67dee15416b4dd8b840e5fc2dd Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 13 Nov 2019 14:22:37 +0300 Subject: [PATCH 2/5] Updated on 2026-08-14 --- .../java/com/tangem/common/tlv/TlvMapper.kt | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tangem-core/src/main/java/com/tangem/common/tlv/TlvMapper.kt b/tangem-core/src/main/java/com/tangem/common/tlv/TlvMapper.kt index 5182afddd6..bec99188c8 100644 --- a/tangem-core/src/main/java/com/tangem/common/tlv/TlvMapper.kt +++ b/tangem-core/src/main/java/com/tangem/common/tlv/TlvMapper.kt @@ -1,14 +1,10 @@ package com.tangem.common.tlv -import com.tangem.commands.CardStatus -import com.tangem.commands.EllipticCurve -import com.tangem.commands.ProductMask -import com.tangem.commands.SigningMethod +import com.tangem.commands.* import com.tangem.common.extentions.toDate import com.tangem.common.extentions.toHexString import com.tangem.common.extentions.toInt import com.tangem.common.extentions.toUtf8 -import com.tangem.data.SettingsMask import java.util.* @@ -16,7 +12,7 @@ open class TlvMapperException(message: String?) : Exception(message) class MissingTagException(message: String? = null) : TlvMapperException(message) class WrongTypeException(message: String? = null) : TlvMapperException(message) -class ConvertionException(message: String? = null) : TlvMapperException(message) +class ConversionException(message: String? = null) : TlvMapperException(message) class TlvMapper(val tlvList: List) { @@ -49,7 +45,11 @@ class TlvMapper(val tlvList: List) { TlvValueType.IntValue -> { if (T::class != Integer::class) throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - tlvValue.toInt() as T + try { + tlvValue.toInt() as T + } catch (exception: IllegalArgumentException) { + throw ConversionException(exception.message) + } } TlvValueType.BoolValue -> { if (T::class != Boolean::class) @@ -64,34 +64,40 @@ class TlvMapper(val tlvList: List) { TlvValueType.EllipticCurve -> { if (T::class != EllipticCurve::class) throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - EllipticCurve.byName(tlvValue.toUtf8()) as T + EllipticCurve.byName(tlvValue.toUtf8()) as? T + ?: throw ConversionException("Unknown Elliptic Curve value: ${tlvValue.toUtf8()}") } TlvValueType.DateTime -> { if (T::class != Date::class) throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - tlvValue.toDate() as T + try { + tlvValue.toDate() as T + } catch (exception: Exception) { + throw ConversionException("Converting to date with the following exception: " + exception.message) + } } TlvValueType.ProductMask -> { if (T::class != ProductMask::class) throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - ProductMask.byCode(tlvValue.first()) as T - + ProductMask.byCode(tlvValue.first()) as? T + ?: throw ConversionException("Unknown Product Mask Code: ${tlvValue.first()}.") } TlvValueType.SettingsMask -> { if (T::class != SettingsMask::class) throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") SettingsMask(tlvValue.toInt()) as T - } TlvValueType.CardStatus -> { if (T::class != CardStatus::class) throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") CardStatus.byCode(tlvValue.toInt()) as T + ?: throw ConversionException("Unknown Card Status with code of: ${tlvValue.toInt()}") } TlvValueType.SigningMethod -> { if (T::class != SigningMethod::class) throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") SigningMethod.byCode(tlvValue.toInt()) as T + ?: throw ConversionException("Unknown Signing Method with code of: ${tlvValue.toInt()}") } } } From bbdcad141066a00ce89a01615ce8d2b2a45f61a4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 13 Nov 2019 14:27:46 +0300 Subject: [PATCH 3/5] Updated on 2026-08-14 --- .../src/main/java/com/tangem/CardManager.kt | 29 +++---- .../java/com/tangem/CardManagerDelegate.kt | 9 +- .../src/main/java/com/tangem/CardReader.kt | 2 +- .../src/main/java/com/tangem/DataStorage.kt | 10 --- .../src/main/java/com/tangem/Response.kt | 16 ---- .../com/tangem/commands/CheckWalletCommand.kt | 13 ++- .../java/com/tangem/commands/SignCommand.kt | 17 ++-- .../com/tangem/common/apdu/CommandApdu.kt | 18 +++- .../java/com/tangem/common/apdu/StatusWord.kt | 4 +- .../main/java/com/tangem/common/tlv/Tlv.kt | 6 +- .../main/java/com/tangem/common/tlv/TlvTag.kt | 14 +++ .../com/tangem/common/tlv/TlvValueType.kt | 15 ---- .../java/com/tangem/crypto/CryptoUtils.kt | 41 +++++---- .../main/java/com/tangem/data/SettingsMask.kt | 32 ------- .../main/java/com/tangem/tasks/ScanTask.kt | 87 ++++++++----------- .../com/tangem/tasks/SingleCommandTask.kt | 17 ++-- .../src/main/java/com/tangem/tasks/Task.kt | 80 ++++++++++++----- .../main/java/com/tangem/tasks/TaskError.kt | 30 ------- 18 files changed, 188 insertions(+), 252 deletions(-) delete mode 100644 tangem-core/src/main/java/com/tangem/DataStorage.kt delete mode 100644 tangem-core/src/main/java/com/tangem/Response.kt delete mode 100644 tangem-core/src/main/java/com/tangem/common/tlv/TlvValueType.kt delete mode 100644 tangem-core/src/main/java/com/tangem/data/SettingsMask.kt delete mode 100644 tangem-core/src/main/java/com/tangem/tasks/TaskError.kt diff --git a/tangem-core/src/main/java/com/tangem/CardManager.kt b/tangem-core/src/main/java/com/tangem/CardManager.kt index 349289bb83..d0efa5a194 100644 --- a/tangem-core/src/main/java/com/tangem/CardManager.kt +++ b/tangem-core/src/main/java/com/tangem/CardManager.kt @@ -4,7 +4,7 @@ import com.tangem.commands.CommandResponse import com.tangem.commands.CommandSerializer import com.tangem.commands.SignCommand import com.tangem.commands.SignResponse -import com.tangem.crypto.initCrypto +import com.tangem.crypto.CryptoUtils import com.tangem.tasks.* import java.util.concurrent.Executors @@ -17,7 +17,7 @@ class CardManager( private val cardManagerExecutor = Executors.newSingleThreadExecutor() init { - initCrypto() + CryptoUtils.initCrypto() } fun scanCard(callback: (result: TaskEvent) -> Unit) { @@ -56,26 +56,21 @@ class CardManager( task.delegate = cardManagerDelegate cardManagerExecutor.execute { - task.run(environment) { - when (it) { - is TaskEvent.Event -> callback(it) - is TaskEvent.Completion -> { - isBusy = false - callback(it) - } - } + task.run(environment) { taskEvent -> + if (taskEvent is TaskEvent.Completion) isBusy = false + callback(taskEvent) } } } + fun runCommand(command: CommandSerializer, + cardId: String? = null, + callback: (result: TaskEvent) -> Unit) { + val task = SingleCommandTask(command) + runTask(task, cardId, callback) + } + private fun fetchCardEnvironment(cardId: String?): CardEnvironment { return cardEnvironmentRepository[cardId] ?: CardEnvironment() } - - fun runCommand(commandSerializer: CommandSerializer, - cardId: String? = null, - callback: (result: TaskEvent) -> Unit) { - val task = SingleCommandTask(commandSerializer) - runTask(task, cardId, callback) - } } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt b/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt index 82051b143d..94d62f79dc 100644 --- a/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt +++ b/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt @@ -5,10 +5,11 @@ import com.tangem.tasks.TaskError interface CardManagerDelegate { - fun onTaskStarted() - fun showSecurityDelay(ms: Int) - fun onTaskCompleted() - fun onTaskError(error: TaskError? = null) + fun onNfcSessionStarted() + fun onSecurityDelay(ms: Int) + fun hideSecurityDelay() + fun onNfcSessionCompleted() + fun onError(error: TaskError? = null) fun requestPin(callback: (result: CompletionResult) -> Unit) diff --git a/tangem-core/src/main/java/com/tangem/CardReader.kt b/tangem-core/src/main/java/com/tangem/CardReader.kt index 15f9fa9eea..4b4d00769f 100644 --- a/tangem-core/src/main/java/com/tangem/CardReader.kt +++ b/tangem-core/src/main/java/com/tangem/CardReader.kt @@ -7,6 +7,6 @@ import com.tangem.common.apdu.ResponseApdu interface CardReader { var readingActive: Boolean fun transceiveApdu(apdu: CommandApdu, callback: (response: CompletionResult) -> Unit) - fun setStartSession() + fun startNfcSession() fun closeSession() } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/DataStorage.kt b/tangem-core/src/main/java/com/tangem/DataStorage.kt deleted file mode 100644 index b1c531c671..0000000000 --- a/tangem-core/src/main/java/com/tangem/DataStorage.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.tangem - -interface DataStorage { - - fun getTerminalPublicKey(): ByteArray? - fun getTerminalPrivateKey(): ByteArray? - fun getPin1(): String? - fun getPin2(): String? - -} \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/Response.kt b/tangem-core/src/main/java/com/tangem/Response.kt deleted file mode 100644 index 33b18cee40..0000000000 --- a/tangem-core/src/main/java/com/tangem/Response.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.tangem -// -//data class SignResponse( -// val cid: String, -// val signature: ByteArray, -// val remainingSignatures: Int, -// val signedHashes: Int -//) -// -// -//data class CardError( -// val code: Int = 0 -//) -// - - diff --git a/tangem-core/src/main/java/com/tangem/commands/CheckWalletCommand.kt b/tangem-core/src/main/java/com/tangem/commands/CheckWalletCommand.kt index 7a189d8c7a..b581bc36ce 100644 --- a/tangem-core/src/main/java/com/tangem/commands/CheckWalletCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/CheckWalletCommand.kt @@ -19,20 +19,19 @@ class CheckWalletResponse( class CheckWalletCommand( - val pin1: String, val cid: String, - val challenge: ByteArray, val publicKeyChallenge: ByteArray) : CommandSerializer() { - - override val instruction = Instruction.CheckWallet - override val instructionCode = instruction.code + private val pin1: String, + private val cardId: String, + private val challenge: ByteArray +) : CommandSerializer() { override fun serialize(cardEnvironment: CardEnvironment): CommandApdu { val tlvData = listOf( Tlv(TlvTag.Pin, cardEnvironment.pin1.calculateSha256()), - Tlv(TlvTag.CardId, cid.hexToBytes()), + Tlv(TlvTag.CardId, cardId.hexToBytes()), Tlv(TlvTag.Challenge, challenge) ) - return CommandApdu(instructionCode, tlvData) + return CommandApdu(Instruction.CheckWallet, tlvData) } override fun deserialize(cardEnvironment: CardEnvironment, responseApdu: ResponseApdu): CheckWalletResponse? { diff --git a/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt b/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt index 736c68507e..df7a61c2ff 100644 --- a/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt @@ -23,9 +23,6 @@ class SignResponse( class SignCommand(private val hashes: Array, private val cardId: String) : CommandSerializer() { - override val instruction = Instruction.Sign - override val instructionCode = instruction.code - private val hashSizes = if (hashes.isNotEmpty()) hashes.first().size else 0 private val dataToSign = flattenHashes() @@ -36,7 +33,7 @@ class SignCommand(private val hashes: Array, private val cardId: Stri private fun checkForErrors() { if (hashes.isEmpty()) throw TaskError.EmptyHashes() - if (hashes.size > 10) throw TaskError.TooMuchHashes() + if (hashes.size > 10) throw TaskError.TooMuchHashes() if (hashes.any { it.size != hashSizes }) throw TaskError.HashSizeMustBeEqual() } @@ -45,20 +42,20 @@ class SignCommand(private val hashes: Array, private val cardId: Stri Tlv(TlvTag.Pin, cardEnvironment.pin1.calculateSha256()), Tlv(TlvTag.Pin2, cardEnvironment.pin2.calculateSha256()), Tlv(TlvTag.CardId, cardId.hexToBytes()), - Tlv(TlvTag.TransactionOutHashSize,byteArrayOf(hashSizes.toByte())), + Tlv(TlvTag.TransactionOutHashSize, byteArrayOf(hashSizes.toByte())), Tlv(TlvTag.TransactionOutHash, dataToSign) ) addTerminalSignature(cardEnvironment, tlvData) - return CommandApdu(instructionCode, tlvData) + return CommandApdu(Instruction.Sign, tlvData) } private fun addTerminalSignature(cardEnvironment: CardEnvironment, tlvData: MutableList) { - cardEnvironment.terminalKeys?.let { - val signedData = dataToSign.sign(it.privateKey) + cardEnvironment.terminalKeys?.let { terminalKeyPair -> + val signedData = dataToSign.sign(terminalKeyPair.privateKey) tlvData.add(Tlv(TlvTag.TerminalTransactionSignature, signedData)) - tlvData.add(Tlv(TlvTag.TerminalPublicKey, it.publicKey)) + tlvData.add(Tlv(TlvTag.TerminalPublicKey, terminalKeyPair.publicKey)) } } @@ -67,7 +64,7 @@ class SignCommand(private val hashes: Array, private val cardId: Stri val tlvMapper = TlvMapper(tlvData) return SignResponse( - cardId= tlvMapper.map(TlvTag.CardId), + cardId = tlvMapper.map(TlvTag.CardId), signature = tlvMapper.map(TlvTag.Signature), remainingSignatures = tlvMapper.map(TlvTag.RemainingSignatures), signedHashes = tlvMapper.map(TlvTag.SignedHashes) diff --git a/tangem-core/src/main/java/com/tangem/common/apdu/CommandApdu.kt b/tangem-core/src/main/java/com/tangem/common/apdu/CommandApdu.kt index 1fee89160a..86a706bd3e 100644 --- a/tangem-core/src/main/java/com/tangem/common/apdu/CommandApdu.kt +++ b/tangem-core/src/main/java/com/tangem/common/apdu/CommandApdu.kt @@ -7,7 +7,7 @@ import java.io.ByteArrayOutputStream class CommandApdu( - private val instruction: Int, + private val ins: Int, private val tlvList: List, private val cla: Byte = ISO_CLA, @@ -19,6 +19,18 @@ class CommandApdu( private val encryptionMode: EncryptionMode = EncryptionMode.NONE, private val encryptionKey: ByteArray? = null) { + constructor( + instruction: Instruction, + tlvList: List, + encryptionMode: EncryptionMode = EncryptionMode.NONE, + encryptionKey: ByteArray? = null + ) : this( + instruction.code, + tlvList, + encryptionMode = encryptionMode, + encryptionKey = encryptionKey + ) + val apduData: ByteArray init { @@ -39,7 +51,7 @@ class CommandApdu( val byteStream = ByteArrayOutputStream() byteStream.write(cla.toInt()) - byteStream.write(instruction) + byteStream.write(ins) byteStream.write(p1.toInt()) byteStream.write(p2.toInt()) if (lc != 0) { @@ -58,7 +70,7 @@ class CommandApdu( private fun encrypt() { - + TODO("not implemented") } companion object { diff --git a/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt b/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt index 4cbc0d2a81..c346fe1e71 100644 --- a/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt +++ b/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt @@ -6,13 +6,13 @@ enum class StatusWord (val code: Int, val description: String){ InvalidParams(0x6A86, "SW_INVALID_PARAMS"), ErrorProcessingCommand(0x6286, "SW_ERROR_PROCESSING_COMMAND"), InvalidState(0x6985, "SW_INVALID_STATE"), - // PinsNotChanged(ProcessCompleted.code, ProcessCompleted.description), Pin1Changed(ProcessCompleted.code + 0x0001, "SW_PIN1_CHANGED"), Pin2Changed(ProcessCompleted.code + 0x0002, "SW_PIN2_CHANGED"), PinsChanged(ProcessCompleted.code + 0x0003, "SW_PINS_CHANGED"), InsNotSupported(0x6D00, "SW_INS_NOT_SUPPORTED"), NeedEncryption(0x6982, "SW_NEED_ENCRYPTION"), - NeedPause(0x9789, "SW_NEED_PAUSE"); + NeedPause(0x9789, "SW_NEED_PAUSE"), + Unknown(0x0000, "SW_UNKNOWN"); companion object { private val values = values() diff --git a/tangem-core/src/main/java/com/tangem/common/tlv/Tlv.kt b/tangem-core/src/main/java/com/tangem/common/tlv/Tlv.kt index a22dad60c1..b1b2c3b5fa 100644 --- a/tangem-core/src/main/java/com/tangem/common/tlv/Tlv.kt +++ b/tangem-core/src/main/java/com/tangem/common/tlv/Tlv.kt @@ -7,17 +7,17 @@ class Tlv { val tag: TlvTag val value: ByteArray - val tagCode: Int + val tagRaw: Int constructor(tagCode: Int, value: ByteArray = byteArrayOf()) { this.tag = TlvTag.byCode(tagCode) - this.tagCode = tagCode + this.tagRaw = tagCode this.value = value } constructor(tag: TlvTag, value: ByteArray = byteArrayOf()) { this.tag = tag - this.tagCode = tag.code + this.tagRaw = tag.code this.value = value } diff --git a/tangem-core/src/main/java/com/tangem/common/tlv/TlvTag.kt b/tangem-core/src/main/java/com/tangem/common/tlv/TlvTag.kt index 71eb6d009f..aa0e0036f8 100644 --- a/tangem-core/src/main/java/com/tangem/common/tlv/TlvTag.kt +++ b/tangem-core/src/main/java/com/tangem/common/tlv/TlvTag.kt @@ -1,5 +1,19 @@ package com.tangem.common.tlv +enum class TlvValueType { + HexString, + Utf8String, + IntValue, + BoolValue, + ByteArray, + EllipticCurve, + DateTime, + ProductMask, + SettingsMask, + CardStatus, + SigningMethod +} + enum class TlvTag(val code: Int) { Unknown(0x00), CardId(0x01), diff --git a/tangem-core/src/main/java/com/tangem/common/tlv/TlvValueType.kt b/tangem-core/src/main/java/com/tangem/common/tlv/TlvValueType.kt deleted file mode 100644 index c71a19fa4a..0000000000 --- a/tangem-core/src/main/java/com/tangem/common/tlv/TlvValueType.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.tangem.common.tlv - -enum class TlvValueType { - HexString, - Utf8String, - IntValue, - BoolValue, - ByteArray, - EllipticCurve, - DateTime, - ProductMask, - SettingsMask, - CardStatus, - SigningMethod -} \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/crypto/CryptoUtils.kt b/tangem-core/src/main/java/com/tangem/crypto/CryptoUtils.kt index 14ca802dc2..1dc0d2bc82 100644 --- a/tangem-core/src/main/java/com/tangem/crypto/CryptoUtils.kt +++ b/tangem-core/src/main/java/com/tangem/crypto/CryptoUtils.kt @@ -5,35 +5,34 @@ import net.i2p.crypto.eddsa.EdDSASecurityProvider import java.security.SecureRandom import java.security.Security -fun generateRandomBytes(length: Int): ByteArray { - val bytes = ByteArray(length) - SecureRandom().nextBytes(bytes) - return bytes -} -fun verify(publicKey: ByteArray, message: ByteArray, signature: ByteArray, - curve: EllipticCurve = EllipticCurve.Secp256k1): Boolean { - return when (curve) { - EllipticCurve.Secp256k1 -> verifySecp256k1(publicKey, message, signature) - EllipticCurve.Ed25519 -> verifyEd25519(publicKey, message, signature) +object CryptoUtils { + + fun initCrypto() { + Security.insertProviderAt(org.spongycastle.jce.provider.BouncyCastleProvider(), 1) + Security.addProvider(EdDSASecurityProvider()) + } + + fun generateRandomBytes(length: Int): ByteArray { + val bytes = ByteArray(length) + SecureRandom().nextBytes(bytes) + return bytes + } + + fun verify(publicKey: ByteArray, message: ByteArray, signature: ByteArray, + curve: EllipticCurve = EllipticCurve.Secp256k1): Boolean { + return when (curve) { + EllipticCurve.Secp256k1 -> verifySecp256k1(publicKey, message, signature) + EllipticCurve.Ed25519 -> verifyEd25519(publicKey, message, signature) + } } } - -fun initCrypto() { - Security.insertProviderAt(org.spongycastle.jce.provider.BouncyCastleProvider(), 1) - Security.addProvider(EdDSASecurityProvider()) -} - - fun ByteArray.sign(privateKeyArray: ByteArray, curve: EllipticCurve = EllipticCurve.Secp256k1): ByteArray { - return when (curve) { - EllipticCurve.Secp256k1 -> signSecp256k1(this,privateKeyArray) + EllipticCurve.Secp256k1 -> signSecp256k1(this, privateKeyArray) EllipticCurve.Ed25519 -> signEd25519(this, privateKeyArray) } - - } diff --git a/tangem-core/src/main/java/com/tangem/data/SettingsMask.kt b/tangem-core/src/main/java/com/tangem/data/SettingsMask.kt deleted file mode 100644 index 696b947202..0000000000 --- a/tangem-core/src/main/java/com/tangem/data/SettingsMask.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.tangem.data - -data class SettingsMask(val rawValue: Int) { - - companion object{ - const val IsReusable = 0x0001 - const val UseActivation = 0x0002 - const val ForbidPurgeWallet = 0x0004 - const val UseBlock = 0x0008 - - const val AllowSwapPIN = 0x0010 - const val AllowSwapPIN2 = 0x0020 - const val UseCVC = 0x0040 - const val ForbidDefaultPIN = 0x0080 - - const val UseOneCommandAtTime = 0x0100 - const val UseNDEF = 0x0200 - const val UseDynamicNDEF = 0x0400 - const val SmartSecurityDelay = 0x0800 - - const val Protocol_AllowUnencrypted = 0x1000 - const val Protocol_AllowStaticEncryption = 0x2000 - - const val ProtectIssuerDataAgainstReplay = 0x4000 - - const val AllowSelectBlockchain = 0x8000 - - const val DisablePrecomputedNDEF = 0x00010000 - - const val SkipSecurityDelayIfValidatedByLinkedTerminal = 0x00080000 - } -} \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt b/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt index 371e5686e7..4bd9194dc9 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt @@ -3,11 +3,9 @@ package com.tangem.tasks import com.tangem.CardEnvironment import com.tangem.commands.Card import com.tangem.commands.CheckWalletCommand -import com.tangem.commands.EllipticCurve -import com.tangem.commands.ReadCardCommand +import com.tangem.commands.ReadCommand import com.tangem.common.CompletionResult -import com.tangem.crypto.generateRandomBytes -import com.tangem.crypto.verify +import com.tangem.crypto.CryptoUtils sealed class ScanEvent { data class OnReadEvent(val card: Card) : ScanEvent() @@ -17,76 +15,67 @@ sealed class ScanEvent { internal class ScanTask : Task() { - private lateinit var cardData: Card - private lateinit var challenge: ByteArray - private lateinit var curve: EllipticCurve - private lateinit var walletPublickKey: ByteArray - override fun onRun(cardEnvironment: CardEnvironment, callback: (result: TaskEvent) -> Unit) { - val readCommand = ReadCardCommand() - sendCommand(readCommand, cardEnvironment) { readEvent -> + val readCommand = ReadCommand() + sendCommand(readCommand, cardEnvironment) { readResult -> + + when (readResult) { + + is CompletionResult.Failure -> { + if (readResult.error !is TaskError.UserCancelledError) { + completeNfcSession(true, readResult.error) + } + callback(TaskEvent.Completion(readResult.error)) + } - when (readEvent) { is CompletionResult.Success -> { - cardData = readEvent.data + val card = readResult.data - callback(TaskEvent.Event(ScanEvent.OnReadEvent(cardData))) + callback(TaskEvent.Event(ScanEvent.OnReadEvent(card))) - if (cardData.curve != null && cardData.walletPublicKey != null) { - curve = cardData.curve!! - walletPublickKey = cardData.walletPublicKey!! - } else { - onTaskCompleted(true) + if (card.curve == null || card.walletPublicKey == null) { + completeNfcSession(true) callback(TaskEvent.Completion(TaskError.CardError())) + return@sendCommand } - val checkWalletCommand = prepareCheckWalletCommand(cardEnvironment) + val challenge = CryptoUtils.generateRandomBytes(16) + val checkWalletCommand = CheckWalletCommand( + cardEnvironment.pin1, + card.cardId, + challenge) + + sendCommand(checkWalletCommand, cardEnvironment) { result -> + when (result) { + is CompletionResult.Failure -> { + if (result.error !is TaskError.UserCancelledError) { + completeNfcSession(true, result.error) + } + callback(TaskEvent.Completion(result.error)) + } - sendCommand(checkWalletCommand, cardEnvironment) { checkWalletEvent -> - when (checkWalletEvent) { is CompletionResult.Success -> { - val checkWalletResponse = checkWalletEvent.data - val verified = verify(walletPublickKey, + completeNfcSession() + val checkWalletResponse = result.data + val verified = CryptoUtils.verify( + card.walletPublicKey, challenge + checkWalletResponse.salt, checkWalletResponse.walletSignature, - curve) + card.curve) if (verified) { - onTaskCompleted() - callback(TaskEvent.Completion()) callback(TaskEvent.Event(ScanEvent.OnVerifyEvent(true))) + callback(TaskEvent.Completion()) } else { - onTaskCompleted(true) callback(TaskEvent.Completion(TaskError.VefificationFailed())) } } - is CompletionResult.Failure -> { - if (checkWalletEvent.error !is TaskError.UserCancelledError) { - onTaskCompleted(true, checkWalletEvent.error) - } - callback(TaskEvent.Completion(checkWalletEvent.error)) - } } } } - is CompletionResult.Failure -> { - if (readEvent.error !is TaskError.UserCancelledError) { - onTaskCompleted(true, readEvent.error) - } - callback(TaskEvent.Completion(readEvent.error)) - } } } } - - private fun prepareCheckWalletCommand(cardEnvironment: CardEnvironment): CheckWalletCommand { - challenge = generateRandomBytes(16) - return CheckWalletCommand( - cardEnvironment.pin1, - cardData.cardId, - challenge, - byteArrayOf()) - } } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/tasks/SingleCommandTask.kt b/tangem-core/src/main/java/com/tangem/tasks/SingleCommandTask.kt index 5728ed9305..96176afdc6 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/SingleCommandTask.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/SingleCommandTask.kt @@ -6,22 +6,23 @@ import com.tangem.commands.CommandSerializer import com.tangem.common.CompletionResult class SingleCommandTask( - private val commandSerializer: CommandSerializer) : Task() { + private val command: CommandSerializer +) : Task() { override fun onRun(cardEnvironment: CardEnvironment, callback: (result: TaskEvent) -> Unit) { - sendCommand(commandSerializer, cardEnvironment) { completionResult -> - when (completionResult) { + sendCommand(command, cardEnvironment) { result -> + when (result) { is CompletionResult.Success -> { - onTaskCompleted() - callback(TaskEvent.Event(completionResult.data)) + completeNfcSession() + callback(TaskEvent.Event(result.data)) callback(TaskEvent.Completion()) } is CompletionResult.Failure -> { - if (completionResult.error !is TaskError.UserCancelledError) { - onTaskCompleted(true, completionResult.error) + if (result.error !is TaskError.UserCancelledError) { + completeNfcSession(true, result.error) } - callback(TaskEvent.Completion(completionResult.error)) + callback(TaskEvent.Completion(result.error)) } } } 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 cfcfddc25e..b866f6ad47 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/Task.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/Task.kt @@ -7,8 +7,40 @@ import com.tangem.Log import com.tangem.commands.CommandResponse import com.tangem.commands.CommandSerializer import com.tangem.common.CompletionResult +import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.StatusWord +sealed class TaskError(description: String? = null) : Exception(description) { + class UnknownStatus(sw: Int) : TaskError("Unknown StatusWord: $sw") + class MappingError : TaskError() + class GenericError(description: String? = null) : TaskError(description) + class UserCancelledError() : TaskError() + class Busy() : TaskError() + class TagLost() : TaskError() + + class ErrorProcessingCommand : TaskError() + class InvalidState : TaskError() + class InsNotSupported : TaskError() + class InvalidParams : TaskError() + class NeedEncryption : TaskError() + class NeedPause : TaskError() + + class VefificationFailed : TaskError() + class CardError : TaskError() + class ReaderError() : TaskError() + class SerializeCommandError() : TaskError() + + class CardIsMissing() : TaskError() + class EmptyHashes() : TaskError() + class TooMuchHashes() : TaskError() + class HashSizeMustBeEqual() : TaskError() +} + +sealed class TaskEvent { + class Event(val data: T) : TaskEvent() + class Completion(val error: TaskError? = null) : TaskEvent() +} + abstract class Task { var delegate: CardManagerDelegate? = null @@ -16,18 +48,18 @@ abstract class Task { fun run(cardEnvironment: CardEnvironment, callback: (result: TaskEvent) -> Unit) { - delegate?.onTaskStarted() - reader?.setStartSession() + delegate?.onNfcSessionStarted() + reader?.startNfcSession() Log.i(this::class.simpleName!!, "Nfc task is started") onRun(cardEnvironment, callback) } - protected fun onTaskCompleted(withError: Boolean = false, taskError: TaskError? = null) { + protected fun completeNfcSession(withError: Boolean = false, taskError: TaskError? = null) { reader?.closeSession() if (withError) { - delegate?.onTaskError(taskError) + delegate?.onError(taskError) } else { - delegate?.onTaskCompleted() + delegate?.onNfcSessionCompleted() } } @@ -35,15 +67,22 @@ abstract class Task { callback: (result: TaskEvent) -> Unit) protected fun sendCommand( - commandSerializer: CommandSerializer, + command: CommandSerializer, cardEnvironment: CardEnvironment, callback: (result: CompletionResult) -> Unit) { - Log.i(this::class.simpleName!!, "Nfc command ${commandSerializer::class.simpleName!!} is initiated") + Log.i(this::class.simpleName!!, "Nfc command ${command::class.simpleName!!} is initiated") + val commandApdu = command.serialize(cardEnvironment) + sendRequest(command, commandApdu, cardEnvironment, callback) + } - reader?.transceiveApdu( - commandSerializer.serialize(cardEnvironment)) { result -> + private fun sendRequest(command: CommandSerializer, + commandApdu: CommandApdu, + cardEnvironment: CardEnvironment, + callback: (result: CompletionResult) -> Unit) { + + reader?.transceiveApdu(commandApdu) { result -> when (result) { is CompletionResult.Success -> { @@ -52,24 +91,26 @@ abstract class Task { StatusWord.ProcessCompleted, StatusWord.Pin1Changed, StatusWord.Pin2Changed, StatusWord.PinsChanged -> { try { - val responseData = commandSerializer.deserialize(cardEnvironment, responseApdu) - Log.i(this::class.simpleName!!, "Nfc command ${commandSerializer::class.simpleName!!} is completed") + val responseData = command.deserialize(cardEnvironment, responseApdu) + Log.i(this::class.simpleName!!, "Nfc command ${command::class.simpleName!!} is completed") callback(CompletionResult.Success(responseData as T)) } catch (error: TaskError) { callback(CompletionResult.Failure(error)) } } StatusWord.InvalidParams -> callback(CompletionResult.Failure(TaskError.InvalidParams())) + StatusWord.Unknown -> callback(CompletionResult.Failure(TaskError.UnknownStatus(result.data.sw))) StatusWord.ErrorProcessingCommand -> callback(CompletionResult.Failure(TaskError.ErrorProcessingCommand())) StatusWord.InvalidState -> callback(CompletionResult.Failure(TaskError.InvalidState())) StatusWord.InsNotSupported -> callback(CompletionResult.Failure(TaskError.InsNotSupported())) StatusWord.NeedEncryption -> callback(CompletionResult.Failure(TaskError.NeedEncryption())) StatusWord.NeedPause -> { - val remainingTime = commandSerializer.deserializeSecurityDelay(responseApdu, cardEnvironment) - if (remainingTime != null) delegate?.showSecurityDelay(remainingTime) - Log.i(this::class.simpleName!!, "Nfc command ${commandSerializer::class.simpleName!!} triggered security delay of $remainingTime milliseconds") - sendCommand(commandSerializer, cardEnvironment, callback) + // When NeedPause is returned from the card whenever security delay is triggered. + val remainingTime = command.deserializeSecurityDelay(responseApdu, cardEnvironment) + if (remainingTime != null) delegate?.onSecurityDelay(remainingTime) + Log.i(this::class.simpleName!!, "Nfc command ${command::class.simpleName!!} triggered security delay of $remainingTime milliseconds") + sendRequest(command, commandApdu, cardEnvironment, callback) } } } @@ -80,18 +121,9 @@ abstract class Task { callback(CompletionResult.Failure(TaskError.UserCancelledError())) reader?.readingActive = false } - } } } } -/** - * Returns in callback from tasks - */ -sealed class TaskEvent { - class Event(val data: T) : TaskEvent() - class Completion(val error: TaskError? = null) : TaskEvent() -} - diff --git a/tangem-core/src/main/java/com/tangem/tasks/TaskError.kt b/tangem-core/src/main/java/com/tangem/tasks/TaskError.kt deleted file mode 100644 index 7287c281cb..0000000000 --- a/tangem-core/src/main/java/com/tangem/tasks/TaskError.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.tangem.tasks - -/** - * An error class that covers typical errors that may occur when performing Tangem SDK tasks. - * Errors are got propagated back within callbacks. - */ -sealed class TaskError(description: String? = null) : Exception(description) { - class UnknownStatus(sw: Int) : TaskError() - class MappingError : TaskError() - class GenericError(description: String? = null) : TaskError(description) - class UserCancelledError() : TaskError() - class Busy() : TaskError() - - class ErrorProcessingCommand : TaskError() - class InvalidState : TaskError() - class InsNotSupported : TaskError() - class InvalidParams : TaskError() - class NeedEncryption : TaskError() - class NeedPause : TaskError() - - class VefificationFailed : TaskError() - class CardError : TaskError() - class ReaderError() : TaskError() - class SerializeCommandError() : TaskError() - - class CardIsMissing() : TaskError() - class EmptyHashes() : TaskError() - class TooMuchHashes() : TaskError() - class HashSizeMustBeEqual() : TaskError() -} \ No newline at end of file From d48abc8579759c24b8a43822fcb6652b40b0ae89 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 13 Nov 2019 14:33:07 +0300 Subject: [PATCH 4/5] Updated on 2026-08-14 --- .../tangem_sdk_new/DefaultCardManagerDelegate.kt | 9 ++++----- .../main/java/com/tangem/tangem_sdk_new/Utils.kt | 2 +- .../com/tangem/tangem_sdk_new/nfc/NfcManager.kt | 15 ++++++++------- .../com/tangem/tangem_sdk_new/nfc/NfcReader.kt | 13 ++++++++----- .../tangem/tangem_sdk_new/ui/NfcEnableDialog.kt | 2 +- .../tangem_sdk_new/ui/TouchCardAnimation.kt | 8 ++++---- 6 files changed, 26 insertions(+), 23 deletions(-) diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt index 1616c3d6f7..622f985eb1 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt @@ -25,8 +25,7 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel setLogger() } - override fun onTaskStarted() { -// reader.isoDep = null + override fun onNfcSessionStarted() { reader.readingCancelled = false postUI { showReadingDialog(activity) } if (!reader.nfcEnabled) showNFCEnableDialog() @@ -58,7 +57,7 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel activity.supportFragmentManager.let { nfcEnableDialog?.show(it, NfcEnableDialog.TAG) } } - override fun showSecurityDelay(ms: Int) { + override fun onSecurityDelay(ms: Int) { postUI { readingDialog?.lTouchCard?.visibility = View.GONE readingDialog?.tvRemainingTime?.text = ms.div(100).toString() @@ -78,7 +77,7 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel } } - override fun onTaskCompleted() { + override fun onNfcSessionCompleted() { postUI { readingDialog?.lTouchCard?.visibility = View.GONE readingDialog?.flSecurityDelay?.visibility = View.GONE @@ -88,7 +87,7 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel postUI(300) { readingDialog?.dismiss() } } - override fun onTaskError(error: TaskError?) { + override fun onError(error: TaskError?) { postUI { readingDialog?.lTouchCard?.visibility = View.GONE readingDialog?.flSecurityDelay?.visibility = View.GONE diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/Utils.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/Utils.kt index 491f7a1a52..5cf40bef81 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/Utils.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/Utils.kt @@ -5,6 +5,6 @@ import android.os.Looper val uiHandler = Handler(Looper.getMainLooper()) - internal fun postUI(msTime: Long = 0, func: () -> Unit) { +internal fun postUI(msTime: Long = 0, func: () -> Unit) { if (msTime > 0) uiHandler.postDelayed({ func() }, msTime) else uiHandler.post(func) } \ No newline at end of file diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcManager.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcManager.kt index d827dcd584..b6e29e445a 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcManager.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcManager.kt @@ -1,5 +1,6 @@ package com.tangem.tangem_sdk_new.nfc +import android.app.Activity import android.content.BroadcastReceiver import android.content.Context import android.content.Intent @@ -9,16 +10,15 @@ import android.nfc.Tag import android.nfc.tech.IsoDep import android.os.Build import android.os.Bundle -import androidx.fragment.app.FragmentActivity import com.tangem.Log class NfcManager : NfcAdapter.ReaderCallback { val reader = NfcReader() - private var activity: FragmentActivity? = null + private var activity: Activity? = null private var nfcAdapter: NfcAdapter? = null - fun setCurrentActivity(activity: FragmentActivity) { + fun setCurrentActivity(activity: Activity) { this.activity = activity nfcAdapter = NfcAdapter.getDefaultAdapter(activity) } @@ -49,11 +49,13 @@ class NfcManager : NfcAdapter.ReaderCallback { reader.nfcEnabled = true enableReaderMode() } + reader.manager = this } fun onPause() { activity?.unregisterReceiver(mBroadcastReceiver) disableReaderMode() + reader.manager = null } fun onDestroy() { @@ -61,12 +63,11 @@ class NfcManager : NfcAdapter.ReaderCallback { nfcAdapter = null } - private fun enableReaderMode() { - val options = Bundle() - nfcAdapter?.enableReaderMode(activity, this, READER_FLAGS, options) + fun enableReaderMode() { + nfcAdapter?.enableReaderMode(activity, this, READER_FLAGS, Bundle()) } - private fun disableReaderMode() { + fun disableReaderMode() { nfcAdapter?.disableReaderMode(activity) } diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcReader.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcReader.kt index 9addd2f9bd..713e232cdf 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcReader.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcReader.kt @@ -1,6 +1,7 @@ package com.tangem.tangem_sdk_new.nfc import android.nfc.Tag +import android.nfc.TagLostException import android.nfc.tech.IsoDep import com.tangem.CardReader import com.tangem.Log @@ -13,14 +14,15 @@ class NfcReader : CardReader { override var readingActive = false var nfcEnabled = false - var isoDep: IsoDep? = null + var manager: NfcManager? = null + private var isoDep: IsoDep? = null set(value) { - // if tag is received, call connect first before transceiving data + // don't reassign when there's an active tag already if (field == null) { field = value + // if tag is received, call connect first before transceiving data connect() } - // don't reassign when there's an active tag already if (value == null) field = value } @@ -38,9 +40,11 @@ class NfcReader : CardReader { var data: ByteArray? = null var callback: ((response: CompletionResult) -> Unit)? = null - override fun setStartSession() { + override fun startNfcSession() { readingActive = true readingCancelled = false + manager?.disableReaderMode() + manager?.enableReaderMode() } override fun closeSession() { @@ -93,7 +97,6 @@ class NfcReader : CardReader { isoDep?.connect() isoDep?.timeout = 240000 Log.i(this::class.simpleName!!, "Nfc session is started") - } } \ No newline at end of file diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/ui/NfcEnableDialog.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/ui/NfcEnableDialog.kt index bbdf00079d..a7d6c2689c 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/ui/NfcEnableDialog.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/ui/NfcEnableDialog.kt @@ -15,7 +15,7 @@ class NfcEnableDialog : DialogFragment() { } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val builder = AlertDialog.Builder(requireContext()) + val builder = AlertDialog.Builder(requireContext()) builder.setCancelable(false) .setIcon(R.drawable.ic_action_nfc_gray) .setTitle(R.string.dialog_nfc_enable_title) diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/ui/TouchCardAnimation.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/ui/TouchCardAnimation.kt index 717c0cf827..10546e2aeb 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/ui/TouchCardAnimation.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/ui/TouchCardAnimation.kt @@ -11,10 +11,10 @@ import android.widget.RelativeLayout import androidx.appcompat.widget.LinearLayoutCompat class TouchCardAnimation(private var context: Context, - private var ivHandCardHorizontal: ImageView, - private var ivHandCardVertical: ImageView, - private var llHand: LinearLayoutCompat, - private var llNfc: LinearLayoutCompat) { + private var ivHandCardHorizontal: ImageView, + private var ivHandCardVertical: ImageView, + private var llHand: LinearLayoutCompat, + private var llNfc: LinearLayoutCompat) { companion object { const val CARD_ON_BACK = 0 From 1d4d03de63baae9bd6689e5c7174eb7eb2fb5e14 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 14 Nov 2019 10:15:59 +0300 Subject: [PATCH 5/5] Updated on 2026-08-14 --- tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt | 2 +- .../com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt b/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt index 94d62f79dc..124d8e9d01 100644 --- a/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt +++ b/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt @@ -7,7 +7,7 @@ interface CardManagerDelegate { fun onNfcSessionStarted() fun onSecurityDelay(ms: Int) - fun hideSecurityDelay() + fun onTagLost() fun onNfcSessionCompleted() fun onError(error: TaskError? = null) diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt index 622f985eb1..e2a6e984f6 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt @@ -68,7 +68,7 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel } } - override fun hideSecurityDelay() { + override fun onTagLost() { postUI { readingDialog?.lTouchCard?.visibility = View.VISIBLE readingDialog?.flSecurityDelay?.visibility = View.GONE