Merge pull request #2111 from open-keychain/auto-value

Auto value
This commit is contained in:
Vincent Breitmoser
2017-05-25 19:42:02 +02:00
committed by GitHub
99 changed files with 2074 additions and 2798 deletions

View File

@@ -24,6 +24,7 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.sufficientlysecure.keychain.securitytoken.KeyFormat;
import org.sufficientlysecure.keychain.securitytoken.RSAKeyFormat;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import java.io.File;
import java.net.Proxy;
@@ -178,12 +179,12 @@ public final class Constants {
/**
* Default key configuration: 3072 bit RSA (certify, sign, encrypt)
*/
public static void addDefaultSubkeys(SaveKeyringParcel saveKeyringParcel) {
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
public static void addDefaultSubkeys(SaveKeyringParcel.Builder builder) {
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
3072, null, KeyFlags.CERTIFY_OTHER, 0L));
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
3072, null, KeyFlags.SIGN_DATA, 0L));
saveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
3072, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L));
}

View File

@@ -129,7 +129,7 @@ public class ImportKeysListCloudLoader
mEntryList.clear();
GetKeyResult pendingResult = new GetKeyResult(null,
RequiredInputParcel.createOrbotRequiredOperation(),
new CryptoInputParcel());
CryptoInputParcel.createCryptoInputParcel());
mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, pendingResult);
return;
}

View File

