diff --git a/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java b/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java index 8f30cd2f6b..96d9993c0d 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java +++ b/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java @@ -9,6 +9,7 @@ import android.util.Log; import com.tangem.domain.wallet.CoinEngine; import com.tangem.domain.wallet.CoinEngineFactory; import com.tangem.domain.wallet.Issuer; +import com.tangem.domain.wallet.LocalStorage; import com.tangem.domain.wallet.TangemCard; import com.tangem.domain.wallet.Manufacturer; import com.tangem.util.Util; @@ -469,7 +470,6 @@ public class CardProtocol { if( mCard.getBatch().equals("0017") ) { - mCard.setContractAddress("0x9Eef75bA8e81340da9D8d1fd06B2f313DB88839c"); } else if( mCard.getBatch().equals("0019") ) @@ -524,6 +524,17 @@ public class CardProtocol { } } + // substitutions for card, that was produced with wrong blockchain data (for example token contract was unknown) + try { + LocalStorage localStorage = new LocalStorage(mContext); + localStorage.applySubstitution(mCard); + }catch(Exception e) + { + Log.e(logTag, "Can't apply card data substitution"); + e.printStackTrace(); + } + + try { mCard.setSettingsMask(readResult.getTagAsInt(TLV.Tag.TAG_SettingsMask)); } catch (Exception e) { diff --git a/app/src/main/java/com/tangem/domain/wallet/LocalStorage.kt b/app/src/main/java/com/tangem/domain/wallet/LocalStorage.kt index d9e391a87c..68a114d6bc 100644 --- a/app/src/main/java/com/tangem/domain/wallet/LocalStorage.kt +++ b/app/src/main/java/com/tangem/domain/wallet/LocalStorage.kt @@ -6,7 +6,9 @@ import android.graphics.Bitmap import java.io.File import kotlin.collections.HashMap import android.graphics.BitmapFactory +import android.util.Log import com.google.gson.Gson +import com.google.gson.annotations.SerializedName import com.google.gson.reflect.TypeToken import com.tangem.data.network.model.CardVerifyAndGetInfo import com.tangem.domain.cardReader.CardCrypto @@ -37,36 +39,44 @@ data class LocalStorage( artworksFile.bufferedReader().use { artworks = Gson().fromJson(it, object : TypeToken>() {}.type) } } else { artworks = HashMap() - putResourceArtworkToCatalog("card_default", false) - putResourceArtworkToCatalog("card_btc_001", false) - putResourceArtworkToCatalog("card_btc_005", true) + putResourceArtworkToCatalog(R.drawable.card_default, false) + putResourceArtworkToCatalog(R.drawable.card_ru006, false) + putResourceArtworkToCatalog(R.drawable.card_ru007, false) + putResourceArtworkToCatalog(R.drawable.card_ru011, false) + putResourceArtworkToCatalog(R.drawable.card_ru012, false) + putResourceArtworkToCatalog(R.drawable.card_ru013, false) + putResourceArtworkToCatalog(R.drawable.card_ru014, false) + putResourceArtworkToCatalog(R.drawable.card_ru015, false) + putResourceArtworkToCatalog(R.drawable.card_ru016, false) + putResourceArtworkToCatalog(R.drawable.card_ru020, false) + putResourceArtworkToCatalog(R.drawable.card_ru021, false) + putResourceArtworkToCatalog(R.drawable.card_ru022, false) + putResourceArtworkToCatalog(R.drawable.card_ru023, true) } if (batchesFile.exists()) { batchesFile.bufferedReader().use { batches = Gson().fromJson(it, object : TypeToken>() {}.type) } } else { batches = HashMap() -// putBatchToCatalog("0004", "card_btc_001", false) -// putBatchToCatalog("0006", "card_btc_001", false) -// putBatchToCatalog("0010", "card_btc_001", false) -// -// putBatchToCatalog("0005", "card_btc_005", false) -// putBatchToCatalog("0007", "card_btc_005", false) -// putBatchToCatalog("0011", "card_btc_005", true) - -// "0012": card_seed; -// "0013": card_btc_hk_s; -// "0014": card_btc_0014 -// "0015": card_btc_000; -// "0016": card_eth000; -// "0017": card_qlear200; -// "0019": card_cle100; -// "001A": card_btc_001a; -// "001B": card_btc_001b; -// "001C": card_btc_001c; -// "001D": card_eth_001d; + putBatchToCatalog("0004", R.drawable.card_ru006, false) + putBatchToCatalog("0006", R.drawable.card_ru006, false) + putBatchToCatalog("0010", R.drawable.card_ru006, false) + putBatchToCatalog("0005", R.drawable.card_ru007, false) + putBatchToCatalog("0007", R.drawable.card_ru007, false) + putBatchToCatalog("0011", R.drawable.card_ru007, false) + putBatchToCatalog("0012", R.drawable.card_ru011, false) + putBatchToCatalog("0013", R.drawable.card_ru012, false) + putBatchToCatalog("0014", R.drawable.card_ru006, false) + putBatchToCatalog("0015", R.drawable.card_ru020, false) + putBatchToCatalog("0016", R.drawable.card_ru021, false) + putBatchToCatalog("0017", R.drawable.card_ru013, false) + putBatchToCatalog("0019", R.drawable.card_ru016, false) + putBatchToCatalog("001A", R.drawable.card_ru014, false) + putBatchToCatalog("001B", R.drawable.card_ru015, false) + putBatchToCatalog("001C", R.drawable.card_ru023, false) + putBatchToCatalog("001D", R.drawable.card_ru022, true) } } @@ -89,7 +99,7 @@ data class LocalStorage( } fun checkNeedUpdateArtwork(artwork: CardVerifyAndGetInfo.Response.Item.ArtworkInfo?): Boolean { - if (artwork == null) return false + if (artwork == null || artwork.id.isBlank()) return false val localArtwork = artworks[artwork.id] ?: return true if (localArtwork.hash == artwork.hash) return false @@ -98,16 +108,20 @@ data class LocalStorage( return localArtwork.updateDate == null || localArtwork.updateDate < artwork.getUpdateDate() } - fun checkBatchInfoChanged(result: CardVerifyAndGetInfo.Response.Item): Boolean { + fun checkBatchInfoChanged(card: TangemCard, result: CardVerifyAndGetInfo.Response.Item): Boolean { var sData: String? = result.substitution?.data var sSignature: String? = result.substitution?.signature - if (!BatchInfo.CardDataSubstitution.verifySignature(result.batch, sData, sSignature)) { + if( card.batch!=result.batch ) { + Log.e("LocalStorage", "Invalid batch received!") + return false + } + if (!BatchInfo.CardDataSubstitution.verifySignature(card, sData, sSignature)) { sData = null sSignature = null } val batchInfo = batches[result.batch] - if (batchInfo == null || batchInfo.artworkId != result.artwork?.id || batchInfo.dataSubstitution != sData) { - putBatchToCatalog(result.batch, result.artwork?.id, sData, sSignature) + if (batchInfo == null || batchInfo.artworkId?.toLowerCase() != result.artwork?.id?.toLowerCase() || batchInfo.dataSubstitution != sData) { + putBatchToCatalog(result.batch, result.artwork?.id?.toLowerCase(), sData, sSignature) return true } return false @@ -115,10 +129,14 @@ data class LocalStorage( fun updateArtwork(artworkId: String, inputStream: InputStream, updateDate: Instant) { val data = inputStream.readBytes() - saveArtworkBitmapToFile(artworkId, data) + saveArtworkBitmapToFile(artworkId.toLowerCase(), data) putArtworkToCatalog(artworkId, false, data, updateDate, true) } + private fun putBatchToCatalog(batch: String, resourceId: Int, forceSave: Boolean = true) { + putBatchToCatalog(batch, context.resources.getResourceEntryName(resourceId), null, null, forceSave) + } + private fun putBatchToCatalog(batch: String, artworkId: String?, substitution: String?, substitutionSignature: String?, forceSave: Boolean = true) { batches[batch] = BatchInfo(artworkId, substitution, substitutionSignature) if (forceSave) { @@ -128,15 +146,15 @@ data class LocalStorage( } @SuppressLint("ResourceType") - private fun putResourceArtworkToCatalog(artworkId: String, forceSave: Boolean) { - context.resources.openRawResource(R.drawable.card_default).use { putArtworkToCatalog(artworkId, true, it.readBytes(), null, forceSave) } + private fun putResourceArtworkToCatalog(resourceId: Int, forceSave: Boolean) { + context.resources.openRawResource(R.drawable.card_default).use { putArtworkToCatalog(context.resources.getResourceEntryName(resourceId), true, it.readBytes(), null, forceSave) } } private fun putArtworkToCatalog(artworkId: String, isResource: Boolean, data: ByteArray, instant: Instant?, forceSave: Boolean = true) { val artworkInfo = ArtworkInfo( isResource, Util.bytesToHex(Util.calculateSHA256(data)), instant ) - artworks[artworkId] = artworkInfo + artworks[artworkId.toLowerCase()] = artworkInfo if (forceSave) { val sArtworks = Gson().toJson(artworks) artworksFile.bufferedWriter().use { it.write(sArtworks) } @@ -144,7 +162,8 @@ data class LocalStorage( } private fun getArtworkBitmap(artworkId: String): Bitmap? { - val info = artworks[artworkId] ?: return null + if( artworkId.isBlank() ) return null + val info = artworks[artworkId.toLowerCase()] ?: return null return if (info.isResource) { val resID = context.resources.getIdentifier(artworkId, "drawable", context.packageName) if (resID == 0) return null @@ -170,42 +189,42 @@ data class LocalStorage( val artworkId = when (card.cidDescription) { in "AA01 0000 0000 0000".."AA01 0000 0000 4999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_001) + context.resources.getResourceEntryName(R.drawable.card_ru006) } in "AA01 0000 0000 5000".."AA01 0000 0000 9999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_005) + context.resources.getResourceEntryName(R.drawable.card_ru007) } in "AE01 0000 0000 0000".."AE01 0000 0000 4999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_001) + context.resources.getResourceEntryName(R.drawable.card_ru006) } in "AE01 0000 0000 5000".."AE01 0000 0000 9999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_005) + context.resources.getResourceEntryName(R.drawable.card_ru007) } in "CB01 0000 0000 0000".."CB01 0000 0000 9999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_001) + context.resources.getResourceEntryName(R.drawable.card_ru006) } in "CB01 0000 0001 0000".."CB01 0000 0001 9999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_005) + context.resources.getResourceEntryName(R.drawable.card_ru007) } in "CB01 0000 0002 0000".."CB01 0000 0003 9999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_001) + context.resources.getResourceEntryName(R.drawable.card_ru006) } in "CB01 0000 0004 0000".."CB01 0000 0005 9999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_005) + context.resources.getResourceEntryName(R.drawable.card_ru007) } in "CB02 0000 0000 0000".."CB02 0000 0002 4999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_001) + context.resources.getResourceEntryName(R.drawable.card_ru006) } in "CB02 0000 0002 5000".."CB02 0000 0004 9999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_005) + context.resources.getResourceEntryName(R.drawable.card_ru007) } in "CB05 0000 1000 0000".."CB05 0000 1000 9999" -> { - context.resources.getResourceEntryName(R.drawable.card_btc_001) + context.resources.getResourceEntryName(R.drawable.card_ru006) } else -> { @@ -220,7 +239,7 @@ data class LocalStorage( fun applySubstitution(card: TangemCard) { val batchInfo = batches[card.batch] ?: return - val substitution = batchInfo.getDataSubstitution(card.batch) ?: return + val substitution = batchInfo.getDataSubstitution(card) ?: return substitution.applyToCard(card) } @@ -236,8 +255,8 @@ data class LocalStorage( val dataSubstitutionSignature: String? ) { - fun getDataSubstitution(batch: String): CardDataSubstitution? { - return if (CardDataSubstitution.verifySignature(batch, dataSubstitution, dataSubstitutionSignature)) { + fun getDataSubstitution(card: TangemCard): CardDataSubstitution? { + return if (CardDataSubstitution.verifySignature(card, dataSubstitution, dataSubstitutionSignature)) { Gson().fromJson(dataSubstitution, CardDataSubstitution::class.java) } else { null @@ -245,9 +264,12 @@ data class LocalStorage( } class CardDataSubstitution( - val tokenSymbol: String?, - val tokenDecimal: Int?, - val contractAddress: String? + @SerializedName("token_symbol") + private val tokenSymbol: String?, + @SerializedName("token_decimal") + private val tokenDecimal: Int?, + @SerializedName("token_contract_address") + private val contractAddress: String? ) { fun applyToCard(card: TangemCard) { if (card.tokenSymbol.isNullOrBlank()) card.tokenSymbol = tokenSymbol @@ -256,12 +278,11 @@ data class LocalStorage( } companion object { - private val substitutionPublicKey: ByteArray = byteArrayOf(0x00, 0x00) - fun verifySignature(batch: String, substitutionData: String?, substitutionSignature: String?): Boolean { + fun verifySignature(card: TangemCard, substitutionData: String?, substitutionSignature: String?): Boolean { if (substitutionData == null && substitutionSignature == null) return true if (substitutionData == null || substitutionSignature == null) return false - val dataToSign = batch.toByteArray(StandardCharsets.UTF_8) + substitutionData.toByteArray(StandardCharsets.UTF_8) - return CardCrypto.VerifySignature(substitutionPublicKey, dataToSign, Util.hexToBytes(substitutionSignature)) + val dataToSign = card.batch.toByteArray(StandardCharsets.UTF_8) + substitutionData.toByteArray(StandardCharsets.UTF_8) + return CardCrypto.VerifySignature(card.issuer.publicDataKey, dataToSign, Util.hexToBytes(substitutionSignature)) } } diff --git a/app/src/main/java/com/tangem/domain/wallet/TangemCard.java b/app/src/main/java/com/tangem/domain/wallet/TangemCard.java index e0aa034bbe..122c5fe571 100644 --- a/app/src/main/java/com/tangem/domain/wallet/TangemCard.java +++ b/app/src/main/java/com/tangem/domain/wallet/TangemCard.java @@ -1509,44 +1509,6 @@ public class TangemCard { return new String(hexChars); } - public int getCardImageResource() { - switch (getBatch()) { - case "0004": - case "0006": - case "0010": - return R.drawable.card_btc_001; - case "0005": - case "0007": - case "0011": - return R.drawable.card_btc_005; - case "0012": - return R.drawable.card_seed; - case "0013": - return R.drawable.card_btc_hk_s; - case "0014": - return R.drawable.card_btc_0014; - case "0015": - return R.drawable.card_btc_000; - case "0016": - return R.drawable.card_eth000; - case "0017": - return R.drawable.card_qlear200; - case "0019": - return R.drawable.card_cle100; - case "001A": - return R.drawable.card_btc_001a; - case "001B": - return R.drawable.card_btc_001b; - case "001C": - return R.drawable.card_btc_001c; - case "001D": - return R.drawable.card_eth_001d; - - default: - return R.drawable.card_default; - } - } - public enum EncryptionMode { None((byte) 0x0), Fast((byte) 0x1), Strong((byte) 0x2); diff --git a/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt b/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt index 8396d858f7..817e7300ad 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt +++ b/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt @@ -93,8 +93,6 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific lastTag = activity!!.intent.getParcelableExtra(MainActivity.EXTRA_LAST_DISCOVERED_TAG) localStorage = LocalStorage(context!!) - localStorage.applySubstitution(card!!) - } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -238,9 +236,10 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific if (!result.passed) return@setCardVerifyAndGetInfoListener - if (localStorage.checkBatchInfoChanged(result)) { + if (localStorage.checkBatchInfoChanged(card!!, result)) { Log.w(TAG, "Batch ${result.batch} info changed to '$result'") ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(card!!)) + localStorage.applySubstitution(card!!) updateViews() } if (result.artwork!=null && localStorage.checkNeedUpdateArtwork(result.artwork)) { @@ -323,6 +322,8 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific e.printStackTrace() } catch (e: NumberFormatException) { e.printStackTrace() + } catch (e: Exception) { + e.printStackTrace() } } diff --git a/app/src/main/res/drawable/card_btc_0014.png b/app/src/main/res/drawable/card_btc_0014.png deleted file mode 100644 index 0450aa659e..0000000000 Binary files a/app/src/main/res/drawable/card_btc_0014.png and /dev/null differ diff --git a/app/src/main/res/drawable/card_btc_001.png b/app/src/main/res/drawable/card_ru006.png similarity index 100% rename from app/src/main/res/drawable/card_btc_001.png rename to app/src/main/res/drawable/card_ru006.png diff --git a/app/src/main/res/drawable/card_btc_005.png b/app/src/main/res/drawable/card_ru007.png similarity index 100% rename from app/src/main/res/drawable/card_btc_005.png rename to app/src/main/res/drawable/card_ru007.png diff --git a/app/src/main/res/drawable/card_seed.png b/app/src/main/res/drawable/card_ru011.png similarity index 100% rename from app/src/main/res/drawable/card_seed.png rename to app/src/main/res/drawable/card_ru011.png diff --git a/app/src/main/res/drawable/card_btc_hk_s.png b/app/src/main/res/drawable/card_ru012.png similarity index 100% rename from app/src/main/res/drawable/card_btc_hk_s.png rename to app/src/main/res/drawable/card_ru012.png diff --git a/app/src/main/res/drawable/card_qlear200.png b/app/src/main/res/drawable/card_ru013.png similarity index 100% rename from app/src/main/res/drawable/card_qlear200.png rename to app/src/main/res/drawable/card_ru013.png diff --git a/app/src/main/res/drawable/card_btc_001a.png b/app/src/main/res/drawable/card_ru014.png similarity index 100% rename from app/src/main/res/drawable/card_btc_001a.png rename to app/src/main/res/drawable/card_ru014.png diff --git a/app/src/main/res/drawable/card_btc_001b.png b/app/src/main/res/drawable/card_ru015.png similarity index 100% rename from app/src/main/res/drawable/card_btc_001b.png rename to app/src/main/res/drawable/card_ru015.png diff --git a/app/src/main/res/drawable/card_cle100.png b/app/src/main/res/drawable/card_ru016.png similarity index 100% rename from app/src/main/res/drawable/card_cle100.png rename to app/src/main/res/drawable/card_ru016.png diff --git a/app/src/main/res/drawable/card_btc_000.png b/app/src/main/res/drawable/card_ru020.png similarity index 100% rename from app/src/main/res/drawable/card_btc_000.png rename to app/src/main/res/drawable/card_ru020.png diff --git a/app/src/main/res/drawable/card_eth000.png b/app/src/main/res/drawable/card_ru021.png similarity index 100% rename from app/src/main/res/drawable/card_eth000.png rename to app/src/main/res/drawable/card_ru021.png diff --git a/app/src/main/res/drawable/card_eth_001d.png b/app/src/main/res/drawable/card_ru022.png similarity index 100% rename from app/src/main/res/drawable/card_eth_001d.png rename to app/src/main/res/drawable/card_ru022.png diff --git a/app/src/main/res/drawable/card_btc_001c.png b/app/src/main/res/drawable/card_ru023.png similarity index 100% rename from app/src/main/res/drawable/card_btc_001c.png rename to app/src/main/res/drawable/card_ru023.png