token-import: use entire fingerprint for promote operation

This commit is contained in:
Vincent Breitmoser
2017-09-11 14:54:06 +02:00
parent 10eeb5672b
commit 863651918e
11 changed files with 80 additions and 89 deletions

View File

@@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.operations;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import android.content.Context; import android.content.Context;
@@ -71,30 +72,24 @@ public class PromoteKeyOperation extends BaseReadWriteOperation<PromoteKeyringPa
CanonicalizedPublicKeyRing pubRing = CanonicalizedPublicKeyRing pubRing =
mKeyRepository.getCanonicalizedPublicKeyRing(promoteKeyringParcel.getMasterKeyId()); mKeyRepository.getCanonicalizedPublicKeyRing(promoteKeyringParcel.getMasterKeyId());
long[] subKeyIds = promoteKeyringParcel.getSubKeyIds(); List<byte[]> fingerprints = promoteKeyringParcel.getFingerprints();
if (subKeyIds == null) { if (fingerprints == null) {
log.add(LogType.MSG_PR_ALL, 1); log.add(LogType.MSG_PR_ALL, 1);
} else { } else {
// sort for binary search // sort for binary search
for (CanonicalizedPublicKey key : pubRing.publicKeyIterator()) { for (CanonicalizedPublicKey key : pubRing.publicKeyIterator()) {
long subKeyId = key.getKeyId(); long subKeyId = key.getKeyId();
// we ignore key ids from empty fingerprints here if (naiveArraySearch(fingerprints, key.getFingerprint())) {
if (subKeyId == 0L) { log.add(LogType.MSG_PR_SUBKEY_MATCH, 1, KeyFormattingUtils.convertKeyIdToHex(subKeyId));
continue;
}
if (naiveIndexOf(subKeyIds, subKeyId) != null) {
log.add(LogType.MSG_PR_SUBKEY_MATCH, 1,
KeyFormattingUtils.convertKeyIdToHex(subKeyId));
} else { } else {
log.add(LogType.MSG_PR_SUBKEY_NOMATCH, 1, log.add(LogType.MSG_PR_SUBKEY_NOMATCH, 1, KeyFormattingUtils.convertKeyIdToHex(subKeyId));
KeyFormattingUtils.convertKeyIdToHex(subKeyId));
} }
} }
} }
// create divert-to-card secret key from public key // create divert-to-card secret key from public key
promotedRing = pubRing.createDivertSecretRing(promoteKeyringParcel.getCardAid(), subKeyIds); promotedRing = pubRing.createDivertSecretRing(promoteKeyringParcel.getCardAid(), fingerprints);
} catch (NotFoundException e) { } catch (NotFoundException e) {
log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2); log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2);
@@ -134,13 +129,13 @@ public class PromoteKeyOperation extends BaseReadWriteOperation<PromoteKeyringPa
} }
static private Integer naiveIndexOf(long[] haystack, long needle) { static private boolean naiveArraySearch(List<byte[]> searchElements, byte[] needle) {
for (int i = 0; i < haystack.length; i++) { for (byte[] searchElement : searchElements) {
if (needle == haystack[i]) { if (Arrays.equals(needle, searchElement)) {
return i; return true;
} }
} }
return null; return false;
} }
} }

View File

