Merge pull request #1953 from open-keychain/openpgp-signature-result-v4

Openpgp signature result v4
This commit is contained in:
Dominik Schürmann
2016-11-30 16:28:16 +01:00
committed by GitHub
8 changed files with 37 additions and 32 deletions

View File

@@ -19,8 +19,10 @@ package org.sufficientlysecure.keychain.pgp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.OpenPgpSignatureResult.SenderStatusResult;
import org.openintents.openpgp.util.OpenPgpUtils; import org.openintents.openpgp.util.OpenPgpUtils;
import org.openintents.openpgp.util.OpenPgpUtils.UserId; import org.openintents.openpgp.util.OpenPgpUtils.UserId;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
@@ -42,7 +44,7 @@ public class OpenPgpSignatureResultBuilder {
private ArrayList<String> mUserIds = new ArrayList<>(); private ArrayList<String> mUserIds = new ArrayList<>();
private ArrayList<String> mConfirmedUserIds; private ArrayList<String> mConfirmedUserIds;
private long mKeyId; private long mKeyId;
private int mSenderStatus; private SenderStatusResult mSenderStatusResult;
// builder // builder
private boolean mSignatureAvailable = false; private boolean mSignatureAvailable = false;
@@ -53,6 +55,7 @@ public class OpenPgpSignatureResultBuilder {
private boolean mIsKeyExpired = false; private boolean mIsKeyExpired = false;
private boolean mInsecure = false; private boolean mInsecure = false;
private String mSenderAddress; private String mSenderAddress;
private Date mSignatureTimestamp;
public OpenPgpSignatureResultBuilder(ProviderHelper providerHelper) { public OpenPgpSignatureResultBuilder(ProviderHelper providerHelper) {
this.mProviderHelper = providerHelper; this.mProviderHelper = providerHelper;
@@ -66,6 +69,10 @@ public class OpenPgpSignatureResultBuilder {
this.mKeyId = keyId; this.mKeyId = keyId;
} }
public void setSignatureTimestamp(Date signatureTimestamp) {
mSignatureTimestamp = signatureTimestamp;
}
public void setKnownKey(boolean knownKey) { public void setKnownKey(boolean knownKey) {
this.mKnownKey = knownKey; this.mKnownKey = knownKey;
} }
@@ -125,14 +132,14 @@ public class OpenPgpSignatureResultBuilder {
if (mSenderAddress != null) { if (mSenderAddress != null) {
if (userIdListContainsAddress(mSenderAddress, confirmedUserIds)) { if (userIdListContainsAddress(mSenderAddress, confirmedUserIds)) {
setSenderStatus(OpenPgpSignatureResult.SENDER_RESULT_UID_CONFIRMED); mSenderStatusResult = SenderStatusResult.USER_ID_CONFIRMED;
} else if (userIdListContainsAddress(mSenderAddress, allUserIds)) { } else if (userIdListContainsAddress(mSenderAddress, allUserIds)) {
setSenderStatus(OpenPgpSignatureResult.SENDER_RESULT_UID_UNCONFIRMED); mSenderStatusResult = SenderStatusResult.USER_ID_UNCONFIRMED;
} else { } else {
setSenderStatus(OpenPgpSignatureResult.SENDER_RESULT_UID_MISSING); mSenderStatusResult = SenderStatusResult.USER_ID_MISSING;
} }
} else { } else {
setSenderStatus(OpenPgpSignatureResult.SENDER_RESULT_NO_SENDER); mSenderStatusResult = SenderStatusResult.UNKNOWN;
} }
} catch (NotFoundException e) { } catch (NotFoundException e) {
@@ -162,7 +169,7 @@ public class OpenPgpSignatureResultBuilder {
if (!mKnownKey) { if (!mKnownKey) {
Log.d(Constants.TAG, "RESULT_KEY_MISSING"); Log.d(Constants.TAG, "RESULT_KEY_MISSING");
return OpenPgpSignatureResult.createWithKeyMissing(mKeyId); return OpenPgpSignatureResult.createWithKeyMissing(mKeyId, mSignatureTimestamp);
} }
if (!mValidSignature) { if (!mValidSignature) {
@@ -189,14 +196,11 @@ public class OpenPgpSignatureResultBuilder {
} }
return OpenPgpSignatureResult.createWithValidSignature( return OpenPgpSignatureResult.createWithValidSignature(
signatureStatus, mPrimaryUserId, mKeyId, mUserIds, mConfirmedUserIds, mSenderStatus); signatureStatus, mPrimaryUserId, mKeyId, mUserIds, mConfirmedUserIds, mSenderStatusResult, mSignatureTimestamp);
} }
public void setSenderAddress(String senderAddress) { public void setSenderAddress(String senderAddress) {
mSenderAddress = senderAddress; mSenderAddress = senderAddress;
} }
public void setSenderStatus(int senderStatus) {
mSenderStatus = senderStatus;
}
} }

View File

@@ -237,6 +237,7 @@ class PgpSignatureChecker {
signatureResultBuilder.setInsecure(true); signatureResultBuilder.setInsecure(true);
} }
signatureResultBuilder.setSignatureTimestamp(signature.getCreationTime());
signatureResultBuilder.setValidSignature(validSignature); signatureResultBuilder.setValidSignature(validSignature);
} }
@@ -271,6 +272,7 @@ class PgpSignatureChecker {
signatureResultBuilder.setInsecure(true); signatureResultBuilder.setInsecure(true);
} }
signatureResultBuilder.setSignatureTimestamp(messageSignature.getCreationTime());
signatureResultBuilder.setValidSignature(validSignature); signatureResultBuilder.setValidSignature(validSignature);
return true; return true;

