mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-27 19:22:14 -05:00
All keybase proofs now in place
This commit is contained in:
parent
3c19e6cfc1
commit
36bac67dd5
@ -84,6 +84,12 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import de.measite.minidns.Client;
|
||||||
|
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 APG. It receives Intents with
|
* This Service contains all important long lasting operations for APG. It receives Intents with
|
||||||
* data from the activities or other apps, queues these intents, executes them, and stops itself
|
* data from the activities or other apps, queues these intents, executes them, and stops itself
|
||||||
@ -124,6 +130,7 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
// encrypt, decrypt, import export
|
// encrypt, decrypt, import export
|
||||||
public static final String TARGET = "target";
|
public static final String TARGET = "target";
|
||||||
public static final String SOURCE = "source";
|
public static final String SOURCE = "source";
|
||||||
|
|
||||||
// possible targets:
|
// possible targets:
|
||||||
public static final int IO_BYTES = 1;
|
public static final int IO_BYTES = 1;
|
||||||
public static final int IO_URI = 2;
|
public static final int IO_URI = 2;
|
||||||
@ -321,12 +328,27 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String domain = prover.dnsTxtCheckRequired();
|
||||||
|
if (domain != null) {
|
||||||
|
Record[] records = new Client().query(new Question(domain, Record.TYPE.TXT)).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();
|
byte[] messageBytes = prover.getPgpMessage().getBytes();
|
||||||
if (prover.rawMessageCheckRequired()) {
|
if (prover.rawMessageCheckRequired()) {
|
||||||
InputStream messageByteStream = PGPUtil.getDecoderStream(new ByteArrayInputStream(messageBytes));
|
InputStream messageByteStream = PGPUtil.getDecoderStream(new ByteArrayInputStream(messageBytes));
|
||||||
String problem = prover.checkRawMessageBytes(messageByteStream);
|
if (!prover.checkRawMessageBytes(messageByteStream)) {
|
||||||
if (problem != null) {
|
sendProofError(prover.getLog(), null);
|
||||||
sendProofError(prover.getLog(), problem);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,6 +387,11 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
|
|
||||||
Bundle resultData = new Bundle();
|
Bundle resultData = new Bundle();
|
||||||
resultData.putString(KeychainIntentServiceHandler.DATA_MESSAGE, "OK");
|
resultData.putString(KeychainIntentServiceHandler.DATA_MESSAGE, "OK");
|
||||||
|
|
||||||
|
// these help the handler construct a useful human-readable message
|
||||||
|
resultData.putString(KeychainIntentServiceHandler.KEYBASE_PROOF_URL, prover.getProofUrl());
|
||||||
|
resultData.putString(KeychainIntentServiceHandler.KEYBASE_PRESENCE_URL, prover.getPresenceUrl());
|
||||||
|
resultData.putString(KeychainIntentServiceHandler.KEYBASE_PRESENCE_LABEL, prover.getPresenceLabel());
|
||||||
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
|
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
sendErrorToHandler(e);
|
sendErrorToHandler(e);
|
||||||
@ -678,11 +705,12 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
|
|
||||||
private void sendProofError(List<String> log, String label) {
|
private void sendProofError(List<String> log, String label) {
|
||||||
String msg = null;
|
String msg = null;
|
||||||
|
label = (label == null) ? "" : label + ": ";
|
||||||
for (String m : log) {
|
for (String m : log) {
|
||||||
Log.e(Constants.TAG, label + ": " + m);
|
Log.e(Constants.TAG, label + m);
|
||||||
msg = m;
|
msg = m;
|
||||||
}
|
}
|
||||||
sendProofError(label + ": " + msg);
|
sendProofError(label + msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendProofError(String msg) {
|
private void sendProofError(String msg) {
|
||||||
|
@ -45,6 +45,11 @@ public class KeychainIntentServiceHandler extends Handler {
|
|||||||
public static final String DATA_MESSAGE = "message";
|
public static final String DATA_MESSAGE = "message";
|
||||||
public static final String DATA_MESSAGE_ID = "message_id";
|
public static final String DATA_MESSAGE_ID = "message_id";
|
||||||
|
|
||||||
|
// keybase proof specific
|
||||||
|
public static final String KEYBASE_PROOF_URL = "keybase_proof_url";
|
||||||
|
public static final String KEYBASE_PRESENCE_URL = "keybase_presence_url";
|
||||||
|
public static final String KEYBASE_PRESENCE_LABEL = "keybase_presence_label";
|
||||||
|
|
||||||
Activity mActivity;
|
Activity mActivity;
|
||||||
ProgressDialogFragment mProgressDialogFragment;
|
ProgressDialogFragment mProgressDialogFragment;
|
||||||
|
|
||||||
|
@ -324,9 +324,6 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void appendIfOK(Hashtable<Integer, ArrayList<Proof>> table, Integer proofType, Proof proof) throws KeybaseException {
|
private void appendIfOK(Hashtable<Integer, ArrayList<Proof>> table, Integer proofType, Proof proof) throws KeybaseException {
|
||||||
if (!proofIsOK(proof)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ArrayList<Proof> list = table.get(proofType);
|
ArrayList<Proof> list = table.get(proofType);
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
list = new ArrayList<Proof>();
|
list = new ArrayList<Proof>();
|
||||||
@ -335,23 +332,16 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
|
|||||||
list.add(proof);
|
list.add(proof);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We only accept http & https proofs. Maybe whitelist later?
|
|
||||||
private boolean proofIsOK(Proof proof) throws KeybaseException {
|
|
||||||
Uri uri = Uri.parse(proof.getServiceUrl());
|
|
||||||
String scheme = uri.getScheme();
|
|
||||||
return ("https".equalsIgnoreCase(scheme) || "http".equalsIgnoreCase(scheme));
|
|
||||||
}
|
|
||||||
|
|
||||||
// which proofs do we have working verifiers for?
|
// which proofs do we have working verifiers for?
|
||||||
private boolean haveProofFor(int proofType) {
|
private boolean haveProofFor(int proofType) {
|
||||||
switch (proofType) {
|
switch (proofType) {
|
||||||
case Proof.PROOF_TYPE_TWITTER: return true;
|
case Proof.PROOF_TYPE_TWITTER: return true;
|
||||||
case Proof.PROOF_TYPE_GITHUB: return true;
|
case Proof.PROOF_TYPE_GITHUB: return true;
|
||||||
case Proof.PROOF_TYPE_DNS: return false;
|
case Proof.PROOF_TYPE_DNS: return true;
|
||||||
case Proof.PROOF_TYPE_WEB_SITE: return true;
|
case Proof.PROOF_TYPE_WEB_SITE: return true;
|
||||||
case Proof.PROOF_TYPE_HACKERNEWS: return true;
|
case Proof.PROOF_TYPE_HACKERNEWS: return true;
|
||||||
case Proof.PROOF_TYPE_COINBASE: return false;
|
case Proof.PROOF_TYPE_COINBASE: return true;
|
||||||
case Proof.PROOF_TYPE_REDDIT: return false;
|
case Proof.PROOF_TYPE_REDDIT: return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -381,47 +371,69 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
|
|||||||
SpannableStringBuilder ssb = new SpannableStringBuilder();
|
SpannableStringBuilder ssb = new SpannableStringBuilder();
|
||||||
|
|
||||||
if ((msg != null) && msg.equals("OK")) {
|
if ((msg != null) && msg.equals("OK")) {
|
||||||
//yay
|
|
||||||
String serviceUrl, urlLabel, postUrl;
|
|
||||||
try {
|
|
||||||
serviceUrl = proof.getServiceUrl();
|
|
||||||
if (serviceUrl.startsWith("https://")) {
|
|
||||||
urlLabel = serviceUrl.substring("https://".length());
|
|
||||||
} else if (serviceUrl.startsWith("http://")) {
|
|
||||||
urlLabel = serviceUrl.substring("http://".length());
|
|
||||||
} else {
|
|
||||||
urlLabel = serviceUrl;
|
|
||||||
}
|
|
||||||
postUrl = proof.getHumanUrl();
|
|
||||||
|
|
||||||
} catch (KeybaseException e) {
|
//yay
|
||||||
throw new RuntimeException(e);
|
String proofUrl = returnData.getString(KeychainIntentServiceHandler.KEYBASE_PROOF_URL);
|
||||||
|
String presenceUrl = returnData.getString(KeychainIntentServiceHandler.KEYBASE_PRESENCE_URL);
|
||||||
|
String presenceLabel = returnData.getString(KeychainIntentServiceHandler.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssb.append(getString(R.string.keybase_proof_succeeded));
|
ssb.append(getString(R.string.keybase_proof_succeeded));
|
||||||
StyleSpan bold = new StyleSpan(Typeface.BOLD);
|
StyleSpan bold = new StyleSpan(Typeface.BOLD);
|
||||||
ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
ssb.append("\n\n");
|
ssb.append("\n\n");
|
||||||
int length = ssb.length();
|
int length = ssb.length();
|
||||||
String segment = getString(R.string.keybase_a_post);
|
ssb.append(proofLabel);
|
||||||
ssb.append(segment);
|
if (proofUrl != null) {
|
||||||
URLSpan postLink = new URLSpan(postUrl);
|
URLSpan postLink = new URLSpan(proofUrl);
|
||||||
ssb.setSpan(postLink, length, length + segment.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
ssb.setSpan(postLink, length, length + proofLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
ssb.append(" ").append(getString(R.string.keybase_fetched_from)).append(" ");
|
}
|
||||||
URLSpan serviceLink = new URLSpan(serviceUrl);
|
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();
|
length = ssb.length();
|
||||||
ssb.append(urlLabel);
|
URLSpan presenceLink = new URLSpan(presenceUrl);
|
||||||
ssb.setSpan(serviceLink, length, length + urlLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
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));
|
ssb.append(" ").append(getString(R.string.keybase_contained_signature));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// verification failed!
|
||||||
msg = returnData.getString(KeychainIntentServiceHandler.DATA_ERROR);
|
msg = returnData.getString(KeychainIntentServiceHandler.DATA_ERROR);
|
||||||
ssb.append(getString(R.string.keybase_proof_failure));
|
ssb.append(getString(R.string.keybase_proof_failure));
|
||||||
if (msg == null) {
|
if (msg == null) {
|
||||||
msg = getString(R.string.keybase_unknown_proof_failure);
|
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);
|
|
||||||
}
|
}
|
||||||
|
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);
|
mProofVerifyHeader.setVisibility(View.VISIBLE);
|
||||||
mProofVerifyDetail.setVisibility(View.VISIBLE);
|
mProofVerifyDetail.setVisibility(View.VISIBLE);
|
||||||
|
@ -567,7 +567,14 @@
|
|||||||
<string name="keybase_proof_succeeded">"This proof has been verified!"</string>
|
<string name="keybase_proof_succeeded">"This proof has been verified!"</string>
|
||||||
<string name="keybase_a_post">"A post"</string>
|
<string name="keybase_a_post">"A post"</string>
|
||||||
<string name="keybase_fetched_from">"fetched from"</string>
|
<string name="keybase_fetched_from">"fetched from"</string>
|
||||||
|
<string name="keybase_for_the_domain">"for the domain"</string>
|
||||||
<string name="keybase_contained_signature">"contains a message which could only have been created by the owner of this key."</string>
|
<string name="keybase_contained_signature">"contains a message which could only have been created by the owner of this key."</string>
|
||||||
|
<string name="keybase_twitter_proof">"A tweet"</string>
|
||||||
|
<string name="keybase_dns_proof">"A DNS TXT record"</string>
|
||||||
|
<string name="keybase_web_site_proof">"A text file"</string>
|
||||||
|
<string name="keybase_github_proof">"A gist"</string>
|
||||||
|
<string name="keybase_reddit_proof">"A JSON file"</string>
|
||||||
|
<string name="keybase_reddit_attribution">"attributed by Reddit to"</string>
|
||||||
|
|
||||||
<!-- Edit key -->
|
<!-- Edit key -->
|
||||||
<string name="edit_key_action_change_passphrase">"Change Passphrase"</string>
|
<string name="edit_key_action_change_passphrase">"Change Passphrase"</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user