service: support sender address status and list of confirmed user ids to OpenPgpSignatureResult
This commit is contained in:
@@ -17,22 +17,30 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
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 org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class can be used to build OpenPgpSignatureResult objects based on several checks.
|
* 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.
|
* It serves as a constraint which information are returned inside an OpenPgpSignatureResult object.
|
||||||
*/
|
*/
|
||||||
public class OpenPgpSignatureResultBuilder {
|
public class OpenPgpSignatureResultBuilder {
|
||||||
|
// injected
|
||||||
|
private final ProviderHelper mProviderHelper;
|
||||||
|
|
||||||
// OpenPgpSignatureResult
|
// OpenPgpSignatureResult
|
||||||
private String mPrimaryUserId;
|
private String mPrimaryUserId;
|
||||||
private ArrayList<String> mUserIds = new ArrayList<>();
|
private ArrayList<String> mUserIds = new ArrayList<>();
|
||||||
|
private ArrayList<String> mConfirmedUserIds;
|
||||||
private long mKeyId;
|
private long mKeyId;
|
||||||
|
private int mSenderStatus;
|
||||||
|
|
||||||
// builder
|
// builder
|
||||||
private boolean mSignatureAvailable = false;
|
private boolean mSignatureAvailable = false;
|
||||||
@@ -42,6 +50,11 @@ public class OpenPgpSignatureResultBuilder {
|
|||||||
private boolean mIsKeyRevoked = false;
|
private boolean mIsKeyRevoked = false;
|
||||||
private boolean mIsKeyExpired = false;
|
private boolean mIsKeyExpired = false;
|
||||||
private boolean mInsecure = false;
|
private boolean mInsecure = false;
|
||||||
|
private String mSenderAddress;
|
||||||
|
|
||||||
|
public OpenPgpSignatureResultBuilder(ProviderHelper providerHelper) {
|
||||||
|
this.mProviderHelper = providerHelper;
|
||||||
|
}
|
||||||
|
|
||||||
public void setPrimaryUserId(String userId) {
|
public void setPrimaryUserId(String userId) {
|
||||||
this.mPrimaryUserId = userId;
|
this.mPrimaryUserId = userId;
|
||||||
@@ -79,8 +92,9 @@ public class OpenPgpSignatureResultBuilder {
|
|||||||
this.mIsKeyExpired = keyExpired;
|
this.mIsKeyExpired = keyExpired;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserIds(ArrayList<String> userIds) {
|
public void setUserIds(ArrayList<String> userIds, ArrayList<String> confirmedUserIds) {
|
||||||
this.mUserIds = userIds;
|
this.mUserIds = userIds;
|
||||||
|
this.mConfirmedUserIds = confirmedUserIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValidSignature() {
|
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());
|
Log.d(Constants.TAG, "No primary user id in keyring with master key id " + signingRing.getMasterKeyId());
|
||||||
}
|
}
|
||||||
setSignatureKeyCertified(signingRing.getVerified() > 0);
|
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
|
// either master key is expired/revoked or this specific subkey is expired/revoked
|
||||||
setKeyExpired(signingRing.isExpired() || signingKey.isExpired());
|
setKeyExpired(signingRing.isExpired() || signingKey.isExpired());
|
||||||
@@ -139,6 +172,8 @@ public class OpenPgpSignatureResultBuilder {
|
|||||||
result.setKeyId(mKeyId);
|
result.setKeyId(mKeyId);
|
||||||
result.setPrimaryUserId(mPrimaryUserId);
|
result.setPrimaryUserId(mPrimaryUserId);
|
||||||
result.setUserIds(mUserIds);
|
result.setUserIds(mUserIds);
|
||||||
|
result.setConfirmedUserIds(mConfirmedUserIds);
|
||||||
|
result.setSenderResult(mSenderStatus);
|
||||||
|
|
||||||
if (mIsKeyRevoked) {
|
if (mIsKeyRevoked) {
|
||||||
Log.d(Constants.TAG, "RESULT_INVALID_KEY_REVOKED");
|
Log.d(Constants.TAG, "RESULT_INVALID_KEY_REVOKED");
|
||||||
@@ -160,5 +195,11 @@ public class OpenPgpSignatureResultBuilder {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSenderAddress(String senderAddress) {
|
||||||
|
mSenderAddress = senderAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSenderStatus(int senderStatus) {
|
||||||
|
mSenderStatus = senderStatus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
|
|||||||
private boolean mDecryptMetadataOnly;
|
private boolean mDecryptMetadataOnly;
|
||||||
private byte[] mDetachedSignature;
|
private byte[] mDetachedSignature;
|
||||||
private String mRequiredSignerFingerprint;
|
private String mRequiredSignerFingerprint;
|
||||||
|
private String mSenderAddress;
|
||||||
|
|
||||||
public PgpDecryptVerifyInputParcel() {
|
public PgpDecryptVerifyInputParcel() {
|
||||||
}
|
}
|
||||||
@@ -138,6 +139,15 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PgpDecryptVerifyInputParcel setSenderAddress(String senderAddress) {
|
||||||
|
mSenderAddress = senderAddress;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSenderAddress() {
|
||||||
|
return mSenderAddress;
|
||||||
|
}
|
||||||
|
|
||||||
String getRequiredSignerFingerprint() {
|
String getRequiredSignerFingerprint() {
|
||||||
return mRequiredSignerFingerprint;
|
return mRequiredSignerFingerprint;
|
||||||
}
|
}
|
||||||
@@ -156,6 +166,5 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
|
|||||||
return new PgpDecryptVerifyInputParcel[size];
|
return new PgpDecryptVerifyInputParcel[size];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
|
|
||||||
if (aIn.isClearText()) {
|
if (aIn.isClearText()) {
|
||||||
// a cleartext signature, verify it with the other method
|
// a cleartext signature, verify it with the other method
|
||||||
return verifyCleartextSignature(aIn, outputStream, 0);
|
return verifyCleartextSignature(input, aIn, outputStream, 0);
|
||||||
} else {
|
} else {
|
||||||
// else: ascii armored encryption! go on...
|
// else: ascii armored encryption! go on...
|
||||||
return decryptVerify(input, cryptoInput, inputData, inputStream, outputStream, 0);
|
return decryptVerify(input, cryptoInput, inputData, inputStream, outputStream, 0);
|
||||||
@@ -354,7 +354,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
plainFact = fact;
|
plainFact = fact;
|
||||||
}
|
}
|
||||||
|
|
||||||
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper);
|
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper, input.getSenderAddress());
|
||||||
if (signatureChecker.initializeOnePassSignature(dataChunk, log, indent +1)) {
|
if (signatureChecker.initializeOnePassSignature(dataChunk, log, indent +1)) {
|
||||||
dataChunk = plainFact.nextObject();
|
dataChunk = plainFact.nextObject();
|
||||||
}
|
}
|
||||||
@@ -835,7 +835,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
private DecryptVerifyResult verifyCleartextSignature(
|
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();
|
OperationLog log = new OperationLog();
|
||||||
|
|
||||||
@@ -872,7 +872,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
updateProgress(R.string.progress_processing_signature, 60, 100);
|
updateProgress(R.string.progress_processing_signature, 60, 100);
|
||||||
JcaSkipMarkerPGPObjectFactory pgpFact = new JcaSkipMarkerPGPObjectFactory(aIn);
|
JcaSkipMarkerPGPObjectFactory pgpFact = new JcaSkipMarkerPGPObjectFactory(aIn);
|
||||||
|
|
||||||
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper);
|
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper, input.getSenderAddress());
|
||||||
|
|
||||||
Object o = pgpFact.nextObject();
|
Object o = pgpFact.nextObject();
|
||||||
if (!signatureChecker.initializeSignature(o, log, indent+1)) {
|
if (!signatureChecker.initializeSignature(o, log, indent+1)) {
|
||||||
@@ -927,7 +927,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
o = pgpFact.nextObject();
|
o = pgpFact.nextObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper);
|
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper, input.getSenderAddress());
|
||||||
|
|
||||||
if ( ! signatureChecker.initializeSignature(o, log, indent+1)) {
|
if ( ! signatureChecker.initializeSignature(o, log, indent+1)) {
|
||||||
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0);
|
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import org.sufficientlysecure.keychain.util.Log;
|
|||||||
*/
|
*/
|
||||||
class PgpSignatureChecker {
|
class PgpSignatureChecker {
|
||||||
|
|
||||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
private final OpenPgpSignatureResultBuilder signatureResultBuilder;
|
||||||
|
|
||||||
private CanonicalizedPublicKey signingKey;
|
private CanonicalizedPublicKey signingKey;
|
||||||
|
|
||||||
@@ -57,8 +57,11 @@ class PgpSignatureChecker {
|
|||||||
|
|
||||||
ProviderHelper mProviderHelper;
|
ProviderHelper mProviderHelper;
|
||||||
|
|
||||||
PgpSignatureChecker(ProviderHelper providerHelper) {
|
PgpSignatureChecker(ProviderHelper providerHelper, String senderAddress) {
|
||||||
mProviderHelper = providerHelper;
|
mProviderHelper = providerHelper;
|
||||||
|
|
||||||
|
signatureResultBuilder = new OpenPgpSignatureResultBuilder(providerHelper);
|
||||||
|
signatureResultBuilder.setSenderAddress(senderAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean initializeSignature(Object dataChunk, OperationLog log, int indent) throws PGPException {
|
boolean initializeSignature(Object dataChunk, OperationLog log, int indent) throws PGPException {
|
||||||
|
|||||||
@@ -274,6 +274,27 @@ public class ProviderHelper {
|
|||||||
return (CanonicalizedSecretKeyRing) getCanonicalizedKeyRing(queryUri, true);
|
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 {
|
private KeyRing getCanonicalizedKeyRing(Uri queryUri, boolean secret) throws NotFoundException {
|
||||||
Cursor cursor = mContentResolver.query(queryUri,
|
Cursor cursor = mContentResolver.query(queryUri,
|
||||||
new String[]{
|
new String[]{
|
||||||
|
|||||||
@@ -478,6 +478,7 @@ public class OpenPgpService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE);
|
byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE);
|
||||||
|
String senderAddress = data.getStringExtra(OpenPgpApi.EXTRA_SENDER_ADDRESS);
|
||||||
|
|
||||||
PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(this, mProviderHelper, progressable);
|
PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(this, mProviderHelper, progressable);
|
||||||
|
|
||||||
@@ -490,7 +491,8 @@ public class OpenPgpService extends Service {
|
|||||||
.setAllowSymmetricDecryption(false)
|
.setAllowSymmetricDecryption(false)
|
||||||
.setAllowedKeyIds(allowedKeyIds)
|
.setAllowedKeyIds(allowedKeyIds)
|
||||||
.setDecryptMetadataOnly(decryptMetadataOnly)
|
.setDecryptMetadataOnly(decryptMetadataOnly)
|
||||||
.setDetachedSignature(detachedSignature);
|
.setDetachedSignature(detachedSignature)
|
||||||
|
.setSenderAddress(senderAddress);
|
||||||
|
|
||||||
DecryptVerifyResult pgpResult = op.execute(input, cryptoInput, inputData, outputStream);
|
DecryptVerifyResult pgpResult = op.execute(input, cryptoInput, inputData, outputStream);
|
||||||
|
|
||||||
|
|||||||
2
extern/openpgp-api-lib
vendored
2
extern/openpgp-api-lib
vendored
Submodule extern/openpgp-api-lib updated: 32794ee94f...84fdd0c37d
Reference in New Issue
Block a user