aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/plugin/otr
diff options
context:
space:
mode:
authorMarin <m.dzhigarov@gmail.com>2013-10-21 15:24:19 +0300
committerMarin <m.dzhigarov@gmail.com>2013-11-07 09:21:32 +0200
commit88bc48e9b121685f11e3a36b13a7ce0d79b0044d (patch)
tree5ac80d3c172833083246cddb4536a57e93f9e87e /src/net/java/sip/communicator/plugin/otr
parenta7e685476c1bd29b9feb50afbc3a791d257041a6 (diff)
downloadjitsi-88bc48e9b121685f11e3a36b13a7ce0d79b0044d.zip
jitsi-88bc48e9b121685f11e3a36b13a7ce0d79b0044d.tar.gz
jitsi-88bc48e9b121685f11e3a36b13a7ce0d79b0044d.tar.bz2
Added support for SMP for the OTR plugin.
Diffstat (limited to 'src/net/java/sip/communicator/plugin/otr')
-rw-r--r--src/net/java/sip/communicator/plugin/otr/CustomTextArea.java26
-rw-r--r--src/net/java/sip/communicator/plugin/otr/FingerprintAuthenticationPanel.java257
-rw-r--r--src/net/java/sip/communicator/plugin/otr/OtrBuddyAuthenticationDialog.java283
-rw-r--r--src/net/java/sip/communicator/plugin/otr/ScOtrEngine.java32
-rw-r--r--src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java654
-rwxr-xr-xsrc/net/java/sip/communicator/plugin/otr/ScOtrKeyManager.java2
-rwxr-xr-xsrc/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerImpl.java20
-rw-r--r--src/net/java/sip/communicator/plugin/otr/SecretQuestionAuthenticationPanel.java117
-rw-r--r--src/net/java/sip/communicator/plugin/otr/SharedSecretAuthenticationPanel.java89
-rw-r--r--src/net/java/sip/communicator/plugin/otr/otr.manifest.mf2
10 files changed, 1278 insertions, 204 deletions
diff --git a/src/net/java/sip/communicator/plugin/otr/CustomTextArea.java b/src/net/java/sip/communicator/plugin/otr/CustomTextArea.java
new file mode 100644
index 0000000..00aa7d1
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/otr/CustomTextArea.java
@@ -0,0 +1,26 @@
+package net.java.sip.communicator.plugin.otr;
+
+import java.awt.*;
+
+import javax.swing.*;
+
+/**
+ * A special {@link JTextArea} for use in the OTR authentication panels.
+ * It is meant to be used for fingerprint representation and general
+ * information display.
+ *
+ * @author George Politis
+ */
+ public class CustomTextArea
+ extends JTextArea
+ {
+ public CustomTextArea()
+ {
+ this.setBackground(new Color(0,0,0,0));
+ this.setOpaque(false);
+ this.setColumns(20);
+ this.setEditable(false);
+ this.setLineWrap(true);
+ this.setWrapStyleWord(true);
+ }
+ } \ No newline at end of file
diff --git a/src/net/java/sip/communicator/plugin/otr/FingerprintAuthenticationPanel.java b/src/net/java/sip/communicator/plugin/otr/FingerprintAuthenticationPanel.java
new file mode 100644
index 0000000..70ef5d8
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/otr/FingerprintAuthenticationPanel.java
@@ -0,0 +1,257 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.plugin.otr;
+
+import java.awt.*;
+
+import javax.swing.*;
+import javax.swing.event.*;
+
+import net.java.sip.communicator.plugin.desktoputil.*;
+import net.java.sip.communicator.service.protocol.*;
+
+/**
+ * @author George Politis
+ * @author Marin Dzhigarov
+ */
+@SuppressWarnings("serial")
+public class FingerprintAuthenticationPanel
+ extends TransparentPanel
+ implements DocumentListener
+{
+
+ /**
+ * The Contact that we are authenticating.
+ */
+ private final Contact contact;
+
+ private SIPCommTextField txtRemoteFingerprintComparison;
+
+ /**
+ * Our fingerprint.
+ */
+ private JTextArea txtLocalFingerprint;
+
+ /**
+ * The purported fingerprint of the remote party.
+ */
+ private JTextArea txtRemoteFingerprint;
+
+ /**
+ * The "I have" / "I have not" combo box.
+ */
+ private JComboBox cbAction;
+
+ private ActionComboBoxItem actionIHave =
+ new ActionComboBoxItem(ActionComboBoxItemIndex.I_HAVE);
+
+ private ActionComboBoxItem actionIHaveNot =
+ new ActionComboBoxItem(ActionComboBoxItemIndex.I_HAVE_NOT);
+
+ private JTextArea txtAction;
+
+ /**
+ * Creates an instance FingerprintAuthenticationPanel
+ *
+ * @param contact The contact that this panel refers to.
+ */
+ FingerprintAuthenticationPanel(Contact contact)
+ {
+ this.contact = contact;
+ initComponents();
+ loadContact();
+
+ }
+
+ /**
+ * Initializes the {@link FingerprintAuthenticationPanel} components.
+ */
+ private void initComponents()
+ {
+ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+ setPreferredSize(new Dimension(350, 300));
+
+ JTextArea generalInformation = new CustomTextArea();
+ generalInformation.setText(OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.AUTHENTICATION_FINGERPRINT"));
+ this.add(generalInformation);
+
+ add(Box.createVerticalStrut(10));
+
+ txtLocalFingerprint = new CustomTextArea();
+ this.add(txtLocalFingerprint);
+
+ add(Box.createVerticalStrut(10));
+
+ txtRemoteFingerprint = new CustomTextArea();
+ this.add(txtRemoteFingerprint);
+
+ add(Box.createVerticalStrut(10));
+
+ // Action Panel (the panel that holds the I have/I have not dropdown)
+ JPanel pnlAction = new JPanel(new GridBagLayout());
+ pnlAction.setBorder(BorderFactory.createEtchedBorder());
+ this.add(pnlAction);
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(5, 5, 5, 5);
+ c.weightx = 0.0;
+
+ setCbAction(new JComboBox());
+ getCbAction().addItem(actionIHave);
+ getCbAction().addItem(actionIHaveNot);
+ getCbAction().setSelectedItem(OtrActivator.scOtrKeyManager
+ .isVerified(contact) ? actionIHave : actionIHaveNot);
+
+ pnlAction.add(getCbAction(), c);
+
+ txtAction = new CustomTextArea();
+ c.weightx = 1.0;
+ pnlAction.add(txtAction, c);
+
+ txtRemoteFingerprintComparison = new SIPCommTextField(
+ OtrActivator.resourceService
+ .getI18NString("plugin.otr.authbuddydialog.FINGERPRINT_CHECK",
+ new String[]{contact.getDisplayName()}));
+ txtRemoteFingerprintComparison.getDocument().addDocumentListener(this);
+
+ c.gridwidth = 2;
+ c.gridy = 1;
+ pnlAction.add(txtRemoteFingerprintComparison, c);
+ c.gridwidth = 1;
+ c.gridy = 0;
+ }
+
+ /**
+ * Sets up the {@link OtrBuddyAuthenticationDialog} components so that they
+ * reflect the {@link OtrBuddyAuthenticationDialog#contact}
+ */
+ private void loadContact()
+ {
+ // Local fingerprint.
+ String account =
+ contact.getProtocolProvider().getAccountID().getDisplayName();
+ String localFingerprint =
+ OtrActivator.scOtrKeyManager.getLocalFingerprint(contact
+ .getProtocolProvider().getAccountID());
+ txtLocalFingerprint.setText(OtrActivator.resourceService.getI18NString(
+ "plugin.otr.authbuddydialog.LOCAL_FINGERPRINT", new String[]
+ { account, localFingerprint }));
+
+ // Remote fingerprint.
+ String user = contact.getDisplayName();
+ String remoteFingerprint =
+ OtrActivator.scOtrKeyManager.getRemoteFingerprint(contact);
+ txtRemoteFingerprint.setText(OtrActivator.resourceService
+ .getI18NString("plugin.otr.authbuddydialog.REMOTE_FINGERPRINT",
+ new String[]
+ { user, remoteFingerprint }));
+
+ // Action
+ txtAction.setText(OtrActivator.resourceService.getI18NString(
+ "plugin.otr.authbuddydialog.VERIFY_ACTION", new String[]
+ { user }));
+ }
+
+ public void removeUpdate(DocumentEvent e)
+ {
+ compareFingerprints();
+ }
+
+ public void insertUpdate(DocumentEvent e)
+ {
+ compareFingerprints();
+ }
+
+ public void changedUpdate(DocumentEvent e)
+ {
+ compareFingerprints();
+ }
+
+ public void compareFingerprints()
+ {
+ if(txtRemoteFingerprintComparison.getText() == null
+ || txtRemoteFingerprintComparison.getText().length() == 0)
+ {
+ txtRemoteFingerprintComparison.setBackground(Color.white);
+ return;
+ }
+ if(txtRemoteFingerprintComparison.getText().toLowerCase().contains(
+ OtrActivator.scOtrKeyManager
+ .getRemoteFingerprint(contact).toLowerCase()))
+ {
+ txtRemoteFingerprintComparison.setBackground(Color.green);
+ getCbAction().setSelectedItem(actionIHave);
+ }
+ else
+ {
+ txtRemoteFingerprintComparison.setBackground(
+ new Color(243, 72, 48));
+ getCbAction().setSelectedItem(actionIHaveNot);
+ }
+ }
+
+ public JComboBox getCbAction()
+ {
+ return cbAction;
+ }
+
+ public void setCbAction(JComboBox cbAction)
+ {
+ this.cbAction = cbAction;
+ }
+
+ /**
+ * A simple enumeration that is meant to be used with
+ * {@link ActionComboBoxItem} to distinguish them (like an ID).
+ *
+ * @author George Politis
+ */
+ enum ActionComboBoxItemIndex
+ {
+ I_HAVE, I_HAVE_NOT
+ }
+
+ /**
+ * A special {@link JComboBox} that is hosted in
+ * {@link OtrBuddyAuthenticationDialog#cbAction}.
+ *
+ * @author George Politis
+ */
+ class ActionComboBoxItem
+ {
+ public ActionComboBoxItemIndex action;
+
+ private String text;
+
+ public ActionComboBoxItem(ActionComboBoxItemIndex actionIndex)
+ {
+ this.action = actionIndex;
+ switch (action)
+ {
+ case I_HAVE:
+ text =
+ OtrActivator.resourceService
+ .getI18NString("plugin.otr.authbuddydialog.I_HAVE");
+ break;
+ case I_HAVE_NOT:
+ text =
+ OtrActivator.resourceService
+ .getI18NString("plugin.otr.authbuddydialog.I_HAVE_NOT");
+ break;
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return text;
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/otr/OtrBuddyAuthenticationDialog.java b/src/net/java/sip/communicator/plugin/otr/OtrBuddyAuthenticationDialog.java
index 5d5e06c..a78fb7a 100644
--- a/src/net/java/sip/communicator/plugin/otr/OtrBuddyAuthenticationDialog.java
+++ b/src/net/java/sip/communicator/plugin/otr/OtrBuddyAuthenticationDialog.java
@@ -10,18 +10,18 @@ import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import javax.swing.event.*;
-import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.plugin.desktoputil.*;
+import net.java.sip.communicator.plugin.otr.FingerprintAuthenticationPanel.ActionComboBoxItem;
+import net.java.sip.communicator.service.protocol.*;
/**
* @author George Politis
+ * @author Marin Dzhigarov
*/
@SuppressWarnings("serial")
public class OtrBuddyAuthenticationDialog
extends SIPCommDialog
- implements DocumentListener
{
private final Contact contact;
@@ -37,121 +37,6 @@ public class OtrBuddyAuthenticationDialog
this.contact = contact;
initComponents();
- loadContact();
- }
-
- private SIPCommTextField txtRemoteFingerprintComparison;
-
- private JTextArea txtLocalFingerprint;
-
- private JTextArea txtRemoteFingerprint;
-
- private JComboBox cbAction;
- ActionComboBoxItem actionIHave =
- new ActionComboBoxItem(ActionComboBoxItemIndex.I_HAVE);
- ActionComboBoxItem actionIHaveNot =
- new ActionComboBoxItem(ActionComboBoxItemIndex.I_HAVE_NOT);
-
- private JTextArea txtAction;
-
- /**
- * Sets up the {@link OtrBuddyAuthenticationDialog} components so that they
- * reflect the {@link OtrBuddyAuthenticationDialog#contact}
- */
- private void loadContact()
- {
- // Local fingerprint.
- String account =
- contact.getProtocolProvider().getAccountID().getDisplayName();
- String localFingerprint =
- OtrActivator.scOtrKeyManager.getLocalFingerprint(contact
- .getProtocolProvider().getAccountID());
- txtLocalFingerprint.setText(OtrActivator.resourceService.getI18NString(
- "plugin.otr.authbuddydialog.LOCAL_FINGERPRINT", new String[]
- { account, localFingerprint }));
-
- // Remote fingerprint.
- String user = contact.getDisplayName();
- String remoteFingerprint =
- OtrActivator.scOtrKeyManager.getRemoteFingerprint(contact);
- txtRemoteFingerprint.setText(OtrActivator.resourceService
- .getI18NString("plugin.otr.authbuddydialog.REMOTE_FINGERPRINT",
- new String[]
- { user, remoteFingerprint }));
-
- // Action
- txtAction.setText(OtrActivator.resourceService.getI18NString(
- "plugin.otr.authbuddydialog.VERIFY_ACTION", new String[]
- { user }));
- }
-
- /**
- * A special {@link JTextArea} for use in the
- * {@link OtrBuddyAuthenticationDialog}. It is meant to be used for
- * fingerprint representation and general information display.
- *
- * @author George Politis
- */
- class CustomTextArea
- extends JTextArea
- {
- public CustomTextArea()
- {
- this.setBackground(new Color(0,0,0,0));
- this.setOpaque(false);
- this.setColumns(20);
- this.setEditable(false);
- this.setLineWrap(true);
- this.setWrapStyleWord(true);
- }
- }
-
- /**
- * A simple enumeration that is meant to be used with
- * {@link ActionComboBoxItem} to distinguish them (like an ID).
- *
- * @author George Politis
- */
- enum ActionComboBoxItemIndex
- {
- I_HAVE, I_HAVE_NOT
- }
-
- /**
- * A special {@link JComboBox} that is hosted in
- * {@link OtrBuddyAuthenticationDialog#cbAction}.
- *
- * @author George Politis
- */
- class ActionComboBoxItem
- {
- public ActionComboBoxItemIndex action;
-
- private String text;
-
- public ActionComboBoxItem(ActionComboBoxItemIndex actionIndex)
- {
- this.action = actionIndex;
- switch (action)
- {
- case I_HAVE:
- text =
- OtrActivator.resourceService
- .getI18NString("plugin.otr.authbuddydialog.I_HAVE");
- break;
- case I_HAVE_NOT:
- text =
- OtrActivator.resourceService
- .getI18NString("plugin.otr.authbuddydialog.I_HAVE_NOT");
- break;
- }
- }
-
- @Override
- public String toString()
- {
- return text;
- }
}
/**
@@ -172,45 +57,60 @@ public class OtrBuddyAuthenticationDialog
.getI18NString("plugin.otr.authbuddydialog.AUTHENTICATION_INFO"));
mainPanel.add(generalInformation);
- txtLocalFingerprint = new CustomTextArea();
- mainPanel.add(txtLocalFingerprint);
-
- txtRemoteFingerprint = new CustomTextArea();
- mainPanel.add(txtRemoteFingerprint);
-
- // Action Panel (the panel that holds the I have/I have not dropdown)
- JPanel pnlAction = new JPanel(new GridBagLayout());
- pnlAction.setBorder(BorderFactory.createEtchedBorder());
- mainPanel.add(pnlAction);
+ mainPanel.add(Box.createVerticalStrut(10));
+
+ // Add authentication method label and combo box.
+ final String am[] = new String[]{
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_QUESTION"),
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_SECRET"),
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_FINGERPRINT")};
+ final JComboBox authenticationMethodComboBox =
+ new JComboBox(am);
+ JTextArea authMethodLabel = new CustomTextArea();
+ authMethodLabel.setText(
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.authbuddydialog.AUTHENTICATION_METHOD"));
+ mainPanel.add(authMethodLabel);
+ mainPanel.add(authenticationMethodComboBox);
+ mainPanel.add(Box.createVerticalStrut(10));
+
+ // Add authentication panels in a card layout so that the user can
+ // use the combo box to switch between authentication methods.
+ final JPanel authenticationPanel =
+ new TransparentPanel(new CardLayout());
+ final FingerprintAuthenticationPanel fingerprintPanel =
+ new FingerprintAuthenticationPanel(contact);
+ final SecretQuestionAuthenticationPanel secretQuestionPanel =
+ new SecretQuestionAuthenticationPanel();
+ final SharedSecretAuthenticationPanel sharedSecretPanel =
+ new SharedSecretAuthenticationPanel();
+ authenticationPanel.add(secretQuestionPanel, am[0]);
+ authenticationPanel.add(sharedSecretPanel, am[1]);
+ authenticationPanel.add(fingerprintPanel, am[2]);
+
+ authenticationMethodComboBox.addItemListener(new ItemListener()
+ {
+ @Override
+ public void itemStateChanged(ItemEvent e)
+ {
+ if (e.getStateChange() == ItemEvent.SELECTED)
+ {
+ CardLayout cl =
+ (CardLayout) (authenticationPanel.getLayout());
+ cl.show(authenticationPanel, (String)e.getItem());
+ }
+ }
+ });
+ authenticationMethodComboBox.setSelectedIndex(0);
+ mainPanel.add(authenticationPanel);
GridBagConstraints c = new GridBagConstraints();
- c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(5, 5, 5, 5);
- c.weightx = 0.0;
-
- cbAction = new JComboBox();
- cbAction.addItem(actionIHave);
- cbAction.addItem(actionIHaveNot);
- cbAction.setSelectedItem(OtrActivator.scOtrKeyManager
- .isVerified(contact) ? actionIHave : actionIHaveNot);
-
- pnlAction.add(cbAction, c);
-
- txtAction = new CustomTextArea();
c.weightx = 1.0;
- pnlAction.add(txtAction, c);
-
- txtRemoteFingerprintComparison = new SIPCommTextField(
- OtrActivator.resourceService
- .getI18NString("plugin.otr.authbuddydialog.FINGERPRINT_CHECK",
- new String[]{contact.getDisplayName()}));
- txtRemoteFingerprintComparison.getDocument().addDocumentListener(this);
-
- c.gridwidth = 2;
- c.gridy = 1;
- pnlAction.add(txtRemoteFingerprintComparison, c);
c.gridwidth = 1;
- c.gridy = 0;
// Buttons panel.
JPanel buttonPanel = new TransparentPanel(new GridBagLayout());
@@ -254,19 +154,40 @@ public class OtrBuddyAuthenticationDialog
{
public void actionPerformed(ActionEvent e)
{
- ActionComboBoxItem actionItem =
- (ActionComboBoxItem) cbAction.getSelectedItem();
- switch (actionItem.action)
+ String authenticationMethod =
+ (String)authenticationMethodComboBox.getSelectedItem();
+ if (authenticationMethod.equals(am[0]))
{
- case I_HAVE:
- OtrActivator.scOtrKeyManager.verify(contact);
- break;
- case I_HAVE_NOT:
- OtrActivator.scOtrKeyManager.unverify(contact);
- break;
+ String secret = secretQuestionPanel.getSecret();
+ String question = secretQuestionPanel.getQuestion();
+
+ OtrActivator.scOtrEngine.initSmp(contact, question, secret);
+ dispose();
}
+ else if (authenticationMethod.equals(am[1]))
+ {
+ String secret = secretQuestionPanel.getSecret();
+ String question = null;
- dispose();
+ OtrActivator.scOtrEngine.initSmp(contact, question, secret);
+ dispose();
+ }
+ else if (authenticationMethod.equals(am[2]))
+ {
+ ActionComboBoxItem actionItem =
+ (ActionComboBoxItem) fingerprintPanel.
+ getCbAction().getSelectedItem();
+ switch (actionItem.action)
+ {
+ case I_HAVE:
+ OtrActivator.scOtrKeyManager.verify(contact);
+ break;
+ case I_HAVE_NOT:
+ OtrActivator.scOtrKeyManager.unverify(contact);
+ break;
+ }
+ dispose();
+ }
}
});
buttonPanel.add(authenticateButton, c);
@@ -275,42 +196,4 @@ public class OtrBuddyAuthenticationDialog
this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
this.pack();
}
-
- public void removeUpdate(DocumentEvent e)
- {
- compareFingerprints();
- }
-
- public void insertUpdate(DocumentEvent e)
- {
- compareFingerprints();
- }
-
- public void changedUpdate(DocumentEvent e)
- {
- compareFingerprints();
- }
-
- public void compareFingerprints()
- {
- if(txtRemoteFingerprintComparison.getText() == null
- || txtRemoteFingerprintComparison.getText().length() == 0)
- {
- txtRemoteFingerprintComparison.setBackground(Color.white);
- return;
- }
- if(txtRemoteFingerprintComparison.getText().toLowerCase().contains(
- OtrActivator.scOtrKeyManager
- .getRemoteFingerprint(contact).toLowerCase()))
- {
- txtRemoteFingerprintComparison.setBackground(Color.green);
- cbAction.setSelectedItem(actionIHave);
- }
- else
- {
- txtRemoteFingerprintComparison.setBackground(
- new Color(243, 72, 48));
- cbAction.setSelectedItem(actionIHaveNot);
- }
- }
}
diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrEngine.java b/src/net/java/sip/communicator/plugin/otr/ScOtrEngine.java
index 1e7b5e8..3e8e6e5 100644
--- a/src/net/java/sip/communicator/plugin/otr/ScOtrEngine.java
+++ b/src/net/java/sip/communicator/plugin/otr/ScOtrEngine.java
@@ -21,6 +21,38 @@ public interface ScOtrEngine
// Proxy methods OtrEngine.
/**
+ * Initializes Smp negotiation.
+ * See {@link http://en.wikipedia.org/wiki/Socialist_Millionaire_Problem}
+ *
+ * @param contact The contact with whom we want to start the Smp negotiation
+ * @param question The question that is asked during the Smp negotiation
+ * @param secret The secret answer for the question.
+ */
+ public abstract void initSmp(
+ Contact contact, String question, String secret);
+
+ /**
+ * Responds to a question that is asked during the Smp negotiation process.
+ * See {@link http://en.wikipedia.org/wiki/Socialist_Millionaire_Problem}
+ *
+ * @param contact The contact for whom we want to respond to a question
+ * during the Smp negotiation process.
+ * @param question The question that is asked during the Smp negotiation.
+ * @param secret The secret answer for the question.
+ */
+ public abstract void respondSmp(
+ Contact contact, String question, String secret);
+
+ /**
+ * Aborts the Smp negotiation process.
+ * See {@link http://en.wikipedia.org/wiki/Socialist_Millionaire_Problem}
+ *
+ * @param contact The contact with whom we want to abort the
+ * Smp negotiation process.
+ */
+ public abstract void abortSmp(Contact contact);
+
+ /**
* Transforms an outgoing message.
*
* @param contact the destination {@link Contact}.
diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java
index f60ef33..c465e94 100644
--- a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java
+++ b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java
@@ -6,13 +6,20 @@
*/
package net.java.sip.communicator.plugin.otr;
+import java.awt.*;
+import java.awt.event.*;
import java.net.*;
import java.security.*;
import java.util.*;
+import java.util.List;
+import java.util.concurrent.*;
+
+import javax.swing.*;
+import javax.swing.plaf.basic.*;
import net.java.otr4j.*;
import net.java.otr4j.session.*;
-
+import net.java.sip.communicator.plugin.desktoputil.*;
import net.java.sip.communicator.service.browserlauncher.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.gui.*;
@@ -36,7 +43,7 @@ public class ScOtrEngineImpl
class ScOtrEngineHost
implements OtrEngineHost
{
- public KeyPair getKeyPair(SessionID sessionID)
+ public KeyPair getLocalKeyPair(SessionID sessionID)
{
AccountID accountID =
OtrActivator.getAccountIDByUID(sessionID.getAccountID());
@@ -83,11 +90,242 @@ public class ScOtrEngineImpl
Chat.SYSTEM_MESSAGE, warn,
OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE);
}
+
+ @Override
+ public void unreadableMessageReceived(SessionID sessionID)
+ throws OtrException
+ {
+ Contact contact = getContact(sessionID);
+ if (contact == null)
+ return;
+
+ String error =
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.activator.unreadablemsgreceived",
+ new String[] {contact.getDisplayName()});
+ OtrActivator.uiService.getChat(contact).addMessage(
+ contact.getDisplayName(), new Date(),
+ Chat.ERROR_MESSAGE, error,
+ OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE);
+ }
+
+ @Override
+ public void unencryptedMessageReceived(SessionID sessionID, String msg)
+ throws OtrException
+ {
+ Contact contact = getContact(sessionID);
+ if (contact == null)
+ return;
+
+ String warn =
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.activator.unencryptedmsgreceived");
+ OtrActivator.uiService.getChat(contact).addMessage(
+ contact.getDisplayName(), new Date(),
+ Chat.SYSTEM_MESSAGE, warn,
+ OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE);
+ }
+
+ @Override
+ public void smpError(SessionID sessionID, int tlvType, boolean cheated)
+ throws OtrException
+ {
+ Contact contact = getContact(sessionID);
+ if (contact == null)
+ return;
+
+ logger.debug("SMP error occurred"
+ + ". Contact: " + contact.getDisplayName()
+ + ". TLV type: " + tlvType
+ + ". Cheated: " + cheated);
+
+ String error =
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.activator.smperror");
+ OtrActivator.uiService.getChat(contact).addMessage(
+ contact.getDisplayName(), new Date(),
+ Chat.ERROR_MESSAGE, error,
+ OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE);
+
+ SmpProgressDialog progressDialog = progressDialogMap.get(contact);
+ if (progressDialog == null)
+ {
+ progressDialog = new SmpProgressDialog(contact);
+ progressDialogMap.put(contact, progressDialog);
+ }
+
+ progressDialog.setProgressFail();
+ progressDialog.setVisible(true);
+ }
+
+ @Override
+ public void smpAborted(SessionID sessionID) throws OtrException
+ {
+ Contact contact = getContact(sessionID);
+ if (contact == null)
+ return;
+
+ Session session = otrEngine.getSession(sessionID);
+ if (session.isSmpInProgress())
+ {
+ String warn =
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.activator.smpaborted",
+ new String[] {contact.getDisplayName()});
+ OtrActivator.uiService.getChat(contact).addMessage(
+ contact.getDisplayName(), new Date(),
+ Chat.SYSTEM_MESSAGE, warn,
+ OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE);
+
+ SmpProgressDialog progressDialog = progressDialogMap.get(contact);
+ if (progressDialog == null)
+ {
+ progressDialog = new SmpProgressDialog(contact);
+ progressDialogMap.put(contact, progressDialog);
+ }
+
+ progressDialog.setProgressFail();
+ progressDialog.setVisible(true);
+ }
+ }
+
+ @Override
+ public void finishedSessionMessage(SessionID sessionID)
+ throws OtrException
+ {
+ Contact contact = getContact(sessionID);
+ if (contact == null)
+ return;
+
+ String error =
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.activator.sessionfinishederror",
+ new String[] {contact.getDisplayName()});
+ OtrActivator.uiService.getChat(contact).addMessage(
+ contact.getDisplayName(), new Date(),
+ Chat.ERROR_MESSAGE, error,
+ OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE);
+ }
+
+ @Override
+ public void requireEncryptedMessage(SessionID sessionID, String msgText)
+ throws OtrException
+ {
+ Contact contact = getContact(sessionID);
+ if (contact == null)
+ return;
+
+ String error =
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.activator.requireencryption",
+ new String[] {contact.getDisplayName()});
+ OtrActivator.uiService.getChat(contact).addMessage(
+ contact.getDisplayName(), new Date(),
+ Chat.ERROR_MESSAGE, error,
+ OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE);
+ }
+
+ @Override
+ public byte[] getLocalFingerprintRaw(SessionID sessionID)
+ {
+ AccountID accountID =
+ OtrActivator.getAccountIDByUID(sessionID.getAccountID());
+ return
+ OtrActivator.scOtrKeyManager.getLocalFingerprintRaw(accountID);
+ }
+
+ @Override
+ public void askForSecret(SessionID sessionID, String question)
+ {
+ Contact contact = getContact(sessionID);
+ if (contact == null)
+ return;
+
+ SmpAuthenticateBuddyDialog dialog =
+ new SmpAuthenticateBuddyDialog(contact, question);
+ dialog.setVisible(true);
+
+ SmpProgressDialog progressDialog = progressDialogMap.get(contact);
+ if (progressDialog == null)
+ {
+ progressDialog = new SmpProgressDialog(contact);
+ progressDialogMap.put(contact, progressDialog);
+ }
+
+ progressDialog.init();
+ progressDialog.setVisible(true);
+ }
+
+ @Override
+ public void verify(SessionID sessionID, boolean approved)
+ {
+ Contact contact = getContact(sessionID);
+ if (contact == null)
+ return;
+
+ OtrActivator.scOtrKeyManager.verify(contact);
+
+ SmpProgressDialog progressDialog = progressDialogMap.get(contact);
+ if (progressDialog == null)
+ {
+ progressDialog = new SmpProgressDialog(contact);
+ progressDialogMap.put(contact, progressDialog);
+ }
+
+ progressDialog.setProgressSuccess();
+ progressDialog.setVisible(true);
+ }
+
+ @Override
+ public void unverify(SessionID sessionID)
+ {
+ Contact contact = getContact(sessionID);
+ if (contact == null)
+ return;
+
+ OtrActivator.scOtrKeyManager.unverify(contact);
+
+ SmpProgressDialog progressDialog = progressDialogMap.get(contact);
+ if (progressDialog == null)
+ {
+ progressDialog = new SmpProgressDialog(contact);
+ progressDialogMap.put(contact, progressDialog);
+ }
+
+ progressDialog.setProgressFail();
+ progressDialog.setVisible(true);
+ }
+
+ @Override
+ public String getReplyForUnreadableMessage(SessionID sessionID)
+ {
+ AccountID accountID =
+ OtrActivator.getAccountIDByUID(sessionID.getAccountID());
+
+ return OtrActivator.resourceService.getI18NString(
+ "plugin.otr.activator.unreadablemsgreply",
+ new String[] {accountID.getDisplayName(),
+ accountID.getDisplayName()});
+ }
+
+ @Override
+ public String getFallbackMessage(SessionID sessionID)
+ {
+ AccountID accountID =
+ OtrActivator.getAccountIDByUID(sessionID.getAccountID());
+
+ return OtrActivator.resourceService.getI18NString(
+ "plugin.otr.activator.fallbackmessage",
+ new String[] {accountID.getDisplayName()});
+ }
}
private static final Map<ScSessionID, Contact> contactsMap =
new Hashtable<ScSessionID, Contact>();
+ private static final Map<Contact, SmpProgressDialog> progressDialogMap =
+ new ConcurrentHashMap<Contact, SmpProgressDialog>();
+
public static Contact getContact(SessionID sessionID)
{
return contactsMap.get(new ScSessionID(sessionID));
@@ -145,11 +383,14 @@ public class ScOtrEngineImpl
*/
private final Logger logger = Logger.getLogger(ScOtrEngineImpl.class);
- private final OtrEngine otrEngine
- = new OtrEngineImpl(new ScOtrEngineHost());
+ final OtrEngineHost otrEngineHost = new ScOtrEngineHost();
+
+ private final OtrEngine otrEngine;
public ScOtrEngineImpl()
{
+ otrEngine = new OtrEngineImpl(otrEngineHost);
+
// Clears the map after previous instance
// This is required because of OSGi restarts in the same VM on Android
contactsMap.clear();
@@ -449,6 +690,9 @@ public class ScOtrEngineImpl
logger.debug(
"Unregistering a ProtocolProviderService, cleaning"
+ " OTR's ScSessionID to Contact map.");
+ logger.debug(
+ "Unregistering a ProtocolProviderService, cleaning"
+ + " OTR's Contact to SpmProgressDialog map.");
}
ProtocolProviderService provider
@@ -464,6 +708,14 @@ public class ScOtrEngineImpl
i.remove();
}
}
+
+ Iterator<Contact> i = progressDialogMap.keySet().iterator();
+
+ while (i.hasNext())
+ {
+ if (provider.equals(i.next().getProtocolProvider()))
+ i.remove();
+ }
}
}
@@ -545,4 +797,398 @@ public class ScOtrEngineImpl
return null;
}
}
+
+ private Session getSession(Contact contact)
+ {
+ SessionID sessionID = getSessionID(contact);
+ return otrEngine.getSession(sessionID);
+ }
+
+ @Override
+ public void initSmp(Contact contact, String question, String secret)
+ {
+ Session session = getSession(contact);
+ try
+ {
+ session.initSmp(question, secret);
+
+ SmpProgressDialog progressDialog = progressDialogMap.get(contact);
+ if (progressDialog == null)
+ {
+ progressDialog = new SmpProgressDialog(contact);
+ progressDialogMap.put(contact, progressDialog);
+ }
+
+ progressDialog.init();
+ progressDialog.setVisible(true);
+ }
+ catch (OtrException e)
+ {
+ logger.error("Error initializing SMP session with contact "
+ + contact.getDisplayName(), e);
+ showError(session.getSessionID(), e.getMessage());
+ }
+ }
+
+ @Override
+ public void respondSmp(Contact contact, String question, String secret)
+ {
+ Session session = getSession(contact);
+ try
+ {
+ session.respondSmp(question, secret);
+
+ SmpProgressDialog progressDialog = progressDialogMap.get(contact);
+ if (progressDialog == null)
+ {
+ progressDialog = new SmpProgressDialog(contact);
+ progressDialogMap.put(contact, progressDialog);
+ }
+
+ progressDialog.incrementProgress();
+ progressDialog.setVisible(true);
+ }
+ catch (OtrException e)
+ {
+ logger.error(
+ "Error occured when sending SMP response to contact "
+ + contact.getDisplayName(), e);
+ showError(session.getSessionID(), e.getMessage());
+ }
+ }
+
+ @Override
+ public void abortSmp(Contact contact)
+ {
+ Session session = getSession(contact);
+ try
+ {
+ session.abortSmp();
+
+ SmpProgressDialog progressDialog = progressDialogMap.get(contact);
+ if (progressDialog == null)
+ {
+ progressDialog = new SmpProgressDialog(contact);
+ progressDialogMap.put(contact, progressDialog);
+ }
+
+ progressDialog.dispose();
+ }
+ catch (OtrException e)
+ {
+ logger.error("Error aborting SMP session with contact "
+ + contact.getDisplayName(), e);
+ showError(session.getSessionID(), e.getMessage());
+ }
+
+ }
+
+ /**
+ * The dialog that pops up when SMP negotiation starts.
+ * It contains a progress bar that indicates the status of the SMP
+ * authentication process.
+ */
+ @SuppressWarnings("serial")
+ private class SmpProgressDialog
+ extends SIPCommDialog
+ {
+ private final JProgressBar progressBar = new JProgressBar(0, 100);
+
+ private final Color successColor = new Color(86, 140, 2);
+
+ private final Color failColor = new Color(204, 0, 0);
+
+ private final JLabel iconLabel = new JLabel();
+
+ /**
+ * Instantiates SmpProgressDialog.
+ *
+ * @param contact The contact that this dialog is associated with.
+ */
+ public SmpProgressDialog(Contact contact)
+ {
+ setTitle(
+ OtrActivator.resourceService.getI18NString(
+ "plugin.otr.smpprogressdialog.TITLE"));
+
+ JPanel mainPanel = new TransparentPanel();
+ mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
+ mainPanel.setBorder(
+ BorderFactory.createEmptyBorder(10, 10, 10, 10));
+ mainPanel.setPreferredSize(new Dimension(300, 70));
+
+ String authFromText =
+ String.format(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.AUTHENTICATION_FROM",
+ new String[] {contact.getDisplayName()}));
+
+ JPanel labelsPanel = new TransparentPanel();
+ labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.X_AXIS));
+
+ labelsPanel.add(iconLabel);
+ labelsPanel.add(Box.createRigidArea(new Dimension(5,0)));
+ labelsPanel.add(new JLabel(authFromText));
+
+ mainPanel.add(labelsPanel);
+ mainPanel.add(progressBar);
+
+ init();
+
+ this.getContentPane().add(mainPanel);
+ this.pack();
+ }
+
+ /**
+ * Initializes the progress bar and sets it's progression to 1/3.
+ */
+ public void init()
+ {
+ progressBar.setUI(new BasicProgressBarUI() {
+ private Rectangle r = new Rectangle();
+
+ @Override
+ protected void paintIndeterminate(Graphics g, JComponent c) {
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.setRenderingHint(
+ RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ r = getBox(r);
+ g.setColor(progressBar.getForeground());
+ g.fillOval(r.x, r.y, r.width, r.height);
+ }
+ });
+ progressBar.setValue(33);
+ progressBar.setForeground(successColor);
+ progressBar.setStringPainted(false);
+ iconLabel.setIcon(
+ OtrActivator.resourceService.getImage(
+ "plugin.otr.ENCRYPTED_UNVERIFIED_ICON_22x22"));
+ }
+
+ /**
+ * Sets the progress bar to 2/3 of completion.
+ */
+ public void incrementProgress()
+ {
+ progressBar.setValue(66);
+ }
+
+ /**
+ * Sets the progress bar to green.
+ */
+ public void setProgressSuccess()
+ {
+ progressBar.setValue(100);
+ progressBar.setForeground(successColor);
+ progressBar.setStringPainted(true);
+ progressBar.setString(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.smpprogressdialog.AUTHENTICATION_SUCCESS"));
+ iconLabel.setIcon(
+ OtrActivator.resourceService.getImage(
+ "plugin.otr.ENCRYPTED_ICON_22x22"));
+ }
+
+ /**
+ * Sets the progress bar to red.
+ */
+ public void setProgressFail()
+ {
+ progressBar.setValue(100);
+ progressBar.setForeground(failColor);
+ progressBar.setStringPainted(true);
+ progressBar.setString(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.smpprogressdialog.AUTHENTICATION_FAIL"));
+ }
+ }
+
+ /**
+ * The dialog that pops up when the remote party send us SMP
+ * request. It contains detailed information for the user about
+ * the authentication process and allows him to authenticate.
+ *
+ */
+ @SuppressWarnings("serial")
+ private class SmpAuthenticateBuddyDialog
+ extends SIPCommDialog
+ {
+ private final Contact contact;
+
+ private final String question;
+
+ SmpAuthenticateBuddyDialog(Contact contact, String question)
+ {
+ this.contact = contact;
+ this.question = question;
+ initComponents();
+ }
+
+ private void initComponents()
+ {
+ this.setTitle(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.TITLE"));
+
+ // The main panel that contains all components.
+ JPanel mainPanel = new TransparentPanel();
+ mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
+ mainPanel.setBorder(
+ BorderFactory.createEmptyBorder(10, 10, 10, 10));
+ mainPanel.setPreferredSize(new Dimension(300, 350));
+
+ // Add "authentication from contact" to the main panel.
+ JTextArea authenticationFrom = new CustomTextArea();
+ Font newFont =
+ new Font(
+ UIManager.getDefaults().getFont("TextArea.font").
+ getFontName()
+ , Font.BOLD
+ , 14);
+ authenticationFrom.setFont(newFont);
+ String authFromText =
+ String.format(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.AUTHENTICATION_FROM",
+ new String[] {contact.getDisplayName()}));
+ authenticationFrom.setText(authFromText);
+ mainPanel.add(authenticationFrom);
+
+ // Add "general info" text to the main panel.
+ JTextArea generalInfo = new CustomTextArea();
+ generalInfo.setText(OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.AUTHENTICATION_INFO"));
+ mainPanel.add(generalInfo);
+
+ // Add "authentication-by-secret" info text to the main panel.
+ JTextArea authBySecretInfo = new CustomTextArea();
+ newFont =
+ new Font(
+ UIManager.getDefaults().getFont("TextArea.font").
+ getFontName()
+ , Font.ITALIC
+ , 10);
+ authBySecretInfo.setText(OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.AUTH_BY_SECRET_INFO_RESPOND"));
+ authBySecretInfo.setFont(newFont);
+ mainPanel.add(authBySecretInfo);
+
+ // Create a panel to add question/answer related components
+ JPanel questionAnswerPanel = new JPanel(new GridBagLayout());
+ questionAnswerPanel.setBorder(BorderFactory.createEtchedBorder());
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(5, 5, 0, 5);
+ c.weightx = 0;
+
+ // Add question label.
+ JLabel questionLabel =
+ new JLabel(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.QUESTION_RESPOND"));
+ questionAnswerPanel.add(questionLabel, c);
+
+ // Add the question.
+ c.insets = new Insets(0, 5, 5, 5);
+ c.gridy = 1;
+ JTextArea questionArea =
+ new CustomTextArea();
+ newFont =
+ new Font(
+ UIManager.getDefaults().getFont("TextArea.font").
+ getFontName()
+ , Font.BOLD
+ , UIManager.getDefaults().getFont("TextArea.font")
+ .getSize());
+ questionArea.setFont(newFont);
+ questionArea.setText(question);
+ questionAnswerPanel.add(questionArea, c);
+
+ // Add answer label.
+ c.insets = new Insets(5, 5, 5, 5);
+ c.gridy = 2;
+ JLabel answerLabel =
+ new JLabel(OtrActivator.resourceService
+ .getI18NString("plugin.otr.authbuddydialog.ANSWER"));
+ questionAnswerPanel.add(answerLabel, c);
+
+ // Add the answer text field.
+ c.gridy = 3;
+ final JTextField answerTextBox = new JTextField();
+ questionAnswerPanel.add(answerTextBox, c);
+
+ // Add the question/answer panel to the main panel.
+ mainPanel.add(questionAnswerPanel);
+
+ // Buttons panel.
+ JPanel buttonPanel = new TransparentPanel(new GridBagLayout());
+ buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
+
+ JButton helpButton =
+ new JButton(OtrActivator.resourceService
+ .getI18NString("plugin.otr.authbuddydialog.HELP"));
+ helpButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent arg0)
+ {
+ OtrActivator.scOtrEngine.launchHelp();
+ }
+ });
+
+ c.gridwidth = 1;
+ c.gridy = 0;
+ c.gridx = 0;
+ c.weightx = 0;
+ c.insets = new Insets(5, 5, 5, 20);
+ buttonPanel.add(helpButton, c);
+
+ JButton cancelButton =
+ new JButton(OtrActivator.resourceService
+ .getI18NString("plugin.otr.authbuddydialog.CANCEL"));
+ cancelButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ ScOtrEngineImpl.this.abortSmp(contact);
+ SmpAuthenticateBuddyDialog.this.dispose();
+ }
+ });
+ c.insets = new Insets(5, 5, 5, 5);
+ c.gridx = 1;
+ buttonPanel.add(cancelButton, c);
+
+ c.gridx = 2;
+ JButton authenticateButton =
+ new JButton(OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.AUTHENTICATE_BUDDY"));
+ authenticateButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ ScOtrEngineImpl.this.respondSmp(
+ contact, question, answerTextBox.getText());
+ SmpAuthenticateBuddyDialog.this.dispose();
+ }
+ });
+
+ buttonPanel.add(authenticateButton, c);
+
+ this.getContentPane().add(mainPanel, BorderLayout.NORTH);
+ this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
+ this.pack();
+ }
+ }
}
diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManager.java b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManager.java
index fef0f9f..bc83cd7 100755
--- a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManager.java
+++ b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManager.java
@@ -32,6 +32,8 @@ public interface ScOtrKeyManager
public abstract String getLocalFingerprint(AccountID account);
+ public abstract byte[] getLocalFingerprintRaw(AccountID account);
+
public abstract void savePublicKey(Contact contact, PublicKey pubKey);
public abstract PublicKey loadPublicKey(Contact contact);
diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerImpl.java b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerImpl.java
index c461ad0..37adc63 100755
--- a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerImpl.java
+++ b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerImpl.java
@@ -131,6 +131,26 @@ public class ScOtrKeyManagerImpl
}
}
+ public byte[] getLocalFingerprintRaw(AccountID account)
+ {
+ KeyPair keyPair = loadKeyPair(account);
+
+ if (keyPair == null)
+ return null;
+
+ PublicKey pubKey = keyPair.getPublic();
+
+ try
+ {
+ return new OtrCryptoEngineImpl().getFingerprintRaw(pubKey);
+ }
+ catch (OtrCryptoException e)
+ {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
public void savePublicKey(Contact contact, PublicKey pubKey)
{
if (contact == null)
diff --git a/src/net/java/sip/communicator/plugin/otr/SecretQuestionAuthenticationPanel.java b/src/net/java/sip/communicator/plugin/otr/SecretQuestionAuthenticationPanel.java
new file mode 100644
index 0000000..7134d7d
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/otr/SecretQuestionAuthenticationPanel.java
@@ -0,0 +1,117 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.plugin.otr;
+
+import java.awt.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.plugin.desktoputil.*;
+
+/**
+ * @author Marin Dzhigarov
+ */
+@SuppressWarnings("serial")
+public class SecretQuestionAuthenticationPanel
+ extends TransparentPanel
+{
+ /**
+ * The text field where the authentication initiator will type his question.
+ */
+ private final JTextField question = new JTextField();
+
+ /**
+ * The text field where the authentication initiator will type his answer.
+ */
+ private final JTextField answer = new JTextField();
+
+
+ /**
+ * Creates an instance SecretQuestionAuthenticationPanel.
+ */
+ SecretQuestionAuthenticationPanel()
+ {
+ initComponents();
+ }
+
+ /**
+ * Initializes the {@link SecretQuestionAuthenticationPanel} components.
+ */
+ private void initComponents()
+ {
+ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ JTextArea generalInformation = new CustomTextArea();
+ generalInformation.setText(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.AUTH_BY_QUESTION_INFO_INIT"));
+ this.add(generalInformation);
+
+ this.add(Box.createVerticalStrut(10));
+
+ JPanel questionAnswerPanel = new JPanel(new GridBagLayout());
+ questionAnswerPanel.setBorder(BorderFactory.createEtchedBorder());
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(5, 5, 0, 5);
+ c.weightx = 1;
+
+ JLabel questionLabel =
+ new JLabel(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.QUESTION_INIT"));
+ questionAnswerPanel.add(questionLabel, c);
+
+ c.gridy = 1;
+ c.insets = new Insets(0, 5, 5, 5);
+ questionAnswerPanel.add(question, c);
+
+ c.gridy = 2;
+ c.insets = new Insets(5, 5, 0, 5);
+ JLabel answerLabel =
+ new JLabel(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.ANSWER"));
+ questionAnswerPanel.add(answerLabel, c);
+
+ c.gridy = 3;
+ c.insets = new Insets(0, 5, 5, 5);
+ questionAnswerPanel.add(answer, c);
+
+ this.add(questionAnswerPanel);
+ this.add(new Box.Filler(
+ new Dimension(300, 100),
+ new Dimension(300, 100),
+ new Dimension(300, 100)));
+ }
+
+ /**
+ * Returns the secret answer text.
+ *
+ * @return The secret answer text.
+ */
+ String getSecret()
+ {
+ return answer.getText();
+ }
+
+ /**
+ * Returns the secret question text.
+ *
+ * @return The secret question text.
+ */
+ String getQuestion()
+ {
+ return question.getText();
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/otr/SharedSecretAuthenticationPanel.java b/src/net/java/sip/communicator/plugin/otr/SharedSecretAuthenticationPanel.java
new file mode 100644
index 0000000..39769f2
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/otr/SharedSecretAuthenticationPanel.java
@@ -0,0 +1,89 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.plugin.otr;
+
+import java.awt.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.plugin.desktoputil.*;
+
+/**
+ * @author Marin Dzhigarov
+ *
+ */
+@SuppressWarnings("serial")
+public class SharedSecretAuthenticationPanel
+ extends TransparentPanel
+{
+ /**
+ * The text field where the authentication initiator will type his answer.
+ */
+ private final JTextField secret = new JTextField();
+
+ /**
+ * Creates an instance SecretQuestionAuthenticationPanel.
+ */
+ SharedSecretAuthenticationPanel()
+ {
+ initComponents();
+ }
+
+ /**
+ * Initializes the {@link SecretQuestionAuthenticationPanel} components.
+ */
+ private void initComponents()
+ {
+ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ JTextArea generalInformation = new CustomTextArea();
+ generalInformation.setText(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.AUTH_BY_SECRET_INFO_INIT"));
+ this.add(generalInformation);
+
+ this.add(Box.createVerticalStrut(10));
+
+ JPanel questionAnswerPanel = new JPanel(new GridBagLayout());
+ questionAnswerPanel.setBorder(BorderFactory.createEtchedBorder());
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(5, 5, 0, 5);
+ c.weightx = 1;
+
+ JLabel questionLabel =
+ new JLabel(
+ OtrActivator.resourceService
+ .getI18NString(
+ "plugin.otr.authbuddydialog.SHARED_SECRET"));
+ questionAnswerPanel.add(questionLabel, c);
+
+ c.gridy = 1;
+ c.insets = new Insets(0, 5, 5, 5);
+ questionAnswerPanel.add(secret, c);
+
+ this.add(questionAnswerPanel);
+ this.add(new Box.Filler(
+ new Dimension(300, 150),
+ new Dimension(300, 150),
+ new Dimension(300, 150)));
+ }
+
+ /**
+ * Returns the shared secret text.
+ *
+ * @return The shared secret text.
+ */
+ String getSecret()
+ {
+ return secret.getText();
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf b/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf
index 3e74c53..71c607c 100644
--- a/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf
+++ b/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf
@@ -20,6 +20,8 @@ Import-Package: org.osgi.framework,
javax.swing.table,
javax.swing.text,
javax.swing.event,
+ javax.swing.plaf,
+ javax.swing.plaf.basic,
javax.crypto,
javax.crypto.interfaces,
javax.crypto.spec,