Updated on 2026-08-14

This commit is contained in:
Tangem 2018-09-28 10:23:03 +03:00
parent 8f77a7ab99
commit cd6da4efe7
8 changed files with 56 additions and 46 deletions

View file

@ -25,9 +25,9 @@ import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Random;
@ -297,14 +297,14 @@ public class ServerApiHelper {
private ArtworkListener artworkListener;
public interface ArtworkListener {
void onArtwork(String artworkId, InputStream inputStream, Instant updateDate);
void onArtwork(String artworkId, InputStream inputStream, Date updateDate);
}
public void setArtworkListener(ArtworkListener listener) {
artworkListener = listener;
}
public void requestArtwork(String artworkId, Instant updateDate, TangemCard card) {
public void requestArtwork(String artworkId, Date updateDate, TangemCard card) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
@ -548,9 +548,9 @@ public class ServerApiHelper {
if (response.code() == 200) {
String stringResponse;
try {
stringResponse = response.body().string();
stringResponse = response.body() != null ? response.body().string() : null;
lastVersionListener.onLastVersion(stringResponse);
} catch (IOException e) {
} catch (Exception e) {
e.printStackTrace();
}
}

View file

@ -1,11 +1,6 @@
package com.tangem.data.network.model
import android.os.Build
import java.text.SimpleDateFormat
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.util.*
class CardVerifyAndGetInfo {
@ -38,16 +33,12 @@ class CardVerifyAndGetInfo {
var hash: String = "",
var date: String = ""
) {
fun getUpdateDate(): Instant? {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return LocalDateTime.parse(date, DateTimeFormatter.ISO_LOCAL_DATE_TIME).toInstant(ZoneOffset.UTC)
} else {
return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US).parse(date).toInstant()
}
fun getUpdateDate(): Date? {
return try {
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US).parse(date)
} catch (e: Exception) {
e.printStackTrace()
return null
null
}
}

View file

@ -38,6 +38,7 @@ import javax.crypto.spec.SecretKeySpec;
public class CardCrypto {
public static PublicKey LoadPublicKey(byte[] publicKeyArray) throws Exception {
if( publicKeyArray==null ) throw new Exception("Public key not specified!");
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
KeyFactory factory = KeyFactory.getInstance("EC", "SC");

View file

@ -498,19 +498,19 @@ public class CardProtocol {
try {
if (mCard.getFirmwareVersion().compareTo("1.05") < 0) {
mCard.setIssuer(Issuer.FindIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), readResult.getTLV(TLV.Tag.TAG_Issuer_Transaction_PublicKey).Value));
mCard.setIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), readResult.getTLV(TLV.Tag.TAG_Issuer_Transaction_PublicKey).Value);
} else {
mCard.setIssuer(Issuer.FindIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), readResult.getTLV(TLV.Tag.TAG_Issuer_Data_PublicKey).Value));
mCard.setIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), readResult.getTLV(TLV.Tag.TAG_Issuer_Data_PublicKey).Value);
}
} catch (Exception e) {
e.printStackTrace();
Log.e(logTag, "Cannot get issuer, try a version for older cards");
try {
mCard.setIssuer(Issuer.FindIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), readResult.getTLV(TLV.Tag.TAG_Issuer_Transaction_PublicKey).Value));
mCard.setIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), readResult.getTLV(TLV.Tag.TAG_Issuer_Transaction_PublicKey).Value);
} catch (Exception ee) {
ee.printStackTrace();
Log.e(logTag, "Cannot get issuer");
mCard.setIssuer(Issuer.Unknown());
mCard.setIssuer(Issuer.Unknown().getID(), null);
}
}

View file

