Updated on 2026-08-14

This commit is contained in:
Tangem 2020-04-29 10:20:17 +03:00
parent 316b2551a5
commit 8bef686eeb
34 changed files with 661 additions and 69 deletions

View file

@ -44,7 +44,7 @@ class ReadIssuerExtraDataResponse(
val issuerDataSignature: ByteArray?,
/**
* An optional counter that protect issuer data against replay attack.
* An optional counter that protects issuer data against replay attack.
* When flag [Settings.ProtectIssuerDataAgainstReplay] set in [SettingsMask]
* then this value is mandatory and must increase on each execution of [WriteIssuerDataCommand].
*/

View file

@ -17,7 +17,7 @@ class WriteUserDataResponse(
) : CommandResponse
/**
* This command write some of User_Data, User_ProtectedData, User_Counter and User_ProtectedCounter fields.
* This command writes to the card any of User_Data, User_ProtectedData, User_Counter and User_ProtectedCounter fields.
* User_Data and User_ProtectedData are never changed or parsed by the executable code the Tangem COS.
* The App defines purpose of use, format and it's payload. For example, this field may contain cashed information
* from blockchain to accelerate preparing new transaction.

View file

@ -63,15 +63,15 @@ class ActionListFragment : BaseFragment() {
ActionType.Scan,
ActionType.Sign,
ActionType.Personalize,
ActionType.Depersonalize
// ActionType.CreateWallet,
// ActionType.PurgeWallet,
// ActionType.ReadIssuerData,
// ActionType.WriteIssuerData,
// ActionType.ReadIssuerExData,
// ActionType.WriteIssuerExData,
// ActionType.ReadUserData,
// ActionType.WriteUserData
ActionType.Depersonalize,
ActionType.CreateWallet,
ActionType.PurgeWallet,
ActionType.ReadIssuerData,
ActionType.WriteIssuerData,
ActionType.ReadIssuerExData,
ActionType.WriteIssuerExData,
ActionType.ReadUserData,
ActionType.WriteUserData
)
}
}

View file

@ -0,0 +1,23 @@
package com.tangem.devkit.ucase.domain.actions
import com.tangem.devkit._arch.structure.Id
import com.tangem.devkit._arch.structure.PayloadHolder
import com.tangem.devkit._arch.structure.abstraction.findItem
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
import com.tangem.devkit.ucase.variants.TlvId
class CreateWalletAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val item = attrs.itemList.findItem(TlvId.CardId) ?: return
val cardId = item.viewModel.data as? String ?: return
attrs.tangemSdk.createWallet(cardId) { handleResult(payload, it, null, attrs, callback) }
}
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}
}

View file

@ -0,0 +1,23 @@
package com.tangem.devkit.ucase.domain.actions
import com.tangem.devkit._arch.structure.Id
import com.tangem.devkit._arch.structure.PayloadHolder
import com.tangem.devkit._arch.structure.abstraction.findItem
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
import com.tangem.devkit.ucase.variants.TlvId
class PurgeWalletAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val item = attrs.itemList.findItem(TlvId.CardId) ?: return
val cardId = item.viewModel.data as? String ?: return
attrs.tangemSdk.purgeWallet(cardId) { handleResult(payload, it, null, attrs, callback) }
}
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}
}

View file

@ -0,0 +1,23 @@
package com.tangem.devkit.ucase.domain.actions
import com.tangem.devkit._arch.structure.Id
import com.tangem.devkit._arch.structure.PayloadHolder
import com.tangem.devkit._arch.structure.abstraction.findItem
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
import com.tangem.devkit.ucase.variants.TlvId
class ReadIssuerDataAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val item = attrs.itemList.findItem(TlvId.CardId) ?: return
val cardId = item.viewModel.data as? String ?: return
attrs.tangemSdk.readIssuerData(cardId) { handleResult(payload, it, null, attrs, callback) }
}
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}
}

View file

@ -0,0 +1,23 @@
package com.tangem.devkit.ucase.domain.actions
import com.tangem.devkit._arch.structure.Id
import com.tangem.devkit._arch.structure.PayloadHolder
import com.tangem.devkit._arch.structure.abstraction.findItem
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
import com.tangem.devkit.ucase.variants.TlvId
class ReadIssuerExtraDataAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val item = attrs.itemList.findItem(TlvId.CardId) ?: return
val cardId = item.viewModel.data as? String ?: return
attrs.tangemSdk.readIssuerExtraData(cardId) { handleResult(payload, it, null, attrs, callback) }
}
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}
}

View file

@ -0,0 +1,23 @@
package com.tangem.devkit.ucase.domain.actions
import com.tangem.devkit._arch.structure.Id
import com.tangem.devkit._arch.structure.PayloadHolder
import com.tangem.devkit._arch.structure.abstraction.findItem
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
import com.tangem.devkit.ucase.variants.TlvId
class ReadUserDataAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val item = attrs.itemList.findItem(TlvId.CardId) ?: return
val cardId = item.viewModel.data as? String ?: return
attrs.tangemSdk.readUserData(cardId) { handleResult(payload, it, null, attrs, callback) }
}
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}
}

View file

@ -0,0 +1,37 @@
package com.tangem.devkit.ucase.domain.actions
import com.tangem.common.extensions.hexToBytes
import com.tangem.common.extensions.toByteArray
import com.tangem.crypto.sign
import com.tangem.devkit._arch.structure.Id
import com.tangem.devkit._arch.structure.PayloadHolder
import com.tangem.devkit._arch.structure.abstraction.findItem
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
import com.tangem.devkit.ucase.variants.TlvId
import com.tangem.devkit.ucase.variants.personalize.dto.DefaultPersonalizationParams
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
class WriteIssuerDataAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val cardId = attrs.itemList.findItem(TlvId.CardId)?.viewModel?.data ?: return
val counter = (attrs.itemList.findItem(TlvId.Counter)?.viewModel?.data as? Int) ?: 1
val issuerDataItem = attrs.itemList.findItem(TlvId.IssuerData) ?: return
val issuerData = (issuerDataItem.getData() as? String)?.toByteArray() ?: return
val signedIssuerData = (
stringOf(cardId).hexToBytes() + issuerData + counter.toByteArray(4))
.sign(DefaultPersonalizationParams.issuer().dataKeyPair.privateKey)
attrs.tangemSdk.writeIssuerData(stringOf(cardId), issuerData, signedIssuerData, counter) {
handleResult(payload, it, null, attrs, callback)
}
}
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}
}

View file

@ -0,0 +1,45 @@
package com.tangem.devkit.ucase.domain.actions
import com.tangem.commands.WriteIssuerExtraDataCommand
import com.tangem.common.extensions.hexToBytes
import com.tangem.common.extensions.toByteArray
import com.tangem.crypto.CryptoUtils
import com.tangem.crypto.sign
import com.tangem.devkit._arch.structure.Id
import com.tangem.devkit._arch.structure.PayloadHolder
import com.tangem.devkit._arch.structure.abstraction.findItem
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
import com.tangem.devkit.ucase.variants.TlvId
import com.tangem.devkit.ucase.variants.personalize.dto.DefaultPersonalizationParams
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
class WriteIssuerExtraDataAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val cardId = attrs.itemList.findItem(TlvId.CardId)?.viewModel?.data ?: return
val counter = (attrs.itemList.findItem(TlvId.Counter)?.viewModel?.data as? String)?.toInt() ?: 1
val issuerData = CryptoUtils.generateRandomBytes(WriteIssuerExtraDataCommand.SINGLE_WRITE_SIZE * 5)
val startingSignature = (
stringOf(cardId).hexToBytes() + counter.toByteArray(4) + issuerData.size.toByteArray(2))
.sign(DefaultPersonalizationParams.issuer().dataKeyPair.privateKey)
val finalizingSignature = (
stringOf(cardId).hexToBytes() + issuerData + counter.toByteArray(4))
.sign(DefaultPersonalizationParams.issuer().dataKeyPair.privateKey)
attrs.tangemSdk.writeIssuerExtraData(
stringOf(cardId), issuerData, startingSignature, finalizingSignature, counter
) {
handleResult(payload, it, null, attrs, callback)
}
}
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}
}

View file

@ -0,0 +1,31 @@
package com.tangem.devkit.ucase.domain.actions
import com.tangem.devkit._arch.structure.Id
import com.tangem.devkit._arch.structure.PayloadHolder
import com.tangem.devkit._arch.structure.abstraction.findItem
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
import com.tangem.devkit.ucase.variants.TlvId
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
class WriteUserDataAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val userData = (attrs.itemList.findItem(TlvId.UserData)?.getData() as? String)?.toByteArray()
?: return
val protectedUserData = (attrs.itemList.findItem(TlvId.ProtectedUserData)?.getData() as? String)?.toByteArray()
?: return
val cardId = attrs.itemList.findItem(TlvId.CardId)?.viewModel?.data ?: return
val counter = (attrs.itemList.findItem(TlvId.Counter)?.viewModel?.data as? Int) ?: 1
attrs.tangemSdk.writeUserData(stringOf(cardId), userData, protectedUserData, counter, counter) {
handleResult(payload, it, null, attrs, callback)
}
}
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
TlvId.Counter -> { callback -> ReadUserDataAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}
}

View file

@ -1,9 +1,7 @@
package com.tangem.devkit.ucase.domain.paramsManager.managers
import com.tangem.devkit._arch.structure.impl.EditTextItem
import com.tangem.devkit.ucase.domain.actions.DepersonalizeAction
import com.tangem.devkit.ucase.domain.actions.ScanAction
import com.tangem.devkit.ucase.domain.actions.SignAction
import com.tangem.devkit.ucase.domain.actions.*
import com.tangem.devkit.ucase.domain.paramsManager.triggers.changeConsequence.CardIdConsequence
import com.tangem.devkit.ucase.variants.TlvId
@ -29,4 +27,78 @@ class SignItemsManager : BaseItemsManager(SignAction()) {
EditTextItem(TlvId.TransactionOutHash, "Data used for hashing")
))
}
}
class CreateWalletItemsManager : BaseItemsManager(CreateWalletAction()) {
init {
setItemChangeConsequences(CardIdConsequence())
setItems(listOf(EditTextItem(TlvId.CardId, null)))
}
}
class PurgeWalletItemsManager : BaseItemsManager(PurgeWalletAction()) {
init {
setItemChangeConsequences(CardIdConsequence())
setItems(listOf(EditTextItem(TlvId.CardId, null)))
}
}
class ReadIssuerDataItemsManager : BaseItemsManager(ReadIssuerDataAction()) {
init {
setItemChangeConsequences(CardIdConsequence())
setItems(listOf(EditTextItem(TlvId.CardId, null)))
}
}
class WriteIssuerDataItemsManager : BaseItemsManager(WriteIssuerDataAction()) {
init {
setItemChangeConsequences(CardIdConsequence())
setItems(listOf(
EditTextItem(TlvId.CardId, null),
EditTextItem(TlvId.IssuerData, "Data to be written on a card as issuer data"),
EditTextItem(TlvId.Counter, "1")
))
}
}
class ReadIssuerExtraDataItemsManager : BaseItemsManager(ReadIssuerExtraDataAction()) {
init {
setItemChangeConsequences(CardIdConsequence())
setItems(listOf(EditTextItem(TlvId.CardId, null)))
}
}
class WriteIssuerExtraDataItemsManager : BaseItemsManager(WriteIssuerExtraDataAction()) {
init {
setItemChangeConsequences(CardIdConsequence())
setItems(listOf(
EditTextItem(TlvId.CardId, null),
EditTextItem(TlvId.Counter, "1")
))
}
}
class ReadUserDataItemsManager : BaseItemsManager(ReadUserDataAction()) {
init {
setItemChangeConsequences(CardIdConsequence())
setItems(listOf(EditTextItem(TlvId.CardId, null)))
}
}
class WriteUserDataItemsManager : BaseItemsManager(WriteUserDataAction()) {
init {
setItemChangeConsequences(CardIdConsequence())
setItems(listOf(
EditTextItem(TlvId.CardId, null),
EditTextItem(TlvId.Counter, "1"),
EditTextItem(TlvId.UserData, "User data to be written on a card"),
EditTextItem(TlvId.ProtectedUserData, "Protected user data to be written on a card")
))
}
}

View file

@ -3,10 +3,7 @@ package com.tangem.devkit.ucase.resources.initializers
import com.tangem.devkit.R
import com.tangem.devkit.ucase.resources.MainResourceHolder
import com.tangem.devkit.ucase.resources.Resources
import com.tangem.devkit.ucase.variants.responses.CardDataId
import com.tangem.devkit.ucase.variants.responses.CardId
import com.tangem.devkit.ucase.variants.responses.DepersonalizeId
import com.tangem.devkit.ucase.variants.responses.SignId
import com.tangem.devkit.ucase.variants.responses.*
/**
[REDACTED_AUTHOR]
@ -17,6 +14,13 @@ class ResponseResources {
initCardData(holder)
initSignResponse(holder)
initDepersonalizeResponse(holder)
initCreateWalletResponse(holder)
initPurgeWalletResponse(holder)
initReadIssuerDataResponse(holder)
initWriteIssuerDataResponse(holder)
initReadIssuerExtraDataResponse(holder)
initReadUserDataResponse(holder)
initWriteUserDataResponse(holder)
}
private fun initCard(holder: MainResourceHolder) {
@ -65,4 +69,46 @@ class ResponseResources {
private fun initDepersonalizeResponse(holder: MainResourceHolder) {
holder.register(DepersonalizeId.isSuccess, Resources(R.string.response_depersonalize_is_success, R.string.info_response_depersonalize_is_success))
}
private fun initCreateWalletResponse(holder: MainResourceHolder) {
holder.register(CreateWalletId.cid, Resources(R.string.response_card_cid, R.string.info_response_card_cid))
holder.register(CreateWalletId.cardStatus, Resources(R.string.response_card_status, R.string.info_response_card_status))
holder.register(CreateWalletId.walletPublicKey, Resources(R.string.response_card_wallet_public_key, R.string.info_response_card_wallet_public_key))
}
private fun initPurgeWalletResponse(holder: MainResourceHolder) {
holder.register(PurgeWalletId.cid, Resources(R.string.response_card_cid, R.string.info_response_card_cid))
holder.register(PurgeWalletId.cardStatus, Resources(R.string.response_card_status, R.string.info_response_card_status))
}
private fun initReadIssuerDataResponse(holder: MainResourceHolder) {
holder.register(ReadIssuerDataId.cid, Resources(R.string.response_card_cid, R.string.info_response_card_cid))
holder.register(ReadIssuerDataId.issuerData, Resources(R.string.response_issuer_data, R.string.info_response_issuer_data))
holder.register(ReadIssuerDataId.issuerDataSignature, Resources(R.string.response_issuer_data_signature, R.string.info_response_issuer_data_signature))
holder.register(ReadIssuerDataId.issuerDataCounter, Resources(R.string.response_issuer_data_counter, R.string.info_response_issuer_data_counter))
}
private fun initWriteIssuerDataResponse(holder: MainResourceHolder) {
holder.register(ReadIssuerDataId.cid, Resources(R.string.response_card_cid, R.string.info_response_card_cid))
}
private fun initReadIssuerExtraDataResponse(holder: MainResourceHolder) {
holder.register(ReadIssuerExtraDataId.cid, Resources(R.string.response_card_cid, R.string.info_response_card_cid))
holder.register(ReadIssuerExtraDataId.size, Resources(R.string.response_issuer_data_size, R.string.info_response_issuer_data_size))
holder.register(ReadIssuerExtraDataId.issuerData, Resources(R.string.response_issuer_data, R.string.info_response_issuer_data))
holder.register(ReadIssuerExtraDataId.issuerDataSignature, Resources(R.string.response_issuer_data_signature, R.string.info_response_issuer_data_signature))
holder.register(ReadIssuerExtraDataId.issuerDataCounter, Resources(R.string.response_issuer_data_counter, R.string.info_response_issuer_data_counter))
}
private fun initReadUserDataResponse(holder: MainResourceHolder) {
holder.register(ReadUserDataId.cid, Resources(R.string.response_card_cid, R.string.info_response_card_cid))
holder.register(ReadUserDataId.userData, Resources(R.string.response_user_data, R.string.info_response_user_data))
holder.register(ReadUserDataId.userProtectedData, Resources(R.string.response_user_protected_data, R.string.info_response_user_protected_data))
holder.register(ReadUserDataId.userCounter, Resources(R.string.response_user_data_counter, R.string.info_response_user_data_counter))
holder.register(ReadUserDataId.userProtectedCounter, Resources(R.string.response_user_data_protected_counter, R.string.info_response_user_data_protected_counter))
}
private fun initWriteUserDataResponse(holder: MainResourceHolder) {
holder.register(ReadIssuerDataId.cid, Resources(R.string.response_card_cid, R.string.info_response_card_cid))
}
}

View file

@ -16,5 +16,9 @@ class TlvResources {
private fun initScan(holder: MainResourceHolder) {
holder.register(TlvId.CardId, Resources(R.string.tlv_card_id, R.string.info_tlv_card_id))
holder.register(TlvId.TransactionOutHash, Resources(R.string.tlv_transaction_out_hash, R.string.info_tlv_transaction_out_hash))
holder.register(TlvId.Counter, Resources(R.string.tlv_counter, R.string.info_tlv_counter))
holder.register(TlvId.IssuerData, Resources(R.string.tlv_issuer_data, R.string.info_tlv_issuer_data))
holder.register(TlvId.UserData, Resources(R.string.tlv_issuer_data, R.string.info_tlv_user_data))
holder.register(TlvId.ProtectedUserData, Resources(R.string.tlv_user_protected_data, R.string.info_tlv_protected_user_data))
}
}

View file

@ -140,7 +140,7 @@ abstract class BaseCardActionFragment : BaseFragment(), ActionView {
})
}
private fun inflateParamView(where: ViewGroup): ViewGroup {
protected fun inflateParamView(where: ViewGroup): ViewGroup {
val inflater = LayoutInflater.from(where.context)
val view = inflater.inflate(R.layout.w_card_incoming_param, where, false)
where.plusAssign(view)

View file

@ -8,4 +8,8 @@ import com.tangem.devkit._arch.structure.Id
enum class TlvId : Id {
CardId,
TransactionOutHash,
IssuerData,
Counter,
UserData,
ProtectedUserData
}

View file

@ -0,0 +1,10 @@
package com.tangem.devkit.ucase.variants.createwallet.ui
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
import com.tangem.devkit.ucase.domain.paramsManager.managers.CreateWalletItemsManager
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
class CreateWalletActionFragment : BaseCardActionFragment() {
override val itemsManager: ItemsManager by lazy { CreateWalletItemsManager() }
}

View file

@ -0,0 +1,10 @@
package com.tangem.devkit.ucase.variants.issuerdata.ui
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
import com.tangem.devkit.ucase.domain.paramsManager.managers.ReadIssuerDataItemsManager
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
class ReadIssuerDataFragment : BaseCardActionFragment() {
override val itemsManager: ItemsManager by lazy { ReadIssuerDataItemsManager() }
}

View file

@ -0,0 +1,10 @@
package com.tangem.devkit.ucase.variants.issuerdata.ui
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
import com.tangem.devkit.ucase.domain.paramsManager.managers.ReadIssuerExtraDataItemsManager
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
class ReadIssuerExtraDataFragment : BaseCardActionFragment() {
override val itemsManager: ItemsManager by lazy { ReadIssuerExtraDataItemsManager() }
}

View file

@ -0,0 +1,10 @@
package com.tangem.devkit.ucase.variants.issuerdata.ui
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
import com.tangem.devkit.ucase.domain.paramsManager.managers.WriteIssuerDataItemsManager
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
class WriteIssuerDataFragment : BaseCardActionFragment() {
override val itemsManager: ItemsManager by lazy { WriteIssuerDataItemsManager() }
}

View file

@ -0,0 +1,10 @@
package com.tangem.devkit.ucase.variants.issuerdata.ui
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
import com.tangem.devkit.ucase.domain.paramsManager.managers.WriteIssuerExtraDataItemsManager
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
class WriteIssuerExtraDataFragment : BaseCardActionFragment() {
override val itemsManager: ItemsManager by lazy { WriteIssuerExtraDataItemsManager() }
}

View file

@ -4,6 +4,7 @@ import com.tangem.KeyPair
import com.tangem.commands.personalization.entities.Acquirer
import com.tangem.commands.personalization.entities.Issuer
import com.tangem.commands.personalization.entities.Manufacturer
import com.tangem.common.extensions.hexToBytes
/**
[REDACTED_AUTHOR]
@ -18,12 +19,14 @@ interface DefaultPersonalizationParams {
name = name,
id = name + "\u0000",
dataKeyPair = KeyPair(
"".toByteArray(),
"11121314151617184771ED81F2BACF57479E4735EB1405083927372D40DA9E92".toByteArray()
("045f16bd1d2eafe463e62a335a09e6b2bbcbd04452526885cb679fc4d27af1bd22f553c7deefb54fd3d4f" +
"361d14e6dc3f11b7d4ea183250a60720ebdf9e110cd26").hexToBytes(),
"11121314151617184771ED81F2BACF57479E4735EB1405083927372D40DA9E92".hexToBytes()
),
transactionKeyPair = KeyPair(
"".toByteArray(),
"11121314151617184771ED81F2BACF57479E4735EB1405081918171615141312".toByteArray()
("0484c5192e9bfa6c528a344f442137a92b89ea835bfef1d04cb4362eb906b508c5889846cfea71ba6dc7b" +
"3120c2208df9c46127d3d85cb5cfbd1479e97133a39d8").hexToBytes(),
"11121314151617184771ED81F2BACF57479E4735EB1405081918171615141312".hexToBytes()
)
)
}
@ -34,8 +37,9 @@ interface DefaultPersonalizationParams {
name = name,
id = name + "\u0000",
keyPair = KeyPair(
"".toByteArray(),
"21222324252627284771ED81F2BACF57479E4735EB1405083927372D40DA9E92".toByteArray()
("0456ad1a82b22bcb40c38fd08939f87e6b80e40dec5b3bdb351c55fcd709e47f9fb2ed00c2304d3a9" +
"86f79c5ae0ac3c84e88da46dc8f513b7542c716af8c9a2daf").hexToBytes(),
"21222324252627284771ED81F2BACF57479E4735EB1405083927372D40DA9E92".hexToBytes()
)
)
}

View file

@ -0,0 +1,10 @@
package com.tangem.devkit.ucase.variants.purgewallet.ui
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
import com.tangem.devkit.ucase.domain.paramsManager.managers.PurgeWalletItemsManager
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
class PurgeWalletActionFragment : BaseCardActionFragment() {
override val itemsManager: ItemsManager by lazy { PurgeWalletItemsManager() }
}

View file

@ -53,4 +53,38 @@ enum class SignId : ResponseId {
enum class DepersonalizeId: ResponseId {
isSuccess
}
enum class CreateWalletId : ResponseId {
cid,
cardStatus,
walletPublicKey,
}
enum class PurgeWalletId : ResponseId {
cid,
cardStatus
}
enum class ReadIssuerDataId : ResponseId {
cid,
issuerData,
issuerDataSignature,
issuerDataCounter
}
enum class ReadIssuerExtraDataId : ResponseId {
cid,
size,
issuerData,
issuerDataSignature,
issuerDataCounter
}
enum class ReadUserDataId : ResponseId {
cid,
userData,
userProtectedData,
userCounter,
userProtectedCounter
}

View file

@ -2,9 +2,7 @@ package com.tangem.devkit.ucase.variants.responses
import android.view.View
import androidx.lifecycle.ViewModel
import com.tangem.commands.Card
import com.tangem.commands.CommandResponse
import com.tangem.commands.SignResponse
import com.tangem.commands.*
import com.tangem.commands.personalization.DepersonalizeResponse
import com.tangem.devkit.R
import com.tangem.devkit._arch.structure.abstraction.Item
@ -44,6 +42,14 @@ class ResponseViewModel : ViewModel() {
is Card -> R.string.fg_name_response_personalization
is SignResponse -> R.string.fg_name_response_sign
is DepersonalizeResponse -> R.string.fg_name_response_depersonalization
is CreateWalletResponse -> R.string.fg_name_response_create_wallet
is PurgeWalletResponse -> R.string.fg_name_response_purge_wallet
is ReadIssuerDataResponse -> R.string.fg_name_response_read_issuer_data
is WriteIssuerDataResponse -> R.string.fg_name_response_write_issuer_data
is ReadIssuerExtraDataResponse -> R.string.fg_name_response_read_issuer_extra_data
is ReadUserDataResponse -> R.string.fg_name_response_read_user_data
is WriteUserDataResponse -> R.string.fg_name_response_write_user_data
else -> R.string.unknown
}
}

View file

@ -1,7 +1,6 @@
package com.tangem.devkit.ucase.variants.responses.converter
import com.tangem.commands.Card
import com.tangem.commands.SignResponse
import com.tangem.commands.*
import com.tangem.commands.personalization.DepersonalizeResponse
import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder
import java.lang.reflect.Type
@ -12,5 +11,12 @@ class ConvertersStore : BaseTypedHolder<Type, Any>() {
register(SignResponse::class.java, SignResponseConverter())
register(Card::class.java, CardConverter())
register(DepersonalizeResponse::class.java, DepersonalizeResponseConverter())
register(CreateWalletResponse::class.java, CreateWalletResponseConverter())
register(PurgeWalletResponse::class.java, PurgeWalletResponseConverter())
register(ReadIssuerDataResponse::class.java, ReadIssuerDataResponseConverter())
register(ReadIssuerExtraDataResponse::class.java, ReadIssuerExtraDataResponseConverter())
register(WriteIssuerDataResponse::class.java, WriteIssuerDataResponseConverter())
register(ReadUserDataResponse::class.java, ReadUserDataResponseConverter())
register(WriteUserDataResponse::class.java, WriteUserDataResponseConverter())
}
}

View file

@ -1,11 +1,10 @@
package com.tangem.devkit.ucase.variants.responses.converter
import com.tangem.commands.SignResponse
import com.tangem.commands.*
import com.tangem.commands.personalization.DepersonalizeResponse
import com.tangem.devkit._arch.structure.abstraction.Item
import com.tangem.devkit._arch.structure.impl.TextItem
import com.tangem.devkit.ucase.variants.responses.DepersonalizeId
import com.tangem.devkit.ucase.variants.responses.SignId
import com.tangem.devkit.ucase.variants.responses.*
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
/**
@ -27,4 +26,74 @@ class DepersonalizeResponseConverter : BaseResponseConverter<DepersonalizeRespon
override fun convert(from: DepersonalizeResponse): List<Item> {
return listOf(TextItem(DepersonalizeId.isSuccess, stringOf(from.success)))
}
}
class CreateWalletResponseConverter : BaseResponseConverter<CreateWalletResponse>() {
override fun convert(from: CreateWalletResponse): List<Item> {
return listOf(
TextItem(CreateWalletId.cid, from.cardId),
TextItem(CreateWalletId.cardStatus, valueToString(from.status)),
TextItem(CreateWalletId.walletPublicKey, fieldConverter.byteArray(from.walletPublicKey))
)
}
}
class PurgeWalletResponseConverter : BaseResponseConverter<PurgeWalletResponse>() {
override fun convert(from: PurgeWalletResponse): List<Item> {
return listOf(
TextItem(CreateWalletId.cid, from.cardId),
TextItem(CreateWalletId.cardStatus, valueToString(from.status))
)
}
}
class ReadIssuerDataResponseConverter : BaseResponseConverter<ReadIssuerDataResponse>() {
override fun convert(from: ReadIssuerDataResponse): List<Item> {
return listOf(
TextItem(ReadIssuerDataId.cid, from.cardId),
TextItem(ReadIssuerDataId.issuerData, fieldConverter.byteArray(from.issuerData)),
TextItem(ReadIssuerDataId.issuerDataSignature, fieldConverter.byteArray(from.issuerDataSignature)),
TextItem(ReadIssuerDataId.issuerDataCounter, valueToString(from.issuerDataCounter))
)
}
}
class ReadIssuerExtraDataResponseConverter : BaseResponseConverter<ReadIssuerExtraDataResponse>() {
override fun convert(from: ReadIssuerExtraDataResponse): List<Item> {
return listOf(
TextItem(ReadIssuerExtraDataId.cid, from.cardId),
TextItem(ReadIssuerExtraDataId.size, valueToString(from.size)),
TextItem(ReadIssuerExtraDataId.issuerData, fieldConverter.byteArray(from.issuerData)),
TextItem(ReadIssuerExtraDataId.issuerDataSignature, fieldConverter.byteArray(from.issuerDataSignature)),
TextItem(ReadIssuerExtraDataId.issuerDataCounter, valueToString(from.issuerDataCounter))
)
}
}
class WriteIssuerDataResponseConverter : BaseResponseConverter<WriteIssuerDataResponse>() {
override fun convert(from: WriteIssuerDataResponse): List<Item> {
return listOf(
TextItem(CardId.cardId, from.cardId)
)
}
}
class ReadUserDataResponseConverter : BaseResponseConverter<ReadUserDataResponse>() {
override fun convert(from: ReadUserDataResponse): List<Item> {
return listOf(
TextItem(ReadUserDataId.cid, from.cardId),
TextItem(ReadUserDataId.userData, fieldConverter.byteArray(from.userData)),
TextItem(ReadUserDataId.userProtectedData, fieldConverter.byteArray(from.userProtectedData)),
TextItem(ReadUserDataId.userCounter, valueToString(from.userCounter)),
TextItem(ReadUserDataId.userProtectedCounter, valueToString(from.userProtectedCounter))
)
}
}
class WriteUserDataResponseConverter : BaseResponseConverter<WriteUserDataResponse>() {
override fun convert(from: WriteUserDataResponse): List<Item> {
return listOf(
TextItem(CardId.cardId, from.cardId)
)
}
}

View file

@ -0,0 +1,10 @@
package com.tangem.devkit.ucase.variants.userdata.ui
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
import com.tangem.devkit.ucase.domain.paramsManager.managers.ReadUserDataItemsManager
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
class ReadUserDataFragment : BaseCardActionFragment() {
override val itemsManager: ItemsManager by lazy { ReadUserDataItemsManager() }
}

View file

@ -0,0 +1,10 @@
package com.tangem.devkit.ucase.variants.userdata.ui
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
import com.tangem.devkit.ucase.domain.paramsManager.managers.WriteUserDataItemsManager
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
class WriteUserDataFragment : BaseCardActionFragment() {
override val itemsManager: ItemsManager by lazy { WriteUserDataItemsManager() }
}

View file

@ -85,51 +85,51 @@
<fragment
android:id="@+id/nav_issuer_read_data"
android:name="com.tangem.devkit.ucase.ui.IssuerReadDataActionFragment"
android:name="com.tangem.devkit.ucase.variants.issuerdata.ui.ReadIssuerDataFragment"
android:label="@string/action_issuer_read_data"
tools:layout="@layout/fg_action_issuer_read_data" />
tools:layout="@layout/fg_base_action_layout" />
<fragment
android:id="@+id/nav_issuer_write_data"
android:name="com.tangem.devkit.ucase.ui.IssuerWriteDataActionFragment"
android:name="com.tangem.devkit.ucase.variants.issuerdata.ui.WriteIssuerDataFragment"
android:label="@string/action_issuer_write_data"
tools:layout="@layout/fg_action_issuer_write_data" />
tools:layout="@layout/fg_base_action_layout" />
<fragment
android:id="@+id/nav_issuer_read_ex_data"
android:name="com.tangem.devkit.ucase.ui.IssuerReadExDataActionFragment"
android:name="com.tangem.devkit.ucase.variants.issuerdata.ui.ReadIssuerExtraDataFragment"
android:label="@string/action_issuer_read_ex_data"
tools:layout="@layout/fg_action_issuer_read_ex_data" />
tools:layout="@layout/fg_base_action_layout" />
<fragment
android:id="@+id/nav_issuer_write_ex_data"
android:name="com.tangem.devkit.ucase.ui.IssuerWriteExDataActionFragment"
android:name="com.tangem.devkit.ucase.variants.issuerdata.ui.WriteIssuerExtraDataFragment"
android:label="@string/action_issuer_write_ex_data"
tools:layout="@layout/fg_action_issuer_write_ex_data" />
tools:layout="@layout/fg_base_action_layout" />
<fragment
android:id="@+id/nav_user_read_data"
android:name="com.tangem.devkit.ucase.ui.UserReadDataActionFragment"
android:name="com.tangem.devkit.ucase.variants.userdata.ui.ReadUserDataFragment"
android:label="@string/action_user_read_data"
tools:layout="@layout/fg_action_user_read_data" />
tools:layout="@layout/fg_base_action_layout" />
<fragment
android:id="@+id/nav_user_write_data"
android:name="com.tangem.devkit.ucase.ui.UserWriteDataActionFragment"
android:name="com.tangem.devkit.ucase.variants.userdata.ui.WriteUserDataFragment"
android:label="@string/action_user_write_data"
tools:layout="@layout/fg_action_user_write_data" />
tools:layout="@layout/fg_base_action_layout" />
<fragment
android:id="@+id/nav_wallet_create"
android:name="com.tangem.devkit.ucase.ui.WalletCreateActionFragment"
android:name="com.tangem.devkit.ucase.variants.createwallet.ui.CreateWalletActionFragment"
android:label="@string/action_wallet_create"
tools:layout="@layout/fg_action_wallet_create" />
tools:layout="@layout/fg_base_action_layout" />
<fragment
android:id="@+id/nav_wallet_purge"
android:name="com.tangem.devkit.ucase.ui.WalletPurgeActionFragment"
android:name="com.tangem.devkit.ucase.variants.purgewallet.ui.PurgeWalletActionFragment"
android:label="@string/action_wallet_purge"
tools:layout="@layout/fg_action_wallet_purge" />
tools:layout="@layout/fg_base_action_layout" />
<fragment
android:id="@+id/nav_card_response"

View file

@ -14,10 +14,17 @@
<string name="error_nothing_to_load">Nothing to load</string>
<string name="fg_name_entry_point">@string/app_name</string>
<string name="fg_name_response_scan">Read response</string>
<string name="fg_name_response_sign">Sign response</string>
<string name="fg_name_response_personalization">Personalization response</string>
<string name="fg_name_response_depersonalization">Depersonalization response</string>
<string name="fg_name_response_scan">Read Response</string>
<string name="fg_name_response_sign">Sign Response</string>
<string name="fg_name_response_personalization">Personalization Response</string>
<string name="fg_name_response_depersonalization">Depersonalization Response</string>
<string name="fg_name_response_create_wallet">Create Wallet Response</string>
<string name="fg_name_response_purge_wallet">Purge Wallet Response</string>
<string name="fg_name_response_read_issuer_data">Read Issuer Data Response</string>
<string name="fg_name_response_write_issuer_data">Write Issuer Data Response</string>
<string name="fg_name_response_read_issuer_extra_data">Read Issuer Extra Data Response</string>
<string name="fg_name_response_read_user_data">Read User Data Response</string>
<string name="fg_name_response_write_user_data">Write User Data Response</string>
<string name="switch_description">Docs</string>

View file

@ -5,27 +5,28 @@
<string name="action_card_sign">Sign</string>
<string name="action_personalize">Personalize</string>
<string name="action_depersonalize">Depersonalize</string>
<string name="action_wallet_create">Create wallet</string>
<string name="action_wallet_purge">Purge wallet</string>
<string name="action_issuer_read_data">Read issuer data</string>
<string name="action_issuer_write_data">Write issuer data</string>
<string name="action_issuer_read_ex_data">Read issuer extra data</string>
<string name="action_issuer_write_ex_data">Write issuer extra data</string>
<string name="action_user_read_data">Read user data</string>
<string name="action_user_write_data">Write user data</string>
<string name="action_wallet_create">Create Wallet</string>
<string name="action_wallet_purge">Purge Wallet</string>
<string name="action_issuer_read_data">Read Issuer Data</string>
<string name="action_issuer_write_data">Write Issuer Data</string>
<string name="action_issuer_read_ex_data">Read Issuer Extra Data</string>
<string name="action_issuer_write_ex_data">Write Issuer Extra Data</string>
<string name="action_user_read_data">Read User Data</string>
<string name="action_user_write_data">Write User Data</string>
<string name="info_action_card_scan">This command returns all data about the card and the wallet, including unique card number (CID) that has to be submitted while calling all other commands</string>
<string name="info_action_card_sign">Depending on Signing_Method parameter defined during personalization, this command signs data using Wallet_PrivateKey</string>
<string name="info_action_personalize">Personalization is an initialization procedure, required before start using a card. During this procedure all card setting are performed. During this procedure all data exchange are encrypted because it\'s usually done at the third-party factory.</string>
<string name="info_action_depersonalize">This command reset card to initial state - erase all data, writed during previous personalization and previous usage.
\nCommand available on SDK cards only</string>
<string name="info_action_wallet_create">SomeDescription</string>
<string name="info_action_wallet_purge">SomeDescription</string>
<string name="info_action_issuer_read_data">SomeDescription</string>
<string name="info_action_issuer_write_data">SomeDescription</string>
<string name="info_action_issuer_read_ex_data">SomeDescription</string>
<string name="info_action_issuer_write_ex_data">SomeDescription</string>
<string name="info_action_user_read_data">SomeDescription</string>
<string name="info_action_user_write_data">SomeDescription</string>
<string name="info_action_wallet_create">If the card has an Empty state, this command will create a new wallet, changing a state to Loaded.</string>
<string name="info_action_wallet_purge">This command deletes all wallet data. If IsReusable flag was enabled during personalization, the card changes state to Empty and a new wallet can be created by Create Wallet Command.</string>
<string name="info_action_issuer_read_data">This command returns 512-byte Issuer Data field and its issuers signature.</string>
<string name="info_action_issuer_write_data">This command writes 512-byte Issuer Data field and its issuers signature to the card.</string>
<string name="info_action_issuer_read_ex_data">This command retrieves Issuer Extra Data field and its issuers signature.</string>
<string name="info_action_issuer_write_ex_data">This command writes Issuer Extra Data field and its issuers signature to the card.</string>
<string name="info_action_user_read_data">This command returns User Data and User Protected Data (up to 512-byte each) and two counters: User Counter and User Protected Counter.</string>
<string name="info_action_user_write_data"> This command writes to the card any of User Data, User Protected Data, User Counter and User Protected Counter fields.
</string>
</resources>

View file

@ -155,4 +155,27 @@
<string name="info_response_depersonalize_is_success">Is success</string>
<!-- Field names - Response: Read Issuer (Extra) Data -->
<string name="response_issuer_data_size">Size of Issuer Data</string>
<string name="response_issuer_data">Issuer Data</string>
<string name="response_issuer_data_signature">Issuer Data Signature</string>
<string name="response_issuer_data_counter">Issuer Data Counter</string>
<string name="info_response_issuer_data_size">A size of issuer extra data written on a card.</string>
<string name="info_response_issuer_data">Data defined by the issuer.</string>
<string name="info_response_issuer_data_signature">Issuer data, signed by the issuer with issuer data private key.</string>
<string name="info_response_issuer_data_counter">An optional counter that protects issuer data against replay attack.</string>
<!-- Field names - Response: Read User Data -->
<string name="response_user_data">User Data</string>
<string name="response_user_protected_data">Protected User Data</string>
<string name="response_user_data_counter">User Data Counter</string>
<string name="response_user_data_protected_counter">Protected User Data Counter</string>
<string name="info_response_user_data">Data defined by user\'s App</string>
<string name="info_response_user_protected_data">Data defined by users App (confirmed by PIN2)</string>
<string name="info_response_user_data_counter">Counter initialized by users App and increased on every signing of new transaction</string>
<string name="info_response_user_data_protected_counter">Counter initialized by users App (confirmed by PIN2) and increased on every signing of new transaction</string>
</resources>

View file

@ -3,8 +3,16 @@
<string name="tlv_card_id">Card Id (CID)</string>
<string name="tlv_transaction_out_hash">Hash to sign</string>
<string name="tlv_issuer_data">Issuer Data</string>
<string name="tlv_user_data">User Data</string>
<string name="tlv_user_protected_data">Protected User Data</string>
<string name="tlv_counter">Counter</string>
<string name="info_tlv_card_id">Unique Tangem card ID number</string>
<string name="info_tlv_transaction_out_hash">Hashed transaction you want to be signed </string>
<string name="info_tlv_issuer_data">Issuer Data to be written by this command</string>
<string name="info_tlv_user_data">User Data to be written by this command</string>
<string name="info_tlv_protected_user_data">Protected User Data to be written by this command</string>
<string name="info_tlv_counter">Counter that protects this type of data against replay attack.</string>
</resources>