improve status reporting in yubikey dialogue

This commit is contained in:
Vincent Breitmoser 2015-03-22 03:34:34 +01:00
parent a7c52a1c9f
commit 22063cdd6e
3 changed files with 114 additions and 14 deletions

View File

@ -1,35 +1,48 @@
package org.sufficientlysecure.keychain.ui;
import java.nio.ByteBuffer;
import java.util.Arrays;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import org.spongycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
public class ViewKeyYubikeyFragment extends Fragment {
public class ViewKeyYubikeyFragment extends Fragment
implements LoaderCallbacks<Cursor> {
public static final String ARG_FINGERPRINT = "fingerprint";
public static final String ARG_USER_ID = "user_id";
public static final String ARG_AID = "aid";
private byte[] mFingerprints;
private byte[][] mFingerprints;
private String mUserId;
private byte[] mAid;
private long mMasterKeyId;
private Button vButton;
private TextView vStatus;
public static ViewKeyYubikeyFragment newInstance(byte[] fingerprints, String userId, byte[] aid) {
@ -50,10 +63,19 @@ public class ViewKeyYubikeyFragment extends Fragment {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
mFingerprints = args.getByteArray(ARG_FINGERPRINT);
ByteBuffer buf = ByteBuffer.wrap(args.getByteArray(ARG_FINGERPRINT));
mFingerprints = new byte[buf.remaining()/40][];
for (int i = 0; i < mFingerprints.length; i++) {
mFingerprints[i] = new byte[20];
buf.get(mFingerprints[i]);
}
mUserId = args.getString(ARG_USER_ID);
mAid = args.getByteArray(ARG_AID);
mMasterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mFingerprints[0]);
getLoaderManager().initLoader(0, null, this);
}
@Override
@ -64,21 +86,23 @@ public class ViewKeyYubikeyFragment extends Fragment {
TextView vUserId = (TextView) view.findViewById(R.id.yubikey_userid);
String serno = Hex.toHexString(mAid, 10, 4);
vSerNo.setText("Serial N° " + serno);
vSerNo.setText(getString(R.string.yubikey_serno, serno));
if (!mUserId.isEmpty()) {
vUserId.setText("Key holder: " + mUserId);
vUserId.setText(getString(R.string.yubikey_key_holder, mUserId));
} else {
vUserId.setText("Key holder: " + "<unset>");
vUserId.setText(getString(R.string.yubikey_key_holder_unset));
}
view.findViewById(R.id.button_import).setOnClickListener(new OnClickListener() {
vButton = (Button) view.findViewById(R.id.button_bind);
vButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
promoteToSecretKey();
}
});
vStatus = (TextView) view.findViewById(R.id.yubikey_status);
return view;
}
@ -111,10 +135,8 @@ public class ViewKeyYubikeyFragment extends Fragment {
intent.setAction(KeychainIntentService.ACTION_PROMOTE_KEYRING);
long masterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mFingerprints);
Bundle data = new Bundle();
data.putLong(KeychainIntentService.PROMOTE_MASTER_KEY_ID, masterKeyId);
data.putLong(KeychainIntentService.PROMOTE_MASTER_KEY_ID, mMasterKeyId);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
// Create a new Messenger for the communication back
@ -126,4 +148,73 @@ public class ViewKeyYubikeyFragment extends Fragment {
}
public static final String[] PROJECTION = new String[]{
Keys._ID,
Keys.KEY_ID,
Keys.RANK,
Keys.HAS_SECRET,
Keys.FINGERPRINT
};
private static final int INDEX_KEY_ID = 1;
private static final int INDEX_RANK = 2;
private static final int INDEX_HAS_SECRET = 3;
private static final int INDEX_FINGERPRINT = 4;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), Keys.buildKeysUri(mMasterKeyId),
PROJECTION, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (!data.moveToFirst()) {
// wut?
return;
}
boolean allBound = true;
boolean noneBound = true;
do {
SecretKeyType keyType = SecretKeyType.fromNum(data.getInt(INDEX_HAS_SECRET));
byte[] fingerprint = data.getBlob(INDEX_FINGERPRINT);
Integer index = naiveIndexOf(mFingerprints, fingerprint);
if (index == null) {
continue;
}
if (keyType == SecretKeyType.DIVERT_TO_CARD) {
noneBound = false;
} else {
allBound = false;
}
} while (data.moveToNext());
if (allBound) {
vButton.setVisibility(View.GONE);
vStatus.setText("Key matches, fully bound");
} else {
vButton.setVisibility(View.VISIBLE);
if (noneBound) {
vStatus.setText("Key matches, can be bound");
} else {
vStatus.setText("Key matches, partly bound");
}
}
}
public Integer naiveIndexOf(byte[][] haystack, byte[] needle) {
for (int i = 0; i < haystack.length; i++) {
if (Arrays.equals(needle, haystack[i])) {
return i;
}
}
return null;
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
}

View File

@ -21,7 +21,8 @@
card_view:cardBackgroundColor="@android:color/white"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true"
card_view:cardCornerRadius="4dp">
card_view:cardCornerRadius="4dp"
android:animateLayoutChanges="true">
<LinearLayout
android:layout_width="match_parent"
@ -37,6 +38,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:orientation="horizontal">
<ImageView
@ -69,6 +72,7 @@
/>
<TextView
android:id="@+id/yubikey_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
@ -80,13 +84,14 @@
</LinearLayout>
<Button
android:id="@+id/button_import"
android:id="@+id/button_bind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|end"
android:text="Import"
android:text="@string/button_bind_key"
android:textColor="@color/link_text_material_light"
style="?android:attr/borderlessButtonStyle"
android:visibility="gone"
/>
</LinearLayout>

View File

@ -1269,5 +1269,9 @@
<string name="unlocked">Unlocked</string>
<string name="nfc_settings">Settings</string>
<string name="snack_yubikey_view">View</string>
<string name="button_bind_key">Bind Key</string>
<string name="yubikey_serno">"Serial No: %s"</string>
<string name="yubikey_key_holder">"Key holder: "</string>
<string name="yubikey_key_holder_unset">"Key holder: &lt;unset&gt;"</string>
</resources>