View File

@@ -519,11 +519,11 @@ public class OpenPgpService extends Service {
signatureResult.getKeyId())); signatureResult.getKeyId()));
break; break;
} }
case OpenPgpSignatureResult.RESULT_VALID_CONFIRMED: case OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED:
case OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED: case OpenPgpSignatureResult.RESULT_VALID_KEY_UNCONFIRMED:
case OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED: case OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED:
case OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED: case OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED:
case OpenPgpSignatureResult.RESULT_INVALID_INSECURE: { case OpenPgpSignatureResult.RESULT_INVALID_KEY_INSECURE: {
// If signature key is known, return PendingIntent to show key // If signature key is known, return PendingIntent to show key
result.putExtra(OpenPgpApi.RESULT_INTENT, result.putExtra(OpenPgpApi.RESULT_INTENT,
piFactory.createShowKeyPendingIntent(data, signatureResult.getKeyId())); piFactory.createShowKeyPendingIntent(data, signatureResult.getKeyId()));
@@ -546,7 +546,7 @@ public class OpenPgpService extends Service {
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 8) { if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 8) {
// RESULT_INVALID_INSECURE has been added in version 8, fallback to RESULT_INVALID_SIGNATURE // RESULT_INVALID_INSECURE has been added in version 8, fallback to RESULT_INVALID_SIGNATURE
if (signatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_INSECURE) { if (signatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_INSECURE) {
signatureResult = OpenPgpSignatureResult.createWithInvalidSignature(); signatureResult = OpenPgpSignatureResult.createWithInvalidSignature();
} }

View File

@@ -327,7 +327,7 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
// revoked/expired subkeys // revoked/expired subkeys
boolean isRevoked = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED; boolean isRevoked = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_REVOKED;
boolean isExpired = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED; boolean isExpired = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_EXPIRED;
boolean isInsecure = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_INSECURE; boolean isInsecure = mSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_INVALID_KEY_INSECURE;
boolean isVerified = data.getInt(INDEX_VERIFIED) > 0; boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
boolean isYours = data.getInt(INDEX_HAS_ANY_SECRET) != 0; boolean isYours = data.getInt(INDEX_HAS_ANY_SECRET) != 0;

View File

@@ -517,7 +517,7 @@ public class KeyFormattingUtils {
break; break;
} }
case OpenPgpSignatureResult.RESULT_VALID_CONFIRMED: { case OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED: {
sigText = R.string.decrypt_result_signature_certified; sigText = R.string.decrypt_result_signature_certified;
sigIcon = R.drawable.status_signature_verified_cutout_24dp; sigIcon = R.drawable.status_signature_verified_cutout_24dp;
sigColor = R.color.key_flag_green; sigColor = R.color.key_flag_green;
@@ -526,7 +526,7 @@ public class KeyFormattingUtils {
break; break;
} }
case OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED: { case OpenPgpSignatureResult.RESULT_VALID_KEY_UNCONFIRMED: {
sigText = R.string.decrypt_result_signature_uncertified; sigText = R.string.decrypt_result_signature_uncertified;
sigIcon = R.drawable.status_signature_unverified_cutout_24dp; sigIcon = R.drawable.status_signature_unverified_cutout_24dp;
sigColor = R.color.key_flag_orange; sigColor = R.color.key_flag_orange;
@@ -562,7 +562,7 @@ public class KeyFormattingUtils {
break; break;
} }
case OpenPgpSignatureResult.RESULT_INVALID_INSECURE: { case OpenPgpSignatureResult.RESULT_INVALID_KEY_INSECURE: {
sigText = R.string.decrypt_result_insecure_cryptography; sigText = R.string.decrypt_result_insecure_cryptography;
sigIcon = R.drawable.status_signature_invalid_cutout_24dp; sigIcon = R.drawable.status_signature_invalid_cutout_24dp;
sigColor = R.color.key_flag_red; sigColor = R.color.key_flag_red;

View File

@@ -28,6 +28,12 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import org.apache.tools.ant.util.StringUtils; import org.apache.tools.ant.util.StringUtils;
import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.Packet;
import org.bouncycastle.bcpg.PacketTags;
import org.bouncycastle.bcpg.PublicKeyEncSessionPacket;
import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@@ -40,13 +46,6 @@ import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog; import org.robolectric.shadows.ShadowLog;
import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.Packet;
import org.bouncycastle.bcpg.PacketTags;
import org.bouncycastle.bcpg.PublicKeyEncSessionPacket;
import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPKeyFlags;
import org.sufficientlysecure.keychain.WorkaroundBuildConfig; import org.sufficientlysecure.keychain.WorkaroundBuildConfig;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
@@ -336,7 +335,7 @@ public class PgpEncryptDecryptTest {
Assert.assertEquals("decryptionResult should be RESULT_NOT_ENCRYPTED", Assert.assertEquals("decryptionResult should be RESULT_NOT_ENCRYPTED",
OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED, result.getDecryptionResult().getResult()); OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED, result.getDecryptionResult().getResult());
Assert.assertEquals("signatureResult should be RESULT_VALID_CONFIRMED", Assert.assertEquals("signatureResult should be RESULT_VALID_CONFIRMED",
OpenPgpSignatureResult.RESULT_VALID_CONFIRMED, result.getSignatureResult().getResult()); OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED, result.getSignatureResult().getResult());
OpenPgpMetadata metadata = result.getDecryptionMetadata(); OpenPgpMetadata metadata = result.getDecryptionMetadata();
Assert.assertEquals("filesize must be correct", Assert.assertEquals("filesize must be correct",
@@ -398,7 +397,7 @@ public class PgpEncryptDecryptTest {
Assert.assertEquals("decryptionResult should be RESULT_NOT_ENCRYPTED", Assert.assertEquals("decryptionResult should be RESULT_NOT_ENCRYPTED",
OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED, result.getDecryptionResult().getResult()); OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED, result.getDecryptionResult().getResult());
Assert.assertEquals("signatureResult should be RESULT_VALID_CONFIRMED", Assert.assertEquals("signatureResult should be RESULT_VALID_CONFIRMED",
OpenPgpSignatureResult.RESULT_VALID_CONFIRMED, result.getSignatureResult().getResult()); OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED, result.getSignatureResult().getResult());
OpenPgpMetadata metadata = result.getDecryptionMetadata(); OpenPgpMetadata metadata = result.getDecryptionMetadata();
Assert.assertEquals("filesize must be correct", Assert.assertEquals("filesize must be correct",
@@ -454,7 +453,7 @@ public class PgpEncryptDecryptTest {
Assert.assertEquals("decryptionResult should be RESULT_NOT_ENCRYPTED", Assert.assertEquals("decryptionResult should be RESULT_NOT_ENCRYPTED",
OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED, result.getDecryptionResult().getResult()); OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED, result.getDecryptionResult().getResult());
Assert.assertEquals("signatureResult should be RESULT_VALID_CONFIRMED", Assert.assertEquals("signatureResult should be RESULT_VALID_CONFIRMED",
OpenPgpSignatureResult.RESULT_VALID_CONFIRMED, result.getSignatureResult().getResult()); OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED, result.getSignatureResult().getResult());
// TODO should detached verify return any metadata? // TODO should detached verify return any metadata?
// OpenPgpMetadata metadata = result.getDecryptionMetadata(); // OpenPgpMetadata metadata = result.getDecryptionMetadata();
@@ -901,7 +900,7 @@ public class PgpEncryptDecryptTest {
Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext", Assert.assertArrayEquals("decrypted ciphertext with cached passphrase should equal plaintext",
out.toByteArray(), plaintext.getBytes()); out.toByteArray(), plaintext.getBytes());
Assert.assertEquals("signature should be verified and certified", Assert.assertEquals("signature should be verified and certified",
OpenPgpSignatureResult.RESULT_VALID_CONFIRMED, result.getSignatureResult().getResult()); OpenPgpSignatureResult.RESULT_VALID_KEY_CONFIRMED, result.getSignatureResult().getResult());
OpenPgpMetadata metadata = result.getDecryptionMetadata(); OpenPgpMetadata metadata = result.getDecryptionMetadata();
Assert.assertEquals("filesize must be correct", Assert.assertEquals("filesize must be correct",

View File

@@ -158,8 +158,8 @@ public class InteropTest {
// Certain keys are too short, so we check appropriately. // Certain keys are too short, so we check appropriately.
int code = result.getSignatureResult().getResult(); int code = result.getSignatureResult().getResult();
Assert.assertTrue(base + ": should have a signature", Assert.assertTrue(base + ": should have a signature",
(code == OpenPgpSignatureResult.RESULT_INVALID_INSECURE) || (code == OpenPgpSignatureResult.RESULT_INVALID_KEY_INSECURE) ||
(code == OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED)); (code == OpenPgpSignatureResult.RESULT_VALID_KEY_UNCONFIRMED));
} }
OpenPgpMetadata metadata = result.getDecryptionMetadata(); OpenPgpMetadata metadata = result.getDecryptionMetadata();
Assert.assertEquals(base + ": filesize must be correct", Assert.assertEquals(base + ": filesize must be correct",