extract database access from CachedPublicKeyRing
This commit is contained in:
parent
aa640f3227
commit
31830a8c86
|
@ -24,24 +24,21 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.os.CancellationSignal;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.operations.results.ExportResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
|
@ -56,14 +53,13 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
|||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
|
||||
import org.sufficientlysecure.keychain.provider.TemporaryFileProvider;
|
||||
import org.sufficientlysecure.keychain.service.BackupKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.util.Numeric9x4PassphraseUtil;
|
||||
import org.sufficientlysecure.keychain.util.CountingOutputStream;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
import org.sufficientlysecure.keychain.util.Numeric9x4PassphraseUtil;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
@ -84,8 +80,6 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
|||
KeyRings.MASTER_KEY_ID,
|
||||
KeyRings.HAS_ANY_SECRET
|
||||
};
|
||||
private static final int INDEX_MASTER_KEY_ID = 0;
|
||||
private static final int INDEX_HAS_ANY_SECRET = 1;
|
||||
|
||||
// this is a very simple matcher, we only need basic sanitization
|
||||
private static final Pattern HEADER_PATTERN = Pattern.compile("[a-zA-Z0-9_-]+: [^\\n]+");
|
||||
|
@ -224,42 +218,36 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
|||
OutputStream outStream, List<String> extraSecretKeyHeaders) {
|
||||
// noinspection unused TODO use these in a log entry
|
||||
int okSecret = 0, okPublic = 0;
|
||||
|
||||
int progress = 0;
|
||||
|
||||
Cursor cursor = queryForKeys(masterKeyIds);
|
||||
|
||||
if (cursor == null || !cursor.moveToFirst()) {
|
||||
log.add(LogType.MSG_BACKUP_ERROR_DB, 1);
|
||||
return false; // new ExportResult(ExportResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
int numKeys = cursor.getCount();
|
||||
List<UnifiedKeyInfo> unifiedKeyInfos;
|
||||
if (masterKeyIds == null) {
|
||||
unifiedKeyInfos = mKeyRepository.getAllUnifiedKeyInfo();
|
||||
} else {
|
||||
unifiedKeyInfos = mKeyRepository.getUnifiedKeyInfo(masterKeyIds);
|
||||
}
|
||||
int numKeys = unifiedKeyInfos.size();
|
||||
|
||||
updateProgress(mContext.getResources().getQuantityString(R.plurals.progress_exporting_key, numKeys),
|
||||
0, numKeys);
|
||||
|
||||
// For each public masterKey id
|
||||
while (!cursor.isAfterLast()) {
|
||||
|
||||
long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);
|
||||
log.add(LogType.MSG_BACKUP_PUBLIC, 1, KeyFormattingUtils.beautifyKeyId(masterKeyId));
|
||||
for (UnifiedKeyInfo keyInfo : unifiedKeyInfos) {
|
||||
log.add(LogType.MSG_BACKUP_PUBLIC, 1, KeyFormattingUtils.beautifyKeyId(keyInfo.master_key_id()));
|
||||
|
||||
boolean publicKeyWriteOk = false;
|
||||
if (exportPublic) {
|
||||
publicKeyWriteOk = writePublicKeyToStream(masterKeyId, log, outStream);
|
||||
publicKeyWriteOk = writePublicKeyToStream(keyInfo.master_key_id(), log, outStream);
|
||||
if (publicKeyWriteOk) {
|
||||
okPublic += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (publicKeyWriteOk || !exportPublic) {
|
||||
boolean hasSecret = cursor.getInt(INDEX_HAS_ANY_SECRET) > 0;
|
||||
if (exportSecret && hasSecret) {
|
||||
log.add(LogType.MSG_BACKUP_SECRET, 2, KeyFormattingUtils.beautifyKeyId(masterKeyId));
|
||||
if (writeSecretKeyToStream(masterKeyId, log, outStream, extraSecretKeyHeaders)) {
|
||||
if (exportSecret && keyInfo.has_any_secret()) {
|
||||
log.add(LogType.MSG_BACKUP_SECRET, 2, KeyFormattingUtils.beautifyKeyId(keyInfo.master_key_id()));
|
||||
if (writeSecretKeyToStream(keyInfo.master_key_id(), log, outStream, extraSecretKeyHeaders)) {
|
||||
okSecret += 1;
|
||||
}
|
||||
extraSecretKeyHeaders = null;
|
||||
|
@ -267,7 +255,6 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
|||
}
|
||||
|
||||
updateProgress(progress++, numKeys);
|
||||
cursor.moveToNext();
|
||||
}
|
||||
|
||||
updateProgress(R.string.progress_done, numKeys, numKeys);
|
||||
|
@ -282,7 +269,6 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
|||
} catch (Exception e) {
|
||||
Timber.e(e, "error closing stream");
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -342,29 +328,4 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
|
|||
}
|
||||
}
|
||||
|
||||
private Cursor queryForKeys(long[] masterKeyIds) {
|
||||
String selection = null, selectionArgs[] = null;
|
||||
|
||||
if (masterKeyIds != null) {
|
||||
// convert long[] to String[]
|
||||
selectionArgs = new String[masterKeyIds.length];
|
||||
for (int i = 0; i < masterKeyIds.length; i++) {
|
||||
selectionArgs[i] = Long.toString(masterKeyIds[i]);
|
||||
}
|
||||
|
||||
// generates ?,?,? as placeholders for selectionArgs
|
||||
String placeholders = TextUtils.join(",",
|
||||
Collections.nCopies(masterKeyIds.length, "?"));
|
||||
|
||||
// put together selection string
|
||||
selection = Tables.KEYS + "." + KeyRings.MASTER_KEY_ID
|
||||
+ " IN (" + placeholders + ")";
|
||||
}
|
||||
|
||||
return mKeyRepository.getContentResolver().query(
|
||||
KeyRings.buildUnifiedKeyRingsUri(), PROJECTION, selection, selectionArgs,
|
||||
Tables.KEYS + "." + KeyRings.MASTER_KEY_ID
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -86,10 +86,8 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
|||
|
||||
log.add(LogType.MSG_CRT_MASTER_FETCH, 1);
|
||||
|
||||
CachedPublicKeyRing cachedPublicKeyRing = mKeyRepository.getCachedPublicKeyRing(masterKeyId);
|
||||
Passphrase passphrase;
|
||||
|
||||
switch (cachedPublicKeyRing.getSecretKeyType(masterKeyId)) {
|
||||
switch (mKeyRepository.getSecretKeyType(masterKeyId)) {
|
||||
case PASSPHRASE:
|
||||
passphrase = cryptoInput.getPassphrase();
|
||||
if (passphrase == null) {
|
||||
|
|
|
@ -21,12 +21,11 @@ package org.sufficientlysecure.keychain.operations;
|
|||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.RevokeResult;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.service.RevokeKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
|
@ -56,18 +55,21 @@ public class RevokeOperation extends BaseReadWriteOperation<RevokeKeyringParcel>
|
|||
KeyFormattingUtils.beautifyKeyId(masterKeyId));
|
||||
|
||||
try {
|
||||
|
||||
CachedPublicKeyRing keyRing = mKeyRepository.getCachedPublicKeyRing(masterKeyId);
|
||||
UnifiedKeyInfo keyInfo = mKeyRepository.getUnifiedKeyInfo(masterKeyId);
|
||||
if (keyInfo == null) {
|
||||
log.add(OperationResult.LogType.MSG_REVOKE_ERROR_KEY_FAIL, 1);
|
||||
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
|
||||
}
|
||||
|
||||
// check if this is a master secret key we can work with
|
||||
switch (keyRing.getSecretKeyType(masterKeyId)) {
|
||||
switch (mKeyRepository.getSecretKeyType(masterKeyId)) {
|
||||
case GNU_DUMMY:
|
||||
log.add(OperationResult.LogType.MSG_EK_ERROR_DUMMY, 1);
|
||||
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
|
||||
}
|
||||
|
||||
SaveKeyringParcel.Builder saveKeyringParcel =
|
||||
SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
|
||||
SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyInfo.fingerprint());
|
||||
|
||||
// all revoke operations are made atomic as of now
|
||||
saveKeyringParcel.setUpdateOptions(revokeKeyringParcel.isShouldUpload(), true,
|
||||
|
@ -93,7 +95,7 @@ public class RevokeOperation extends BaseReadWriteOperation<RevokeKeyringParcel>
|
|||
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
|
||||
}
|
||||
|
||||
} catch (PgpKeyNotFoundException | KeyWritableRepository.NotFoundException e) {
|
||||
} catch (KeyWritableRepository.NotFoundException e) {
|
||||
Timber.e(e, "could not find key to revoke");
|
||||
log.add(OperationResult.LogType.MSG_REVOKE_ERROR_KEY_FAIL, 1);
|
||||
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
|
||||
|
|
|
@ -124,7 +124,7 @@ public class OpenPgpSignatureResultBuilder {
|
|||
} catch (PgpKeyNotFoundException e) {
|
||||
Timber.d("No primary user id in keyring with master key id " + signingRing.getMasterKeyId());
|
||||
}
|
||||
setSignatureKeyCertified(signingRing.getVerified() != VerificationStatus.UNVERIFIED);
|
||||
setSignatureKeyCertified(signingRing.getVerified() == VerificationStatus.VERIFIED_SECRET);
|
||||
|
||||
List<String> allUserIds = signingRing.getUnorderedUserIds();
|
||||
List<String> confirmedUserIds = mKeyRepository.getConfirmedUserIds(signingRing.getMasterKeyId());
|
||||
|
|
|
@ -71,7 +71,6 @@ import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmPr
|
|||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.MissingMdc;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
|
@ -633,7 +632,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||
break;
|
||||
}
|
||||
|
||||
CachedPublicKeyRing cachedPublicKeyRing;
|
||||
try {
|
||||
// get actual keyring object based on master key id
|
||||
Long masterKeyId = mKeyRepository.getMasterKeyIdBySubkeyId(subKeyId);
|
||||
|
@ -641,7 +639,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||
log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1);
|
||||
continue;
|
||||
}
|
||||
cachedPublicKeyRing = mKeyRepository.getCachedPublicKeyRing(masterKeyId);
|
||||
|
||||
// allow only specific keys for decryption?
|
||||
if (input.getAllowedKeyIds() != null) {
|
||||
|
@ -658,7 +655,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||
}
|
||||
}
|
||||
|
||||
SecretKeyType secretKeyType = cachedPublicKeyRing.getSecretKeyType(subKeyId);
|
||||
SecretKeyType secretKeyType = mKeyRepository.getSecretKeyType(subKeyId);
|
||||
if (!secretKeyType.isUsable()) {
|
||||
decryptionKey = null;
|
||||
log.add(LogType.MSG_DC_ASKIP_UNAVAILABLE, indent + 1);
|
||||
|
|
|
@ -63,10 +63,9 @@ import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainComp
|
|||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainHashAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
|
@ -226,8 +225,8 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
|||
Long signingSubKeyId = data.getSignatureSubKeyId();
|
||||
if (signingSubKeyId == null) {
|
||||
try {
|
||||
signingSubKeyId = mKeyRepository.getCachedPublicKeyRing(signingMasterKeyId).getSecretSignId();
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
signingSubKeyId = mKeyRepository.getSecretSignId(signingMasterKeyId);
|
||||
} catch (NotFoundException e) {
|
||||
log.add(LogType.MSG_PSE_ERROR_KEY_SIGN, indent);
|
||||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
@ -257,7 +256,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
|
|||
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
||||
switch (mKeyRepository.getCachedPublicKeyRing(signingMasterKeyId).getSecretKeyType(signingSubKeyId)) {
|
||||
switch (mKeyRepository.getSecretKeyType(signingSubKeyId)) {
|
||||
case DIVERT_TO_CARD:
|
||||
case PASSPHRASE_EMPTY: {
|
||||
if (!signingKey.unlock(new Passphrase())) {
|
||||
|
|
|
@ -41,6 +41,15 @@ class AbstractDao {
|
|||
return result;
|
||||
}
|
||||
|
||||
<T> T mapSingleRow(SupportSQLiteQuery query, Mapper<T> mapper) {
|
||||
try (Cursor cursor = getReadableDb().query(query)) {
|
||||
if (cursor.moveToNext()) {
|
||||
return mapper.map(cursor);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
interface Mapper<T> {
|
||||
T map(Cursor cursor);
|
||||
}
|
||||
|
|
|
@ -18,16 +18,11 @@
|
|||
package org.sufficientlysecure.keychain.provider;
|
||||
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import org.sufficientlysecure.keychain.model.CustomColumnAdapters;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing.VerificationStatus;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
/** This implementation of KeyRing provides a cached view of PublicKeyRing
|
||||
|
@ -47,234 +42,64 @@ import timber.log.Timber;
|
|||
*
|
||||
*/
|
||||
public class CachedPublicKeyRing extends KeyRing {
|
||||
private UnifiedKeyInfo unifiedKeyInfo;
|
||||
|
||||
final KeyRepository mKeyRepository;
|
||||
final Uri mUri;
|
||||
|
||||
public CachedPublicKeyRing(KeyRepository keyRepository, Uri uri) {
|
||||
mKeyRepository = keyRepository;
|
||||
mUri = uri;
|
||||
public CachedPublicKeyRing(UnifiedKeyInfo unifiedKeyInfo) {
|
||||
this.unifiedKeyInfo = unifiedKeyInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMasterKeyId() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeychainContract.KeyRings.MASTER_KEY_ID, KeyRepository.FIELD_TYPE_INTEGER);
|
||||
return (Long) data;
|
||||
} catch (KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
public long getMasterKeyId() {
|
||||
return unifiedKeyInfo.master_key_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the master key id related to a given query. The id will either be extracted from the
|
||||
* query, which should work for all specific /key_rings/ queries, or will be queried if it can't.
|
||||
*/
|
||||
public long extractOrGetMasterKeyId() throws PgpKeyNotFoundException {
|
||||
// try extracting from the uri first
|
||||
String firstSegment = mUri.getPathSegments().get(1);
|
||||
if (!"find".equals(firstSegment)) try {
|
||||
return Long.parseLong(firstSegment);
|
||||
} catch (NumberFormatException e) {
|
||||
// didn't work? oh well.
|
||||
Timber.d("Couldn't get masterKeyId from URI, querying...");
|
||||
}
|
||||
return getMasterKeyId();
|
||||
public byte[] getFingerprint() {
|
||||
return unifiedKeyInfo.fingerprint();
|
||||
}
|
||||
|
||||
public byte[] getFingerprint() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeychainContract.KeyRings.FINGERPRINT, KeyRepository.FIELD_TYPE_BLOB);
|
||||
return (byte[]) data;
|
||||
} catch (KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public long getCreationTime() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeychainContract.KeyRings.CREATION, KeyRepository.FIELD_TYPE_INTEGER);
|
||||
return (long) data;
|
||||
} catch (KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
public long getCreationTime() {
|
||||
return unifiedKeyInfo.creation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimaryUserId() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeychainContract.KeyRings.USER_ID,
|
||||
KeyRepository.FIELD_TYPE_STRING);
|
||||
return (String) data;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
public String getPrimaryUserId() {
|
||||
return unifiedKeyInfo.user_id();
|
||||
}
|
||||
|
||||
public String getPrimaryUserIdWithFallback() throws PgpKeyNotFoundException {
|
||||
public String getPrimaryUserIdWithFallback() {
|
||||
return getPrimaryUserId();
|
||||
}
|
||||
|
||||
public String getName() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeyRings.NAME,
|
||||
KeyRepository.FIELD_TYPE_STRING);
|
||||
return (String) data;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getEmail() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeyRings.EMAIL,
|
||||
KeyRepository.FIELD_TYPE_STRING);
|
||||
return (String) data;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getComment() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeyRings.COMMENT,
|
||||
KeyRepository.FIELD_TYPE_STRING);
|
||||
return (String) data;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
@Override
|
||||
public boolean isRevoked() {
|
||||
return unifiedKeyInfo.is_revoked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRevoked() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeychainContract.KeyRings.IS_REVOKED,
|
||||
KeyRepository.FIELD_TYPE_INTEGER);
|
||||
return (Long) data > 0;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
public boolean canCertify() {
|
||||
return unifiedKeyInfo.can_certify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCertify() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeychainContract.KeyRings.HAS_CERTIFY_SECRET,
|
||||
KeyRepository.FIELD_TYPE_NULL);
|
||||
return !((Boolean) data);
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
public long getEncryptId() {
|
||||
return unifiedKeyInfo.has_encrypt_key_int();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEncryptId() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeyRings.HAS_ENCRYPT,
|
||||
KeyRepository.FIELD_TYPE_INTEGER);
|
||||
return (Long) data;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
public boolean hasEncrypt() {
|
||||
return unifiedKeyInfo.has_encrypt_key();
|
||||
}
|
||||
|
||||
public long getAuthenticationId() {
|
||||
return unifiedKeyInfo.has_auth_key_int();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEncrypt() throws PgpKeyNotFoundException {
|
||||
return getEncryptId() != 0;
|
||||
public VerificationStatus getVerified() {
|
||||
return unifiedKeyInfo.verified();
|
||||
}
|
||||
|
||||
/** Returns the key id which should be used for signing.
|
||||
*
|
||||
* This method returns keys which are actually available (ie. secret available, and not stripped,
|
||||
* revoked, or expired), hence only works on keyrings where a secret key is available!
|
||||
*
|
||||
*/
|
||||
public long getSecretSignId() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeyRings.HAS_SIGN_SECRET,
|
||||
KeyRepository.FIELD_TYPE_INTEGER);
|
||||
return (Long) data;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the key id which should be used for authentication.
|
||||
*
|
||||
* This method returns keys which are actually available (ie. secret available, and not stripped,
|
||||
* revoked, or expired), hence only works on keyrings where a secret key is available!
|
||||
*
|
||||
*/
|
||||
public long getSecretAuthenticationId() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeyRings.HAS_AUTHENTICATE_SECRET,
|
||||
KeyRepository.FIELD_TYPE_INTEGER);
|
||||
return (Long) data;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public long getAuthenticationId() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeyRings.HAS_AUTHENTICATE,
|
||||
KeyRepository.FIELD_TYPE_INTEGER);
|
||||
return (Long) data;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerificationStatus getVerified() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeychainContract.KeyRings.VERIFIED,
|
||||
KeyRepository.FIELD_TYPE_INTEGER);
|
||||
return CustomColumnAdapters.VERIFICATON_STATUS_ADAPTER.decode((Long) data);
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasAnySecret() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
Object data = mKeyRepository.getGenericData(mUri,
|
||||
KeychainContract.KeyRings.HAS_ANY_SECRET,
|
||||
KeyRepository.FIELD_TYPE_INTEGER);
|
||||
return (Long) data > 0;
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public SecretKeyType getSecretKeyType(long keyId) throws NotFoundException {
|
||||
SecretKeyType secretKeyType = mKeyRepository.getSecretKeyType(keyId);
|
||||
if (secretKeyType == null) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return secretKeyType;
|
||||
}
|
||||
|
||||
public byte[] getEncoded() throws PgpKeyNotFoundException {
|
||||
try {
|
||||
return mKeyRepository.loadPublicKeyRingData(getMasterKeyId());
|
||||
} catch(KeyWritableRepository.NotFoundException e) {
|
||||
throw new PgpKeyNotFoundException(e);
|
||||
}
|
||||
public boolean hasAnySecret() {
|
||||
return unifiedKeyInfo.has_any_secret();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,13 +21,11 @@ package org.sufficientlysecure.keychain.provider;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.squareup.sqldelight.SqlDelightQuery;
|
||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
||||
|
@ -43,21 +41,10 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing.VerificationStat
|
|||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
public class KeyRepository extends AbstractDao {
|
||||
// If we ever switch to api level 11, we can ditch this whole mess!
|
||||
public static final int FIELD_TYPE_NULL = 1;
|
||||
// this is called integer to stay coherent with the constants in Cursor (api level 11)
|
||||
public static final int FIELD_TYPE_INTEGER = 2;
|
||||
public static final int FIELD_TYPE_FLOAT = 3;
|
||||
public static final int FIELD_TYPE_STRING = 4;
|
||||
public static final int FIELD_TYPE_BLOB = 5;
|
||||
|
||||
final ContentResolver contentResolver;
|
||||
final LocalPublicKeyStorage mLocalPublicKeyStorage;
|
||||
final LocalSecretKeyStorage localSecretKeyStorage;
|
||||
|
@ -115,72 +102,13 @@ public class KeyRepository extends AbstractDao {
|
|||
mLog = new OperationLog();
|
||||
}
|
||||
|
||||
Object getGenericData(Uri uri, String column, int type) throws NotFoundException {
|
||||
Object result = getGenericData(uri, new String[]{column}, new int[]{type}, null).get(column);
|
||||
if (result == null) {
|
||||
// replace with getUnifiedKeyInfo
|
||||
public CachedPublicKeyRing getCachedPublicKeyRing(long masterKeyId) throws NotFoundException {
|
||||
UnifiedKeyInfo unifiedKeyInfo = getUnifiedKeyInfo(masterKeyId);
|
||||
if (unifiedKeyInfo == null) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private HashMap<String, Object> getGenericData(Uri uri, String[] proj, int[] types)
|
||||
throws NotFoundException {
|
||||
return getGenericData(uri, proj, types, null);
|
||||
}
|
||||
|
||||
private HashMap<String, Object> getGenericData(Uri uri, String[] proj, int[] types, String selection)
|
||||
throws NotFoundException {
|
||||
Cursor cursor = contentResolver.query(uri, proj, selection, null, null);
|
||||
|
||||
try {
|
||||
HashMap<String, Object> result = new HashMap<>(proj.length);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
int pos = 0;
|
||||
for (String p : proj) {
|
||||
switch (types[pos]) {
|
||||
case FIELD_TYPE_NULL:
|
||||
result.put(p, cursor.isNull(pos));
|
||||
break;
|
||||
case FIELD_TYPE_INTEGER:
|
||||
result.put(p, cursor.getLong(pos));
|
||||
break;
|
||||
case FIELD_TYPE_FLOAT:
|
||||
result.put(p, cursor.getFloat(pos));
|
||||
break;
|
||||
case FIELD_TYPE_STRING:
|
||||
result.put(p, cursor.getString(pos));
|
||||
break;
|
||||
case FIELD_TYPE_BLOB:
|
||||
result.put(p, cursor.getBlob(pos));
|
||||
break;
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
} else {
|
||||
// If no data was found, throw an appropriate exception
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
return result;
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HashMap<String, Object> getUnifiedData(long masterKeyId, String[] proj, int[] types)
|
||||
throws NotFoundException {
|
||||
return getGenericData(KeyRings.buildUnifiedKeyRingUri(masterKeyId), proj, types);
|
||||
}
|
||||
|
||||
public CachedPublicKeyRing getCachedPublicKeyRing(Uri queryUri) throws PgpKeyNotFoundException {
|
||||
long masterKeyId = new CachedPublicKeyRing(this, queryUri).extractOrGetMasterKeyId();
|
||||
return getCachedPublicKeyRing(masterKeyId);
|
||||
}
|
||||
|
||||
public CachedPublicKeyRing getCachedPublicKeyRing(long id) {
|
||||
return new CachedPublicKeyRing(this, KeyRings.buildUnifiedKeyRingUri(id));
|
||||
return new CachedPublicKeyRing(unifiedKeyInfo);
|
||||
}
|
||||
|
||||
public CanonicalizedPublicKeyRing getCanonicalizedPublicKeyRing(long masterKeyId) throws NotFoundException {
|
||||
|
@ -211,11 +139,7 @@ public class KeyRepository extends AbstractDao {
|
|||
}
|
||||
|
||||
public List<Long> getMasterKeyIdsBySigner(List<Long> signerMasterKeyIds) {
|
||||
long[] signerKeyIds = new long[signerMasterKeyIds.size()];
|
||||
int i = 0;
|
||||
for (Long signerKeyId : signerMasterKeyIds) {
|
||||
signerKeyIds[i++] = signerKeyId;
|
||||
}
|
||||
long[] signerKeyIds = getLongListAsArray(signerMasterKeyIds);
|
||||
SqlDelightQuery query = SubKey.FACTORY.selectMasterKeyIdsBySigner(signerKeyIds);
|
||||
return mapAllRows(query, KeyRingPublic.FACTORY.selectAllMasterKeyIdsMapper()::map);
|
||||
}
|
||||
|
@ -240,6 +164,11 @@ public class KeyRepository extends AbstractDao {
|
|||
}
|
||||
}
|
||||
|
||||
public List<UnifiedKeyInfo> getUnifiedKeyInfo(long... masterKeyIds) {
|
||||
SqlDelightQuery query = SubKey.FACTORY.selectUnifiedKeyInfoByMasterKeyIds(masterKeyIds);
|
||||
return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map);
|
||||
}
|
||||
|
||||
public List<UnifiedKeyInfo> getUnifiedKeyInfosByMailAddress(String mailAddress) {
|
||||
SqlDelightQuery query = SubKey.FACTORY.selectUnifiedKeyInfoSearchMailAddress('%' + mailAddress + '%');
|
||||
return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map);
|
||||
|
@ -275,17 +204,17 @@ public class KeyRepository extends AbstractDao {
|
|||
return mapAllRows(query, SubKey.SUBKEY_MAPPER::map);
|
||||
}
|
||||
|
||||
public SecretKeyType getSecretKeyType(long keyId) {
|
||||
public SecretKeyType getSecretKeyType(long keyId) throws NotFoundException {
|
||||
SqlDelightQuery query = SubKey.FACTORY.selectSecretKeyType(keyId);
|
||||
try (Cursor cursor = getReadableDb().query(query)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
return SubKey.SKT_MAPPER.map(cursor);
|
||||
}
|
||||
return null;
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getKeyRingAsArmoredData(byte[] data) throws IOException, PgpGeneralException {
|
||||
private byte[] getKeyRingAsArmoredData(byte[] data) throws IOException {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ArmoredOutputStream aos = new ArmoredOutputStream(bos);
|
||||
|
||||
|
@ -295,15 +224,13 @@ public class KeyRepository extends AbstractDao {
|
|||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
public String getPublicKeyRingAsArmoredString(long masterKeyId)
|
||||
throws NotFoundException, IOException, PgpGeneralException {
|
||||
public String getPublicKeyRingAsArmoredString(long masterKeyId) throws NotFoundException, IOException {
|
||||
byte[] data = loadPublicKeyRingData(masterKeyId);
|
||||
byte[] armoredData = getKeyRingAsArmoredData(data);
|
||||
return new String(armoredData);
|
||||
}
|
||||
|
||||
public byte[] getSecretKeyRingAsArmoredData(long masterKeyId)
|
||||
throws NotFoundException, IOException, PgpGeneralException {
|
||||
public byte[] getSecretKeyRingAsArmoredData(long masterKeyId) throws NotFoundException, IOException {
|
||||
byte[] data = loadSecretKeyRingData(masterKeyId);
|
||||
return getKeyRingAsArmoredData(data);
|
||||
}
|
||||
|
@ -338,6 +265,24 @@ public class KeyRepository extends AbstractDao {
|
|||
}
|
||||
}
|
||||
|
||||
public long getSecretSignId(long masterKeyId) throws NotFoundException {
|
||||
SqlDelightQuery query = SubKey.FACTORY.selectEffectiveSignKeyIdByMasterKeyId(masterKeyId);
|
||||
Long signKeyId = mapSingleRow(query, SubKey.FACTORY.selectEffectiveSignKeyIdByMasterKeyIdMapper()::map);
|
||||
if (signKeyId == null) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return signKeyId;
|
||||
}
|
||||
|
||||
public Long getSecretAuthenticationId(long masterKeyId) throws NotFoundException {
|
||||
SqlDelightQuery query = SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyId(masterKeyId);
|
||||
Long authKeyId = mapSingleRow(query, SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyIdMapper()::map);
|
||||
if (authKeyId == null) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return authKeyId;
|
||||
}
|
||||
|
||||
public static class NotFoundException extends Exception {
|
||||
public NotFoundException() {
|
||||
}
|
||||
|
@ -346,4 +291,13 @@ public class KeyRepository extends AbstractDao {
|
|||
super(name);
|
||||
}
|
||||
}
|
||||
|
||||
private long[] getLongListAsArray(List<Long> longList) {
|
||||
long[] longs = new long[longList.size()];
|
||||
int i = 0;
|
||||
for (Long aLong : longList) {
|
||||
longs[i++] = aLong;
|
||||
}
|
||||
return longs;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import android.content.ContentProviderOperation;
|
|||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.OperationApplicationException;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.NonNull;
|
||||
|
@ -40,6 +39,7 @@ import org.openintents.openpgp.util.OpenPgpUtils;
|
|||
import org.sufficientlysecure.keychain.KeyRingsPublicModel.DeleteByMasterKeyId;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.model.CustomColumnAdapters;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
|
||||
|
@ -60,7 +60,6 @@ import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
|||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeySignatures;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
||||
|
@ -99,8 +98,7 @@ public class KeyWritableRepository extends KeyRepository {
|
|||
localPublicKeyStorage, localSecretKeyStorage, databaseNotifyManager, autocryptPeerDao);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
KeyWritableRepository(Context context,
|
||||
private KeyWritableRepository(Context context,
|
||||
KeychainDatabase database, LocalPublicKeyStorage localPublicKeyStorage,
|
||||
LocalSecretKeyStorage localSecretKeyStorage,
|
||||
DatabaseNotifyManager databaseNotifyManager, AutocryptPeerDao autocryptPeerDao) {
|
||||
|
@ -120,40 +118,22 @@ public class KeyWritableRepository extends KeyRepository {
|
|||
}
|
||||
|
||||
private LongSparseArray<CanonicalizedPublicKey> getTrustedMasterKeys() {
|
||||
Cursor cursor = contentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), new String[] {
|
||||
KeyRings.MASTER_KEY_ID,
|
||||
// we pick from cache only information that is not easily available from keyrings
|
||||
KeyRings.HAS_ANY_SECRET, KeyRings.VERIFIED
|
||||
}, KeyRings.HAS_ANY_SECRET + " = 1", null, null);
|
||||
LongSparseArray<CanonicalizedPublicKey> result = new LongSparseArray<>();
|
||||
|
||||
try {
|
||||
LongSparseArray<CanonicalizedPublicKey> result = new LongSparseArray<>();
|
||||
|
||||
if (cursor == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
try {
|
||||
long masterKeyId = cursor.getLong(0);
|
||||
long verified = cursor.getLong(2);
|
||||
byte[] blob = loadPublicKeyRingData(masterKeyId);
|
||||
VerificationStatus verificationStatus = CustomColumnAdapters.VERIFICATON_STATUS_ADAPTER.decode(verified);
|
||||
if (blob != null) {
|
||||
result.put(masterKeyId, new CanonicalizedPublicKeyRing(blob, verificationStatus).getPublicKey());
|
||||
}
|
||||
} catch (NotFoundException e) {
|
||||
throw new IllegalStateException("Error reading secret key data, this should not happen!", e);
|
||||
List<UnifiedKeyInfo> unifiedKeyInfoWithSecret = getAllUnifiedKeyInfoWithSecret();
|
||||
for (UnifiedKeyInfo unifiedKeyInfo : unifiedKeyInfoWithSecret) {
|
||||
try {
|
||||
byte[] blob = loadPublicKeyRingData(unifiedKeyInfo.master_key_id());
|
||||
if (blob != null) {
|
||||
result.put(unifiedKeyInfo.master_key_id(),
|
||||
new CanonicalizedPublicKeyRing(blob, unifiedKeyInfo.verified()).getPublicKey());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
} catch (NotFoundException e) {
|
||||
throw new IllegalStateException("Error reading secret key data, this should not happen!", e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// bits, in order: CESA. make SURE these are correct, we will get bad log entries otherwise!!
|
||||
|
|
|
@ -99,9 +99,6 @@ public class KeychainContract {
|
|||
|
||||
public static final String PATH_UNIFIED = "unified";
|
||||
|
||||
public static final String PATH_FIND = "find";
|
||||
public static final String PATH_BY_SUBKEY = "subkey";
|
||||
|
||||
public static final String PATH_PUBLIC = "public";
|
||||
public static final String PATH_USER_IDS = "user_ids";
|
||||
public static final String PATH_KEYS = "keys";
|
||||
|
@ -132,16 +129,6 @@ public class KeychainContract {
|
|||
public static Uri buildGenericKeyRingUri(long masterKeyId) {
|
||||
return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).build();
|
||||
}
|
||||
|
||||
public static Uri buildUnifiedKeyRingUri(long masterKeyId) {
|
||||
return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId))
|
||||
.appendPath(PATH_UNIFIED).build();
|
||||
}
|
||||
|
||||
public static Uri buildUnifiedKeyRingsFindBySubkeyUri(long subkey) {
|
||||
return CONTENT_URI.buildUpon().appendPath(PATH_FIND)
|
||||
.appendPath(PATH_BY_SUBKEY).appendPath(Long.toString(subkey)).build();
|
||||
}
|
||||
}
|
||||
|
||||
public static class KeyRingData implements KeyRingsColumns, BaseColumns {
|
||||
|
|
|
@ -32,7 +32,9 @@ import android.content.Context;
|
|||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import org.sufficientlysecure.keychain.ApiAllowedKeysModel;
|
||||
import org.sufficientlysecure.keychain.ApiAppsModel;
|
||||
import org.sufficientlysecure.keychain.AutocryptPeersModel;
|
||||
import org.sufficientlysecure.keychain.CertsModel;
|
||||
|
@ -66,12 +68,15 @@ public class KeychainDatabase {
|
|||
private static KeychainDatabase sInstance;
|
||||
|
||||
public static KeychainDatabase getInstance(Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new KeychainDatabase(context.getApplicationContext());
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void resetSingleton() {
|
||||
sInstance = null;
|
||||
}
|
||||
|
||||
public interface Tables {
|
||||
String KEY_RINGS_PUBLIC = "keyrings_public";
|
||||
String KEYS = "keys";
|
||||
|
@ -133,7 +138,7 @@ public class KeychainDatabase {
|
|||
db.execSQL(ApiAppsModel.CREATE_TABLE);
|
||||
db.execSQL(OverriddenWarningsModel.CREATE_TABLE);
|
||||
db.execSQL(AutocryptPeersModel.CREATE_TABLE);
|
||||
db.execSQL(ApiAppsModel.CREATE_TABLE);
|
||||
db.execSQL(ApiAllowedKeysModel.CREATE_TABLE);
|
||||
db.execSQL(KeysModel.UNIFIEDKEYVIEW);
|
||||
|
||||
db.execSQL("CREATE INDEX keys_by_rank ON keys (" + KeysColumns.RANK + ", " + KeysColumns.MASTER_KEY_ID + ");");
|
||||
|
@ -460,8 +465,8 @@ public class KeychainDatabase {
|
|||
|
||||
// DANGEROUS, use in test code ONLY!
|
||||
public void clearDatabase() {
|
||||
getWritableDatabase().execSQL("delete from " + Tables.KEY_RINGS_PUBLIC);
|
||||
getWritableDatabase().execSQL("delete from " + Tables.API_ALLOWED_KEYS);
|
||||
getWritableDatabase().execSQL("delete from " + KeyRingsPublicModel.TABLE_NAME);
|
||||
getWritableDatabase().execSQL("delete from " + ApiAllowedKeysModel.TABLE_NAME);
|
||||
getWritableDatabase().execSQL("delete from api_apps");
|
||||
}
|
||||
|
||||
|
|
|
@ -61,8 +61,6 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
|
|||
private static final int KEY_RING_PUBLIC = 203;
|
||||
private static final int KEY_RING_CERTS = 205;
|
||||
|
||||
private static final int KEY_RINGS_FIND_BY_SUBKEY = 401;
|
||||
|
||||
private static final int KEY_SIGNATURES = 700;
|
||||
|
||||
protected UriMatcher mUriMatcher;
|
||||
|
@ -88,16 +86,6 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
|
|||
+ "/" + KeychainContract.PATH_UNIFIED,
|
||||
KEY_RINGS_UNIFIED);
|
||||
|
||||
/*
|
||||
* find by criteria other than master key id
|
||||
*
|
||||
* key_rings/find/subkey/_
|
||||
*
|
||||
*/
|
||||
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
|
||||
+ KeychainContract.PATH_FIND + "/" + KeychainContract.PATH_BY_SUBKEY + "/*",
|
||||
KEY_RINGS_FIND_BY_SUBKEY);
|
||||
|
||||
/*
|
||||
* list key_ring specifics
|
||||
*
|
||||
|
@ -174,8 +162,7 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
|
|||
|
||||
switch (match) {
|
||||
case KEY_RING_UNIFIED:
|
||||
case KEY_RINGS_UNIFIED:
|
||||
case KEY_RINGS_FIND_BY_SUBKEY: {
|
||||
case KEY_RINGS_UNIFIED: {
|
||||
HashMap<String, String> projectionMap = new HashMap<>();
|
||||
projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id");
|
||||
projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID);
|
||||
|
@ -318,28 +305,8 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
|
|||
// in case there are multiple verifying certificates
|
||||
groupBy = Tables.KEYS + "." + Keys.MASTER_KEY_ID;
|
||||
|
||||
switch(match) {
|
||||
case KEY_RING_UNIFIED: {
|
||||
qb.appendWhere(" AND " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = ");
|
||||
qb.appendWhereEscapeString(uri.getPathSegments().get(1));
|
||||
break;
|
||||
}
|
||||
case KEY_RINGS_FIND_BY_SUBKEY: {
|
||||
try {
|
||||
String subkey = Long.valueOf(uri.getLastPathSegment()).toString();
|
||||
qb.appendWhere(" AND EXISTS ("
|
||||
+ " SELECT 1 FROM " + Tables.KEYS + " AS tmp"
|
||||
+ " WHERE tmp." + UserPackets.MASTER_KEY_ID
|
||||
+ " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID
|
||||
+ " AND tmp." + Keys.KEY_ID + " = " + subkey + ""
|
||||
+ ")");
|
||||
} catch(NumberFormatException e) {
|
||||
Timber.e(e, "Malformed find by subkey query!");
|
||||
qb.appendWhere(" AND 0");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
qb.appendWhere(" AND " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = ");
|
||||
qb.appendWhereEscapeString(uri.getPathSegments().get(1));
|
||||
|
||||
if (TextUtils.isEmpty(sortOrder)) {
|
||||
sortOrder = Tables.USER_PACKETS + "." + UserPackets.USER_ID + " ASC";
|
||||
|
|
|
@ -66,12 +66,11 @@ import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
|
|||
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.ApiAppDao;
|
||||
import org.sufficientlysecure.keychain.provider.AutocryptPeerDao;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainExternalContract.AutocryptStatus;
|
||||
import org.sufficientlysecure.keychain.provider.OverriddenWarningsRepository;
|
||||
import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.KeyIdResult;
|
||||
|
@ -139,9 +138,9 @@ public class OpenPgpService extends Service {
|
|||
|
||||
// get first usable subkey capable of signing
|
||||
try {
|
||||
long signSubKeyId = mKeyRepository.getCachedPublicKeyRing(signKeyId).getSecretSignId();
|
||||
long signSubKeyId = mKeyRepository.getSecretSignId(signKeyId);
|
||||
pgpData.setSignatureSubKeyId(signSubKeyId);
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
} catch (NotFoundException e) {
|
||||
throw new Exception("signing subkey not found!", e);
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +229,7 @@ public class OpenPgpService extends Service {
|
|||
if (signKeyId == Constants.key.none) {
|
||||
throw new Exception("No signing key given");
|
||||
}
|
||||
long signSubKeyId = mKeyRepository.getCachedPublicKeyRing(signKeyId).getSecretSignId();
|
||||
long signSubKeyId = mKeyRepository.getSecretSignId(signKeyId);
|
||||
|
||||
pgpData.setSignatureMasterKeyId(signKeyId)
|
||||
.setSignatureSubKeyId(signSubKeyId)
|
||||
|
@ -627,7 +626,8 @@ public class OpenPgpService extends Service {
|
|||
}
|
||||
|
||||
try {
|
||||
CanonicalizedPublicKeyRing keyRing = mKeyRepository.getCanonicalizedPublicKeyRing(masterKeyId);
|
||||
CanonicalizedPublicKeyRing keyRing =
|
||||
mKeyRepository.getCanonicalizedPublicKeyRing(masterKeyId);
|
||||
|
||||
Intent result = new Intent();
|
||||
result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
|
||||
|
@ -749,7 +749,7 @@ public class OpenPgpService extends Service {
|
|||
|
||||
result.putExtra(OpenPgpApi.RESULT_PRIMARY_USER_ID, userId);
|
||||
result.putExtra(OpenPgpApi.RESULT_KEY_CREATION_TIME, creationTime);
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
} catch (NotFoundException e) {
|
||||
Timber.e(e, "Error loading key info");
|
||||
return createErrorResultIntent(OpenPgpError.GENERIC_ERROR, e.getMessage());
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
|||
import org.sufficientlysecure.keychain.provider.ApiAppDao;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.ssh.AuthenticationData;
|
||||
|
@ -59,8 +60,6 @@ import timber.log.Timber;
|
|||
|
||||
|
||||
public class SshAuthenticationService extends Service {
|
||||
private static final String TAG = "SshAuthService";
|
||||
|
||||
private ApiPermissionHelper mApiPermissionHelper;
|
||||
private KeyRepository mKeyRepository;
|
||||
private ApiAppDao mApiAppDao;
|
||||
|
@ -144,23 +143,18 @@ public class SshAuthenticationService extends Service {
|
|||
AuthenticationData.Builder authData = AuthenticationData.builder();
|
||||
authData.setAuthenticationMasterKeyId(masterKeyId);
|
||||
|
||||
CachedPublicKeyRing cachedPublicKeyRing = mKeyRepository.getCachedPublicKeyRing(masterKeyId);
|
||||
|
||||
long authSubKeyId;
|
||||
int authSubKeyAlgorithm;
|
||||
String authSubKeyCurveOid = null;
|
||||
try {
|
||||
// get first usable subkey capable of authentication
|
||||
authSubKeyId = cachedPublicKeyRing.getSecretAuthenticationId();
|
||||
authSubKeyId = mKeyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
// needed for encoding the resulting signature
|
||||
authSubKeyAlgorithm = getPublicKey(masterKeyId).getAlgorithm();
|
||||
if (authSubKeyAlgorithm == PublicKeyAlgorithmTags.ECDSA) {
|
||||
authSubKeyCurveOid = getPublicKey(masterKeyId).getCurveOid();
|
||||
}
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
return createExceptionErrorResult(SshAuthenticationApiError.NO_AUTH_KEY,
|
||||
"authentication key for master key id not found in keychain", e);
|
||||
} catch (KeyRepository.NotFoundException e) {
|
||||
} catch (NotFoundException e) {
|
||||
return createExceptionErrorResult(SshAuthenticationApiError.NO_SUCH_KEY,
|
||||
"Key for master key id not found", e);
|
||||
}
|
||||
|
@ -272,7 +266,7 @@ public class SshAuthenticationService extends Service {
|
|||
|
||||
try {
|
||||
description = getDescription(masterKeyId);
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
} catch (NotFoundException e) {
|
||||
return createExceptionErrorResult(SshAuthenticationApiError.NO_SUCH_KEY,
|
||||
"Could not create description", e);
|
||||
}
|
||||
|
@ -372,8 +366,7 @@ public class SshAuthenticationService extends Service {
|
|||
return new SshPublicKeyResponse(sshPublicKeyBlob).toIntent();
|
||||
}
|
||||
|
||||
private CanonicalizedPublicKey getPublicKey(long masterKeyId)
|
||||
throws PgpKeyNotFoundException, KeyRepository.NotFoundException {
|
||||
private CanonicalizedPublicKey getPublicKey(long masterKeyId) throws NotFoundException {
|
||||
KeyRepository keyRepository = KeyRepository.create(getApplicationContext());
|
||||
long authSubKeyId = keyRepository.getCachedPublicKeyRing(masterKeyId)
|
||||
.getAuthenticationId();
|
||||
|
@ -381,11 +374,11 @@ public class SshAuthenticationService extends Service {
|
|||
.getPublicKey(authSubKeyId);
|
||||
}
|
||||
|
||||
private String getDescription(long masterKeyId) throws PgpKeyNotFoundException {
|
||||
private String getDescription(long masterKeyId) throws NotFoundException {
|
||||
CachedPublicKeyRing cachedPublicKeyRing = mKeyRepository.getCachedPublicKeyRing(masterKeyId);
|
||||
|
||||
String description = "";
|
||||
long authSubKeyId = cachedPublicKeyRing.getSecretAuthenticationId();
|
||||
long authSubKeyId = mKeyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
description += cachedPublicKeyRing.getPrimaryUserId();
|
||||
description += " (" + Long.toHexString(authSubKeyId) + ")";
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ class RequestKeyPermissionPresenter {
|
|||
}
|
||||
CachedPublicKeyRing cachedPublicKeyRing = keyRepository.getCachedPublicKeyRing(masterKeyId);
|
||||
|
||||
SecretKeyType secretKeyType = cachedPublicKeyRing.getSecretKeyType(candidateSubKeyId);
|
||||
SecretKeyType secretKeyType = keyRepository.getSecretKeyType(candidateSubKeyId);
|
||||
if (secretKeyType.isUsable()) {
|
||||
return cachedPublicKeyRing;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
package org.sufficientlysecure.keychain.service;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
|
@ -41,14 +43,11 @@ import org.sufficientlysecure.keychain.Constants;
|
|||
import org.sufficientlysecure.keychain.Constants.NotificationIds;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* This service runs in its own process, but is available to all other processes as the main
|
||||
* passphrase cache. Use the static methods addCachedPassphrase and getCachedPassphrase for
|
||||
|
@ -246,8 +245,8 @@ public class PassphraseCacheService extends Service {
|
|||
+ masterKeyId + ", subKeyId " + subKeyId);
|
||||
|
||||
// get the type of key (from the database)
|
||||
CachedPublicKeyRing keyRing = KeyRepository.create(this).getCachedPublicKeyRing(masterKeyId);
|
||||
SecretKeyType keyType = keyRing.getSecretKeyType(subKeyId);
|
||||
KeyRepository keyRepository = KeyRepository.create(this);
|
||||
SecretKeyType keyType = keyRepository.getSecretKeyType(subKeyId);
|
||||
|
||||
switch (keyType) {
|
||||
case PASSPHRASE_EMPTY:
|
||||
|
|
|
@ -17,8 +17,12 @@
|
|||
|
||||
package org.sufficientlysecure.keychain.ssh;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.bouncycastle.openpgp.AuthenticationSignatureGenerator;
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.operator.jcajce.NfcSyncPGPContentSignerBuilder;
|
||||
|
@ -29,15 +33,13 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
|
|||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
|
||||
|
@ -101,8 +103,8 @@ public class AuthenticationOperation extends BaseOperation<AuthenticationParcel>
|
|||
Long authSubKeyId = data.getAuthenticationSubKeyId();
|
||||
if (authSubKeyId == null) {
|
||||
try { // Get the key id of the authentication key belonging to the master key id
|
||||
authSubKeyId = mKeyRepository.getCachedPublicKeyRing(authMasterKeyId).getSecretAuthenticationId();
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
authSubKeyId = mKeyRepository.getSecretAuthenticationId(authMasterKeyId);
|
||||
} catch (NotFoundException e) {
|
||||
log.add(LogType.MSG_AUTH_ERROR_KEY_AUTH, indent);
|
||||
return new AuthenticationResult(AuthenticationResult.RESULT_ERROR, log);
|
||||
}
|
||||
|
@ -142,9 +144,7 @@ public class AuthenticationOperation extends BaseOperation<AuthenticationParcel>
|
|||
|
||||
CanonicalizedSecretKey.SecretKeyType secretKeyType;
|
||||
try {
|
||||
secretKeyType = mKeyRepository
|
||||
.getCachedPublicKeyRing(authMasterKeyId)
|
||||
.getSecretKeyType(authSubKeyId);
|
||||
secretKeyType = mKeyRepository.getSecretKeyType(authSubKeyId);
|
||||
} catch (KeyRepository.NotFoundException e) {
|
||||
log.add(LogType.MSG_AUTH_ERROR_KEY_AUTH, indent);
|
||||
return new AuthenticationResult(AuthenticationResult.RESULT_ERROR, log);
|
||||
|
|
|
@ -36,9 +36,9 @@ import org.sufficientlysecure.keychain.Constants;
|
|||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.operations.results.CertifyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
|
@ -75,7 +75,7 @@ public class CertifyKeyFragment
|
|||
if (key.canCertify()) {
|
||||
mCertifyKeySpinner.setPreSelectedKeyId(certifyKeyId);
|
||||
}
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
} catch (NotFoundException e) {
|
||||
Timber.e(e, "certify certify check failed");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,9 +48,9 @@ import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
|
|||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.UploadResult;
|
||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
|
||||
|
@ -413,10 +413,10 @@ public class CreateKeyFinalFragment extends Fragment {
|
|||
KeyRepository keyRepository = KeyRepository.create(getContext());
|
||||
|
||||
SaveKeyringParcel.Builder builder;
|
||||
CachedPublicKeyRing key = keyRepository.getCachedPublicKeyRing(saveKeyResult.mMasterKeyId);
|
||||
try {
|
||||
CachedPublicKeyRing key = keyRepository.getCachedPublicKeyRing(saveKeyResult.mMasterKeyId);
|
||||
builder = SaveKeyringParcel.buildChangeKeyringParcel(saveKeyResult.mMasterKeyId, key.getFingerprint());
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
} catch (NotFoundException e) {
|
||||
Timber.e("Key that should be moved to Security Token not found in database!");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import android.widget.Spinner;
|
|||
import android.widget.TextView;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.operations.results.DeleteResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.RevokeResult;
|
||||
|
@ -86,35 +87,23 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
|
|||
|
||||
if (mMasterKeyIds.length == 1 && mHasSecret) {
|
||||
// if mMasterKeyIds.length == 0 we let the DeleteOperation respond
|
||||
try {
|
||||
KeyRepository keyRepository = KeyRepository.create(this);
|
||||
HashMap<String, Object> data = keyRepository.getUnifiedData(
|
||||
mMasterKeyIds[0], new String[]{
|
||||
KeychainContract.KeyRings.NAME,
|
||||
KeychainContract.KeyRings.IS_REVOKED
|
||||
}, new int[]{
|
||||
KeyRepository.FIELD_TYPE_STRING,
|
||||
KeyRepository.FIELD_TYPE_INTEGER
|
||||
}
|
||||
);
|
||||
|
||||
String name;
|
||||
|
||||
name = (String) data.get(KeychainContract.KeyRings.NAME);
|
||||
|
||||
if (name == null) {
|
||||
name = getString(R.string.user_id_no_name);
|
||||
}
|
||||
|
||||
if ((long) data.get(KeychainContract.KeyRings.IS_REVOKED) > 0) {
|
||||
showNormalDeleteDialog();
|
||||
} else {
|
||||
showRevokeDeleteDialog(name);
|
||||
}
|
||||
} catch (KeyRepository.NotFoundException e) {
|
||||
Timber.e(e, "Secret key to delete not found at DeleteKeyDialogActivity for "
|
||||
+ mMasterKeyIds[0]);
|
||||
KeyRepository keyRepository = KeyRepository.create(this);
|
||||
UnifiedKeyInfo keyInfo = keyRepository.getUnifiedKeyInfo(mMasterKeyIds[0]);
|
||||
if (keyInfo == null) {
|
||||
Timber.e("Secret key to delete not found at DeleteKeyDialogActivity for " + mMasterKeyIds[0]);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
String name = keyInfo.name();
|
||||
if (name == null) {
|
||||
name = getString(R.string.user_id_no_name);
|
||||
}
|
||||
|
||||
if (keyInfo.is_revoked()) {
|
||||
showNormalDeleteDialog();
|
||||
} else {
|
||||
showRevokeDeleteDialog(name);
|
||||
}
|
||||
} else {
|
||||
showNormalDeleteDialog();
|
||||
|
@ -269,36 +258,26 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
|
|||
if (masterKeyIds.length == 1) {
|
||||
long masterKeyId = masterKeyIds[0];
|
||||
|
||||
try {
|
||||
HashMap<String, Object> data = KeyRepository.create(getContext())
|
||||
.getUnifiedData(
|
||||
masterKeyId, new String[]{
|
||||
KeychainContract.KeyRings.NAME,
|
||||
KeychainContract.KeyRings.HAS_ANY_SECRET
|
||||
}, new int[]{
|
||||
KeyRepository.FIELD_TYPE_STRING,
|
||||
KeyRepository.FIELD_TYPE_INTEGER
|
||||
}
|
||||
);
|
||||
String name;
|
||||
|
||||
name = (String) data.get(KeychainContract.KeyRings.NAME);
|
||||
if (name == null) {
|
||||
name = getString(R.string.user_id_no_name);
|
||||
}
|
||||
|
||||
if (hasSecret) {
|
||||
// show title only for secret key deletions,
|
||||
// see http://www.google.com/design/spec/components/dialogs.html#dialogs-behavior
|
||||
builder.setTitle(getString(R.string.title_delete_secret_key, name));
|
||||
mMainMessage.setText(getString(R.string.secret_key_deletion_confirmation, name));
|
||||
} else {
|
||||
mMainMessage.setText(getString(R.string.public_key_deletetion_confirmation, name));
|
||||
}
|
||||
} catch (KeyRepository.NotFoundException e) {
|
||||
KeyRepository keyRepository = KeyRepository.create(getContext());
|
||||
UnifiedKeyInfo keyInfo = keyRepository.getUnifiedKeyInfo(masterKeyId);
|
||||
if (keyInfo == null) {
|
||||
dismiss();
|
||||
return null;
|
||||
}
|
||||
String name = keyInfo.name();
|
||||
|
||||
if (name == null) {
|
||||
name = getString(R.string.user_id_no_name);
|
||||
}
|
||||
|
||||
if (keyInfo.has_any_secret()) {
|
||||
// show title only for secret key deletions,
|
||||
// see http://www.google.com/design/spec/components/dialogs.html#dialogs-behavior
|
||||
builder.setTitle(getString(R.string.title_delete_secret_key, name));
|
||||
mMainMessage.setText(getString(R.string.secret_key_deletion_confirmation, name));
|
||||
} else {
|
||||
mMainMessage.setText(getString(R.string.public_key_deletetion_confirmation, name));
|
||||
}
|
||||
} else {
|
||||
mMainMessage.setText(R.string.key_deletion_confirmation_multi);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import com.tokenautocomplete.TokenCompleteTextView.TokenListener;
|
|||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
|
@ -142,7 +141,7 @@ public class EncryptModeAsymmetricFragment extends EncryptModeFragment {
|
|||
if (keyring.hasAnySecret()) {
|
||||
mSignKeySpinner.setPreSelectedKeyId(signatureKeyId);
|
||||
}
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
} catch (NotFoundException e) {
|
||||
Timber.e(e, "key not found for signing!");
|
||||
Notify.create(getActivity(), getString(R.string.error_preselect_sign_key,
|
||||
KeyFormattingUtils.beautifyKeyId(signatureKeyId)),
|
||||
|
|
|
@ -61,7 +61,6 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
|||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
|
@ -115,10 +114,9 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
|||
|
||||
// handle empty passphrases by directly returning an empty crypto input parcel
|
||||
try {
|
||||
CachedPublicKeyRing pubRing =
|
||||
KeyRepository.create(this).getCachedPublicKeyRing(requiredInput.getMasterKeyId());
|
||||
KeyRepository keyRepository = KeyRepository.create(this);
|
||||
// use empty passphrase for empty passphrase
|
||||
if (pubRing.getSecretKeyType(requiredInput.getSubKeyId()) == SecretKeyType.PASSPHRASE_EMPTY) {
|
||||
if (keyRepository.getSecretKeyType(requiredInput.getSubKeyId()) == SecretKeyType.PASSPHRASE_EMPTY) {
|
||||
// also return passphrase back to activity
|
||||
Intent returnIntent = new Intent();
|
||||
cryptoInputParcel = cryptoInputParcel.withPassphrase(new Passphrase(""), requiredInput.getSubKeyId());
|
||||
|
@ -299,7 +297,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
|||
userId = getString(R.string.user_id_no_name);
|
||||
}
|
||||
|
||||
keyType = cachedPublicKeyRing.getSecretKeyType(subKeyId);
|
||||
keyType = keyRepository.getSecretKeyType(subKeyId);
|
||||
switch (keyType) {
|
||||
case PASSPHRASE:
|
||||
message = getString(R.string.passphrase_for, userId);
|
||||
|
@ -316,7 +314,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
|||
throw new AssertionError("Unhandled SecretKeyType (should not happen)");
|
||||
}
|
||||
}
|
||||
} catch (PgpKeyNotFoundException | KeyRepository.NotFoundException e) {
|
||||
} catch (KeyRepository.NotFoundException e) {
|
||||
alert.setTitle(R.string.title_key_not_found);
|
||||
alert.setMessage(getString(R.string.key_not_found, mRequiredInput.getSubKeyId()));
|
||||
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
|
|
|
@ -54,8 +54,8 @@ import org.sufficientlysecure.keychain.livedata.GenericLiveData;
|
|||
import org.sufficientlysecure.keychain.model.Certification.CertDetails;
|
||||
import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter;
|
||||
|
@ -382,9 +382,8 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements OnB
|
|||
|
||||
byte[] fingerprint;
|
||||
try {
|
||||
fingerprint = KeyRepository.create(activity).getCachedPublicKeyRing(
|
||||
masterKeyId).getFingerprint();
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
fingerprint = KeyRepository.create(activity).getCachedPublicKeyRing(masterKeyId).getFingerprint();
|
||||
} catch (NotFoundException e) {
|
||||
throw new IllegalStateException("Key to verify linked id for must exist in db!");
|
||||
}
|
||||
|
||||
|
|
|
@ -483,8 +483,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
|
|||
private boolean keyHasPassphrase() {
|
||||
try {
|
||||
long masterKeyId = unifiedKeyInfo.master_key_id();
|
||||
SecretKeyType secretKeyType =
|
||||
keyRepository.getCachedPublicKeyRing(masterKeyId).getSecretKeyType(masterKeyId);
|
||||
SecretKeyType secretKeyType = keyRepository.getSecretKeyType(masterKeyId);
|
||||
switch (secretKeyType) {
|
||||
// all of these make no sense to ask
|
||||
case PASSPHRASE_EMPTY:
|
||||
|
|
|
@ -29,14 +29,12 @@ import android.os.SystemClock;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request.Builder;
|
||||
import okhttp3.Response;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverClient;
|
||||
import org.sufficientlysecure.keychain.keyimport.KeyserverClient.QueryFailedException;
|
||||
|
@ -48,11 +46,8 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
|
|||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing.IteratorWithIOThrow;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.ui.token.PublicKeyRetrievalLoader.KeyRetrievalResult;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.util.ParcelableProxy;
|
||||
|
@ -120,7 +115,6 @@ public abstract class PublicKeyRetrievalLoader extends AsyncTaskLoader<KeyRetrie
|
|||
log.add(LogType.MSG_RET_LOCAL_NOT_FOUND, 2);
|
||||
continue;
|
||||
}
|
||||
CachedPublicKeyRing cachedPublicKeyRing = keyRepository.getCachedPublicKeyRing(masterKeyId);
|
||||
|
||||
// TODO check fingerprint
|
||||
// if (!Arrays.equals(fingerprints, cachedPublicKeyRing.getFingerprint())) {
|
||||
|
@ -130,7 +124,7 @@ public abstract class PublicKeyRetrievalLoader extends AsyncTaskLoader<KeyRetrie
|
|||
// log.add(LogType.MSG_RET_LOCAL_FP_MATCH, 1);
|
||||
// }
|
||||
|
||||
switch (cachedPublicKeyRing.getSecretKeyType(keyId)) {
|
||||
switch (keyRepository.getSecretKeyType(keyId)) {
|
||||
case PASSPHRASE:
|
||||
case PASSPHRASE_EMPTY: {
|
||||
log.add(LogType.MSG_RET_LOCAL_SECRET, 1);
|
||||
|
|
|
@ -414,7 +414,7 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
|||
byte[] armoredSecretKey = databaseInteractor.getSecretKeyRingAsArmoredData(masterKeyId);
|
||||
secretKeyAdapter.focusItem(masterKeyId);
|
||||
connectionSend(armoredSecretKey, Long.toString(masterKeyId));
|
||||
} catch (IOException | NotFoundException | PgpGeneralException e) {
|
||||
} catch (IOException | NotFoundException e) {
|
||||
// TODO
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ CREATE TABLE IF NOT EXISTS certs(
|
|||
rank INTEGER NOT NULL,
|
||||
key_id_certifier INTEGER NOT NULL,
|
||||
type INTEGER NOT NULL,
|
||||
verified INTEGER AS VerificationStatus NOT NULL,
|
||||
verified INTEGER AS VerificationStatus NOT NULL DEFAULT 0,
|
||||
creation INTEGER NOT NULL,
|
||||
data BLOB NOT NULL,
|
||||
PRIMARY KEY(master_key_id, rank, key_id_certifier),
|
||||
|
|
|
@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS keys (
|
|||
can_encrypt INTEGER AS Boolean NOT NULL,
|
||||
can_authenticate INTEGER AS Boolean NOT NULL,
|
||||
is_revoked INTEGER AS Boolean NOT NULL,
|
||||
has_secret INTEGER AS SecretKeyType NOT NULL,
|
||||
has_secret INTEGER AS SecretKeyType NOT NULL DEFAULT 0,
|
||||
is_secure INTEGER AS Boolean NOT NULL,
|
||||
creation INTEGER NOT NULL,
|
||||
expiry INTEGER,
|
||||
|
@ -25,11 +25,12 @@ CREATE TABLE IF NOT EXISTS keys (
|
|||
|
||||
unifiedKeyView:
|
||||
CREATE VIEW unifiedKeyView AS
|
||||
SELECT keys.master_key_id, keys.fingerprint, MIN(user_packets.rank), user_packets.name, user_packets.email, user_packets.comment, keys.creation, keys.expiry, keys.is_revoked, keys.is_secure, certs.verified,
|
||||
SELECT keys.master_key_id, keys.fingerprint, MIN(user_packets.rank), user_packets.user_id, user_packets.name, user_packets.email, user_packets.comment, keys.creation, keys.expiry, keys.is_revoked, keys.is_secure, keys.can_certify, certs.verified,
|
||||
(EXISTS (SELECT * FROM user_packets AS dups WHERE dups.master_key_id != keys.master_key_id AND dups.rank = 0 AND dups.name = user_packets.name COLLATE NOCASE AND dups.email = user_packets.email COLLATE NOCASE )) AS has_duplicate_int,
|
||||
(EXISTS (SELECT * FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.has_secret != 0 )) AS has_any_secret_int,
|
||||
(EXISTS (SELECT * FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.can_authenticate != 0 )) AS has_auth_key_int,
|
||||
(EXISTS (SELECT * FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.can_encrypt != 0 )) AS has_encrypt_key_int,
|
||||
(SELECT key_id FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.can_encrypt != 0 LIMIT 1) AS has_encrypt_key_int,
|
||||
(SELECT key_id FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.can_sign != 0 LIMIT 1) AS has_sign_key_int,
|
||||
(SELECT key_id FROM keys AS k WHERE k.master_key_id = keys.master_key_id AND k.can_authenticate != 0 LIMIT 1) AS has_auth_key_int,
|
||||
GROUP_CONCAT(DISTINCT aTI.package_name) AS autocrypt_package_names_csv,
|
||||
GROUP_CONCAT(user_packets.user_id, '|||') AS user_id_list
|
||||
FROM keys
|
||||
|
@ -47,6 +48,10 @@ selectUnifiedKeyInfoByMasterKeyId:
|
|||
SELECT * FROM unifiedKeyView
|
||||
WHERE is_revoked = 0 AND master_key_id = ?;
|
||||
|
||||
selectUnifiedKeyInfoByMasterKeyIds:
|
||||
SELECT * FROM unifiedKeyView
|
||||
WHERE is_revoked = 0 AND master_key_id IN ?;
|
||||
|
||||
selectUnifiedKeyInfoSearchMailAddress:
|
||||
SELECT * FROM unifiedKeyView
|
||||
WHERE email LIKE ?
|
||||
|
@ -73,7 +78,19 @@ SELECT has_secret
|
|||
FROM keys
|
||||
WHERE key_id = ?;
|
||||
|
||||
selectEffectiveSignKeyIdByMasterKeyId:
|
||||
SELECT key_id
|
||||
FROM keys
|
||||
WHERE is_revoked = 0 AND is_secure = 1 AND has_secret > 1 AND ( expiry IS NULL OR expiry >= date('now') )
|
||||
AND can_sign = 1 AND master_key_id = ?;
|
||||
|
||||
selectEffectiveAuthKeyIdByMasterKeyId:
|
||||
SELECT key_id
|
||||
FROM keys
|
||||
WHERE is_revoked = 0 AND is_secure = 1 AND has_secret > 1 AND ( expiry IS NULL OR expiry >= date('now') )
|
||||
AND can_authenticate = 1 AND master_key_id = ?;
|
||||
|
||||
-- TODO move to KeySignatures.sq
|
||||
selectMasterKeyIdsBySigner:
|
||||
SELECT master_key_id
|
||||
FROM key_signatures WHERE signer_key_id IN ?;
|
||||
FROM key_signatures WHERE signer_key_id IN ?;
|
|
@ -1,5 +1,6 @@
|
|||
package org.sufficientlysecure.keychain;
|
||||
|
||||
|
||||
import org.junit.runners.model.InitializationError;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
|
|
@ -19,6 +19,13 @@
|
|||
package org.sufficientlysecure.keychain.operations;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Security;
|
||||
import java.security.Signature;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bouncycastle.bcpg.HashAlgorithmTags;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.eddsa.EdDSAEngine;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.eddsa.spec.EdDSANamedCurveTable;
|
||||
|
@ -44,13 +51,6 @@ import org.sufficientlysecure.keychain.ssh.AuthenticationResult;
|
|||
import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Security;
|
||||
import java.security.Signature;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@RunWith(KeychainTestRunner.class)
|
||||
public class AuthenticationOperationTest {
|
||||
|
||||
|
@ -160,7 +160,7 @@ public class AuthenticationOperationTest {
|
|||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||
|
||||
long masterKeyId = mStaticRingRsa.getMasterKeyId();
|
||||
Long authSubKeyId = keyRepository.getCachedPublicKeyRing(masterKeyId).getSecretAuthenticationId();
|
||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
|
||||
{ // sign challenge
|
||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||
|
@ -206,7 +206,7 @@ public class AuthenticationOperationTest {
|
|||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||
|
||||
long masterKeyId = mStaticRingEcDsa.getMasterKeyId();
|
||||
Long authSubKeyId = keyRepository.getCachedPublicKeyRing(masterKeyId).getSecretAuthenticationId();
|
||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
|
||||
{ // sign challenge
|
||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||
|
@ -252,7 +252,7 @@ public class AuthenticationOperationTest {
|
|||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||
|
||||
long masterKeyId = mStaticRingEdDsa.getMasterKeyId();
|
||||
Long authSubKeyId = keyRepository.getCachedPublicKeyRing(masterKeyId).getSecretAuthenticationId();
|
||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
|
||||
{ // sign challenge
|
||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||
|
@ -300,7 +300,7 @@ public class AuthenticationOperationTest {
|
|||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||
|
||||
long masterKeyId = mStaticRingDsa.getMasterKeyId();
|
||||
Long authSubKeyId = keyRepository.getCachedPublicKeyRing(masterKeyId).getSecretAuthenticationId();
|
||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
|
||||
{ // sign challenge
|
||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||
|
@ -345,7 +345,7 @@ public class AuthenticationOperationTest {
|
|||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||
|
||||
long masterKeyId = mStaticRingEcDsa.getMasterKeyId();
|
||||
Long authSubKeyId = keyRepository.getCachedPublicKeyRing(masterKeyId).getSecretAuthenticationId();
|
||||
Long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
|
||||
{ // sign challenge - should succeed with selected key allowed
|
||||
AuthenticationOperation op = new AuthenticationOperation(RuntimeEnvironment.application,
|
||||
|
|
|
@ -162,15 +162,6 @@ public class BackupOperationTest {
|
|||
|
||||
assertTrue("export must be a success", result);
|
||||
|
||||
long masterKeyId1, masterKeyId2;
|
||||
if (mStaticRing1.getMasterKeyId() < mStaticRing2.getMasterKeyId()) {
|
||||
masterKeyId1 = mStaticRing1.getMasterKeyId();
|
||||
masterKeyId2 = mStaticRing2.getMasterKeyId();
|
||||
} else {
|
||||
masterKeyId2 = mStaticRing1.getMasterKeyId();
|
||||
masterKeyId1 = mStaticRing2.getMasterKeyId();
|
||||
}
|
||||
|
||||
IteratorWithIOThrow<UncachedKeyRing> unc =
|
||||
UncachedKeyRing.fromStream(new ByteArrayInputStream(out.toByteArray()));
|
||||
|
||||
|
@ -178,7 +169,7 @@ public class BackupOperationTest {
|
|||
assertTrue("export must have two keys (1/2)", unc.hasNext());
|
||||
UncachedKeyRing ring = unc.next();
|
||||
Assert.assertEquals("first exported key has correct masterkeyid",
|
||||
masterKeyId1, ring.getMasterKeyId());
|
||||
mStaticRing2.getMasterKeyId(), ring.getMasterKeyId());
|
||||
assertFalse("first exported key must not be secret", ring.isSecret());
|
||||
assertFalse("there must be no local signatures in an exported keyring",
|
||||
checkForLocal(ring));
|
||||
|
@ -188,7 +179,7 @@ public class BackupOperationTest {
|
|||
assertTrue("export must have two keys (2/2)", unc.hasNext());
|
||||
UncachedKeyRing ring = unc.next();
|
||||
Assert.assertEquals("second exported key has correct masterkeyid",
|
||||
masterKeyId2, ring.getMasterKeyId());
|
||||
mStaticRing1.getMasterKeyId(), ring.getMasterKeyId());
|
||||
assertFalse("second exported key must not be secret", ring.isSecret());
|
||||
assertFalse("there must be no local signatures in an exported keyring",
|
||||
checkForLocal(ring));
|
||||
|
@ -205,7 +196,7 @@ public class BackupOperationTest {
|
|||
assertTrue("export must have four keys (1/4)", unc.hasNext());
|
||||
UncachedKeyRing ring = unc.next();
|
||||
Assert.assertEquals("1/4 exported key has correct masterkeyid",
|
||||
masterKeyId1, ring.getMasterKeyId());
|
||||
mStaticRing2.getMasterKeyId(), ring.getMasterKeyId());
|
||||
assertFalse("1/4 exported key must not be public", ring.isSecret());
|
||||
assertFalse("there must be no local signatures in an exported keyring",
|
||||
checkForLocal(ring));
|
||||
|
@ -213,7 +204,7 @@ public class BackupOperationTest {
|
|||
assertTrue("export must have four keys (2/4)", unc.hasNext());
|
||||
ring = unc.next();
|
||||
Assert.assertEquals("2/4 exported key has correct masterkeyid",
|
||||
masterKeyId1, ring.getMasterKeyId());
|
||||
mStaticRing2.getMasterKeyId(), ring.getMasterKeyId());
|
||||
assertTrue("2/4 exported key must be public", ring.isSecret());
|
||||
assertFalse("there must be no local signatures in an exported keyring",
|
||||
checkForLocal(ring));
|
||||
|
@ -223,7 +214,7 @@ public class BackupOperationTest {
|
|||
assertTrue("export must have four keys (3/4)", unc.hasNext());
|
||||
UncachedKeyRing ring = unc.next();
|
||||
Assert.assertEquals("3/4 exported key has correct masterkeyid",
|
||||
masterKeyId2, ring.getMasterKeyId());
|
||||
mStaticRing1.getMasterKeyId(), ring.getMasterKeyId());
|
||||
assertFalse("3/4 exported key must not be public", ring.isSecret());
|
||||
assertFalse("there must be no local signatures in an exported keyring",
|
||||
checkForLocal(ring));
|
||||
|
@ -231,7 +222,7 @@ public class BackupOperationTest {
|
|||
assertTrue("export must have four keys (4/4)", unc.hasNext());
|
||||
ring = unc.next();
|
||||
Assert.assertEquals("4/4 exported key has correct masterkeyid",
|
||||
masterKeyId2, ring.getMasterKeyId());
|
||||
mStaticRing1.getMasterKeyId(), ring.getMasterKeyId());
|
||||
assertTrue("4/4 exported key must be public", ring.isSecret());
|
||||
assertFalse("there must be no local signatures in an exported keyring",
|
||||
checkForLocal(ring));
|
||||
|
|
|
@ -149,8 +149,8 @@ public class CertifyOperationTest {
|
|||
{
|
||||
CanonicalizedPublicKeyRing ring = KeyWritableRepository.create(RuntimeEnvironment.application)
|
||||
.getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
|
||||
Assert.assertEquals("public key must not be marked verified prior to certification",
|
||||
VerificationStatus.UNVERIFIED, ring.getVerified());
|
||||
Assert.assertNull("public key must not be marked verified prior to certification",
|
||||
ring.getVerified());
|
||||
}
|
||||
|
||||
CertifyActionsParcel.Builder actions = CertifyActionsParcel.builder(mStaticRing1.getMasterKeyId());
|
||||
|
@ -164,21 +164,20 @@ public class CertifyOperationTest {
|
|||
CanonicalizedPublicKeyRing ring = KeyWritableRepository.create(RuntimeEnvironment.application)
|
||||
.getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
|
||||
Assert.assertEquals("new key must be verified now",
|
||||
VerificationStatus.UNVERIFIED, ring.getVerified());
|
||||
VerificationStatus.VERIFIED_SECRET, ring.getVerified());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCertifyAttribute() throws Exception {
|
||||
CertifyOperation op = new CertifyOperation(RuntimeEnvironment.application,
|
||||
KeyWritableRepository.create(RuntimeEnvironment.application), null, null);
|
||||
KeyWritableRepository keyWritableRepository = KeyWritableRepository.create(RuntimeEnvironment.application);
|
||||
CertifyOperation op = new CertifyOperation(RuntimeEnvironment.application, keyWritableRepository, null, null);
|
||||
|
||||
{
|
||||
CanonicalizedPublicKeyRing ring = KeyWritableRepository.create(RuntimeEnvironment.application)
|
||||
.getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
|
||||
Assert.assertEquals("public key must not be marked verified prior to certification",
|
||||
VerificationStatus.UNVERIFIED, ring.getVerified());
|
||||
CanonicalizedPublicKeyRing ring = keyWritableRepository.getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
|
||||
Assert.assertNull("public key must not be marked verified prior to certification",
|
||||
ring.getVerified());
|
||||
}
|
||||
|
||||
CertifyActionsParcel.Builder actions = CertifyActionsParcel.builder(mStaticRing1.getMasterKeyId());
|
||||
|
@ -189,8 +188,7 @@ public class CertifyOperationTest {
|
|||
Assert.assertTrue("certification must succeed", result.success());
|
||||
|
||||
{
|
||||
CanonicalizedPublicKeyRing ring = KeyWritableRepository.create(RuntimeEnvironment.application)
|
||||
.getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
|
||||
CanonicalizedPublicKeyRing ring = keyWritableRepository.getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId());
|
||||
Assert.assertEquals("new key must be verified now",
|
||||
VerificationStatus.VERIFIED_SECRET, ring.getVerified());
|
||||
}
|
||||
|
|
|
@ -105,8 +105,9 @@ public class PromoteKeyOperationTest {
|
|||
|
||||
@Test
|
||||
public void testPromote() throws Exception {
|
||||
KeyWritableRepository keyRepository = KeyWritableRepository.create(RuntimeEnvironment.application);
|
||||
PromoteKeyOperation op = new PromoteKeyOperation(RuntimeEnvironment.application,
|
||||
KeyWritableRepository.create(RuntimeEnvironment.application), null, null);
|
||||
keyRepository, null, null);
|
||||
|
||||
PromoteKeyResult result = op.execute(
|
||||
PromoteKeyringParcel.createPromoteKeyringParcel(mStaticRing.getMasterKeyId(), null, null), null);
|
||||
|
@ -114,15 +115,14 @@ public class PromoteKeyOperationTest {
|
|||
Assert.assertTrue("promotion must succeed", result.success());
|
||||
|
||||
{
|
||||
CachedPublicKeyRing ring = KeyWritableRepository.create(RuntimeEnvironment.application)
|
||||
.getCachedPublicKeyRing(mStaticRing.getMasterKeyId());
|
||||
CachedPublicKeyRing ring = keyRepository.getCachedPublicKeyRing(mStaticRing.getMasterKeyId());
|
||||
Assert.assertTrue("key must have a secret now", ring.hasAnySecret());
|
||||
|
||||
Iterator<UncachedPublicKey> it = mStaticRing.getPublicKeys();
|
||||
while (it.hasNext()) {
|
||||
long keyId = it.next().getKeyId();
|
||||
Assert.assertEquals("all subkeys must be gnu dummy",
|
||||
SecretKeyType.GNU_DUMMY, ring.getSecretKeyType(keyId));
|
||||
SecretKeyType.GNU_DUMMY, keyRepository.getSecretKeyType(keyId));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.bouncycastle.bcpg.PublicKeyEncSessionPacket;
|
|||
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
|
||||
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -54,7 +55,7 @@ import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength;
|
|||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureEncryptionAlgorithm;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem.MissingMdc;
|
||||
import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
|
|
|
@ -55,6 +55,7 @@ import org.sufficientlysecure.keychain.KeychainTestRunner;
|
|||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing.VerificationStatus;
|
||||
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
|
||||
|
@ -672,7 +673,7 @@ public class PgpKeyOperationTest {
|
|||
resetBuilder();
|
||||
builder.addRevokeSubkey(123L);
|
||||
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), 0);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
UncachedKeyRing otherModified = op.modifySecretKeyRing(secretRing, cryptoInput, builder.build()).getRing();
|
||||
|
||||
Assert.assertNull("revoking a nonexistent subkey should fail", otherModified);
|
||||
|
@ -869,7 +870,7 @@ public class PgpKeyOperationTest {
|
|||
securityTokenBuilder.addOrReplaceSubkeyChange(SubkeyChange.createMoveToSecurityTokenChange(keyId));
|
||||
|
||||
CanonicalizedSecretKeyRing secretRing =
|
||||
new CanonicalizedSecretKeyRing(ringSecurityToken.getEncoded(), 0);
|
||||
new CanonicalizedSecretKeyRing(ringSecurityToken.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
PgpKeyOperation op = new PgpKeyOperation(null);
|
||||
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, securityTokenBuilder.build());
|
||||
Assert.assertTrue("moveKeyToSecurityToken operation should be pending", result.isPending());
|
||||
|
@ -904,7 +905,7 @@ public class PgpKeyOperationTest {
|
|||
securityTokenBuilder.addOrReplaceSubkeyChange(SubkeyChange.createRecertifyChange(keyId, true));
|
||||
|
||||
CanonicalizedSecretKeyRing secretRing =
|
||||
new CanonicalizedSecretKeyRing(modified.getEncoded(), 0);
|
||||
new CanonicalizedSecretKeyRing(modified.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
PgpKeyOperation op = new PgpKeyOperation(null);
|
||||
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, securityTokenBuilder.build());
|
||||
Assert.assertTrue("moveKeyToSecurityToken operation should be pending", result.isPending());
|
||||
|
@ -1187,7 +1188,7 @@ public class PgpKeyOperationTest {
|
|||
|
||||
// we should still be able to modify it (and change its passphrase) without errors
|
||||
PgpKeyOperation op = new PgpKeyOperation(null);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), 0);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, otherCryptoInput, builder.build());
|
||||
Assert.assertTrue("key modification must succeed", result.success());
|
||||
Assert.assertFalse("log must not contain a warning",
|
||||
|
@ -1201,7 +1202,7 @@ public class PgpKeyOperationTest {
|
|||
modified = KeyringTestingHelper.injectPacket(modified, sKeyWithPassphrase.buf, sKeyWithPassphrase.position);
|
||||
|
||||
PgpKeyOperation op = new PgpKeyOperation(null);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), 0);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing,
|
||||
CryptoInputParcel.createCryptoInputParcel(otherPassphrase2), builder.build());
|
||||
Assert.assertTrue("key modification must succeed", result.success());
|
||||
|
@ -1214,7 +1215,7 @@ public class PgpKeyOperationTest {
|
|||
@Test
|
||||
public void testRestricted() throws Exception {
|
||||
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), 0);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
|
||||
builder.addUserId("discord");
|
||||
PgpKeyOperation op = new PgpKeyOperation(null);
|
||||
|
@ -1250,7 +1251,7 @@ public class PgpKeyOperationTest {
|
|||
try {
|
||||
|
||||
Assert.assertTrue("modified keyring must be secret", ring.isSecret());
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), 0);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
|
||||
PgpKeyOperation op = new PgpKeyOperation(null);
|
||||
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, parcel);
|
||||
|
@ -1323,7 +1324,7 @@ public class PgpKeyOperationTest {
|
|||
SaveKeyringParcel parcel, CryptoInputParcel cryptoInput, LogType expected)
|
||||
throws Exception {
|
||||
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), 0);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, parcel);
|
||||
|
||||
Assert.assertFalse(reason, result.success());
|
||||
|
@ -1337,7 +1338,7 @@ public class PgpKeyOperationTest {
|
|||
LogType expected)
|
||||
throws Exception {
|
||||
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), 0);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, cryptoInput, parcel);
|
||||
|
||||
Assert.assertFalse(reason, result.success());
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.KeychainTestRunner;
|
|||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing.VerificationStatus;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpCertifyOperation.PgpCertifyResult;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
|
||||
|
@ -188,7 +189,7 @@ public class UncachedKeyringMergeTest {
|
|||
|
||||
UncachedKeyRing modifiedA, modifiedB; {
|
||||
CanonicalizedSecretKeyRing secretRing =
|
||||
new CanonicalizedSecretKeyRing(ringA.getEncoded(), 0);
|
||||
new CanonicalizedSecretKeyRing(ringA.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
|
||||
resetBuilder();
|
||||
builder.addUserId("flim");
|
||||
|
@ -230,7 +231,7 @@ public class UncachedKeyringMergeTest {
|
|||
UncachedKeyRing modifiedA, modifiedB;
|
||||
long subKeyIdA, subKeyIdB;
|
||||
{
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ringA.getEncoded(), 0);
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ringA.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
|
||||
resetBuilder();
|
||||
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(
|
||||
|
@ -278,7 +279,7 @@ public class UncachedKeyringMergeTest {
|
|||
resetBuilder();
|
||||
builder.addRevokeSubkey(KeyringTestingHelper.getSubkeyId(ringA, 1));
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(
|
||||
ringA.getEncoded(), 0);
|
||||
ringA.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
modified = op.modifySecretKeyRing(secretRing,
|
||||
CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), builder.build()).getRing();
|
||||
}
|
||||
|
@ -301,10 +302,10 @@ public class UncachedKeyringMergeTest {
|
|||
|
||||
final UncachedKeyRing modified; {
|
||||
CanonicalizedPublicKeyRing publicRing = new CanonicalizedPublicKeyRing(
|
||||
pubRing.getEncoded(), 0);
|
||||
pubRing.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
|
||||
CanonicalizedSecretKey secretKey = new CanonicalizedSecretKeyRing(
|
||||
ringB.getEncoded(), 0).getSecretKey();
|
||||
ringB.getEncoded(), VerificationStatus.UNVERIFIED).getSecretKey();
|
||||
secretKey.unlock(new Passphrase());
|
||||
PgpCertifyOperation op = new PgpCertifyOperation();
|
||||
CertifyAction action = CertifyAction.createForUserIds(
|
||||
|
@ -379,7 +380,7 @@ public class UncachedKeyringMergeTest {
|
|||
builder.addUserAttribute(uat);
|
||||
|
||||
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(
|
||||
ringA.getEncoded(), 0);
|
||||
ringA.getEncoded(), VerificationStatus.UNVERIFIED);
|
||||
modified = op.modifySecretKeyRing(secretRing,
|
||||
CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase()), builder.build()).getRing();
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@ import java.net.URL;
|
|||
import java.security.Security;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
@ -45,14 +43,9 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
|||
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.util.InputData;
|
||||
|
@ -62,7 +55,7 @@ import org.sufficientlysecure.keychain.util.Passphrase;
|
|||
public class InteropTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpOnce() throws Exception {
|
||||
public static void setUpOnce() {
|
||||
Security.insertProviderAt(new BouncyCastleProvider(), 1);
|
||||
ShadowLog.stream = System.out;
|
||||
}
|
||||
|
@ -104,11 +97,11 @@ public class InteropTest {
|
|||
}
|
||||
}
|
||||
|
||||
private static final String asString(File json) throws Exception {
|
||||
private static String asString(File json) throws Exception {
|
||||
return new String(asBytes(json), "utf-8");
|
||||
}
|
||||
|
||||
private static final byte[] asBytes(File f) throws Exception {
|
||||
private static byte[] asBytes(File f) throws Exception {
|
||||
FileInputStream fin = null;
|
||||
try {
|
||||
fin = new FileInputStream(f);
|
||||
|
@ -123,16 +116,14 @@ public class InteropTest {
|
|||
private void runDecryptTest(JSONObject config, File base) throws Exception {
|
||||
File root = base.getParentFile();
|
||||
String baseName = getBaseName(base);
|
||||
CanonicalizedPublicKeyRing verify;
|
||||
UncachedKeyRing verify;
|
||||
if (config.has("verifyKey")) {
|
||||
verify = (CanonicalizedPublicKeyRing)
|
||||
readRingFromFile(new File(root, config.getString("verifyKey")));
|
||||
verify = readUncachedRingFromFile(new File(root, config.getString("verifyKey")));
|
||||
} else {
|
||||
verify = null;
|
||||
}
|
||||
|
||||
CanonicalizedSecretKeyRing decrypt = (CanonicalizedSecretKeyRing)
|
||||
readRingFromFile(new File(root, config.getString("decryptKey")));
|
||||
UncachedKeyRing decrypt = readUncachedRingFromFile(new File(root, config.getString("decryptKey")));
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ByteArrayInputStream in =
|
||||
|
@ -154,9 +145,10 @@ public class InteropTest {
|
|||
if (verify != null) {
|
||||
// Certain keys are too short, so we check appropriately.
|
||||
int code = result.getSignatureResult().getResult();
|
||||
Assert.assertTrue(base + ": should have a signature",
|
||||
(code == OpenPgpSignatureResult.RESULT_INVALID_KEY_INSECURE) ||
|
||||
(code == OpenPgpSignatureResult.RESULT_VALID_KEY_UNCONFIRMED));
|
||||
Assert.assertTrue(base + ": should have a signature (code: " + code + ")",
|
||||
code == OpenPgpSignatureResult.RESULT_INVALID_KEY_INSECURE ||
|
||||
code == OpenPgpSignatureResult.RESULT_VALID_KEY_UNCONFIRMED
|
||||
|| code == OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED);
|
||||
}
|
||||
OpenPgpMetadata metadata = result.getDecryptionMetadata();
|
||||
Assert.assertEquals(base + ": filesize must be correct",
|
||||
|
@ -168,11 +160,10 @@ public class InteropTest {
|
|||
private void runImportTest(JSONObject config, File base) throws Exception {
|
||||
File root = base.getParentFile();
|
||||
String baseName = getBaseName(base);
|
||||
CanonicalizedKeyRing pkr =
|
||||
readRingFromFile(new File(root, baseName + ".asc"));
|
||||
CanonicalizedKeyRing pkr = readRingFromFile(new File(root, baseName + ".asc"));
|
||||
|
||||
// Check we have the correct uids.
|
||||
ArrayList<String> expected = new ArrayList<String>();
|
||||
ArrayList<String> expected = new ArrayList<>();
|
||||
JSONArray uids = config.getJSONArray("expected_uids");
|
||||
for (int i = 0; i < uids.length(); i++) {
|
||||
expected.add(uids.getString(i));
|
||||
|
@ -188,7 +179,7 @@ public class InteropTest {
|
|||
expected.add(subkeys.getJSONObject(i).getString("expected_fingerprint"));
|
||||
}
|
||||
}
|
||||
ArrayList<String> actual = new ArrayList<String>();
|
||||
ArrayList<String> actual = new ArrayList<>();
|
||||
for (CanonicalizedPublicKey pk: pkr.publicKeyIterator()) {
|
||||
if (pk.isValid()) {
|
||||
actual.add(KeyFormattingUtils.convertFingerprintToHex(pk.getFingerprint()));
|
||||
|
@ -204,7 +195,7 @@ public class InteropTest {
|
|||
}
|
||||
}
|
||||
|
||||
UncachedKeyRing readUncachedRingFromFile(File path) throws Exception {
|
||||
private UncachedKeyRing readUncachedRingFromFile(File path) throws Exception {
|
||||
BufferedInputStream bin = null;
|
||||
try {
|
||||
bin = new BufferedInputStream(new FileInputStream(path));
|
||||
|
@ -214,87 +205,40 @@ public class InteropTest {
|
|||
}
|
||||
}
|
||||
|
||||
CanonicalizedKeyRing readRingFromFile(File path) throws Exception {
|
||||
private CanonicalizedKeyRing readRingFromFile(File path) throws Exception {
|
||||
UncachedKeyRing ukr = readUncachedRingFromFile(path);
|
||||
OperationLog log = new OperationLog();
|
||||
return ukr.canonicalize(log, 0);
|
||||
}
|
||||
|
||||
private static final void close(Closeable v) {
|
||||
private static void close(Closeable v) {
|
||||
if (v != null) {
|
||||
try {
|
||||
v.close();
|
||||
} catch (Throwable any) {
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final String getBaseName(File base) {
|
||||
private static String getBaseName(File base) {
|
||||
String name = base.getName();
|
||||
return name.substring(0, name.length() - ".json".length());
|
||||
}
|
||||
|
||||
private PgpDecryptVerifyOperation makeOperation(final String msg, final Passphrase passphrase,
|
||||
final CanonicalizedSecretKeyRing decrypt, final CanonicalizedPublicKeyRing verify)
|
||||
throws Exception {
|
||||
UncachedKeyRing decrypt, UncachedKeyRing verify) {
|
||||
KeyWritableRepository keyRepository = KeyWritableRepository.create(RuntimeEnvironment.application);
|
||||
|
||||
final long decryptId = decrypt.getEncryptId();
|
||||
final Uri decryptUri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(decryptId);
|
||||
final Uri verifyUri = verify != null ?
|
||||
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(verify.getMasterKeyId()) : null;
|
||||
|
||||
KeyWritableRepository helper = new KeyWritableRepository(RuntimeEnvironment.application,
|
||||
KeychainDatabase.getInstance(RuntimeEnvironment.application),
|
||||
LocalPublicKeyStorage.getInstance(RuntimeEnvironment.application),
|
||||
LocalSecretKeyStorage.getInstance(RuntimeEnvironment.application),
|
||||
DatabaseNotifyManager.create(RuntimeEnvironment.application),
|
||||
AutocryptPeerDao.getInstance(RuntimeEnvironment.application)) {
|
||||
Assert.assertTrue(keyRepository.saveSecretKeyRing(decrypt).success());
|
||||
if (verify != null) {
|
||||
Assert.assertTrue(keyRepository.savePublicKeyRing(verify).success());
|
||||
}
|
||||
|
||||
return new PgpDecryptVerifyOperation(RuntimeEnvironment.application, keyRepository, null) {
|
||||
@Override
|
||||
public CachedPublicKeyRing getCachedPublicKeyRing(Uri queryUri) throws PgpKeyNotFoundException {
|
||||
Assert.assertEquals(msg + ": query should be for the decryption key", queryUri, decryptUri);
|
||||
return new CachedPublicKeyRing(this, queryUri) {
|
||||
@Override
|
||||
public long getMasterKeyId() throws PgpKeyNotFoundException {
|
||||
return decrypt.getMasterKeyId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKeyType getSecretKeyType(long keyId) throws NotFoundException {
|
||||
return decrypt.getSecretKey(keyId).getSecretKeyTypeSuperExpensive();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public CanonicalizedPublicKeyRing getCanonicalizedPublicKeyRing(Uri q)
|
||||
throws NotFoundException {
|
||||
Assert.assertEquals(msg + ": query should be for verification key", q, verifyUri);
|
||||
return verify;
|
||||
}
|
||||
|
||||
public CanonicalizedSecretKeyRing getCanonicalizedSecretKeyRing(Uri q)
|
||||
throws NotFoundException {
|
||||
Assert.assertEquals(msg + ": query should be for the decryption key", q, decryptUri);
|
||||
return decrypt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CanonicalizedSecretKeyRing getCanonicalizedSecretKeyRing(long masterKeyId)
|
||||
throws NotFoundException {
|
||||
Assert.assertEquals(msg + ": query should be for the decryption key",
|
||||
masterKeyId, decrypt.getMasterKeyId());
|
||||
return decrypt;
|
||||
}
|
||||
};
|
||||
|
||||
return new PgpDecryptVerifyOperation(RuntimeEnvironment.application, helper, null) {
|
||||
@Override
|
||||
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId)
|
||||
throws NoSecretKeyException {
|
||||
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) {
|
||||
Assert.assertEquals(msg + ": passphrase should be for the secret key",
|
||||
masterKeyId, decrypt.getMasterKeyId());
|
||||
Assert.assertEquals(msg + ": passphrase should refer to the decryption subkey",
|
||||
subKeyId, decryptId);
|
||||
return passphrase;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
package org.sufficientlysecure.keychain.provider;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.junit.Assert;
|
||||
|
@ -36,9 +40,6 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
|||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
@RunWith(KeychainTestRunner.class)
|
||||
public class KeyRepositorySaveTest {
|
||||
|
||||
|
@ -153,9 +154,8 @@ public class KeyRepositorySaveTest {
|
|||
Assert.assertTrue("canCertify() should be true", key.canCertify());
|
||||
Assert.assertTrue("canSign() should be true", key.canSign());
|
||||
|
||||
// cached
|
||||
Assert.assertEquals("all subkeys from CachedPublicKeyRing should be divert-to-key",
|
||||
SecretKeyType.DIVERT_TO_CARD, cachedRing.getSecretKeyType(key.getKeyId()));
|
||||
SecretKeyType.DIVERT_TO_CARD, mDatabaseInteractor.getSecretKeyType(key.getKeyId()));
|
||||
}
|
||||
|
||||
{ // second subkey
|
||||
|
@ -169,7 +169,7 @@ public class KeyRepositorySaveTest {
|
|||
|
||||
// cached
|
||||
Assert.assertEquals("all subkeys from CachedPublicKeyRing should be divert-to-key",
|
||||
SecretKeyType.DIVERT_TO_CARD, cachedRing.getSecretKeyType(key.getKeyId()));
|
||||
SecretKeyType.DIVERT_TO_CARD, mDatabaseInteractor.getSecretKeyType(key.getKeyId()));
|
||||
}
|
||||
|
||||
{ // third subkey
|
||||
|
@ -183,7 +183,7 @@ public class KeyRepositorySaveTest {
|
|||
|
||||
// cached
|
||||
Assert.assertEquals("all subkeys from CachedPublicKeyRing should be divert-to-key",
|
||||
SecretKeyType.DIVERT_TO_CARD, cachedRing.getSecretKeyType(key.getKeyId()));
|
||||
SecretKeyType.DIVERT_TO_CARD, mDatabaseInteractor.getSecretKeyType(key.getKeyId()));
|
||||
}
|
||||
|
||||
Assert.assertFalse("keyring should have 3 subkeys (4)", it.hasNext());
|
||||
|
@ -233,14 +233,14 @@ public class KeyRepositorySaveTest {
|
|||
Assert.assertTrue("master key should have sign flag", ring.getPublicKey().canSign());
|
||||
Assert.assertTrue("master key should have encrypt flag", ring.getPublicKey().canEncrypt());
|
||||
|
||||
signId = mDatabaseInteractor.getCachedPublicKeyRing(masterKeyId).getSecretSignId();
|
||||
signId = mDatabaseInteractor.getSecretSignId(masterKeyId);
|
||||
Assert.assertNotEquals("encrypt id should not be 0", 0, signId);
|
||||
Assert.assertNotEquals("encrypt key should be different from master key", masterKeyId, signId);
|
||||
Assert.assertNotEquals("signing key should be different from master key", masterKeyId, signId);
|
||||
}
|
||||
|
||||
{
|
||||
CachedPublicKeyRing ring = mDatabaseInteractor.getCachedPublicKeyRing(masterKeyId);
|
||||
Assert.assertEquals("signing key should be same id cached as uncached", signId, ring.getSecretSignId());
|
||||
Assert.assertEquals("signing key should be same id cached as uncached",
|
||||
signId, mDatabaseInteractor.getSecretSignId(masterKeyId));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ public class SshPublicKeyTest {
|
|||
KeyRepository keyRepository = KeyRepository.create(RuntimeEnvironment.application);
|
||||
|
||||
long masterKeyId = mStaticRingEcDsa.getMasterKeyId();
|
||||
long authSubKeyId = keyRepository.getCachedPublicKeyRing(masterKeyId).getSecretAuthenticationId();
|
||||
long authSubKeyId = keyRepository.getSecretAuthenticationId(masterKeyId);
|
||||
CanonicalizedPublicKey canonicalizedPublicKey = keyRepository.getCanonicalizedPublicKeyRing(masterKeyId)
|
||||
.getPublicKey(authSubKeyId);
|
||||
|
||||
|
|
Loading…
Reference in a new issue