aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src/main
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2014-04-06 04:27:55 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2014-04-06 04:27:55 +0200
commit456a634149d0eecb00f6d7e0053a71f1b19538b6 (patch)
tree7823b457fe11b5d2101d4faf13b774be06649bd7 /OpenPGP-Keychain/src/main
parentf01a96f56ed5cc13b7557a2805e51227312e0c2b (diff)
downloadopen-keychain-456a634149d0eecb00f6d7e0053a71f1b19538b6.tar.gz
open-keychain-456a634149d0eecb00f6d7e0053a71f1b19538b6.tar.bz2
open-keychain-456a634149d0eecb00f6d7e0053a71f1b19538b6.zip
certs: ditch expiry, re-add data blob, improve ViewCertActivity
GnuPG doesn't support expiry of user id certifications. The number of rings with an expiration subpacket in a cert out there is likely negligible. ViewCertActivity now verifies the key and displays a status. For revocation certs, the revocation reason is also shown.
Diffstat (limited to 'OpenPGP-Keychain/src/main')
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java3
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java2
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java15
-rw-r--r--OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java83
-rw-r--r--OpenPGP-Keychain/src/main/res/layout/view_cert_activity.xml37
6 files changed, 101 insertions, 41 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
index 0eff929f3..a029da478 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -62,7 +62,7 @@ public class KeychainContract {
String TYPE = "type";
String VERIFIED = "verified";
String CREATION = "creation";
- String EXPIRY = "expiry";
+ String DATA = "data";
}
interface ApiAppsColumns {
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
index 2bd1c13a0..7fbfe1d60 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java
@@ -114,7 +114,8 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ CertsColumns.TYPE + " INTEGER, "
+ CertsColumns.VERIFIED + " INTEGER, "
+ CertsColumns.CREATION + " INTEGER, "
- + CertsColumns.EXPIRY + " INTEGER, "
+
+ + CertsColumns.DATA + " BLOB, "
+ "PRIMARY KEY(" + CertsColumns.MASTER_KEY_ID + ", " + CertsColumns.RANK + ", "
+ CertsColumns.KEY_ID_CERTIFIER + "), "
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
index f684006b0..72cb53e76 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java
@@ -448,8 +448,8 @@ public class KeychainProvider extends ContentProvider {
projectionMap.put(Certs.VERIFIED, Tables.CERTS + "." + Certs.VERIFIED);
projectionMap.put(Certs.TYPE, Tables.CERTS + "." + Certs.TYPE);
projectionMap.put(Certs.CREATION, Tables.CERTS + "." + Certs.CREATION);
- projectionMap.put(Certs.EXPIRY, Tables.CERTS + "." + Certs.EXPIRY);
projectionMap.put(Certs.KEY_ID_CERTIFIER, Tables.CERTS + "." + Certs.KEY_ID_CERTIFIER);
+ projectionMap.put(Certs.DATA, Tables.CERTS + "." + Certs.DATA);
projectionMap.put(Certs.USER_ID, Tables.USER_IDS + "." + UserIds.USER_ID);
projectionMap.put(Certs.SIGNER_UID, "signer." + UserIds.USER_ID + " AS " + Certs.SIGNER_UID);
qb.setProjectionMap(projectionMap);
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 78d61a521..bcea66498 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -246,10 +246,8 @@ public class ProviderHelper {
try {
// self signature
if(certId == masterKeyId) {
- cert.init(
- new JcaPGPContentVerifierBuilderProvider().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME),
- masterKey);
+ cert.init(new JcaPGPContentVerifierBuilderProvider().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME), masterKey);
if(!cert.verifyCertification(userId, masterKey)) {
// not verified?! dang! TODO notify user? this is kinda serious...
Log.e(Constants.TAG, "Could not verify self signature for " + userId + "!");
@@ -267,8 +265,7 @@ public class ProviderHelper {
// verify signatures from known private keys
if(allKeyRings.containsKey(certId)) {
// mark them as verified
- cert.init(
- new JcaPGPContentVerifierBuilderProvider().setProvider(
+ cert.init(new JcaPGPContentVerifierBuilderProvider().setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME),
allKeyRings.get(certId).getPublicKey());
if(cert.verifyCertification(userId, masterKey)) {
@@ -423,12 +420,8 @@ public class ProviderHelper {
values.put(Certs.KEY_ID_CERTIFIER, cert.getKeyID());
values.put(Certs.TYPE, cert.getSignatureType());
values.put(Certs.CREATION, cert.getCreationTime().getTime() / 1000);
- if(cert.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.EXPIRE_TIME)) {
- long ext = ((SignatureExpirationTime) cert.getHashedSubPackets().getSubpacket(
- SignatureSubpacketTags.EXPIRE_TIME)).getTime();
- values.put(Certs.EXPIRY, cert.getCreationTime().getTime() / 1000 + ext);
- }
values.put(Certs.VERIFIED, verified);
+ values.put(Certs.DATA, cert.getEncoded());
Uri uri = Certs.buildCertsUri(Long.toString(masterKeyId));
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
index 4e525cff8..ac4194afc 100644
--- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
+++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java
@@ -30,18 +30,27 @@ import android.support.v7.app.ActionBarActivity;
import android.text.format.DateFormat;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.View;
import android.widget.TextView;
+import org.spongycastle.bcpg.SignatureSubpacket;
+import org.spongycastle.bcpg.SignatureSubpacketTags;
+import org.spongycastle.bcpg.sig.RevocationReason;
+import org.spongycastle.openpgp.PGPException;
+import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPSignature;
+import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
+import java.security.SignatureException;
import java.util.Date;
/**
@@ -56,24 +65,25 @@ public class ViewCertActivity extends ActionBarActivity
Certs.USER_ID,
Certs.TYPE,
Certs.CREATION,
- Certs.EXPIRY,
Certs.KEY_ID_CERTIFIER,
Certs.SIGNER_UID,
+ Certs.DATA,
};
private static final int INDEX_MASTER_KEY_ID = 0;
private static final int INDEX_USER_ID = 1;
private static final int INDEX_TYPE = 2;
private static final int INDEX_CREATION = 3;
- private static final int INDEX_EXPIRY = 4;
- private static final int INDEX_KEY_ID_CERTIFIER = 5;
- private static final int INDEX_SIGNER_UID = 6;
+ private static final int INDEX_KEY_ID_CERTIFIER = 4;
+ private static final int INDEX_SIGNER_UID = 5;
+ private static final int INDEX_DATA = 6;
private Uri mDataUri;
private long mSignerKeyId;
- private TextView mSigneeKey, mSigneeUid, mRank, mAlgorithm, mType, mCreation, mExpiry;
- private TextView mSignerKey, mSignerUid;
+ private TextView mSigneeKey, mSigneeUid, mAlgorithm, mType, mRReason, mCreation;
+ private TextView mSignerKey, mSignerUid, mStatus;
+ private View mRowReason;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -84,16 +94,19 @@ public class ViewCertActivity extends ActionBarActivity
setContentView(R.layout.view_cert_activity);
+ mStatus = (TextView) findViewById(R.id.status);
mSigneeKey = (TextView) findViewById(R.id.signee_key);
mSigneeUid = (TextView) findViewById(R.id.signee_uid);
mAlgorithm = (TextView) findViewById(R.id.algorithm);
mType = (TextView) findViewById(R.id.signature_type);
+ mRReason = (TextView) findViewById(R.id.reason);
mCreation = (TextView) findViewById(R.id.creation);
- mExpiry = (TextView) findViewById(R.id.expiry);
mSignerKey = (TextView) findViewById(R.id.signer_key_id);
mSignerUid = (TextView) findViewById(R.id.signer_uid);
+ mRowReason = findViewById(R.id.row_reason);
+
mDataUri = getIntent().getData();
if (mDataUri == null) {
Log.e(Constants.TAG, "Intent data missing. Should be Uri of key!");
@@ -134,9 +147,36 @@ public class ViewCertActivity extends ActionBarActivity
else
mSignerUid.setText(R.string.unknown_uid);
- // String algorithmStr = PgpKeyHelper.getAlgorithmInfo(sig.getKeyAlgorithm(), 0);
- // mAlgorithm.setText(algorithmStr);
+ PGPSignature sig = PgpConversionHelper.BytesToPGPSignature(data.getBlob(INDEX_DATA));
+ PGPKeyRing signeeRing = ProviderHelper.getPGPKeyRing(this,
+ KeychainContract.KeyRingData.buildPublicKeyRingUri(Long.toString(data.getLong(INDEX_MASTER_KEY_ID))));
+ PGPKeyRing signerRing = ProviderHelper.getPGPKeyRing(this,
+ KeychainContract.KeyRingData.buildPublicKeyRingUri(Long.toString(sig.getKeyID())));
+ if(signerRing != null) try {
+ sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider(
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME), signeeRing.getPublicKey());
+ if (sig.verifyCertification(signeeUid, signerRing.getPublicKey())) {
+ mStatus.setText("ok");
+ mStatus.setTextColor(getResources().getColor(R.color.bbutton_success));
+ } else {
+ mStatus.setText("failed!");
+ mStatus.setTextColor(getResources().getColor(R.color.alert));
+ }
+ } catch(SignatureException e) {
+ mStatus.setText("error!");
+ mStatus.setTextColor(getResources().getColor(R.color.alert));
+ } catch(PGPException e) {
+ mStatus.setText("error!");
+ mStatus.setTextColor(getResources().getColor(R.color.alert));
+ } else {
+ mStatus.setText("key unavailable");
+ mStatus.setTextColor(getResources().getColor(R.color.black));
+ }
+
+ String algorithmStr = PgpKeyHelper.getAlgorithmInfo(sig.getKeyAlgorithm(), 0);
+ mAlgorithm.setText(algorithmStr);
+ mRowReason.setVisibility(View.GONE);
switch(data.getInt(INDEX_TYPE)) {
case PGPSignature.DEFAULT_CERTIFICATION:
mType.setText(R.string.cert_default); break;
@@ -146,16 +186,21 @@ public class ViewCertActivity extends ActionBarActivity
mType.setText(R.string.cert_casual); break;
case PGPSignature.POSITIVE_CERTIFICATION:
mType.setText(R.string.cert_positive); break;
- case PGPSignature.CERTIFICATION_REVOCATION:
- mType.setText(R.string.cert_revoke); break;
- }
-
- long expiry = data.getLong(INDEX_EXPIRY);
- if(expiry == 0) {
- mExpiry.setText(R.string.never);
- } else {
- Date expiryDate = new Date(creationDate.getTime() + expiry * 1000);
- mExpiry.setText(DateFormat.getDateFormat(getApplicationContext()).format(expiryDate));
+ case PGPSignature.CERTIFICATION_REVOCATION: {
+ mType.setText(R.string.cert_revoke);
+ if(sig.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.REVOCATION_REASON)) {
+ SignatureSubpacket p = sig.getHashedSubPackets().getSubpacket(
+ SignatureSubpacketTags.REVOCATION_REASON);
+ // For some reason, this is missing in SignatureSubpacketInputStream:146
+ if(!(p instanceof RevocationReason)) {
+ p = new RevocationReason(false, p.getData());
+ }
+ String reason = ((RevocationReason) p).getRevocationDescription();
+ mRReason.setText(reason);
+ mRowReason.setVisibility(View.VISIBLE);
+ }
+ break;
+ }
}
}
}
diff --git a/OpenPGP-Keychain/src/main/res/layout/view_cert_activity.xml b/OpenPGP-Keychain/src/main/res/layout/view_cert_activity.xml
index 3c6c09429..95b8ffc8d 100644
--- a/OpenPGP-Keychain/src/main/res/layout/view_cert_activity.xml
+++ b/OpenPGP-Keychain/src/main/res/layout/view_cert_activity.xml
@@ -14,6 +14,26 @@
android:paddingLeft="16dp"
android:paddingRight="16dp">
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:layout_marginTop="14dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Verification Status" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="ok"
+ android:id="@+id/status"
+ android:layout_marginLeft="30dp" />
+ </LinearLayout>
+
<TextView
style="@style/SectionHeader"
android:layout_width="wrap_content"
@@ -96,35 +116,36 @@
android:paddingRight="5dip" />
</TableRow>
- <TableRow>
+ <TableRow
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/row_reason">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingRight="10dip"
- android:text="Creation" />
+ android:text="Revocation Reason" />
<TextView
- android:id="@+id/creation"
+ android:id="@+id/reason"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingRight="5dip" />
</TableRow>
- <TableRow
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
+ <TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingRight="10dip"
- android:text="Expires" />
+ android:text="Creation" />
<TextView
- android:id="@+id/expiry"
+ android:id="@+id/creation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingRight="5dip" />