@ -17,7 +17,7 @@ import com.tangem.wallet.R
import java.io.InputStream
import java.lang.Exception
import java.nio.charset.StandardCharsets
import java.time.Instant
import java.util.*
data class LocalStorage(
val context: Context
@ -119,7 +119,7 @@ data class LocalStorage(
if (localArtwork.hash == artwork.hash) return false
return localArtwork.updateDate == null || localArtwork.updateDate < artwork.getUpdateDate()
return localArtwork.updateDate == null || localArtwork.updateDate.before(artwork.getUpdateDate())
}
fun checkBatchInfoChanged(card: TangemCard, result: CardVerifyAndGetInfo.Response.Item): Boolean {
@ -141,7 +141,7 @@ data class LocalStorage(
return false
}
fun updateArtwork(artworkId: String, inputStream: InputStream, updateDate: Instant) {
fun updateArtwork(artworkId: String, inputStream: InputStream, updateDate: Date) {
val data = inputStream.readBytes()
saveArtworkBitmapToFile(artworkId.toLowerCase(), data)
putArtworkToCatalog(artworkId, false, data, updateDate, true)
@ -164,9 +164,9 @@ data class LocalStorage(
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) {
private fun putArtworkToCatalog(artworkId: String, isResource: Boolean, data: ByteArray, updateDate: Date?, forceSave: Boolean = true) {
val artworkInfo = ArtworkInfo(
isResource, Util.bytesToHex(Util.calculateSHA256(data)), instant
isResource, Util.bytesToHex(Util.calculateSHA256(data)), updateDate
)
artworks[artworkId.toLowerCase()] = artworkInfo
if (forceSave) {
@ -258,7 +258,7 @@ data class LocalStorage(
private data class ArtworkInfo(
val isResource: Boolean,
val hash: String,
val updateDate: Instant?
val updateDate: Date?
)
private data class BatchInfo(
@ -294,7 +294,12 @@ data class LocalStorage(
if (substitutionData == null && substitutionSignature == null) return true
if (substitutionData == null || substitutionSignature == null) return false
val dataToSign = card.batch.toByteArray(StandardCharsets.UTF_8) + substitutionData.toByteArray(StandardCharsets.UTF_8)
return CardCrypto.VerifySignature(card.issuer.publicDataKey, dataToSign, Util.hexToBytes(substitutionSignature))
return try {
CardCrypto.VerifySignature(card.issuerPublicDataKey, dataToSign, Util.hexToBytes(substitutionSignature))
} catch (E: Exception) {
E.printStackTrace()
false
}
}
}

View file

@ -579,9 +579,27 @@ public class TangemCard {
}
private Issuer issuer = Issuer.Unknown();
private byte[] issuerPublicDataKey = null;
public void setIssuer(Issuer issuer) {
this.issuer = issuer;
// public void setIssuer(Issuer issuer) {
// this.issuer = issuer;
// }
public void setIssuer(String issuerID, byte[] issuerPublicDataKey) {
this.issuerPublicDataKey = issuerPublicDataKey;
this.issuer = Issuer.FindIssuer(issuerID, issuerPublicDataKey);
}
public Issuer getIssuer() {
return issuer;
}
public byte[] getIssuerPublicDataKey() {
return issuerPublicDataKey;
}
public String getIssuerDescription() {
return issuer.getOfficialName();
}
String contractAddress = "";
@ -618,13 +636,6 @@ public class TangemCard {
return tokensDecimal;
}
public Issuer getIssuer() {
return issuer;
}
public String getIssuerDescription() {
return issuer.getOfficialName();
}
private byte[] issuerData;
private byte[] issuerDataSignature;
@ -1274,6 +1285,7 @@ public class TangemCard {
if (manufacturer != null) B.putString("Manufacturer", manufacturer.name());
if (encryptionMode != null) B.putString("EncryptionMode", encryptionMode.name());
if (issuer != null) B.putString("Issuer", issuer.getID());
if (issuerPublicDataKey != null) B.putByteArray("IssuerPublicDataKey", issuerPublicDataKey);
if (firmwareVersion != null) B.putString("FirmwareVersion", firmwareVersion);
if (balanceEqual != null) B.putBoolean("isBalanceEqual", balanceEqual);
if (batch != null) B.putString("Batch", batch);
@ -1411,6 +1423,8 @@ public class TangemCard {
if (B.containsKey("FailedBalance"))
failedBalanceRequestCounter = new AtomicInteger(B.getInt("FailedBalance"));
if (B.containsKey("Issuer")) issuer = Issuer.FindIssuer(B.getString("Issuer"));
if (B.containsKey("IssuerPublicDataKey")) issuerPublicDataKey = B.getByteArray("IssuerPublicDataKey");
if (B.containsKey("FirmwareVersion")) firmwareVersion = B.getString("FirmwareVersion");
if (B.containsKey("Batch")) batch = B.getString("Batch");

View file

@ -160,13 +160,12 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
val apiHelper = ServerApiHelper()
apiHelper.setLastVersionListener { response ->
try {
val responseVersionName=response.trim(' ','\n','\r','\t')
val responseBuildVersion=responseVersionName.split('.').last()
val appBuildVersion=BuildConfig.VERSION_NAME.split('.').last()
if (responseBuildVersion.toInt()>appBuildVersion.toInt()) Toast.makeText(this, "There is a new application version: $responseVersionName", Toast.LENGTH_LONG).show()
}
catch (E: Exception)
{
if (response.isNullOrEmpty()) return@setLastVersionListener
val responseVersionName = response.trim(' ', '\n', '\r', '\t')
val responseBuildVersion = responseVersionName.split('.').last()
val appBuildVersion = BuildConfig.VERSION_NAME.split('.').last()
if (responseBuildVersion.toInt() > appBuildVersion.toInt()) Toast.makeText(this, "There is a new application version: $responseVersionName", Toast.LENGTH_LONG).show()
} catch (E: Exception) {
E.printStackTrace()
}
}

View file

@ -87,7 +87,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
sp = PreferenceManager.getDefaultSharedPreferences(activity)
card = TangemCard(activity!!.intent.getStringExtra(TangemCard.EXTRA_CARD))
card = TangemCard(activity!!.intent.getStringExtra(TangemCard.EXTRA_UID))
card!!.loadFromBundle(activity!!.intent.extras.getBundle(TangemCard.EXTRA_CARD))
lastTag = activity!!.intent.getParcelableExtra(MainActivity.EXTRA_LAST_DISCOVERED_TAG)