Updated on 2026-08-14
This commit is contained in:
parent
8f77a7ab99
commit
cd6da4efe7
8 changed files with 56 additions and 46 deletions
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue