aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org
diff options
context:
space:
mode:
authorAdithya Abraham Philip <adithyaphilip@gmail.com>2015-06-24 06:15:01 +0530
committerAdithya Abraham Philip <adithyaphilip@gmail.com>2015-06-27 01:20:23 +0530
commit2f110344ed37e62320d2ff30ffad6c24315ff179 (patch)
tree14966682201b9b8acefbbf69990850d8a4c434d5 /OpenKeychain/src/main/java/org
parentb33004a2f599d34035c0b49dff75cf00a21adb7e (diff)
downloadopen-keychain-2f110344ed37e62320d2ff30ffad6c24315ff179.tar.gz
open-keychain-2f110344ed37e62320d2ff30ffad6c24315ff179.tar.bz2
open-keychain-2f110344ed37e62320d2ff30ffad6c24315ff179.zip
migrated Keybase verification
Diffstat (limited to 'OpenKeychain/src/main/java/org')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java141
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java59
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeybaseVerificationParcel.java43
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainNewService.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java180
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java225
8 files changed, 394 insertions, 285 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
index 439260b74..cb76c8ba3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
@@ -58,12 +58,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
* @see CertifyActionsParcel
*
*/
-public class CertifyOperation extends BaseOperation {
+public class CertifyOperation extends BaseOperation<CertifyActionsParcel> {
public CertifyOperation(Context context, ProviderHelper providerHelper, Progressable progressable, AtomicBoolean cancelled) {
super(context, providerHelper, progressable, cancelled);
}
+ @Override
public CertifyResult execute(CertifyActionsParcel parcel, CryptoInputParcel cryptoInput) {
OperationLog log = new OperationLog();
@@ -86,8 +87,10 @@ public class CertifyOperation extends BaseOperation {
case PATTERN:
case PASSPHRASE:
if (!cryptoInput.hasPassphrase()) {
- return new CertifyResult(log, RequiredInputParcel.createRequiredSignPassphrase(
- certificationKey.getKeyId(), certificationKey.getKeyId(), null));
+ return new CertifyResult(log,
+ RequiredInputParcel.createRequiredSignPassphrase(
+ certificationKey.getKeyId(), certificationKey.getKeyId(), null)
+ );
}
// certification is always with the master key id, so use that one
passphrase = cryptoInput.getPassphrase();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java
new file mode 100644
index 000000000..683fc9fa9
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java
@@ -0,0 +1,141 @@
+package org.sufficientlysecure.keychain.operations;
+
+import android.content.Context;
+import com.textuality.keybase.lib.Proof;
+import com.textuality.keybase.lib.prover.Prover;
+import de.measite.minidns.Client;
+import de.measite.minidns.DNSMessage;
+import de.measite.minidns.Question;
+import de.measite.minidns.Record;
+import de.measite.minidns.record.Data;
+import de.measite.minidns.record.TXT;
+import org.json.JSONObject;
+import org.spongycastle.openpgp.PGPUtil;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
+import org.sufficientlysecure.keychain.operations.results.KeybaseVerificationResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
+import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
+import org.sufficientlysecure.keychain.pgp.Progressable;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.KeybaseVerificationParcel;
+import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificationParcel> {
+
+ public KeybaseVerificationOperation(Context context, ProviderHelper providerHelper,
+ Progressable progressable) {
+ super(context, providerHelper, progressable);
+ }
+
+ @Override
+ public KeybaseVerificationResult execute(KeybaseVerificationParcel keybaseInput,
+ CryptoInputParcel cryptoInput) {
+
+ String requiredFingerprint = keybaseInput.mRequiredFingerprint;
+
+ OperationResult.OperationLog log = new OperationResult.OperationLog();
+ log.add(OperationResult.LogType.MSG_KEYBASE_VERIFICATION, 0, requiredFingerprint);
+
+ try {
+ String keybaseProof = keybaseInput.mKeybaseProof;
+ Proof proof = new Proof(new JSONObject(keybaseProof));
+ mProgressable.setProgress(R.string.keybase_message_fetching_data, 0, 100);
+
+ Prover prover = Prover.findProverFor(proof);
+
+ if (prover == null) {
+ log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_NO_PROVER, 1,
+ proof.getPrettyName());
+ return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
+ }
+
+ if (!prover.fetchProofData()) {
+ log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_FETCH_PROOF, 1);
+ return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
+ }
+
+ if (!prover.checkFingerprint(requiredFingerprint)) {
+ log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_FINGERPRINT_MISMATCH, 1);
+ return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
+ }
+
+ String domain = prover.dnsTxtCheckRequired();
+ if (domain != null) {
+ DNSMessage dnsQuery = new Client().query(new Question(domain, Record.TYPE.TXT));
+ if (dnsQuery == null) {
+ log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_DNS_FAIL, 1);
+ log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_SPECIFIC, 2,
+ getFlattenedProverLog(prover));
+ return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
+ }
+ Record[] records = dnsQuery.getAnswers();
+ List<List<byte[]>> extents = new ArrayList<List<byte[]>>();
+ for (Record r : records) {
+ Data d = r.getPayload();
+ if (d instanceof TXT) {
+ extents.add(((TXT) d).getExtents());
+ }
+ }
+ if (!prover.checkDnsTxt(extents)) {
+ log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_SPECIFIC, 1,
+ getFlattenedProverLog(prover));
+ return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
+ }
+ }
+
+ byte[] messageBytes = prover.getPgpMessage().getBytes();
+ if (prover.rawMessageCheckRequired()) {
+ InputStream messageByteStream = PGPUtil.getDecoderStream(new
+ ByteArrayInputStream
+ (messageBytes));
+ if (!prover.checkRawMessageBytes(messageByteStream)) {
+ log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_SPECIFIC, 1,
+ getFlattenedProverLog(prover));
+ return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
+ }
+ }
+
+ PgpDecryptVerify op = new PgpDecryptVerify(mContext, mProviderHelper, mProgressable);
+
+ PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(messageBytes)
+ .setSignedLiteralData(true)
+ .setRequiredSignerFingerprint(requiredFingerprint);
+
+ DecryptVerifyResult decryptVerifyResult = op.execute(input, new CryptoInputParcel());
+
+ if (!decryptVerifyResult.success()) {
+ log.add(decryptVerifyResult, 1);
+ return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
+ }
+
+ if (!prover.validate(new String(decryptVerifyResult.getOutputBytes()))) {
+ log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_PAYLOAD_MISMATCH, 1);
+ return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
+ }
+
+ return new KeybaseVerificationResult(OperationResult.RESULT_OK, log, prover);
+ } catch (Exception e) {
+ // just adds the passed parameter, in this case e.getMessage()
+ log.add(OperationResult.LogType.MSG_KEYBASE_ERROR_SPECIFIC, 1, e.getMessage());
+ return new KeybaseVerificationResult(OperationResult.RESULT_ERROR, log);
+ }
+ }
+
+ private String getFlattenedProverLog(Prover prover) {
+ String log = "";
+ for (String line : prover.getLog()) {
+ log += line + "\n";
+ }
+ return log;
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java
new file mode 100644
index 000000000..f4312ae47
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java
@@ -0,0 +1,59 @@
+package org.sufficientlysecure.keychain.operations.results;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import com.textuality.keybase.lib.KeybaseException;
+import com.textuality.keybase.lib.prover.Prover;
+
+public class KeybaseVerificationResult extends OperationResult implements Parcelable {
+ public final String mProofUrl;
+ public final String mPresenceUrl;
+ public final String mPresenceLabel;
+
+ public KeybaseVerificationResult(int result, OperationLog log) {
+ super(result, log);
+ mProofUrl = null;
+ mPresenceLabel = null;
+ mPresenceUrl = null;
+ }
+
+ public KeybaseVerificationResult(int result, OperationLog log, Prover prover)
+ throws KeybaseException {
+ super(result, log);
+ mProofUrl = prover.getProofUrl();
+ mPresenceUrl = prover.getPresenceUrl();
+ mPresenceLabel = prover.getPresenceLabel();
+ }
+
+ protected KeybaseVerificationResult(Parcel in) {
+ super(in);
+ mProofUrl = in.readString();
+ mPresenceUrl = in.readString();
+ mPresenceLabel = in.readString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(mProofUrl);
+ dest.writeString(mPresenceUrl);
+ dest.writeString(mPresenceLabel);
+ }
+
+ public static final Parcelable.Creator<KeybaseVerificationResult> CREATOR = new Parcelable.Creator<KeybaseVerificationResult>() {
+ @Override
+ public KeybaseVerificationResult createFromParcel(Parcel in) {
+ return new KeybaseVerificationResult(in);
+ }
+
+ @Override
+ public KeybaseVerificationResult[] newArray(int size) {
+ return new KeybaseVerificationResult[size];
+ }
+ };
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
index c9e427462..f0561bef2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
@@ -750,7 +750,19 @@ public abstract class OperationResult implements Parcelable {
MSG_DEL_OK (LogLevel.OK, R.plurals.msg_del_ok),
MSG_DEL_FAIL (LogLevel.WARN, R.plurals.msg_del_fail),
- //export log
+ // keybase verification
+ MSG_KEYBASE_VERIFICATION(LogLevel.START, R.string.msg_keybase_verification),
+
+ MSG_KEYBASE_ERROR_NO_PROVER(LogLevel.ERROR, R.string.msg_keybase_error_no_prover),
+ MSG_KEYBASE_ERROR_FETCH_PROOF(LogLevel.ERROR, R.string.msg_keybase_error_fetching_evidence),
+ MSG_KEYBASE_ERROR_FINGERPRINT_MISMATCH(LogLevel.ERROR,
+ R.string.msg_keybase_error_key_mismatch),
+ MSG_KEYBASE_ERROR_DNS_FAIL(LogLevel.ERROR, R.string.msg_keybase_error_dns_fail),
+ MSG_KEYBASE_ERROR_SPECIFIC(LogLevel.ERROR, R.string.msg_keybase_error_specific),
+ MSG_KEYBASE_ERROR_PAYLOAD_MISMATCH(LogLevel.ERROR,
+ R.string.msg_keybase_error_msg_payload_mismatch),
+
+ // export log
MSG_EXPORT_LOG(LogLevel.START,R.string.msg_export_log_start),
MSG_EXPORT_LOG_EXPORT_ERROR_NO_FILE(LogLevel.ERROR,R.string.msg_export_log_error_no_file),
MSG_EXPORT_LOG_EXPORT_ERROR_FOPEN(LogLevel.ERROR,R.string.msg_export_log_error_fopen),
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeybaseVerificationParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeybaseVerificationParcel.java
new file mode 100644
index 000000000..866eb84a9
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeybaseVerificationParcel.java
@@ -0,0 +1,43 @@
+package org.sufficientlysecure.keychain.service;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class KeybaseVerificationParcel implements Parcelable {
+
+ public String mKeybaseProof;
+ public String mRequiredFingerprint;
+
+ public KeybaseVerificationParcel(String keybaseProof, String requiredFingerprint) {
+ mKeybaseProof = keybaseProof;
+ mRequiredFingerprint = requiredFingerprint;
+ }
+
+ protected KeybaseVerificationParcel(Parcel in) {
+ mKeybaseProof = in.readString();
+ mRequiredFingerprint = in.readString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mKeybaseProof);
+ dest.writeString(mRequiredFingerprint);
+ }
+
+ public static final Parcelable.Creator<KeybaseVerificationParcel> CREATOR = new Parcelable.Creator<KeybaseVerificationParcel>() {
+ @Override
+ public KeybaseVerificationParcel createFromParcel(Parcel in) {
+ return new KeybaseVerificationParcel(in);
+ }
+
+ @Override
+ public KeybaseVerificationParcel[] newArray(int size) {
+ return new KeybaseVerificationParcel[size];
+ }
+ };
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainNewService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainNewService.java
index 080f6a38f..9998e46a2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainNewService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainNewService.java
@@ -106,19 +106,23 @@ public class KeychainNewService extends Service implements Progressable {
mActionCanceled);
} else if (inputParcel instanceof DeleteKeyringParcel) {
op = new DeleteOperation(outerThis, new ProviderHelper(outerThis), outerThis);
- } else if (inputParcel instanceof PromoteKeyringParcel){
+ } else if (inputParcel instanceof PromoteKeyringParcel) {
op = new PromoteKeyOperation(outerThis, new ProviderHelper(outerThis),
outerThis, mActionCanceled);
} else if (inputParcel instanceof ImportKeyringParcel
- || inputParcel instanceof ExportKeyringParcel){
+ || inputParcel instanceof ExportKeyringParcel) {
op = new ImportExportOperation(outerThis, new ProviderHelper(outerThis),
outerThis, mActionCanceled);
} else if (inputParcel instanceof ConsolidateInputParcel) {
op = new ConsolidateOperation(outerThis, new ProviderHelper(outerThis),
outerThis);
+ } else if (inputParcel instanceof KeybaseVerificationParcel) {
+ op = new KeybaseVerificationOperation(outerThis, new ProviderHelper(outerThis),
+ outerThis);
} else {
return;
}
+
@SuppressWarnings("unchecked") // this is unchecked, we make sure it's the correct op above!
OperationResult result = op.execute(inputParcel, cryptoInput);
sendMessageToHandler(MessageStatus.OKAY, result);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java
index 127719ab7..e532982ce 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java
@@ -38,14 +38,8 @@ import org.sufficientlysecure.keychain.keyimport.HkpKeyserver;
import org.sufficientlysecure.keychain.keyimport.Keyserver;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.*;
-import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
-import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
-import org.sufficientlysecure.keychain.operations.results.DeleteResult;
-import org.sufficientlysecure.keychain.operations.results.ExportResult;
-import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.operations.results.*;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
-import org.sufficientlysecure.keychain.operations.results.PromoteKeyResult;
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel;
@@ -61,14 +55,6 @@ import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import de.measite.minidns.Client;
-import de.measite.minidns.DNSMessage;
-import de.measite.minidns.Question;
-import de.measite.minidns.Record;
-import de.measite.minidns.record.Data;
-import de.measite.minidns.record.TXT;
/**
* This Service contains all important long lasting operations for OpenKeychain. It receives Intents with
@@ -80,28 +66,8 @@ public class KeychainService extends Service implements Progressable {
public static final String EXTRA_MESSENGER = "messenger";
public static final String EXTRA_DATA = "data";
- /* possible actions */
-
- public static final String ACTION_VERIFY_KEYBASE_PROOF = Constants.INTENT_PREFIX + "VERIFY_KEYBASE_PROOF";
-
- public static final String ACTION_CONSOLIDATE = Constants.INTENT_PREFIX + "CONSOLIDATE";
-
- public static final String ACTION_CANCEL = Constants.INTENT_PREFIX + "CANCEL";
-
- /* keys for data bundle */
-
- // keybase proof
- public static final String KEYBASE_REQUIRED_FINGERPRINT = "keybase_required_fingerprint";
- public static final String KEYBASE_PROOF = "keybase_proof";
-
- // consolidate
- public static final String CONSOLIDATE_RECOVERY = "consolidate_recovery";
-
Messenger mMessenger;
- // this attribute can possibly merged with the one above? not sure...
- private AtomicBoolean mActionCanceled = new AtomicBoolean(false);
-
@Override
public IBinder onBind(Intent intent) {
return null;
@@ -112,150 +78,6 @@ public class KeychainService extends Service implements Progressable {
*/
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
-
- if (ACTION_CANCEL.equals(intent.getAction())) {
- mActionCanceled.set(true);
- return START_NOT_STICKY;
- }
-
- Runnable actionRunnable = new Runnable() {
- @Override
- public void run() {
- // We have not been cancelled! (yet)
- mActionCanceled.set(false);
-
- Bundle extras = intent.getExtras();
- if (extras == null) {
- Log.e(Constants.TAG, "Extras bundle is null!");
- return;
- }
-
- if (!(extras.containsKey(EXTRA_MESSENGER) || extras.containsKey(EXTRA_DATA) || (intent
- .getAction() == null))) {
- Log.e(Constants.TAG,
- "Extra bundle must contain a messenger, a data bundle, and an action!");
- return;
- }
-
- Uri dataUri = intent.getData();
-
- mMessenger = (Messenger) extras.get(EXTRA_MESSENGER);
- Bundle data = extras.getBundle(EXTRA_DATA);
- if (data == null) {
- Log.e(Constants.TAG, "data extra is null!");
- return;
- }
-
- Log.logDebugBundle(data, "EXTRA_DATA");
-
- ProviderHelper providerHelper = new ProviderHelper(KeychainService.this);
-
- String action = intent.getAction();
-
- // executeServiceMethod action from extra bundle
- switch (action) {
- case ACTION_VERIFY_KEYBASE_PROOF: {
-
- try {
- Proof proof = new Proof(new JSONObject(data.getString(KEYBASE_PROOF)));
- setProgress(R.string.keybase_message_fetching_data, 0, 100);
-
- Prover prover = Prover.findProverFor(proof);
-
- if (prover == null) {
- sendProofError(getString(R.string.keybase_no_prover_found) + ": " + proof
- .getPrettyName());
- return;
- }
-
- if (!prover.fetchProofData()) {
- sendProofError(prover.getLog(), getString(R.string.keybase_problem_fetching_evidence));
- return;
- }
- String requiredFingerprint = data.getString(KEYBASE_REQUIRED_FINGERPRINT);
- if (!prover.checkFingerprint(requiredFingerprint)) {
- sendProofError(getString(R.string.keybase_key_mismatch));
- return;
- }
-
- String domain = prover.dnsTxtCheckRequired();
- if (domain != null) {
- DNSMessage dnsQuery = new Client().query(new Question(domain, Record.TYPE.TXT));
- if (dnsQuery == null) {
- sendProofError(prover.getLog(), getString(R.string.keybase_dns_query_failure));
- return;
- }
- Record[] records = dnsQuery.getAnswers();
- List<List<byte[]>> extents = new ArrayList<List<byte[]>>();
- for (Record r : records) {
- Data d = r.getPayload();
- if (d instanceof TXT) {
- extents.add(((TXT) d).getExtents());
- }
- }
- if (!prover.checkDnsTxt(extents)) {
- sendProofError(prover.getLog(), null);
- return;
- }
- }
-
- byte[] messageBytes = prover.getPgpMessage().getBytes();
- if (prover.rawMessageCheckRequired()) {
- InputStream messageByteStream = PGPUtil.getDecoderStream(new ByteArrayInputStream
- (messageBytes));
- if (!prover.checkRawMessageBytes(messageByteStream)) {
- sendProofError(prover.getLog(), null);
- return;
- }
- }
-
- PgpDecryptVerify op = new PgpDecryptVerify(KeychainService.this, providerHelper,
- KeychainService.this);
-
- PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(messageBytes)
- .setSignedLiteralData(true)
- .setRequiredSignerFingerprint(requiredFingerprint);
-
- DecryptVerifyResult decryptVerifyResult = op.execute(input, new CryptoInputParcel());
-
- if (!decryptVerifyResult.success()) {
- OperationLog log = decryptVerifyResult.getLog();
- OperationResult.LogEntryParcel lastEntry = null;
- for (OperationResult.LogEntryParcel entry : log) {
- lastEntry = entry;
- }
- sendProofError(getString(lastEntry.mType.getMsgId()));
- return;
- }
-
- if (!prover.validate(new String(decryptVerifyResult.getOutputBytes()))) {
- sendProofError(getString(R.string.keybase_message_payload_mismatch));
- return;
- }
-
- Bundle resultData = new Bundle();
- resultData.putString(ServiceProgressHandler.DATA_MESSAGE, "OK");
-
- // these help the handler construct a useful human-readable message
- resultData.putString(ServiceProgressHandler.KEYBASE_PROOF_URL, prover.getProofUrl());
- resultData.putString(ServiceProgressHandler.KEYBASE_PRESENCE_URL, prover.getPresenceUrl());
- resultData.putString(ServiceProgressHandler.KEYBASE_PRESENCE_LABEL, prover
- .getPresenceLabel());
- sendMessageToHandler(MessageStatus.OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
-
- break;
- }
- }
- stopSelf();
- }
- };
-
- Thread actionThread = new Thread(actionRunnable);
- actionThread.start();
-
return START_NOT_STICKY;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
index c33485adc..b196f06e2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
@@ -48,9 +48,12 @@ import com.textuality.keybase.lib.User;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.operations.results.KeybaseVerificationResult;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.service.KeybaseVerificationParcel;
import org.sufficientlysecure.keychain.service.KeychainService;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
+import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
@@ -59,7 +62,8 @@ import java.util.Hashtable;
import java.util.List;
public class ViewKeyTrustFragment extends LoaderFragment implements
- LoaderManager.LoaderCallbacks<Cursor> {
+ LoaderManager.LoaderCallbacks<Cursor>,
+ CryptoOperationHelper.Callback<KeybaseVerificationParcel, KeybaseVerificationResult> {
public static final String ARG_DATA_URI = "uri";
@@ -76,6 +80,14 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
// for retrieving the key we’re working on
private Uri mDataUri;
+ private Proof mProof;
+
+ // for CryptoOperationHelper,Callback
+ private String mKeybaseProof;
+ private String mKeybaseFingerprint;
+ private CryptoOperationHelper<KeybaseVerificationParcel, KeybaseVerificationResult>
+ mKeybaseOpHelper;
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
View root = super.onCreateView(inflater, superContainer, savedInstanceState);
@@ -349,112 +361,125 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
}
private void verify(final Proof proof, final String fingerprint) {
- Intent intent = new Intent(getActivity(), KeychainService.class);
- Bundle data = new Bundle();
- intent.setAction(KeychainService.ACTION_VERIFY_KEYBASE_PROOF);
- data.putString(KeychainService.KEYBASE_PROOF, proof.toString());
- data.putString(KeychainService.KEYBASE_REQUIRED_FINGERPRINT, fingerprint);
- intent.putExtra(KeychainService.EXTRA_DATA, data);
+ mProof = proof;
+ mKeybaseProof = proof.toString();
+ mKeybaseFingerprint = fingerprint;
mProofVerifyDetail.setVisibility(View.GONE);
- // Create a new Messenger for the communication back after proof work is done
- ServiceProgressHandler handler = new ServiceProgressHandler(getActivity()) {
- @Override
- public void handleMessage(Message message) {
- // handle messages by standard KeychainIntentServiceHandler first
- super.handleMessage(message);
-
- if (message.arg1 == MessageStatus.OKAY.ordinal()) {
- Bundle returnData = message.getData();
- String msg = returnData.getString(ServiceProgressHandler.DATA_MESSAGE);
- SpannableStringBuilder ssb = new SpannableStringBuilder();
-
- if ((msg != null) && msg.equals("OK")) {
-
- //yay
- String proofUrl = returnData.getString(ServiceProgressHandler.KEYBASE_PROOF_URL);
- String presenceUrl = returnData.getString(ServiceProgressHandler.KEYBASE_PRESENCE_URL);
- String presenceLabel = returnData.getString(ServiceProgressHandler.KEYBASE_PRESENCE_LABEL);
-
- String proofLabel;
- switch (proof.getType()) {
- case Proof.PROOF_TYPE_TWITTER:
- proofLabel = getString(R.string.keybase_twitter_proof);
- break;
- case Proof.PROOF_TYPE_DNS:
- proofLabel = getString(R.string.keybase_dns_proof);
- break;
- case Proof.PROOF_TYPE_WEB_SITE:
- proofLabel = getString(R.string.keybase_web_site_proof);
- break;
- case Proof.PROOF_TYPE_GITHUB:
- proofLabel = getString(R.string.keybase_github_proof);
- break;
- case Proof.PROOF_TYPE_REDDIT:
- proofLabel = getString(R.string.keybase_reddit_proof);
- break;
- default:
- proofLabel = getString(R.string.keybase_a_post);
- break;
- }
+ mKeybaseOpHelper = new CryptoOperationHelper<>(this, this,
+ R.string.progress_verifying_signature);
+ mKeybaseOpHelper.cryptoOperation();
+ }
- ssb.append(getString(R.string.keybase_proof_succeeded));
- StyleSpan bold = new StyleSpan(Typeface.BOLD);
- ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- ssb.append("\n\n");
- int length = ssb.length();
- ssb.append(proofLabel);
- if (proofUrl != null) {
- URLSpan postLink = new URLSpan(proofUrl);
- ssb.setSpan(postLink, length, length + proofLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- if (Proof.PROOF_TYPE_DNS == proof.getType()) {
- ssb.append(" ").append(getString(R.string.keybase_for_the_domain)).append(" ");
- } else {
- ssb.append(" ").append(getString(R.string.keybase_fetched_from)).append(" ");
- }
- length = ssb.length();
- URLSpan presenceLink = new URLSpan(presenceUrl);
- ssb.append(presenceLabel);
- ssb.setSpan(presenceLink, length, length + presenceLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- if (Proof.PROOF_TYPE_REDDIT == proof.getType()) {
- ssb.append(", ").
- append(getString(R.string.keybase_reddit_attribution)).
- append(" “").append(proof.getHandle()).append("”, ");
- }
- ssb.append(" ").append(getString(R.string.keybase_contained_signature));
- } else {
- // verification failed!
- msg = returnData.getString(ServiceProgressHandler.DATA_ERROR);
- ssb.append(getString(R.string.keybase_proof_failure));
- if (msg == null) {
- msg = getString(R.string.keybase_unknown_proof_failure);
- }
- StyleSpan bold = new StyleSpan(Typeface.BOLD);
- ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- ssb.append("\n\n").append(msg);
- }
- mProofVerifyHeader.setVisibility(View.VISIBLE);
- mProofVerifyDetail.setVisibility(View.VISIBLE);
- mProofVerifyDetail.setMovementMethod(LinkMovementMethod.getInstance());
- mProofVerifyDetail.setText(ssb);
- }
- }
- };
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (mKeybaseOpHelper != null) {
+ mKeybaseOpHelper.handleActivityResult(requestCode, resultCode, data);
+ }
+ }
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(handler);
- intent.putExtra(KeychainService.EXTRA_MESSENGER, messenger);
+ // CryptoOperationHelper.Callback methods
+ @Override
+ public KeybaseVerificationParcel createOperationInput() {
+ return new KeybaseVerificationParcel(mKeybaseProof, mKeybaseFingerprint);
+ }
- // show progress dialog
- handler.showProgressDialog(
- getString(R.string.progress_verifying_signature),
- ProgressDialog.STYLE_HORIZONTAL, false
- );
+ @Override
+ public void onCryptoOperationSuccess(KeybaseVerificationResult result) {
+
+ result.createNotify(getActivity()).show();
+
+ String proofUrl = result.mProofUrl;
+ String presenceUrl = result.mPresenceUrl;
+ String presenceLabel = result.mPresenceLabel;
+
+ Proof proof = mProof; // TODO: should ideally be contained in result
+
+ String proofLabel;
+ switch (proof.getType()) {
+ case Proof.PROOF_TYPE_TWITTER:
+ proofLabel = getString(R.string.keybase_twitter_proof);
+ break;
+ case Proof.PROOF_TYPE_DNS:
+ proofLabel = getString(R.string.keybase_dns_proof);
+ break;
+ case Proof.PROOF_TYPE_WEB_SITE:
+ proofLabel = getString(R.string.keybase_web_site_proof);
+ break;
+ case Proof.PROOF_TYPE_GITHUB:
+ proofLabel = getString(R.string.keybase_github_proof);
+ break;
+ case Proof.PROOF_TYPE_REDDIT:
+ proofLabel = getString(R.string.keybase_reddit_proof);
+ break;
+ default:
+ proofLabel = getString(R.string.keybase_a_post);
+ break;
+ }
+
+ SpannableStringBuilder ssb = new SpannableStringBuilder();
+
+ ssb.append(getString(R.string.keybase_proof_succeeded));
+ StyleSpan bold = new StyleSpan(Typeface.BOLD);
+ ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ssb.append("\n\n");
+ int length = ssb.length();
+ ssb.append(proofLabel);
+ if (proofUrl != null) {
+ URLSpan postLink = new URLSpan(proofUrl);
+ ssb.setSpan(postLink, length, length + proofLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ if (Proof.PROOF_TYPE_DNS == proof.getType()) {
+ ssb.append(" ").append(getString(R.string.keybase_for_the_domain)).append(" ");
+ } else {
+ ssb.append(" ").append(getString(R.string.keybase_fetched_from)).append(" ");
+ }
+ length = ssb.length();
+ URLSpan presenceLink = new URLSpan(presenceUrl);
+ ssb.append(presenceLabel);
+ ssb.setSpan(presenceLink, length, length + presenceLabel.length(), Spanned
+ .SPAN_EXCLUSIVE_EXCLUSIVE);
+ if (Proof.PROOF_TYPE_REDDIT == proof.getType()) {
+ ssb.append(", ").
+ append(getString(R.string.keybase_reddit_attribution)).
+ append(" “").append(proof.getHandle()).append("”, ");
+ }
+ ssb.append(" ").append(getString(R.string.keybase_contained_signature));
+
+ displaySpannableResult(ssb);
+ }
+
+ @Override
+ public void onCryptoOperationCancelled() {
+
+ }
+
+ @Override
+ public void onCryptoOperationError(KeybaseVerificationResult result) {
+
+ result.createNotify(getActivity()).show();
+
+ SpannableStringBuilder ssb = new SpannableStringBuilder();
+
+ ssb.append(getString(R.string.keybase_proof_failure));
+ String msg = getString(result.getLog().getLast().mType.mMsgId);
+ if (msg == null) {
+ msg = getString(R.string.keybase_unknown_proof_failure);
+ }
+ StyleSpan bold = new StyleSpan(Typeface.BOLD);
+ ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ssb.append("\n\n").append(msg);
+
+ displaySpannableResult(ssb);
+ }
- // start service with intent
- getActivity().startService(intent);
+ private void displaySpannableResult(SpannableStringBuilder ssb) {
+ mProofVerifyHeader.setVisibility(View.VISIBLE);
+ mProofVerifyDetail.setVisibility(View.VISIBLE);
+ mProofVerifyDetail.setMovementMethod(LinkMovementMethod.getInstance());
+ mProofVerifyDetail.setText(ssb);
}
}