reaching otr beta status

git-svn-id: http://svn.igniterealtime.org/svn/repos/spark/branches/otrplugin@12462 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Holger Bergunde
2011-06-08 11:58:42 +00:00
committed by holger.bergunde
parent ede41b8e70
commit 5af5d63c7f
14 changed files with 197 additions and 302 deletions

View File

@ -1,44 +0,0 @@
package org.jivesoftware.spark.otrplug;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.spark.ChatManager;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.ui.ChatRoom;
import org.jivesoftware.spark.ui.ChatRoomListenerAdapter;
import org.jivesoftware.spark.ui.MessageEventListener;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
public class MessageListenerHandler extends ChatRoomListenerAdapter {
final ChatManager chatManager = SparkManager.getChatManager();
public MessageListenerHandler() {
chatManager.addChatRoomListener(this);
}
@Override
public void chatRoomOpened(ChatRoom room) {
super.chatRoomOpened(room);
if (room instanceof ChatRoomImpl) {
// OTRManager.getInstance().startOTRSession((ChatRoomImpl) room, ((ChatRoomImpl) room).getParticipantJID());
//
((ChatRoomImpl) room).addMessageEventListener(new MessageEventListener() {
@Override
public void sendingMessage(Message message) {
//System.out.println(message.getBody());
}
@Override
public void receivingMessage(Message message) {
// System.out.println(message.getBody());
}
});
}
}
}

View File

