Updated on 2026-08-14
|
|
@ -68,8 +68,7 @@ public class LogFileProvider extends ContentProvider {
|
|||
// Create & return a ParcelFileDescriptor pointing to the file
|
||||
// Note: I don't care what mode they ask for - they're only getting
|
||||
// read only
|
||||
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(
|
||||
fileLocation), ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(fileLocation), ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
return pfd;
|
||||
|
||||
// Otherwise unrecognised Uri
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.data;
|
|||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import android.security.keystore.KeyGenParameterSpec;
|
|||
import android.security.keystore.KeyPermanentlyInvalidatedException;
|
||||
import android.security.keystore.KeyProperties;
|
||||
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.presentation.activity.PinRequestActivity;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
|||
|
|
@ -4,30 +4,22 @@ import android.annotation.SuppressLint;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.internal.LinkedTreeMap;
|
||||
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
|
||||
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
//import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Call;
|
||||
|
|
@ -36,9 +28,7 @@ import retrofit2.converter.gson.GsonConverterFactory;
|
|||
import retrofit2.http.Body;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.Multipart;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Part;
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import android.annotation.SuppressLint;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
|
@ -12,7 +11,7 @@ import com.google.gson.annotations.SerializedName;
|
|||
import com.google.gson.internal.LinkedTreeMap;
|
||||
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
|
||||
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@ import android.annotation.SuppressLint;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import org.spongycastle.util.encoders.Base64;
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import android.util.Log;
|
|||
import com.tangem.App;
|
||||
import com.tangem.data.network.model.CardVerifyAndGetInfo;
|
||||
import com.tangem.data.network.model.RateInfoResponse;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package com.tangem.data.network;
|
|||
import android.util.Log;
|
||||
|
||||
import com.tangem.App;
|
||||
import com.tangem.domain.wallet.Blockchain;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.tangemcard.data.Blockchain;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.domain.wallet.bch.BitcoinCashNode;
|
||||
import com.tangem.domain.wallet.btc.BitcoinNode;
|
||||
import com.tangem.domain.wallet.btc.BitcoinNodeTestNet;
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
package com.tangem.data.nfc;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
|
||||
public class PurgeTask extends Thread {
|
||||
public static final String TAG = PurgeTask.class.getSimpleName();
|
||||
|
||||
private String txOutAddress;
|
||||
private Context mContext;
|
||||
private TangemCard mCard;
|
||||
private NfcManager mNfcManager;
|
||||
private IsoDep mIsoDep;
|
||||
private CardProtocol.Notifications mNotifications;
|
||||
private boolean isCancelled = false;
|
||||
|
||||
public PurgeTask(Context context, TangemCard card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
mCard = card;
|
||||
mContext = context;
|
||||
mNfcManager = nfcManager;
|
||||
mIsoDep = isoDep;
|
||||
mNotifications = notifications;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mIsoDep == null) {
|
||||
return;
|
||||
}
|
||||
CardProtocol protocol = new CardProtocol(mContext, mIsoDep, mCard, mNotifications);
|
||||
|
||||
mNotifications.onReadStart(protocol);
|
||||
try {
|
||||
|
||||
// for Samsung's bugs - Workaround for the Samsung Galaxy S5 (since the first connection always hangs on transceive).
|
||||
int timeout = mIsoDep.getTimeout();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.close();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.setTimeout(timeout);
|
||||
try {
|
||||
mNotifications.onReadProgress(protocol, 5);
|
||||
|
||||
Log.i(TAG, "[-- Start purge --]");
|
||||
|
||||
if (isCancelled) return;
|
||||
|
||||
if (mCard.getPauseBeforePIN2() > 0) {
|
||||
mNotifications.onReadWait(mCard.getPauseBeforePIN2());
|
||||
}
|
||||
|
||||
// try {
|
||||
protocol.run_PurgeWallet(PINStorage.getPIN2());
|
||||
// } finally {
|
||||
// mNotifications.onReadWait(0);
|
||||
// }
|
||||
|
||||
mNotifications.onReadProgress(protocol, 50);
|
||||
|
||||
protocol.run_Read();
|
||||
|
||||
mNotifications.onReadProgress(protocol, 100);
|
||||
|
||||
if (isCancelled)
|
||||
return;
|
||||
|
||||
} finally {
|
||||
mNfcManager.ignoreTag(mIsoDep.getTag());
|
||||
mNotifications.onReadWait(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
protocol.setError(e);
|
||||
|
||||
} finally {
|
||||
Log.i(TAG, "[-- Finish purge --]");
|
||||
mNotifications.onReadFinish(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel(Boolean AllowInterrupt) {
|
||||
try {
|
||||
if (isAlive()) {
|
||||
isCancelled = true;
|
||||
join(500);
|
||||
}
|
||||
if (isAlive() && AllowInterrupt) {
|
||||
interrupt();
|
||||
mNotifications.onReadCancel();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
package com.tangem.data.nfc;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.util.Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ReadCardInfoTask extends Thread {
|
||||
public static final String TAG = ReadCardInfoTask.class.getSimpleName();
|
||||
|
||||
private IsoDep mIsoDep;
|
||||
private CardProtocol.Notifications mNotifications;
|
||||
private boolean isCancelled = false;
|
||||
private Context mContext;
|
||||
private NfcManager mNfcManager;
|
||||
|
||||
// this fields are static to optimize process when need enter pin and scan card again
|
||||
private static ArrayList<String> lastRead_UnsuccessfullPINs = new ArrayList<>();
|
||||
private static TangemCard.EncryptionMode lastRead_Encryption = null;
|
||||
private static String lastRead_UID;
|
||||
|
||||
public static void resetLastReadInfo() {
|
||||
lastRead_UID="";
|
||||
lastRead_Encryption=null;
|
||||
lastRead_UnsuccessfullPINs.clear();
|
||||
}
|
||||
|
||||
public ReadCardInfoTask(Context context, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
mContext = context;
|
||||
mIsoDep = isoDep;
|
||||
mNotifications = notifications;
|
||||
mNfcManager = nfcManager;
|
||||
// ReadCardInfoTask.lastRead_UID = lastRead_UID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mIsoDep == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// for Samsung's bugs -
|
||||
// Workaround for the Samsung Galaxy S5 (since the
|
||||
// first connection always hangs on transceive).
|
||||
int timeout = mIsoDep.getTimeout();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.close();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.setTimeout(timeout);
|
||||
try {
|
||||
CardProtocol protocol = new CardProtocol(mContext, mIsoDep, mNotifications);
|
||||
mNotifications.onReadStart(protocol);
|
||||
try {
|
||||
mNotifications.onReadProgress(protocol, 5);
|
||||
|
||||
byte[] UID = mIsoDep.getTag().getId();
|
||||
String sUID = Util.byteArrayToHexString(UID);
|
||||
if (!lastRead_UID.equals(sUID)) {
|
||||
resetLastReadInfo();
|
||||
}
|
||||
|
||||
Log.i(TAG, "[-- Start read card info --]");
|
||||
|
||||
if (isCancelled) return;
|
||||
|
||||
protocol.setPIN(PINStorage.getDefaultPIN());
|
||||
protocol.clearReadResult();
|
||||
|
||||
if (lastRead_Encryption == null) {
|
||||
Log.i(TAG, "Try get supported encryption mode");
|
||||
protocol.run_GetSupportedEncryption();
|
||||
} else {
|
||||
Log.i(TAG, "Use already defined encryption mode: " + lastRead_Encryption.name());
|
||||
protocol.getCard().encryptionMode = lastRead_Encryption;
|
||||
}
|
||||
|
||||
if (protocol.haveReadResult()) {
|
||||
//already have read result (obtained while get supported encryption), only read issuer data and define offline balance
|
||||
protocol.parseReadResult();
|
||||
protocol.run_ReadWriteIssuerData();
|
||||
mNotifications.onReadProgress(protocol, 60);
|
||||
PINStorage.setLastUsedPIN(protocol.getCard().getPIN());
|
||||
} else {
|
||||
//don't have read result - may be don't get supported encryption on this try, need encryption or need another PIN
|
||||
if (lastRead_Encryption == null) {
|
||||
// we try get supported encryption on this time
|
||||
lastRead_Encryption = protocol.getCard().encryptionMode;
|
||||
if (protocol.getCard().encryptionMode == TangemCard.EncryptionMode.None) {
|
||||
// default pin not accepted
|
||||
lastRead_UnsuccessfullPINs.add(PINStorage.getDefaultPIN());
|
||||
}
|
||||
}
|
||||
|
||||
boolean pinFound = false;
|
||||
for (String PIN : PINStorage.getPINs()) {
|
||||
Log.e(TAG, "PIN: " + PIN);
|
||||
|
||||
boolean skipPin = false;
|
||||
for (int i = 0; i < lastRead_UnsuccessfullPINs.size(); i++) {
|
||||
if (lastRead_UnsuccessfullPINs.get(i).equals(PIN)) {
|
||||
skipPin = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skipPin) {
|
||||
Log.e(TAG, "Skip PIN - already checked before");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
protocol.setPIN(PIN);
|
||||
if (protocol.getCard().encryptionMode != TangemCard.EncryptionMode.None) {
|
||||
protocol.CreateProtocolKey();
|
||||
}
|
||||
protocol.run_Read();
|
||||
mNotifications.onReadProgress(protocol, 60);
|
||||
PINStorage.setLastUsedPIN(PIN);
|
||||
pinFound = true;
|
||||
protocol.getCard().setPIN(PIN);
|
||||
break;
|
||||
} catch (CardProtocol.TangemException_InvalidPIN e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
lastRead_UnsuccessfullPINs.add(PIN);
|
||||
}
|
||||
}
|
||||
if (!pinFound) {
|
||||
throw new CardProtocol.TangemException_InvalidPIN("No valid PIN found!");
|
||||
}
|
||||
}
|
||||
|
||||
protocol.run_CheckPIN2isDefault();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
protocol.setError(e);
|
||||
|
||||
} finally {
|
||||
Log.i(TAG, "[-- Finish read card info --]");
|
||||
mNotifications.onReadFinish(protocol);
|
||||
}
|
||||
} finally {
|
||||
mNfcManager.ignoreTag(mIsoDep.getTag());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
mNfcManager.notifyReadResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel(Boolean AllowInterrupt) {
|
||||
try {
|
||||
if (isAlive()) {
|
||||
isCancelled = true;
|
||||
join(500);
|
||||
}
|
||||
if (isAlive() && AllowInterrupt) {
|
||||
interrupt();
|
||||
mNotifications.onReadCancel();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
package com.tangem.data.nfc;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.Firmwares;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by dvol on 04.02.2018.
|
||||
*/
|
||||
|
||||
public class VerifyCardTask extends Thread {
|
||||
public static final String TAG = VerifyCardTask.class.getSimpleName();
|
||||
|
||||
private IsoDep mIsoDep;
|
||||
private CardProtocol.Notifications mNotifications;
|
||||
private boolean isCancelled = false;
|
||||
private Context mContext;
|
||||
private TangemCard mCard;
|
||||
private NfcManager mNfcManager;
|
||||
|
||||
public VerifyCardTask(Context context, TangemCard card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
mCard = card;
|
||||
mContext = context;
|
||||
mIsoDep = isoDep;
|
||||
mNotifications = notifications;
|
||||
mNfcManager = nfcManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mIsoDep == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// for Samsung's bugs -
|
||||
// Workaround for the Samsung Galaxy S5 (since the
|
||||
// first connection always hangs on transceive).
|
||||
int timeout = mIsoDep.getTimeout();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.close();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.setTimeout(timeout);
|
||||
try {
|
||||
CardProtocol protocol = new CardProtocol(mContext, mIsoDep, mCard, mNotifications);
|
||||
mNotifications.onReadStart(protocol);
|
||||
try {
|
||||
mNotifications.onReadProgress(protocol, 5);
|
||||
|
||||
Log.i(TAG, "[-- Start verify card --]");
|
||||
|
||||
if (isCancelled) return;
|
||||
|
||||
String PIN = mCard.getPIN();
|
||||
protocol.setPIN(PIN);
|
||||
protocol.run_Read(false);
|
||||
PINStorage.setLastUsedPIN(PIN);
|
||||
mNotifications.onReadProgress(protocol, 20);
|
||||
if (isCancelled) return;
|
||||
protocol.run_VerifyCard();
|
||||
mNotifications.onReadProgress(protocol, 50);
|
||||
Log.i(TAG, "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName());
|
||||
if (isCancelled) return;
|
||||
if (protocol.getCard().getStatus() == TangemCard.Status.Loaded) {
|
||||
protocol.run_CheckWalletWithSignatureVerify();
|
||||
mNotifications.onReadProgress(protocol, 80);
|
||||
}
|
||||
if (isCancelled) return;
|
||||
Firmwares.VerifyCodeRecord record=Firmwares.selectRandomVerifyCodeBlock(mCard.getFirmwareVersion());
|
||||
if (isCancelled) return;
|
||||
if( record!=null ) {
|
||||
byte[] returnedDigest = protocol.run_VerifyCode(record.hashAlg, record.blockIndex, record.blockCount, record.challenge);
|
||||
mCard.setCodeConfirmed(Arrays.equals(returnedDigest, record.digest));
|
||||
}else{
|
||||
mCard.setCodeConfirmed(null);
|
||||
}
|
||||
mNotifications.onReadProgress(protocol, 90);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
protocol.setError(e);
|
||||
|
||||
} finally {
|
||||
Log.i(TAG, "[-- Finish verify card --]");
|
||||
mNotifications.onReadFinish(protocol);
|
||||
}
|
||||
} finally {
|
||||
mNfcManager.ignoreTag(mIsoDep.getTag());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel(Boolean AllowInterrupt) {
|
||||
try {
|
||||
if (isAlive()) {
|
||||
isCancelled = true;
|
||||
join(500);
|
||||
}
|
||||
if (isAlive() && AllowInterrupt) {
|
||||
interrupt();
|
||||
mNotifications.onReadCancel();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import android.app.Activity
|
|||
import android.nfc.Tag
|
||||
import android.os.Bundle
|
||||
import com.tangem.domain.wallet.CoinData
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.presentation.activity.EmptyWalletActivity
|
||||
import com.tangem.presentation.activity.LoadedWalletActivity
|
||||
import com.tangem.presentation.activity.MainActivity
|
||||
|
|
|
|||
|
|
@ -11,21 +11,14 @@ import com.tangem.domain.wallet.btc.BitcoinOutputStream;
|
|||
import com.tangem.domain.wallet.btc.BtcData;
|
||||
import com.tangem.util.CryptoUtil;
|
||||
import com.tangem.util.FormatUtil;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "TryWithIdenticalCatches", "unused"})
|
||||
public final class BTCUtils {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.domain.wallet;
|
||||
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
public class BalanceValidator {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package com.tangem.domain.wallet;
|
|||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import com.tangem.tangemcard.data.Blockchain;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public abstract class CoinData {
|
||||
|
|
@ -12,6 +12,24 @@ public abstract class CoinData {
|
|||
public CoinData() {
|
||||
}
|
||||
|
||||
private String wallet;
|
||||
|
||||
public void setWallet(String wallet) {
|
||||
this.wallet = wallet;
|
||||
}
|
||||
|
||||
public String getWallet() {
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public String getShortWalletString() {
|
||||
if (wallet.length() < 22) {
|
||||
return wallet;
|
||||
} else {
|
||||
return wallet.substring(0, 10) + "......" + wallet.substring(wallet.length() - 10, wallet.length());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBalanceReceived() {
|
||||
return balanceReceived;
|
||||
}
|
||||
|
|
@ -23,6 +41,8 @@ public abstract class CoinData {
|
|||
}
|
||||
|
||||
public void loadFromBundle(Bundle B) {
|
||||
wallet = B.getString("Wallet");
|
||||
|
||||
if (B.containsKey("balanceReceived")) setBalanceReceived(B.getBoolean("balanceReceived"));
|
||||
|
||||
validationNodeDescription = B.getString("validationNodeDescription");
|
||||
|
|
@ -40,6 +60,8 @@ public abstract class CoinData {
|
|||
|
||||
public void saveToBundle(Bundle B) {
|
||||
try {
|
||||
B.putString("Wallet", wallet);
|
||||
|
||||
if (balanceEqual != null) B.putBoolean("isBalanceEqual", balanceEqual);
|
||||
|
||||
if (failedBalanceRequestCounter != null)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.domain.wallet;
|
|||
import android.net.Uri;
|
||||
import android.text.InputFilter;
|
||||
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.domain.wallet.btc.BtcEngine
|
|||
import com.tangem.domain.wallet.eth.EthEngine
|
||||
import com.tangem.domain.wallet.token.TokenEngine
|
||||
import com.tangem.domain.wallet.bch.BtcCashEngine
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
|
||||
/**
|
||||
* Factory for create specific engine
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import android.content.Intent;
|
|||
import android.os.Bundle;
|
||||
|
||||
import com.tangem.Constant;
|
||||
import com.tangem.tangemcard.data.Blockchain;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
|
||||
|
||||
public class TangemContext {
|
||||
|
|
@ -121,4 +123,17 @@ public class TangemContext {
|
|||
if (context != null) return getContext().getResources().getString(stringId);
|
||||
return "context.resources.string[" + stringId + "]";
|
||||
}
|
||||
|
||||
public void setDenomination(byte[] denomination) {
|
||||
try {
|
||||
CoinEngine engine= CoinEngineFactory.INSTANCE.create(getBlockchain());
|
||||
CoinEngine.InternalAmount internalAmount=engine.convertToInternalAmount(denomination);
|
||||
CoinEngine.Amount amount=engine.convertToAmount(internalAmount);
|
||||
card.setDenomination(denomination,amount.toString());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
card.setDenomination(denomination,"N/A");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@ package com.tangem.domain.wallet.bch;
|
|||
import android.net.Uri;
|
||||
import android.text.InputFilter;
|
||||
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.TLV;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
import com.tangem.domain.wallet.Blockchain;
|
||||
import com.tangem.tangemcard.data.Blockchain;
|
||||
import com.tangem.domain.wallet.CoinEngineFactory;
|
||||
import com.tangem.domain.wallet.btc.BtcData;
|
||||
import com.tangem.domain.wallet.CoinData;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.domain.wallet.TangemContext;
|
||||
import com.tangem.domain.wallet.Transaction;
|
||||
import com.tangem.domain.wallet.UnspentOutputInfo;
|
||||
|
|
@ -20,7 +20,7 @@ import com.tangem.domain.wallet.BTCUtils;
|
|||
import com.tangem.util.CryptoUtil;
|
||||
import com.tangem.util.DecimalDigitsInputFilter;
|
||||
import com.tangem.util.DerEncodingUtil;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ package com.tangem.domain.wallet.btc;
|
|||
import android.net.Uri;
|
||||
import android.text.InputFilter;
|
||||
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.TLV;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
import com.tangem.domain.wallet.Base58;
|
||||
import com.tangem.domain.wallet.Blockchain;
|
||||
import com.tangem.tangemcard.data.Blockchain;
|
||||
import com.tangem.domain.wallet.CoinData;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.domain.wallet.TangemContext;
|
||||
import com.tangem.domain.wallet.Transaction;
|
||||
import com.tangem.domain.wallet.UnspentOutputInfo;
|
||||
|
|
@ -19,7 +19,7 @@ import com.tangem.domain.wallet.BTCUtils;
|
|||
import com.tangem.util.CryptoUtil;
|
||||
import com.tangem.util.DecimalDigitsInputFilter;
|
||||
import com.tangem.util.DerEncodingUtil;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
|
|
|||
|
|
@ -4,18 +4,18 @@ import android.net.Uri;
|
|||
import android.text.InputFilter;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.TLV;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
import com.tangem.domain.wallet.Blockchain;
|
||||
import com.tangem.tangemcard.data.Blockchain;
|
||||
import com.tangem.domain.wallet.CoinData;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
import com.tangem.domain.wallet.ECDSASignatureETH;
|
||||
import com.tangem.domain.wallet.EthTransaction;
|
||||
import com.tangem.domain.wallet.Issuer;
|
||||
import com.tangem.tangemcard.data.Issuer;
|
||||
import com.tangem.domain.wallet.Keccak256;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.domain.wallet.TangemContext;
|
||||
import com.tangem.domain.wallet.BTCUtils;
|
||||
import com.tangem.util.CryptoUtil;
|
||||
|
|
|
|||
|
|
@ -5,17 +5,17 @@ import android.text.InputFilter;
|
|||
import android.util.Log;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.TLV;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
import com.tangem.domain.wallet.CoinData;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
import com.tangem.domain.wallet.ECDSASignatureETH;
|
||||
import com.tangem.domain.wallet.EthTransaction;
|
||||
import com.tangem.domain.wallet.Issuer;
|
||||
import com.tangem.tangemcard.data.Issuer;
|
||||
import com.tangem.domain.wallet.Keccak256;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.domain.wallet.TangemContext;
|
||||
import com.tangem.domain.wallet.BTCUtils;
|
||||
import com.tangem.util.CryptoUtil;
|
||||
|
|
|
|||
|
|
@ -18,13 +18,15 @@ import com.tangem.data.network.ServerApiCommon
|
|||
import com.tangem.data.network.ServerApiElectrum
|
||||
import com.tangem.data.network.ServerApiInfura
|
||||
import com.tangem.data.network.model.InfuraResponse
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.domain.wallet.*
|
||||
import com.tangem.domain.wallet.btc.BtcData
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import com.tangem.util.*
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_confirm_payment.*
|
||||
import org.json.JSONException
|
||||
import java.io.IOException
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
|
|
|
|||
|
|
@ -12,14 +12,13 @@ import android.support.v7.app.AppCompatActivity
|
|||
import android.view.View
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.nfc.CreateNewWalletTask
|
||||
import com.tangem.domain.cardReader.CardProtocol
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.tangemcard.tasks.CreateNewWalletTask
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.util.Util
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_create_new_wallet.*
|
||||
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@ import android.support.v7.app.AppCompatActivity
|
|||
import android.text.Html
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.nfc.VerifyCardTask
|
||||
import com.tangem.domain.cardReader.CardProtocol
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.tangemcard.tasks.VerifyCardTask
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.util.Util
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_empty_wallet.*
|
||||
|
||||
|
|
|
|||
|
|
@ -26,18 +26,19 @@ import android.widget.Toast
|
|||
import com.scottyab.rootbeer.RootBeer
|
||||
import com.tangem.App
|
||||
import com.tangem.data.Logger
|
||||
import com.tangem.data.db.PINStorage
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.data.network.ServerApiCommon
|
||||
import com.tangem.data.nfc.DeviceNFCAntennaLocation
|
||||
import com.tangem.data.nfc.ReadCardInfoTask
|
||||
import com.tangem.tangemcard.data.DeviceNFCAntennaLocation
|
||||
import com.tangem.tangemcard.tasks.ReadCardInfoTask
|
||||
import com.tangem.di.Navigator
|
||||
import com.tangem.domain.cardReader.CardProtocol
|
||||
import com.tangem.domain.cardReader.Firmwares
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.*
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.data.Firmwares
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
||||
import com.tangem.presentation.dialog.RootFoundDialog
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.tangemcard.data.Issuer
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.util.CommonUtil
|
||||
import com.tangem.util.PhoneUtility
|
||||
import com.tangem.wallet.BuildConfig
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ import android.util.Log
|
|||
import android.view.View
|
||||
import android.widget.Button
|
||||
import com.tangem.data.fingerprint.StartFingerprintReaderTask
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.data.fingerprint.FingerprintHelper
|
||||
import com.tangem.data.db.PINStorage
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_pin_request.*
|
||||
import kotlinx.android.synthetic.main.layout_pin_buttons.*
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import android.widget.Button
|
|||
import android.widget.Toast
|
||||
import com.tangem.data.fingerprint.ConfirmWithFingerprintTask
|
||||
import com.tangem.data.fingerprint.FingerprintHelper
|
||||
import com.tangem.data.db.PINStorage
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_pin_save.*
|
||||
import kotlinx.android.synthetic.main.layout_pin_buttons.*
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@ import android.support.v7.app.AppCompatActivity
|
|||
import android.view.View
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.nfc.SwapPINTask
|
||||
import com.tangem.domain.cardReader.CardProtocol
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.tangemcard.tasks.SwapPINTask
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.util.Util
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_pin_swap.*
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import android.os.Bundle
|
|||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.View
|
||||
import com.tangem.data.network.CryptonitOtherApi
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.Blockchain
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
import com.tangem.domain.wallet.CoinEngineFactory
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.wallet.R
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ import android.view.inputmethod.EditorInfo
|
|||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.network.Cryptonit
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.Blockchain
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
import com.tangem.domain.wallet.CoinEngineFactory
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.util.DecimalDigitsInputFilter
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ import android.view.inputmethod.EditorInfo
|
|||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.network.Kraken
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.Blockchain
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
import com.tangem.domain.wallet.CoinEngineFactory
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.wallet.R
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import android.text.Html
|
|||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.Blockchain
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
import com.tangem.domain.wallet.CoinEngineFactory
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.wallet.R
|
||||
|
|
|
|||
|
|
@ -12,14 +12,13 @@ import android.os.Bundle
|
|||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.nfc.PurgeTask
|
||||
import com.tangem.domain.cardReader.CardProtocol
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.tangemcard.tasks.PurgeTask
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.util.Util
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_purge.*
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ import com.tangem.data.network.ElectrumRequest
|
|||
import com.tangem.data.network.ServerApiElectrum
|
||||
import com.tangem.data.network.ServerApiInfura
|
||||
import com.tangem.data.network.model.InfuraResponse
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.domain.wallet.*
|
||||
import com.tangem.domain.wallet.eth.EthData
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.util.UtilHelper
|
||||
import com.tangem.wallet.R
|
||||
import java.io.IOException
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@ import android.view.KeyEvent
|
|||
import android.view.View
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.nfc.SignPaymentTask
|
||||
import com.tangem.domain.cardReader.CardProtocol
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.tangemcard.tasks.SignPaymentTask
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.domain.wallet.CoinEngine
|
||||
import com.tangem.domain.wallet.TangemContext
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.util.Util
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_sign_payment.*
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.App
|
|||
import com.tangem.Constant
|
||||
import com.tangem.di.Navigator
|
||||
import com.tangem.domain.wallet.CoinData
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.presentation.fragment.VerifyCard
|
||||
import com.tangem.wallet.R
|
||||
import javax.inject.Inject
|
||||
|
|
|
|||
|
|
@ -19,17 +19,17 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.db.LocalStorage
|
||||
import com.tangem.data.db.PINStorage
|
||||
import com.tangem.tangemcard.data.LocalStorage
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.data.network.ElectrumRequest
|
||||
import com.tangem.data.network.ServerApiCommon
|
||||
import com.tangem.data.network.ServerApiElectrum
|
||||
import com.tangem.data.network.ServerApiInfura
|
||||
import com.tangem.data.network.model.CardVerifyAndGetInfo
|
||||
import com.tangem.data.network.model.InfuraResponse
|
||||
import com.tangem.data.nfc.VerifyCardTask
|
||||
import com.tangem.domain.cardReader.CardProtocol
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.tangemcard.tasks.VerifyCardTask
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.domain.wallet.*
|
||||
import com.tangem.domain.wallet.bch.BtcCashEngine
|
||||
import com.tangem.domain.wallet.btc.BtcData
|
||||
|
|
@ -41,7 +41,9 @@ import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
|||
import com.tangem.presentation.dialog.PINSwapWarningDialog
|
||||
import com.tangem.presentation.dialog.ShowQRCodeDialog
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.util.Util
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.tangemcard.util.Util
|
||||
import com.tangem.util.UtilHelper
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.fr_loaded_wallet.*
|
||||
|
|
|
|||
|
|
@ -13,14 +13,16 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.db.PINStorage
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.tangemcard.data.PINStorage
|
||||
import com.tangem.tangemcard.reader.NfcManager
|
||||
import com.tangem.domain.wallet.*
|
||||
import com.tangem.presentation.activity.CreateNewWalletActivity
|
||||
import com.tangem.presentation.activity.PurgeActivity
|
||||
import com.tangem.presentation.activity.PinRequestActivity
|
||||
import com.tangem.presentation.activity.PinSwapActivity
|
||||
import com.tangem.presentation.dialog.PINSwapWarningDialog
|
||||
import com.tangem.tangemcard.data.Blockchain
|
||||
import com.tangem.tangemcard.data.TangemCard
|
||||
import com.tangem.wallet.BuildConfig
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.fr_verify_card.*
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.util;
|
|||
import android.util.Log;
|
||||
|
||||
import com.tangem.domain.wallet.ECDSASignatureETH;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import org.spongycastle.asn1.ASN1EncodableVector;
|
||||
import org.spongycastle.asn1.ASN1Integer;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,8 @@ apply plugin: 'kotlin-android'
|
|||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
|
@ -22,6 +20,7 @@ android {
|
|||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
buildToolsVersion '28.0.3'
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -29,10 +28,37 @@ dependencies {
|
|||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
// implementation 'com.android.support:design:28.0.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.5'
|
||||
implementation 'com.madgag.spongycastle:core:1.56.0.0'
|
||||
implementation 'com.madgag.spongycastle:prov:1.56.0.0'
|
||||
implementation 'com.scottyab:rootbeer-lib:0.0.7'
|
||||
|
||||
// implementation 'com.android.support:support-compat:28.0.0'
|
||||
// implementation 'com.android.support:cardview-v7:28.0.0'
|
||||
// implementation 'com.android.support:support-v4:28.0.0'
|
||||
// implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
// implementation 'com.google.zxing:core:3.3.3'
|
||||
// implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
|
||||
// implementation 'com.squareup.retrofit2:retrofit:2.5.0'
|
||||
// implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
||||
// implementation 'com.skyfishjy.ripplebackground:library:1.0.1'
|
||||
// implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
|
||||
// implementation 'com.google.dagger:dagger:2.16'
|
||||
implementation 'org.bitcoinj:bitcoinj-parent:0.14.7'
|
||||
implementation 'org.bitcoinj:bitcoinj-core:0.14.7'
|
||||
// implementation 'me.dm7.barcodescanner:zxing:1.9.8'
|
||||
// implementation 'info.hoang8f:android-segmented:1.0.6'
|
||||
// implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
|
||||
// implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
||||
// implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
||||
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
|
|
|||
|
|
@ -1,2 +1,15 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.tangem.tangemcard" />
|
||||
package="com.tangem.tangemcard" >
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application>
|
||||
<!--<provider-->
|
||||
<!--android:name="com.tangem.data.LogFileProvider"-->
|
||||
<!--android:authorities="@string/log_file_provider_authorities"-->
|
||||
<!--android:enabled="true"-->
|
||||
<!--android:exported="false"-->
|
||||
<!--android:grantUriPermissions="true" />-->
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.domain.wallet;
|
||||
package com.tangem.tangemcard.data;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.tangemcard.R;
|
||||
|
||||
/**
|
||||
* Created by dvol on 06.08.2017.
|
||||
|
|
@ -71,7 +70,7 @@ public enum Blockchain {
|
|||
}
|
||||
|
||||
public int getImageResource(android.content.Context context, String name) {
|
||||
if (Strings.isNullOrEmpty(name))
|
||||
if (name==null || name.isEmpty())
|
||||
return getImageResource();
|
||||
|
||||
name = name.toLowerCase();
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.data.nfc
|
||||
package com.tangem.tangemcard.data
|
||||
|
||||
import android.os.Build
|
||||
import com.tangem.tangemcard.nfc.NFCLocation
|
||||
|
||||
class DeviceNFCAntennaLocation {
|
||||
companion object {
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.data;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
|
@ -1,15 +1,12 @@
|
|||
package com.tangem.domain.wallet;
|
||||
package com.tangem.tangemcard.data;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.tangem.domain.cardReader.CardCrypto;
|
||||
import com.tangem.tangemcard.reader.CardCrypto;
|
||||
import com.tangem.util.Util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.data.db
|
||||
package com.tangem.tangemcard.data
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
|
|
@ -11,7 +11,7 @@ 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
|
||||
import com.tangem.tangemcard.reader.CardCrypto
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.util.Util
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.wallet;
|
||||
package com.tangem.tangemcard.data;
|
||||
|
||||
/**
|
||||
* Created by dvol on 09.08.2017.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.tangemcard.nfc
|
||||
package com.tangem.tangemcard.data
|
||||
|
||||
enum class NFCLocation(val codename: String, val fullName: String, val orientation: Int, val x: Int, val y: Int, val z: Int) {
|
||||
model1("sailfish", "Google Pixel", 0, 65, 25, 0),
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.data.db;
|
||||
package com.tangem.tangemcard.data;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
package com.tangem.domain.wallet;
|
||||
package com.tangem.tangemcard.data;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.cardReader.SettingsMask;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.reader.SettingsMask;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
|
|
@ -21,7 +20,6 @@ public class TangemCard {
|
|||
|
||||
private byte[] CID;
|
||||
private Status status;
|
||||
private String wallet;
|
||||
private String UID;
|
||||
private String blockchainID;
|
||||
private Manufacturer manufacturer = Manufacturer.Unknown;
|
||||
|
|
@ -43,7 +41,7 @@ public class TangemCard {
|
|||
}
|
||||
|
||||
public void setBlockchain(Blockchain blockchain) {
|
||||
blockchainID=blockchain.getID();
|
||||
blockchainID = blockchain.getID();
|
||||
}
|
||||
|
||||
public void setBlockchainID(String blockchainID) {
|
||||
|
|
@ -57,7 +55,7 @@ public class TangemCard {
|
|||
String oldName = getBlockchain().getOfficialName();
|
||||
//String newName = String.format("%s - %s ERC20 token", token, oldName);
|
||||
String newName = token + " <br><small><small> " + oldName + " ERC20 token</small></small>";
|
||||
blockchainName=newName;
|
||||
blockchainName = newName;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -549,22 +547,6 @@ public class TangemCard {
|
|||
}
|
||||
}
|
||||
|
||||
public void setWallet(String wallet) {
|
||||
this.wallet = wallet;
|
||||
}
|
||||
|
||||
public String getWallet() {
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public String getShortWalletString() {
|
||||
if (wallet.length() < 22) {
|
||||
return wallet;
|
||||
} else {
|
||||
return wallet.substring(0, 10) + "......" + wallet.substring(wallet.length() - 10, wallet.length());
|
||||
}
|
||||
}
|
||||
|
||||
public String getUID() {
|
||||
return UID;
|
||||
}
|
||||
|
|
@ -596,19 +578,6 @@ public class TangemCard {
|
|||
this.DenominationText = denominationText;
|
||||
}
|
||||
|
||||
public void setDenomination(byte[] denomination) {
|
||||
this.Denomination = denomination;
|
||||
try {
|
||||
CoinEngine engine= CoinEngineFactory.INSTANCE.create(getBlockchain());
|
||||
CoinEngine.InternalAmount internalAmount=engine.convertToInternalAmount(denomination);
|
||||
CoinEngine.Amount amount=engine.convertToAmount(internalAmount);
|
||||
this.DenominationText = amount.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
this.DenominationText = "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getDenomination() {
|
||||
return Denomination;
|
||||
}
|
||||
|
|
@ -673,7 +642,6 @@ public class TangemCard {
|
|||
B.putByteArray("CardPublicKey", getCardPublicKey());
|
||||
|
||||
B.putInt("SignedHashes", getSignedHashes());
|
||||
B.putString("Wallet", wallet);
|
||||
B.putBoolean("WalletPublicKeyValid", isWalletPublicKeyValid());
|
||||
if (pbWalletKey != null)
|
||||
B.putByteArray("PublicKey", pbWalletKey);
|
||||
|
|
@ -683,6 +651,7 @@ public class TangemCard {
|
|||
if (getOfflineBalance() != null) B.putByteArray("OfflineBalance", getOfflineBalance());
|
||||
|
||||
if (getDenomination() != null) B.putByteArray("Denomination", getDenomination());
|
||||
if (getDenominationText() != null) B.putString("DenominationText", getDenominationText());
|
||||
|
||||
if (getIssuerData() != null && getIssuerDataSignature() != null) {
|
||||
B.putByteArray("IssuerData", getIssuerData());
|
||||
|
|
@ -725,7 +694,6 @@ public class TangemCard {
|
|||
PIN = B.getString("PIN");
|
||||
PIN2 = PIN2_Mode.valueOf(B.getString("PIN2"));
|
||||
status = Status.valueOf(B.getString("Status"));
|
||||
wallet = B.getString("Wallet");
|
||||
blockchainID = B.getString("Blockchain");
|
||||
tokensDecimal = B.getInt("TokensDecimal", 18);
|
||||
tokenSymbol = B.getString("TokenSymbol", "");
|
||||
|
|
@ -765,8 +733,11 @@ public class TangemCard {
|
|||
if (B.containsKey("OfflineBalance")) setOfflineBalance(B.getByteArray("OfflineBalance"));
|
||||
else clearOfflineBalance();
|
||||
|
||||
if (B.containsKey("Denomination")) setDenomination(B.getByteArray("Denomination"));
|
||||
else clearDenomination();
|
||||
if (B.containsKey("Denomination") && B.containsKey("DenominationText")) {
|
||||
setDenomination(B.getByteArray("Denomination"), B.getString("DenominationText"));
|
||||
} else if (B.containsKey("Denomination")) {
|
||||
setDenomination(B.getByteArray("Denomination"), "N/A");
|
||||
} else clearDenomination();
|
||||
|
||||
if (B.containsKey("IssuerData") && B.containsKey("IssuerDataSignature"))
|
||||
setIssuerData(B.getByteArray("IssuerData"), B.getByteArray("IssuerDataSignature"));
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import org.spongycastle.asn1.ASN1EncodableVector;
|
||||
import org.spongycastle.asn1.ASN1Integer;
|
||||
|
|
@ -23,7 +23,6 @@ import java.security.PrivateKey;
|
|||
import java.security.PublicKey;
|
||||
import java.security.Security;
|
||||
import java.security.Signature;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.Tag;
|
||||
|
|
@ -6,14 +6,12 @@ import android.nfc.TagLostException;
|
|||
import android.nfc.tech.IsoDep;
|
||||
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.data.db.LocalStorage;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.domain.wallet.Manufacturer;
|
||||
import com.tangem.domain.wallet.TangemContext;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.data.Issuer;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.tangemcard.data.Firmwares;
|
||||
import com.tangem.tangemcard.data.LocalStorage;
|
||||
import com.tangem.tangemcard.data.Manufacturer;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import org.spongycastle.jce.ECNamedCurveTable;
|
||||
import org.spongycastle.jce.interfaces.ECPublicKey;
|
||||
|
|
@ -29,6 +27,7 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.security.SecureRandom;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.util.Calendar;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.crypto.KeyAgreement;
|
||||
|
||||
|
|
@ -153,34 +152,25 @@ public class CardProtocol {
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructor for reading a card for the first time
|
||||
* Constructor
|
||||
*
|
||||
* @param context - Android context
|
||||
* @param isoDep - Android NFC tag
|
||||
* @param notifications - UI notification callbacks
|
||||
*/
|
||||
public CardProtocol(Context context, IsoDep isoDep, Notifications notifications) {
|
||||
mContext = context;
|
||||
mIsoDep = isoDep;
|
||||
mNotifications = notifications;
|
||||
mPIN = null;
|
||||
mCard = new TangemCard(Util.byteArrayToHexString(mIsoDep.getTag().getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for subsequent reading of the card
|
||||
*
|
||||
* @param context - Android context
|
||||
* @param isoDep - Android NFC tag
|
||||
* @param card - TangemCard object, stored data from previous reading
|
||||
* @param card - TangemCard object, stored data from previous reading or null for reading a card for the first time
|
||||
* @param notifications - UI notification callbacks
|
||||
*/
|
||||
public CardProtocol(Context context, IsoDep isoDep, TangemCard card, Notifications notifications) {
|
||||
mContext = context;
|
||||
mIsoDep = isoDep;
|
||||
mNotifications = notifications;
|
||||
mPIN = card.getPIN();
|
||||
mCard = card;
|
||||
if (card != null)
|
||||
{
|
||||
mPIN = card.getPIN();
|
||||
mCard = card;
|
||||
}else{
|
||||
mPIN = null;
|
||||
mCard = new TangemCard(Util.byteArrayToHexString(mIsoDep.getTag().getId()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -502,15 +492,15 @@ public class CardProtocol {
|
|||
return Apdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run READ command and parse answer
|
||||
* {@see run_Read(boolean parseResult) }
|
||||
*
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
public void run_Read() throws Exception {
|
||||
run_Read(true);
|
||||
}
|
||||
// /**
|
||||
// * Run READ command and parse answer
|
||||
// * {@see run_Read(boolean parseResult) }
|
||||
// *
|
||||
// * @throws Exception if something went wrong
|
||||
// */
|
||||
// public void run_Read() throws Exception {
|
||||
// run_Read1(true);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Run READ command and parse answer (if specified)
|
||||
|
|
@ -523,10 +513,9 @@ public class CardProtocol {
|
|||
* This command requires only PIN1 parameter while other commands also need CID
|
||||
* See [1] 8, 8.2
|
||||
*
|
||||
* @param parseResult - parse answer into TangemCard object or not
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
public void run_Read(boolean parseResult) throws Exception {
|
||||
public void run_Read1() throws Exception {
|
||||
CommandApdu rqApdu = StartPrepareCommand(INS.Read);
|
||||
Log.i(logTag, String.format("[%s]\n%s", rqApdu.getCommandName(), rqApdu.getTLVs().getParsedTLVs(" ")));
|
||||
|
||||
|
|
@ -536,15 +525,6 @@ public class CardProtocol {
|
|||
|
||||
Log.i(logTag, String.format("OK: [%04X]\n%s", rspApdu.getSW1SW2(), rspApdu.getTLVs().getParsedTLVs(" ")));
|
||||
readResult = rspApdu.getTLVs();
|
||||
if (parseResult) {
|
||||
// After first successful read, data will be parsed into TangemCard object
|
||||
parseReadResult();
|
||||
//TODO: move issuer data out from here
|
||||
run_ReadWriteIssuerData();
|
||||
} else {
|
||||
//TODO: check that card is the same
|
||||
}
|
||||
|
||||
} else if (rspApdu.isStatus(SW_PIN_ERROR)) {
|
||||
throw new TangemException_InvalidPIN(String.format("FAILED: [%04X] - Possible PIN is invalid!\n", rspApdu.getSW1SW2()));
|
||||
} else {
|
||||
|
|
@ -553,54 +533,6 @@ public class CardProtocol {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executing GET_ISSUER_DATA or WRITE_ISSUER_DATA depending on state in TangemCard object {@see TangemCard.getNeedWriteIssuerData()}
|
||||
* See [1] 8.7
|
||||
*
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
public void run_ReadWriteIssuerData() throws Exception {
|
||||
TLVList tlvIssuerData;
|
||||
if (mCard.getNeedWriteIssuerData()) {
|
||||
run_WriteIssuerData(mCard.getIssuerData(), mCard.getIssuerDataSignature());
|
||||
try {
|
||||
tlvIssuerData = TLVList.fromBytes(mCard.getIssuerData());
|
||||
} catch (TLVException e) {
|
||||
e.printStackTrace();
|
||||
tlvIssuerData = null;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
tlvIssuerData = run_GetIssuerData();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
tlvIssuerData = null;
|
||||
}
|
||||
}
|
||||
|
||||
// try read offline balance data
|
||||
if (mCard.getStatus() == TangemCard.Status.Loaded) {
|
||||
if (tlvIssuerData != null && tlvIssuerData.getTLV(TLV.Tag.TAG_ValidatedBalance) != null && mCard.getMaxSignatures() == mCard.getRemainingSignatures()) {
|
||||
mCard.setOfflineBalance(tlvIssuerData.getTLV(TLV.Tag.TAG_ValidatedBalance).Value);
|
||||
} else {
|
||||
mCard.clearOfflineBalance();
|
||||
}
|
||||
} else {
|
||||
mCard.clearOfflineBalance();
|
||||
}
|
||||
|
||||
// try read denomination
|
||||
if (tlvIssuerData != null && tlvIssuerData.getTLV(TLV.Tag.TAG_Denomination) != null) {
|
||||
if (tlvIssuerData.getTLV(TLV.Tag.TAG_DenominationText) != null) {
|
||||
mCard.setDenomination(tlvIssuerData.getTLV(TLV.Tag.TAG_Denomination).Value, tlvIssuerData.getTLV(TLV.Tag.TAG_DenominationText).getAsString());
|
||||
} else {
|
||||
mCard.setDenomination(tlvIssuerData.getTLV(TLV.Tag.TAG_Denomination).Value);
|
||||
}
|
||||
} else {
|
||||
mCard.clearDenomination();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A TLV list containing response of the last READ command
|
||||
*/
|
||||
|
|
@ -615,181 +547,12 @@ public class CardProtocol {
|
|||
return readResult != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse response of the last READ command into TangemCard object
|
||||
* See [1] 8.2, 5.3, 3.3
|
||||
*
|
||||
* @throws TangemException - if something went wrong
|
||||
*/
|
||||
public void parseReadResult() throws TangemException {
|
||||
// These tags always present in the parsed response: TAG_Status, TAG_CID, TAG_Manufacture_ID, TAG_Health, TAG_Firmware
|
||||
TLV tlvStatus = readResult.getTLV(TLV.Tag.TAG_Status);
|
||||
mCard.setStatus(TangemCard.Status.fromCode(Util.byteArrayToInt(tlvStatus.Value)));
|
||||
TLV tlvCID = readResult.getTLV(TLV.Tag.TAG_CardID);
|
||||
mCard.setCID(tlvCID.Value);
|
||||
mCard.setManufacturer(Manufacturer.FindManufacturer(readResult.getTLV(TLV.Tag.TAG_Manufacture_ID).getAsString()), true);
|
||||
|
||||
// Support of legacy Firmware
|
||||
if (readResult.getTLV(TLV.Tag.TAG_Firmware) != null) {
|
||||
mCard.setFirmwareVersion(readResult.getTLV(TLV.Tag.TAG_Firmware).getAsString());
|
||||
}
|
||||
mCard.setHealth(readResult.getTLV(TLV.Tag.TAG_Health).getAsInt());
|
||||
|
||||
// If the card was previously personalized then parse personalized card data - card public key, blockchain data and other settings
|
||||
if (mCard.getStatus() != TangemCard.Status.NotPersonalized) {
|
||||
try {
|
||||
TLV tlvCardPubkicKey = readResult.getTLV(TLV.Tag.TAG_CardPublicKey);
|
||||
if (tlvCardPubkicKey == null)
|
||||
throw new TangemException("Invalid answer format");
|
||||
|
||||
mCard.setCardPublicKey(tlvCardPubkicKey.Value);
|
||||
|
||||
TLVList tlvCardData = TLVList.fromBytes(readResult.getTLV(TLV.Tag.TAG_CardData).Value);
|
||||
|
||||
mCard.setBatch(tlvCardData.getTLV(TLV.Tag.TAG_Batch).getAsHexString());
|
||||
|
||||
TLV tokenSymbol = tlvCardData.getTLV(TLV.Tag.TAG_Token_Symbol);
|
||||
TLV contractAddress = tlvCardData.getTLV(TLV.Tag.TAG_Token_Contract_Address);
|
||||
TLV tokens_decimal = tlvCardData.getTLV(TLV.Tag.TAG_Token_Decimal);
|
||||
|
||||
if (tokenSymbol != null)
|
||||
mCard.setTokenSymbol(tokenSymbol.getAsString());
|
||||
|
||||
if (contractAddress != null)
|
||||
mCard.setContractAddress(contractAddress.getAsString());
|
||||
|
||||
if (tokens_decimal != null)
|
||||
mCard.setTokensDecimal(tokens_decimal.getAsInt());
|
||||
|
||||
byte[] tlvPersonalizationDT = tlvCardData.getTLV(TLV.Tag.TAG_ManufactureDateTime).Value;
|
||||
int year = (tlvPersonalizationDT[0] & 0xFF) << 8 | (tlvPersonalizationDT[1] & 0xFF);
|
||||
int month = tlvPersonalizationDT[2] - 1;
|
||||
int day = tlvPersonalizationDT[3];
|
||||
Calendar cd = Calendar.getInstance();
|
||||
cd.set(year, month, day, 0, 0, 0);
|
||||
mCard.setPersonalizationDateTime(cd.getTime());
|
||||
try {
|
||||
// Support of legacy Firmware
|
||||
if (mCard.getFirmwareVersion() == null) {
|
||||
mCard.setFirmwareVersion(tlvCardData.getTLV(TLV.Tag.TAG_Firmware).getAsString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(logTag, "Cannot get firmware version");
|
||||
mCard.setFirmwareVersion("0.00");
|
||||
}
|
||||
|
||||
try {
|
||||
if (mCard.getFirmwareVersion().compareTo("1.05") < 0) {
|
||||
// In FW ver 1.05, the issuer has one key pair used as both DataKey and TransactionKey, see [1] 3.3.1 and [1] 3.3.2
|
||||
mCard.setIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), readResult.getTLV(TLV.Tag.TAG_Issuer_Transaction_PublicKey).Value);
|
||||
} else {
|
||||
// In newer FW versions, the issuer has two different key pairs - DataKey and TransactionKey, see [1] 3.3.1 and [1] 3.3.2
|
||||
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 {
|
||||
// for very very old cards Issuer key can be stored in different TLV tag
|
||||
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().getID(), null);
|
||||
}
|
||||
}
|
||||
|
||||
// Overriding of missing card data, e.g. for cards with unknown ERC20 contract data
|
||||
// This method must be called after the issuer data is defined because newly written data is verified by issuer data key
|
||||
try {
|
||||
// Hardcoded for some known batches, or, for other batches, received from Tangem server and stored in local storage
|
||||
if (mCard.getBatch().equals("0017")) {
|
||||
mCard.setContractAddress("0x9Eef75bA8e81340da9D8d1fd06B2f313DB88839c");
|
||||
} else if (mCard.getBatch().equals("0019")) {
|
||||
mCard.setContractAddress("0x0c056b0cda0763cc14b8b2d6c02465c91e33ec72");
|
||||
} else {
|
||||
LocalStorage localStorage = new LocalStorage(mContext);
|
||||
localStorage.applySubstitution(mCard);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(logTag, "Can't apply card data substitution");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
mCard.setBlockchainIDFromCard(tlvCardData.getTLV(TLV.Tag.TAG_Blockchain_ID).getAsString());
|
||||
|
||||
try {
|
||||
mCard.setSettingsMask(readResult.getTagAsInt(TLV.Tag.TAG_SettingsMask));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(logTag, "Can't get settings mask");
|
||||
}
|
||||
|
||||
if (readResult.getTLV(TLV.Tag.TAG_PauseBeforePIN2) != null) {
|
||||
mCard.setPauseBeforePIN2(10 * readResult.getTagAsInt(TLV.Tag.TAG_PauseBeforePIN2));
|
||||
}
|
||||
|
||||
try {
|
||||
mCard.setSigningMethod(readResult.getTagAsInt(TLV.Tag.TAG_SigningMethod));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(logTag, "Can't get signing method");
|
||||
mCard.setSigningMethod(0);
|
||||
}
|
||||
|
||||
try {
|
||||
mCard.setMaxSignatures(readResult.getTagAsInt(TLV.Tag.TAG_MaxSignatures));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(logTag, "Can't get max signatures");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new TangemException("Can't parse card data");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parse additional parameters for Loaded cards: wallet public key, remaining signatures, etc
|
||||
if (mCard.getStatus() == TangemCard.Status.Loaded) {
|
||||
|
||||
TLV tlvPublicKey = readResult.getTLV(TLV.Tag.TAG_Wallet_PublicKey);
|
||||
|
||||
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
ECPoint p1 = spec.getCurve().decodePoint(tlvPublicKey.Value);
|
||||
|
||||
byte pkUncompressed[] = p1.getEncoded(false);
|
||||
|
||||
byte pkCompresses[] = p1.getEncoded(true);
|
||||
mCard.setWalletPublicKey(pkUncompressed);
|
||||
mCard.setWalletPublicKeyRar(pkCompresses);
|
||||
|
||||
TangemContext ctx = new TangemContext(mCard);
|
||||
try {
|
||||
// TODO - store in mCard only public key, not wallet address, move wallet address to coinData
|
||||
CoinEngine engineCoin = CoinEngineFactory.INSTANCE.create(ctx);
|
||||
if (engineCoin == null) throw new Exception("Can't create CoinEngine!");
|
||||
String wallet = engineCoin.calculateAddress(pkUncompressed);
|
||||
mCard.setWallet(wallet);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new TangemException("Can't define wallet address");
|
||||
}
|
||||
//mCard.setWallet(Blockchain.calculateWalletAddress(mCard, pkUncompressed));
|
||||
|
||||
mCard.setRemainingSignatures(readResult.getTagAsInt(TLV.Tag.TAG_RemainingSignatures));
|
||||
|
||||
if (readResult != null && readResult.getTLV(TLV.Tag.TAG_SignedHashes) != null) {
|
||||
mCard.setSignedHashes(readResult.getTagAsInt(TLV.Tag.TAG_SignedHashes));
|
||||
}
|
||||
|
||||
} else {
|
||||
mCard.setWallet("N/A");
|
||||
}
|
||||
public TLVList getReadResult()
|
||||
{
|
||||
return readResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* VERIFY_CARD command and verify card's signature
|
||||
* By using standard challenge-response scheme, the card proves
|
||||
|
|
@ -801,7 +564,7 @@ public class CardProtocol {
|
|||
*/
|
||||
public TLVList run_VerifyCard() throws Exception {
|
||||
if (mCard.getCardPublicKey() == null || readResult == null) {
|
||||
run_Read();
|
||||
throw new TangemException("Before run_VerifyCard execute run_Read card first!");
|
||||
}
|
||||
if (mCard.getStatus() == TangemCard.Status.NotPersonalized) {
|
||||
getCard().setManufacturer(Manufacturer.Unknown, false);
|
||||
|
|
@ -869,7 +632,7 @@ public class CardProtocol {
|
|||
* @throws Exception - if something went wrong
|
||||
*/
|
||||
public void run_CreateWallet(String PIN2) throws Exception {
|
||||
if (readResult == null) run_Read();
|
||||
if (readResult == null) throw new TangemException("Before run_VerifyCard execute run_Read card first!");
|
||||
CommandApdu rqApdu = StartPrepareCommand(INS.CreateWallet);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_PIN2, Util.calculateSHA256(PIN2));
|
||||
Log.i(logTag, String.format("[%s]\n%s", rqApdu.getCommandName(), rqApdu.getTLVs().getParsedTLVs(" ")));
|
||||
|
|
@ -930,7 +693,7 @@ public class CardProtocol {
|
|||
*/
|
||||
public void run_CheckWalletWithSignatureVerify() throws Exception {
|
||||
if (mCard.getCardPublicKey() == null || readResult == null) {
|
||||
run_Read();
|
||||
throw new TangemException("Before run_VerifyCard execute run_Read card first!");
|
||||
}
|
||||
if (mCard.getStatus() == TangemCard.Status.NotPersonalized) {
|
||||
getCard().setManufacturer(Manufacturer.Unknown, false);
|
||||
|
|
@ -1043,29 +806,6 @@ public class CardProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if default PIN2 is set on the card and enable UseDefaultPIN2 flag {@link TangemCard}
|
||||
* Works in firmware 1.12 and later, for older version UseDefaultPIN2 is always null
|
||||
* This function NEVER triggers security delay
|
||||
*
|
||||
* @throws Exception - if something went wrong
|
||||
*/
|
||||
public void run_CheckPIN2isDefault() throws Exception {
|
||||
// can obtain SetPIN(to default) answer without security delay - try check if PIN2 is default with card request
|
||||
if (mCard.isFirmwareNewer("1.19") || (mCard.isFirmwareNewer("1.12") && (mCard.getPauseBeforePIN2() == 0 || mCard.useSmartSecurityDelay()))) {
|
||||
try {
|
||||
run_SetPIN(DefaultPIN2, mPIN, DefaultPIN2, true);
|
||||
mCard.setUseDefaultPIN2(true);
|
||||
} catch (TangemException_NeedPause e) {
|
||||
mCard.setUseDefaultPIN2(null);
|
||||
} catch (TangemException_InvalidPIN e) {
|
||||
mCard.setUseDefaultPIN2(false);
|
||||
}
|
||||
} else {
|
||||
mCard.setUseDefaultPIN2(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SIGN command to sign hashes - SigningMethod=0,2,4 (see {@link TangemCard.SigningMethod})
|
||||
* See [1] 8.6
|
||||
|
|
@ -1177,7 +917,7 @@ public class CardProtocol {
|
|||
* @throws Exception - if something went wrong
|
||||
*/
|
||||
public byte[] run_VerifyCode(String hashAlgID, int codePageAddress, int codePageCount, byte[] challenge) throws Exception {
|
||||
if (readResult == null) run_Read();
|
||||
if (readResult == null) throw new TangemException("Before run_VerifyCard execute run_Read card first!");
|
||||
CommandApdu rqApdu = StartPrepareCommand(INS.VerifyCode);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_HashAlgID, hashAlgID.getBytes("US-ASCII"));
|
||||
rqApdu.addTLV_U32(TLV.Tag.TAG_CodePageAddress, codePageAddress);
|
||||
|
|
@ -1212,7 +952,7 @@ public class CardProtocol {
|
|||
* @throws Exception - if something went wrong
|
||||
*/
|
||||
private void run_ValidateCard(String PIN2) throws Exception {
|
||||
if (readResult == null) run_Read();
|
||||
if (readResult == null) throw new TangemException("Before run_VerifyCard execute run_Read card first!");
|
||||
CommandApdu rqApdu = StartPrepareCommand(INS.ValidateCard);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_PIN2, Util.calculateSHA256(PIN2));
|
||||
|
||||
|
|
@ -1244,8 +984,8 @@ public class CardProtocol {
|
|||
* @param issuerSignature - signature of issuerData with IssuerDataKey
|
||||
* @throws Exception - if something went wrong
|
||||
*/
|
||||
private void run_WriteIssuerData(byte[] issuerData, byte[] issuerSignature) throws Exception {
|
||||
run_Read();
|
||||
public void run_WriteIssuerData(byte[] issuerData, byte[] issuerSignature) throws Exception {
|
||||
if( readResult==null ) throw new TangemException("Before run_VerifyCard execute run_Read card first!");
|
||||
|
||||
CommandApdu rqApdu = StartPrepareCommand(INS.WriteIssuerData);
|
||||
rqApdu.addTLV(TLV.Tag.TAG_Issuer_Data, issuerData);
|
||||
|
|
@ -1269,7 +1009,7 @@ public class CardProtocol {
|
|||
* @return TLVList with issuerData (if success read and verify)
|
||||
* @throws Exception - if something went wrong
|
||||
*/
|
||||
private TLVList run_GetIssuerData() throws Exception {
|
||||
public TLVList run_GetIssuerData() throws Exception {
|
||||
CommandApdu rqApdu = StartPrepareCommand(INS.GetIssuerData);
|
||||
|
||||
Log.i(logTag, String.format("[%s]\n%s", rqApdu.getCommandName(), rqApdu.getTLVs().getParsedTLVs(" ")));
|
||||
|
|
@ -1342,4 +1082,5 @@ public class CardProtocol {
|
|||
} while (true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 07.03.2018.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.TargetApi;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
import org.spongycastle.crypto.CipherParameters;
|
||||
import org.spongycastle.crypto.digests.SHA256Digest;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
import com.tangem.util.Util;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 07.03.2018.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 07.03.2018.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
import com.tangem.util.Util;
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
public class TLVException extends Exception {
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.domain.cardReader;
|
||||
package com.tangem.tangemcard.reader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 23.06.2017.
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package com.tangem.data.nfc;
|
||||
package com.tangem.tangemcard.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
|
||||
public class CreateNewWalletTask extends Thread {
|
||||
public static final String TAG = CreateNewWalletTask.class.getSimpleName();
|
||||
|
|
@ -0,0 +1,454 @@
|
|||
package com.tangem.tangemcard.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.data.Issuer;
|
||||
import com.tangem.tangemcard.data.LocalStorage;
|
||||
import com.tangem.tangemcard.data.Manufacturer;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.reader.TLV;
|
||||
import com.tangem.tangemcard.reader.TLVException;
|
||||
import com.tangem.tangemcard.reader.TLVList;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
|
||||
import org.spongycastle.jce.ECNamedCurveTable;
|
||||
import org.spongycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* Base class for card communication task
|
||||
*/
|
||||
public class CustomReadCardTask extends Thread {
|
||||
public static final String TAG = CustomReadCardTask.class.getSimpleName();
|
||||
|
||||
protected IsoDep mIsoDep;
|
||||
protected CardProtocol.Notifications mNotifications;
|
||||
protected boolean isCancelled = false;
|
||||
protected Context mContext;
|
||||
protected NfcManager mNfcManager;
|
||||
protected TangemCard mCard ;
|
||||
CardProtocol protocol;
|
||||
|
||||
// this fields are static to optimize process when need enter pin and scan card again
|
||||
private static ArrayList<String> lastRead_UnsuccessfullPINs = new ArrayList<>();
|
||||
private static TangemCard.EncryptionMode lastRead_Encryption = null;
|
||||
private static String lastRead_UID;
|
||||
|
||||
public static void resetLastReadInfo() {
|
||||
lastRead_UID = "";
|
||||
lastRead_Encryption = null;
|
||||
lastRead_UnsuccessfullPINs.clear();
|
||||
}
|
||||
|
||||
public CustomReadCardTask(Context context, TangemCard card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
mContext = context;
|
||||
mIsoDep = isoDep;
|
||||
mNotifications = notifications;
|
||||
mNfcManager = nfcManager;
|
||||
mCard=card;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executing GET_ISSUER_DATA or WRITE_ISSUER_DATA depending on state in TangemCard object {@see TangemCard.getNeedWriteIssuerData()}
|
||||
* See [1] 8.7
|
||||
* Usually this function must be called if run_Task() of descendants
|
||||
*
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
protected void run_ReadOrWriteIssuerData() throws Exception {
|
||||
TLVList tlvIssuerData;
|
||||
if (mCard.getNeedWriteIssuerData()) {
|
||||
protocol.run_WriteIssuerData(mCard.getIssuerData(), mCard.getIssuerDataSignature());
|
||||
try {
|
||||
tlvIssuerData = TLVList.fromBytes(mCard.getIssuerData());
|
||||
} catch (TLVException e) {
|
||||
e.printStackTrace();
|
||||
tlvIssuerData = null;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
tlvIssuerData = protocol.run_GetIssuerData();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
tlvIssuerData = null;
|
||||
}
|
||||
}
|
||||
|
||||
// try read offline balance data
|
||||
if (mCard.getStatus() == TangemCard.Status.Loaded) {
|
||||
if (tlvIssuerData != null && tlvIssuerData.getTLV(TLV.Tag.TAG_ValidatedBalance) != null && mCard.getMaxSignatures() == mCard.getRemainingSignatures()) {
|
||||
mCard.setOfflineBalance(tlvIssuerData.getTLV(TLV.Tag.TAG_ValidatedBalance).Value);
|
||||
} else {
|
||||
mCard.clearOfflineBalance();
|
||||
}
|
||||
} else {
|
||||
mCard.clearOfflineBalance();
|
||||
}
|
||||
|
||||
// try read denomination
|
||||
if (tlvIssuerData != null && tlvIssuerData.getTLV(TLV.Tag.TAG_Denomination) != null) {
|
||||
if (tlvIssuerData.getTLV(TLV.Tag.TAG_DenominationText) != null) {
|
||||
mCard.setDenomination(tlvIssuerData.getTLV(TLV.Tag.TAG_Denomination).Value, tlvIssuerData.getTLV(TLV.Tag.TAG_DenominationText).getAsString());
|
||||
} else {
|
||||
mCard.setDenomination(tlvIssuerData.getTLV(TLV.Tag.TAG_Denomination).Value, null);
|
||||
}
|
||||
} else {
|
||||
mCard.clearDenomination();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse response of the last READ command into TangemCard object
|
||||
* See [1] 8.2, 5.3, 3.3
|
||||
*
|
||||
* @throws CardProtocol.TangemException - if something went wrong
|
||||
*/
|
||||
public void parseReadResult() throws CardProtocol.TangemException {
|
||||
// These tags always present in the parsed response: TAG_Status, TAG_CID, TAG_Manufacture_ID, TAG_Health, TAG_Firmware
|
||||
TLV tlvStatus = protocol.getReadResult().getTLV(TLV.Tag.TAG_Status);
|
||||
mCard.setStatus(TangemCard.Status.fromCode(Util.byteArrayToInt(tlvStatus.Value)));
|
||||
TLV tlvCID = protocol.getReadResult().getTLV(TLV.Tag.TAG_CardID);
|
||||
mCard.setCID(tlvCID.Value);
|
||||
mCard.setManufacturer(Manufacturer.FindManufacturer(protocol.getReadResult().getTLV(TLV.Tag.TAG_Manufacture_ID).getAsString()), true);
|
||||
|
||||
// Support of legacy Firmware
|
||||
if (protocol.getReadResult().getTLV(TLV.Tag.TAG_Firmware) != null) {
|
||||
mCard.setFirmwareVersion(protocol.getReadResult().getTLV(TLV.Tag.TAG_Firmware).getAsString());
|
||||
}
|
||||
mCard.setHealth(protocol.getReadResult().getTLV(TLV.Tag.TAG_Health).getAsInt());
|
||||
|
||||
// If the card was previously personalized then parse personalized card data - card public key, blockchain data and other settings
|
||||
if (mCard.getStatus() != TangemCard.Status.NotPersonalized) {
|
||||
try {
|
||||
TLV tlvCardPubkicKey = protocol.getReadResult().getTLV(TLV.Tag.TAG_CardPublicKey);
|
||||
if (tlvCardPubkicKey == null)
|
||||
throw new CardProtocol.TangemException("Invalid answer format");
|
||||
|
||||
mCard.setCardPublicKey(tlvCardPubkicKey.Value);
|
||||
|
||||
TLVList tlvCardData = TLVList.fromBytes(protocol.getReadResult().getTLV(TLV.Tag.TAG_CardData).Value);
|
||||
|
||||
mCard.setBatch(tlvCardData.getTLV(TLV.Tag.TAG_Batch).getAsHexString());
|
||||
|
||||
TLV tokenSymbol = tlvCardData.getTLV(TLV.Tag.TAG_Token_Symbol);
|
||||
TLV contractAddress = tlvCardData.getTLV(TLV.Tag.TAG_Token_Contract_Address);
|
||||
TLV tokens_decimal = tlvCardData.getTLV(TLV.Tag.TAG_Token_Decimal);
|
||||
|
||||
if (tokenSymbol != null)
|
||||
mCard.setTokenSymbol(tokenSymbol.getAsString());
|
||||
|
||||
if (contractAddress != null)
|
||||
mCard.setContractAddress(contractAddress.getAsString());
|
||||
|
||||
if (tokens_decimal != null)
|
||||
mCard.setTokensDecimal(tokens_decimal.getAsInt());
|
||||
|
||||
byte[] tlvPersonalizationDT = tlvCardData.getTLV(TLV.Tag.TAG_ManufactureDateTime).Value;
|
||||
int year = (tlvPersonalizationDT[0] & 0xFF) << 8 | (tlvPersonalizationDT[1] & 0xFF);
|
||||
int month = tlvPersonalizationDT[2] - 1;
|
||||
int day = tlvPersonalizationDT[3];
|
||||
Calendar cd = Calendar.getInstance();
|
||||
cd.set(year, month, day, 0, 0, 0);
|
||||
mCard.setPersonalizationDateTime(cd.getTime());
|
||||
try {
|
||||
// Support of legacy Firmware
|
||||
if (mCard.getFirmwareVersion() == null) {
|
||||
mCard.setFirmwareVersion(tlvCardData.getTLV(TLV.Tag.TAG_Firmware).getAsString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Cannot get firmware version");
|
||||
mCard.setFirmwareVersion("0.00");
|
||||
}
|
||||
|
||||
try {
|
||||
if (mCard.getFirmwareVersion().compareTo("1.05") < 0) {
|
||||
// In FW ver 1.05, the issuer has one key pair used as both DataKey and TransactionKey, see [1] 3.3.1 and [1] 3.3.2
|
||||
mCard.setIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), protocol.getReadResult().getTLV(TLV.Tag.TAG_Issuer_Transaction_PublicKey).Value);
|
||||
} else {
|
||||
// In newer FW versions, the issuer has two different key pairs - DataKey and TransactionKey, see [1] 3.3.1 and [1] 3.3.2
|
||||
mCard.setIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), protocol.getReadResult().getTLV(TLV.Tag.TAG_Issuer_Data_PublicKey).Value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Cannot get issuer, try a version for older cards");
|
||||
try {
|
||||
// for very very old cards Issuer key can be stored in different TLV tag
|
||||
mCard.setIssuer(tlvCardData.getTLV(TLV.Tag.TAG_Issuer_ID).getAsString(), protocol.getReadResult().getTLV(TLV.Tag.TAG_Issuer_Transaction_PublicKey).Value);
|
||||
} catch (Exception ee) {
|
||||
ee.printStackTrace();
|
||||
Log.e(TAG, "Cannot get issuer");
|
||||
mCard.setIssuer(Issuer.Unknown().getID(), null);
|
||||
}
|
||||
}
|
||||
|
||||
// Overriding of missing card data, e.g. for cards with unknown ERC20 contract data
|
||||
// This method must be called after the issuer data is defined because newly written data is verified by issuer data key
|
||||
try {
|
||||
// Hardcoded for some known batches, or, for other batches, received from Tangem server and stored in local storage
|
||||
if (mCard.getBatch().equals("0017")) {
|
||||
mCard.setContractAddress("0x9Eef75bA8e81340da9D8d1fd06B2f313DB88839c");
|
||||
} else if (mCard.getBatch().equals("0019")) {
|
||||
mCard.setContractAddress("0x0c056b0cda0763cc14b8b2d6c02465c91e33ec72");
|
||||
} else {
|
||||
LocalStorage localStorage = new LocalStorage(mContext);
|
||||
localStorage.applySubstitution(mCard);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Can't apply card data substitution");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
mCard.setBlockchainIDFromCard(tlvCardData.getTLV(TLV.Tag.TAG_Blockchain_ID).getAsString());
|
||||
|
||||
try {
|
||||
mCard.setSettingsMask(protocol.getReadResult().getTagAsInt(TLV.Tag.TAG_SettingsMask));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Can't get settings mask");
|
||||
}
|
||||
|
||||
if (protocol.getReadResult().getTLV(TLV.Tag.TAG_PauseBeforePIN2) != null) {
|
||||
mCard.setPauseBeforePIN2(10 * protocol.getReadResult().getTagAsInt(TLV.Tag.TAG_PauseBeforePIN2));
|
||||
}
|
||||
|
||||
try {
|
||||
mCard.setSigningMethod(protocol.getReadResult().getTagAsInt(TLV.Tag.TAG_SigningMethod));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Can't get signing method");
|
||||
mCard.setSigningMethod(0);
|
||||
}
|
||||
|
||||
try {
|
||||
mCard.setMaxSignatures(protocol.getReadResult().getTagAsInt(TLV.Tag.TAG_MaxSignatures));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Can't get max signatures");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new CardProtocol.TangemException("Can't parse card data");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parse additional parameters for Loaded cards: wallet public key, remaining signatures, etc
|
||||
if (mCard.getStatus() == TangemCard.Status.Loaded) {
|
||||
|
||||
TLV tlvPublicKey = protocol.getReadResult().getTLV(TLV.Tag.TAG_Wallet_PublicKey);
|
||||
|
||||
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
ECPoint p1 = spec.getCurve().decodePoint(tlvPublicKey.Value);
|
||||
|
||||
byte pkUncompressed[] = p1.getEncoded(false);
|
||||
|
||||
byte pkCompresses[] = p1.getEncoded(true);
|
||||
mCard.setWalletPublicKey(pkUncompressed);
|
||||
mCard.setWalletPublicKeyRar(pkCompresses);
|
||||
|
||||
// TODO - store in mCard only public key, not wallet address, move wallet address to coinData
|
||||
// TangemContext ctx = new TangemContext(mCard);
|
||||
// try {
|
||||
// CoinEngine engineCoin = CoinEngineFactory.INSTANCE.create(ctx);
|
||||
// if (engineCoin == null) throw new Exception("Can't create CoinEngine!");
|
||||
// String wallet = engineCoin.calculateAddress(pkUncompressed);
|
||||
// mCard.setWallet(wallet);
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// throw new TangemException("Can't define wallet address");
|
||||
// }
|
||||
//mCard.setWallet(Blockchain.calculateWalletAddress(mCard, pkUncompressed));
|
||||
|
||||
mCard.setRemainingSignatures(protocol.getReadResult().getTagAsInt(TLV.Tag.TAG_RemainingSignatures));
|
||||
|
||||
if (protocol.getReadResult() != null && protocol.getReadResult().getTLV(TLV.Tag.TAG_SignedHashes) != null) {
|
||||
mCard.setSignedHashes(protocol.getReadResult().getTagAsInt(TLV.Tag.TAG_SignedHashes));
|
||||
}
|
||||
|
||||
} else {
|
||||
// mCard.setWallet("N/A");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* On first time card reading run READ command, parse answer and Executing GET_ISSUER_DATA or WRITE_ISSUER_DATA depending on state in TangemCard object {@see TangemCard.getNeedWriteIssuerData()}
|
||||
* See [1] 8.7
|
||||
*
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
public void run_FirstTimeRead() throws Exception {
|
||||
|
||||
|
||||
byte[] UID = mIsoDep.getTag().getId();
|
||||
String sUID = Util.byteArrayToHexString(UID);
|
||||
if (!lastRead_UID.equals(sUID)) {
|
||||
resetLastReadInfo();
|
||||
}
|
||||
|
||||
Log.i(TAG, "[-- Start read card info --]");
|
||||
|
||||
if (isCancelled) return;
|
||||
|
||||
protocol.setPIN(PINStorage.getDefaultPIN());
|
||||
protocol.clearReadResult();
|
||||
|
||||
if (lastRead_Encryption == null) {
|
||||
Log.i(TAG, "Try get supported encryption mode");
|
||||
protocol.run_GetSupportedEncryption();
|
||||
} else {
|
||||
Log.i(TAG, "Use already defined encryption mode: " + lastRead_Encryption.name());
|
||||
protocol.getCard().encryptionMode = lastRead_Encryption;
|
||||
}
|
||||
|
||||
if (protocol.haveReadResult()) {
|
||||
//already have read result (obtained while get supported encryption), only read issuer data and define offline balance
|
||||
parseReadResult();
|
||||
PINStorage.setLastUsedPIN(protocol.getCard().getPIN());
|
||||
} else {
|
||||
//don't have read result - may be don't get supported encryption on this try, need encryption or need another PIN
|
||||
if (lastRead_Encryption == null) {
|
||||
// we try get supported encryption on this time
|
||||
lastRead_Encryption = protocol.getCard().encryptionMode;
|
||||
if (protocol.getCard().encryptionMode == TangemCard.EncryptionMode.None) {
|
||||
// default pin not accepted
|
||||
lastRead_UnsuccessfullPINs.add(PINStorage.getDefaultPIN());
|
||||
}
|
||||
}
|
||||
|
||||
boolean pinFound = false;
|
||||
for (String PIN : PINStorage.getPINs()) {
|
||||
Log.e(TAG, "PIN: " + PIN);
|
||||
|
||||
boolean skipPin = false;
|
||||
for (int i = 0; i < lastRead_UnsuccessfullPINs.size(); i++) {
|
||||
if (lastRead_UnsuccessfullPINs.get(i).equals(PIN)) {
|
||||
skipPin = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skipPin) {
|
||||
Log.e(TAG, "Skip PIN - already checked before");
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
protocol.setPIN(PIN);
|
||||
if (protocol.getCard().encryptionMode != TangemCard.EncryptionMode.None) {
|
||||
protocol.CreateProtocolKey();
|
||||
}
|
||||
protocol.run_Read1();
|
||||
// After first successful read, data will be parsed into TangemCard object
|
||||
parseReadResult();
|
||||
|
||||
PINStorage.setLastUsedPIN(PIN);
|
||||
pinFound = true;
|
||||
protocol.getCard().setPIN(PIN);
|
||||
break;
|
||||
} catch (CardProtocol.TangemException_InvalidPIN e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
lastRead_UnsuccessfullPINs.add(PIN);
|
||||
}
|
||||
}
|
||||
if (!pinFound) {
|
||||
throw new CardProtocol.TangemException_InvalidPIN("No valid PIN found!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run read and check that the card is the same
|
||||
*
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
public void run_SecondTimeRead() throws Exception {
|
||||
String PIN = mCard.getPIN();
|
||||
protocol.setPIN(PIN);
|
||||
protocol.run_Read1();
|
||||
PINStorage.setLastUsedPIN(PIN);
|
||||
if (!mCard.getCID().equals(protocol.getReadResult().getTLV(TLV.Tag.TAG_CardID))) {
|
||||
throw new CardProtocol.TangemException("Card must be the same. Reading attempt on different card!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function must be override in descendants to arrive the task goal - sign, verify and etc
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
public void run_Task() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (mIsoDep == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// for Samsung's bugs -
|
||||
// Workaround for the Samsung Galaxy S5 (since the
|
||||
// first connection always hangs on transceive).
|
||||
int timeout = mIsoDep.getTimeout();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.close();
|
||||
mIsoDep.connect();
|
||||
mIsoDep.setTimeout(timeout);
|
||||
try {
|
||||
protocol = new CardProtocol(mContext, mIsoDep, mCard, mNotifications);
|
||||
mNotifications.onReadStart(protocol);
|
||||
try {
|
||||
Log.i(TAG, String.format("[-- Start task -- %s --]", getClass().getSimpleName()));
|
||||
mNotifications.onReadProgress(protocol, 5);
|
||||
if (mCard == null) {
|
||||
// first time reading
|
||||
run_FirstTimeRead();
|
||||
} else {
|
||||
run_SecondTimeRead();
|
||||
}
|
||||
run_Task();
|
||||
mNotifications.onReadProgress(protocol, 100);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
protocol.setError(e);
|
||||
|
||||
} finally {
|
||||
Log.i(TAG, String.format("[-- Finish task -- %s --]", getClass().getSimpleName()));
|
||||
mNotifications.onReadFinish(protocol);
|
||||
}
|
||||
} finally {
|
||||
mNfcManager.ignoreTag(mIsoDep.getTag());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
mNfcManager.notifyReadResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel(Boolean AllowInterrupt) {
|
||||
try {
|
||||
if (isAlive()) {
|
||||
isCancelled = true;
|
||||
join(500);
|
||||
}
|
||||
if (isAlive() && AllowInterrupt) {
|
||||
interrupt();
|
||||
mNotifications.onReadCancel();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.tangemcard.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
|
||||
public class PurgeTask extends CustomReadCardTask {
|
||||
public static final String TAG = PurgeTask.class.getSimpleName();
|
||||
|
||||
public PurgeTask(Context context, TangemCard card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
super(context, card, nfcManager, isoDep, notifications);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run_Task() throws Exception {
|
||||
if (mCard.getPauseBeforePIN2() > 0) {
|
||||
mNotifications.onReadWait(mCard.getPauseBeforePIN2());
|
||||
}
|
||||
protocol.run_PurgeWallet(PINStorage.getPIN2());
|
||||
mNotifications.onReadProgress(protocol, 50);
|
||||
protocol.run_Read1();
|
||||
mNotifications.onReadProgress(protocol, 100);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package com.tangem.tangemcard.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
|
||||
public class ReadCardInfoTask extends CustomReadCardTask {
|
||||
public static final String TAG = ReadCardInfoTask.class.getSimpleName();
|
||||
|
||||
public ReadCardInfoTask(Context context, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
super(context, null, nfcManager, isoDep, notifications);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if default PIN2 is set on the card and enable UseDefaultPIN2 flag {@link TangemCard}
|
||||
* Works in firmware 1.12 and later, for older version UseDefaultPIN2 is always null
|
||||
* This function NEVER triggers security delay
|
||||
*
|
||||
* @throws Exception - if something went wrong
|
||||
*/
|
||||
public void run_CheckPIN2isDefault() throws Exception {
|
||||
// can obtain SetPIN(to default) answer without security delay - try check if PIN2 is default with card request
|
||||
if (mCard.isFirmwareNewer("1.19") || (mCard.isFirmwareNewer("1.12") && (mCard.getPauseBeforePIN2() == 0 || mCard.useSmartSecurityDelay()))) {
|
||||
try {
|
||||
protocol.run_SetPIN(protocol.DefaultPIN2, mCard.getPIN(), protocol.DefaultPIN2, true);
|
||||
mCard.setUseDefaultPIN2(true);
|
||||
} catch (CardProtocol.TangemException_NeedPause e) {
|
||||
mCard.setUseDefaultPIN2(null);
|
||||
} catch (CardProtocol.TangemException_InvalidPIN e) {
|
||||
mCard.setUseDefaultPIN2(false);
|
||||
}
|
||||
} else {
|
||||
mCard.setUseDefaultPIN2(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run_Task() throws Exception {
|
||||
mNotifications.onReadProgress(protocol, 20);
|
||||
run_ReadOrWriteIssuerData();
|
||||
mNotifications.onReadProgress(protocol, 50);
|
||||
run_CheckPIN2isDefault();
|
||||
mNotifications.onReadProgress(protocol, 90);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package com.tangem.data.nfc;
|
||||
package com.tangem.tangemcard.tasks;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.domain.wallet.Blockchain;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.Blockchain;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
import com.tangem.domain.wallet.CoinEngineFactory;
|
||||
import com.tangem.domain.wallet.TangemContext;
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package com.tangem.data.nfc;
|
||||
package com.tangem.tangemcard.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.data.db.PINStorage;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
|
||||
public class SwapPINTask extends Thread {
|
||||
public static final String TAG = SwapPINTask.class.getSimpleName();
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package com.tangem.tangemcard.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.tangemcard.data.Firmwares;
|
||||
import com.tangem.tangemcard.reader.NfcManager;
|
||||
import com.tangem.tangemcard.data.PINStorage;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by dvol on 04.02.2018.
|
||||
*/
|
||||
|
||||
public class VerifyCardTask extends CustomReadCardTask {
|
||||
public static final String TAG = VerifyCardTask.class.getSimpleName();
|
||||
|
||||
public VerifyCardTask(Context context, TangemCard card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
super(context, card, nfcManager, isoDep, notifications);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run_Task() throws Exception {
|
||||
mNotifications.onReadProgress(protocol, 20);
|
||||
if (isCancelled) return;
|
||||
protocol.run_VerifyCard();
|
||||
mNotifications.onReadProgress(protocol, 50);
|
||||
Log.i(TAG, "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName());
|
||||
if (isCancelled) return;
|
||||
if (protocol.getCard().getStatus() == TangemCard.Status.Loaded) {
|
||||
protocol.run_CheckWalletWithSignatureVerify();
|
||||
mNotifications.onReadProgress(protocol, 80);
|
||||
}
|
||||
if (isCancelled) return;
|
||||
Firmwares.VerifyCodeRecord record=Firmwares.selectRandomVerifyCodeBlock(mCard.getFirmwareVersion());
|
||||
if (isCancelled) return;
|
||||
if( record!=null ) {
|
||||
byte[] returnedDigest = protocol.run_VerifyCode(record.hashAlg, record.blockIndex, record.blockCount, record.challenge);
|
||||
mCard.setCodeConfirmed(Arrays.equals(returnedDigest, record.digest));
|
||||
}else{
|
||||
mCard.setCodeConfirmed(null);
|
||||
}
|
||||
mNotifications.onReadProgress(protocol, 90);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.util;
|
||||
package com.tangem.tangemcard.util;
|
||||
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |