parse otr-fingerprint in qr codes and nfc. include otr fingerprint in shareable uri where ever possible

This commit is contained in:
iNPUTmice 2014-11-16 00:20:20 +01:00
parent 0fb1772f18
commit 88c3537b68
11 changed files with 119 additions and 69 deletions

View file

@ -280,10 +280,11 @@ public class Account extends AbstractEntity {
return values;
}
public OtrEngine getOtrEngine(XmppConnectionService context) {
if (otrEngine == null) {
otrEngine = new OtrEngine(context, this);
}
public void initOtrEngine(XmppConnectionService context) {
this.otrEngine = new OtrEngine(context, this);
}
public OtrEngine getOtrEngine() {
return this.otrEngine;
}
@ -298,23 +299,21 @@ public class Account extends AbstractEntity {
public String getOtrFingerprint() {
if (this.otrFingerprint == null) {
try {
DSAPublicKey pubkey = (DSAPublicKey) this.otrEngine
.getPublicKey();
if (pubkey == null) {
if (this.otrEngine == null) {
return null;
}
StringBuilder builder = new StringBuilder(
new OtrCryptoEngineImpl().getFingerprint(pubkey));
builder.insert(8, " ");
builder.insert(17, " ");
builder.insert(26, " ");
builder.insert(35, " ");
this.otrFingerprint = builder.toString();
DSAPublicKey publicKey = (DSAPublicKey) this.otrEngine.getPublicKey();
if (publicKey == null) {
return null;
}
this.otrFingerprint = new OtrCryptoEngineImpl().getFingerprint(publicKey);
return this.otrFingerprint;
} catch (final OtrCryptoException ignored) {
return null;
}
} else {
return this.otrFingerprint;
}
return this.otrFingerprint;
}
public String getRosterVersion() {
@ -329,11 +328,6 @@ public class Account extends AbstractEntity {
this.rosterVersion = version;
}
public String getOtrFingerprint(XmppConnectionService service) {
this.getOtrEngine(service);
return this.getOtrFingerprint();
}
public void updatePresence(String resource, int status) {
this.presences.updatePresence(resource, status);
}
@ -411,4 +405,13 @@ public class Account extends AbstractEntity {
public boolean inGracePeriod() {
return SystemClock.elapsedRealtime() < this.mEndGracePeriod;
}
public String getShareableUri() {
String fingerprint = this.getOtrFingerprint();
if (fingerprint != null) {
return "xmpp:" + this.getJid().toBareJid().toString() + "?otr-fingerprint="+fingerprint;
} else {
return "xmpp:" + this.getJid().toBareJid().toString();
}
}
}

View file

@ -7,6 +7,7 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@ -206,24 +207,26 @@ public class Contact implements ListItem {
return systemAccount;
}
public Set<String> getOtrFingerprints() {
Set<String> set = new HashSet<>();
public ArrayList<String> getOtrFingerprints() {
ArrayList<String> fingerprints = new ArrayList<String>();
try {
if (this.keys.has("otr_fingerprints")) {
JSONArray fingerprints = this.keys
JSONArray prints = this.keys
.getJSONArray("otr_fingerprints");
for (int i = 0; i < fingerprints.length(); ++i) {
set.add(fingerprints.getString(i));
for (int i = 0; i < prints.length(); ++i) {
fingerprints.add(prints.getString(i));
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (final JSONException ignored) {
}
return set;
return fingerprints;
}
public void addOtrFingerprint(String print) {
public boolean addOtrFingerprint(String print) {
if (getOtrFingerprints().contains(print)) {
return false;
}
try {
JSONArray fingerprints;
if (!this.keys.has("otr_fingerprints")) {
@ -234,8 +237,9 @@ public class Contact implements ListItem {
}
fingerprints.put(print);
this.keys.put("otr_fingerprints", fingerprints);
return true;
} catch (final JSONException ignored) {
return false;
}
}
@ -396,4 +400,13 @@ public class Contact implements ListItem {
public boolean trusted() {
return getOption(Options.FROM) && getOption(Options.TO);
}
public String getShareableUri() {
if (getOtrFingerprints().size() >= 1) {
String otr = getOtrFingerprints().get(0);
return "xmpp:"+getJid().toBareJid().toString()+"?otr-fingerprint="+otr.replace(" ","");
} else {
return "xmpp:"+getJid().toBareJid().toString();
}
}
}

View file

@ -240,16 +240,14 @@ public class Conversation extends AbstractEntity {
this.mode = mode;
}
public SessionImpl startOtrSession(XmppConnectionService service,
String presence, boolean sendStart) {
public SessionImpl startOtrSession(String presence, boolean sendStart) {
if (this.otrSession != null) {
return this.otrSession;
} else {
final SessionID sessionId = new SessionID(this.getContactJid().toBareJid().toString(),
presence,
"xmpp");
this.otrSession = new SessionImpl(sessionId, getAccount()
.getOtrEngine(service));
this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine());
try {
if (sendStart) {
this.otrSession.startSession();

View file

@ -76,8 +76,7 @@ public class MessageParser extends AbstractParser implements
}
if (!conversation.hasValidOtrSession()) {
if (properlyAddressed) {
conversation.startOtrSession(mXmppConnectionService, presence,
false);
conversation.startOtrSession(presence,false);
} else {
return null;
}
@ -87,8 +86,7 @@ public class MessageParser extends AbstractParser implements
if (!foreignPresence.equals(presence)) {
conversation.endOtrIfNeeded();
if (properlyAddressed) {
conversation.startOtrSession(mXmppConnectionService,
presence, false);
conversation.startOtrSession(presence, false);
} else {
return null;
}

View file

@ -491,6 +491,7 @@ public class XmppConnectionService extends Service {
this.accounts = databaseBackend.getAccounts();
for (Account account : this.accounts) {
account.initOtrEngine(this);
this.databaseBackend.readRoster(account.getRoster());
}
this.mergePhoneContactsWithRoster();
@ -608,8 +609,7 @@ public class XmppConnectionService extends Service {
if (message.getCounterpart() != null) {
if (message.getEncryption() == Message.ENCRYPTION_OTR) {
if (!conv.hasValidOtrSession()) {
conv.startOtrSession(this, message.getCounterpart().getResourcepart(),
true);
conv.startOtrSession(message.getCounterpart().getResourcepart(),true);
message.setStatus(Message.STATUS_WAITING);
} else if (conv.hasValidOtrSession()
&& conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) {
@ -628,7 +628,7 @@ public class XmppConnectionService extends Service {
} else {
if (message.getEncryption() == Message.ENCRYPTION_OTR) {
if (!conv.hasValidOtrSession() && (message.getCounterpart() != null)) {
conv.startOtrSession(this, message.getCounterpart().getResourcepart(), true);
conv.startOtrSession(message.getCounterpart().getResourcepart(), true);
message.setStatus(Message.STATUS_WAITING);
} else if (conv.hasValidOtrSession()) {
if (conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) {
@ -672,7 +672,7 @@ public class XmppConnectionService extends Service {
} else if (message.getEncryption() == Message.ENCRYPTION_OTR) {
if (!conv.hasValidOtrSession()
&& message.getCounterpart() != null) {
conv.startOtrSession(this, message.getCounterpart().getResourcepart(), false);
conv.startOtrSession(message.getCounterpart().getResourcepart(), false);
}
}
}
@ -709,13 +709,11 @@ public class XmppConnectionService extends Service {
if (!message.getConversation().hasValidOtrSession()) {
if ((message.getCounterpart() != null)
&& (presences.has(message.getCounterpart().getResourcepart()))) {
message.getConversation().startOtrSession(this,
message.getCounterpart().getResourcepart(), true);
message.getConversation().startOtrSession(message.getCounterpart().getResourcepart(), true);
} else {
if (presences.size() == 1) {
String presence = presences.asStringArray()[0];
message.getConversation().startOtrSession(this,
presence, true);
message.getConversation().startOtrSession(presence, true);
}
}
} else {
@ -1061,6 +1059,7 @@ public class XmppConnectionService extends Service {
}
public void createAccount(Account account) {
account.initOtrEngine(this);
databaseBackend.createAccount(account);
this.accounts.add(account);
this.reconnectAccount(account, false);

View file

@ -154,7 +154,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
@Override
protected String getShareableUri() {
if (contact != null) {
return "xmpp:" + contact.getJid();
return contact.getShareableUri();
} else {
return "";
}
@ -326,10 +326,8 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
keys.removeAllViews();
boolean hasKeys = false;
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (Iterator<String> iterator = contact.getOtrFingerprints()
.iterator(); iterator.hasNext(); ) {
for(final String otrFingerprint : contact.getOtrFingerprints()) {
hasKeys = true;
final String otrFingerprint = iterator.next();
View view = inflater.inflate(R.layout.contact_key, keys, false);
TextView key = (TextView) view.findViewById(R.id.key);
TextView keyType = (TextView) view.findViewById(R.id.key_type);

View file

@ -108,7 +108,7 @@ public class ConversationActivity extends XmppActivity implements
protected String getShareableUri() {
Conversation conversation = getSelectedConversation();
if (conversation != null) {
return "xmpp:" + conversation.getAccount().getJid().toBareJid();
return conversation.getAccount().getShareableUri();
} else {
return "";
}

View file

@ -26,6 +26,7 @@ import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.utils.Validator;
import eu.siacs.conversations.xmpp.XmppConnection.Features;
@ -270,7 +271,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
@Override
protected String getShareableUri() {
if (mAccount!=null) {
return "xmpp:"+mAccount.getJid().toBareJid();
return mAccount.getShareableUri();
} else {
return "";
}
@ -402,11 +403,10 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
} else {
this.mServerInfoPep.setText(R.string.server_info_unavailable);
}
final String fingerprint = this.mAccount
.getOtrFingerprint(xmppConnectionService);
final String fingerprint = this.mAccount.getOtrFingerprint();
if (fingerprint != null) {
this.mOtrFingerprintBox.setVisibility(View.VISIBLE);
this.mOtrFingerprint.setText(fingerprint);
this.mOtrFingerprint.setText(CryptoHelper.prettifyFingerprint(fingerprint));
this.mOtrFingerprintToClipboardButton
.setVisibility(View.VISIBLE);
this.mOtrFingerprintToClipboardButton

View file

@ -62,6 +62,7 @@ import eu.siacs.conversations.entities.ListItem;
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
import eu.siacs.conversations.ui.adapter.ListItemAdapter;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.Validator;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
@ -316,7 +317,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
}
@SuppressLint("InflateParams")
protected void showCreateContactDialog(String prefilledJid) {
protected void showCreateContactDialog(final String prefilledJid, final String fingerprint) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.create_contact);
View dialogView = getLayoutInflater().inflate(
@ -328,6 +329,12 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
android.R.layout.simple_list_item_1, mKnownHosts));
if (prefilledJid != null) {
jid.append(prefilledJid);
if (fingerprint!=null) {
jid.setFocusable(false);
jid.setFocusableInTouchMode(false);
jid.setClickable(false);
jid.setCursorVisible(false);
}
}
populateAccountSpinner(spinner);
builder.setView(dialogView);
@ -367,6 +374,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
if (contact.showInRoster()) {
jid.setError(getString(R.string.contact_already_exists));
} else {
contact.addOtrFingerprint(fingerprint);
xmppConnectionService.createContact(contact);
dialog.dismiss();
switchToConversation(contact);
@ -511,7 +519,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_create_contact:
showCreateContactDialog(null);
showCreateContactDialog(null,null);
return true;
case R.id.action_join_conference:
showJoinConferenceDialog(null);
@ -615,22 +623,29 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
return false;
}
private boolean handleJid(String jid) {
List<Contact> contacts = xmppConnectionService.findContacts(jid);
private boolean handleJid(Invite invite) {
List<Contact> contacts = xmppConnectionService.findContacts(invite.jid);
if (contacts.size() == 0) {
showCreateContactDialog(jid);
showCreateContactDialog(invite.jid,invite.fingerprint);
return false;
} else if (contacts.size() == 1) {
switchToConversation(contacts.get(0));
Contact contact = contacts.get(0);
if (invite.fingerprint != null) {
if (contact.addOtrFingerprint(invite.fingerprint)) {
Log.d(Config.LOGTAG,"added new fingerprint");
xmppConnectionService.syncRosterToDisk(contact.getAccount());
}
}
switchToConversation(contact);
return true;
} else {
if (mMenuSearchView != null) {
mMenuSearchView.expandActionView();
mSearchEditText.setText("");
mSearchEditText.append(jid);
filter(jid);
mSearchEditText.append(invite.jid);
filter(invite.jid);
} else {
mInitialJid = jid;
mInitialJid = invite.jid;
}
return true;
}
@ -743,6 +758,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
private class Invite {
private String jid;
private boolean muc;
private String fingerprint;
Invite(Uri uri) {
parse(uri);
@ -761,7 +777,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
if (muc) {
showJoinConferenceDialog(jid);
} else {
return handleJid(jid);
return handleJid(this);
}
}
return false;
@ -777,6 +793,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
} else {
jid = uri.getSchemeSpecificPart().split("\\?")[0];
}
fingerprint = parseFingerprint(uri.getQuery());
} else if ("imto".equals(scheme)) {
// sample: imto://xmpp/jid@foo.com
try {
@ -785,5 +802,19 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
}
}
}
String parseFingerprint(String query) {
if (query == null) {
return null;
} else {
final String NEEDLE = "otr-fingerprint=";
int index = query.indexOf(NEEDLE);
if (index >= 0 && query.length() >= (NEEDLE.length() + index + 40)) {
return CryptoHelper.prettifyFingerprint(query.substring(index + NEEDLE.length(), index + NEEDLE.length() + 40));
} else {
return null;
}
}
}
}
}

View file

@ -16,6 +16,7 @@ import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
@ -184,7 +185,7 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
this.mVerificationAreaOne.setVisibility(View.VISIBLE);
this.mVerificationAreaTwo.setVisibility(View.VISIBLE);
this.mErrorNoSession.setVisibility(View.GONE);
this.mYourFingerprint.setText(this.mAccount.getOtrFingerprint(xmppConnectionService));
this.mYourFingerprint.setText(CryptoHelper.prettifyFingerprint(this.mAccount.getOtrFingerprint()));
this.mRemoteFingerprint.setText(this.mConversation.getOtrFingerprint());
this.mRemoteJid.setText(this.mConversation.getContact().getJid().toBareJid().toString());
Conversation.Smp smp = mConversation.smp();
@ -279,7 +280,7 @@ public class VerifyOTRActivity extends XmppActivity implements XmppConnectionSer
@Override
protected String getShareableUri() {
if (mAccount!=null) {
return "xmpp:"+mAccount.getJid().toBareJid();
return mAccount.getShareableUri();
} else {
return "";
}

View file

@ -82,4 +82,13 @@ public class CryptoHelper {
public static String saslPrep(final String s) {
return saslEscape(Normalizer.normalize(s, Normalizer.Form.NFKC));
}
public static String prettifyFingerprint(String fingerprint) {
StringBuilder builder = new StringBuilder(fingerprint);
builder.insert(8, " ");
builder.insert(17, " ");
builder.insert(26, " ");
builder.insert(35, " ");
return builder.toString();
}
}