service: support sender address status and list of confirmed user ids to OpenPgpSignatureResult

This commit is contained in:
Vincent Breitmoser 2016-06-02 15:32:45 +02:00
parent 24b92172be
commit 88b0903bf5
7 changed files with 91 additions and 15 deletions

View file

@ -17,22 +17,30 @@
package org.sufficientlysecure.keychain.pgp;
import java.util.ArrayList;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
/**
* This class can be used to build OpenPgpSignatureResult objects based on several checks.
* It serves as a constraint which information are returned inside an OpenPgpSignatureResult object.
*/
public class OpenPgpSignatureResultBuilder {
// injected
private final ProviderHelper mProviderHelper;
// OpenPgpSignatureResult
private String mPrimaryUserId;
private ArrayList<String> mUserIds = new ArrayList<>();
private ArrayList<String> mConfirmedUserIds;
private long mKeyId;
private int mSenderStatus;
// builder
private boolean mSignatureAvailable = false;
@ -42,6 +50,11 @@ public class OpenPgpSignatureResultBuilder {
private boolean mIsKeyRevoked = false;
private boolean mIsKeyExpired = false;
private boolean mInsecure = false;
private String mSenderAddress;
public OpenPgpSignatureResultBuilder(ProviderHelper providerHelper) {
this.mProviderHelper = providerHelper;
}
public void setPrimaryUserId(String userId) {
this.mPrimaryUserId = userId;
@ -79,8 +92,9 @@ public class OpenPgpSignatureResultBuilder {
this.mIsKeyExpired = keyExpired;
}
public void setUserIds(ArrayList<String> userIds) {
public void setUserIds(ArrayList<String> userIds, ArrayList<String> confirmedUserIds) {
this.mUserIds = userIds;
this.mConfirmedUserIds = confirmedUserIds;
}
public boolean isValidSignature() {
@ -105,8 +119,27 @@ public class OpenPgpSignatureResultBuilder {
Log.d(Constants.TAG, "No primary user id in keyring with master key id " + signingRing.getMasterKeyId());
}
setSignatureKeyCertified(signingRing.getVerified() > 0);
Log.d(Constants.TAG, "signingRing.getUnorderedUserIds(): " + signingRing.getUnorderedUserIds());
setUserIds(signingRing.getUnorderedUserIds());
try {
ArrayList<String> allUserIds = signingRing.getUnorderedUserIds();
ArrayList<String> confirmedUserIds = mProviderHelper.getConfirmedUserIds(signingRing.getMasterKeyId());
setUserIds(allUserIds, confirmedUserIds);
if (mSenderAddress != null) {
if (confirmedUserIds.contains(mSenderAddress)) {
setSenderStatus(OpenPgpSignatureResult.SENDER_RESULT_CONFIRMED);
} else if (allUserIds.contains(mSenderAddress)) {
setSenderStatus(OpenPgpSignatureResult.SENDER_RESULT_UNCONFIRMED);
} else {
setSenderStatus(OpenPgpSignatureResult.SENDER_RESULT_MISSING);
}
} else {
setSenderStatus(OpenPgpSignatureResult.SENDER_RESULT_NO_SENDER);
}
} catch (NotFoundException e) {
throw new IllegalStateException("Key didn't exist anymore for user id query!", e);
}
// either master key is expired/revoked or this specific subkey is expired/revoked
setKeyExpired(signingRing.isExpired() || signingKey.isExpired());
@ -139,6 +172,8 @@ public class OpenPgpSignatureResultBuilder {
result.setKeyId(mKeyId);
result.setPrimaryUserId(mPrimaryUserId);
result.setUserIds(mUserIds);
result.setConfirmedUserIds(mConfirmedUserIds);
result.setSenderResult(mSenderStatus);
if (mIsKeyRevoked) {
Log.d(Constants.TAG, "RESULT_INVALID_KEY_REVOKED");
@ -160,5 +195,11 @@ public class OpenPgpSignatureResultBuilder {
return result;
}
public void setSenderAddress(String senderAddress) {
mSenderAddress = senderAddress;
}
public void setSenderStatus(int senderStatus) {
mSenderStatus = senderStatus;
}
}

View file

@ -36,6 +36,7 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
private boolean mDecryptMetadataOnly;
private byte[] mDetachedSignature;
private String mRequiredSignerFingerprint;
private String mSenderAddress;
public PgpDecryptVerifyInputParcel() {
}
@ -138,6 +139,15 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
return this;
}
public PgpDecryptVerifyInputParcel setSenderAddress(String senderAddress) {
mSenderAddress = senderAddress;
return this;
}
public String getSenderAddress() {
return mSenderAddress;
}
String getRequiredSignerFingerprint() {
return mRequiredSignerFingerprint;
}
@ -156,6 +166,5 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
return new PgpDecryptVerifyInputParcel[size];
}
};
}

View file

@ -164,7 +164,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
if (aIn.isClearText()) {
// a cleartext signature, verify it with the other method
return verifyCleartextSignature(aIn, outputStream, 0);
return verifyCleartextSignature(input, aIn, outputStream, 0);
} else {
// else: ascii armored encryption! go on...
return decryptVerify(input, cryptoInput, inputData, inputStream, outputStream, 0);
@ -354,7 +354,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
plainFact = fact;
}
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper);
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper, input.getSenderAddress());
if (signatureChecker.initializeOnePassSignature(dataChunk, log, indent +1)) {
dataChunk = plainFact.nextObject();
}
@ -835,7 +835,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
*/
@NonNull
private DecryptVerifyResult verifyCleartextSignature(
ArmoredInputStream aIn, OutputStream outputStream, int indent) throws IOException, PGPException {
PgpDecryptVerifyInputParcel input, ArmoredInputStream aIn, OutputStream outputStream, int indent) throws IOException, PGPException {
OperationLog log = new OperationLog();
@ -872,7 +872,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
updateProgress(R.string.progress_processing_signature, 60, 100);
JcaSkipMarkerPGPObjectFactory pgpFact = new JcaSkipMarkerPGPObjectFactory(aIn);
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper);
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper, input.getSenderAddress());
Object o = pgpFact.nextObject();
if (!signatureChecker.initializeSignature(o, log, indent+1)) {
@ -927,7 +927,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
o = pgpFact.nextObject();
}
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper);
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper, input.getSenderAddress());
if ( ! signatureChecker.initializeSignature(o, log, indent+1)) {
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0);

View file

@ -47,7 +47,7 @@ import org.sufficientlysecure.keychain.util.Log;
*/
class PgpSignatureChecker {
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
private final OpenPgpSignatureResultBuilder signatureResultBuilder;
private CanonicalizedPublicKey signingKey;
@ -57,8 +57,11 @@ class PgpSignatureChecker {
ProviderHelper mProviderHelper;
PgpSignatureChecker(ProviderHelper providerHelper) {
PgpSignatureChecker(ProviderHelper providerHelper, String senderAddress) {
mProviderHelper = providerHelper;
signatureResultBuilder = new OpenPgpSignatureResultBuilder(providerHelper);
signatureResultBuilder.setSenderAddress(senderAddress);
}
boolean initializeSignature(Object dataChunk, OperationLog log, int indent) throws PGPException {

View file

@ -274,6 +274,27 @@ public class ProviderHelper {
return (CanonicalizedSecretKeyRing) getCanonicalizedKeyRing(queryUri, true);
}
public ArrayList<String> getConfirmedUserIds(long masterKeyId) throws NotFoundException {
Cursor cursor = mContentResolver.query(UserPackets.buildUserIdsUri(masterKeyId),
new String[]{ UserPackets.USER_ID }, UserPackets.VERIFIED + " = " + Certs.VERIFIED_SECRET, null, null
);
if (cursor == null) {
throw new NotFoundException("Key id for requested user ids not found");
}
try {
ArrayList<String> userIds = new ArrayList<>(cursor.getCount());
while (cursor.moveToNext()) {
String userId = cursor.getString(0);
userIds.add(userId);
}
return userIds;
} finally {
cursor.close();
}
}
private KeyRing getCanonicalizedKeyRing(Uri queryUri, boolean secret) throws NotFoundException {
Cursor cursor = mContentResolver.query(queryUri,
new String[]{

View file

@ -478,6 +478,7 @@ public class OpenPgpService extends Service {
}
byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE);
String senderAddress = data.getStringExtra(OpenPgpApi.EXTRA_SENDER_ADDRESS);
PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(this, mProviderHelper, progressable);
@ -490,7 +491,8 @@ public class OpenPgpService extends Service {
.setAllowSymmetricDecryption(false)
.setAllowedKeyIds(allowedKeyIds)
.setDecryptMetadataOnly(decryptMetadataOnly)
.setDetachedSignature(detachedSignature);
.setDetachedSignature(detachedSignature)
.setSenderAddress(senderAddress);
DecryptVerifyResult pgpResult = op.execute(input, cryptoInput, inputData, outputStream);

@ -1 +1 @@
Subproject commit 32794ee94fcd3c8065163da1f6da41e7ceb87c05
Subproject commit 84fdd0c37dc2ef6e303a3488cc412c8d2cc4fd28