parse otr-fingerprint in qr codes and nfc. include otr fingerprint in shareable uri where ever possible
This commit is contained in:
parent
0fb1772f18
commit
88c3537b68
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 "";
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 "";
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue