add incomplete otr code

Thu, 26 Dec 2024 12:29:05 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 26 Dec 2024 12:29:05 +0100
changeset 1
42d0d099492b
parent 0
f3095cda599e
child 2
94c6a715fa44

add incomplete otr code

src/main/java/de/unixwork/im/ConversationFrame.java file | annotate | diff | comparison | revisions
src/main/java/de/unixwork/im/OTR.java file | annotate | diff | comparison | revisions
src/main/java/de/unixwork/im/Xmpp.java file | annotate | diff | comparison | revisions
src/main/java/de/unixwork/im/XmppSession.java file | annotate | diff | comparison | revisions
--- a/src/main/java/de/unixwork/im/ConversationFrame.java	Wed Dec 25 21:49:48 2024 +0100
+++ b/src/main/java/de/unixwork/im/ConversationFrame.java	Thu Dec 26 12:29:05 2024 +0100
@@ -15,10 +15,11 @@
     private JTextArea messageHistory;
     private JTextArea messageInput;
     private JButton sendButton;
-    private JButton topRightButton;
+    private JButton secureButton;
     private MessageSendListener messageSendListener;
-    private TopRightButtonListener topRightButtonListener;
-
+    
+    boolean isSecure = false;
+    
     public ConversationFrame(String xid) {
         this.xid = xid;
 
@@ -29,8 +30,8 @@
 
         // Top panel with top-right button
         JPanel topPanel = new JPanel(new BorderLayout());
-        topRightButton = new JButton("Insecure");
-        topPanel.add(topRightButton, BorderLayout.EAST);
+        secureButton = new JButton("Insecure");
+        topPanel.add(secureButton, BorderLayout.EAST);
         add(topPanel, BorderLayout.NORTH);
 
         // Split pane
@@ -77,11 +78,13 @@
             }
         });
 
-        topRightButton.addActionListener(new ActionListener() {
+        secureButton.addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent e) {
-                if (topRightButtonListener != null) {
-                    topRightButtonListener.onTopRightButtonClicked();
+                if(isSecure) {
+                    
+                } else {
+                    App.getInstance().getXmpp().startOTR(xid);
                 }
             }
         });
@@ -119,11 +122,6 @@
         this.messageSendListener = listener;
     }
 
-    // Method to set the top-right button listener
-    public void setTopRightButtonListener(TopRightButtonListener listener) {
-        this.topRightButtonListener = listener;
-    }
-
     // Trigger the message send callback
     private void triggerMessageSend() {
         if (messageSendListener != null) {
@@ -135,9 +133,4 @@
         }
     }
 
-    // Interface for top-right button callback
-    public interface TopRightButtonListener {
-        void onTopRightButtonClicked();
-    }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/unixwork/im/OTR.java	Thu Dec 26 12:29:05 2024 +0100
@@ -0,0 +1,160 @@
+package de.unixwork.im;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.java.otr4j.OtrEngineHost;
+import net.java.otr4j.OtrException;
+import net.java.otr4j.OtrPolicy;
+import net.java.otr4j.OtrPolicyImpl;
+import net.java.otr4j.crypto.OtrCryptoEngineImpl;
+import net.java.otr4j.crypto.OtrCryptoException;
+import net.java.otr4j.session.FragmenterInstructions;
+import net.java.otr4j.session.InstanceTag;
+import net.java.otr4j.session.SessionID;
+
+public class OTR implements OtrEngineHost {
+    private final Xmpp xmpp;
+    
+    // Map to store key pairs for each session
+    private final Map<SessionID, KeyPair> keyPairCache = new HashMap<>();
+    
+    public OTR(Xmpp xmpp) {
+        this.xmpp = xmpp;
+    }
+    
+    @Override
+    public void injectMessage(SessionID sid, String string) throws OtrException {
+        System.out.println("inject " + string);
+        xmpp.send(sid.getUserID(), string);
+    }
+
+    @Override
+    public void unreadableMessageReceived(SessionID sid) throws OtrException {
+        // TODO: send error to App
+    }
+
+    @Override
+    public void unencryptedMessageReceived(SessionID sid, String string) throws OtrException {
+        // TODO: send error to App
+    }
+
+    @Override
+    public void showError(SessionID sid, String string) throws OtrException {
+        System.out.println("showError " + string);
+    }
+
+    @Override
+    public void smpError(SessionID sid, int i, boolean bln) throws OtrException {
+        System.out.println("smpError");
+    }
+
+    @Override
+    public void smpAborted(SessionID sid) throws OtrException {
+        
+    }
+
+    @Override
+    public void finishedSessionMessage(SessionID sid, String string) throws OtrException {
+        System.out.println("finishedSessionMessage: " + sid);
+    }
+
+    @Override
+    public void requireEncryptedMessage(SessionID sid, String string) throws OtrException {
+        System.out.println("requireEncryptedMessage");
+    }
+
+    @Override
+    public OtrPolicy getSessionPolicy(SessionID sid) {
+        return new OtrPolicyImpl(OtrPolicy.ALLOW_V2 | OtrPolicy.ALLOW_V3 | OtrPolicy.OPPORTUNISTIC);
+    }
+
+    @Override
+    public FragmenterInstructions getFragmenterInstructions(SessionID sid) {
+        return new FragmenterInstructions(4096, 131072);
+    }
+
+    @Override
+    public KeyPair getLocalKeyPair(SessionID sid) throws OtrException {
+        // Check if a key pair already exists for the session
+        if (keyPairCache.containsKey(sid)) {
+            return keyPairCache.get(sid);
+        }
+
+        // Generate a new key pair
+        KeyPair keyPair = generateKeyPair();
+
+        // Cache the key pair for this session
+        keyPairCache.put(sid, keyPair);
+
+        return keyPair;
+    }
+    
+        // Helper method to generate a new key pair
+    private KeyPair generateKeyPair() {
+        try {
+            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA"); // Use DSA for OTR
+            keyPairGenerator.initialize(1024); // OTR uses 1024-bit keys
+            return keyPairGenerator.generateKeyPair();
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("Error generating key pair", e);
+        }
+    }
+
+    @Override
+    public byte[] getLocalFingerprintRaw(SessionID sid) {
+        // code from DummyClient: https://github.com/jitsi/otr4j/blob/master/src/test/java/net/java/otr4j/session/DummyClient.java
+        try {
+            return new OtrCryptoEngineImpl()
+                            .getFingerprintRaw(getLocalKeyPair(sid)
+                                            .getPublic());
+            } catch (OtrCryptoException e) {
+                e.printStackTrace();
+            } catch (OtrException ex) {
+            Logger.getLogger(OTR.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        return null;
+    }
+
+    @Override
+    public void askForSecret(SessionID sid, InstanceTag it, String string) {
+        System.out.println("askForSecret " + sid);
+    }
+
+    @Override
+    public void verify(SessionID sid, String string, boolean bln) {
+        System.out.println("verify");
+    }
+
+    @Override
+    public void unverify(SessionID sid, String string) {
+        System.out.println("unverify");
+    }
+
+    @Override
+    public String getReplyForUnreadableMessage(SessionID sid) {
+        return "Message unreadable";
+    }
+
+    @Override
+    public String getFallbackMessage(SessionID sid) {
+        return "error";
+    }
+
+    @Override
+    public void messageFromAnotherInstanceReceived(SessionID sid) {
+        System.out.println("messageFromAnotherInstanceReceived");
+    }
+
+    @Override
+    public void multipleInstancesDetected(SessionID sid) {
+        System.out.println("multipleInstancesDeteced");
+    }
+    
+}
--- a/src/main/java/de/unixwork/im/Xmpp.java	Wed Dec 25 21:49:48 2024 +0100
+++ b/src/main/java/de/unixwork/im/Xmpp.java	Thu Dec 26 12:29:05 2024 +0100
@@ -8,6 +8,16 @@
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import net.java.otr4j.OtrException;
+import net.java.otr4j.OtrPolicy;
+import net.java.otr4j.OtrPolicyImpl;
+import net.java.otr4j.OtrSessionManager;
+import net.java.otr4j.OtrSessionManagerImpl;
+import net.java.otr4j.session.InstanceTag;
+import net.java.otr4j.session.Session;
+import net.java.otr4j.session.SessionID;
+import net.java.otr4j.session.SessionImpl;
+import net.java.otr4j.session.TLV;
 import org.jivesoftware.smack.ConnectionConfiguration;
 import org.jivesoftware.smack.SmackException;
 import org.jivesoftware.smack.XMPPException;
@@ -25,11 +35,40 @@
     
     private XMPPTCPConnection connection = null;
     
+    private final OTR otr;
+    
+    private final OtrSessionManager otrSM;
+    
     // BlockingQueue for event-driven communication
     private final BlockingQueue<XmppEvent> eventQueue = new LinkedBlockingQueue<>();
     
     public Xmpp(XMPPTCPConnectionConfiguration xmppConfig) {
         config = xmppConfig;
+        otr = new OTR(this);
+        otrSM = new OtrSessionManagerImpl(otr);
+        
+    }
+    
+    public OTR getOTR() {
+        return otr;
+    }
+    
+    public OtrSessionManager getOtrSM() {
+        return otrSM;
+    }
+    
+    public void startOTR(String xid) {
+        String account = config.getUsername() + "@" + config.getHostString() + "/IM5";
+        SessionID sid = new SessionID(account, xid, "xmpp");
+        
+        Session session = new SessionImpl(sid, otr);
+        String[] outgoingMessage;
+        try {
+            session.startSession();
+        } catch (OtrException ex) {
+            Logger.getLogger(Xmpp.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        
     }
     
     // Method to send a message (this will be called from another thread)
@@ -42,12 +81,15 @@
         }
     }
     
+    public void send(String to, String message) {
+        sendMessage(to, message, false);
+    }
+    
     private void connect() throws SmackException, IOException, XMPPException, InterruptedException {
         connection = new XMPPTCPConnection(config);
         connection.setUseStreamManagement(false);
         connection.connect();
         connection.login();
-        
     }
     
     public List<RosterEntry> getRosterItems() throws SmackException.NotLoggedInException, SmackException.NotConnectedException, InterruptedException {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/unixwork/im/XmppSession.java	Thu Dec 26 12:29:05 2024 +0100
@@ -0,0 +1,30 @@
+package de.unixwork.im;
+
+import net.java.otr4j.crypto.OtrCryptoEngine;
+import net.java.otr4j.crypto.OtrCryptoEngineImpl;
+
+public class XmppSession {
+    private String xid;
+    private String resource;
+    
+    
+    private boolean isSecure = false;
+    
+    public XmppSession(String xid, String resource) {
+        this.xid = xid;
+        this.resource = resource;
+    }
+    
+    public void startOtr(Xmpp xmpp) {
+        
+        
+    }
+    
+    public void endOtr(Xmpp xmpp) {
+        
+    }
+    
+    public boolean isSecure() {
+        return isSecure;
+    }
+}

mercurial