token-import: introduce parcelable SecurityTokenInfo

This commit is contained in:
Vincent Breitmoser 2017-09-06 02:40:47 +02:00
parent f40cebfb21
commit 768abb3074
9 changed files with 115 additions and 129 deletions

View file

@ -956,6 +956,25 @@ public class SecurityTokenHelper {
return mOpenPgpCapabilities;
}
public SecurityTokenInfo getTokenInfo() throws IOException {
byte[] fingerprints = getFingerprints();
byte[] fpSign = new byte[20];
byte[] fpDecrypt = new byte[20];
byte[] fpAuth = new byte[20];
ByteBuffer buf = ByteBuffer.wrap(fingerprints);
buf.get(fpSign);
buf.get(fpDecrypt);
buf.get(fpAuth);
byte[] aid = getAid();
String userId = getUserId();
String url = getUrl();
byte[] pwInfo = getPwStatusBytes();
return SecurityTokenInfo.create(fpSign, fpDecrypt, fpAuth, aid, userId, url, pwInfo[4], pwInfo[6]);
}
private static class LazyHolder {
private static final SecurityTokenHelper SECURITY_TOKEN_HELPER = new SecurityTokenHelper();
}

View file

@ -0,0 +1,48 @@
package org.sufficientlysecure.keychain.securitytoken;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
@AutoValue
public abstract class SecurityTokenInfo implements Parcelable {
@Nullable
public abstract byte[] getFingerprintSign();
@Nullable
public abstract byte[] getFingerprintDecrypt();
@Nullable
public abstract byte[] getFingerprintAuth();
@Nullable
public abstract byte[] getAid();
@Nullable
public abstract String getUserId();
@Nullable
public abstract String getUrl();
public abstract int getVerifyRetries();
public abstract int getVerifyAdminRetries();
public byte[][] getAllFingerprints() {
byte[][] fingerprints = new byte[3][];
fingerprints[0] = getFingerprintSign();
fingerprints[1] = getFingerprintDecrypt();
fingerprints[2] = getFingerprintAuth();
return fingerprints;
}
public boolean isEmpty() {
return getFingerprintSign() == null && getFingerprintDecrypt() == null && getFingerprintAuth() == null;
}
public static SecurityTokenInfo create(byte[] fpSign, byte[] fpDecrypt, byte[] fpAuth,
byte[] aid, String userId, String url, int verifyRetries, int verifyAdminRetries) {
return new AutoValue_SecurityTokenInfo(fpSign, fpDecrypt, fpAuth, aid,
userId, url, verifyRetries, verifyAdminRetries);
}
public static SecurityTokenInfo createBlank(byte[] aid) {
return new AutoValue_SecurityTokenInfo(null, null, null, aid, null, null, 0, 0);
}
}

View file