@ -3,28 +3,24 @@ package org.jivesoftware.spark.otrplug;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import net.java.otr4j.OtrKeyManager;
import net.java.otr4j.OtrKeyManagerImpl;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.spark.ChatManager;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.otrplug.impl.MyOtrKeyManager;
import org.jivesoftware.spark.otrplug.impl.OTRSession;
import org.jivesoftware.spark.otrplug.util.OTRProperties;
import org.jivesoftware.spark.ui.ChatRoom;
import org.jivesoftware.spark.ui.ChatRoomListenerAdapter;
import org.jivesoftware.spark.ui.ContactItem;
import org.jivesoftware.spark.ui.ContactItemHandler;
import org.jivesoftware.spark.ui.MessageEventListener;
import org.jivesoftware.spark.ui.MyOtrKeyManager;
import org.jivesoftware.spark.ui.OTRSession;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
@ -34,7 +30,6 @@ public class OTRManager extends ChatRoomListenerAdapter implements ContactItemH
private static OTRManager singleton;
private static Object LOCK = new Object();
private MessageListenerHandler _msgListener;
private Map<String, OTRSession> _activeSessions = new HashMap<String,OTRSession>();
final ChatManager chatManager = SparkManager.getChatManager();
private static MyOtrKeyManager _keyManager;
@ -42,7 +37,6 @@ public class OTRManager extends ChatRoomListenerAdapter implements ContactItemH
private OTRManager()
{
_msgListener = new MessageListenerHandler();
chatManager.addChatRoomListener(this);
chatManager.addContactItemHandler(this);
}
@ -91,6 +85,13 @@ public class OTRManager extends ChatRoomListenerAdapter implements ContactItemH
return singleton;
}
public void startOtrWithUser(String jid)
{
if (_activeSessions.containsKey(jid))
{
_activeSessions.get(jid).startSession();
}
}
private void createOTRSession(ChatRoomImpl chatroom, String jid)
{

View File

@ -1,9 +1,9 @@
package org.jivesoftware.spark.otrplug;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.otrplug.pref.OTRPreferences;
import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.preference.Preference;
import org.jivesoftware.spark.ui.OTRPreferences;

View File

@ -1,179 +0,0 @@
package org.jivesoftware.spark.otrplug;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Logger;
import net.java.otr4j.OtrEngineHost;
import net.java.otr4j.OtrPolicy;
import net.java.otr4j.OtrEngineImpl;
import net.java.otr4j.OtrPolicyImpl;
import net.java.otr4j.session.SessionID;
import net.java.otr4j.session.SessionStatus;
public class OtrEngineImplTest {
private SessionID aliceSessionID = new SessionID("Alice@Wonderland", "Bob@Wonderland", "Scytale");
private SessionID bobSessionID = new SessionID("Bob@Wonderland", "Alice@Wonderland", "Scytale");
private static Logger logger = Logger.getLogger(OtrEngineImplTest.class.getName());
class DummyOtrEngineHost implements OtrEngineHost {
private OtrPolicy policy;
public String lastInjectedMessage;
public DummyOtrEngineHost(OtrPolicy policy) {
this.policy = policy;
}
public OtrPolicy getSessionPolicy(SessionID ctx) {
return this.policy;
}
public void injectMessage(SessionID sessionID, String msg) {
this.lastInjectedMessage = msg;
String msgDisplay = (msg.length() > 10) ? msg.substring(0, 10) + "..." : msg;
logger.finest("IM injects message: " + msgDisplay);
}
public void showError(SessionID sessionID, String error) {
logger.severe("IM shows error to user: " + error);
}
public void showWarning(SessionID sessionID, String warning) {
logger.warning("IM shows warning to user: " + warning);
}
public void sessionStatusChanged(SessionID sessionID) {
// don't care.
}
public KeyPair getKeyPair(SessionID paramSessionID) {
KeyPairGenerator kg;
try {
kg = KeyPairGenerator.getInstance("DSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
return kg.genKeyPair();
}
}
public void testSession() throws Exception {
this.startSession();
this.exchageMessages();
this.endSession();
}
private OtrEngineImpl usAlice;
private OtrEngineImpl usBob;
private DummyOtrEngineHost host;
private void startSession() {
host = new DummyOtrEngineHost(new OtrPolicyImpl(OtrPolicy.ALLOW_V2 | OtrPolicy.ERROR_START_AKE));
usAlice = new OtrEngineImpl(host);
usBob = new OtrEngineImpl(host);
usAlice.startSession(aliceSessionID);
// Bob receives query, sends D-H commit.
usBob.transformReceiving(bobSessionID, host.lastInjectedMessage);
// Alice received D-H Commit, sends D-H key.
usAlice.transformReceiving(aliceSessionID, host.lastInjectedMessage);
// Bob receives D-H Key, sends reveal signature.
usBob.transformReceiving(bobSessionID, host.lastInjectedMessage);
// Alice receives Reveal Signature, sends signature and goes secure.
usAlice.transformReceiving(aliceSessionID, host.lastInjectedMessage);
// Bobs receives Signature, goes secure.
usBob.transformReceiving(bobSessionID, host.lastInjectedMessage);
if (usBob.getSessionStatus(bobSessionID) != SessionStatus.ENCRYPTED || usAlice.getSessionStatus(aliceSessionID) != SessionStatus.ENCRYPTED)
fail("Could not establish a secure session.");
}
private void fail(String string) {
System.err.println("fail "+ string);
}
private void fail() {
System.err.println("fail ");
}
private void exchageMessages() {
// We are both secure, send encrypted message.
String clearTextMessage = "Hello Bob, this new IM software you installed on my PC the other day says we are talking Off-the-Record, what is that supposed to mean?";
String sentMessage = usAlice.transformSending(aliceSessionID, clearTextMessage);
// Receive encrypted message.
String receivedMessage = usBob.transformReceiving(bobSessionID, sentMessage);
if (!clearTextMessage.equals(receivedMessage))
fail();
// Send encrypted message.
clearTextMessage = "Hey Alice, it means that our communication is encrypted and authenticated.";
sentMessage = usBob.transformSending(bobSessionID, clearTextMessage);
// Receive encrypted message.
receivedMessage = usAlice.transformReceiving(aliceSessionID, sentMessage);
if (!clearTextMessage.equals(receivedMessage))
fail();
// Send encrypted message.
clearTextMessage = "Oh, is that all?";
sentMessage = usAlice.transformSending(aliceSessionID, clearTextMessage);
// Receive encrypted message.
receivedMessage = usBob.transformReceiving(bobSessionID, sentMessage);
if (!clearTextMessage.equals(receivedMessage))
fail();
// Send encrypted message.
clearTextMessage = "Actually no, our communication has the properties of perfect forward secrecy and deniable authentication.";
sentMessage = usBob.transformSending(bobSessionID, clearTextMessage);
// Receive encrypted message.
receivedMessage = usAlice.transformReceiving(aliceSessionID, sentMessage);
if (!clearTextMessage.equals(receivedMessage))
fail();
// Send encrypted message. Test UTF-8 space characters.
clearTextMessage = "Oh really?! pouvons-nous parler en fran<61>ais?";
sentMessage = usAlice.transformSending(aliceSessionID, clearTextMessage);
// Receive encrypted message.
receivedMessage = usBob.transformReceiving(bobSessionID, sentMessage);
if (!clearTextMessage.equals(receivedMessage))
fail();
}
private void endSession() {
usBob.endSession(bobSessionID);
usAlice.endSession(aliceSessionID);
if (usBob.getSessionStatus(bobSessionID) != SessionStatus.PLAINTEXT || usAlice.getSessionStatus(aliceSessionID) != SessionStatus.PLAINTEXT)
fail("Failed to end session.");
}
}

View File

@ -1,4 +1,4 @@
package org.jivesoftware.spark.ui;
package org.jivesoftware.spark.otrplug.impl;
import java.io.BufferedInputStream;
import java.io.File;

View File

@ -1,4 +1,4 @@
package org.jivesoftware.spark.otrplug;
package org.jivesoftware.spark.otrplug.impl;
import java.awt.Color;
import java.security.KeyPair;
@ -7,6 +7,7 @@ import java.security.KeyPair;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.otrplug.OTRManager;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
import net.java.otr4j.OtrEngineHost;

View File

@ -1,4 +1,4 @@
package org.jivesoftware.spark.ui;
package org.jivesoftware.spark.otrplug.impl;
import java.awt.Color;
import java.awt.event.ActionEvent;
@ -9,12 +9,13 @@ import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.RolloverButton;
import org.jivesoftware.spark.otrplug.OTREngineHost;
import org.jivesoftware.spark.otrplug.OTRManager;
import org.jivesoftware.spark.otrplug.OTRProperties;
import org.jivesoftware.spark.otrplug.OTRResources;
import org.jivesoftware.spark.otrplug.ui.OTRConnectionPanel;
import org.jivesoftware.spark.otrplug.util.OTRProperties;
import org.jivesoftware.spark.otrplug.util.OTRResources;
import org.jivesoftware.spark.ui.ChatRoomButton;
import org.jivesoftware.spark.ui.MessageEventListener;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
import net.java.otr4j.OtrEngineHost;
@ -35,6 +36,7 @@ public class OTRSession {
private OtrEngineImpl _engine;
private OTRManager _manager = OTRManager.getInstance();
final ChatRoomButton _otrButton = new ChatRoomButton();
private OTRConnectionPanel _conPanel;
private boolean _OtrEnabled = false;
public OTRSession(ChatRoomImpl chatroom, String myJID, String remoteJID) {
@ -60,6 +62,10 @@ public class OTRSession {
}
private void setUpMessageListener() {
_conPanel = new OTRConnectionPanel(_chatRoom);
_chatRoom.addMessageEventListener(new MessageEventListener() {
@Override
@ -93,7 +99,6 @@ public class OTRSession {
}
} else if (!_OtrEnabled)
{
System.out.println("bin drin");
String old = message.getBody();
message.setBody(null);
if (old.length() > 3 && old.substring(0, 4).equals("?OTR")) {
@ -142,7 +147,8 @@ public class OTRSession {
@Override
public void sessionStatusChanged(SessionID arg0) {
if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) {
_conPanel.sucessfullyCon();
String otrkey = _manager.getKeyManager().getRemoteFingerprint(_mySession);
if (otrkey == null) {
PublicKey pubkey = _engine.getRemotePublicKey(_mySession);
@ -161,15 +167,13 @@ public class OTRSession {
}
}
_chatRoom.getTranscriptWindow().insertNotificationMessage("From now on, your conversation is encrypted Remotekey: ", Color.gray);
_otrButton.setIcon(new ImageIcon(cl.getResource("otr_on.png")));
} else if (_engine.getSessionStatus(_mySession).equals(SessionStatus.FINISHED)) {
_chatRoom.getTranscriptWindow().insertNotificationMessage("From now on, your conversation is NOT encrypted", Color.gray);
_otrButton.setIcon(new ImageIcon(cl.getResource("otr_off.png")));
stopSession();
} else if (_engine.getSessionStatus(_mySession).equals(SessionStatus.PLAINTEXT)) {
_chatRoom.getTranscriptWindow().insertNotificationMessage("From now on, your conversation is NOT encrypted", Color.gray);
_otrButton.setIcon(new ImageIcon(cl.getResource("otr_off.png")));
stopSession();
}
}
@ -178,12 +182,13 @@ public class OTRSession {
}
public void startSession() {
_conPanel.tryToStart();
_engine.startSession(_mySession);
_chatRoom.getTranscriptWindow().insertNotificationMessage("Trying to establish OTR Connection", Color.green);
}
public void stopSession() {
if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) {
_conPanel.connectionClosed();
if (_engine.getSessionStatus(_mySession).equals(SessionStatus.ENCRYPTED)) {
final ClassLoader cl = getClass().getClassLoader();
_otrButton.setIcon(new ImageIcon(cl.getResource("otr_off.png")));
_engine.endSession(_mySession);

View File

@ -1,4 +1,4 @@
package org.jivesoftware.spark.ui;
package org.jivesoftware.spark.otrplug.pref;
import java.awt.BorderLayout;
@ -13,7 +13,8 @@ import javax.swing.JTable;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import org.jivesoftware.spark.otrplug.OTRResources;
import org.jivesoftware.spark.otrplug.util.OTRResources;
public class OTRKeyTable extends JPanel {

View File

@ -1,4 +1,4 @@
package org.jivesoftware.spark.ui;
package org.jivesoftware.spark.otrplug.pref;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
@ -21,10 +21,11 @@ import net.java.otr4j.session.SessionID;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.VerticalFlowLayout;
import org.jivesoftware.spark.otrplug.OTRManager;
import org.jivesoftware.spark.otrplug.OTRProperties;
import org.jivesoftware.spark.otrplug.OTRResources;
import org.jivesoftware.spark.otrplug.impl.MyOtrKeyManager;
import org.jivesoftware.spark.otrplug.util.OTRProperties;
import org.jivesoftware.spark.otrplug.util.OTRResources;
public class OTRPrefPanel extends JPanel {

View File

@ -1,10 +1,11 @@
package org.jivesoftware.spark.ui;
package org.jivesoftware.spark.otrplug.pref;
import javax.swing.Icon;
import javax.swing.JComponent;
import org.jivesoftware.spark.otrplug.OTRProperties;
import org.jivesoftware.spark.otrplug.OTRResources;
import org.jivesoftware.spark.otrplug.util.OTRProperties;
import org.jivesoftware.spark.otrplug.util.OTRResources;
import org.jivesoftware.spark.preference.Preference;
public class OTRPreferences implements Preference {

View File

@ -0,0 +1,141 @@
package org.jivesoftware.spark.otrplug.ui;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.spark.otrplug.OTRManager;
import org.jivesoftware.spark.otrplug.util.OTRResources;
import org.jivesoftware.spark.ui.TranscriptWindow;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
public class OTRConnectionPanel {
private ChatRoomImpl _chatRoom;
private JLabel _label;
private ImageIcon _icon;
private JPanel _conPanel;
private int _i;
private StyledDocument _doc;
private TranscriptWindow _transcriptWindow;
private JButton _retry;
private boolean _succesfull = false;
private boolean _waiting = false;
public OTRConnectionPanel(ChatRoomImpl chatroom) {
_chatRoom = chatroom;
_transcriptWindow = _chatRoom.getTranscriptWindow();
_doc = _transcriptWindow.getStyledDocument();
_retry = new JButton(OTRResources.getString("otr.retry"));
_retry.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
OTRManager.getInstance().startOtrWithUser(_chatRoom.getParticipantJID());
}
});
_retry.setVisible(false);
}
public void tryToStart() {
if (!_succesfull && !_waiting) {
renewPanel();
_icon.setImage(SparkRes.getImageIcon(SparkRes.BUSY_IMAGE).getImage());
_conPanel.setVisible(true);
_i = 10;
_label.setText(OTRResources.getString("otr.try.to.connect.for.seconds",_i));
Timer t = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
if (_i != 0 && !_succesfull) {
_waiting = true;
_label.setText(OTRResources.getString("otr.try.to.connect.for.seconds",_i));
decI();
} else if (!_succesfull) {
_waiting = true;
_icon.setImage(SparkRes.getImageIcon(SparkRes.SMALL_DELETE).getImage());
_label.setText(OTRResources.getString("otr.failed.to.establish",_i));
_retry.setVisible(true);
this.cancel();
} else {
this.cancel();
}
}
};
t.scheduleAtFixedRate(task, 0, 1000);
}
}
private void renewPanel() {
_conPanel = new JPanel(new GridBagLayout());
_label = new JLabel();
_icon = new ImageIcon();
_conPanel.add(new JLabel(_icon), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0));
_conPanel.add(_label, new GridBagConstraints(1, 0, 1, 1, 0.7, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 15, 0, 0), 0, 0));
_conPanel.add(_retry,new GridBagConstraints(2, 0, 1, 1, 2.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0));
Style style = _doc.addStyle("OTRStyle", null);
StyleConstants.setComponent(style, _conPanel);
try {
_doc.insertString(_doc.getLength(), "ignored text", style);
_doc.insertString(_doc.getLength(), "\n", null);
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void connectionClosed() {
if (_succesfull) {
renewPanel();
_succesfull = false;
_label.setText(OTRResources.getString("otr.disconnected"));
_icon.setImage(SparkRes.getImageIcon(SparkRes.SMALL_STOP).getImage());
_conPanel.setVisible(true);
}
}
private void decI() {
--_i;
}
public void sucessfullyCon() {
if(!_waiting)
renewPanel();
_retry.setVisible(false);
_conPanel.setVisible(true);
_succesfull = true;
_waiting = false;
_icon.setImage(SparkRes.getImageIcon(SparkRes.SMALL_CHECK).getImage());
_label.setText("Sucessfully Connected. Your conversation is encrypted");
}
}

View File

@ -1,5 +1,5 @@
package org.jivesoftware.spark.otrplug;
package org.jivesoftware.spark.otrplug.util;
import java.awt.Color;
import java.io.File;
@ -112,47 +112,8 @@ public class OTRProperties {
props.setProperty(property, "" + integer);
}
private void setColor(String property, Color color) {
props.setProperty(property, convertColor(color));
}
private Color getColor(String property, Color defaultcolor) {
try {
return convertString(props.getProperty(property));
} catch (Exception e) {
return defaultcolor;
}
}
public String getProperty(String property) {
return props.getProperty(property);
}
/**
* Converts a {@link String} matching xxx,xxx,xxx to a {@link Color}<br>
* where xxx is a number from 0 to 255
*
* @param s
* @return
*/
public static Color convertString(String s) throws Exception {
String[] arr = s.split(",");
return new Color(Integer.parseInt(arr[0]), Integer.parseInt(arr[1]),
Integer.parseInt(arr[2]));
}
/**
* Converts a {@link Color} to a {@link String} in this format:<br>
* <b>xxx,xxx,xxx</b> <br>
* where xxx is a number from 0 to 255
*
* @param color
* @return
*/
public static String convertColor(Color color) {
return color.getRed() + "," + color.getGreen() + "," + color.getBlue();
}
}

View File

@ -1,4 +1,4 @@
package org.jivesoftware.spark.otrplug;
package org.jivesoftware.spark.otrplug.util;
import java.text.MessageFormat;
import java.util.PropertyResourceBundle;

View File

@ -22,3 +22,9 @@ otr.table.public.key = Public key
otr.key.verified = Verified
#OTR Panel in Chat
otr.retry = Retry
otr.try.to.connect.for.seconds = Trying to establish an OTR session. {0}s remaining...
otr.failed.to.establish = Failed to establish OTR session. Timeout.
otr.successfull = OTR successfully establish. Messages will be encrypted.
otr.disconnected = OTR session closed. Messages are no longer encrypted.