@@ -20,7 +20,9 @@ package org.sufficientlysecure.keychain.pgp;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
@@ -32,6 +34,7 @@ import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.IterableIterator;
@@ -153,19 +156,19 @@ public class CanonicalizedPublicKeyRing extends CanonicalizedKeyRing {
} }
/** Create a dummy secret ring from this key */ /** Create a dummy secret ring from this key */
public UncachedKeyRing createDivertSecretRing (byte[] cardAid, long[] subKeyIds) { public UncachedKeyRing createDivertSecretRing(byte[] cardAid, List<byte[]> subKeyFingerprints) {
PGPSecretKeyRing secRing = PGPSecretKeyRing.constructDummyFromPublic(getRing(), cardAid); PGPSecretKeyRing secRing = PGPSecretKeyRing.constructDummyFromPublic(getRing(), cardAid);
if (subKeyIds == null) { if (subKeyFingerprints == null) {
return new UncachedKeyRing(secRing); return new UncachedKeyRing(secRing);
} }
// if only specific subkeys should be promoted, construct a // if only specific subkeys should be promoted, construct a
// stripped dummy, then move divert-to-card keys over // stripped dummy, then move divert-to-card keys over
PGPSecretKeyRing newRing = PGPSecretKeyRing.constructDummyFromPublic(getRing()); PGPSecretKeyRing newRing = PGPSecretKeyRing.constructDummyFromPublic(getRing());
for (long subKeyId : subKeyIds) { for (byte[] subKeyFingerprint : subKeyFingerprints) {
PGPSecretKey key = secRing.getSecretKey(subKeyId); PGPSecretKey key = secRing.getSecretKey(KeyFormattingUtils.convertFingerprintToKeyId(subKeyFingerprint));
if (key != null) { if (key != null && Arrays.equals(subKeyFingerprint, key.getPublicKey().getFingerprint())) {
newRing = PGPSecretKeyRing.insertSecretKey(newRing, key); newRing = PGPSecretKeyRing.insertSecretKey(newRing, key);
} }
} }

View File

@@ -32,6 +32,7 @@ import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.TreeSet; import java.util.TreeSet;
@@ -171,7 +172,7 @@ public class UncachedKeyRing {
} }
public boolean containsKeyWithAnyFingerprint(byte[]... expectedFingerprints) { public boolean containsKeyWithAnyFingerprint(List<byte[]> expectedFingerprints) {
Iterator<UncachedPublicKey> publicKeys = getPublicKeys(); Iterator<UncachedPublicKey> publicKeys = getPublicKeys();
while (publicKeys.hasNext()) { while (publicKeys.hasNext()) {

View File

@@ -979,22 +979,21 @@ public class SecurityTokenHelper {
} }
public SecurityTokenInfo getTokenInfo() throws IOException { public SecurityTokenInfo getTokenInfo() throws IOException {
byte[] fingerprints = getFingerprints(); byte[] rawFingerprints = getFingerprints();
byte[] fpSign = new byte[20]; byte[][] fingerprints = new byte[rawFingerprints.length / 20][];
byte[] fpDecrypt = new byte[20]; ByteBuffer buf = ByteBuffer.wrap(rawFingerprints);
byte[] fpAuth = new byte[20]; for (int i = 0; i < rawFingerprints.length / 20; i++) {
ByteBuffer buf = ByteBuffer.wrap(fingerprints); fingerprints[i] = new byte[20];
buf.get(fpSign); buf.get(fingerprints[i]);
buf.get(fpDecrypt); }
buf.get(fpAuth);
byte[] aid = getAid(); byte[] aid = getAid();
String userId = getUserId(); String userId = getUserId();
String url = getUrl(); String url = getUrl();
byte[] pwInfo = getPwStatusBytes(); byte[] pwInfo = getPwStatusBytes();
return SecurityTokenInfo.create(fpSign, fpDecrypt, fpAuth, aid, userId, url, pwInfo[4], pwInfo[6]); return SecurityTokenInfo.create(fingerprints, aid, userId, url, pwInfo[4], pwInfo[6]);
} }
private static class LazyHolder { private static class LazyHolder {

View File

@@ -1,7 +1,9 @@
package org.sufficientlysecure.keychain.securitytoken; package org.sufficientlysecure.keychain.securitytoken;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import android.os.Parcelable; import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
@@ -16,12 +18,7 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
public abstract class SecurityTokenInfo implements Parcelable { public abstract class SecurityTokenInfo implements Parcelable {
private static final byte[] EMPTY_ARRAY = new byte[20]; private static final byte[] EMPTY_ARRAY = new byte[20];
@Nullable public abstract List<byte[]> getFingerprints();
public abstract byte[] getFingerprintSign();
@Nullable
public abstract byte[] getFingerprintDecrypt();
@Nullable
public abstract byte[] getFingerprintAuth();
@Nullable @Nullable
public abstract byte[] getAid(); public abstract byte[] getAid();
@Nullable @Nullable
@@ -31,23 +28,19 @@ public abstract class SecurityTokenInfo implements Parcelable {
public abstract int getVerifyRetries(); public abstract int getVerifyRetries();
public abstract int getVerifyAdminRetries(); 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() { public boolean isEmpty() {
return Arrays.equals(EMPTY_ARRAY, getFingerprintSign()) && Arrays.equals(EMPTY_ARRAY, getFingerprintDecrypt()) && return getFingerprints().isEmpty();
Arrays.equals(EMPTY_ARRAY, getFingerprintAuth());
} }
public static SecurityTokenInfo create(byte[] fpSign, byte[] fpDecrypt, byte[] fpAuth, public static SecurityTokenInfo create(byte[][] fingerprints, byte[] aid, String userId, String url,
byte[] aid, String userId, String url, int verifyRetries, int verifyAdminRetries) { int verifyRetries, int verifyAdminRetries) {
return new AutoValue_SecurityTokenInfo(fpSign, fpDecrypt, fpAuth, aid, ArrayList<byte[]> fingerprintList = new ArrayList<>(fingerprints.length);
userId, url, verifyRetries, verifyAdminRetries); for (byte[] fingerprint : fingerprints) {
if (!Arrays.equals(EMPTY_ARRAY, fingerprint)) {
fingerprintList.add(fingerprint);
}
}
return new AutoValue_SecurityTokenInfo(fingerprintList, aid, userId, url, verifyRetries, verifyAdminRetries);
} }
public static SecurityTokenInfo newInstanceDebugKeyserver() { public static SecurityTokenInfo newInstanceDebugKeyserver() {
@@ -55,8 +48,8 @@ public abstract class SecurityTokenInfo implements Parcelable {
throw new UnsupportedOperationException("This operation is only available in debug builds!"); throw new UnsupportedOperationException("This operation is only available in debug builds!");
} }
return SecurityTokenInfo.create( return SecurityTokenInfo.create(
KeyFormattingUtils.convertFingerprintHexFingerprint("1efdb4845ca242ca6977fddb1f788094fd3b430a"), new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("1efdb4845ca242ca6977fddb1f788094fd3b430a") },
new byte[20], new byte[20], Hex.decode("010203040506"), "yubinu2@mugenguild.com", null, 3, 3); Hex.decode("010203040506"), "yubinu2@mugenguild.com", null, 3, 3);
} }
public static SecurityTokenInfo newInstanceDebugUri() { public static SecurityTokenInfo newInstanceDebugUri() {
@@ -64,9 +57,8 @@ public abstract class SecurityTokenInfo implements Parcelable {
throw new UnsupportedOperationException("This operation is only available in debug builds!"); throw new UnsupportedOperationException("This operation is only available in debug builds!");
} }
return SecurityTokenInfo.create( return SecurityTokenInfo.create(
KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E"), new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E") },
new byte[20], new byte[20], Hex.decode("010203040506"), Hex.decode("010203040506"), "yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 3, 3);
"yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 3, 3);
} }
public static SecurityTokenInfo newInstanceDebugLocked() { public static SecurityTokenInfo newInstanceDebugLocked() {
@@ -74,9 +66,8 @@ public abstract class SecurityTokenInfo implements Parcelable {
throw new UnsupportedOperationException("This operation is only available in debug builds!"); throw new UnsupportedOperationException("This operation is only available in debug builds!");
} }
return SecurityTokenInfo.create( return SecurityTokenInfo.create(
KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E"), new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E") },
new byte[20], new byte[20], Hex.decode("010203040506"), Hex.decode("010203040506"), "yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 0, 3);
"yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 0, 3);
} }
public static SecurityTokenInfo newInstanceDebugLockedHard() { public static SecurityTokenInfo newInstanceDebugLockedHard() {
@@ -84,9 +75,8 @@ public abstract class SecurityTokenInfo implements Parcelable {
throw new UnsupportedOperationException("This operation is only available in debug builds!"); throw new UnsupportedOperationException("This operation is only available in debug builds!");
} }
return SecurityTokenInfo.create( return SecurityTokenInfo.create(
KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E"), new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E") },
new byte[20], new byte[20], Hex.decode("010203040506"), Hex.decode("010203040506"), "yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 0, 0);
"yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 0, 0);
} }
} }

View File

@@ -20,11 +20,12 @@
package org.sufficientlysecure.keychain.service; package org.sufficientlysecure.keychain.service;
import java.util.List;
import android.os.Parcelable; import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue; import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo;
@AutoValue @AutoValue
@@ -35,10 +36,10 @@ public abstract class PromoteKeyringParcel implements Parcelable {
public abstract byte[] getCardAid(); public abstract byte[] getCardAid();
@Nullable @Nullable
@SuppressWarnings("mutable") @SuppressWarnings("mutable")
public abstract long[] getSubKeyIds(); public abstract List<byte[]> getFingerprints();
public static PromoteKeyringParcel createPromoteKeyringParcel(long keyRingId, byte[] cardAid, public static PromoteKeyringParcel createPromoteKeyringParcel(long keyRingId, byte[] cardAid,
@Nullable long[] subKeyIds) { @Nullable List<byte[]> fingerprints) {
return new AutoValue_PromoteKeyringParcel(keyRingId, cardAid, subKeyIds); return new AutoValue_PromoteKeyringParcel(keyRingId, cardAid, fingerprints);
} }
} }

View File

@@ -18,6 +18,8 @@
package org.sufficientlysecure.keychain.ui.token; package org.sufficientlysecure.keychain.ui.token;
import java.util.List;
import android.net.Uri; import android.net.Uri;
import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult;
@@ -79,7 +81,7 @@ class ManageSecurityTokenContract {
void hideAction(); void hideAction();
void operationImportKey(byte[] importKeyData); void operationImportKey(byte[] importKeyData);
void operationPromote(long masterKeyId, byte[] cardAid, long[] subKeyIds); void operationPromote(long masterKeyId, byte[] cardAid, List<byte[]> fingerprints);
void operationResetSecurityToken(); void operationResetSecurityToken();
void operationChangePinSecurityToken(String adminPin, String newPin); void operationChangePinSecurityToken(String adminPin, String newPin);

View File

@@ -18,6 +18,8 @@
package org.sufficientlysecure.keychain.ui.token; package org.sufficientlysecure.keychain.ui.token;
import java.util.List;
import android.Manifest; import android.Manifest;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.Activity; import android.app.Activity;
@@ -277,12 +279,13 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur
} }
@Override @Override
public void operationPromote(long masterKeyId, byte[] cardAid, long[] subkeys) { public void operationPromote(long masterKeyId, byte[] cardAid, List<byte[]> fingerprints) {
if (currentImportKeyringParcel != null) { if (currentImportKeyringParcel != null) {
throw new IllegalStateException("Cannot trigger import operation twice!"); throw new IllegalStateException("Cannot trigger import operation twice!");
} }
currentPromoteKeyringParcel = PromoteKeyringParcel.createPromoteKeyringParcel(masterKeyId, cardAid, subkeys); currentPromoteKeyringParcel = PromoteKeyringParcel.createPromoteKeyringParcel(
masterKeyId, cardAid, fingerprints);
cryptoPromoteOperationHelper.setOperationMinimumDelay(1000L); cryptoPromoteOperationHelper.setOperationMinimumDelay(1000L);
cryptoPromoteOperationHelper.cryptoOperation(); cryptoPromoteOperationHelper.cryptoOperation();
} }