@@ -71,7 +71,7 @@ import org.sufficientlysecure.keychain.util.Log;
* This class receives a source and/or destination of keys as input and performs
* all steps for this backup.
*
* @see org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter#getSelectedEntries()
* see org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter#getSelectedEntries()
* For the backup operation, the input consists of a set of key ids and
* either the name of a file or an output uri to write to.
*/
@@ -104,8 +104,8 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
OutputStream outputStream) {
OperationLog log = new OperationLog();
if (backupInput.mMasterKeyIds != null) {
log.add(LogType.MSG_BACKUP, 0, backupInput.mMasterKeyIds.length);
if (backupInput.getMasterKeyIds() != null) {
log.add(LogType.MSG_BACKUP, 0, backupInput.getMasterKeyIds().length);
} else {
log.add(LogType.MSG_BACKUP_ALL, 0);
}
@@ -113,7 +113,7 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
try {
Uri plainUri = null;
OutputStream plainOut;
if (backupInput.mIsEncrypted) {
if (backupInput.getIsEncrypted()) {
if (cryptoInput == null) {
throw new IllegalStateException("Encrypted backup must supply cryptoInput parameter");
}
@@ -121,23 +121,23 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
plainUri = TemporaryFileProvider.createFile(mContext);
plainOut = mContext.getContentResolver().openOutputStream(plainUri);
} else {
if (backupInput.mOutputUri == null || outputStream != null) {
if (backupInput.getOutputUri() == null || outputStream != null) {
throw new IllegalArgumentException("Unencrypted export to output stream is not supported!");
} else {
plainOut = mContext.getContentResolver().openOutputStream(backupInput.mOutputUri);
plainOut = mContext.getContentResolver().openOutputStream(backupInput.getOutputUri());
}
}
CountingOutputStream outStream = new CountingOutputStream(new BufferedOutputStream(plainOut));
boolean backupSuccess = exportKeysToStream(
log, backupInput.mMasterKeyIds, backupInput.mExportSecret, outStream);
log, backupInput.getMasterKeyIds(), backupInput.getExportSecret(), outStream);
if (!backupSuccess) {
// if there was an error, it will be in the log so we just have to return
return new ExportResult(ExportResult.RESULT_ERROR, log);
}
if (!backupInput.mIsEncrypted) {
if (!backupInput.getIsEncrypted()) {
// log.add(LogType.MSG_EXPORT_NO_ENCRYPT, 1);
log.add(LogType.MSG_BACKUP_SUCCESS, 1);
return new ExportResult(ExportResult.RESULT_OK, log);
@@ -170,27 +170,29 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
throws FileNotFoundException {
PgpSignEncryptOperation signEncryptOperation = new PgpSignEncryptOperation(mContext, mKeyRepository, mProgressable, mCancelled);
PgpSignEncryptData data = new PgpSignEncryptData();
data.setSymmetricPassphrase(cryptoInput.getPassphrase());
data.setEnableAsciiArmorOutput(backupInput.mEnableAsciiArmorOutput);
data.setAddBackupHeader(true);
PgpSignEncryptInputParcel inputParcel = new PgpSignEncryptInputParcel(data);
PgpSignEncryptData.Builder builder = PgpSignEncryptData.builder();
builder.setSymmetricPassphrase(cryptoInput.getPassphrase());
builder.setEnableAsciiArmorOutput(backupInput.getEnableAsciiArmorOutput());
builder.setAddBackupHeader(true);
PgpSignEncryptData pgpSignEncryptData = builder.build();
InputStream inStream = mContext.getContentResolver().openInputStream(plainUri);
String filename;
if (backupInput.mMasterKeyIds != null && backupInput.mMasterKeyIds.length == 1) {
filename = Constants.FILE_BACKUP_PREFIX + KeyFormattingUtils.convertKeyIdToHex(backupInput.mMasterKeyIds[0]);
long[] masterKeyIds = backupInput.getMasterKeyIds();
if (masterKeyIds != null && masterKeyIds.length == 1) {
filename = Constants.FILE_BACKUP_PREFIX + KeyFormattingUtils.convertKeyIdToHex(
masterKeyIds[0]);
} else {
filename = Constants.FILE_BACKUP_PREFIX + new SimpleDateFormat("yyyy-MM-dd", Locale
.getDefault()).format(new Date());
}
filename += backupInput.mExportSecret ? Constants.FILE_EXTENSION_BACKUP_SECRET : Constants.FILE_EXTENSION_BACKUP_PUBLIC;
filename += backupInput.getExportSecret() ? Constants.FILE_EXTENSION_BACKUP_SECRET : Constants.FILE_EXTENSION_BACKUP_PUBLIC;
InputData inputData = new InputData(inStream, exportedDataSize, filename);
OutputStream outStream;
if (backupInput.mOutputUri == null) {
if (backupInput.getOutputUri() == null) {
if (outputStream == null) {
throw new IllegalArgumentException("If output uri is not set, outputStream must not be null!");
}
@@ -199,10 +201,11 @@ public class BackupOperation extends BaseOperation<BackupKeyringParcel> {
if (outputStream != null) {
throw new IllegalArgumentException("If output uri is set, outputStream must null!");
}
outStream = mContext.getContentResolver().openOutputStream(backupInput.mOutputUri);
outStream = mContext.getContentResolver().openOutputStream(backupInput.getOutputUri());
}
return signEncryptOperation.execute(inputParcel, new CryptoInputParcel(), inputData, outStream);
return signEncryptOperation.execute(
pgpSignEncryptData, CryptoInputParcel.createCryptoInputParcel(), inputData, outStream);
}
boolean exportKeysToStream(OperationLog log, long[] masterKeyIds, boolean exportSecret, OutputStream outStream) {

View File

@@ -41,7 +41,6 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
@@ -83,12 +82,11 @@ public class BenchmarkOperation extends BaseOperation<BenchmarkInputParcel> {
SignEncryptOperation op =
new SignEncryptOperation(mContext, mKeyRepository,
new ProgressScaler(mProgressable, i*(50/numRepeats), (i+1)*(50/numRepeats), 100), mCancelled);
PgpSignEncryptData data = new PgpSignEncryptData();
PgpSignEncryptData.Builder data = PgpSignEncryptData.builder();
data.setSymmetricPassphrase(passphrase);
data.setSymmetricEncryptionAlgorithm(OpenKeychainSymmetricKeyAlgorithmTags.AES_128);
SignEncryptParcel input = new SignEncryptParcel(data);
input.setBytes(buf);
encryptResult = op.execute(input, new CryptoInputParcel());
data.setSymmetricEncryptionAlgorithm(SymmetricKeyAlgorithmTags.AES_128);
SignEncryptParcel input = SignEncryptParcel.createSignEncryptParcel(data.build(), buf);
encryptResult = op.execute(input, CryptoInputParcel.createCryptoInputParcel());
log.add(encryptResult, 1);
log.add(LogType.MSG_BENCH_ENC_TIME, 2,
String.format("%.2f", encryptResult.getResults().get(0).mOperationTime / 1000.0));
@@ -105,9 +103,10 @@ public class BenchmarkOperation extends BaseOperation<BenchmarkInputParcel> {
PgpDecryptVerifyOperation op =
new PgpDecryptVerifyOperation(mContext, mKeyRepository,
new ProgressScaler(mProgressable, 50 +i*(50/numRepeats), 50 +(i+1)*(50/numRepeats), 100));
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(encryptResult.getResultBytes());
input.setAllowSymmetricDecryption(true);
decryptResult = op.execute(input, new CryptoInputParcel(passphrase));
PgpDecryptVerifyInputParcel.Builder builder = PgpDecryptVerifyInputParcel.builder()
.setInputBytes(encryptResult.getResultBytes())
.setAllowSymmetricDecryption(true);
decryptResult = op.execute(builder.build(), CryptoInputParcel.createCryptoInputParcel(passphrase));
log.add(decryptResult, 1);
log.add(LogType.MSG_BENCH_DEC_TIME, 2, String.format("%.2f", decryptResult.mOperationTime / 1000.0));
totalTime += decryptResult.mOperationTime;

View File

@@ -76,7 +76,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
// Retrieve and unlock secret key
CanonicalizedSecretKey certificationKey;
long masterKeyId = parcel.mMasterKeyId;
long masterKeyId = parcel.getMasterKeyId();
try {
log.add(LogType.MSG_CRT_MASTER_FETCH, 1);
@@ -121,7 +121,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
// Get actual secret key
CanonicalizedSecretKeyRing secretKeyRing =
mKeyRepository.getCanonicalizedSecretKeyRing(parcel.mMasterKeyId);
mKeyRepository.getCanonicalizedSecretKeyRing(parcel.getMasterKeyId());
certificationKey = secretKeyRing.getSecretKey();
log.add(LogType.MSG_CRT_UNLOCK, 1);
@@ -148,7 +148,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
cryptoInput.getSignatureTime(), masterKeyId, masterKeyId);
// Work through all requested certifications
for (CertifyAction action : parcel.mCertifyActions) {
for (CertifyAction action : parcel.getCertifyActions()) {
// Check if we were cancelled
if (checkCancelled()) {
@@ -158,14 +158,14 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
try {
if (action.mMasterKeyId == parcel.mMasterKeyId) {
if (action.getMasterKeyId() == parcel.getMasterKeyId()) {
log.add(LogType.MSG_CRT_ERROR_SELF, 2);
certifyError += 1;
continue;
}
CanonicalizedPublicKeyRing publicRing =
mKeyRepository.getCanonicalizedPublicKeyRing(action.mMasterKeyId);
mKeyRepository.getCanonicalizedPublicKeyRing(action.getMasterKeyId());
PgpCertifyOperation op = new PgpCertifyOperation();
PgpCertifyResult result = op.certify(certificationKey, publicRing,
@@ -205,7 +205,7 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
// these variables are used inside the following loop, but they need to be created only once
UploadOperation uploadOperation = null;
if (parcel.keyServerUri != null) {
if (parcel.getParcelableKeyServer() != null) {
uploadOperation = new UploadOperation(mContext, mKeyRepository, mProgressable, mCancelled);
}
@@ -226,8 +226,8 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
SaveKeyringResult result = mKeyWritableRepository.savePublicKeyRing(certifiedKey);
if (uploadOperation != null) {
UploadKeyringParcel uploadInput =
new UploadKeyringParcel(parcel.keyServerUri, certifiedKey.getMasterKeyId());
UploadKeyringParcel uploadInput = UploadKeyringParcel.createWithKeyId(
parcel.getParcelableKeyServer(), certifiedKey.getMasterKeyId());
UploadResult uploadResult = uploadOperation.execute(uploadInput, cryptoInput);
log.add(uploadResult, 2);

View File

@@ -47,7 +47,7 @@ public class ChangeUnlockOperation extends BaseReadWriteOperation<ChangeUnlockPa
OperationResult.OperationLog log = new OperationResult.OperationLog();
log.add(OperationResult.LogType.MSG_ED, 0);
if (unlockParcel == null || unlockParcel.mMasterKeyId == null) {
if (unlockParcel == null || unlockParcel.getMasterKeyId() == null) {
log.add(OperationResult.LogType.MSG_ED_ERROR_NO_PARCEL, 1);
return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
}
@@ -60,10 +60,10 @@ public class ChangeUnlockOperation extends BaseReadWriteOperation<ChangeUnlockPa
try {
log.add(OperationResult.LogType.MSG_ED_FETCHING, 1,
KeyFormattingUtils.convertKeyIdToHex(unlockParcel.mMasterKeyId));
KeyFormattingUtils.convertKeyIdToHex(unlockParcel.getMasterKeyId()));
CanonicalizedSecretKeyRing secRing =
mKeyRepository.getCanonicalizedSecretKeyRing(unlockParcel.mMasterKeyId);
mKeyRepository.getCanonicalizedSecretKeyRing(unlockParcel.getMasterKeyId());
modifyResult = keyOperations.modifyKeyRingPassphrase(secRing, cryptoInput, unlockParcel);
if (modifyResult.isPending()) {

View File

@@ -39,7 +39,7 @@ public class ConsolidateOperation extends BaseReadWriteOperation<ConsolidateInpu
@Override
public ConsolidateResult execute(ConsolidateInputParcel consolidateInputParcel,
CryptoInputParcel cryptoInputParcel) {
if (consolidateInputParcel.mConsolidateRecovery) {
if (consolidateInputParcel.isStartFromRecovery()) {
return mKeyWritableRepository.consolidateDatabaseStep2(mProgressable);
} else {
return mKeyWritableRepository.consolidateDatabaseStep1(mProgressable);

View File

@@ -52,8 +52,8 @@ public class DeleteOperation extends BaseReadWriteOperation<DeleteKeyringParcel>
public OperationResult execute(DeleteKeyringParcel deleteKeyringParcel,
CryptoInputParcel cryptoInputParcel) {
long[] masterKeyIds = deleteKeyringParcel.mMasterKeyIds;
boolean isSecret = deleteKeyringParcel.mIsSecret;
long[] masterKeyIds = deleteKeyringParcel.getMasterKeyIds();
boolean isSecret = deleteKeyringParcel.isDeleteSecret();
return onlyDeleteKey(masterKeyIds, isSecret);
}

View File

@@ -88,13 +88,13 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
new PgpKeyOperation(new ProgressScaler(mProgressable, 10, 60, 100), mCancelled);
// If a key id is specified, fetch and edit
if (saveParcel.mMasterKeyId != null) {
if (saveParcel.getMasterKeyId() != null) {
try {
log.add(LogType.MSG_ED_FETCHING, 1,
KeyFormattingUtils.convertKeyIdToHex(saveParcel.mMasterKeyId));
KeyFormattingUtils.convertKeyIdToHex(saveParcel.getMasterKeyId()));
CanonicalizedSecretKeyRing secRing =
mKeyRepository.getCanonicalizedSecretKeyRing(saveParcel.mMasterKeyId);
mKeyRepository.getCanonicalizedSecretKeyRing(saveParcel.getMasterKeyId());
modifyResult = keyOperations.modifySecretKeyRing(secRing, cryptoInput, saveParcel);
if (modifyResult.isPending()) {
@@ -133,7 +133,7 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
// It's a success, so this must be non-null now
UncachedKeyRing ring = modifyResult.getRing();
if (saveParcel.isUpload()) {
if (saveParcel.isShouldUpload()) {
byte[] keyringBytes;
try {
UncachedKeyRing publicKeyRing = ring.extractPublicKeyRing();
@@ -144,7 +144,7 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
}
UploadKeyringParcel exportKeyringParcel =
new UploadKeyringParcel(saveParcel.getUploadKeyserver(), keyringBytes);
UploadKeyringParcel.createWithKeyringBytes(saveParcel.getUploadKeyserver(), keyringBytes);
UploadResult uploadResult = new UploadOperation(
mContext, mKeyRepository, new ProgressScaler(mProgressable, 60, 80, 100), mCancelled)
@@ -154,7 +154,7 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
if (uploadResult.isPending()) {
return new EditKeyResult(log, uploadResult);
} else if (!uploadResult.success() && saveParcel.isUploadAtomic()) {
} else if (!uploadResult.success() && saveParcel.isShouldUploadAtomic()) {
// if atomic, update fail implies edit operation should also fail and not save
return new EditKeyResult(log, RequiredInputParcel.createRetryUploadOperation(), cryptoInput);
}

View File

@@ -469,9 +469,9 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
@NonNull
@Override
public ImportKeyResult execute(ImportKeyringParcel importInput, CryptoInputParcel cryptoInput) {
ArrayList<ParcelableKeyRing> keyList = importInput.mKeyList;
ParcelableHkpKeyserver keyServer = importInput.mKeyserver;
boolean skipSave = importInput.mSkipSave;
ArrayList<ParcelableKeyRing> keyList = importInput.getKeyList();
ParcelableHkpKeyserver keyServer = importInput.getKeyserver();
boolean skipSave = importInput.isSkipSave();
ImportKeyResult result;
if (keyList == null) {// import from file, do serially
@@ -495,7 +495,7 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
result = multiThreadedKeyImport(keyList, keyServer, proxy, skipSave);
}
if (!importInput.mSkipSave) {
if (!skipSave) {
ContactSyncAdapterService.requestContactsSync();
}
return result;

View File

@@ -103,10 +103,12 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
PgpDecryptVerifyOperation op =
new PgpDecryptVerifyOperation(mContext, mKeyRepository, mProgressable);
decryptInput.setInputUri(input.getInputUri());
currentInputUri = TemporaryFileProvider.createFile(mContext);
decryptInput.setOutputUri(currentInputUri);
decryptInput = decryptInput.toBuilder()
.setInputUri(input.getInputUri())
.setOutputUri(currentInputUri)
.build();
decryptResult = op.execute(decryptInput, cryptoInput);
if (decryptResult.isPending()) {
@@ -264,9 +266,10 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
}
detachedSig.close();
PgpDecryptVerifyInputParcel decryptInput = new PgpDecryptVerifyInputParcel();
decryptInput.setInputUri(uncheckedSignedDataUri);
decryptInput.setDetachedSignature(detachedSig.toByteArray());
PgpDecryptVerifyInputParcel decryptInput = PgpDecryptVerifyInputParcel.builder()
.setInputUri(uncheckedSignedDataUri)
.setDetachedSignature(detachedSig.toByteArray())
.build();
PgpDecryptVerifyOperation op =
new PgpDecryptVerifyOperation(mContext, mKeyRepository, mProgressable);

View File

@@ -152,9 +152,11 @@ public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificat
PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(mContext, mKeyRepository, mProgressable);
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(messageBytes);
PgpDecryptVerifyInputParcel input = PgpDecryptVerifyInputParcel.builder()
.setInputBytes(messageBytes)
.build();
DecryptVerifyResult decryptVerifyResult = op.execute(input, new CryptoInputParcel());
DecryptVerifyResult decryptVerifyResult = op.execute(input, CryptoInputParcel.createCryptoInputParcel());
if (!decryptVerifyResult.success()) {
log.add(decryptVerifyResult, 1);

View File

@@ -38,7 +38,6 @@ import org.sufficientlysecure.keychain.provider.KeyWritableRepository;
import org.sufficientlysecure.keychain.service.PromoteKeyringParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.ProgressScaler;
/** An operation which promotes a public key ring to a secret one.
*
@@ -67,17 +66,18 @@ public class PromoteKeyOperation extends BaseReadWriteOperation<PromoteKeyringPa
try {
log.add(LogType.MSG_PR_FETCHING, 1,
KeyFormattingUtils.convertKeyIdToHex(promoteKeyringParcel.mKeyRingId));
KeyFormattingUtils.convertKeyIdToHex(promoteKeyringParcel.getMasterKeyId()));
CanonicalizedPublicKeyRing pubRing =
mKeyRepository.getCanonicalizedPublicKeyRing(promoteKeyringParcel.mKeyRingId);
mKeyRepository.getCanonicalizedPublicKeyRing(promoteKeyringParcel.getMasterKeyId());
if (promoteKeyringParcel.mSubKeyIds == null) {
long[] subKeyIds = promoteKeyringParcel.getSubKeyIds();
if (subKeyIds == null) {
log.add(LogType.MSG_PR_ALL, 1);
} else {
// sort for binary search
for (CanonicalizedPublicKey key : pubRing.publicKeyIterator()) {
long subKeyId = key.getKeyId();
if (naiveIndexOf(promoteKeyringParcel.mSubKeyIds, subKeyId) != null) {
if (naiveIndexOf(subKeyIds, subKeyId) != null) {
log.add(LogType.MSG_PR_SUBKEY_MATCH, 1,
KeyFormattingUtils.convertKeyIdToHex(subKeyId));
} else {
@@ -88,8 +88,7 @@ public class PromoteKeyOperation extends BaseReadWriteOperation<PromoteKeyringPa
}
// create divert-to-card secret key from public key
promotedRing = pubRing.createDivertSecretRing(promoteKeyringParcel.mCardAid,
promoteKeyringParcel.mSubKeyIds);
promotedRing = pubRing.createDivertSecretRing(promoteKeyringParcel.getCardAid(), subKeyIds);
} catch (NotFoundException e) {
log.add(LogType.MSG_PR_ERROR_KEY_NOT_FOUND, 2);

View File

@@ -51,9 +51,9 @@ public class RevokeOperation extends BaseReadWriteOperation<RevokeKeyringParcel>
CryptoInputParcel cryptoInputParcel) {
// we don't cache passphrases during revocation
cryptoInputParcel.mCachePassphrase = false;
cryptoInputParcel = cryptoInputParcel.withNoCachePassphrase();
long masterKeyId = revokeKeyringParcel.mMasterKeyId;
long masterKeyId = revokeKeyringParcel.getMasterKeyId();
OperationResult.OperationLog log = new OperationResult.OperationLog();
log.add(OperationResult.LogType.MSG_REVOKE, 0,
@@ -71,17 +71,18 @@ public class RevokeOperation extends BaseReadWriteOperation<RevokeKeyringParcel>
return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId);
}
SaveKeyringParcel saveKeyringParcel =
new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
SaveKeyringParcel.Builder saveKeyringParcel =
SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
// all revoke operations are made atomic as of now
saveKeyringParcel.setUpdateOptions(revokeKeyringParcel.mUpload, true,
revokeKeyringParcel.mKeyserver);
saveKeyringParcel.setUpdateOptions(revokeKeyringParcel.isShouldUpload(), true,
revokeKeyringParcel.getKeyserver());
saveKeyringParcel.mRevokeSubKeys.add(masterKeyId);
saveKeyringParcel.addRevokeSubkey(masterKeyId);
EditKeyResult revokeAndUploadResult = new EditKeyOperation(mContext,
mKeyWritableRepository, mProgressable, mCancelled).execute(saveKeyringParcel, cryptoInputParcel);
mKeyWritableRepository, mProgressable, mCancelled).execute(
saveKeyringParcel.build(), cryptoInputParcel);
if (revokeAndUploadResult.isPending()) {
return revokeAndUploadResult;

View File

@@ -26,7 +26,6 @@ import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
@@ -36,13 +35,11 @@ import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenSignOperationsBuilder;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressScaler;
@@ -76,20 +73,6 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
SecurityTokenSignOperationsBuilder pendingInputBuilder = null;
PgpSignEncryptData data = input.getData();
// if signing subkey has not explicitly been set, get first usable subkey capable of signing
if (data.getSignatureMasterKeyId() != Constants.key.none
&& data.getSignatureSubKeyId() == null) {
try {
long signKeyId = mKeyRepository.getCachedPublicKeyRing(
data.getSignatureMasterKeyId()).getSecretSignId();
data.setSignatureSubKeyId(signKeyId);
} catch (PgpKeyNotFoundException e) {
Log.e(Constants.TAG, "Key not found", e);
return new SignEncryptResult(SignEncryptResult.RESULT_ERROR, log, results);
}
}
do {
if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED, 0);
@@ -98,13 +81,14 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
PgpSignEncryptOperation op = new PgpSignEncryptOperation(mContext, mKeyRepository,
new ProgressScaler(mProgressable, 100 * count / total, 100 * ++count / total, 100), mCancelled);
PgpSignEncryptInputParcel inputParcel = new PgpSignEncryptInputParcel(input.getData());
PgpSignEncryptInputParcel inputParcel;
if (inputBytes != null) {
inputParcel.setInputBytes(inputBytes);
inputParcel = PgpSignEncryptInputParcel.createForBytes(
input.getSignEncryptData(), outputUris.pollFirst(), inputBytes);
} else {
inputParcel.setInputUri(inputUris.removeFirst());
inputParcel = PgpSignEncryptInputParcel.createForInputUri(
input.getSignEncryptData(), outputUris.pollFirst(), inputUris.removeFirst());
}
inputParcel.setOutputUri(outputUris.pollFirst());
PgpSignEncryptResult result = op.execute(inputParcel, cryptoInput);
results.add(result);
@@ -118,7 +102,7 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
}
if (pendingInputBuilder == null) {
pendingInputBuilder = new SecurityTokenSignOperationsBuilder(requiredInput.mSignatureTime,
data.getSignatureMasterKeyId(), data.getSignatureSubKeyId());
requiredInput.getMasterKeyId(), requiredInput.getSubKeyId());
}
pendingInputBuilder.addAll(requiredInput);
} else if (!result.success()) {

View File

@@ -96,7 +96,7 @@ public class UploadOperation extends BaseOperation<UploadKeyringParcel> {
ParcelableHkpKeyserver hkpKeyserver;
{
hkpKeyserver = uploadInput.mKeyserver;
hkpKeyserver = uploadInput.getKeyserver();
log.add(LogType.MSG_UPLOAD_SERVER, 1, hkpKeyserver.toString());
}
@@ -110,22 +110,15 @@ public class UploadOperation extends BaseOperation<UploadKeyringParcel> {
@Nullable
private CanonicalizedPublicKeyRing getPublicKeyringFromInput(OperationLog log, UploadKeyringParcel uploadInput) {
boolean hasMasterKeyId = uploadInput.mMasterKeyId != null;
boolean hasKeyringBytes = uploadInput.mUncachedKeyringBytes != null;
if (hasMasterKeyId == hasKeyringBytes) {
throw new IllegalArgumentException("either keyid xor bytes must be non-null for this method call!");
}
try {
if (hasMasterKeyId) {
log.add(LogType.MSG_UPLOAD_KEY, 0, KeyFormattingUtils.convertKeyIdToHex(uploadInput.mMasterKeyId));
return mKeyRepository.getCanonicalizedPublicKeyRing(uploadInput.mMasterKeyId);
Long masterKeyId = uploadInput.getMasterKeyId();
if (masterKeyId != null) {
log.add(LogType.MSG_UPLOAD_KEY, 0, KeyFormattingUtils.convertKeyIdToHex(masterKeyId));
return mKeyRepository.getCanonicalizedPublicKeyRing(masterKeyId);
}
CanonicalizedKeyRing canonicalizedRing =
UncachedKeyRing.decodeFromData(uploadInput.mUncachedKeyringBytes)
UncachedKeyRing.decodeFromData(uploadInput.getUncachedKeyringBytes())
.canonicalize(new OperationLog(), 0, true);
if (!CanonicalizedPublicKeyRing.class.isInstance(canonicalizedRing)) {
throw new IllegalArgumentException("keyring bytes must contain public key ring!");

View File

@@ -1,121 +0,0 @@
/*
* Copyright (C) 2016 Vincent Breitmoser <look@my.amazin.horse>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.pgp;
import java.util.Arrays;
import android.os.Parcel;
import android.os.Parcelable;
import org.bouncycastle.bcpg.S2K;
/** This is an immutable and parcelable class which stores the full s2k parametrization
* of an encrypted secret key, i.e. all fields of the {@link S2K} class (type, hash algo,
* iteration count, iv) plus the encryptionAlgorithm. This class is intended to be used
* as key in a HashMap for session key caching purposes, and overrides the
* {@link #hashCode} and {@link #equals} methods in a suitable way.
*
* Note that although it is a rather unlikely scenario that secret keys of the same key
* are encrypted with different ciphers, the encryption algorithm still determines the
* length of the specific session key and thus needs to be considered for purposes of
* session key caching.
*
* @see org.bouncycastle.bcpg.S2K
*/
public class ComparableS2K implements Parcelable {
private final int encryptionAlgorithm;
private final int s2kType;
private final int s2kHashAlgo;
private final long s2kItCount;
private final byte[] s2kIV;
Integer cachedHashCode;
public ComparableS2K(int encryptionAlgorithm, S2K s2k) {
this.encryptionAlgorithm = encryptionAlgorithm;
this.s2kType = s2k.getType();
this.s2kHashAlgo = s2k.getHashAlgorithm();
this.s2kItCount = s2k.getIterationCount();
this.s2kIV = s2k.getIV();
}
protected ComparableS2K(Parcel in) {
encryptionAlgorithm = in.readInt();
s2kType = in.readInt();
s2kHashAlgo = in.readInt();
s2kItCount = in.readLong();
s2kIV = in.createByteArray();
}
@Override
public int hashCode() {
if (cachedHashCode == null) {
cachedHashCode = encryptionAlgorithm;
cachedHashCode = 31 * cachedHashCode + s2kType;
cachedHashCode = 31 * cachedHashCode + s2kHashAlgo;
cachedHashCode = 31 * cachedHashCode + (int) (s2kItCount ^ (s2kItCount >>> 32));
cachedHashCode = 31 * cachedHashCode + Arrays.hashCode(s2kIV);
}
return cachedHashCode;
}
@Override
public boolean equals(Object o) {
boolean isComparableS2K = o instanceof ComparableS2K;
if (!isComparableS2K) {
return false;
}
ComparableS2K other = (ComparableS2K) o;
return encryptionAlgorithm == other.encryptionAlgorithm
&& s2kType == other.s2kType
&& s2kHashAlgo == other.s2kHashAlgo
&& s2kItCount == other.s2kItCount
&& Arrays.equals(s2kIV, other.s2kIV);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(encryptionAlgorithm);
dest.writeInt(s2kType);
dest.writeInt(s2kHashAlgo);
dest.writeLong(s2kItCount);
dest.writeByteArray(s2kIV);
}
public static final Creator<ComparableS2K> CREATOR = new Creator<ComparableS2K>() {
@Override
public ComparableS2K createFromParcel(Parcel in) {
return new ComparableS2K(in);
}
@Override
public ComparableS2K[] newArray(int size) {
return new ComparableS2K[size];
}
};
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2016 Vincent Breitmoser <look@my.amazin.horse>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.pgp;
import android.os.Parcelable;
import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
import org.bouncycastle.bcpg.S2K;
/** This is an immutable and parcelable class which stores the full s2k parametrization
* of an encrypted secret key, i.e. all fields of the {@link S2K} class (type, hash algo,
* iteration count, iv) plus the encryptionAlgorithm. This class is intended to be used
* as key in a HashMap for session key caching purposes, and overrides the
* {@link #hashCode} and {@link #equals} methods in a suitable way.
*
* Note that although it is a rather unlikely scenario that secret keys of the same key
* are encrypted with different ciphers, the encryption algorithm still determines the
* length of the specific session key and thus needs to be considered for purposes of
* session key caching.
*
* @see org.bouncycastle.bcpg.S2K
*/
@AutoValue
public abstract class ParcelableS2K implements Parcelable {
abstract int getEncryptionAlgorithm();
abstract int getS2kType();
abstract int getS2kHashAlgo();
abstract long getS2kItCount();
@SuppressWarnings("mutable")
abstract byte[] getS2kIV();
@Memoized
@Override
public abstract int hashCode();
public static ParcelableS2K fromS2K(int encryptionAlgorithm, S2K s2k) {
return new AutoValue_ParcelableS2K(encryptionAlgorithm,
s2k.getType(), s2k.getHashAlgorithm(), s2k.getIterationCount(), s2k.getIV());
}
}

View File

@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
@@ -80,12 +81,13 @@ public class PgpCertifyOperation {
publicKey.getKeyID(), publicKey.getKeyID());
try {
if (action.mUserIds != null) {
log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(),
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
ArrayList<String> userIds = action.getUserIds();
if (userIds != null && !userIds.isEmpty()) {
log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, userIds.size(),
KeyFormattingUtils.convertKeyIdToHex(action.getMasterKeyId()));
// fetch public key ring, add the certification and return it
for (String userId : action.mUserIds) {
for (String userId : userIds) {
try {
PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey);
publicKey = PGPPublicKey.addCertification(publicKey, userId, sig);
@@ -96,12 +98,13 @@ public class PgpCertifyOperation {
}
if (action.mUserAttributes != null) {
log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, action.mUserAttributes.size(),
KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId));
ArrayList<WrappedUserAttribute> userAttributes = action.getUserAttributes();
if (userAttributes != null && !userAttributes.isEmpty()) {
log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, userAttributes.size(),
KeyFormattingUtils.convertKeyIdToHex(action.getMasterKeyId()));
// fetch public key ring, add the certification and return it
for (WrappedUserAttribute userAttribute : action.mUserAttributes) {
for (WrappedUserAttribute userAttribute : userAttributes) {
PGPUserAttributeSubpacketVector vector = userAttribute.getVector();
try {
PGPSignature sig = signatureGenerator.generateCertification(vector, publicKey);

View File

@@ -19,152 +19,69 @@
package org.sufficientlysecure.keychain.pgp;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
public class PgpDecryptVerifyInputParcel implements Parcelable {
import com.google.auto.value.AutoValue;
private Uri mInputUri;
private Uri mOutputUri;
private byte[] mInputBytes;
private boolean mAllowSymmetricDecryption;
private HashSet<Long> mAllowedKeyIds;
private boolean mDecryptMetadataOnly;
private byte[] mDetachedSignature;
private String mRequiredSignerFingerprint;
private String mSenderAddress;
@AutoValue
public abstract class PgpDecryptVerifyInputParcel implements Parcelable {
@Nullable
@SuppressWarnings("mutable")
abstract byte[] getInputBytes();
public PgpDecryptVerifyInputParcel() {
@Nullable
abstract Uri getInputUri();
@Nullable
abstract Uri getOutputUri();
abstract boolean isAllowSymmetricDecryption();
abstract boolean isDecryptMetadataOnly();
@Nullable
abstract List<Long> getAllowedKeyIds();
@Nullable
@SuppressWarnings("mutable")
abstract byte[] getDetachedSignature();
@Nullable
abstract String getSenderAddress();
public abstract Builder toBuilder();
public static Builder builder() {
return new AutoValue_PgpDecryptVerifyInputParcel.Builder()
.setAllowSymmetricDecryption(false)
.setDecryptMetadataOnly(false);
}
public PgpDecryptVerifyInputParcel(Uri inputUri, Uri outputUri) {
mInputUri = inputUri;
mOutputUri = outputUri;
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setInputBytes(byte[] inputBytes);
public abstract Builder setInputUri(Uri inputUri);
public abstract Builder setOutputUri(Uri outputUri);
public PgpDecryptVerifyInputParcel(byte[] inputBytes) {
mInputBytes = inputBytes;
}
public abstract Builder setAllowSymmetricDecryption(boolean allowSymmetricDecryption);
public abstract Builder setDecryptMetadataOnly(boolean decryptMetadataOnly);
public abstract Builder setDetachedSignature(byte[] detachedSignature);
public abstract Builder setSenderAddress(String senderAddress);
PgpDecryptVerifyInputParcel(Parcel source) {
// we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
mInputUri = source.readParcelable(getClass().getClassLoader());
mOutputUri = source.readParcelable(getClass().getClassLoader());
mInputBytes = source.createByteArray();
public abstract Builder setAllowedKeyIds(List<Long> allowedKeyIds);
abstract List<Long> getAllowedKeyIds();
mAllowSymmetricDecryption = source.readInt() != 0;
mAllowedKeyIds = (HashSet<Long>) source.readSerializable();
mDecryptMetadataOnly = source.readInt() != 0;
mDetachedSignature = source.createByteArray();
mRequiredSignerFingerprint = source.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mInputUri, 0);
dest.writeParcelable(mOutputUri, 0);
dest.writeByteArray(mInputBytes);
dest.writeInt(mAllowSymmetricDecryption ? 1 : 0);
dest.writeSerializable(mAllowedKeyIds);
dest.writeInt(mDecryptMetadataOnly ? 1 : 0);
dest.writeByteArray(mDetachedSignature);
dest.writeString(mRequiredSignerFingerprint);
}
byte[] getInputBytes() {
return mInputBytes;
}
public PgpDecryptVerifyInputParcel setInputUri(Uri uri) {
mInputUri = uri;
return this;
}
Uri getInputUri() {
return mInputUri;
}
public PgpDecryptVerifyInputParcel setOutputUri(Uri uri) {
mOutputUri = uri;
return this;
}
Uri getOutputUri() {
return mOutputUri;
}
boolean isAllowSymmetricDecryption() {
return mAllowSymmetricDecryption;
}
public PgpDecryptVerifyInputParcel setAllowSymmetricDecryption(boolean allowSymmetricDecryption) {
mAllowSymmetricDecryption = allowSymmetricDecryption;
return this;
}
HashSet<Long> getAllowedKeyIds() {
return mAllowedKeyIds;
}
public PgpDecryptVerifyInputParcel setAllowedKeyIds(HashSet<Long> allowedKeyIds) {
mAllowedKeyIds = allowedKeyIds;
return this;
}
boolean isDecryptMetadataOnly() {
return mDecryptMetadataOnly;
}
public PgpDecryptVerifyInputParcel setDecryptMetadataOnly(boolean decryptMetadataOnly) {
mDecryptMetadataOnly = decryptMetadataOnly;
return this;
}
byte[] getDetachedSignature() {
return mDetachedSignature;
}
public PgpDecryptVerifyInputParcel setDetachedSignature(byte[] detachedSignature) {
mDetachedSignature = detachedSignature;
return this;
}
public PgpDecryptVerifyInputParcel setSenderAddress(String senderAddress) {
mSenderAddress = senderAddress;
return this;
}
public String getSenderAddress() {
return mSenderAddress;
}
String getRequiredSignerFingerprint() {
return mRequiredSignerFingerprint;
}
public PgpDecryptVerifyInputParcel setRequiredSignerFingerprint(String requiredSignerFingerprint) {
mRequiredSignerFingerprint = requiredSignerFingerprint;
return this;
}
public static final Creator<PgpDecryptVerifyInputParcel> CREATOR = new Creator<PgpDecryptVerifyInputParcel>() {
public PgpDecryptVerifyInputParcel createFromParcel(final Parcel source) {
return new PgpDecryptVerifyInputParcel(source);
abstract PgpDecryptVerifyInputParcel autoBuild();
public PgpDecryptVerifyInputParcel build() {
List<Long> allowedKeyIds = getAllowedKeyIds();
if (allowedKeyIds != null) {
setAllowedKeyIds(Collections.unmodifiableList(allowedKeyIds));
}
return autoBuild();
}
public PgpDecryptVerifyInputParcel[] newArray(final int size) {
return new PgpDecryptVerifyInputParcel[size];
}
};
}
}

View File

@@ -69,10 +69,9 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem.DecryptVerifySecurityProblemBuilder;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.MissingMdc;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
@@ -321,6 +320,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
decryptionResultBuilder.setEncrypted(true);
if (esResult.sessionKey != null && esResult.decryptedSessionKey != null) {
decryptionResultBuilder.setSessionKey(esResult.sessionKey, esResult.decryptedSessionKey);
cryptoInput = cryptoInput.withCryptoData(esResult.sessionKey, esResult.decryptedSessionKey);
}
if (esResult.encryptionKeySecurityProblem != null) {
@@ -361,10 +361,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
log.add(LogType.MSG_DC_CLEAR_DECOMPRESS, indent + 1);
PGPCompressedData compressedData = (PGPCompressedData) dataChunk;
JcaSkipMarkerPGPObjectFactory fact = new JcaSkipMarkerPGPObjectFactory(compressedData.getDataStream());
dataChunk = fact.nextObject();
plainFact = fact;
plainFact = new JcaSkipMarkerPGPObjectFactory(compressedData.getDataStream());
dataChunk = plainFact.nextObject();
}
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(
@@ -378,10 +376,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
dataChunk = plainFact.nextObject();
}
OpenPgpMetadata metadata;
if ( ! (dataChunk instanceof PGPLiteralData)) {
if (!(dataChunk instanceof PGPLiteralData)) {
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, indent);
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
@@ -422,6 +417,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
log.add(LogType.MSG_DC_CLEAR_META_TIME, indent + 1,
new Date(literalData.getModificationTime().getTime()).toString());
OpenPgpMetadata metadata;
// return here if we want to decrypt the metadata only
if (input.isDecryptMetadataOnly()) {
@@ -820,7 +817,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
result.encryptedData = encryptedDataAsymmetric;
Map<ByteBuffer, byte[]> cachedSessionKeys = decryptorFactory.getCachedSessionKeys();
cryptoInput.addCryptoData(cachedSessionKeys);
if (cachedSessionKeys.size() >= 1) {
Entry<ByteBuffer, byte[]> entry = cachedSessionKeys.entrySet().iterator().next();
result.sessionKey = entry.getKey().array();

View File

@@ -32,6 +32,7 @@ import java.security.spec.ECGenParameterSpec;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -79,8 +80,10 @@ import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Builder;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenKeyToCardOperationsBuilder;
@@ -166,17 +169,17 @@ public class PgpKeyOperation {
try {
// Some safety checks
if (add.mAlgorithm == Algorithm.ECDH || add.mAlgorithm == Algorithm.ECDSA) {
if (add.mCurve == null) {
if (add.getAlgorithm() == Algorithm.ECDH || add.getAlgorithm() == Algorithm.ECDSA) {
if (add.getCurve() == null) {
log.add(LogType.MSG_CR_ERROR_NO_CURVE, indent);
return null;
}
} else {
if (add.mKeySize == null) {
if (add.getKeySize() == null) {
log.add(LogType.MSG_CR_ERROR_NO_KEYSIZE, indent);
return null;
}
if (add.mKeySize < 2048) {
if (add.getKeySize() < 2048) {
log.add(LogType.MSG_CR_ERROR_KEYSIZE_2048, indent);
return null;
}
@@ -185,27 +188,27 @@ public class PgpKeyOperation {
int algorithm;
KeyPairGenerator keyGen;
switch (add.mAlgorithm) {
switch (add.getAlgorithm()) {
case DSA: {
if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
if ((add.getFlags() & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
log.add(LogType.MSG_CR_ERROR_FLAGS_DSA, indent);
return null;
}
progress(R.string.progress_generating_dsa, 30);
keyGen = KeyPairGenerator.getInstance("DSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
keyGen.initialize(add.mKeySize, new SecureRandom());
keyGen.initialize(add.getKeySize(), new SecureRandom());
algorithm = PGPPublicKey.DSA;
break;
}
case ELGAMAL: {
if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
if ((add.getFlags() & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
log.add(LogType.MSG_CR_ERROR_FLAGS_ELGAMAL, indent);
return null;
}
progress(R.string.progress_generating_elgamal, 30);
keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
BigInteger p = Primes.getBestPrime(add.mKeySize);
BigInteger p = Primes.getBestPrime(add.getKeySize());
BigInteger g = new BigInteger("2");
ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g);
@@ -218,19 +221,19 @@ public class PgpKeyOperation {
case RSA: {
progress(R.string.progress_generating_rsa, 30);
keyGen = KeyPairGenerator.getInstance("RSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
keyGen.initialize(add.mKeySize, new SecureRandom());
keyGen.initialize(add.getKeySize(), new SecureRandom());
algorithm = PGPPublicKey.RSA_GENERAL;
break;
}
case ECDSA: {
if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
if ((add.getFlags() & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) {
log.add(LogType.MSG_CR_ERROR_FLAGS_ECDSA, indent);
return null;
}
progress(R.string.progress_generating_ecdsa, 30);
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve);
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.getCurve());
keyGen = KeyPairGenerator.getInstance("ECDSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
keyGen.initialize(ecParamSpec, new SecureRandom());
@@ -240,12 +243,12 @@ public class PgpKeyOperation {
case ECDH: {
// make sure there are no sign or certify flags set
if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
if ((add.getFlags() & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) {
log.add(LogType.MSG_CR_ERROR_FLAGS_ECDH, indent);
return null;
}
progress(R.string.progress_generating_ecdh, 30);
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve);
ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.getCurve());
keyGen = KeyPairGenerator.getInstance("ECDH", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
keyGen.initialize(ecParamSpec, new SecureRandom());
@@ -285,23 +288,23 @@ public class PgpKeyOperation {
progress(R.string.progress_building_key, 0);
indent += 1;
if (saveParcel.mAddSubKeys.isEmpty()) {
if (saveParcel.getAddSubKeys().isEmpty()) {
log.add(LogType.MSG_CR_ERROR_NO_MASTER, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (saveParcel.mAddUserIds.isEmpty()) {
if (saveParcel.getAddUserIds().isEmpty()) {
log.add(LogType.MSG_CR_ERROR_NO_USER_ID, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
SubkeyAdd add = saveParcel.mAddSubKeys.remove(0);
if ((add.mFlags & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
SubkeyAdd certificationKey = saveParcel.getAddSubKeys().get(0);
if ((certificationKey.getFlags() & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
log.add(LogType.MSG_CR_ERROR_NO_CERTIFY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (add.mExpiry == null) {
if (certificationKey.getExpiry() == null) {
log.add(LogType.MSG_CR_ERROR_NULL_EXPIRY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
@@ -309,7 +312,7 @@ public class PgpKeyOperation {
Date creationTime = new Date();
subProgressPush(10, 30);
PGPKeyPair keyPair = createKey(add, creationTime, log, indent);
PGPKeyPair keyPair = createKey(certificationKey, creationTime, log, indent);
subProgressPop();
// return null if this failed (an error will already have been logged by createKey)
@@ -335,9 +338,14 @@ public class PgpKeyOperation {
PGPSecretKeyRing sKR = new PGPSecretKeyRing(
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
// Remove certification key from remaining SaveKeyringParcel
Builder builder = SaveKeyringParcel.buildUpon(saveParcel);
builder.getMutableAddSubKeys().remove(certificationKey);
saveParcel = builder.build();
subProgressPush(50, 100);
CryptoInputParcel cryptoInput = new CryptoInputParcel(creationTime, new Passphrase(""));
return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, cryptoInput, saveParcel, log, indent);
CryptoInputParcel cryptoInput = CryptoInputParcel.createCryptoInputParcel(creationTime, new Passphrase(""));
return internal(sKR, masterSecretKey, certificationKey.getFlags(), certificationKey.getExpiry(), cryptoInput, saveParcel, log, indent);
} catch (PGPException e) {
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
@@ -392,7 +400,7 @@ public class PgpKeyOperation {
progress(R.string.progress_building_key, 0);
// Make sure this is called with a proper SaveKeyringParcel
if (saveParcel.mMasterKeyId == null || saveParcel.mMasterKeyId != wsKR.getMasterKeyId()) {
if (saveParcel.getMasterKeyId() == null || saveParcel.getMasterKeyId() != wsKR.getMasterKeyId()) {
log.add(LogType.MSG_MF_ERROR_KEYID, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
@@ -402,75 +410,29 @@ public class PgpKeyOperation {
PGPSecretKey masterSecretKey = sKR.getSecretKey();
// Make sure the fingerprint matches
if (saveParcel.mFingerprint == null || !Arrays.equals(saveParcel.mFingerprint,
if (saveParcel.getFingerprint() == null || !Arrays.equals(saveParcel.getFingerprint(),
masterSecretKey.getPublicKey().getFingerprint())) {
log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (saveParcel.isEmpty()) {
if (isParcelEmpty(saveParcel)) {
log.add(LogType.MSG_MF_ERROR_NOOP, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
// Ensure we don't have multiple keys for the same slot.
boolean hasSign = false;
boolean hasEncrypt = false;
boolean hasAuth = false;
for(SaveKeyringParcel.SubkeyChange change : saveParcel.mChangeSubKeys) {
if (change.mMoveKeyToSecurityToken) {
// If this is a moveKeyToSecurityToken operation, see if it was completed: look for a hash
// matching the given subkey ID in cryptoData.
byte[] subKeyId = new byte[8];
ByteBuffer buf = ByteBuffer.wrap(subKeyId);
buf.putLong(change.mKeyId).rewind();
saveParcel = parseSecurityTokenSerialNumberIntoSubkeyChanges(cryptoInput, saveParcel);
byte[] serialNumber = cryptoInput.getCryptoData().get(buf);
if (serialNumber != null) {
change.mMoveKeyToSecurityToken = false;
change.mSecurityTokenSerialNo = serialNumber;
}
}
if (change.mMoveKeyToSecurityToken) {
// Pending moveKeyToSecurityToken operation. Need to make sure that we don't have multiple
// subkeys pending for the same slot.
CanonicalizedSecretKey wsK = wsKR.getSecretKey(change.mKeyId);
if ((wsK.canSign() || wsK.canCertify())) {
if (hasSign) {
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} else {
hasSign = true;
}
} else if ((wsK.canEncrypt())) {
if (hasEncrypt) {
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} else {
hasEncrypt = true;
}
} else if ((wsK.canAuthenticate())) {
if (hasAuth) {
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
} else {
hasAuth = true;
}
} else {
log.add(LogType.MSG_MF_ERROR_INVALID_FLAGS_FOR_KEYTOCARD, indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
}
if (!checkCapabilitiesAreUnique(wsKR, saveParcel, log, indent)) {
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (isDummy(masterSecretKey) && ! saveParcel.isRestrictedOnly()) {
if (isDummy(masterSecretKey) && ! isParcelRestrictedOnly(saveParcel)) {
log.add(LogType.MSG_EK_ERROR_DUMMY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (isDummy(masterSecretKey) || saveParcel.isRestrictedOnly()) {
if (isDummy(masterSecretKey) || isParcelRestrictedOnly(saveParcel)) {
log.add(LogType.MSG_MF_RESTRICTED_MODE, indent);
return internalRestricted(sKR, saveParcel, log, indent + 1);
}
@@ -494,6 +456,70 @@ public class PgpKeyOperation {
}
private SaveKeyringParcel parseSecurityTokenSerialNumberIntoSubkeyChanges(CryptoInputParcel cryptoInput,
SaveKeyringParcel saveParcel) {
SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildUpon(saveParcel);
for (SubkeyChange change : saveParcel.getChangeSubKeys()) {
if (change.getMoveKeyToSecurityToken()) {
// If this is a moveKeyToSecurityToken operation, see if it was completed: look for a hash
// matching the given subkey ID in cryptoData.
byte[] subKeyId = new byte[8];
ByteBuffer buf = ByteBuffer.wrap(subKeyId);
buf.putLong(change.getSubKeyId()).rewind();
byte[] serialNumber = cryptoInput.getCryptoData().get(buf);
if (serialNumber != null) {
builder.addOrReplaceSubkeyChange(
SubkeyChange.createSecurityTokenSerialNo(change.getSubKeyId(), serialNumber));
}
}
}
saveParcel = builder.build();
return saveParcel;
}
private boolean checkCapabilitiesAreUnique(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel,
OperationLog log, int indent) {
boolean hasSign = false;
boolean hasEncrypt = false;
boolean hasAuth = false;
for (SubkeyChange change : saveParcel.getChangeSubKeys()) {
if (change.getMoveKeyToSecurityToken()) {
// Pending moveKeyToSecurityToken operation. Need to make sure that we don't have multiple
// subkeys pending for the same slot.
CanonicalizedSecretKey wsK = wsKR.getSecretKey(change.getSubKeyId());
if ((wsK.canSign() || wsK.canCertify())) {
if (hasSign) {
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
return false;
} else {
hasSign = true;
}
} else if ((wsK.canEncrypt())) {
if (hasEncrypt) {
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
return false;
} else {
hasEncrypt = true;
}
} else if ((wsK.canAuthenticate())) {
if (hasAuth) {
log.add(LogType.MSG_MF_ERROR_DUPLICATE_KEYTOCARD_FOR_SLOT, indent + 1);
return false;
} else {
hasAuth = true;
}
} else {
log.add(LogType.MSG_MF_ERROR_INVALID_FLAGS_FOR_KEYTOCARD, indent + 1);
return false;
}
}
}
return true;
}
private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
int masterKeyFlags, long masterKeyExpiry,
CryptoInputParcel cryptoInput,
@@ -547,10 +573,11 @@ public class PgpKeyOperation {
// 2a. Add certificates for new user ids
subProgressPush(15, 23);
for (int i = 0; i < saveParcel.mAddUserIds.size(); i++) {
String changePrimaryUserId = saveParcel.getChangePrimaryUserId();
for (int i = 0; i < saveParcel.getAddUserIds().size(); i++) {
progress(R.string.progress_modify_adduid, (i - 1) * (100 / saveParcel.mAddUserIds.size()));
String userId = saveParcel.mAddUserIds.get(i);
progress(R.string.progress_modify_adduid, (i - 1) * (100 / saveParcel.getAddUserIds().size()));
String userId = saveParcel.getAddUserIds().get(i);
log.add(LogType.MSG_MF_UID_ADD, indent, userId);
if ("".equals(userId)) {
@@ -581,8 +608,8 @@ public class PgpKeyOperation {
}
// if it's supposed to be primary, we can do that here as well
boolean isPrimary = saveParcel.mChangePrimaryUserId != null
&& userId.equals(saveParcel.mChangePrimaryUserId);
boolean isPrimary = changePrimaryUserId != null
&& userId.equals(changePrimaryUserId);
// generate and add new certificate
try {
PGPSignature cert = generateUserIdSignature(
@@ -599,10 +626,10 @@ public class PgpKeyOperation {
// 2b. Add certificates for new user ids
subProgressPush(23, 32);
for (int i = 0; i < saveParcel.mAddUserAttribute.size(); i++) {
progress(R.string.progress_modify_adduat, (i - 1) * (100 / saveParcel.mAddUserAttribute.size()));
WrappedUserAttribute attribute = saveParcel.mAddUserAttribute.get(i);
List<WrappedUserAttribute> addUserAttributes = saveParcel.getAddUserAttribute();
for (int i = 0; i < addUserAttributes.size(); i++) {
progress(R.string.progress_modify_adduat, (i - 1) * (100 / addUserAttributes.size()));
WrappedUserAttribute attribute = addUserAttributes.get(i);
switch (attribute.getType()) {
// the 'none' type must not succeed
@@ -635,10 +662,10 @@ public class PgpKeyOperation {
// 2c. Add revocations for revoked user ids
subProgressPush(32, 40);
for (int i = 0; i < saveParcel.mRevokeUserIds.size(); i++) {
progress(R.string.progress_modify_revokeuid, (i - 1) * (100 / saveParcel.mRevokeUserIds.size()));
String userId = saveParcel.mRevokeUserIds.get(i);
List<String> revokeUserIds = saveParcel.getRevokeUserIds();
for (int i = 0, j = revokeUserIds.size(); i < j; i++) {
progress(R.string.progress_modify_revokeuid, (i - 1) * (100 / revokeUserIds.size()));
String userId = revokeUserIds.get(i);
log.add(LogType.MSG_MF_UID_REVOKE, indent, userId);
// Make sure the user id exists (yes these are 10 LoC in Java!)
@@ -670,12 +697,12 @@ public class PgpKeyOperation {
subProgressPop();
// 3. If primary user id changed, generate new certificates for both old and new
if (saveParcel.mChangePrimaryUserId != null) {
if (changePrimaryUserId != null) {
progress(R.string.progress_modify_primaryuid, 40);
// keep track if we actually changed one
boolean ok = false;
log.add(LogType.MSG_MF_UID_PRIMARY, indent, saveParcel.mChangePrimaryUserId);
log.add(LogType.MSG_MF_UID_PRIMARY, indent, changePrimaryUserId);
indent += 1;
// we work on the modifiedPublicKey here, to respect new or newly revoked uids
@@ -716,7 +743,7 @@ public class PgpKeyOperation {
// we definitely should not update certifications of revoked keys, so just leave it.
if (isRevoked) {
// revoked user ids cannot be primary!
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
if (userId.equals(changePrimaryUserId)) {
log.add(LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
@@ -727,7 +754,7 @@ public class PgpKeyOperation {
if (currentCert.getHashedSubPackets() != null
&& currentCert.getHashedSubPackets().isPrimaryUserID()) {
// if it's the one we want, just leave it as is
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
if (userId.equals(changePrimaryUserId)) {
ok = true;
continue;
}
@@ -753,7 +780,7 @@ public class PgpKeyOperation {
// if we are here, this is not currently a primary user id
// if it should be
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
if (userId.equals(changePrimaryUserId)) {
// add shiny new primary user id certificate
log.add(LogType.MSG_MF_PRIMARY_NEW, indent);
modifiedPublicKey = PGPPublicKey.removeCertification(
@@ -801,67 +828,68 @@ public class PgpKeyOperation {
// 4a. For each subkey change, generate new subkey binding certificate
subProgressPush(50, 60);
for (int i = 0; i < saveParcel.mChangeSubKeys.size(); i++) {
List<SubkeyChange> changeSubKeys = saveParcel.getChangeSubKeys();
for (int i = 0, j = changeSubKeys.size(); i < j; i++) {
progress(R.string.progress_modify_subkeychange, (i-1) * (100 / saveParcel.mChangeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i);
progress(R.string.progress_modify_subkeychange, (i-1) * (100 / changeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change = changeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_CHANGE,
indent, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId);
PGPSecretKey sKey = sKR.getSecretKey(change.getSubKeyId());
if (sKey == null) {
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (change.mDummyStrip) {
if (change.getDummyStrip()) {
// IT'S DANGEROUS~
// no really, it is. this operation irrevocably removes the private key data from the key
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
} else if (change.mMoveKeyToSecurityToken) {
} else if (change.getMoveKeyToSecurityToken()) {
if (checkSecurityTokenCompatibility(sKey, log, indent + 1)) {
log.add(LogType.MSG_MF_KEYTOCARD_START, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
nfcKeyToCardOps.addSubkey(change.mKeyId);
KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
nfcKeyToCardOps.addSubkey(change.getSubKeyId());
} else {
// Appropriate log message already set by checkSecurityTokenCompatibility
return new PgpEditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
}
} else if (change.mSecurityTokenSerialNo != null) {
} else if (change.getSecurityTokenSerialNo() != null) {
// NOTE: Does this code get executed? Or always handled in internalRestricted?
if (change.mSecurityTokenSerialNo.length != 16) {
if (change.getSecurityTokenSerialNo().length != 16) {
log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
log.add(LogType.MSG_MF_KEYTOCARD_FINISH, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(change.mKeyId),
Hex.toHexString(change.mSecurityTokenSerialNo, 8, 6));
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.mSecurityTokenSerialNo);
KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()),
Hex.toHexString(change.getSecurityTokenSerialNo(), 8, 6));
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.getSecurityTokenSerialNo());
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
}
// This doesn't concern us any further
if (!change.mRecertify && (change.mExpiry == null && change.mFlags == null)) {
if (!change.getRecertify() && (change.getExpiry() == null && change.getFlags() == null)) {
continue;
}
// expiry must not be in the past
if (change.mExpiry != null && change.mExpiry != 0 &&
new Date(change.mExpiry*1000).before(new Date())) {
if (change.getExpiry() != null && change.getExpiry() != 0 &&
new Date(change.getExpiry() * 1000).before(new Date())) {
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
// if this is the master key, update uid certificates instead
if (change.mKeyId == masterPublicKey.getKeyID()) {
int flags = change.mFlags == null ? masterKeyFlags : change.mFlags;
long expiry = change.mExpiry == null ? masterKeyExpiry : change.mExpiry;
if (change.getSubKeyId() == masterPublicKey.getKeyID()) {
int flags = change.getFlags() == null ? masterKeyFlags : change.getFlags();
long expiry = change.getExpiry() == null ? masterKeyExpiry : change.getExpiry();
if ((flags & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
log.add(LogType.MSG_MF_ERROR_NO_CERTIFY, indent + 1);
@@ -886,22 +914,22 @@ public class PgpKeyOperation {
PGPPublicKey pKey = sKey.getPublicKey();
// keep old flags, or replace with new ones
int flags = change.mFlags == null ? readKeyFlags(pKey) : change.mFlags;
int flags = change.getFlags() == null ? readKeyFlags(pKey) : change.getFlags();
long expiry;
if (change.mExpiry == null) {
if (change.getExpiry() == null) {
long valid = pKey.getValidSeconds();
expiry = valid == 0
? 0
: pKey.getCreationTime().getTime() / 1000 + pKey.getValidSeconds();
} else {
expiry = change.mExpiry;
expiry = change.getExpiry();
}
// drop all old signatures, they will be superseded by the new one
//noinspection unchecked
for (PGPSignature sig : new IterableIterator<PGPSignature>(pKey.getSignatures())) {
// special case: if there is a revocation, don't use expiry from before
if ( (change.mExpiry == null || change.mExpiry == 0L)
if ( (change.getExpiry() == null || change.getExpiry() == 0L)
&& sig.getSignatureType() == PGPSignature.SUBKEY_REVOCATION) {
expiry = 0;
}
@@ -917,7 +945,7 @@ public class PgpKeyOperation {
// super special case: subkey is allowed to sign, but isn't available
if (subPrivateKey == null) {
log.add(LogType.MSG_MF_ERROR_SUB_STRIPPED,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
} else {
@@ -942,10 +970,10 @@ public class PgpKeyOperation {
// 4b. For each subkey revocation, generate new subkey revocation certificate
subProgressPush(60, 65);
for (int i = 0; i < saveParcel.mRevokeSubKeys.size(); i++) {
progress(R.string.progress_modify_subkeyrevoke, (i-1) * (100 / saveParcel.mRevokeSubKeys.size()));
long revocation = saveParcel.mRevokeSubKeys.get(i);
List<Long> revokeSubKeys = saveParcel.getRevokeSubKeys();
for (int i = 0, j = revokeSubKeys.size(); i < j; i++) {
progress(R.string.progress_modify_subkeyrevoke, (i-1) * (100 / revokeSubKeys.size()));
long revocation = revokeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_REVOKE,
indent, KeyFormattingUtils.convertKeyIdToHex(revocation));
@@ -974,38 +1002,38 @@ public class PgpKeyOperation {
// 5. Generate and add new subkeys
subProgressPush(70, 90);
for (int i = 0; i < saveParcel.mAddSubKeys.size(); i++) {
List<SubkeyAdd> addSubKeys = saveParcel.getAddSubKeys();
for (int i = 0, j = addSubKeys.size(); i < j; i++) {
// Check if we were cancelled - again. This operation is expensive so we do it each loop.
if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null);
}
progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / saveParcel.mAddSubKeys.size()));
SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i);
progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / addSubKeys.size()));
SaveKeyringParcel.SubkeyAdd add = addSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_NEW, indent,
KeyFormattingUtils.getAlgorithmInfo(add.mAlgorithm, add.mKeySize, add.mCurve) );
KeyFormattingUtils.getAlgorithmInfo(add.getAlgorithm(), add.getKeySize(), add.getCurve()) );
if (isDivertToCard(masterSecretKey)) {
log.add(LogType.MSG_MF_ERROR_DIVERT_NEWSUB, indent +1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (add.mExpiry == null) {
if (add.getExpiry() == null) {
log.add(LogType.MSG_MF_ERROR_NULL_EXPIRY, indent +1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (add.mExpiry > 0L && new Date(add.mExpiry*1000).before(new Date())) {
if (add.getExpiry() > 0L && new Date(add.getExpiry() * 1000).before(new Date())) {
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY, indent +1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
// generate a new secret key (privkey only for now)
subProgressPush(
(i-1) * (100 / saveParcel.mAddSubKeys.size()),
i * (100 / saveParcel.mAddSubKeys.size())
(i-1) * (100 / addSubKeys.size()),
i * (100 / addSubKeys.size())
);
PGPKeyPair keyPair = createKey(add, cryptoInput.getSignatureTime(), log, indent);
subProgressPop();
@@ -1022,7 +1050,7 @@ public class PgpKeyOperation {
cryptoInput.getSignatureTime(),
masterPublicKey, masterPrivateKey,
getSignatureGenerator(pKey, cryptoInput, false), keyPair.getPrivateKey(), pKey,
add.mFlags, add.mExpiry);
add.getFlags(), add.getExpiry());
pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
} catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
@@ -1058,13 +1086,13 @@ public class PgpKeyOperation {
}
// 6. If requested, change passphrase
if (saveParcel.getChangeUnlockParcel() != null) {
if (saveParcel.getNewUnlock() != null) {
progress(R.string.progress_modify_passphrase, 90);
log.add(LogType.MSG_MF_PASSPHRASE, indent);
indent += 1;
sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(),
saveParcel.getChangeUnlockParcel().mNewPassphrase, log, indent);
saveParcel.getNewUnlock().getNewPassphrase(), log, indent);
if (sKR == null) {
// The error has been logged above, just return a bad state
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
@@ -1074,21 +1102,21 @@ public class PgpKeyOperation {
}
// 7. if requested, change PIN and/or Admin PIN on security token
if (saveParcel.mSecurityTokenPin != null) {
if (saveParcel.getSecurityTokenPin() != null) {
progress(R.string.progress_modify_pin, 90);
log.add(LogType.MSG_MF_PIN, indent);
indent += 1;
nfcKeyToCardOps.setPin(saveParcel.mSecurityTokenPin);
nfcKeyToCardOps.setPin(saveParcel.getSecurityTokenPin());
indent -= 1;
}
if (saveParcel.mSecurityTokenAdminPin != null) {
if (saveParcel.getSecurityTokenAdminPin() != null) {
progress(R.string.progress_modify_admin_pin, 90);
log.add(LogType.MSG_MF_ADMIN_PIN, indent);
indent += 1;
nfcKeyToCardOps.setAdminPin(saveParcel.mSecurityTokenAdminPin);
nfcKeyToCardOps.setAdminPin(saveParcel.getSecurityTokenAdminPin());
indent -= 1;
}
@@ -1139,7 +1167,7 @@ public class PgpKeyOperation {
progress(R.string.progress_modify, 0);
// Make sure the saveParcel includes only operations available without passphrase!
if (!saveParcel.isRestrictedOnly()) {
if (!isParcelRestrictedOnly(saveParcel)) {
log.add(LogType.MSG_MF_ERROR_RESTRICTED, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
@@ -1153,36 +1181,36 @@ public class PgpKeyOperation {
// The only operation we can do here:
// 4a. Strip secret keys, or change their protection mode (stripped/divert-to-card)
subProgressPush(50, 60);
for (int i = 0; i < saveParcel.mChangeSubKeys.size(); i++) {
progress(R.string.progress_modify_subkeychange, (i - 1) * (100 / saveParcel.mChangeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change = saveParcel.mChangeSubKeys.get(i);
List<SubkeyChange> changeSubKeys = saveParcel.getChangeSubKeys();
for (int i = 0, j = changeSubKeys.size(); i < j; i++) {
progress(R.string.progress_modify_subkeychange, (i - 1) * (100 / changeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change = changeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_CHANGE,
indent, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId);
PGPSecretKey sKey = sKR.getSecretKey(change.getSubKeyId());
if (sKey == null) {
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
if (change.mDummyStrip || change.mSecurityTokenSerialNo != null) {
if (change.getDummyStrip() || change.getSecurityTokenSerialNo() != null) {
// IT'S DANGEROUS~
// no really, it is. this operation irrevocably removes the private key data from the key
if (change.mDummyStrip) {
if (change.getDummyStrip()) {
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
} else {
// the serial number must be 16 bytes in length
if (change.mSecurityTokenSerialNo.length != 16) {
if (change.getSecurityTokenSerialNo().length != 16) {
log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
indent + 1, KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
log.add(LogType.MSG_MF_KEYTOCARD_FINISH, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(change.mKeyId),
Hex.toHexString(change.mSecurityTokenSerialNo, 8, 6));
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.mSecurityTokenSerialNo);
KeyFormattingUtils.convertKeyIdToHex(change.getSubKeyId()),
Hex.toHexString(change.getSecurityTokenSerialNo(), 8, 6));
sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.getSecurityTokenSerialNo());
}
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
}
@@ -1204,7 +1232,8 @@ public class PgpKeyOperation {
OperationLog log = new OperationLog();
int indent = 0;
if (changeUnlockParcel.mMasterKeyId == null || changeUnlockParcel.mMasterKeyId != wsKR.getMasterKeyId()) {
Long masterKeyId = changeUnlockParcel.getMasterKeyId();
if (masterKeyId == null || masterKeyId != wsKR.getMasterKeyId()) {
log.add(LogType.MSG_MF_ERROR_KEYID, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
}
@@ -1219,7 +1248,7 @@ public class PgpKeyOperation {
PGPSecretKey masterSecretKey = sKR.getSecretKey();
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
// Make sure the fingerprint matches
if (changeUnlockParcel.mFingerprint == null || !Arrays.equals(changeUnlockParcel.mFingerprint,
if (changeUnlockParcel.getFingerprint()== null || !Arrays.equals(changeUnlockParcel.getFingerprint(),
masterSecretKey.getPublicKey().getFingerprint())) {
log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
@@ -1245,7 +1274,7 @@ public class PgpKeyOperation {
try {
sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(),
changeUnlockParcel.mNewPassphrase, log, indent);
changeUnlockParcel.getNewPassphrase(), log, indent);
if (sKR == null) {
// The error has been logged above, just return a bad state
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
@@ -1697,4 +1726,31 @@ public class PgpKeyOperation {
return true;
}
/** Returns true iff this parcel does not contain any operations which require a passphrase. */
private static boolean isParcelRestrictedOnly(SaveKeyringParcel saveKeyringParcel) {
if (saveKeyringParcel.getNewUnlock() != null
|| !saveKeyringParcel.getAddUserIds().isEmpty()
|| !saveKeyringParcel.getAddUserAttribute().isEmpty()
|| !saveKeyringParcel.getAddSubKeys().isEmpty()
|| saveKeyringParcel.getChangePrimaryUserId() != null
|| !saveKeyringParcel.getRevokeUserIds().isEmpty()
|| !saveKeyringParcel.getRevokeSubKeys().isEmpty()) {
return false;
}
for (SubkeyChange change : saveKeyringParcel.getChangeSubKeys()) {
if (change.getRecertify() || change.getFlags() != null || change.getExpiry() != null
|| change.getMoveKeyToSecurityToken()) {
return false;
}
}
return true;
}
private static boolean isParcelEmpty(SaveKeyringParcel saveKeyringParcel) {
return isParcelRestrictedOnly(saveKeyringParcel) && saveKeyringParcel.getChangeSubKeys().isEmpty();
}
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
* Copyright (C) 2017 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,226 +18,91 @@
package org.sufficientlysecure.keychain.pgp;
import android.os.Parcel;
import android.os.Parcelable;
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainHashAlgorithmTags;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags;
import org.sufficientlysecure.keychain.util.Passphrase;
@AutoValue
public abstract class PgpSignEncryptData implements Parcelable {
@Nullable
public abstract String getCharset();
abstract long getAdditionalEncryptId();
@Nullable
public abstract Long getSignatureSubKeyId();
public abstract long getSignatureMasterKeyId();
@Nullable
public abstract Passphrase getSymmetricPassphrase();
@Nullable
@SuppressWarnings("mutable")
public abstract long[] getEncryptionMasterKeyIds();
@Nullable
public abstract List<Long> getAllowedSigningKeyIds();
@Nullable
public abstract String getVersionHeader();
public class PgpSignEncryptData implements Parcelable {
private String mVersionHeader = null;
private boolean mEnableAsciiArmorOutput = false;
private int mCompressionAlgorithm = CompressionAlgorithmTags.UNCOMPRESSED;
private long[] mEncryptionMasterKeyIds = null;
private Passphrase mSymmetricPassphrase = null;
private int mSymmetricEncryptionAlgorithm = PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT;
private long mSignatureMasterKeyId = Constants.key.none;
private Long mSignatureSubKeyId = null;
private int mSignatureHashAlgorithm = PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT;
private long mAdditionalEncryptId = Constants.key.none;
private String mCharset;
private boolean mCleartextSignature;
private boolean mDetachedSignature = false;
private boolean mHiddenRecipients = false;
private boolean mAddBackupHeader = false;
public abstract int getCompressionAlgorithm();
public abstract int getSignatureHashAlgorithm();
public abstract int getSymmetricEncryptionAlgorithm();
public PgpSignEncryptData(){
public abstract boolean isEnableAsciiArmorOutput();
public abstract boolean isCleartextSignature();
public abstract boolean isDetachedSignature();
public abstract boolean isAddBackupHeader();
public abstract boolean isHiddenRecipients();
public static Builder builder() {
return new AutoValue_PgpSignEncryptData.Builder()
.setSignatureMasterKeyId(Constants.key.none)
.setAdditionalEncryptId(Constants.key.none)
.setEnableAsciiArmorOutput(false)
.setCleartextSignature(false)
.setDetachedSignature(false)
.setAddBackupHeader(false)
.setHiddenRecipients(false)
.setCompressionAlgorithm(OpenKeychainCompressionAlgorithmTags.USE_DEFAULT)
.setSignatureHashAlgorithm(OpenKeychainHashAlgorithmTags.USE_DEFAULT)
.setSymmetricEncryptionAlgorithm(OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
}
private PgpSignEncryptData(Parcel source) {
ClassLoader loader = getClass().getClassLoader();
@AutoValue.Builder
public abstract static class Builder {
public abstract PgpSignEncryptData build();
mVersionHeader = source.readString();
mEnableAsciiArmorOutput = source.readInt() == 1;
mCompressionAlgorithm = source.readInt();
mEncryptionMasterKeyIds = source.createLongArray();
mSymmetricPassphrase = source.readParcelable(loader);
mSymmetricEncryptionAlgorithm = source.readInt();
mSignatureMasterKeyId = source.readLong();
mSignatureSubKeyId = source.readInt() == 1 ? source.readLong() : null;
mSignatureHashAlgorithm = source.readInt();
mAdditionalEncryptId = source.readLong();
mCharset = source.readString();
mCleartextSignature = source.readInt() == 1;
mDetachedSignature = source.readInt() == 1;
mHiddenRecipients = source.readInt() == 1;
mAddBackupHeader = source.readInt() == 1;
}
public abstract Builder setCharset(String charset);
public abstract Builder setAdditionalEncryptId(long additionalEncryptId);
public abstract Builder setSignatureSubKeyId(Long signatureSubKeyId);
public abstract Builder setSignatureMasterKeyId(long signatureMasterKeyId);
public abstract Builder setSymmetricPassphrase(Passphrase symmetricPassphrase);
public abstract Builder setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds);
public abstract Builder setVersionHeader(String versionHeader);
@Override
public int describeContents() {
return 0;
}
public abstract Builder setCompressionAlgorithm(int compressionAlgorithm);
public abstract Builder setSignatureHashAlgorithm(int signatureHashAlgorithm);
public abstract Builder setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm);
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mVersionHeader);
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
dest.writeInt(mCompressionAlgorithm);
dest.writeLongArray(mEncryptionMasterKeyIds);
dest.writeParcelable(mSymmetricPassphrase, 0);
dest.writeInt(mSymmetricEncryptionAlgorithm);
dest.writeLong(mSignatureMasterKeyId);
if (mSignatureSubKeyId != null) {
dest.writeInt(1);
dest.writeLong(mSignatureSubKeyId);
} else {
dest.writeInt(0);
public abstract Builder setAddBackupHeader(boolean isAddBackupHeader);
public abstract Builder setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput);
public abstract Builder setCleartextSignature(boolean isCleartextSignature);
public abstract Builder setDetachedSignature(boolean isDetachedSignature);
public abstract Builder setHiddenRecipients(boolean isHiddenRecipients);
abstract Builder setAllowedSigningKeyIds(List<Long> allowedSigningKeyIds);
public Builder setAllowedSigningKeyIds(Collection<Long> allowedSigningKeyIds) {
setAllowedSigningKeyIds(Collections.unmodifiableList(new ArrayList<>(allowedSigningKeyIds)));
return this;
}
dest.writeInt(mSignatureHashAlgorithm);
dest.writeLong(mAdditionalEncryptId);
dest.writeString(mCharset);
dest.writeInt(mCleartextSignature ? 1 : 0);
dest.writeInt(mDetachedSignature ? 1 : 0);
dest.writeInt(mHiddenRecipients ? 1 : 0);
dest.writeInt(mAddBackupHeader ? 1 : 0);
}
public String getCharset() {
return mCharset;
}
public void setCharset(String mCharset) {
this.mCharset = mCharset;
}
public long getAdditionalEncryptId() {
return mAdditionalEncryptId;
}
public PgpSignEncryptData setAdditionalEncryptId(long additionalEncryptId) {
mAdditionalEncryptId = additionalEncryptId;
return this;
}
public int getSignatureHashAlgorithm() {
return mSignatureHashAlgorithm;
}
public PgpSignEncryptData setSignatureHashAlgorithm(int signatureHashAlgorithm) {
mSignatureHashAlgorithm = signatureHashAlgorithm;
return this;
}
public Long getSignatureSubKeyId() {
return mSignatureSubKeyId;
}
public PgpSignEncryptData setSignatureSubKeyId(long signatureSubKeyId) {
mSignatureSubKeyId = signatureSubKeyId;
return this;
}
public long getSignatureMasterKeyId() {
return mSignatureMasterKeyId;
}
public PgpSignEncryptData setSignatureMasterKeyId(long signatureMasterKeyId) {
mSignatureMasterKeyId = signatureMasterKeyId;
return this;
}
public int getSymmetricEncryptionAlgorithm() {
return mSymmetricEncryptionAlgorithm;
}
public PgpSignEncryptData setSymmetricEncryptionAlgorithm(int symmetricEncryptionAlgorithm) {
mSymmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
return this;
}
public Passphrase getSymmetricPassphrase() {
return mSymmetricPassphrase;
}
public PgpSignEncryptData setSymmetricPassphrase(Passphrase symmetricPassphrase) {
mSymmetricPassphrase = symmetricPassphrase;
return this;
}
public long[] getEncryptionMasterKeyIds() {
return mEncryptionMasterKeyIds;
}
public PgpSignEncryptData setEncryptionMasterKeyIds(long[] encryptionMasterKeyIds) {
mEncryptionMasterKeyIds = encryptionMasterKeyIds;
return this;
}
public int getCompressionAlgorithm() {
return mCompressionAlgorithm;
}
public PgpSignEncryptData setCompressionAlgorithm(int compressionAlgorithm) {
mCompressionAlgorithm = compressionAlgorithm;
return this;
}
public boolean isEnableAsciiArmorOutput() {
return mEnableAsciiArmorOutput;
}
public String getVersionHeader() {
return mVersionHeader;
}
public PgpSignEncryptData setVersionHeader(String versionHeader) {
mVersionHeader = versionHeader;
return this;
}
public PgpSignEncryptData setEnableAsciiArmorOutput(boolean enableAsciiArmorOutput) {
mEnableAsciiArmorOutput = enableAsciiArmorOutput;
return this;
}
public PgpSignEncryptData setCleartextSignature(boolean cleartextSignature) {
this.mCleartextSignature = cleartextSignature;
return this;
}
public boolean isCleartextSignature() {
return mCleartextSignature;
}
public PgpSignEncryptData setDetachedSignature(boolean detachedSignature) {
this.mDetachedSignature = detachedSignature;
return this;
}
public boolean isDetachedSignature() {
return mDetachedSignature;
}
public PgpSignEncryptData setHiddenRecipients(boolean hiddenRecipients) {
this.mHiddenRecipients = hiddenRecipients;
return this;
}
public PgpSignEncryptData setAddBackupHeader(boolean addBackupHeader) {
this.mAddBackupHeader = addBackupHeader;
return this;
}
public boolean isAddBackupHeader() {
return mAddBackupHeader;
}
public boolean isHiddenRecipients() {
return mHiddenRecipients;
}
public static final Creator<PgpSignEncryptData> CREATOR = new Creator<PgpSignEncryptData>() {
public PgpSignEncryptData createFromParcel(final Parcel source) {
return new PgpSignEncryptData(source);
}
public PgpSignEncryptData[] newArray(final int size) {
return new PgpSignEncryptData[size];
}
};
}

View File

@@ -18,104 +18,33 @@
package org.sufficientlysecure.keychain.pgp;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import java.util.HashSet;
import com.google.auto.value.AutoValue;
public class PgpSignEncryptInputParcel implements Parcelable {
@AutoValue
public abstract class PgpSignEncryptInputParcel implements Parcelable {
public abstract PgpSignEncryptData getData();
@Nullable
public abstract Uri getOutputUri();
@Nullable
public abstract Uri getInputUri();
@Nullable
@SuppressWarnings("mutable")
public abstract byte[] getInputBytes();
private PgpSignEncryptData data;
private Uri mInputUri;
private Uri mOutputUri;
private byte[] mInputBytes;
private HashSet<Long> mAllowedKeyIds;
public PgpSignEncryptInputParcel(PgpSignEncryptData data) {
this.data = data;
public static PgpSignEncryptInputParcel createForBytes(
PgpSignEncryptData signEncryptData, Uri outputUri, byte[] inputBytes) {
return new AutoValue_PgpSignEncryptInputParcel(signEncryptData, outputUri, null, inputBytes);
}
PgpSignEncryptInputParcel(Parcel source) {
mInputUri = source.readParcelable(getClass().getClassLoader());
mOutputUri = source.readParcelable(getClass().getClassLoader());
mInputBytes = source.createByteArray();
data = source.readParcelable(getClass().getClassLoader());
mAllowedKeyIds = (HashSet<Long>) source.readSerializable();
public static PgpSignEncryptInputParcel createForInputUri(
PgpSignEncryptData signEncryptData, Uri outputUri, Uri inputUri) {
return new AutoValue_PgpSignEncryptInputParcel(signEncryptData, outputUri, inputUri, null);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mInputUri, 0);
dest.writeParcelable(mOutputUri, 0);
dest.writeByteArray(mInputBytes);
data.writeToParcel(dest, 0);
dest.writeSerializable(mAllowedKeyIds);
}
public void setInputBytes(byte[] inputBytes) {
this.mInputBytes = inputBytes;
}
byte[] getInputBytes() {
return mInputBytes;
}
public PgpSignEncryptInputParcel setInputUri(Uri uri) {
mInputUri = uri;
return this;
}
Uri getInputUri() {
return mInputUri;
}
public PgpSignEncryptInputParcel setOutputUri(Uri uri) {
mOutputUri = uri;
return this;
}
Uri getOutputUri() {
return mOutputUri;
}
public void setData(PgpSignEncryptData data) {
this.data = data;
}
public PgpSignEncryptData getData() {
return data;
}
HashSet<Long> getAllowedKeyIds() {
return mAllowedKeyIds;
}
public void setAllowedKeyIds(HashSet<Long> allowedKeyIds) {
mAllowedKeyIds = allowedKeyIds;
}
public static final Creator<PgpSignEncryptInputParcel> CREATOR = new Creator<PgpSignEncryptInputParcel>() {
public PgpSignEncryptInputParcel createFromParcel(final Parcel source) {
return new PgpSignEncryptInputParcel(source);
}
public PgpSignEncryptInputParcel[] newArray(final int size) {
return new PgpSignEncryptInputParcel[size];
}
};
}

View File

@@ -19,6 +19,24 @@
package org.sufficientlysecure.keychain.pgp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
import java.util.Collection;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
@@ -43,7 +61,11 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags;
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.KeyWritableRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
@@ -56,23 +78,6 @@ import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
import java.util.Arrays;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* This class supports a single, low-level, sign/encrypt operation.
* <p/>
@@ -148,7 +153,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
}
}
PgpSignEncryptResult result = executeInternal(input, cryptoInput, inputData, outStream);
PgpSignEncryptResult result = executeInternal(input.getData(), cryptoInput, inputData, outStream);
if (outStream instanceof ByteArrayOutputStream) {
byte[] outputData = ((ByteArrayOutputStream) outStream).toByteArray();
result.setOutputBytes(outputData);
@@ -158,41 +163,33 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
}
@NonNull
public PgpSignEncryptResult execute(PgpSignEncryptInputParcel input, CryptoInputParcel cryptoInput,
InputData inputData, OutputStream outputStream) {
return executeInternal(input, cryptoInput, inputData, outputStream);
public PgpSignEncryptResult execute(PgpSignEncryptData data, CryptoInputParcel cryptoInput,
InputData inputData, OutputStream outputStream) {
return executeInternal(data, cryptoInput, inputData, outputStream);
}
/**
* Signs and/or encrypts data based on parameters of class
*/
private PgpSignEncryptResult executeInternal(PgpSignEncryptInputParcel input, CryptoInputParcel cryptoInput,
InputData inputData, OutputStream outputStream) {
private PgpSignEncryptResult executeInternal(PgpSignEncryptData data, CryptoInputParcel cryptoInput,
InputData inputData, OutputStream outputStream) {
int indent = 0;
OperationLog log = new OperationLog();
log.add(LogType.MSG_PSE, indent);
indent += 1;
PgpSignEncryptData data = input.getData();
boolean enableSignature = data.getSignatureMasterKeyId() != Constants.key.none;
boolean enableEncryption = ((data.getEncryptionMasterKeyIds() != null && data.getEncryptionMasterKeyIds().length > 0)
|| data.getSymmetricPassphrase() != null);
boolean enableCompression = (data.getCompressionAlgorithm() != CompressionAlgorithmTags.UNCOMPRESSED);
Log.d(Constants.TAG, "enableSignature:" + enableSignature
+ "\nenableEncryption:" + enableEncryption
+ "\nenableCompression:" + enableCompression
+ "\nenableAsciiArmorOutput:" + data.isEnableAsciiArmorOutput()
+ "\nisHiddenRecipients:" + data.isHiddenRecipients());
// add additional key id to encryption ids (mostly to do self-encryption)
if (enableEncryption && data.getAdditionalEncryptId() != Constants.key.none) {
data.setEncryptionMasterKeyIds(Arrays.copyOf(data.getEncryptionMasterKeyIds(), data.getEncryptionMasterKeyIds().length + 1));
data.getEncryptionMasterKeyIds()[data.getEncryptionMasterKeyIds().length - 1] = data.getAdditionalEncryptId();
int compressionAlgorithm = data.getCompressionAlgorithm();
if (compressionAlgorithm == OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
compressionAlgorithm = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
}
Log.d(Constants.TAG, data.toString());
ArmoredOutputStream armorOut = null;
OutputStream out;
if (data.isEnableAsciiArmorOutput()) {
@@ -221,20 +218,26 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
try {
long signingMasterKeyId = data.getSignatureMasterKeyId();
long signingSubKeyId = data.getSignatureSubKeyId();
CanonicalizedSecretKeyRing signingKeyRing =
mKeyRepository.getCanonicalizedSecretKeyRing(signingMasterKeyId);
signingKey = signingKeyRing.getSecretKey(data.getSignatureSubKeyId());
if (input.getAllowedKeyIds() != null) {
if (!input.getAllowedKeyIds().contains(signingMasterKeyId)) {
// this key is in our db, but NOT allowed!
log.add(LogType.MSG_PSE_ERROR_KEY_NOT_ALLOWED, indent + 1);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_KEY_DISALLOWED, log);
Long signingSubKeyId = data.getSignatureSubKeyId();
if (signingSubKeyId == null) {
try {
signingSubKeyId = mKeyRepository.getCachedPublicKeyRing(signingMasterKeyId).getSecretSignId();
} catch (PgpKeyNotFoundException e) {
log.add(LogType.MSG_PSE_ERROR_KEY_SIGN, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
}
CanonicalizedSecretKeyRing signingKeyRing =
mKeyRepository.getCanonicalizedSecretKeyRing(signingMasterKeyId);
signingKey = signingKeyRing.getSecretKey(signingSubKeyId);
Collection<Long> allowedSigningKeyIds = data.getAllowedSigningKeyIds();
if (allowedSigningKeyIds != null && !allowedSigningKeyIds.contains(signingMasterKeyId)) {
// this key is in our db, but NOT allowed!
log.add(LogType.MSG_PSE_ERROR_KEY_NOT_ALLOWED, indent + 1);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_KEY_DISALLOWED, log);
}
// Make sure key is not expired or revoked
if (signingKeyRing.isExpired() || signingKeyRing.isRevoked()
@@ -300,12 +303,6 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
log.add(LogType.MSG_PSE_ERROR_UNLOCK, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
// Use requested hash algo
int requestedAlgorithm = data.getSignatureHashAlgorithm();
if (requestedAlgorithm == PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT) {
data.setSignatureHashAlgorithm(PgpSecurityConstants.DEFAULT_HASH_ALGORITHM);
}
}
updateProgress(R.string.progress_preparing_streams, 2, 100);
@@ -314,12 +311,12 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
if (enableEncryption) {
// Use requested encryption algo
int algo = data.getSymmetricEncryptionAlgorithm();
if (algo == PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) {
algo = PgpSecurityConstants.DEFAULT_SYMMETRIC_ALGORITHM;
int symmetricEncryptionAlgorithm = data.getSymmetricEncryptionAlgorithm();
if (symmetricEncryptionAlgorithm == OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT) {
symmetricEncryptionAlgorithm = PgpSecurityConstants.DEFAULT_SYMMETRIC_ALGORITHM;
}
JcePGPDataEncryptorBuilder encryptorBuilder =
new JcePGPDataEncryptorBuilder(algo)
new JcePGPDataEncryptorBuilder(symmetricEncryptionAlgorithm)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
.setWithIntegrityPacket(true);
@@ -336,36 +333,28 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
log.add(LogType.MSG_PSE_ASYMMETRIC, indent);
// Asymmetric encryption
for (long id : data.getEncryptionMasterKeyIds()) {
try {
CanonicalizedPublicKeyRing keyRing = mKeyRepository.getCanonicalizedPublicKeyRing(
KeyRings.buildUnifiedKeyRingUri(id));
Set<Long> encryptSubKeyIds = keyRing.getEncryptIds();
for (Long subKeyId : encryptSubKeyIds) {
CanonicalizedPublicKey key = keyRing.getPublicKey(subKeyId);
cPk.addMethod(key.getPubKeyEncryptionGenerator(data.isHiddenRecipients()));
log.add(LogType.MSG_PSE_KEY_OK, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(subKeyId));
}
if (encryptSubKeyIds.isEmpty()) {
log.add(LogType.MSG_PSE_KEY_WARN, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(id));
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
// Make sure key is not expired or revoked
if (keyRing.isExpired() || keyRing.isRevoked()) {
log.add(LogType.MSG_PSE_ERROR_REVOKED_OR_EXPIRED, indent);
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
} catch (KeyWritableRepository.NotFoundException e) {
log.add(LogType.MSG_PSE_KEY_UNKNOWN, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(id));
for (long encryptMasterKeyId : data.getEncryptionMasterKeyIds()) {
boolean success = processEncryptionMasterKeyId(indent, log, data, cPk, encryptMasterKeyId);
if (!success) {
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
}
long additionalEncryptId = data.getAdditionalEncryptId();
if (additionalEncryptId != Constants.key.none) {
boolean success = processEncryptionMasterKeyId(indent, log, data, cPk, additionalEncryptId);
if (!success) {
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
}
}
}
int signatureHashAlgorithm = data.getSignatureHashAlgorithm();
if (signatureHashAlgorithm == OpenKeychainHashAlgorithmTags.USE_DEFAULT) {
signatureHashAlgorithm = PgpSecurityConstants.DEFAULT_HASH_ALGORITHM;
}
/* Initialize signature generator object for later usage */
PGPSignatureGenerator signatureGenerator = null;
if (enableSignature) {
@@ -374,7 +363,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
try {
boolean cleartext = data.isCleartextSignature() && data.isEnableAsciiArmorOutput() && !enableEncryption;
signatureGenerator = signingKey.getDataSignatureGenerator(
data.getSignatureHashAlgorithm(), cleartext,
signatureHashAlgorithm, cleartext,
cryptoInput.getCryptoData(), cryptoInput.getSignatureTime());
} catch (PgpGeneralException e) {
log.add(LogType.MSG_PSE_ERROR_NFC, indent);
@@ -409,15 +398,10 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
encryptionOut = cPk.open(out, new byte[1 << 16]);
if (enableCompression) {
if (compressionAlgorithm != CompressionAlgorithmTags.UNCOMPRESSED) {
log.add(LogType.MSG_PSE_COMPRESSING, indent);
// Use preferred compression algo
int algo = data.getCompressionAlgorithm();
if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
}
compressGen = new PGPCompressedDataGenerator(algo);
compressGen = new PGPCompressedDataGenerator(compressionAlgorithm);
bcpgOut = new BCPGOutputStream(compressGen.open(encryptionOut));
} else {
bcpgOut = new BCPGOutputStream(encryptionOut);
@@ -466,7 +450,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
log.add(LogType.MSG_PSE_SIGNING_CLEARTEXT, indent);
// write -----BEGIN PGP SIGNED MESSAGE-----
armorOut.beginClearText(data.getSignatureHashAlgorithm());
armorOut.beginClearText(signatureHashAlgorithm);
InputStream in = new BufferedInputStream(inputData.getInputStream());
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
@@ -539,14 +523,10 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
InputStream in = new BufferedInputStream(inputData.getInputStream());
if (enableCompression) {
// Use preferred compression algo
int algo = data.getCompressionAlgorithm();
if (algo == PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT) {
algo = PgpSecurityConstants.DEFAULT_COMPRESSION_ALGORITHM;
}
if (compressionAlgorithm != CompressionAlgorithmTags.UNCOMPRESSED) {
log.add(LogType.MSG_PSE_COMPRESSING, indent);
compressGen = new PGPCompressedDataGenerator(algo);
compressGen = new PGPCompressedDataGenerator(compressionAlgorithm);
bcpgOut = new BCPGOutputStream(compressGen.open(out));
} else {
bcpgOut = new BCPGOutputStream(out);
@@ -597,16 +577,15 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
}
opTime = System.currentTimeMillis() - startTime;
Log.d(Constants.TAG, "sign/encrypt time taken: " + String.format("%.2f",
opTime / 1000.0) + "s");
Log.d(Constants.TAG, "sign/encrypt time taken: " + String.format("%.2f", opTime / 1000.0) + "s");
// closing outputs
// NOTE: closing needs to be done in the correct order!
if (encryptionOut != null) {
if (compressGen != null) {
compressGen.close();
}
if (compressGen != null) {
compressGen.close();
}
if (encryptionOut != null) {
encryptionOut.close();
}
// Note: Closing ArmoredOutputStream does not close the underlying stream
@@ -653,7 +632,7 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
}
result.setDetachedSignature(detachedByteOut.toByteArray());
try {
String digestName = PGPUtil.getDigestName(data.getSignatureHashAlgorithm());
String digestName = PGPUtil.getDigestName(signatureHashAlgorithm);
// construct micalg parameter according to https://tools.ietf.org/html/rfc3156#section-5
result.setMicAlgDigestName("pgp-" + digestName.toLowerCase());
} catch (PGPException e) {
@@ -663,6 +642,36 @@ public class PgpSignEncryptOperation extends BaseOperation<PgpSignEncryptInputPa
return result;
}
private boolean processEncryptionMasterKeyId(int indent, OperationLog log, PgpSignEncryptData data,
PGPEncryptedDataGenerator cPk, long encryptMasterKeyId) {
try {
CanonicalizedPublicKeyRing keyRing = mKeyRepository.getCanonicalizedPublicKeyRing(
KeyRings.buildUnifiedKeyRingUri(encryptMasterKeyId));
Set<Long> encryptSubKeyIds = keyRing.getEncryptIds();
for (Long subKeyId : encryptSubKeyIds) {
CanonicalizedPublicKey key = keyRing.getPublicKey(subKeyId);
cPk.addMethod(key.getPubKeyEncryptionGenerator(data.isHiddenRecipients()));
log.add(LogType.MSG_PSE_KEY_OK, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(subKeyId));
}
if (encryptSubKeyIds.isEmpty()) {
log.add(LogType.MSG_PSE_KEY_WARN, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(encryptMasterKeyId));
return false;
}
// Make sure key is not expired or revoked
if (keyRing.isExpired() || keyRing.isRevoked()) {
log.add(LogType.MSG_PSE_ERROR_REVOKED_OR_EXPIRED, indent);
return false;
}
} catch (KeyWritableRepository.NotFoundException e) {
log.add(LogType.MSG_PSE_KEY_UNKNOWN, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(encryptMasterKeyId));
return false;
}
return true;
}
/**
* Remove whitespaces on line endings
*/

View File

@@ -19,14 +19,17 @@
package org.sufficientlysecure.keychain.pgp;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.google.auto.value.AutoValue;
/**
* This parcel stores the input of one or more PgpSignEncrypt operations.
* All operations will use the same general parameters, differing only in
@@ -39,83 +42,65 @@ import java.util.List;
* - Once the output uris are empty, there must be exactly one input (uri xor bytes)
* left, which will be returned in a byte array as part of the result parcel.
*/
public class SignEncryptParcel implements Parcelable {
@AutoValue
public abstract class SignEncryptParcel implements Parcelable {
public abstract PgpSignEncryptData getSignEncryptData();
public abstract List<Uri> getInputUris();
public abstract List<Uri> getOutputUris();
@SuppressWarnings("mutable")
@Nullable
public abstract byte[] getBytes();
private PgpSignEncryptData data;
public ArrayList<Uri> mInputUris = new ArrayList<>();
public ArrayList<Uri> mOutputUris = new ArrayList<>();
public byte[] mBytes;
public SignEncryptParcel(PgpSignEncryptData data) {
this.data = data;
}
public SignEncryptParcel(Parcel src) {
mInputUris = src.createTypedArrayList(Uri.CREATOR);
mOutputUris = src.createTypedArrayList(Uri.CREATOR);
mBytes = src.createByteArray();
data = src.readParcelable(getClass().getClassLoader());
}
public boolean isIncomplete() {
return mInputUris.size() > mOutputUris.size();
List<Uri> inputUris = getInputUris();
List<Uri> outputUris = getOutputUris();
if (inputUris == null || outputUris == null) {
throw new IllegalStateException("Invalid operation for bytes-backed SignEncryptParcel!");
}
return inputUris.size() > outputUris.size();
}
public byte[] getBytes() {
return mBytes;
public static SignEncryptParcel createSignEncryptParcel(PgpSignEncryptData signEncryptData, byte[] bytes) {
// noinspection unchecked, it's ok for the empty list
return new AutoValue_SignEncryptParcel(signEncryptData, Collections.EMPTY_LIST, Collections.EMPTY_LIST, bytes);
}
public void setBytes(byte[] bytes) {
mBytes = bytes;
public static Builder builder(SignEncryptParcel signEncryptParcel) {
return new Builder(signEncryptParcel.getSignEncryptData())
.addInputUris(signEncryptParcel.getInputUris())
.addOutputUris(signEncryptParcel.getOutputUris());
}
public List<Uri> getInputUris() {
return Collections.unmodifiableList(mInputUris);
public static Builder builder(PgpSignEncryptData signEncryptData) {
return new Builder(signEncryptData);
}
public void addInputUris(Collection<Uri> inputUris) {
mInputUris.addAll(inputUris);
}
public List<Uri> getOutputUris() {
return Collections.unmodifiableList(mOutputUris);
}
public static class Builder {
private final PgpSignEncryptData signEncryptData;
private ArrayList<Uri> inputUris = new ArrayList<>();
private ArrayList<Uri> outputUris = new ArrayList<>();
public void addOutputUris(ArrayList<Uri> outputUris) {
mOutputUris.addAll(outputUris);
}
public void setData(PgpSignEncryptData data) {
this.data = data;
}
public PgpSignEncryptData getData() {
return data;
}
@Override
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(mInputUris);
dest.writeTypedList(mOutputUris);
dest.writeByteArray(mBytes);
dest.writeParcelable(data, 0);
}
public static final Creator<SignEncryptParcel> CREATOR = new Creator<SignEncryptParcel>() {
public SignEncryptParcel createFromParcel(final Parcel source) {
return new SignEncryptParcel(source);
private Builder(PgpSignEncryptData signEncryptData) {
this.signEncryptData = signEncryptData;
}
public SignEncryptParcel[] newArray(final int size) {
return new SignEncryptParcel[size];
public SignEncryptParcel build() {
return new AutoValue_SignEncryptParcel(signEncryptData,
Collections.unmodifiableList(inputUris),
Collections.unmodifiableList(outputUris),
null);
}
};
public Builder addOutputUris(Collection<Uri> outputUris) {
this.outputUris.addAll(outputUris);
return this;
}
public Builder addInputUris(Collection<Uri> inputUris) {
this.inputUris.addAll(inputUris);
return this;
}
}
}

View File

@@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.pgp;
import com.google.auto.value.AutoValue;
import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.BCPGOutputStream;
import org.bouncycastle.bcpg.Packet;

View File

@@ -22,6 +22,7 @@ package org.sufficientlysecure.keychain.remote;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
@@ -56,9 +57,8 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.DecryptVerifySecurityProblem;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyOperation;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInputParcel;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.SecurityProblem;
@@ -109,12 +109,11 @@ public class OpenPgpService extends Service {
boolean asciiArmor = cleartextSign || data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
// sign-only
PgpSignEncryptData pgpData = new PgpSignEncryptData();
PgpSignEncryptData.Builder pgpData = PgpSignEncryptData.builder();
pgpData.setEnableAsciiArmorOutput(asciiArmor)
.setCleartextSignature(cleartextSign)
.setDetachedSignature(!cleartextSign)
.setVersionHeader(null)
.setSignatureHashAlgorithm(PgpSecurityConstants.OpenKeychainHashAlgorithmTags.USE_DEFAULT);
.setVersionHeader(null);
Intent signKeyIdIntent = getSignKeyMasterId(data);
@@ -132,17 +131,13 @@ public class OpenPgpService extends Service {
// get first usable subkey capable of signing
try {
long signSubKeyId = mKeyRepository.getCachedPublicKeyRing(
pgpData.getSignatureMasterKeyId()).getSecretSignId();
long signSubKeyId = mKeyRepository.getCachedPublicKeyRing(signKeyId).getSecretSignId();
pgpData.setSignatureSubKeyId(signSubKeyId);
} catch (PgpKeyNotFoundException e) {
throw new Exception("signing subkey not found!", e);
}
}
PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel(pgpData);
pseInput.setAllowedKeyIds(getAllowedKeyIds());
pgpData.setAllowedSigningKeyIds(getAllowedKeyIds());
// Get Input- and OutputStream from ParcelFileDescriptor
if (!cleartextSign) {
@@ -155,17 +150,17 @@ public class OpenPgpService extends Service {
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
if (inputParcel == null) {
inputParcel = new CryptoInputParcel(new Date());
inputParcel = CryptoInputParcel.createCryptoInputParcel(new Date());
}
// override passphrase in input parcel if given by API call
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
inputParcel.mPassphrase =
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
inputParcel = inputParcel.withPassphrase(
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
}
// execute PGP operation!
PgpSignEncryptOperation pse = new PgpSignEncryptOperation(this, mKeyRepository, null);
PgpSignEncryptResult pgpResult = pse.execute(pseInput, inputParcel, inputData, outputStream);
PgpSignEncryptResult pgpResult = pse.execute(pgpData.build(), inputParcel, inputData, outputStream);
if (pgpResult.isPending()) {
RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel();
@@ -205,18 +200,14 @@ public class OpenPgpService extends Service {
originalFilename = "";
}
boolean enableCompression = data.getBooleanExtra(OpenPgpApi.EXTRA_ENABLE_COMPRESSION, true);
int compressionId;
if (enableCompression) {
compressionId = PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT;
} else {
compressionId = PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED;
}
PgpSignEncryptData.Builder pgpData = PgpSignEncryptData.builder()
.setEnableAsciiArmorOutput(asciiArmor)
.setVersionHeader(null);
PgpSignEncryptData pgpData = new PgpSignEncryptData();
pgpData.setEnableAsciiArmorOutput(asciiArmor)
.setVersionHeader(null)
.setCompressionAlgorithm(compressionId);
boolean enableCompression = data.getBooleanExtra(OpenPgpApi.EXTRA_ENABLE_COMPRESSION, true);
if (!enableCompression) {
pgpData.setCompressionAlgorithm(OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
}
if (sign) {
Intent signKeyIdIntent = getSignKeyMasterId(data);
@@ -260,17 +251,16 @@ public class OpenPgpService extends Service {
return result;
}
pgpData.setEncryptionMasterKeyIds(keyIdResult.getKeyIds());
PgpSignEncryptInputParcel pseInput = new PgpSignEncryptInputParcel(pgpData);
pseInput.setAllowedKeyIds(getAllowedKeyIds());
pgpData.setAllowedSigningKeyIds(getAllowedKeyIds());
CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
if (inputParcel == null) {
inputParcel = new CryptoInputParcel(new Date());
inputParcel = CryptoInputParcel.createCryptoInputParcel(new Date());
}
// override passphrase in input parcel if given by API call
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
inputParcel.mPassphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
inputParcel = inputParcel.withPassphrase(
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
}
// TODO this is not correct!
@@ -279,7 +269,7 @@ public class OpenPgpService extends Service {
// execute PGP operation!
PgpSignEncryptOperation op = new PgpSignEncryptOperation(this, mKeyRepository, null);
PgpSignEncryptResult pgpResult = op.execute(pseInput, inputParcel, inputData, outputStream);
PgpSignEncryptResult pgpResult = op.execute(pgpData.build(), inputParcel, inputData, outputStream);
if (pgpResult.isPending()) {
RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel();
@@ -353,17 +343,18 @@ public class OpenPgpService extends Service {
CryptoInputParcel cryptoInput = CryptoInputParcelCacheService.getCryptoInputParcel(this, data);
if (cryptoInput == null) {
cryptoInput = new CryptoInputParcel();
cryptoInput = CryptoInputParcel.createCryptoInputParcel();
}
// override passphrase in input parcel if given by API call
if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) {
cryptoInput.mPassphrase =
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
cryptoInput = cryptoInput.withPassphrase(
new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)));
}
if (data.hasExtra(OpenPgpApi.EXTRA_DECRYPTION_RESULT)) {
OpenPgpDecryptionResult decryptionResult = data.getParcelableExtra(OpenPgpApi.EXTRA_DECRYPTION_RESULT);
if (decryptionResult != null && decryptionResult.hasDecryptedSessionKey()) {
cryptoInput.addCryptoData(decryptionResult.getSessionKey(), decryptionResult.getDecryptedSessionKey());
cryptoInput = cryptoInput.withCryptoData(
decryptionResult.getSessionKey(), decryptionResult.getDecryptedSessionKey());
}
}
@@ -377,12 +368,13 @@ public class OpenPgpService extends Service {
// allow only private keys associated with accounts of this app
// no support for symmetric encryption
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel()
PgpDecryptVerifyInputParcel input = PgpDecryptVerifyInputParcel.builder()
.setAllowSymmetricDecryption(false)
.setAllowedKeyIds(getAllowedKeyIds())
.setAllowedKeyIds(new ArrayList<>(getAllowedKeyIds()))
.setDecryptMetadataOnly(decryptMetadataOnly)
.setDetachedSignature(detachedSignature)
.setSenderAddress(senderAddress);
.setSenderAddress(senderAddress)
.build();
DecryptVerifyResult pgpResult = op.execute(input, cryptoInput, inputData, outputStream);
@@ -657,7 +649,8 @@ public class OpenPgpService extends Service {
// after user interaction with RemoteBackupActivity,
// the backup code is cached in CryptoInputParcelCacheService, now we can proceed
BackupKeyringParcel input = new BackupKeyringParcel(masterKeyIds, backupSecret, true, enableAsciiArmorOutput, null);
BackupKeyringParcel input = BackupKeyringParcel
.createBackupKeyringParcel(masterKeyIds, backupSecret, true, enableAsciiArmorOutput, null);
BackupOperation op = new BackupOperation(this, mKeyRepository, null);
ExportResult pgpResult = op.execute(input, inputParcel, outputStream);

View File

@@ -24,6 +24,8 @@ import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.math.ec.ECCurve;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
// 4.3.3.6 Algorithm Attributes
public class ECKeyFormat extends KeyFormat {
@@ -84,7 +86,7 @@ public class ECKeyFormat extends KeyFormat {
}
}
public void addToSaveKeyringParcel(SaveKeyringParcel keyring, int keyFlags) {
public void addToSaveKeyringParcel(SaveKeyringParcel.Builder builder, int keyFlags) {
final X9ECParameters params = NISTNamedCurves.getByOID(mECCurveOID);
final ECCurve curve = params.getCurve();
@@ -105,7 +107,6 @@ public class ECKeyFormat extends KeyFormat {
throw new IllegalArgumentException("Unsupported curve " + mECCurveOID);
}
keyring.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(algo,
curve.getFieldSize(), scurve, keyFlags, 0L));
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(algo, curve.getFieldSize(), scurve, keyFlags, 0L));
}
}

View File

@@ -94,6 +94,6 @@ public abstract class KeyFormat {
throw new IllegalArgumentException("Unsupported Algorithm id " + t);
}
public abstract void addToSaveKeyringParcel(SaveKeyringParcel keyring, int keyFlags);
public abstract void addToSaveKeyringParcel(SaveKeyringParcel.Builder builder, int keyFlags);
}

View File

@@ -18,6 +18,8 @@
package org.sufficientlysecure.keychain.securitytoken;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
// 4.3.3.6 Algorithm Attributes
public class RSAKeyFormat extends KeyFormat {
@@ -84,8 +86,8 @@ public class RSAKeyFormat extends KeyFormat {
}
}
public void addToSaveKeyringParcel(SaveKeyringParcel keyring, int keyFlags) {
keyring.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
public void addToSaveKeyringParcel(SaveKeyringParcel.Builder builder, int keyFlags) {
builder.addSubkeyAdd(SubkeyAdd.createSubkeyAdd(SaveKeyringParcel.Algorithm.RSA,
mModulusLength, null, keyFlags, 0L));
}
}

View File

@@ -19,61 +19,28 @@
package org.sufficientlysecure.keychain.service;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
public class BackupKeyringParcel implements Parcelable {
public Uri mCanonicalizedPublicKeyringUri;
@AutoValue
public abstract class BackupKeyringParcel implements Parcelable {
@Nullable
@SuppressWarnings("mutable")
public abstract long[] getMasterKeyIds();
public abstract boolean getExportSecret();
public abstract boolean getIsEncrypted();
public abstract boolean getEnableAsciiArmorOutput();
@Nullable
public abstract Uri getOutputUri();
public final boolean mExportSecret;
public final boolean mIsEncrypted;
public final boolean mEnableAsciiArmorOutput;
public final long mMasterKeyIds[];
public final Uri mOutputUri;
public BackupKeyringParcel(long[] masterKeyIds, boolean exportSecret, boolean isEncrypted, boolean enableAsciiArmorOutput, Uri outputUri) {
mMasterKeyIds = masterKeyIds;
mExportSecret = exportSecret;
mOutputUri = outputUri;
mIsEncrypted = isEncrypted;
mEnableAsciiArmorOutput = enableAsciiArmorOutput;
public static BackupKeyringParcel createBackupKeyringParcel(long[] masterKeyIds, boolean exportSecret,
boolean isEncrypted, boolean enableAsciiArmorOutput, Uri outputUri) {
return new AutoValue_BackupKeyringParcel(
masterKeyIds, exportSecret, isEncrypted, enableAsciiArmorOutput, outputUri);
}
protected BackupKeyringParcel(Parcel in) {
mCanonicalizedPublicKeyringUri = (Uri) in.readValue(Uri.class.getClassLoader());
mExportSecret = in.readByte() != 0x00;
mOutputUri = (Uri) in.readValue(Uri.class.getClassLoader());
mMasterKeyIds = in.createLongArray();
mIsEncrypted = in.readInt() != 0;
mEnableAsciiArmorOutput = in.readInt() != 0;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(mCanonicalizedPublicKeyringUri);
dest.writeByte((byte) (mExportSecret ? 0x01 : 0x00));
dest.writeValue(mOutputUri);
dest.writeLongArray(mMasterKeyIds);
dest.writeInt(mIsEncrypted ? 1 : 0);
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
}
public static final Parcelable.Creator<BackupKeyringParcel> CREATOR = new Parcelable.Creator<BackupKeyringParcel>() {
@Override
public BackupKeyringParcel createFromParcel(Parcel in) {
return new BackupKeyringParcel(in);
}
@Override
public BackupKeyringParcel[] newArray(int size) {
return new BackupKeyringParcel[size];
}
};
}

View File

@@ -19,36 +19,16 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.auto.value.AutoValue;
public class BenchmarkInputParcel implements Parcelable {
public BenchmarkInputParcel() {
@AutoValue
public abstract class BenchmarkInputParcel implements Parcelable {
public static BenchmarkInputParcel newInstance() {
return new AutoValue_BenchmarkInputParcel();
}
protected BenchmarkInputParcel(Parcel in) {
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
public static final Creator<BenchmarkInputParcel> CREATOR = new Creator<BenchmarkInputParcel>() {
@Override
public BenchmarkInputParcel createFromParcel(Parcel in) {
return new BenchmarkInputParcel(in);
}
@Override
public BenchmarkInputParcel[] newArray(int size) {
return new BenchmarkInputParcel[size];
}
};
}

View File

@@ -18,99 +18,80 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import android.os.Parcelable;
import android.support.annotation.CheckResult;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
/**
* This class is a a transferable representation for a number of keyrings to
* be certified.
*/
public class CertifyActionsParcel implements Parcelable {
@AutoValue
public abstract class CertifyActionsParcel implements Parcelable {
public abstract long getMasterKeyId();
public abstract ArrayList<CertifyAction> getCertifyActions();
@Nullable
public abstract ParcelableHkpKeyserver getParcelableKeyServer();
// the master key id to certify with
final public long mMasterKeyId;
public CertifyLevel mLevel;
public ArrayList<CertifyAction> mCertifyActions = new ArrayList<>();
public ParcelableHkpKeyserver keyServerUri;
public CertifyActionsParcel(long masterKeyId) {
mMasterKeyId = masterKeyId;
mLevel = CertifyLevel.DEFAULT;
public static Builder builder(long masterKeyId) {
return new AutoValue_CertifyActionsParcel.Builder()
.setMasterKeyId(masterKeyId)
.setCertifyActions(new ArrayList<CertifyAction>());
}
public CertifyActionsParcel(Parcel source) {
mMasterKeyId = source.readLong();
// just like parcelables, this is meant for ad-hoc IPC only and is NOT portable!
mLevel = CertifyLevel.values()[source.readInt()];
keyServerUri = source.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
@AutoValue.Builder
public abstract static class Builder {
abstract Builder setMasterKeyId(long masterKeyId);
public abstract Builder setCertifyActions(ArrayList<CertifyAction> certifyActions);
public abstract Builder setParcelableKeyServer(ParcelableHkpKeyserver uri);
mCertifyActions = (ArrayList<CertifyAction>) source.readSerializable();
}
abstract ArrayList<CertifyAction> getCertifyActions();
public void add(CertifyAction action) {
mCertifyActions.add(action);
}
@Override
public void writeToParcel(Parcel destination, int flags) {
destination.writeLong(mMasterKeyId);
destination.writeInt(mLevel.ordinal());
destination.writeParcelable(keyServerUri, flags);
destination.writeSerializable(mCertifyActions);
}
public static final Creator<CertifyActionsParcel> CREATOR = new Creator<CertifyActionsParcel>() {
public CertifyActionsParcel createFromParcel(final Parcel source) {
return new CertifyActionsParcel(source);
public void addAction(CertifyAction action) {
getCertifyActions().add(action);
}
public void addActions(Collection<CertifyAction> certifyActions) {
getCertifyActions().addAll(certifyActions);
}
public CertifyActionsParcel[] newArray(final int size) {
return new CertifyActionsParcel[size];
public abstract CertifyActionsParcel build();
}
@AutoValue
public abstract static class CertifyAction implements Parcelable {
public abstract long getMasterKeyId();
@Nullable
public abstract ArrayList<String> getUserIds();
@Nullable
public abstract ArrayList<WrappedUserAttribute> getUserAttributes();
public static CertifyAction createForUserIds(long masterKeyId, List<String> userIds) {
return new AutoValue_CertifyActionsParcel_CertifyAction(masterKeyId, new ArrayList<>(userIds), null);
}
};
// TODO make this parcelable
public static class CertifyAction implements Serializable {
final public long mMasterKeyId;
public static CertifyAction createForUserAttributes(long masterKeyId, List<WrappedUserAttribute> attributes) {
return new AutoValue_CertifyActionsParcel_CertifyAction(masterKeyId, null, new ArrayList<>(attributes));
}
final public ArrayList<String> mUserIds;
final public ArrayList<WrappedUserAttribute> mUserAttributes;
@CheckResult
public CertifyAction withAddedUserIds(ArrayList<String> addedUserIds) {
if (getUserAttributes() != null) {
throw new IllegalStateException("Can't add user ids to user attribute certification parcel!");
}
ArrayList<String> prevUserIds = getUserIds();
if (prevUserIds == null) {
throw new IllegalStateException("Can't add user ids to user attribute certification parcel!");
}
public CertifyAction(long masterKeyId, List<String> userIds, List<WrappedUserAttribute> attributes) {
mMasterKeyId = masterKeyId;
mUserIds = userIds == null ? null : new ArrayList<>(userIds);
mUserAttributes = attributes == null ? null : new ArrayList<>(attributes);
ArrayList<String> userIds = new ArrayList<>(prevUserIds);
userIds.addAll(addedUserIds);
return new AutoValue_CertifyActionsParcel_CertifyAction(getMasterKeyId(), userIds, null);
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
String out = "mMasterKeyId: " + mMasterKeyId + "\n";
out += "mLevel: " + mLevel + "\n";
out += "mCertifyActions: " + mCertifyActions + "\n";
return out;
}
// All supported algorithms
public enum CertifyLevel {
DEFAULT, NONE, CASUAL, POSITIVE
}
}

View File

@@ -19,70 +19,29 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.util.Passphrase;
public class ChangeUnlockParcel implements Parcelable {
@AutoValue
public abstract class ChangeUnlockParcel implements Parcelable {
@Nullable
public abstract Long getMasterKeyId();
@Nullable
@SuppressWarnings("mutable")
public abstract byte[] getFingerprint();
public abstract Passphrase getNewPassphrase();
// the master key id of keyring.
public Long mMasterKeyId;
// the key fingerprint, for safety.
public byte[] mFingerprint;
// The new passphrase to use
public final Passphrase mNewPassphrase;
public ChangeUnlockParcel(Passphrase newPassphrase) {
mNewPassphrase = newPassphrase;
public static ChangeUnlockParcel createChangeUnlockParcel(Long masterKeyId, byte[] fingerprint,
Passphrase newPassphrase) {
return new AutoValue_ChangeUnlockParcel(masterKeyId, fingerprint, newPassphrase);
}
public ChangeUnlockParcel(Long masterKeyId, byte[] fingerprint, Passphrase newPassphrase) {
if (newPassphrase == null) {
throw new AssertionError("newPassphrase must be non-null. THIS IS A BUG!");
}
mMasterKeyId = masterKeyId;
mFingerprint = fingerprint;
mNewPassphrase = newPassphrase;
public static ChangeUnlockParcel createUnLockParcelForNewKey(Passphrase newPassphrase) {
return new AutoValue_ChangeUnlockParcel(null, null, newPassphrase);
}
public ChangeUnlockParcel(Parcel source) {
mMasterKeyId = source.readInt() != 0 ? source.readLong() : null;
mFingerprint = source.createByteArray();
mNewPassphrase = source.readParcelable(Passphrase.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel destination, int flags) {
destination.writeInt(mMasterKeyId == null ? 0 : 1);
if (mMasterKeyId != null) {
destination.writeLong(mMasterKeyId);
}
destination.writeByteArray(mFingerprint);
destination.writeParcelable(mNewPassphrase, flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<ChangeUnlockParcel> CREATOR = new Creator<ChangeUnlockParcel>() {
public ChangeUnlockParcel createFromParcel(final Parcel source) {
return new ChangeUnlockParcel(source);
}
public ChangeUnlockParcel[] newArray(final int size) {
return new ChangeUnlockParcel[size];
}
};
public String toString() {
String out = "mMasterKeyId: " + mMasterKeyId + "\n";
out += "passphrase (" + mNewPassphrase + ")";
return out;
}
}

View File

@@ -19,40 +19,17 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
public class ConsolidateInputParcel implements Parcelable {
import com.google.auto.value.AutoValue;
public boolean mConsolidateRecovery;
public ConsolidateInputParcel(boolean consolidateRecovery) {
mConsolidateRecovery = consolidateRecovery;
@AutoValue
public abstract class ConsolidateInputParcel implements Parcelable {
public abstract boolean isStartFromRecovery();
public static ConsolidateInputParcel createConsolidateInputParcel(boolean consolidateRecovery) {
return new AutoValue_ConsolidateInputParcel(consolidateRecovery);
}
protected ConsolidateInputParcel(Parcel in) {
mConsolidateRecovery = in.readByte() != 0x00;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mConsolidateRecovery ? 0x01 : 0x00));
}
public static final Parcelable.Creator<ConsolidateInputParcel> CREATOR = new Parcelable.Creator<ConsolidateInputParcel>() {
@Override
public ConsolidateInputParcel createFromParcel(Parcel in) {
return new ConsolidateInputParcel(in);
}
@Override
public ConsolidateInputParcel[] newArray(int size) {
return new ConsolidateInputParcel[size];
}
};
}

View File

@@ -19,45 +19,25 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
public class DeleteKeyringParcel implements Parcelable {
import com.google.auto.value.AutoValue;
public long[] mMasterKeyIds;
public boolean mIsSecret;
public DeleteKeyringParcel(long[] masterKeyIds, boolean isSecret) {
mMasterKeyIds = masterKeyIds;
mIsSecret = isSecret;
@AutoValue
public abstract class DeleteKeyringParcel implements Parcelable {
@SuppressWarnings("mutable")
public abstract long[] getMasterKeyIds();
public abstract boolean isDeleteSecret();
public static DeleteKeyringParcel createDeletePublicKeysParcel(long[] masterKeyIds) {
return new AutoValue_DeleteKeyringParcel(masterKeyIds, false);
}
protected DeleteKeyringParcel(Parcel in) {
mIsSecret = in.readByte() != 0x00;
mMasterKeyIds = in.createLongArray();
public static DeleteKeyringParcel createDeleteSingleSecretKeyParcel(long masterKeyId) {
return new AutoValue_DeleteKeyringParcel(new long[] { masterKeyId }, true);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mIsSecret ? 0x01 : 0x00));
dest.writeLongArray(mMasterKeyIds);
}
public static final Parcelable.Creator<DeleteKeyringParcel> CREATOR = new Parcelable.Creator<DeleteKeyringParcel>() {
@Override
public DeleteKeyringParcel createFromParcel(Parcel in) {
return new DeleteKeyringParcel(in);
}
@Override
public DeleteKeyringParcel[] newArray(int size) {
return new DeleteKeyringParcel[size];
}
};
}

View File

@@ -18,69 +18,31 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import java.util.ArrayList;
public class ImportKeyringParcel implements Parcelable {
// If null, keys are expected to be read from a cache file in ImportExportOperations
public ArrayList<ParcelableKeyRing> mKeyList;
public ParcelableHkpKeyserver mKeyserver; // must be set if keys are to be imported from a keyserver
import android.os.Parcelable;
import android.support.annotation.Nullable;
// If false, don't save the key, only return it as part of result
public boolean mSkipSave = false;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
public ImportKeyringParcel(ArrayList<ParcelableKeyRing> keyList, ParcelableHkpKeyserver keyserver) {
mKeyList = keyList;
mKeyserver = keyserver;
@AutoValue
public abstract class ImportKeyringParcel implements Parcelable {
@Nullable // If null, keys are expected to be read from a cache file in ImportExportOperations
public abstract ArrayList<ParcelableKeyRing> getKeyList();
@Nullable // must be set if keys are to be imported from a keyserver
public abstract ParcelableHkpKeyserver getKeyserver();
public abstract boolean isSkipSave();
public static ImportKeyringParcel createImportKeyringParcel(ArrayList<ParcelableKeyRing> keyList,
ParcelableHkpKeyserver keyserver) {
return new AutoValue_ImportKeyringParcel(keyList, keyserver, false);
}
public ImportKeyringParcel(ArrayList<ParcelableKeyRing> keyList, ParcelableHkpKeyserver keyserver, boolean skipSave) {
this(keyList, keyserver);
mSkipSave = skipSave;
public static ImportKeyringParcel createWithSkipSave(ArrayList<ParcelableKeyRing> keyList,
ParcelableHkpKeyserver keyserver) {
return new AutoValue_ImportKeyringParcel(keyList, keyserver, true);
}
protected ImportKeyringParcel(Parcel in) {
if (in.readByte() == 0x01) {
mKeyList = new ArrayList<>();
in.readList(mKeyList, ParcelableKeyRing.class.getClassLoader());
} else {
mKeyList = null;
}
mKeyserver = in.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
mSkipSave = in.readInt() != 0;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
if (mKeyList == null) {
dest.writeByte((byte) (0x00));
} else {
dest.writeByte((byte) (0x01));
dest.writeList(mKeyList);
}
dest.writeParcelable(mKeyserver, flags);
dest.writeInt(mSkipSave ? 1 : 0);
}
public static final Parcelable.Creator<ImportKeyringParcel> CREATOR = new Parcelable.Creator<ImportKeyringParcel>() {
@Override
public ImportKeyringParcel createFromParcel(Parcel in) {
return new ImportKeyringParcel(in);
}
@Override
public ImportKeyringParcel[] newArray(int size) {
return new ImportKeyringParcel[size];
}
};
}

View File

@@ -17,65 +17,24 @@
package org.sufficientlysecure.keychain.service;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.net.Uri;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
public class InputDataParcel implements Parcelable {
@AutoValue
public abstract class InputDataParcel implements Parcelable {
public abstract Uri getInputUri();
@Nullable
public abstract PgpDecryptVerifyInputParcel getDecryptInput();
public abstract boolean getMimeDecode(); // TODO static value - ditch this?
private Uri mInputUri;
private PgpDecryptVerifyInputParcel mDecryptInput;
private boolean mMimeDecode = true; // TODO default to false
public InputDataParcel(Uri inputUri, PgpDecryptVerifyInputParcel decryptInput) {
mInputUri = inputUri;
mDecryptInput = decryptInput;
public static InputDataParcel createInputDataParcel(Uri inputUri, PgpDecryptVerifyInputParcel decryptInput) {
return new AutoValue_InputDataParcel(inputUri, decryptInput, true);
}
InputDataParcel(Parcel source) {
// we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
mInputUri = source.readParcelable(getClass().getClassLoader());
mDecryptInput = source.readParcelable(getClass().getClassLoader());
mMimeDecode = source.readInt() != 0;
}
public Uri getInputUri() {
return mInputUri;
}
public PgpDecryptVerifyInputParcel getDecryptInput() {
return mDecryptInput;
}
public boolean getMimeDecode() {
return mMimeDecode;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mInputUri, 0);
dest.writeParcelable(mDecryptInput, 0);
dest.writeInt(mMimeDecode ? 1 : 0);
}
public static final Creator<InputDataParcel> CREATOR = new Creator<InputDataParcel>() {
public InputDataParcel createFromParcel(final Parcel source) {
return new InputDataParcel(source);
}
public InputDataParcel[] newArray(final int size) {
return new InputDataParcel[size];
}
};
}

View File

@@ -110,7 +110,7 @@ public class KeyserverSyncAdapterService extends Service {
}
case ACTION_UPDATE_ALL: {
// does not check for screen on/off
asyncKeyUpdate(this, new CryptoInputParcel(), startId);
asyncKeyUpdate(this, CryptoInputParcel.createCryptoInputParcel(), startId);
// we depend on handleUpdateResult to call stopSelf when it is no longer necessary
// for the intent to be redelivered
return START_REDELIVER_INTENT;
@@ -118,7 +118,7 @@ public class KeyserverSyncAdapterService extends Service {
case ACTION_IGNORE_TOR: {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(Constants.Notification.KEYSERVER_SYNC_FAIL_ORBOT);
asyncKeyUpdate(this, new CryptoInputParcel(ParcelableProxy.getForNoProxy()),
asyncKeyUpdate(this, CryptoInputParcel.createCryptoInputParcel(ParcelableProxy.getForNoProxy()),
startId);
// we depend on handleUpdateResult to call stopSelf when it is no longer necessary
// for the intent to be redelivered
@@ -324,7 +324,7 @@ public class KeyserverSyncAdapterService extends Service {
ImportOperation importOp = new ImportOperation(context,
KeyWritableRepository.createDatabaseReadWriteInteractor(context), null);
return importOp.execute(
new ImportKeyringParcel(keyList,
ImportKeyringParcel.createImportKeyringParcel(keyList,
Preferences.getPreferences(context).getPreferredKeyserver()),
cryptoInputParcel
);
@@ -384,7 +384,7 @@ public class KeyserverSyncAdapterService extends Service {
ImportKeyResult result =
new ImportOperation(context, KeyWritableRepository.createDatabaseReadWriteInteractor(context), null, mCancelled)
.execute(
new ImportKeyringParcel(
ImportKeyringParcel.createImportKeyringParcel(
keyWrapper,
Preferences.getPreferences(context)
.getPreferredKeyserver()

View File

@@ -19,48 +19,25 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
public class PromoteKeyringParcel implements Parcelable {
import com.google.auto.value.AutoValue;
public long mKeyRingId;
public byte[] mCardAid;
public long[] mSubKeyIds;
public PromoteKeyringParcel(long keyRingId, byte[] cardAid, long[] subKeyIds) {
mKeyRingId = keyRingId;
mCardAid = cardAid;
mSubKeyIds = subKeyIds;
@AutoValue
public abstract class PromoteKeyringParcel implements Parcelable {
public abstract long getMasterKeyId();
@Nullable
@SuppressWarnings("mutable")
public abstract byte[] getCardAid();
@Nullable
@SuppressWarnings("mutable")
public abstract long[] getSubKeyIds();
public static PromoteKeyringParcel createPromoteKeyringParcel(long keyRingId, byte[] cardAid,
@Nullable long[] subKeyIds) {
return new AutoValue_PromoteKeyringParcel(keyRingId, cardAid, subKeyIds);
}
protected PromoteKeyringParcel(Parcel in) {
mKeyRingId = in.readLong();
mCardAid = in.createByteArray();
mSubKeyIds = in.createLongArray();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mKeyRingId);
dest.writeByteArray(mCardAid);
dest.writeLongArray(mSubKeyIds);
}
public static final Parcelable.Creator<PromoteKeyringParcel> CREATOR = new Parcelable.Creator<PromoteKeyringParcel>() {
@Override
public PromoteKeyringParcel createFromParcel(Parcel in) {
return new PromoteKeyringParcel(in);
}
@Override
public PromoteKeyringParcel[] newArray(int size) {
return new PromoteKeyringParcel[size];
}
};
}

View File

@@ -19,50 +19,22 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
public class RevokeKeyringParcel implements Parcelable {
@AutoValue
public abstract class RevokeKeyringParcel implements Parcelable {
public abstract long getMasterKeyId();
public abstract boolean isShouldUpload();
@Nullable
public abstract ParcelableHkpKeyserver getKeyserver();
final public long mMasterKeyId;
final public boolean mUpload;
final public ParcelableHkpKeyserver mKeyserver;
public RevokeKeyringParcel(long masterKeyId, boolean upload, ParcelableHkpKeyserver keyserver) {
mMasterKeyId = masterKeyId;
mUpload = upload;
mKeyserver = keyserver;
public static RevokeKeyringParcel createRevokeKeyringParcel(long masterKeyId, boolean upload,
ParcelableHkpKeyserver keyserver) {
return new AutoValue_RevokeKeyringParcel(masterKeyId, upload, keyserver);
}
protected RevokeKeyringParcel(Parcel in) {
mMasterKeyId = in.readLong();
mUpload = in.readByte() != 0x00;
mKeyserver = in.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mMasterKeyId);
dest.writeByte((byte) (mUpload ? 0x01 : 0x00));
dest.writeParcelable(mKeyserver, flags);
}
public static final Parcelable.Creator<RevokeKeyringParcel> CREATOR = new Parcelable.Creator<RevokeKeyringParcel>() {
@Override
public RevokeKeyringParcel createFromParcel(Parcel in) {
return new RevokeKeyringParcel(in);
}
@Override
public RevokeKeyringParcel[] newArray(int size) {
return new RevokeKeyringParcel[size];
}
};
}

View File

@@ -18,15 +18,19 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.util.Passphrase;
/**
* This class is a a transferable representation for a collection of changes
@@ -43,306 +47,247 @@ import java.util.ArrayList;
* error in any included operation (for example revocation of a non-existent
* subkey) will cause the operation as a whole to fail.
*/
public class SaveKeyringParcel implements Parcelable {
@AutoValue
public abstract class SaveKeyringParcel implements Parcelable {
// the master key id to be edited. if this is null, a new one will be created
public Long mMasterKeyId;
@Nullable
public abstract Long getMasterKeyId();
// the key fingerprint, for safety. MUST be null for a new key.
public byte[] mFingerprint;
@Nullable
@SuppressWarnings("mutable")
public abstract byte[] getFingerprint();
public ArrayList<String> mAddUserIds;
public ArrayList<WrappedUserAttribute> mAddUserAttribute;
public ArrayList<SubkeyAdd> mAddSubKeys;
public abstract List<String> getAddUserIds();
public abstract List<WrappedUserAttribute> getAddUserAttribute();
public abstract List<SubkeyAdd> getAddSubKeys();
public ArrayList<SubkeyChange> mChangeSubKeys;
public String mChangePrimaryUserId;
public abstract List<SubkeyChange> getChangeSubKeys();
@Nullable
public abstract String getChangePrimaryUserId();
public ArrayList<String> mRevokeUserIds;
public ArrayList<Long> mRevokeSubKeys;
public abstract List<String> getRevokeUserIds();
public abstract List<Long> getRevokeSubKeys();
// if these are non-null, PINs will be changed on the token
public Passphrase mSecurityTokenPin;
public Passphrase mSecurityTokenAdminPin;
@Nullable
public abstract Passphrase getSecurityTokenPin();
@Nullable
public abstract Passphrase getSecurityTokenAdminPin();
// private because they have to be set together with setUpdateOptions
private boolean mUpload;
private boolean mUploadAtomic;
private ParcelableHkpKeyserver mKeyserver;
public abstract boolean isShouldUpload();
public abstract boolean isShouldUploadAtomic();
@Nullable
public abstract ParcelableHkpKeyserver getUploadKeyserver();
// private because we have to set other details like key id
private ChangeUnlockParcel mNewUnlock;
@Nullable
public abstract ChangeUnlockParcel getNewUnlock();
public SaveKeyringParcel() {
reset();
public static Builder buildNewKeyringParcel() {
return new AutoValue_SaveKeyringParcel.Builder()
.setShouldUpload(false)
.setShouldUploadAtomic(false);
}
public SaveKeyringParcel(long masterKeyId, byte[] fingerprint) {
this();
mMasterKeyId = masterKeyId;
mFingerprint = fingerprint;
public static Builder buildChangeKeyringParcel(long masterKeyId, byte[] fingerprint) {
return buildNewKeyringParcel()
.setMasterKeyId(masterKeyId)
.setFingerprint(fingerprint);
}
public void reset() {
mNewUnlock = null;
mAddUserIds = new ArrayList<>();
mAddUserAttribute = new ArrayList<>();
mAddSubKeys = new ArrayList<>();
mChangePrimaryUserId = null;
mChangeSubKeys = new ArrayList<>();
mRevokeUserIds = new ArrayList<>();
mRevokeSubKeys = new ArrayList<>();
mSecurityTokenPin = null;
mSecurityTokenAdminPin = null;
mUpload = false;
mUploadAtomic = false;
mKeyserver = null;
abstract Builder toBuilder();
public static Builder buildUpon(SaveKeyringParcel saveKeyringParcel) {
SaveKeyringParcel.Builder builder = saveKeyringParcel.toBuilder();
builder.addUserIds.addAll(saveKeyringParcel.getAddUserIds());
builder.revokeUserIds.addAll(saveKeyringParcel.getRevokeUserIds());
builder.addUserAttribute.addAll(saveKeyringParcel.getAddUserAttribute());
builder.addSubKeys.addAll(saveKeyringParcel.getAddSubKeys());
builder.changeSubKeys.addAll(saveKeyringParcel.getChangeSubKeys());
builder.revokeSubKeys.addAll(saveKeyringParcel.getRevokeSubKeys());
return builder;
}
public void setUpdateOptions(boolean upload, boolean uploadAtomic, ParcelableHkpKeyserver keyserver) {
mUpload = upload;
mUploadAtomic = uploadAtomic;
mKeyserver = keyserver;
}
@AutoValue.Builder
public static abstract class Builder {
private ArrayList<String> addUserIds = new ArrayList<>();
private ArrayList<String> revokeUserIds = new ArrayList<>();
private ArrayList<WrappedUserAttribute> addUserAttribute = new ArrayList<>();
private ArrayList<SubkeyAdd> addSubKeys = new ArrayList<>();
private ArrayList<SubkeyChange> changeSubKeys = new ArrayList<>();
private ArrayList<Long> revokeSubKeys = new ArrayList<>();
public void setNewUnlock(ChangeUnlockParcel parcel) {
mNewUnlock = parcel;
}
public ChangeUnlockParcel getChangeUnlockParcel() {
if(mNewUnlock != null) {
mNewUnlock.mMasterKeyId = mMasterKeyId;
mNewUnlock.mFingerprint = mFingerprint;
public abstract Builder setChangePrimaryUserId(String changePrimaryUserId);
public abstract Builder setSecurityTokenPin(Passphrase securityTokenPin);
public abstract Builder setSecurityTokenAdminPin(Passphrase securityTokenAdminPin);
public abstract Builder setNewUnlock(ChangeUnlockParcel newUnlock);
public abstract Long getMasterKeyId();
public abstract byte[] getFingerprint();
public abstract String getChangePrimaryUserId();
public ArrayList<SubkeyAdd> getMutableAddSubKeys() {
return addSubKeys;
}
return mNewUnlock;
}
public boolean isUpload() {
return mUpload;
}
public boolean isUploadAtomic() {
return mUploadAtomic;
}
public ParcelableHkpKeyserver getUploadKeyserver() {
return mKeyserver;
}
public boolean isEmpty() {
return isRestrictedOnly() && mChangeSubKeys.isEmpty();
}
/** Returns true iff this parcel does not contain any operations which require a passphrase. */
public boolean isRestrictedOnly() {
if (mNewUnlock != null || !mAddUserIds.isEmpty() || !mAddUserAttribute.isEmpty()
|| !mAddSubKeys.isEmpty() || mChangePrimaryUserId != null || !mRevokeUserIds.isEmpty()
|| !mRevokeSubKeys.isEmpty()) {
return false;
public ArrayList<String> getMutableAddUserIds() {
return addUserIds;
}
public ArrayList<Long> getMutableRevokeSubKeys() {
return revokeSubKeys;
}
public ArrayList<String> getMutableRevokeUserIds() {
return revokeUserIds;
}
for (SubkeyChange change : mChangeSubKeys) {
if (change.mRecertify || change.mFlags != null || change.mExpiry != null
|| change.mMoveKeyToSecurityToken) {
return false;
abstract Builder setMasterKeyId(Long masterKeyId);
abstract Builder setFingerprint(byte[] fingerprint);
abstract Builder setAddUserIds(List<String> addUserIds);
abstract Builder setAddUserAttribute(List<WrappedUserAttribute> addUserAttribute);
abstract Builder setAddSubKeys(List<SubkeyAdd> addSubKeys);
abstract Builder setChangeSubKeys(List<SubkeyChange> changeSubKeys);
abstract Builder setRevokeUserIds(List<String> revokeUserIds);
abstract Builder setRevokeSubKeys(List<Long> revokeSubKeys);
abstract Builder setShouldUpload(boolean upload);
abstract Builder setShouldUploadAtomic(boolean uploadAtomic);
abstract Builder setUploadKeyserver(ParcelableHkpKeyserver keyserver);
public void setUpdateOptions(boolean upload, boolean uploadAtomic, ParcelableHkpKeyserver keyserver) {
setShouldUpload(upload);
setShouldUploadAtomic(uploadAtomic);
setUploadKeyserver(keyserver);
}
public void addSubkeyAdd(SubkeyAdd subkeyAdd) {
addSubKeys.add(subkeyAdd);
}
public void addUserId(String userId) {
addUserIds.add(userId);
}
public void addRevokeSubkey(long masterKeyId) {
revokeSubKeys.add(masterKeyId);
}
public void removeRevokeSubkey(long keyId) {
revokeSubKeys.remove(keyId);
}
public void addRevokeUserId(String userId) {
revokeUserIds.add(userId);
}
public void removeRevokeUserId(String userId) {
revokeUserIds.remove(userId);
}
public void addOrReplaceSubkeyChange(SubkeyChange newChange) {
SubkeyChange foundSubkeyChange = getSubkeyChange(newChange.getSubKeyId());
if (foundSubkeyChange != null) {
changeSubKeys.remove(foundSubkeyChange);
}
changeSubKeys.add(newChange);
}
return true;
public void removeSubkeyChange(SubkeyChange change) {
changeSubKeys.remove(change);
}
public SubkeyChange getSubkeyChange(long keyId) {
if (changeSubKeys == null) {
return null;
}
for (SubkeyChange subkeyChange : changeSubKeys) {
if (subkeyChange.getSubKeyId() == keyId) {
return subkeyChange;
}
}
return null;
}
public void addUserAttribute(WrappedUserAttribute ua) {
addUserAttribute.add(ua);
}
abstract SaveKeyringParcel autoBuild();
public SaveKeyringParcel build() {
setAddUserAttribute(Collections.unmodifiableList(addUserAttribute));
setRevokeSubKeys(Collections.unmodifiableList(revokeSubKeys));
setRevokeUserIds(Collections.unmodifiableList(revokeUserIds));
setAddSubKeys(Collections.unmodifiableList(addSubKeys));
setAddUserIds(Collections.unmodifiableList(addUserIds));
setChangeSubKeys(Collections.unmodifiableList(changeSubKeys));
return autoBuild();
}
}
// performance gain for using Parcelable here would probably be negligible,
// use Serializable instead.
public static class SubkeyAdd implements Serializable {
public Algorithm mAlgorithm;
public Integer mKeySize;
public Curve mCurve;
public int mFlags;
public Long mExpiry;
@AutoValue
public abstract static class SubkeyAdd implements Serializable {
public abstract Algorithm getAlgorithm();
@Nullable
public abstract Integer getKeySize();
@Nullable
public abstract Curve getCurve();
public abstract int getFlags();
@Nullable
public abstract Long getExpiry();
public SubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags, Long expiry) {
mAlgorithm = algorithm;
mKeySize = keySize;
mCurve = curve;
mFlags = flags;
mExpiry = expiry;
}
@Override
public String toString() {
String out = "mAlgorithm: " + mAlgorithm + ", ";
out += "mKeySize: " + mKeySize + ", ";
out += "mCurve: " + mCurve + ", ";
out += "mFlags: " + mFlags;
out += "mExpiry: " + mExpiry;
return out;
public static SubkeyAdd createSubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags,
Long expiry) {
return new AutoValue_SaveKeyringParcel_SubkeyAdd(algorithm, keySize, curve, flags, expiry);
}
}
public static class SubkeyChange implements Serializable {
public final long mKeyId;
public Integer mFlags;
@AutoValue
public abstract static class SubkeyChange implements Serializable {
public abstract long getSubKeyId();
@Nullable
public abstract Integer getFlags();
// this is a long unix timestamp, in seconds (NOT MILLISECONDS!)
public Long mExpiry;
@Nullable
public abstract Long getExpiry();
// if this flag is true, the key will be recertified even if all above
// values are no-ops
public boolean mRecertify;
public abstract boolean getRecertify();
// if this flag is true, the subkey should be changed to a stripped key
public boolean mDummyStrip;
public abstract boolean getDummyStrip();
// if this flag is true, the subkey should be moved to a security token
public boolean mMoveKeyToSecurityToken;
public abstract boolean getMoveKeyToSecurityToken();
// if this is non-null, the subkey will be changed to a divert-to-card
// (security token) key for the given serial number
public byte[] mSecurityTokenSerialNo;
@Nullable
@SuppressWarnings("mutable")
public abstract byte[] getSecurityTokenSerialNo();
public SubkeyChange(long keyId) {
mKeyId = keyId;
public static SubkeyChange createRecertifyChange(long keyId, boolean recertify) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, recertify, false, false, null);
}
public SubkeyChange(long keyId, boolean recertify) {
mKeyId = keyId;
mRecertify = recertify;
public static SubkeyChange createFlagsOrExpiryChange(long keyId, Integer flags, Long expiry) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, flags, expiry, false, false, false, null);
}
public SubkeyChange(long keyId, Integer flags, Long expiry) {
mKeyId = keyId;
mFlags = flags;
mExpiry = expiry;
public static SubkeyChange createStripChange(long keyId) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, false, true, false, null);
}
public SubkeyChange(long keyId, boolean dummyStrip, boolean moveKeyToSecurityToken) {
this(keyId, null, null);
// these flags are mutually exclusive!
if (dummyStrip && moveKeyToSecurityToken) {
throw new AssertionError(
"cannot set strip and moveKeyToSecurityToken" +
" flags at the same time - this is a bug!");
}
mDummyStrip = dummyStrip;
mMoveKeyToSecurityToken = moveKeyToSecurityToken;
public static SubkeyChange createMoveToSecurityTokenChange(long keyId) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, false, false, true, null);
}
@Override
public String toString() {
String out = "mKeyId: " + mKeyId + ", ";
out += "mFlags: " + mFlags + ", ";
out += "mExpiry: " + mExpiry + ", ";
out += "mDummyStrip: " + mDummyStrip + ", ";
out += "mMoveKeyToSecurityToken: " + mMoveKeyToSecurityToken + ", ";
out += "mSecurityTokenSerialNo: [" + (mSecurityTokenSerialNo == null ? 0 : mSecurityTokenSerialNo.length) + " bytes]";
return out;
public static SubkeyChange createSecurityTokenSerialNo(long keyId, byte[] securityTokenSerialNo) {
return new AutoValue_SaveKeyringParcel_SubkeyChange(keyId, null, null, false, false, false, securityTokenSerialNo);
}
}
public SubkeyChange getSubkeyChange(long keyId) {
for (SubkeyChange subkeyChange : mChangeSubKeys) {
if (subkeyChange.mKeyId == keyId) {
return subkeyChange;
}
}
return null;
}
public SubkeyChange getOrCreateSubkeyChange(long keyId) {
SubkeyChange foundSubkeyChange = getSubkeyChange(keyId);
if (foundSubkeyChange != null) {
return foundSubkeyChange;
} else {
// else, create a new one
SubkeyChange newSubkeyChange = new SubkeyChange(keyId);
mChangeSubKeys.add(newSubkeyChange);
return newSubkeyChange;
}
}
@SuppressWarnings("unchecked") // we verify the reads against writes in writeToParcel
public SaveKeyringParcel(Parcel source) {
mMasterKeyId = source.readInt() != 0 ? source.readLong() : null;
mFingerprint = source.createByteArray();
mNewUnlock = source.readParcelable(getClass().getClassLoader());
mAddUserIds = source.createStringArrayList();
mAddUserAttribute = (ArrayList<WrappedUserAttribute>) source.readSerializable();
mAddSubKeys = (ArrayList<SubkeyAdd>) source.readSerializable();
mChangeSubKeys = (ArrayList<SubkeyChange>) source.readSerializable();
mChangePrimaryUserId = source.readString();
mRevokeUserIds = source.createStringArrayList();
mRevokeSubKeys = (ArrayList<Long>) source.readSerializable();
mSecurityTokenPin = source.readParcelable(Passphrase.class.getClassLoader());
mSecurityTokenAdminPin = source.readParcelable(Passphrase.class.getClassLoader());
mUpload = source.readByte() != 0;
mUploadAtomic = source.readByte() != 0;
mKeyserver = source.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel destination, int flags) {
destination.writeInt(mMasterKeyId == null ? 0 : 1);
if (mMasterKeyId != null) {
destination.writeLong(mMasterKeyId);
}
destination.writeByteArray(mFingerprint);
// yes, null values are ok for parcelables
destination.writeParcelable(mNewUnlock, flags);
destination.writeStringList(mAddUserIds);
destination.writeSerializable(mAddUserAttribute);
destination.writeSerializable(mAddSubKeys);
destination.writeSerializable(mChangeSubKeys);
destination.writeString(mChangePrimaryUserId);
destination.writeStringList(mRevokeUserIds);
destination.writeSerializable(mRevokeSubKeys);
destination.writeParcelable(mSecurityTokenPin, flags);
destination.writeParcelable(mSecurityTokenAdminPin, flags);
destination.writeByte((byte) (mUpload ? 1 : 0));
destination.writeByte((byte) (mUploadAtomic ? 1 : 0));
destination.writeParcelable(mKeyserver, flags);
}
public static final Creator<SaveKeyringParcel> CREATOR = new Creator<SaveKeyringParcel>() {
public SaveKeyringParcel createFromParcel(final Parcel source) {
return new SaveKeyringParcel(source);
}
public SaveKeyringParcel[] newArray(final int size) {
return new SaveKeyringParcel[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
String out = "mMasterKeyId: " + mMasterKeyId + "\n";
out += "mNewUnlock: " + mNewUnlock + "\n";
out += "mAddUserIds: " + mAddUserIds + "\n";
out += "mAddUserAttribute: " + mAddUserAttribute + "\n";
out += "mAddSubKeys: " + mAddSubKeys + "\n";
out += "mChangeSubKeys: " + mChangeSubKeys + "\n";
out += "mChangePrimaryUserId: " + mChangePrimaryUserId + "\n";
out += "mRevokeUserIds: " + mRevokeUserIds + "\n";
out += "mRevokeSubKeys: " + mRevokeSubKeys + "\n";
out += "mSecurityTokenPin: " + mSecurityTokenPin + "\n";
out += "mSecurityTokenAdminPin: " + mSecurityTokenAdminPin;
return out;
}
// All supported algorithms
public enum Algorithm {
RSA, DSA, ELGAMAL, ECDSA, ECDH
@@ -357,7 +302,4 @@ public class SaveKeyringParcel implements Parcelable {
// (adding support would be trivial though -> JcaPGPKeyConverter.java:190)
// BRAINPOOL_P256, BRAINPOOL_P384, BRAINPOOL_P512
}
}

View File

@@ -20,62 +20,29 @@
package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
@AutoValue
public abstract class UploadKeyringParcel implements Parcelable {
public abstract ParcelableHkpKeyserver getKeyserver();
@Nullable
public abstract Long getMasterKeyId();
@Nullable
@SuppressWarnings("mutable")
public abstract byte[] getUncachedKeyringBytes();
public class UploadKeyringParcel implements Parcelable {
public ParcelableHkpKeyserver mKeyserver;
public final Long mMasterKeyId;
public final byte[] mUncachedKeyringBytes;
public UploadKeyringParcel(ParcelableHkpKeyserver keyserver, long masterKeyId) {
mKeyserver = keyserver;
mMasterKeyId = masterKeyId;
mUncachedKeyringBytes = null;
public static UploadKeyringParcel createWithKeyId(ParcelableHkpKeyserver keyserver, long masterKeyId) {
return new AutoValue_UploadKeyringParcel(keyserver, masterKeyId, null);
}
public UploadKeyringParcel(ParcelableHkpKeyserver keyserver, byte[] uncachedKeyringBytes) {
mKeyserver = keyserver;
mMasterKeyId = null;
mUncachedKeyringBytes = uncachedKeyringBytes;
public static UploadKeyringParcel createWithKeyringBytes(ParcelableHkpKeyserver keyserver,
@NonNull byte[] uncachedKeyringBytes) {
return new AutoValue_UploadKeyringParcel(keyserver, null, uncachedKeyringBytes);
}
protected UploadKeyringParcel(Parcel in) {
mKeyserver = in.readParcelable(ParcelableHkpKeyserver.class.getClassLoader());
mMasterKeyId = in.readInt() != 0 ? in.readLong() : null;
mUncachedKeyringBytes = in.createByteArray();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mKeyserver, flags);
if (mMasterKeyId != null) {
dest.writeInt(1);
dest.writeLong(mMasterKeyId);
} else {
dest.writeInt(0);
}
dest.writeByteArray(mUncachedKeyringBytes);
}
public static final Creator<UploadKeyringParcel> CREATOR = new Creator<UploadKeyringParcel>() {
@Override
public UploadKeyringParcel createFromParcel(Parcel in) {
return new UploadKeyringParcel(in);
}
@Override
public UploadKeyringParcel[] newArray(int size) {
return new UploadKeyringParcel[size];
}
};
}

View File

@@ -19,181 +19,128 @@ package org.sufficientlysecure.keychain.service.input;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.CheckResult;
import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue;
import com.ryanharter.auto.value.parcel.ParcelAdapter;
import org.sufficientlysecure.keychain.util.ByteMapParcelAdapter;
import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Passphrase;
/**
* This is a base class for the input of crypto operations.
*/
public class CryptoInputParcel implements Parcelable {
@AutoValue
public abstract class CryptoInputParcel implements Parcelable {
@Nullable
public abstract Date getSignatureTime();
@Nullable
public abstract Passphrase getPassphrase();
public abstract boolean isCachePassphrase();
private Date mSignatureTime;
private boolean mHasSignature;
public boolean hasPassphrase() {
return getPassphrase() != null;
}
public Passphrase mPassphrase;
// used to supply an explicit proxy to operations that require it
// this is not final so it can be added to an existing CryptoInputParcel
// (e.g) CertifyOperation with upload might require both passphrase and orbot to be enabled
private ParcelableProxy mParcelableProxy;
// specifies whether passphrases should be cached
public boolean mCachePassphrase = true;
@Nullable
public abstract ParcelableProxy getParcelableProxy();
// this map contains both decrypted session keys and signed hashes to be
// used in the crypto operation described by this parcel.
private HashMap<ByteBuffer, byte[]> mCryptoData = new HashMap<>();
@ParcelAdapter(ByteMapParcelAdapter.class)
public abstract Map<ByteBuffer, byte[]> getCryptoData();
public CryptoInputParcel() {
mSignatureTime = null;
mPassphrase = null;
mCachePassphrase = true;
public static CryptoInputParcel createCryptoInputParcel() {
return new AutoValue_CryptoInputParcel(null, null, true, null, Collections.<ByteBuffer,byte[]>emptyMap());
}
public CryptoInputParcel(Date signatureTime, Passphrase passphrase) {
mHasSignature = true;
mSignatureTime = signatureTime == null ? new Date() : signatureTime;
mPassphrase = passphrase;
mCachePassphrase = true;
}
public CryptoInputParcel(Passphrase passphrase) {
mPassphrase = passphrase;
mCachePassphrase = true;
}
public CryptoInputParcel(Date signatureTime) {
mHasSignature = true;
mSignatureTime = signatureTime == null ? new Date() : signatureTime;
mPassphrase = null;
mCachePassphrase = true;
}
public CryptoInputParcel(ParcelableProxy parcelableProxy) {
this();
mParcelableProxy = parcelableProxy;
}
public CryptoInputParcel(Date signatureTime, boolean cachePassphrase) {
mHasSignature = true;
mSignatureTime = signatureTime == null ? new Date() : signatureTime;
mPassphrase = null;
mCachePassphrase = cachePassphrase;
}
public CryptoInputParcel(boolean cachePassphrase) {
mCachePassphrase = cachePassphrase;
}
protected CryptoInputParcel(Parcel source) {
mHasSignature = source.readByte() != 0;
if (mHasSignature) {
mSignatureTime = new Date(source.readLong());
public static CryptoInputParcel createCryptoInputParcel(Date signatureTime, Passphrase passphrase) {
if (signatureTime == null) {
signatureTime = new Date();
}
mPassphrase = source.readParcelable(getClass().getClassLoader());
mParcelableProxy = source.readParcelable(getClass().getClassLoader());
mCachePassphrase = source.readByte() != 0;
return new AutoValue_CryptoInputParcel(signatureTime, passphrase, true, null,
Collections.<ByteBuffer,byte[]>emptyMap());
}
{
int count = source.readInt();
mCryptoData = new HashMap<>(count);
for (int i = 0; i < count; i++) {
byte[] key = source.createByteArray();
byte[] value = source.createByteArray();
mCryptoData.put(ByteBuffer.wrap(key), value);
}
public static CryptoInputParcel createCryptoInputParcel(Passphrase passphrase) {
return new AutoValue_CryptoInputParcel(null, passphrase, true, null, Collections.<ByteBuffer,byte[]>emptyMap());
}
public static CryptoInputParcel createCryptoInputParcel(Date signatureTime) {
if (signatureTime == null) {
signatureTime = new Date();
}
return new AutoValue_CryptoInputParcel(signatureTime, null, true, null,
Collections.<ByteBuffer,byte[]>emptyMap());
}
@Override
public int describeContents() {
return 0;
public static CryptoInputParcel createCryptoInputParcel(ParcelableProxy parcelableProxy) {
return new AutoValue_CryptoInputParcel(null, null, true, parcelableProxy, new HashMap<ByteBuffer,byte[]>());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mHasSignature ? 1 : 0));
if (mHasSignature) {
dest.writeLong(mSignatureTime.getTime());
}
dest.writeParcelable(mPassphrase, 0);
dest.writeParcelable(mParcelableProxy, 0);
dest.writeByte((byte) (mCachePassphrase ? 1 : 0));
dest.writeInt(mCryptoData.size());
for (HashMap.Entry<ByteBuffer, byte[]> entry : mCryptoData.entrySet()) {
dest.writeByteArray(entry.getKey().array());
dest.writeByteArray(entry.getValue());
public static CryptoInputParcel createCryptoInputParcel(Date signatureTime, boolean cachePassphrase) {
if (signatureTime == null) {
signatureTime = new Date();
}
return new AutoValue_CryptoInputParcel(signatureTime, null, cachePassphrase, null,
new HashMap<ByteBuffer,byte[]>());
}
public void addParcelableProxy(ParcelableProxy parcelableProxy) {
mParcelableProxy = parcelableProxy;
public static CryptoInputParcel createCryptoInputParcel(boolean cachePassphrase) {
return new AutoValue_CryptoInputParcel(null, null, cachePassphrase, null, new HashMap<ByteBuffer,byte[]>());
}
public void addSignatureTime(Date signatureTime) {
mSignatureTime = signatureTime;
// TODO get rid of this!
@CheckResult
public CryptoInputParcel withCryptoData(byte[] hash, byte[] signedHash) {
Map<ByteBuffer,byte[]> newCryptoData = new HashMap<>(getCryptoData());
newCryptoData.put(ByteBuffer.wrap(hash), signedHash);
newCryptoData = Collections.unmodifiableMap(newCryptoData);
return new AutoValue_CryptoInputParcel(getSignatureTime(), getPassphrase(), isCachePassphrase(),
getParcelableProxy(), newCryptoData);
}
public void addCryptoData(byte[] hash, byte[] signedHash) {
mCryptoData.put(ByteBuffer.wrap(hash), signedHash);
@CheckResult
public CryptoInputParcel withCryptoData(Map<ByteBuffer, byte[]> cachedSessionKeys) {
Map<ByteBuffer,byte[]> newCryptoData = new HashMap<>(getCryptoData());
newCryptoData.putAll(cachedSessionKeys);
newCryptoData = Collections.unmodifiableMap(newCryptoData);
return new AutoValue_CryptoInputParcel(getSignatureTime(), getPassphrase(), isCachePassphrase(),
getParcelableProxy(), newCryptoData);
}
public void addCryptoData(Map<ByteBuffer, byte[]> cachedSessionKeys) {
mCryptoData.putAll(cachedSessionKeys);
@CheckResult
public CryptoInputParcel withPassphrase(Passphrase passphrase) {
return new AutoValue_CryptoInputParcel(getSignatureTime(), passphrase, isCachePassphrase(),
getParcelableProxy(), getCryptoData());
}
public ParcelableProxy getParcelableProxy() {
return mParcelableProxy;
@CheckResult
public CryptoInputParcel withNoCachePassphrase() {
return new AutoValue_CryptoInputParcel(getSignatureTime(), getPassphrase(), false, getParcelableProxy(),
getCryptoData());
}
public Map<ByteBuffer, byte[]> getCryptoData() {
return mCryptoData;
@CheckResult
public CryptoInputParcel withSignatureTime(Date signatureTime) {
return new AutoValue_CryptoInputParcel(signatureTime, getPassphrase(), isCachePassphrase(),
getParcelableProxy(), getCryptoData());
}
public Date getSignatureTime() {
return mSignatureTime;
@CheckResult
public CryptoInputParcel withParcelableProxy(ParcelableProxy parcelableProxy) {
return new AutoValue_CryptoInputParcel(getSignatureTime(), getPassphrase(), isCachePassphrase(),
parcelableProxy, getCryptoData());
}
public boolean hasPassphrase() {
return mPassphrase != null;
}
public Passphrase getPassphrase() {
return mPassphrase;
}
public static final Creator<CryptoInputParcel> CREATOR = new Creator<CryptoInputParcel>() {
public CryptoInputParcel createFromParcel(final Parcel source) {
return new CryptoInputParcel(source);
}
public CryptoInputParcel[] newArray(final int size) {
return new CryptoInputParcel[size];
}
};
@Override
public String toString() {
StringBuilder b = new StringBuilder();
b.append("CryptoInput: { ");
b.append(mSignatureTime).append(" ");
if (mPassphrase != null) {
b.append("passphrase");
}
if (mCryptoData != null) {
b.append(mCryptoData.size());
b.append(" hashes ");
}
b.append("}");
return b.toString();
}
}

View File

@@ -523,7 +523,8 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
// if we don't want to execute the actual operation outside of this activity, drop out here
if (!mExecuteBackupOperation) {
((BackupActivity) getActivity()).handleBackupOperation(new CryptoInputParcel(passphrase));
((BackupActivity) getActivity()).handleBackupOperation(
CryptoInputParcel.createCryptoInputParcel(passphrase));
return;
}
@@ -531,7 +532,7 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
mCachedBackupUri = TemporaryFileProvider.createFile(activity, filename,
Constants.MIME_TYPE_ENCRYPTED_ALTERNATE);
cryptoOperation(new CryptoInputParcel(passphrase));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(passphrase));
return;
}
@@ -605,7 +606,8 @@ public class BackupCodeFragment extends CryptoOperationFragment<BackupKeyringPar
@Nullable
@Override
public BackupKeyringParcel createOperationInput() {
return new BackupKeyringParcel(mMasterKeyIds, mExportSecret, true, true, mCachedBackupUri);
return BackupKeyringParcel
.createBackupKeyringParcel(mMasterKeyIds, mExportSecret, true, true, mCachedBackupUri);
}
@Override

View File

@@ -113,7 +113,7 @@ public class CertifyKeyFragment
Notify.create(getActivity(), getString(R.string.select_key_to_certify),
Notify.Style.ERROR).show();
} else {
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
}
}
});
@@ -140,18 +140,17 @@ public class CertifyKeyFragment
long selectedKeyId = mCertifyKeySpinner.getSelectedKeyId();
// fill values for this action
CertifyActionsParcel actionsParcel = new CertifyActionsParcel(selectedKeyId);
actionsParcel.mCertifyActions.addAll(certifyActions);
CertifyActionsParcel.Builder actionsParcel = CertifyActionsParcel.builder(selectedKeyId);
actionsParcel.addActions(certifyActions);
if (mUploadKeyCheckbox.isChecked()) {
actionsParcel.keyServerUri = Preferences.getPreferences(getActivity())
.getPreferredKeyserver();
actionsParcel.setParcelableKeyServer(Preferences.getPreferences(getActivity()).getPreferredKeyserver());
}
// cached for next cryptoOperation loop
cacheActionsParcel(actionsParcel);
return actionsParcel;
// cache for next cryptoOperation loop
CertifyActionsParcel certifyActionsParcel = actionsParcel.build();
cacheActionsParcel(certifyActionsParcel);
return certifyActionsParcel;
}
@Override

View File

@@ -67,7 +67,7 @@ public class ConsolidateDialogActivity extends FragmentActivity
@Override
public ConsolidateInputParcel createOperationInput() {
return new ConsolidateInputParcel(mRecovery);
return ConsolidateInputParcel.createConsolidateInputParcel(mRecovery);
}
@Override

View File

@@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
import org.sufficientlysecure.keychain.service.UploadKeyringParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
@@ -294,7 +295,7 @@ public class CreateKeyFinalFragment extends Fragment {
}
private static SaveKeyringParcel createDefaultSaveKeyringParcel(CreateKeyActivity createKeyActivity) {
SaveKeyringParcel saveKeyringParcel = new SaveKeyringParcel();
SaveKeyringParcel.Builder builder = SaveKeyringParcel.buildNewKeyringParcel();
if (createKeyActivity.mCreateSecurityToken) {
if (createKeyActivity.mSecurityTokenSign == null) {
@@ -302,37 +303,40 @@ public class CreateKeyFinalFragment extends Fragment {
createKeyActivity.mSecurityTokenDec = Constants.SECURITY_TOKEN_V2_DEC;
createKeyActivity.mSecurityTokenAuth = Constants.SECURITY_TOKEN_V2_AUTH;
}
createKeyActivity.mSecurityTokenSign.addToSaveKeyringParcel(saveKeyringParcel, KeyFlags.SIGN_DATA | KeyFlags.CERTIFY_OTHER);
createKeyActivity.mSecurityTokenDec.addToSaveKeyringParcel(saveKeyringParcel, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
createKeyActivity.mSecurityTokenAuth.addToSaveKeyringParcel(saveKeyringParcel, KeyFlags.AUTHENTICATION);
createKeyActivity.mSecurityTokenSign.addToSaveKeyringParcel(
builder, KeyFlags.SIGN_DATA | KeyFlags.CERTIFY_OTHER);
createKeyActivity.mSecurityTokenDec.addToSaveKeyringParcel(
builder, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
createKeyActivity.mSecurityTokenAuth.addToSaveKeyringParcel(builder, KeyFlags.AUTHENTICATION);
// use empty passphrase
saveKeyringParcel.setNewUnlock(new ChangeUnlockParcel(new Passphrase()));
builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase()));
} else {
Constants.addDefaultSubkeys(saveKeyringParcel);
Constants.addDefaultSubkeys(builder);
if (createKeyActivity.mPassphrase != null) {
saveKeyringParcel.setNewUnlock(new ChangeUnlockParcel(createKeyActivity.mPassphrase));
builder.setNewUnlock(
ChangeUnlockParcel.createUnLockParcelForNewKey(createKeyActivity.mPassphrase));
} else {
saveKeyringParcel.setNewUnlock(null);
builder.setNewUnlock(null);
}
}
String userId = KeyRing.createUserId(
new OpenPgpUtils.UserId(createKeyActivity.mName, createKeyActivity.mEmail, null)
);
saveKeyringParcel.mAddUserIds.add(userId);
saveKeyringParcel.mChangePrimaryUserId = userId;
builder.addUserId(userId);
builder.setChangePrimaryUserId(userId);
if (createKeyActivity.mAdditionalEmails != null
&& createKeyActivity.mAdditionalEmails.size() > 0) {
for (String email : createKeyActivity.mAdditionalEmails) {
String thisUserId = KeyRing.createUserId(
new OpenPgpUtils.UserId(createKeyActivity.mName, email, null)
);
saveKeyringParcel.mAddUserIds.add(thisUserId);
builder.addUserId(thisUserId);
}
}
return saveKeyringParcel;
return builder.build();
}
private void checkEmailValidity() {
@@ -425,11 +429,11 @@ public class CreateKeyFinalFragment extends Fragment {
private void moveToCard(final EditKeyResult saveKeyResult) {
CreateKeyActivity activity = (CreateKeyActivity) getActivity();
final SaveKeyringParcel changeKeyringParcel;
SaveKeyringParcel.Builder builder;
CachedPublicKeyRing key = (KeyRepository.createDatabaseInteractor(getContext()))
.getCachedPublicKeyRing(saveKeyResult.mMasterKeyId);
try {
changeKeyringParcel = new SaveKeyringParcel(key.getMasterKeyId(), key.getFingerprint());
builder = SaveKeyringParcel.buildChangeKeyringParcel(key.getMasterKeyId(), key.getFingerprint());
} catch (PgpKeyNotFoundException e) {
Log.e(Constants.TAG, "Key that should be moved to Security Token not found in database!");
return;
@@ -437,13 +441,13 @@ public class CreateKeyFinalFragment extends Fragment {
// define subkeys that should be moved to the card
Cursor cursor = activity.getContentResolver().query(
KeychainContract.Keys.buildKeysUri(changeKeyringParcel.mMasterKeyId),
KeychainContract.Keys.buildKeysUri(builder.getMasterKeyId()),
new String[]{KeychainContract.Keys.KEY_ID,}, null, null, null
);
try {
while (cursor != null && cursor.moveToNext()) {
long subkeyId = cursor.getLong(0);
changeKeyringParcel.getOrCreateSubkeyChange(subkeyId).mMoveKeyToSecurityToken = true;
builder.addOrReplaceSubkeyChange(SubkeyChange.createMoveToSecurityTokenChange(subkeyId));
}
} finally {
if (cursor != null) {
@@ -452,15 +456,17 @@ public class CreateKeyFinalFragment extends Fragment {
}
// define new PIN and Admin PIN for the card
changeKeyringParcel.mSecurityTokenPin = activity.mSecurityTokenPin;
changeKeyringParcel.mSecurityTokenAdminPin = activity.mSecurityTokenAdminPin;
builder.setSecurityTokenPin(activity.mSecurityTokenPin);
builder.setSecurityTokenAdminPin(activity.mSecurityTokenAdminPin);
final SaveKeyringParcel saveKeyringParcel = builder.build();
CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult> callback
= new CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult>() {
@Override
public SaveKeyringParcel createOperationInput() {
return changeKeyringParcel;
return saveKeyringParcel;
}
@Override
@@ -499,7 +505,7 @@ public class CreateKeyFinalFragment extends Fragment {
mMoveToCardOpHelper = new CryptoOperationHelper<>(2, this, callback, R.string.progress_modify);
mMoveToCardOpHelper.cryptoOperation(new CryptoInputParcel(new Date()));
mMoveToCardOpHelper.cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
}
private void uploadKey(final EditKeyResult saveKeyResult) {
@@ -520,7 +526,7 @@ public class CreateKeyFinalFragment extends Fragment {
@Override
public UploadKeyringParcel createOperationInput() {
return new UploadKeyringParcel(keyserver, masterKeyId);
return UploadKeyringParcel.createWithKeyId(keyserver, masterKeyId);
}
@Override

View File

@@ -235,7 +235,7 @@ public class CreateSecurityTokenImportResetFragment
Intent intent = new Intent(getActivity(), SecurityTokenOperationActivity.class);
RequiredInputParcel resetP = RequiredInputParcel.createSecurityTokenReset();
intent.putExtra(SecurityTokenOperationActivity.EXTRA_REQUIRED_INPUT, resetP);
intent.putExtra(SecurityTokenOperationActivity.EXTRA_CRYPTO_INPUT, new CryptoInputParcel());
intent.putExtra(SecurityTokenOperationActivity.EXTRA_CRYPTO_INPUT, CryptoInputParcel.createCryptoInputParcel());
startActivityForResult(intent, REQUEST_CODE_RESET);
}
@@ -271,7 +271,7 @@ public class CreateSecurityTokenImportResetFragment
@Override
public ImportKeyringParcel createOperationInput() {
return new ImportKeyringParcel(mKeyList, mKeyserver);
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
}
@Override

View File

@@ -159,7 +159,7 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
@Override
public ImportKeyringParcel createOperationInput() {
return new ImportKeyringParcel(keyList, keyserver);
return ImportKeyringParcel.createImportKeyringParcel(keyList, keyserver);
}
@Override

View File

@@ -637,9 +637,9 @@ public class DecryptListFragment
return null;
}
PgpDecryptVerifyInputParcel decryptInput = new PgpDecryptVerifyInputParcel()
PgpDecryptVerifyInputParcel.Builder decryptInput = PgpDecryptVerifyInputParcel.builder()
.setAllowSymmetricDecryption(true);
return new InputDataParcel(mCurrentInputUri, decryptInput);
return InputDataParcel.createInputDataParcel(mCurrentInputUri, decryptInput.build());
}
@@ -779,7 +779,7 @@ public class DecryptListFragment
@Override
public ImportKeyringParcel createOperationInput() {
return new ImportKeyringParcel(keyList, keyserver);
return ImportKeyringParcel.createImportKeyringParcel(keyList, keyserver);
}
@Override

View File

@@ -139,7 +139,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
}
private void startRevocationOperation() {
mRevokeOpHelper.cryptoOperation(new CryptoInputParcel(new Date(), false));
mRevokeOpHelper.cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date(), false));
}
private void startDeletionOperation() {
@@ -151,7 +151,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
return new CryptoOperationHelper.Callback<RevokeKeyringParcel, RevokeResult>() {
@Override
public RevokeKeyringParcel createOperationInput() {
return new RevokeKeyringParcel(mMasterKeyIds[0], true,
return RevokeKeyringParcel.createRevokeKeyringParcel(mMasterKeyIds[0], true,
(ParcelableHkpKeyserver) getIntent().getParcelableExtra(EXTRA_KEYSERVER));
}
@@ -183,9 +183,12 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
return new CryptoOperationHelper.Callback<DeleteKeyringParcel, DeleteResult>() {
@Override
public DeleteKeyringParcel createOperationInput() {
return new DeleteKeyringParcel(mMasterKeyIds, mHasSecret);
if (mHasSecret) {
return DeleteKeyringParcel.createDeleteSingleSecretKeyParcel(mMasterKeyIds[0]);
} else {
return DeleteKeyringParcel.createDeletePublicKeysParcel(mMasterKeyIds);
}
}
@Override
public void onCryptoOperationSuccess(DeleteResult result) {
returnResult(result);

View File

@@ -82,7 +82,7 @@ public class EditIdentitiesFragment extends Fragment
private Uri mDataUri;
private SaveKeyringParcel mSaveKeyringParcel;
private SaveKeyringParcel.Builder mSkpBuilder;
private CryptoOperationHelper<SaveKeyringParcel, EditKeyResult> mEditOpHelper;
private CryptoOperationHelper<UploadKeyringParcel, UploadResult> mUploadOpHelper;
@@ -180,7 +180,7 @@ public class EditIdentitiesFragment extends Fragment
return;
}
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback();
} catch (PgpKeyNotFoundException | NotFoundException e) {
@@ -193,11 +193,11 @@ public class EditIdentitiesFragment extends Fragment
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditIdentitiesFragment.this);
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
mUserIdsAdapter.setEditMode(mSaveKeyringParcel);
mUserIdsAdapter.setEditMode(mSkpBuilder);
mUserIdsList.setAdapter(mUserIdsAdapter);
// TODO: SaveParcel from savedInstance?!
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, false);
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), false);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
}
@@ -266,23 +266,23 @@ public class EditIdentitiesFragment extends Fragment
switch (message.what) {
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
// toggle
if (mSaveKeyringParcel.mChangePrimaryUserId != null
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
mSaveKeyringParcel.mChangePrimaryUserId = null;
if (mSkpBuilder.getChangePrimaryUserId() != null
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mSkpBuilder.setChangePrimaryUserId(null);
} else {
mSaveKeyringParcel.mChangePrimaryUserId = userId;
mSkpBuilder.setChangePrimaryUserId(userId);
}
break;
case EditUserIdDialogFragment.MESSAGE_REVOKE:
// toggle
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) {
mSaveKeyringParcel.mRevokeUserIds.remove(userId);
if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
mSkpBuilder.removeRevokeUserId(userId);
} else {
mSaveKeyringParcel.mRevokeUserIds.add(userId);
mSkpBuilder.addRevokeUserId(userId);
// not possible to revoke and change to primary user id
if (mSaveKeyringParcel.mChangePrimaryUserId != null
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
mSaveKeyringParcel.mChangePrimaryUserId = null;
if (mSkpBuilder.getChangePrimaryUserId() != null
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mSkpBuilder.setChangePrimaryUserId(null);
}
}
break;
@@ -339,7 +339,7 @@ public class EditIdentitiesFragment extends Fragment
= new CryptoOperationHelper.Callback<SaveKeyringParcel, EditKeyResult>() {
@Override
public SaveKeyringParcel createOperationInput() {
return mSaveKeyringParcel;
return mSkpBuilder.build();
}
@Override
@@ -395,7 +395,7 @@ public class EditIdentitiesFragment extends Fragment
@Override
public UploadKeyringParcel createOperationInput() {
return new UploadKeyringParcel(keyserver, masterKeyId);
return UploadKeyringParcel.createWithKeyId(keyserver, masterKeyId);
}
@Override

View File

@@ -100,7 +100,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
private Uri mDataUri;
private SaveKeyringParcel mSaveKeyringParcel;
private SaveKeyringParcel.Builder mSkpBuilder;
private String mPrimaryUserId;
@@ -156,7 +156,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
if (mDataUri == null) {
returnKeyringParcel();
} else {
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
}
}
}, new OnClickListener() {
@@ -184,13 +184,13 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
}
private void loadSaveKeyringParcel(SaveKeyringParcel saveKeyringParcel) {
mSaveKeyringParcel = saveKeyringParcel;
mPrimaryUserId = saveKeyringParcel.mChangePrimaryUserId;
mSkpBuilder = SaveKeyringParcel.buildUpon(saveKeyringParcel);
mPrimaryUserId = saveKeyringParcel.getChangePrimaryUserId();
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, true);
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), true);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys, true);
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSkpBuilder.getMutableAddSubKeys(), true);
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
}
@@ -213,7 +213,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
return;
}
mSaveKeyringParcel = new SaveKeyringParcel(masterKeyId, keyRing.getFingerprint());
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(masterKeyId, keyRing.getFingerprint());
mPrimaryUserId = keyRing.getPrimaryUserIdWithFallback();
} catch (PgpKeyNotFoundException | NotFoundException e) {
@@ -227,18 +227,18 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, EditKeyFragment.this);
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
mUserIdsAdapter.setEditMode(mSaveKeyringParcel);
mUserIdsAdapter.setEditMode(mSkpBuilder);
mUserIdsList.setAdapter(mUserIdsAdapter);
// TODO: SaveParcel from savedInstance?!
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSaveKeyringParcel.mAddUserIds, false);
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), false);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0);
mSubkeysAdapter.setEditMode(mSaveKeyringParcel);
mSubkeysAdapter.setEditMode(mSkpBuilder);
mSubkeysList.setAdapter(mSubkeysAdapter);
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys, false);
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSkpBuilder.getMutableAddSubKeys(), false);
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
}
@@ -341,7 +341,8 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
Bundle data = message.getData();
// cache new returned passphrase!
mSaveKeyringParcel.setNewUnlock(new ChangeUnlockParcel(
mSkpBuilder.setNewUnlock(ChangeUnlockParcel.createChangeUnlockParcel(
mSkpBuilder.getMasterKeyId(), mSkpBuilder.getFingerprint(),
(Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE)));
}
}
@@ -367,23 +368,23 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
switch (message.what) {
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
// toggle
if (mSaveKeyringParcel.mChangePrimaryUserId != null
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
mSaveKeyringParcel.mChangePrimaryUserId = null;
String changePrimaryUserId = mSkpBuilder.getChangePrimaryUserId();
if (changePrimaryUserId != null && changePrimaryUserId.equals(userId)) {
mSkpBuilder.setChangePrimaryUserId(null);
} else {
mSaveKeyringParcel.mChangePrimaryUserId = userId;
mSkpBuilder.setChangePrimaryUserId(userId);
}
break;
case EditUserIdDialogFragment.MESSAGE_REVOKE:
// toggle
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) {
mSaveKeyringParcel.mRevokeUserIds.remove(userId);
if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
mSkpBuilder.removeRevokeUserId(userId);
} else {
mSaveKeyringParcel.mRevokeUserIds.add(userId);
mSkpBuilder.addRevokeUserId(userId);
// not possible to revoke and change to primary user id
if (mSaveKeyringParcel.mChangePrimaryUserId != null
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
mSaveKeyringParcel.mChangePrimaryUserId = null;
if (mSkpBuilder.getChangePrimaryUserId() != null
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mSkpBuilder.setChangePrimaryUserId(null);
}
}
break;
@@ -416,10 +417,10 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
break;
case EditSubkeyDialogFragment.MESSAGE_REVOKE:
// toggle
if (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId)) {
mSaveKeyringParcel.mRevokeSubKeys.remove(keyId);
if (mSkpBuilder.getMutableRevokeSubKeys().contains(keyId)) {
mSkpBuilder.removeRevokeSubkey(keyId);
} else {
mSaveKeyringParcel.mRevokeSubKeys.add(keyId);
mSkpBuilder.addRevokeSubkey(keyId);
}
break;
case EditSubkeyDialogFragment.MESSAGE_STRIP: {
@@ -429,16 +430,11 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
break;
}
SubkeyChange change = mSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null) {
mSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false));
break;
}
// toggle
change.mDummyStrip = !change.mDummyStrip;
if (change.mDummyStrip && change.mMoveKeyToSecurityToken) {
// User had chosen to divert key, but now wants to strip it instead.
change.mMoveKeyToSecurityToken = false;
SubkeyChange change = mSkpBuilder.getSubkeyChange(keyId);
if (change == null || !change.getDummyStrip()) {
mSkpBuilder.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId));
} else {
mSkpBuilder.removeSubkeyChange(change);
}
break;
}
@@ -478,19 +474,13 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
break;
}
SubkeyChange change;
change = mSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null) {
mSaveKeyringParcel.mChangeSubKeys.add(
new SubkeyChange(keyId, false, true)
);
SubkeyChange change = mSkpBuilder.getSubkeyChange(keyId);
if (change == null || !change.getMoveKeyToSecurityToken()) {
mSkpBuilder.addOrReplaceSubkeyChange(
SubkeyChange.createMoveToSecurityTokenChange(keyId));
break;
}
// toggle
change.mMoveKeyToSecurityToken = !change.mMoveKeyToSecurityToken;
if (change.mMoveKeyToSecurityToken && change.mDummyStrip) {
// User had chosen to strip key, but now wants to divert it.
change.mDummyStrip = false;
} else {
mSkpBuilder.removeSubkeyChange(change);
}
break;
}
@@ -522,9 +512,10 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
public void handleMessage(Message message) {
switch (message.what) {
case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY:
mSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry =
(Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
Long expiry = (Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
mSkpBuilder.addOrReplaceSubkeyChange(
SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry));
break;
}
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
@@ -585,20 +576,20 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
}
protected void returnKeyringParcel() {
if (mSaveKeyringParcel.mAddUserIds.size() == 0) {
if (mSkpBuilder.getMutableAddUserIds().size() == 0) {
Notify.create(getActivity(), R.string.edit_key_error_add_identity, Notify.Style.ERROR).show();
return;
}
if (mSaveKeyringParcel.mAddSubKeys.size() == 0) {
if (mSkpBuilder.getMutableAddSubKeys().size() == 0) {
Notify.create(getActivity(), R.string.edit_key_error_add_subkey, Notify.Style.ERROR).show();
return;
}
// use first user id as primary
mSaveKeyringParcel.mChangePrimaryUserId = mSaveKeyringParcel.mAddUserIds.get(0);
String firstUserId = mSkpBuilder.getMutableAddUserIds().get(0);
mSkpBuilder.setChangePrimaryUserId(firstUserId);
Intent returnIntent = new Intent();
returnIntent.putExtra(EditKeyActivity.EXTRA_SAVE_KEYRING_PARCEL, mSaveKeyringParcel);
returnIntent.putExtra(EditKeyActivity.EXTRA_SAVE_KEYRING_PARCEL, mSkpBuilder.build());
getActivity().setResult(Activity.RESULT_OK, returnIntent);
getActivity().finish();
}
@@ -619,7 +610,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
@Override
public SaveKeyringParcel createOperationInput() {
return mSaveKeyringParcel;
return mSkpBuilder.build();
}
@Override

View File

@@ -345,19 +345,19 @@ public class EncryptFilesFragment
case R.id.encrypt_save: {
hideKeyboard();
mAfterEncryptAction = AfterEncryptAction.SAVE;
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
break;
}
case R.id.encrypt_share: {
hideKeyboard();
mAfterEncryptAction = AfterEncryptAction.SHARE;
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
break;
}
case R.id.encrypt_copy: {
hideKeyboard();
mAfterEncryptAction = AfterEncryptAction.COPY;
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
break;
}
case R.id.check_use_armor: {
@@ -577,12 +577,10 @@ public class EncryptFilesFragment
}
public SignEncryptParcel createOperationInput() {
SignEncryptParcel actionsParcel = getCachedActionsParcel();
// we have three cases here: nothing cached, cached except output, fully cached
if (actionsParcel == null) {
// clear output uris for now, they will be created by prepareOutputStreams later
mOutputUris = null;
@@ -593,7 +591,6 @@ public class EncryptFilesFragment
}
cacheActionsParcel(actionsParcel);
}
// if it's incomplete, prepare output streams
@@ -606,9 +603,10 @@ public class EncryptFilesFragment
}
}
actionsParcel.addOutputUris(mOutputUris);
actionsParcel = SignEncryptParcel.builder(actionsParcel)
.addOutputUris(mOutputUris)
.build();
cacheActionsParcel(actionsParcel);
}
return actionsParcel;
@@ -623,21 +621,13 @@ public class EncryptFilesFragment
}
// fill values for this action
PgpSignEncryptData data = new PgpSignEncryptData();
PgpSignEncryptData.Builder data = PgpSignEncryptData.builder();
if (mUseCompression) {
data.setCompressionAlgorithm(
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
} else {
data.setCompressionAlgorithm(
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
if (!mUseCompression) {
data.setCompressionAlgorithm(PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
}
data.setHiddenRecipients(mHiddenRecipients);
data.setEnableAsciiArmorOutput(mAfterEncryptAction == AfterEncryptAction.COPY || mUseArmor);
data.setSymmetricEncryptionAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
data.setSignatureHashAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
EncryptActivity encryptActivity = (EncryptActivity) getActivity();
EncryptModeFragment modeFragment = encryptActivity.getModeFragment();
@@ -675,10 +665,9 @@ public class EncryptFilesFragment
}
SignEncryptParcel parcel = new SignEncryptParcel(data);
parcel.addInputUris(mFilesAdapter.getAsArrayList());
return parcel;
SignEncryptParcel.Builder builder = SignEncryptParcel.builder(data.build());
builder.addInputUris(mFilesAdapter.getAsArrayList());
return builder.build();
}
private Intent createSendIntent() {
@@ -733,7 +722,7 @@ public class EncryptFilesFragment
mOutputUris.add(data.getData());
// make sure this is correct at this point
mAfterEncryptAction = AfterEncryptAction.SAVE;
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
} else if (resultCode == Activity.RESULT_CANCELED) {
onCryptoOperationCancelled();
}

View File

@@ -17,6 +17,11 @@
package org.sufficientlysecure.keychain.ui;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
@@ -38,7 +43,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants;
import org.sufficientlysecure.keychain.pgp.PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags;
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
@@ -49,10 +54,6 @@ import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
public class EncryptTextFragment
extends CachingCryptoOperationFragment<SignEncryptParcel, SignEncryptResult> {
@@ -181,18 +182,18 @@ public class EncryptTextFragment
case R.id.encrypt_copy: {
hideKeyboard();
mShareAfterEncrypt = false;
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
break;
}
case R.id.encrypt_share: {
hideKeyboard();
mShareAfterEncrypt = true;
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
break;
}
case R.id.encrypt_paste: {
hideKeyboard();
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
break;
}
default: {
@@ -233,22 +234,14 @@ public class EncryptTextFragment
}
// fill values for this action
PgpSignEncryptData data = new PgpSignEncryptData();
PgpSignEncryptData.Builder data = PgpSignEncryptData.builder();
data.setCleartextSignature(true);
if (mUseCompression) {
data.setCompressionAlgorithm(
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.USE_DEFAULT);
} else {
data.setCompressionAlgorithm(
PgpSecurityConstants.OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
if (!mUseCompression) {
data.setCompressionAlgorithm(OpenKeychainCompressionAlgorithmTags.UNCOMPRESSED);
}
data.setHiddenRecipients(mHiddenRecipients);
data.setSymmetricEncryptionAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
data.setSignatureHashAlgorithm(
PgpSecurityConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_DEFAULT);
// Always use armor for messages
data.setEnableAsciiArmorOutput(true);
@@ -286,10 +279,7 @@ public class EncryptTextFragment
data.setSymmetricPassphrase(passphrase);
}
SignEncryptParcel parcel = new SignEncryptParcel(data);
parcel.setBytes(mMessage.getBytes());
return parcel;
return SignEncryptParcel.createSignEncryptParcel(data.build(), mMessage.getBytes());
}
private void copyToClipboard(SignEncryptResult result) {

View File

@@ -357,7 +357,7 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen
return;
}
ImportKeyringParcel inputParcel = new ImportKeyringParcel(null, null);
ImportKeyringParcel inputParcel = ImportKeyringParcel.createImportKeyringParcel(null, null);
ImportKeysOperationCallback callback = new ImportKeysOperationCallback(this, inputParcel, null);
mOpHelper = new CryptoOperationHelper<>(1, this, callback, R.string.progress_importing);
mOpHelper.cryptoOperation();

View File

@@ -223,7 +223,7 @@ public class ImportKeysProxyActivity extends FragmentActivity
@Override
public ImportKeyringParcel createOperationInput() {
return new ImportKeyringParcel(mKeyList, mKeyserver);
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
}
@Override

View File

@@ -519,7 +519,7 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
@Override
public ImportKeyringParcel createOperationInput() {
return new ImportKeyringParcel(mKeyList, mKeyserver);
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
}
@Override
@@ -553,7 +553,7 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
@Override
public ConsolidateInputParcel createOperationInput() {
return new ConsolidateInputParcel(false); // we want to perform a full consolidate
return ConsolidateInputParcel.createConsolidateInputParcel(false); // we want to perform a full consolidate
}
@Override
@@ -586,7 +586,7 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
@Override
public BenchmarkInputParcel createOperationInput() {
return new BenchmarkInputParcel(); // we want to perform a full consolidate
return BenchmarkInputParcel.newInstance(); // we want to perform a full consolidate
}
@Override

View File

@@ -70,7 +70,7 @@ public class OrbotRequiredDialogActivity extends FragmentActivity
mCryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT);
if (mCryptoInputParcel == null) {
// compatibility with usages that don't use a CryptoInputParcel
mCryptoInputParcel = new CryptoInputParcel();
mCryptoInputParcel = CryptoInputParcel.createCryptoInputParcel();
}
mMessenger = getIntent().getParcelableExtra(EXTRA_MESSENGER);
@@ -147,7 +147,7 @@ public class OrbotRequiredDialogActivity extends FragmentActivity
public void onNeutralButton() {
sendMessage(MESSAGE_ORBOT_IGNORE);
Intent intent = new Intent();
mCryptoInputParcel.addParcelableProxy(ParcelableProxy.getForNoProxy());
mCryptoInputParcel = mCryptoInputParcel.withParcelableProxy(ParcelableProxy.getForNoProxy());
intent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel);
setResult(RESULT_OK, intent);
finish();

View File

@@ -99,7 +99,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
CryptoInputParcel cryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT);
if (cryptoInputParcel == null) {
cryptoInputParcel = new CryptoInputParcel();
cryptoInputParcel = CryptoInputParcel.createCryptoInputParcel();
getIntent().putExtra(EXTRA_CRYPTO_INPUT, cryptoInputParcel);
}
@@ -117,7 +117,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
if (pubRing.getSecretKeyType(requiredInput.getSubKeyId()) == SecretKeyType.PASSPHRASE_EMPTY) {
// also return passphrase back to activity
Intent returnIntent = new Intent();
cryptoInputParcel.mPassphrase = new Passphrase("");
cryptoInputParcel = cryptoInputParcel.withPassphrase(new Passphrase(""));
returnIntent.putExtra(RESULT_CRYPTO_INPUT, cryptoInputParcel);
setResult(RESULT_OK, returnIntent);
finish();
@@ -539,7 +539,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
CryptoInputParcel inputParcel = getArguments().getParcelable(EXTRA_CRYPTO_INPUT);
// noinspection ConstantConditions, we handle the non-null case in PassphraseDialogActivity.onCreate()
inputParcel.mPassphrase = passphrase;
inputParcel = inputParcel.withPassphrase(passphrase);
((PassphraseDialogActivity) getActivity()).handleResult(inputParcel);

View File

@@ -185,7 +185,7 @@ public class SafeSlingerActivity extends BaseActivity
@Override
public ImportKeyringParcel createOperationInput() {
return new ImportKeyringParcel(mKeyList, mKeyserver);
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
}
@Override

View File

@@ -206,7 +206,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
for (int i = 0; i < mRequiredInput.mInputData.length; i++) {
byte[] encryptedSessionKey = mRequiredInput.mInputData[i];
byte[] decryptedSessionKey = mSecurityTokenHelper.decryptSessionKey(encryptedSessionKey, publicKeyRing.getPublicKey(tokenKeyId));
mInputParcel.addCryptoData(encryptedSessionKey, decryptedSessionKey);
mInputParcel = mInputParcel.withCryptoData(encryptedSessionKey, decryptedSessionKey);
}
break;
}
@@ -218,13 +218,13 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
throw new IOException(getString(R.string.error_wrong_security_token));
}
mInputParcel.addSignatureTime(mRequiredInput.mSignatureTime);
mInputParcel = mInputParcel.withSignatureTime(mRequiredInput.mSignatureTime);
for (int i = 0; i < mRequiredInput.mInputData.length; i++) {
byte[] hash = mRequiredInput.mInputData[i];
int algo = mRequiredInput.mSignAlgos[i];
byte[] signedHash = mSecurityTokenHelper.calculateSignature(hash, algo);
mInputParcel.addCryptoData(hash, signedHash);
mInputParcel = mInputParcel.withCryptoData(hash, signedHash);
}
break;
}
@@ -266,7 +266,7 @@ public class SecurityTokenOperationActivity extends BaseSecurityTokenActivity {
mSecurityTokenHelper.changeKey(key, passphrase);
// TODO: Is this really used anywhere?
mInputParcel.addCryptoData(subkeyBytes, tokenSerialNumber);
mInputParcel = mInputParcel.withCryptoData(subkeyBytes, tokenSerialNumber);
}
// change PINs afterwards

View File

@@ -144,7 +144,7 @@ public class UploadKeyActivity extends BaseActivity
public UploadKeyringParcel createOperationInput() {
long[] masterKeyIds = getIntent().getLongArrayExtra(MultiUserIdsFragment.EXTRA_KEY_IDS);
return new UploadKeyringParcel(mKeyserver, masterKeyIds[0]);
return UploadKeyringParcel.createWithKeyId(mKeyserver, masterKeyIds[0]);
}
@Override

View File

@@ -82,7 +82,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
private long mMasterKeyId;
private byte[] mFingerprint;
private boolean mHasSecret;
private SaveKeyringParcel mEditModeSaveKeyringParcel;
private SaveKeyringParcel.Builder mEditModeSkpBuilder;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
@@ -250,15 +250,15 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mEditModeSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint);
mEditModeSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
mSubkeysAddedAdapter =
new SubkeysAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddSubKeys, false);
mSubkeysAddedAdapter = new SubkeysAddedAdapter(
getActivity(), mEditModeSkpBuilder.getMutableAddSubKeys(), false);
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
mSubkeysAddedLayout.setVisibility(View.VISIBLE);
mSubkeyAddFabLayout.setDisplayedChild(1);
mSubkeysAdapter.setEditMode(mEditModeSaveKeyringParcel);
mSubkeysAdapter.setEditMode(mEditModeSkpBuilder);
getLoaderManager().restartLoader(LOADER_ID_SUBKEYS, null, ViewKeyAdvSubkeysFragment.this);
mode.setTitle(R.string.title_edit_subkeys);
@@ -280,7 +280,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
@Override
public void onDestroyActionMode(ActionMode mode) {
mEditModeSaveKeyringParcel = null;
mEditModeSkpBuilder = null;
mSubkeysAdapter.setEditMode(null);
mSubkeysAddedLayout.setVisibility(View.GONE);
mSubkeyAddFabLayout.setDisplayedChild(0);
@@ -323,10 +323,10 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
break;
case EditSubkeyDialogFragment.MESSAGE_REVOKE:
// toggle
if (mEditModeSaveKeyringParcel.mRevokeSubKeys.contains(keyId)) {
mEditModeSaveKeyringParcel.mRevokeSubKeys.remove(keyId);
if (mEditModeSkpBuilder.getMutableRevokeSubKeys().contains(keyId)) {
mEditModeSkpBuilder.removeRevokeSubkey(keyId);
} else {
mEditModeSaveKeyringParcel.mRevokeSubKeys.add(keyId);
mEditModeSkpBuilder.addRevokeSubkey(keyId);
}
break;
case EditSubkeyDialogFragment.MESSAGE_STRIP: {
@@ -336,16 +336,11 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
break;
}
SubkeyChange change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null) {
mEditModeSaveKeyringParcel.mChangeSubKeys.add(new SubkeyChange(keyId, true, false));
break;
}
// toggle
change.mDummyStrip = !change.mDummyStrip;
if (change.mDummyStrip && change.mMoveKeyToSecurityToken) {
// User had chosen to divert key, but now wants to strip it instead.
change.mMoveKeyToSecurityToken = false;
SubkeyChange change = mEditModeSkpBuilder.getSubkeyChange(keyId);
if (change == null || !change.getDummyStrip()) {
mEditModeSkpBuilder.addOrReplaceSubkeyChange(SubkeyChange.createStripChange(keyId));
} else {
mEditModeSkpBuilder.removeSubkeyChange(change);
}
break;
}
@@ -385,19 +380,12 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
break;
}
SubkeyChange change;
change = mEditModeSaveKeyringParcel.getSubkeyChange(keyId);
if (change == null) {
mEditModeSaveKeyringParcel.mChangeSubKeys.add(
new SubkeyChange(keyId, false, true)
);
break;
}
// toggle
change.mMoveKeyToSecurityToken = !change.mMoveKeyToSecurityToken;
if (change.mMoveKeyToSecurityToken && change.mDummyStrip) {
// User had chosen to strip key, but now wants to divert it.
change.mDummyStrip = false;
SubkeyChange change = mEditModeSkpBuilder.getSubkeyChange(keyId);
if (change == null || !change.getMoveKeyToSecurityToken()) {
mEditModeSkpBuilder.addOrReplaceSubkeyChange(
SubkeyChange.createMoveToSecurityTokenChange(keyId));
} else {
mEditModeSkpBuilder.removeSubkeyChange(change);
}
break;
}
@@ -429,9 +417,10 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
public void handleMessage(Message message) {
switch (message.what) {
case EditSubkeyExpiryDialogFragment.MESSAGE_NEW_EXPIRY:
mEditModeSaveKeyringParcel.getOrCreateSubkeyChange(keyId).mExpiry =
(Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
Long expiry = (Long) message.getData().getSerializable(
EditSubkeyExpiryDialogFragment.MESSAGE_DATA_EXPIRY);
mEditModeSkpBuilder.addOrReplaceSubkeyChange(
SubkeyChange.createFlagsOrExpiryChange(keyId, null, expiry));
break;
}
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
@@ -458,7 +447,7 @@ public class ViewKeyAdvSubkeysFragment extends LoaderFragment implements
@Override
public SaveKeyringParcel createOperationInput() {
return mEditModeSaveKeyringParcel;
return mEditModeSkpBuilder.build();
}
@Override

View File

@@ -79,7 +79,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
private long mMasterKeyId;
private byte[] mFingerprint;
private boolean mHasSecret;
private SaveKeyringParcel mEditModeSaveKeyringParcel;
private SaveKeyringParcel.Builder mSkpBuilder;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
@@ -122,7 +122,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
}
private void showOrEditUserIdInfo(final int position) {
if (mEditModeSaveKeyringParcel != null) {
if (mSkpBuilder != null) {
editUserId(position);
} else {
showUserIdInfo(position);
@@ -140,23 +140,23 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
switch (message.what) {
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
// toggle
if (mEditModeSaveKeyringParcel.mChangePrimaryUserId != null
&& mEditModeSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
mEditModeSaveKeyringParcel.mChangePrimaryUserId = null;
if (mSkpBuilder.getChangePrimaryUserId() != null
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mSkpBuilder.setChangePrimaryUserId(null);
} else {
mEditModeSaveKeyringParcel.mChangePrimaryUserId = userId;
mSkpBuilder.setChangePrimaryUserId(userId);
}
break;
case EditUserIdDialogFragment.MESSAGE_REVOKE:
// toggle
if (mEditModeSaveKeyringParcel.mRevokeUserIds.contains(userId)) {
mEditModeSaveKeyringParcel.mRevokeUserIds.remove(userId);
if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
mSkpBuilder.removeRevokeUserId(userId);
} else {
mEditModeSaveKeyringParcel.mRevokeUserIds.add(userId);
mSkpBuilder.addRevokeUserId(userId);
// not possible to revoke and change to primary user id
if (mEditModeSaveKeyringParcel.mChangePrimaryUserId != null
&& mEditModeSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
mEditModeSaveKeyringParcel.mChangePrimaryUserId = null;
if (mSkpBuilder.getChangePrimaryUserId() != null
&& mSkpBuilder.getChangePrimaryUserId().equals(userId)) {
mSkpBuilder.setChangePrimaryUserId(null);
}
}
break;
@@ -342,15 +342,15 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mEditModeSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint);
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
mUserIdsAddedAdapter =
new UserIdsAddedAdapter(getActivity(), mEditModeSaveKeyringParcel.mAddUserIds, false);
new UserIdsAddedAdapter(getActivity(), mSkpBuilder.getMutableAddUserIds(), false);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
mUserIdsAddedLayout.setVisibility(View.VISIBLE);
mUserIdAddFabLayout.setDisplayedChild(1);
mUserIdsAdapter.setEditMode(mEditModeSaveKeyringParcel);
mUserIdsAdapter.setEditMode(mSkpBuilder);
getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this);
mode.setTitle(R.string.title_edit_identities);
@@ -372,7 +372,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
@Override
public void onDestroyActionMode(ActionMode mode) {
mEditModeSaveKeyringParcel = null;
mSkpBuilder = null;
mUserIdsAdapter.setEditMode(null);
mUserIdsAddedLayout.setVisibility(View.GONE);
mUserIdAddFabLayout.setDisplayedChild(0);
@@ -387,7 +387,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
@Override
public SaveKeyringParcel createOperationInput() {
return mEditModeSaveKeyringParcel;
return mSkpBuilder.build();
}
@Override

View File

@@ -213,7 +213,7 @@ public class ViewKeySecurityTokenFragment
@Override
public PromoteKeyringParcel createOperationInput() {
return new PromoteKeyringParcel(mMasterKeyId, mCardAid, mSubKeyIds);
return PromoteKeyringParcel.createPromoteKeyringParcel(mMasterKeyId, mCardAid, mSubKeyIds);
}
@Override

View File

@@ -237,7 +237,11 @@ public class ImportKeysAdapter extends RecyclerView.Adapter<ImportKeysAdapter.Vi
keyserver = entry.getKeyserver();
}
return new ImportKeyringParcel(keysList, keyserver, skipSave);
if (skipSave) {
return ImportKeyringParcel.createWithSkipSave(keysList, keyserver);
} else {
return ImportKeyringParcel.createImportKeyringParcel(keysList, keyserver);
}
}
@Override

View File

@@ -17,6 +17,9 @@
package org.sufficientlysecure.keychain.ui.adapter;
import java.util.ArrayList;
import android.content.Context;
import android.database.Cursor;
import android.os.Parcel;
@@ -35,8 +38,6 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
import java.util.ArrayList;
public class MultiUserIdsAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private final ArrayList<Boolean> mCheckStates;
@@ -178,11 +179,12 @@ public class MultiUserIdsAdapter extends CursorAdapter {
p.recycle();
CertifyAction action = actions.get(keyId);
if (actions.get(keyId) == null) {
actions.put(keyId, new CertifyAction(keyId, uids, null));
if (action == null) {
action = CertifyAction.createForUserIds(keyId, uids);
} else {
action.mUserIds.addAll(uids);
action = action.withAddedUserIds(uids);
}
actions.put(keyId, action);
}
}

View File

@@ -17,6 +17,11 @@
package org.sufficientlysecure.keychain.ui.adapter;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import android.content.Context;
import android.content.res.ColorStateList;
import android.database.Cursor;
@@ -42,13 +47,9 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class SubkeysAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private SaveKeyringParcel mSaveKeyringParcel;
private SaveKeyringParcel.Builder mSkpBuilder;
private boolean mHasAnySecret;
private ColorStateList mDefaultTextColor;
@@ -177,12 +178,9 @@ public class SubkeysAdapter extends CursorAdapter {
cursor.getString(INDEX_KEY_CURVE_OID)
));
SubkeyChange change = mSaveKeyringParcel != null
? mSaveKeyringParcel.getSubkeyChange(keyId)
: null;
if (change != null && (change.mDummyStrip || change.mMoveKeyToSecurityToken)) {
if (change.mDummyStrip) {
SubkeyChange change = mSkpBuilder != null ? mSkpBuilder.getSubkeyChange(keyId) : null;
if (change != null && (change.getDummyStrip() || change.getMoveKeyToSecurityToken())) {
if (change.getDummyStrip()) {
algorithmStr.append(", ");
final SpannableString boldStripped = new SpannableString(
context.getString(R.string.key_stripped)
@@ -190,7 +188,7 @@ public class SubkeysAdapter extends CursorAdapter {
boldStripped.setSpan(new StyleSpan(Typeface.BOLD), 0, boldStripped.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
algorithmStr.append(boldStripped);
}
if (change.mMoveKeyToSecurityToken) {
if (change.getMoveKeyToSecurityToken()) {
algorithmStr.append(", ");
final SpannableString boldDivert = new SpannableString(
context.getString(R.string.key_divert)
@@ -242,8 +240,8 @@ public class SubkeysAdapter extends CursorAdapter {
}
// for edit key
if (mSaveKeyringParcel != null) {
boolean revokeThisSubkey = (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId));
if (mSkpBuilder != null) {
boolean revokeThisSubkey = (mSkpBuilder.getMutableRevokeSubKeys().contains(keyId));
if (revokeThisSubkey) {
if (!isRevoked) {
@@ -251,12 +249,12 @@ public class SubkeysAdapter extends CursorAdapter {
}
}
SaveKeyringParcel.SubkeyChange subkeyChange = mSaveKeyringParcel.getSubkeyChange(keyId);
SaveKeyringParcel.SubkeyChange subkeyChange = mSkpBuilder.getSubkeyChange(keyId);
if (subkeyChange != null) {
if (subkeyChange.mExpiry == null || subkeyChange.mExpiry == 0L) {
if (subkeyChange.getExpiry() == null || subkeyChange.getExpiry() == 0L) {
expiryDate = null;
} else {
expiryDate = new Date(subkeyChange.mExpiry * 1000);
expiryDate = new Date(subkeyChange.getExpiry() * 1000);
}
}
@@ -345,7 +343,7 @@ public class SubkeysAdapter extends CursorAdapter {
// Disable selection of items, http://stackoverflow.com/a/4075045
@Override
public boolean areAllItemsEnabled() {
if (mSaveKeyringParcel == null) {
if (mSkpBuilder == null) {
return false;
} else {
return super.areAllItemsEnabled();
@@ -355,7 +353,7 @@ public class SubkeysAdapter extends CursorAdapter {
// Disable selection of items, http://stackoverflow.com/a/4075045
@Override
public boolean isEnabled(int position) {
if (mSaveKeyringParcel == null) {
if (mSkpBuilder == null) {
return false;
} else {
return super.isEnabled(position);
@@ -370,10 +368,10 @@ public class SubkeysAdapter extends CursorAdapter {
*
* @see SaveKeyringParcel
*
* @param saveKeyringParcel The parcel to get info from, or null to leave edit mode.
* @param builder The parcel to get info from, or null to leave edit mode.
*/
public void setEditMode(@Nullable SaveKeyringParcel saveKeyringParcel) {
mSaveKeyringParcel = saveKeyringParcel;
public void setEditMode(@Nullable SaveKeyringParcel.Builder builder) {
mSkpBuilder = builder;
}
}

View File

@@ -100,9 +100,9 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
String algorithmStr = KeyFormattingUtils.getAlgorithmInfo(
mActivity,
holder.mModel.mAlgorithm,
holder.mModel.mKeySize,
holder.mModel.mCurve
holder.mModel.getAlgorithm(),
holder.mModel.getKeySize(),
holder.mModel.getCurve()
);
boolean isMasterKey = mNewKeyring && position == 0;
@@ -148,8 +148,8 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
holder.vKeyId.setText(R.string.edit_key_new_subkey);
holder.vKeyDetails.setText(algorithmStr);
if (holder.mModel.mExpiry != 0L) {
Date expiryDate = new Date(holder.mModel.mExpiry * 1000);
if (holder.mModel.getExpiry() != 0L) {
Date expiryDate = new Date(holder.mModel.getExpiry() * 1000);
Calendar expiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
expiryCal.setTime(expiryDate);
// convert from UTC to time zone of device
@@ -162,7 +162,7 @@ public class SubkeysAddedAdapter extends ArrayAdapter<SaveKeyringParcel.SubkeyAd
+ getContext().getString(R.string.none));
}
int flags = holder.mModel.mFlags;
int flags = holder.mModel.getFlags();
if ((flags & KeyFlags.CERTIFY_OTHER) > 0) {
holder.vCertifyIcon.setVisibility(View.VISIBLE);
} else {

View File

@@ -32,9 +32,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ViewAnimator;
import org.openintents.openpgp.util.OpenPgpUtils;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
@@ -43,20 +41,18 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
public class UserIdsAdapter extends UserAttributesAdapter {
protected LayoutInflater mInflater;
private SaveKeyringParcel mSaveKeyringParcel;
private SaveKeyringParcel.Builder mSkpBuilder;
private boolean mShowStatusImages;
public UserIdsAdapter(Context context, Cursor c, int flags,
boolean showStatusImages, SaveKeyringParcel saveKeyringParcel) {
public UserIdsAdapter(Context context, Cursor c, int flags, boolean showStatusImages) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
mSaveKeyringParcel = saveKeyringParcel;
mShowStatusImages = showStatusImages;
}
public UserIdsAdapter(Context context, Cursor c, int flags) {
this(context, c, flags, true, null);
this(context, c, flags, true);
}
@Override
@@ -96,11 +92,11 @@ public class UserIdsAdapter extends UserAttributesAdapter {
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
// for edit key
if (mSaveKeyringParcel != null) {
boolean changeAnyPrimaryUserId = (mSaveKeyringParcel.mChangePrimaryUserId != null);
boolean changeThisPrimaryUserId = (mSaveKeyringParcel.mChangePrimaryUserId != null
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId));
boolean revokeThisUserId = (mSaveKeyringParcel.mRevokeUserIds.contains(userId));
if (mSkpBuilder != null) {
String changePrimaryUserId = mSkpBuilder.getChangePrimaryUserId();
boolean changeAnyPrimaryUserId = (changePrimaryUserId != null);
boolean changeThisPrimaryUserId = (changeAnyPrimaryUserId && changePrimaryUserId.equals(userId));
boolean revokeThisUserId = (mSkpBuilder.getMutableRevokeUserIds().contains(userId));
// only if primary user id will be changed
// (this is not triggered if the user id is currently the primary one)
@@ -161,8 +157,8 @@ public class UserIdsAdapter extends UserAttributesAdapter {
String userId = mCursor.getString(INDEX_USER_ID);
boolean isRevokedPending = false;
if (mSaveKeyringParcel != null) {
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) {
if (mSkpBuilder != null) {
if (mSkpBuilder.getMutableRevokeUserIds().contains(userId)) {
isRevokedPending = true;
}
@@ -181,8 +177,8 @@ public class UserIdsAdapter extends UserAttributesAdapter {
*
* @param saveKeyringParcel The parcel to get info from, or null to leave edit mode.
*/
public void setEditMode(@Nullable SaveKeyringParcel saveKeyringParcel) {
mSaveKeyringParcel = saveKeyringParcel;
public void setEditMode(@Nullable SaveKeyringParcel.Builder saveKeyringParcel) {
mSkpBuilder = saveKeyringParcel;
}
@Override

View File

@@ -323,7 +323,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
}
public void cryptoOperation() {
cryptoOperation(new CryptoInputParcel(new Date()));
cryptoOperation(CryptoInputParcel.createCryptoInputParcel(new Date()));
}
public void onHandleResult(OperationResult result) {

View File

@@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import org.sufficientlysecure.keychain.util.Choice;
import java.util.ArrayList;
@@ -304,7 +305,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
expiry = selectedCal.getTime().getTime() / 1000;
}
SaveKeyringParcel.SubkeyAdd newSubkey = new SaveKeyringParcel.SubkeyAdd(
SaveKeyringParcel.SubkeyAdd newSubkey = SubkeyAdd.createSubkeyAdd(
algorithm, keySize, curve, flags, expiry
);
mAlgorithmSelectedListener.onAlgorithmSelected(newSubkey);

View File

@@ -542,14 +542,14 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
@Nullable
@Override
public Parcelable createOperationInput() {
CertifyAction action = new CertifyAction(mMasterKeyId, null,
CertifyAction action = CertifyAction.createForUserAttributes(mMasterKeyId,
Collections.singletonList(mLinkedId.toUserAttribute()));
// fill values for this action
CertifyActionsParcel parcel = new CertifyActionsParcel(mCertifyKeyId);
parcel.mCertifyActions.addAll(Collections.singletonList(action));
CertifyActionsParcel.Builder builder = CertifyActionsParcel.builder(mCertifyKeyId);
builder.addActions(Collections.singletonList(action));
return parcel;
return builder.build();
}
@Override

View File

@@ -474,9 +474,8 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
Bundle data = message.getData();
// use new passphrase!
mChangeUnlockParcel = new ChangeUnlockParcel(
mMasterKeyId,
mFingerprint,
mChangeUnlockParcel = ChangeUnlockParcel.createChangeUnlockParcel(
mMasterKeyId, mFingerprint,
(Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE)
);
@@ -1176,7 +1175,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
@Override
public ImportKeyringParcel createOperationInput() {
return new ImportKeyringParcel(mKeyList, mKeyserver);
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
}
@Override

View File

@@ -143,7 +143,7 @@ public class ViewKeyFragment extends LoaderFragment implements LoaderManager.Loa
mIsSecret = getArguments().getBoolean(ARG_IS_SECRET);
// load user ids after we know if it's a secret key
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null);
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret);
mUserIds.setAdapter(mUserIdsAdapter);
// initialize loaders, which will take care of auto-refresh on change

View File

@@ -210,15 +210,11 @@ public abstract class LinkedIdCreateFinalFragment extends CryptoOperationFragmen
@Nullable
@Override
public Parcelable createOperationInput() {
SaveKeyringParcel skp =
new SaveKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint);
WrappedUserAttribute ua =
LinkedAttribute.fromResource(mVerifiedResource).toUserAttribute();
skp.mAddUserAttribute.add(ua);
return skp;
SaveKeyringParcel.Builder builder=
SaveKeyringParcel.buildChangeKeyringParcel(mLinkedIdWizard.mMasterKeyId, mLinkedIdWizard.mFingerprint);
WrappedUserAttribute ua = LinkedAttribute.fromResource(mVerifiedResource).toUserAttribute();
builder.addUserAttribute(ua);
return builder.build();
}
@Override

View File

@@ -96,7 +96,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
byte[] mFingerprint;
long mMasterKeyId;
private SaveKeyringParcel mSaveKeyringParcel;
private SaveKeyringParcel.Builder mSkpBuilder;
private TextView mLinkedIdTitle, mLinkedIdComment;
private boolean mFinishOnStop;
@@ -405,13 +405,10 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
WrappedUserAttribute ua = LinkedAttribute.fromResource(resource).toUserAttribute();
mSaveKeyringParcel = new SaveKeyringParcel(mMasterKeyId, mFingerprint);
mSaveKeyringParcel.mAddUserAttribute.add(ua);
mSkpBuilder = SaveKeyringParcel.buildChangeKeyringParcel(mMasterKeyId, mFingerprint);
mSkpBuilder.addUserAttribute(ua);
cryptoOperation();
}
}, 250);
@@ -421,7 +418,7 @@ public class LinkedIdCreateGithubFragment extends CryptoOperationFragment<SaveKe
@Override
public SaveKeyringParcel createOperationInput() {
// if this is null, the cryptoOperation silently aborts - which is what we want in that case
return mSaveKeyringParcel;
return mSkpBuilder.build();
}
@Override

View File

@@ -0,0 +1,35 @@
package org.sufficientlysecure.keychain.util;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import android.os.Parcel;
import com.ryanharter.auto.value.parcel.TypeAdapter;
public class ByteMapParcelAdapter implements TypeAdapter<Map<ByteBuffer,byte[]>> {
@Override
public Map<ByteBuffer, byte[]> fromParcel(Parcel source) {
int count = source.readInt();
Map<ByteBuffer,byte[]> result = new HashMap<>(count);
for (int i = 0; i < count; i++) {
byte[] key = source.createByteArray();
byte[] value = source.createByteArray();
result.put(ByteBuffer.wrap(key), value);
}
return Collections.unmodifiableMap(result);
}
@Override
public void toParcel(Map<ByteBuffer, byte[]> value, Parcel dest) {
dest.writeInt(value.size());
for (Map.Entry<ByteBuffer, byte[]> entry : value.entrySet()) {
dest.writeByteArray(entry.getKey().array());
dest.writeByteArray(entry.getValue());
}
}
}

View File

@@ -65,7 +65,7 @@ public class EmailKeyHelper {
@Override
public ImportKeyringParcel createOperationInput() {
return new ImportKeyringParcel(mKeyList, mKeyserver);
return ImportKeyringParcel.createImportKeyringParcel(mKeyList, mKeyserver);
}
}

View File

@@ -25,7 +25,7 @@ import android.widget.EditText;
import org.bouncycastle.bcpg.S2K;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.ComparableS2K;
import org.sufficientlysecure.keychain.pgp.ParcelableS2K;
import java.util.Arrays;
import java.util.HashMap;
@@ -49,7 +49,7 @@ import java.util.Map.Entry;
*/
public class Passphrase implements Parcelable {
private char[] mPassphrase;
private HashMap<ComparableS2K, byte[]> mCachedSessionKeys;
private HashMap<ParcelableS2K, byte[]> mCachedSessionKeys;
/**
* According to http://stackoverflow.com/a/15844273 EditText is not using String internally
@@ -104,7 +104,7 @@ public class Passphrase implements Parcelable {
if (mCachedSessionKeys == null) {
return null;
}
return mCachedSessionKeys.get(new ComparableS2K(keyEncryptionAlgorithm, s2k));
return mCachedSessionKeys.get(ParcelableS2K.fromS2K(keyEncryptionAlgorithm, s2k));
}
/** Adds a session key for a set of s2k parameters to this Passphrase object's
@@ -116,7 +116,7 @@ public class Passphrase implements Parcelable {
if (mCachedSessionKeys == null) {
mCachedSessionKeys = new HashMap<>();
}
mCachedSessionKeys.put(new ComparableS2K(keyEncryptionAlgorithm, s2k), sessionKey);
mCachedSessionKeys.put(ParcelableS2K.fromS2K(keyEncryptionAlgorithm, s2k), sessionKey);
}
/**
@@ -184,7 +184,7 @@ public class Passphrase implements Parcelable {
}
mCachedSessionKeys = new HashMap<>(size);
for (int i = 0; i < size; i++) {
ComparableS2K cachedS2K = source.readParcelable(getClass().getClassLoader());
ParcelableS2K cachedS2K = source.readParcelable(getClass().getClassLoader());
byte[] cachedSessionKey = source.createByteArray();
mCachedSessionKeys.put(cachedS2K, cachedSessionKey);
}
@@ -197,7 +197,7 @@ public class Passphrase implements Parcelable {
return;
}
dest.writeInt(mCachedSessionKeys.size());
for (Entry<ComparableS2K,byte[]> entry : mCachedSessionKeys.entrySet()) {
for (Entry<ParcelableS2K,byte[]> entry : mCachedSessionKeys.entrySet()) {
dest.writeParcelable(entry.getKey(), 0);
dest.writeByteArray(entry.getValue());
}