@ -31,15 +31,10 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.TaskStackBuilder;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.securitytoken.KeyFormat;
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity;
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity;
import org.sufficientlysecure.keychain.ui.token.ManageSecurityTokenFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
@ -54,10 +49,7 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
public static final String EXTRA_SECURITY_TOKEN_PIN = "yubi_key_pin";
public static final String EXTRA_SECURITY_TOKEN_ADMIN_PIN = "yubi_key_admin_pin";
public static final String EXTRA_SECURITY_TOKEN_USER_ID = "nfc_user_id";
public static final String EXTRA_SECURITY_TOKEN_AID = "nfc_aid";
public static final String EXTRA_SECURITY_FINGERPRINTS = "nfc_fingerprints";
public static final String EXTRA_SECURITY_TOKEN_URL = "nfc_url";
public static final String EXTRA_SECURITY_TOKEN_INFO = "token_info";
public static final String FRAGMENT_TAG = "currentFragment";
@ -75,11 +67,7 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
Fragment mCurrentFragment;
byte[] mScannedFingerprints;
byte[] mSecurityTokenAid;
String mSecurityTokenUserId;
private String mSecurityTokenUrl;
SecurityTokenInfo tokenInfo;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -106,7 +94,6 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
mPassphrase = savedInstanceState.getParcelable(EXTRA_PASSPHRASE);
mFirstTime = savedInstanceState.getBoolean(EXTRA_FIRST_TIME);
mCreateSecurityToken = savedInstanceState.getBoolean(EXTRA_CREATE_SECURITY_TOKEN);
mSecurityTokenAid = savedInstanceState.getByteArray(EXTRA_SECURITY_TOKEN_AID);
mSecurityTokenPin = savedInstanceState.getParcelable(EXTRA_SECURITY_TOKEN_PIN);
mSecurityTokenAdminPin = savedInstanceState.getParcelable(EXTRA_SECURITY_TOKEN_ADMIN_PIN);
@ -120,20 +107,16 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
mFirstTime = intent.getBooleanExtra(EXTRA_FIRST_TIME, false);
mCreateSecurityToken = intent.getBooleanExtra(EXTRA_CREATE_SECURITY_TOKEN, false);
if (intent.hasExtra(EXTRA_SECURITY_FINGERPRINTS)) {
byte[] nfcFingerprints = intent.getByteArrayExtra(EXTRA_SECURITY_FINGERPRINTS);
String nfcUserId = intent.getStringExtra(EXTRA_SECURITY_TOKEN_USER_ID);
byte[] nfcAid = intent.getByteArrayExtra(EXTRA_SECURITY_TOKEN_AID);
String nfcUrl = intent.getStringExtra(EXTRA_SECURITY_TOKEN_URL);
if (intent.hasExtra(EXTRA_SECURITY_TOKEN_INFO)) {
SecurityTokenInfo tokenInfo = intent.getParcelableExtra(EXTRA_SECURITY_TOKEN_INFO);
if (containsKeys(nfcFingerprints)) {
Fragment frag = ManageSecurityTokenFragment.newInstance(
nfcFingerprints, nfcAid, nfcUserId, nfcUrl);
if (!tokenInfo.isEmpty()) {
Fragment frag = ManageSecurityTokenFragment.newInstance(tokenInfo);
loadFragment(frag, FragAction.START);
setTitle(R.string.title_import_keys);
} else {
Fragment frag = CreateSecurityTokenBlankFragment.newInstance(nfcAid);
Fragment frag = CreateSecurityTokenBlankFragment.newInstance();
loadFragment(frag, FragAction.START);
setTitle(R.string.title_manage_my_keys);
}
@ -163,10 +146,7 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
return;
}
mScannedFingerprints = mSecurityTokenHelper.getFingerprints();
mSecurityTokenAid = mSecurityTokenHelper.getAid();
mSecurityTokenUserId = mSecurityTokenHelper.getUserId();
mSecurityTokenUrl = mSecurityTokenHelper.getUrl();
tokenInfo = mSecurityTokenHelper.getTokenInfo();
}
@Override
@ -184,30 +164,15 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
CreateSecurityTokenWaitFragment.sDisableFragmentAnimations = false;
}
if (containsKeys(mScannedFingerprints)) {
Fragment frag = ManageSecurityTokenFragment.newInstance(
mScannedFingerprints, mSecurityTokenAid, mSecurityTokenUserId, mSecurityTokenUrl);
if (!tokenInfo.isEmpty()) {
Fragment frag = ManageSecurityTokenFragment.newInstance(tokenInfo);
loadFragment(frag, FragAction.TO_RIGHT);
} else {
Fragment frag = CreateSecurityTokenBlankFragment.newInstance(mSecurityTokenAid);
Fragment frag = CreateSecurityTokenBlankFragment.newInstance();
loadFragment(frag, FragAction.TO_RIGHT);
}
}
private boolean containsKeys(byte[] scannedFingerprints) {
if (scannedFingerprints == null) {
return false;
}
// If all fingerprint bytes are 0, the card contains no keys.
for (byte b : scannedFingerprints) {
if (b != 0) {
return true;
}
}
return false;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@ -218,7 +183,6 @@ public class CreateKeyActivity extends BaseSecurityTokenActivity {
outState.putParcelable(EXTRA_PASSPHRASE, mPassphrase);
outState.putBoolean(EXTRA_FIRST_TIME, mFirstTime);
outState.putBoolean(EXTRA_CREATE_SECURITY_TOKEN, mCreateSecurityToken);
outState.putByteArray(EXTRA_SECURITY_TOKEN_AID, mSecurityTokenAid);
outState.putParcelable(EXTRA_SECURITY_TOKEN_PIN, mSecurityTokenPin);
outState.putParcelable(EXTRA_SECURITY_TOKEN_ADMIN_PIN, mSecurityTokenAdminPin);
}

View file

@ -100,7 +100,7 @@ public class CreateSecurityTokenAlgorithmFragment extends Fragment {
choices.add(new Choice<>(SupportedKeyType.RSA_4096, getResources().getString(
R.string.rsa_4096), getResources().getString(R.string.rsa_4096_description_html)));
final double version = SecurityTokenHelper.parseOpenPgpVersion(mCreateKeyActivity.mSecurityTokenAid);
final double version = SecurityTokenHelper.parseOpenPgpVersion(mCreateKeyActivity.tokenInfo.getAid());
if (version >= 3.0) {
choices.add(new Choice<>(SupportedKeyType.ECC_P256, getResources().getString(

View file

@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
@ -34,20 +35,11 @@ public class CreateSecurityTokenBlankFragment extends Fragment {
View mBackButton;
View mNextButton;
private byte[] mAid;
/**
* Creates new instance of this fragment
*/
public static CreateSecurityTokenBlankFragment newInstance(byte[] aid) {
CreateSecurityTokenBlankFragment frag = new CreateSecurityTokenBlankFragment();
Bundle args = new Bundle();
frag.mAid = aid;
frag.setArguments(args);
return frag;
public static CreateSecurityTokenBlankFragment newInstance() {
return new CreateSecurityTokenBlankFragment();
}
@Override
@ -86,7 +78,6 @@ public class CreateSecurityTokenBlankFragment extends Fragment {
private void nextClicked() {
mCreateKeyActivity.mCreateSecurityToken = true;
mCreateKeyActivity.mSecurityTokenAid = mAid;
CreateKeyNameFragment frag = CreateKeyNameFragment.newInstance();
mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);

View file

@ -201,7 +201,7 @@ public class CreateSecurityTokenPinFragment extends Fragment {
mCreateKeyActivity.mSecurityTokenPin = new Passphrase(mPin.getText().toString());
final double version = SecurityTokenHelper.parseOpenPgpVersion(mCreateKeyActivity.mSecurityTokenAid);
final double version = SecurityTokenHelper.parseOpenPgpVersion(mCreateKeyActivity.tokenInfo.getAid());
Fragment frag;
if (version >= 3.0) {

View file

@ -41,13 +41,10 @@ import nordpol.android.TagDispatcher;
import nordpol.android.TagDispatcherBuilder;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.securitytoken.CardException;
import org.sufficientlysecure.keychain.securitytoken.NfcTransport;
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenHelper;
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
import org.sufficientlysecure.keychain.securitytoken.Transport;
import org.sufficientlysecure.keychain.securitytoken.UsbConnectionDispatcher;
import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransport;
@ -56,10 +53,8 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity;
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity;
import org.sufficientlysecure.keychain.ui.dialog.FidesmoInstallDialog;
import org.sufficientlysecure.keychain.ui.dialog.FidesmoPgpInstallDialog;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.Log;
@ -78,10 +73,7 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
protected UsbConnectionDispatcher mUsbDispatcher;
private boolean mTagHandlingEnabled;
private byte[] mSecurityTokenFingerprints;
private String mSecurityTokenUserId;
private byte[] mSecurityTokenAid;
private String mSecurityTokenUrl;
private SecurityTokenInfo tokenInfo;
/**
* Override to change UI before SecurityToken handling (UI thread)
@ -93,10 +85,8 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
* Override to implement SecurityToken operations (background thread)
*/
protected void doSecurityTokenInBackground() throws IOException {
mSecurityTokenAid = mSecurityTokenHelper.getAid();
mSecurityTokenFingerprints = mSecurityTokenHelper.getFingerprints();
mSecurityTokenUserId = mSecurityTokenHelper.getUserId();
mSecurityTokenUrl = mSecurityTokenHelper.getUrl();
tokenInfo = mSecurityTokenHelper.getTokenInfo();
Log.d(Constants.TAG, "Security Token: " + tokenInfo);
}
/**
@ -104,10 +94,7 @@ public abstract class BaseSecurityTokenActivity extends BaseActivity
*/
protected void onSecurityTokenPostExecute() {
Intent intent = new Intent(this, CreateKeyActivity.class);
intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_FINGERPRINTS, mSecurityTokenFingerprints);
intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_TOKEN_AID, mSecurityTokenAid);
intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_TOKEN_USER_ID, mSecurityTokenUserId);
intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_TOKEN_URL, mSecurityTokenUrl);
intent.putExtra(CreateKeyActivity.EXTRA_SECURITY_TOKEN_INFO, tokenInfo);
startActivity(intent);
}

View file

@ -49,6 +49,7 @@ import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
import org.sufficientlysecure.keychain.service.PromoteKeyringParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
@ -72,10 +73,7 @@ import org.sufficientlysecure.keychain.util.FileHelper;
public class ManageSecurityTokenFragment extends Fragment implements ManageSecurityTokenMvpView,
OnClickListener {
private static final String ARG_FINGERPRINTS = "fingerprint";
private static final String ARG_AID = "aid";
private static final String ARG_USER_ID = "user_ids";
private static final String ARG_URL = "key_uri";
private static final String ARG_TOKEN_INFO = "token_info";
public static final int REQUEST_CODE_OPEN_FILE = 0;
public static final int REQUEST_CODE_RESET = 1;
public static final int PERMISSION_READ_STORAGE = 0;
@ -93,29 +91,29 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur
if (!BuildConfig.DEBUG) {
throw new UnsupportedOperationException("This operation is only available in debug builds!");
}
byte[] scannedFps =
KeyFormattingUtils.convertFingerprintHexFingerprint("1efdb4845ca242ca6977fddb1f788094fd3b430a");
return newInstance(scannedFps, Hex.decode("010203040506"), "yubinu2@mugenguild.com", null);
SecurityTokenInfo securityTokenInfo = SecurityTokenInfo.create(
KeyFormattingUtils.convertFingerprintHexFingerprint("1efdb4845ca242ca6977fddb1f788094fd3b430a"),
new byte[20], new byte[20], Hex.decode("010203040506"),
"yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 3, 3);
return newInstance(securityTokenInfo);
}
public static Fragment newInstanceDebugUri() {
if (!BuildConfig.DEBUG) {
throw new UnsupportedOperationException("This operation is only available in debug builds!");
}
byte[] scannedFps =
KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E");
return newInstance(scannedFps, Hex.decode("010203040506"), "yubinu2@mugenguild.com",
"http://valodim.stratum0.net/mryubinu2.asc");
SecurityTokenInfo securityTokenInfo = SecurityTokenInfo.create(
KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E"),
new byte[20], new byte[20], Hex.decode("010203040506"),
"yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 3, 3);
return newInstance(securityTokenInfo);
}
public static Fragment newInstance(byte[] scannedFingerprints, byte[] nfcAid, String userId, String tokenUrl) {
public static Fragment newInstance(SecurityTokenInfo tokenInfo) {
ManageSecurityTokenFragment frag = new ManageSecurityTokenFragment();
Bundle args = new Bundle();
args.putByteArray(ARG_FINGERPRINTS, scannedFingerprints);
args.putByteArray(ARG_AID, nfcAid);
args.putString(ARG_USER_ID, userId);
args.putString(ARG_URL, tokenUrl);
args.putParcelable(ARG_TOKEN_INFO, tokenInfo);
frag.setArguments(args);
return frag;
@ -126,14 +124,9 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur
super.onCreate(savedInstanceState);
Bundle args = getArguments();
SecurityTokenInfo tokenInfo = args.getParcelable(ARG_TOKEN_INFO);
byte[] tokenFingerprints = args.getByteArray(ARG_FINGERPRINTS);
byte[] tokenAid = args.getByteArray(ARG_AID);
String tokenUserId = args.getString(ARG_USER_ID);
String tokenUrl = args.getString(ARG_URL);
presenter = new ManageSecurityTokenPresenter(
getContext(), tokenFingerprints, tokenAid, tokenUserId, tokenUrl, getLoaderManager());
presenter = new ManageSecurityTokenPresenter(getContext(), getLoaderManager(), tokenInfo);
}
@Override

View file

@ -28,6 +28,7 @@ import android.support.v4.content.Loader;
import org.sufficientlysecure.keychain.operations.results.GenericOperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
import org.sufficientlysecure.keychain.ui.token.ManageSecurityTokenContract.ManageSecurityTokenMvpPresenter;
import org.sufficientlysecure.keychain.ui.token.ManageSecurityTokenContract.ManageSecurityTokenMvpView;
import org.sufficientlysecure.keychain.ui.token.ManageSecurityTokenFragment.StatusLine;
@ -49,11 +50,7 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
private final Context context;
private final LoaderManager loaderManager;
private final byte[][] tokenFingerprints;
private final byte[] tokenAid;
private final String tokenUserId;
private final String tokenUrl;
private final SecurityTokenInfo tokenInfo;
private ManageSecurityTokenMvpView view;
@ -68,23 +65,10 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
private OperationLog log;
private Uri selectedContentUri;
ManageSecurityTokenPresenter(Context context, byte[] tokenFingerprints, byte[] tokenAid,
String tokenUserId, String tokenUrl, LoaderManager loaderManager) {
ManageSecurityTokenPresenter(Context context, LoaderManager loaderManager, SecurityTokenInfo tokenInfo) {
this.context = context.getApplicationContext();
this.tokenAid = tokenAid;
this.tokenUserId = tokenUserId;
this.tokenUrl = tokenUrl;
this.loaderManager = loaderManager;
if (tokenFingerprints.length % 20 != 0) {
throw new IllegalArgumentException("fingerprints must be multiple of 20 bytes!");
}
this.tokenFingerprints = new byte[tokenFingerprints.length / 20][];
for (int i = 0; i < tokenFingerprints.length / 20; i++) {
this.tokenFingerprints[i] = new byte[20];
System.arraycopy(tokenFingerprints, i*20, this.tokenFingerprints[i], 0, 20);
}
this.tokenInfo = tokenInfo;
this.log = new OperationLog();
}
@ -133,13 +117,13 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
public Loader<KeyRetrievalResult> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_LOCAL:
return new LocalKeyLookupLoader(context, tokenFingerprints);
return new LocalKeyLookupLoader(context, tokenInfo.getAllFingerprints());
case LOADER_URI:
return new UriKeyRetrievalLoader(context, tokenUrl, tokenFingerprints);
return new UriKeyRetrievalLoader(context, tokenInfo.getUrl(), tokenInfo.getAllFingerprints());
case LOADER_KEYSERVER:
return new KeyserverRetrievalLoader(context, tokenFingerprints[0]);
return new KeyserverRetrievalLoader(context, tokenInfo.getFingerprintSign());
case LOADER_CONTENT_URI:
return new ContentUriRetrievalLoader(context, tokenFingerprints[0],
return new ContentUriRetrievalLoader(context, tokenInfo.getFingerprintSign(),
args.<Uri>getParcelable(ARG_CONTENT_URI));
}
throw new IllegalArgumentException("called with unknown loader id!");
@ -203,7 +187,7 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
if (masterKeyId != null) {
this.masterKeyId = masterKeyId;
view.statusLineAdd(StatusLine.TOKEN_CHECK);
view.operationPromote(masterKeyId, tokenAid);
view.operationPromote(masterKeyId, tokenInfo.getAid());
return;
}
@ -223,7 +207,7 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
view.statusLineOk();
view.statusLineAdd(StatusLine.TOKEN_PROMOTE);
view.operationPromote(masterKeyId, tokenAid);
view.operationPromote(masterKeyId, tokenInfo.getAid());
}
@Override