diff --git a/tangem-demo/src/main/assets/personalize_default.json b/tangem-demo/src/main/assets/personalize_default.json deleted file mode 100644 index 428ff30a50..0000000000 --- a/tangem-demo/src/main/assets/personalize_default.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "issuerData": null, - "issuerName": "TANGEM SDK", - "series": "DB", - "numberFormat": "", - "PIN": "000000", - "PIN2": "000", - "PIN3": "", - "hexCrExKey": "", - "CVC": "000", - "curveID": "ed25519", - "ndef": "com.tangem.wallet", - "startNumber": 300000000, - "count": 20, - "SigningMethod": 0, - "MaxSignatures": 1000000, - "pauseBeforePIN2": 15000, - "smartSecurityDelay": true, - "releaseVersion": false, - "isReusable": true, - "allowSwapPIN": false, - "allowSwapPIN2": true, - "useActivation": false, - "useCVC": false, - "useNDEF": true, - "useDynamicNDEF": true, - "useOneCommandAtTime": false, - "useBlock": false, - "allowSelectBlockchain": false, - "forbidPurgeWallet": false, - "protocolAllowUnencrypted": true, - "protocolAllowStaticEncryption": true, - "protectIssuerDataAgainstReplay": true, - "forbidDefaultPIN": false, - "disablePrecomputedNDEF": false, - "skipSecurityDelayIfValidatedByIssuer": false, - "skipCheckPIN2andCVCIfValidatedByIssuer": false, - "skipSecurityDelayIfValidatedByLinkedTerminal": true, - "restrictOverwriteIssuerDataEx": false, - "requireTerminalTxSignature": false, - "requireTerminalCertSignature": false, - "checkPIN3onCard": false, - "cardData": { - "date": "2020-02-17", - "batch": "FF87", - "blockchain": "XLM", - "product_note": true, - "product_tag": false, - "product_id_card": false - }, - "createWallet": true -} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt index 51e8223bea..87666d0646 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt @@ -10,25 +10,25 @@ import com.tangem.tasks.TaskEvent */ class PersonalizeAction : BaseCardAction() { override fun executeMainAction(attrs: AttrForAction, callback: ActionCallback) { + var cardId: String? = null ScanAction().executeMainAction(attrs) { response, b -> when (response) { is TaskEvent.Event -> { val taskEvent = response as TaskEvent.Event - val cardId = handleDataEvent(taskEvent.data) + cardId = handleDataEvent(taskEvent.data) if (cardId == null) { handleResponse(response, null, attrs, callback) return@executeMainAction } + } + is TaskEvent.Completion -> { val cardConfig = attrs.payload.remove(cardConfig) as? CardConfig ?: throw IllegalArgumentException("CardConfig must be in the payloads of the ParamsManager") - attrs.cardManager.personalize(cardConfig, cardId) { + attrs.cardManager.personalize(cardConfig, cardId!!) { handleResponse(it, null, attrs, callback) } } - is TaskEvent.Completion -> { - handleResponse(response, null, attrs, callback) - } } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizeConfigConverter.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizeConfigConverter.kt index 6223b4eae3..9696b368db 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizeConfigConverter.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizeConfigConverter.kt @@ -244,46 +244,47 @@ class PersonalizeConfigConverter { }?.let { ndefs.add(it) } return CardConfig( - cardData = cardData, - curveID = EllipticCurve.byName(applyConfig.curveID) ?: EllipticCurve.Secp256k1, - signingMethod = signingMethod, - createWallet = applyConfig.createWallet, - maxSignatures = applyConfig.MaxSignatures.toInt(), - isReusable = applyConfig.isReusable, - protocolAllowUnencrypted = applyConfig.protocolAllowUnencrypted, - protocolAllowStaticEncryption = applyConfig.protocolAllowStaticEncryption, - useActivation = applyConfig.useActivation, - - useOneCommandAtTime = applyConfig.oneApdu, - useCvc = applyConfig.useCVC, - useBlock = applyConfig.useBlock, - allowSwapPin = applyConfig.allowSwapPIN, - allowSwapPin2 = applyConfig.allowSwapPIN2, - useNdef = applyConfig.useNDEF, - useDynamicNdef = applyConfig.useDynamicNDEF, - protectIssuerDataAgainstReplay = applyConfig.protectIssuerDataAgainstReplay, - forbidDefaultPin = applyConfig.forbidDefaultPIN, - smartSecurityDelay = applyConfig.smartSecurityDelay, - pauseBeforePin2 = applyConfig.pauseBeforePIN2.toInt(), - allowSelectBlockchain = applyConfig.allowSelectBlockchain, - forbidPurgeWallet = applyConfig.forbidPurgeWallet, - disablePrecomputedNdef = applyConfig.disablePrecomputedNDEF, - skipSecurityDelayIfValidatedByIssuer = applyConfig.skipSecurityDelayIfValidatedByIssuer, - skipCheckPIN2andCVCIfValidatedByIssuer = applyConfig.skipCheckPIN2andCVCIfValidatedByIssuer, - - skipSecurityDelayIfValidatedByLinkedTerminal = applyConfig.skipSecurityDelayIfValidatedByLinkedTerminal, - restrictOverwriteIssuerDataEx = applyConfig.restrictOverwriteIssuerDataEx, - - requireTerminalTxSignature = applyConfig.requireTerminalTxSignature, - requireTerminalCertSignature = applyConfig.requireTerminalCertSignature, - checkPin3onCard = applyConfig.checkPIN3onCard, - - cvc = applyConfig.CVC, - pin = applyConfig.PIN, - pin2 = applyConfig.PIN2, - pin3 = applyConfig.PIN3, - hexCrExKey = applyConfig.hexCrExKey, - ndefRecords = ndefs + "Tangem", + "MyHomeLts", + "HS", + 0, + 1000, + applyConfig.PIN, + applyConfig.PIN2, + applyConfig.PIN3, + applyConfig.hexCrExKey, + applyConfig.CVC, + applyConfig.pauseBeforePIN2.toInt(), + applyConfig.smartSecurityDelay, + EllipticCurve.byName(applyConfig.curveID) ?: EllipticCurve.Secp256k1, + signingMethod, + applyConfig.MaxSignatures.toInt(), + applyConfig.isReusable, + applyConfig.allowSwapPIN, + applyConfig.allowSwapPIN2, + applyConfig.useActivation, + applyConfig.useCVC, + applyConfig.useNDEF, + applyConfig.useDynamicNDEF, + applyConfig.oneApdu, + applyConfig.useBlock, + applyConfig.allowSelectBlockchain, + applyConfig.forbidPurgeWallet, + applyConfig.protocolAllowUnencrypted, + applyConfig.protocolAllowStaticEncryption, + applyConfig.protectIssuerDataAgainstReplay, + applyConfig.forbidDefaultPIN, + applyConfig.disablePrecomputedNDEF, + applyConfig.skipSecurityDelayIfValidatedByIssuer, + applyConfig.skipCheckPIN2andCVCIfValidatedByIssuer, + applyConfig.skipSecurityDelayIfValidatedByLinkedTerminal, + applyConfig.restrictOverwriteIssuerDataEx, + applyConfig.requireTerminalTxSignature, + applyConfig.requireTerminalCertSignature, + applyConfig.checkPIN3onCard, + applyConfig.createWallet, + cardData, + ndefs ) } } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/CardManagerConfig.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/CardManagerConfig.kt new file mode 100644 index 0000000000..424790bb68 --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/CardManagerConfig.kt @@ -0,0 +1,54 @@ +package com.tangem.tangemtest.ucase.variants.personalize.dto + +import com.tangem.Config +import com.tangem.commands.personalization.entities.Issuer +import com.tangem.common.KeyPair + +/** +[REDACTED_AUTHOR] + */ + +interface CardManagerConfig { + companion object { + fun default(): Config { + val issuer = issuer() + return Config( + true, + issuer = issuer(), + issuerPublicKey = null, + acquirerKeyPair = acquirer(), + manufacturerKeyPair = manufacturer() + ) + } + + private fun issuer(): Issuer { + return Issuer( + name = "TANGEM SDK", + id = "TANGEM SDK" + "\u0000", + dataKeyPair = KeyPair( + "".toByteArray(), + "11121314151617184771ED81F2BACF57479E4735EB1405083927372D40DA9E92".toByteArray() + ), + transactionKeyPair = KeyPair( + "".toByteArray(), + "11121314151617184771ED81F2BACF57479E4735EB1405081918171615141312".toByteArray() + ) + ) + } + + private fun acquirer(): KeyPair { + return KeyPair( + "".toByteArray(), + "21222324252627284771ED81F2BACF57479E4735EB1405083927372D40DA9E92".toByteArray() + ) + } + + private fun manufacturer(): KeyPair { + val manufacturer = Manufacturer(Manufacturer.Mode.Developer) + return KeyPair( + manufacturer.publicKey, + manufacturer.privateKey + ) + } + } +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/Manufacturer.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/Manufacturer.kt new file mode 100644 index 0000000000..8a366eeb26 --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/Manufacturer.kt @@ -0,0 +1,53 @@ +package com.tangem.tangemtest.ucase.variants.personalize.dto + +class Manufacturer(private val mode: Mode) { + + private val devPrivateKeyArray = byteArrayOf( + 0x1B.toByte(), 0x48.toByte(), 0xCF.toByte(), 0xD2.toByte(), 0x4B.toByte(), 0xBB.toByte(), 0x5B.toByte(), 0x39.toByte(), + 0x47.toByte(), 0x71.toByte(), 0xED.toByte(), 0x81.toByte(), 0xF2.toByte(), 0xBA.toByte(), 0xCF.toByte(), 0x57.toByte(), + 0x47.toByte(), 0x9E.toByte(), 0x47.toByte(), 0x35.toByte(), 0xEB.toByte(), 0x14.toByte(), 0x05.toByte(), 0x08.toByte(), + 0x39.toByte(), 0x27.toByte(), 0x37.toByte(), 0x2D.toByte(), 0x40.toByte(), 0xDA.toByte(), 0x9E.toByte(), 0x92.toByte() + ) + private val devPublicKeyArray = byteArrayOf(0x04, + 0xBA.toByte(), 0xB8.toByte(), 0x6D.toByte(), 0x56.toByte(), 0x29.toByte(), 0x8C.toByte(), 0x99.toByte(), 0x6F.toByte(), + 0x56.toByte(), 0x4A.toByte(), 0x84.toByte(), 0xFC.toByte(), 0x88.toByte(), 0xE2.toByte(), 0x8A.toByte(), 0xED.toByte(), + 0x38.toByte(), 0x18.toByte(), 0x4B.toByte(), 0x12.toByte(), 0xF0.toByte(), 0x7E.toByte(), 0x51.toByte(), 0x91.toByte(), + 0x13.toByte(), 0xBE.toByte(), 0xF4.toByte(), 0x8C.toByte(), 0x76.toByte(), 0xF3.toByte(), 0xDF.toByte(), 0x3A.toByte(), + 0xDC.toByte(), 0x30.toByte(), 0x35.toByte(), 0x99.toByte(), 0xB0.toByte(), 0x8A.toByte(), 0xC0.toByte(), 0x5B.toByte(), + 0x55.toByte(), 0xEC.toByte(), 0x3D.toByte(), 0xF9.toByte(), 0x8D.toByte(), 0x93.toByte(), 0x38.toByte(), 0x57.toByte(), + 0x3A.toByte(), 0x62.toByte(), 0x42.toByte(), 0xF7.toByte(), 0x6F.toByte(), 0x5D.toByte(), 0x28.toByte(), 0xF4.toByte(), + 0xF0.toByte(), 0xF3.toByte(), 0x64.toByte(), 0xE8.toByte(), 0x7E.toByte(), 0x8F.toByte(), 0xCA.toByte(), 0x2F.toByte() + ) + private val releasePublicKeyArray = byteArrayOf(0x04.toByte(), + 0x2E.toByte(), 0xDE.toByte(), 0x11.toByte(), 0x9B.toByte(), 0xF3.toByte(), 0x37.toByte(), 0xB2.toByte(), 0x64.toByte(), + 0xFD.toByte(), 0xA1.toByte(), 0x32.toByte(), 0xCF.toByte(), 0xC7.toByte(), 0xC1.toByte(), 0x77.toByte(), 0x82.toByte(), + 0x4D.toByte(), 0x36.toByte(), 0x17.toByte(), 0xDA.toByte(), 0xC8.toByte(), 0x0F.toByte(), 0x25.toByte(), 0xDB.toByte(), + 0xB2.toByte(), 0xA4.toByte(), 0xA8.toByte(), 0xA1.toByte(), 0x18.toByte(), 0x3C.toByte(), 0x03.toByte(), 0xB9.toByte(), + 0x15.toByte(), 0x23.toByte(), 0x05.toByte(), 0xF8.toByte(), 0xF1.toByte(), 0xDB.toByte(), 0x97.toByte(), 0x00.toByte(), + 0x45.toByte(), 0x18.toByte(), 0x48.toByte(), 0x0D.toByte(), 0x50.toByte(), 0x91.toByte(), 0xAD.toByte(), 0xC1.toByte(), + 0xCA.toByte(), 0xB9.toByte(), 0xEA.toByte(), 0xCC.toByte(), 0xC1.toByte(), 0x8E.toByte(), 0x1B.toByte(), 0x9E.toByte(), + 0x9C.toByte(), 0x3B.toByte(), 0xEF.toByte(), 0xB2.toByte(), 0x93.toByte(), 0xDD.toByte(), 0x37.toByte(), 0xB2.toByte() + ) + + val publicKey: ByteArray + get() = if (mode == Mode.Developer) { + devPublicKeyArray + } else { + releasePublicKeyArray + } + + @get:Throws(Exception::class) + val privateKey: ByteArray + get() = if (mode == Mode.Developer) { + devPrivateKeyArray + } else { + throw Exception("Real manufacturer key is very secret!") + } + + val name: String + get() = if (mode == Mode.Release) "SMART CASH" else "SMART CASH SDK" + + enum class Mode { + Developer, Release + } +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeFragment.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeFragment.kt index 930f22cef5..1316456113 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeFragment.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeFragment.kt @@ -1,6 +1,5 @@ package com.tangem.tangemtest.ucase.variants.personalize.ui -import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -13,7 +12,10 @@ import androidx.lifecycle.Observer import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import com.tangem.CardManager -import com.tangem.tangem_sdk_new.extensions.init +import com.tangem.tangem_sdk_new.DefaultCardManagerDelegate +import com.tangem.tangem_sdk_new.NfcLifecycleObserver +import com.tangem.tangem_sdk_new.TerminalKeysStorage +import com.tangem.tangem_sdk_new.nfc.NfcManager import com.tangem.tangemtest.R import com.tangem.tangemtest._arch.structure.abstraction.Block import com.tangem.tangemtest._main.MainViewModel @@ -23,12 +25,11 @@ import com.tangem.tangemtest.ucase.domain.paramsManager.ParamsManagerFactory import com.tangem.tangemtest.ucase.resources.ActionType import com.tangem.tangemtest.ucase.ui.ActionViewModelFactory import com.tangem.tangemtest.ucase.ui.ParamsViewModel +import com.tangem.tangemtest.ucase.variants.personalize.dto.CardManagerConfig +import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.WidgetBuilder import kotlinx.android.synthetic.main.fg_personalize.* import ru.dev.gbixahue.eu4d.lib.android.global.log.Log -import java.io.IOException -import java.io.InputStream -import java.nio.charset.Charset /** [REDACTED_AUTHOR] @@ -36,7 +37,7 @@ import java.nio.charset.Charset class PersonalizeFragment : Fragment() { private val mainActivityVM: MainViewModel by activityViewModels() - private val personalizeVM: PersonalizeViewModel by viewModels { PersonalizeViewModelFactory(getPersonalizeJson()) } + private val personalizeVM: PersonalizeViewModel by viewModels { PersonalizeViewModelFactory(PersonalizeConfig()) } private val paramsManager: ParamsManager by lazy { ParamsManagerFactory.createFactory().get(ActionType.Personalize)!! } private val paramsVM: ParamsViewModel by viewModels() { ActionViewModelFactory(paramsManager) } @@ -55,6 +56,8 @@ class PersonalizeFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + val cardManager = initCardManager() ?: return + val blockList = mutableListOf() personalizeVM.ldBlockList.observe(viewLifecycleOwner, Observer { list -> blockList.clear() @@ -65,7 +68,7 @@ class PersonalizeFragment : Fragment() { personalizeVM.toggleDescriptionVisibility(it) }) - paramsVM.setCardManager(CardManager.init(requireActivity())) + paramsVM.setCardManager(cardManager) paramsVM.ldResponse.observe(viewLifecycleOwner, Observer { Log.d(this, "action response: ${if (it.length > 50) it.substring(0..50) else it}") showSnackbarMessage(it) @@ -78,27 +81,37 @@ class PersonalizeFragment : Fragment() { } } + private fun initCardManager(): CardManager? { + val activity = activity ?: return null + val nfcManager = NfcManager().apply { + this.setCurrentActivity(activity) + activity.lifecycle.addObserver(NfcLifecycleObserver(this)) + } + val cardManagerDelegate = DefaultCardManagerDelegate(nfcManager.reader).apply { + this.activity = activity + } + return CardManager(nfcManager.reader, cardManagerDelegate, CardManagerConfig.default()).apply { + this.setTerminalKeysService(TerminalKeysStorage(activity.application)) + } + } + protected fun showSnackbarMessage(message: String) { Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show() } - private fun getPersonalizeJson(): String { - return getJsonFromAssets(requireContext(), "personalize_default.json") ?: "[]" - } - - private fun getJsonFromAssets(context: Context, fileName: String): String? { - return try { - val stream: InputStream = context.assets.open(fileName) - val size: Int = stream.available() - val buffer = ByteArray(size) - stream.read(buffer) - stream.close() - String(buffer, Charset.forName("UTF-8")) - } catch (e: IOException) { - e.printStackTrace() - null - } - } +// private fun getJsonFromAssets(context: Context, fileName: String): String? { +// return try { +// val stream: InputStream = context.assets.open(fileName) +// val size: Int = stream.available() +// val buffer = ByteArray(size) +// stream.read(buffer) +// stream.close() +// String(buffer, Charset.forName("UTF-8")) +// } catch (e: IOException) { +// e.printStackTrace() +// null +// } +// } } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeViewModel.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeViewModel.kt index cd60a87f98..56d9ba2aac 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeViewModel.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeViewModel.kt @@ -14,18 +14,17 @@ import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig /** [REDACTED_AUTHOR] */ -class PersonalizeViewModelFactory(private val jsonPersonalizeString: String) : ViewModelProvider.NewInstanceFactory() { - override fun create(modelClass: Class): T = PersonalizeViewModel(jsonPersonalizeString) as T +class PersonalizeViewModelFactory(private val config: PersonalizeConfig) : ViewModelProvider.NewInstanceFactory() { + override fun create(modelClass: Class): T = PersonalizeViewModel(config) as T } -class PersonalizeViewModel(private val jsonPersonalizeString: String) : ViewModel() { +class PersonalizeViewModel(private val config: PersonalizeConfig) : ViewModel() { val ldBlockList: MutableLiveData> by lazy { MutableLiveData(initBlockList()) } - private fun initBlockList(): List = parseJsonToBlockList(jsonPersonalizeString) + private fun initBlockList(): List = createBlocksFromConfig(config) - fun parseJsonToBlockList(jsonString: String): List { - val config = Gson().fromJson(jsonString, PersonalizeConfig::class.java) + fun createBlocksFromConfig(config: PersonalizeConfig): List { return PersonalizeConfigConverter().toBlock(config) }