token-import: use entire fingerprint for promote operation
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user