View File

@@ -38,7 +38,6 @@ import org.sufficientlysecure.keychain.ui.token.PublicKeyRetrievalLoader.KeyRetr
import org.sufficientlysecure.keychain.ui.token.PublicKeyRetrievalLoader.KeyserverRetrievalLoader; import org.sufficientlysecure.keychain.ui.token.PublicKeyRetrievalLoader.KeyserverRetrievalLoader;
import org.sufficientlysecure.keychain.ui.token.PublicKeyRetrievalLoader.LocalKeyLookupLoader; import org.sufficientlysecure.keychain.ui.token.PublicKeyRetrievalLoader.LocalKeyLookupLoader;
import org.sufficientlysecure.keychain.ui.token.PublicKeyRetrievalLoader.UriKeyRetrievalLoader; import org.sufficientlysecure.keychain.ui.token.PublicKeyRetrievalLoader.UriKeyRetrievalLoader;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.PermissionsUtil; import org.sufficientlysecure.keychain.ui.util.PermissionsUtil;
@@ -207,13 +206,13 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
public Loader<KeyRetrievalResult> onCreateLoader(int id, Bundle args) { public Loader<KeyRetrievalResult> onCreateLoader(int id, Bundle args) {
switch (id) { switch (id) {
case LOADER_LOCAL: case LOADER_LOCAL:
return new LocalKeyLookupLoader(context, tokenInfo.getAllFingerprints()); return new LocalKeyLookupLoader(context, tokenInfo.getFingerprints());
case LOADER_URI: case LOADER_URI:
return new UriKeyRetrievalLoader(context, tokenInfo.getUrl(), tokenInfo.getAllFingerprints()); return new UriKeyRetrievalLoader(context, tokenInfo.getUrl(), tokenInfo.getFingerprints());
case LOADER_KEYSERVER: case LOADER_KEYSERVER:
return new KeyserverRetrievalLoader(context, tokenInfo.getAllFingerprints()); return new KeyserverRetrievalLoader(context, tokenInfo.getFingerprints());
case LOADER_CONTENT_URI: case LOADER_CONTENT_URI:
return new ContentUriRetrievalLoader(context, tokenInfo.getAllFingerprints(), return new ContentUriRetrievalLoader(context, tokenInfo.getFingerprints(),
args.<Uri>getParcelable(ARG_CONTENT_URI)); args.<Uri>getParcelable(ARG_CONTENT_URI));
} }
throw new IllegalArgumentException("called with unknown loader id!"); throw new IllegalArgumentException("called with unknown loader id!");
@@ -286,10 +285,7 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter {
} }
private void promoteKeyWithTokenInfo(Long masterKeyId) { private void promoteKeyWithTokenInfo(Long masterKeyId) {
long signKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(tokenInfo.getFingerprintSign()); view.operationPromote(masterKeyId, tokenInfo.getAid(), tokenInfo.getFingerprints());
long decryptKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(tokenInfo.getFingerprintDecrypt());
long authKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(tokenInfo.getFingerprintAuth());
view.operationPromote(masterKeyId, tokenInfo.getAid(), new long[] { signKeyId, decryptKeyId, authKeyId });
} }
@Override @Override

View File

@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui.token;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
@@ -64,10 +65,10 @@ public abstract class PublicKeyRetrievalLoader extends AsyncTaskLoader<KeyRetrie
private KeyRetrievalResult cachedResult; private KeyRetrievalResult cachedResult;
protected final byte[][] fingerprints; protected final List<byte[]> fingerprints;
private PublicKeyRetrievalLoader(Context context, byte[][] fingerprints) { private PublicKeyRetrievalLoader(Context context, List<byte[]> fingerprints) {
super(context); super(context);
this.fingerprints = fingerprints; this.fingerprints = fingerprints;
@@ -94,7 +95,7 @@ public abstract class PublicKeyRetrievalLoader extends AsyncTaskLoader<KeyRetrie
static class LocalKeyLookupLoader extends PublicKeyRetrievalLoader { static class LocalKeyLookupLoader extends PublicKeyRetrievalLoader {
private final KeyRepository keyRepository; private final KeyRepository keyRepository;
LocalKeyLookupLoader(Context context, byte[][] fingerprints) { LocalKeyLookupLoader(Context context, List<byte[]> fingerprints) {
super(context, fingerprints); super(context, fingerprints);
this.keyRepository = KeyRepository.createDatabaseInteractor(context); this.keyRepository = KeyRepository.createDatabaseInteractor(context);
@@ -158,7 +159,7 @@ public abstract class PublicKeyRetrievalLoader extends AsyncTaskLoader<KeyRetrie
static class UriKeyRetrievalLoader extends PublicKeyRetrievalLoader { static class UriKeyRetrievalLoader extends PublicKeyRetrievalLoader {
private final String tokenUri; private final String tokenUri;
UriKeyRetrievalLoader(Context context, String tokenUri, byte[][] fingerprints) { UriKeyRetrievalLoader(Context context, String tokenUri, List<byte[]> fingerprints) {
super(context, fingerprints); super(context, fingerprints);
this.tokenUri = tokenUri; this.tokenUri = tokenUri;
@@ -211,7 +212,7 @@ public abstract class PublicKeyRetrievalLoader extends AsyncTaskLoader<KeyRetrie
} }
static class KeyserverRetrievalLoader extends PublicKeyRetrievalLoader { static class KeyserverRetrievalLoader extends PublicKeyRetrievalLoader {
KeyserverRetrievalLoader(Context context, byte[][] fingerprints) { KeyserverRetrievalLoader(Context context, List<byte[]> fingerprints) {
super(context, fingerprints); super(context, fingerprints);
} }
@@ -228,7 +229,7 @@ public abstract class PublicKeyRetrievalLoader extends AsyncTaskLoader<KeyRetrie
log.add(LogType.MSG_RET_KS_START, 0); log.add(LogType.MSG_RET_KS_START, 0);
String keyString = keyserverClient.get( String keyString = keyserverClient.get(
"0x" + KeyFormattingUtils.convertFingerprintToHex(fingerprints[0]), parcelableProxy); "0x" + KeyFormattingUtils.convertFingerprintToHex(fingerprints.get(0)), parcelableProxy);
UncachedKeyRing keyRing = UncachedKeyRing.decodeFromData(keyString.getBytes()); UncachedKeyRing keyRing = UncachedKeyRing.decodeFromData(keyString.getBytes());
if (!keyRing.containsKeyWithAnyFingerprint(fingerprints)) { if (!keyRing.containsKeyWithAnyFingerprint(fingerprints)) {
@@ -255,7 +256,7 @@ public abstract class PublicKeyRetrievalLoader extends AsyncTaskLoader<KeyRetrie
private final ContentResolver contentResolver; private final ContentResolver contentResolver;
private final Uri uri; private final Uri uri;
ContentUriRetrievalLoader(Context context, byte[][] fingerprints, Uri uri) { ContentUriRetrievalLoader(Context context, List<byte[]> fingerprints, Uri uri) {
super(context, fingerprints); super(context, fingerprints);
this.uri = uri; this.uri = uri;

View File

@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.operations;
import java.io.PrintStream; import java.io.PrintStream;
import java.security.Security; import java.security.Security;
import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import org.bouncycastle.bcpg.sig.KeyFlags; import org.bouncycastle.bcpg.sig.KeyFlags;
@@ -164,9 +165,8 @@ public class PromoteKeyOperationTest {
long keyId = KeyringTestingHelper.getSubkeyId(mStaticRing, 1); long keyId = KeyringTestingHelper.getSubkeyId(mStaticRing, 1);
PromoteKeyResult result = op.execute( PromoteKeyResult result = op.execute(
PromoteKeyringParcel.createPromoteKeyringParcel(mStaticRing.getMasterKeyId(), aid, new long[] { PromoteKeyringParcel.createPromoteKeyringParcel(mStaticRing.getMasterKeyId(), aid,
keyId Arrays.asList(mStaticRing.getPublicKey(keyId).getFingerprint())), null);
}), null);
Assert.assertTrue("promotion must succeed", result.success()); Assert.assertTrue("promotion must succeed", result.success());