--- a/app/build.gradle Sun Mar 15 18:57:24 2015 +0100
+++ b/app/build.gradle Sun Mar 15 20:41:17 2015 +0100
@@ -26,7 +26,8 @@
}
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ compile 'org.jitsi:org.otr4j:0.22'
}
apply from: "$project.rootDir/tools/android-checkstyle.gradle"
Binary file app/libs/lcrypto-jdk16-146-20110415.jar has changed
--- a/app/src/main/java/com/beem/project/beem/otr/BeemOtrManager.java Sun Mar 15 18:57:24 2015 +0100
+++ b/app/src/main/java/com/beem/project/beem/otr/BeemOtrManager.java Sun Mar 15 20:41:17 2015 +0100
@@ -31,14 +31,14 @@
import java.util.HashMap;
import java.util.Map;
-import net.java.otr4j.OtrEngine;
import net.java.otr4j.OtrEngineHost;
-import net.java.otr4j.OtrEngineImpl;
import net.java.otr4j.OtrEngineListener;
import net.java.otr4j.OtrException;
import net.java.otr4j.OtrKeyManagerImpl;
import net.java.otr4j.OtrPolicy;
import net.java.otr4j.OtrPolicyImpl;
+import net.java.otr4j.session.FragmenterInstructions;
+import net.java.otr4j.session.InstanceTag;
import net.java.otr4j.session.SessionID;
import net.java.otr4j.session.SessionStatus;
import android.util.Log;
@@ -53,7 +53,7 @@
private static final String TAG = "BeemOtrEngineHostImpl";
private static BeemOtrManager INSTANCE;
//We will have a global policy for Beem as long as we won't need to modify the policy per chat.
- private static final OtrPolicy mGlobalPolicy = new OtrPolicyImpl(OtrPolicy.ALLOW_V2 | OtrPolicy.ERROR_START_AKE);
+ private static final OtrPolicy mGlobalPolicy = new OtrPolicyImpl(OtrPolicy.ALLOW_V2 | OtrPolicy.ALLOW_V3 | OtrPolicy.ERROR_START_AKE);
private OtrEngine mOtrEngine;
private OtrKeyManagerImpl mOtrKeyManager;
@@ -65,8 +65,7 @@
* Private constructor prevents instantiation from other classes.
*/
private BeemOtrManager() {
- mOtrEngine = new OtrEngineImpl(this);
- mOtrEngine.addOtrEngineListener(new BeemOtrListener());
+ mOtrEngine = new OtrEngine(this, new BeemOtrListener());
try {
mOtrKeyManager = new OtrKeyManagerImpl("/sdcard/beem.keystore");
} catch (IOException e) {
@@ -125,7 +124,7 @@
* @param sessionId the current otr session
*/
public void verifyRemoteFingerprint(final SessionID sessionId) {
- mOtrKeyManager.verify(sessionId);
+ verify(sessionId, null, true);
}
/**
@@ -133,7 +132,7 @@
* @param sessionId the current otr session
*/
public void unverifyRemoteFingerprint(final SessionID sessionId) {
- mOtrKeyManager.unverify(sessionId);
+ unverify(sessionId, null);
}
/**
@@ -152,8 +151,13 @@
}
@Override
- public void showWarning(SessionID sessionID, String warning) {
- Log.d(TAG, "Warning for " + sessionID + " : " + warning);
+ public void unreadableMessageReceived(SessionID sessionID) throws OtrException {
+
+ }
+
+ @Override
+ public void unencryptedMessageReceived(SessionID sessionID, String msg) throws OtrException {
+ mOtrEngine.endSession(sessionID);
}
@Override
@@ -162,12 +166,78 @@
}
@Override
+ public void smpError(SessionID sessionID, int tlvType, boolean cheated) throws OtrException {
+ Log.d(TAG, "SmpError for " + sessionID);
+ }
+
+ @Override
+ public void smpAborted(SessionID sessionID) throws OtrException {
+ Log.d(TAG, "SmpAborted for " + sessionID);
+ }
+
+ @Override
+ public void finishedSessionMessage(SessionID sessionID, String msgText) throws OtrException {
+
+ }
+
+ @Override
+ public void requireEncryptedMessage(SessionID sessionID, String msgText) throws OtrException {
+
+ }
+
+ @Override
public OtrPolicy getSessionPolicy(SessionID sessionID) {
return mGlobalPolicy;
}
@Override
- public KeyPair getKeyPair(SessionID sessionID) {
+ public FragmenterInstructions getFragmenterInstructions(SessionID sessionID) {
+ return null;
+ }
+
+
+ @Override
+ public byte[] getLocalFingerprintRaw(SessionID sessionID) {
+ return mOtrKeyManager.getLocalFingerprintRaw(sessionID);
+ }
+
+ @Override
+ public void askForSecret(SessionID sessionID, InstanceTag receiverTag, String question) {
+
+ }
+
+ @Override
+ public void verify(SessionID sessionID, String fingerprint, boolean approved) {
+ mOtrKeyManager.verify(sessionID);
+ }
+
+ @Override
+ public void unverify(SessionID sessionID, String fingerprint) {
+ mOtrKeyManager.unverify(sessionID);
+ }
+
+ @Override
+ public String getReplyForUnreadableMessage(SessionID sessionID) {
+ return null;
+ }
+
+ @Override
+ public String getFallbackMessage(SessionID sessionID) {
+ return null;
+ }
+
+ @Override
+ public void messageFromAnotherInstanceReceived(SessionID sessionID) {
+
+ }
+
+ @Override
+ public void multipleInstancesDetected(SessionID sessionID) {
+
+ }
+
+ @Override
+ public KeyPair getLocalKeyPair(SessionID sessionID) throws OtrException {
KeyPair kp = mOtrKeyManager.loadLocalKeyPair(sessionID);
if (kp != null)
@@ -206,5 +276,15 @@
}
}
}
+
+ @Override
+ public void multipleInstancesDetected(SessionID sessionID) {
+
+ }
+
+ @Override
+ public void outgoingSessionChanged(SessionID sessionID) {
+
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/src/main/java/com/beem/project/beem/otr/OtrEngine.java Sun Mar 15 20:41:17 2015 +0100
@@ -0,0 +1,75 @@
+
+package com.beem.project.beem.otr;
+
+import net.java.otr4j.OtrEngineHost;
+import net.java.otr4j.OtrEngineListener;
+import net.java.otr4j.OtrException;
+import net.java.otr4j.session.Session;
+import net.java.otr4j.session.SessionID;
+import net.java.otr4j.session.SessionImpl;
+import net.java.otr4j.session.SessionStatus;
+
+import java.security.PublicKey;
+import java.util.Hashtable;
+import java.util.Map;
+
+public class OtrEngine {
+
+ public OtrEngine(OtrEngineHost host, OtrEngineListener listener) {
+ this.host = host;
+ this.listener = listener;
+ }
+
+ private OtrEngineHost host;
+ private Map<SessionID, Session> sessions;
+
+ private Session getSession(SessionID sessionID) {
+
+ if (sessionID == null || sessionID.equals(SessionID.Empty))
+ throw new IllegalArgumentException();
+
+ if (sessions == null)
+ sessions = new Hashtable<SessionID, Session>();
+
+ if (!sessions.containsKey(sessionID)) {
+ Session session = new SessionImpl(sessionID, host);
+ sessions.put(sessionID, session);
+
+ session.addOtrEngineListener(listener);
+ return session;
+ } else
+ return sessions.get(sessionID);
+ }
+
+ public SessionStatus getSessionStatus(SessionID sessionID) {
+ return this.getSession(sessionID).getSessionStatus();
+ }
+
+ public String transformReceiving(SessionID sessionID, String msgText)
+ throws OtrException {
+ return this.getSession(sessionID).transformReceiving(msgText);
+ }
+
+ public String[] transformSending(SessionID sessionID, String msgText)
+ throws OtrException {
+ return this.getSession(sessionID).transformSending(msgText, null);
+ }
+
+ public void endSession(SessionID sessionID) throws OtrException {
+ this.getSession(sessionID).endSession();
+ }
+
+ public void startSession(SessionID sessionID) throws OtrException {
+ this.getSession(sessionID).startSession();
+ }
+
+ public void refreshSession(SessionID sessionID) throws OtrException {
+ this.getSession(sessionID).refreshSession();
+ }
+
+ public PublicKey getRemotePublicKey(SessionID sessionID) {
+ return this.getSession(sessionID).getRemotePublicKey();
+ }
+
+ private final OtrEngineListener listener;
+}
--- a/app/src/main/java/com/beem/project/beem/service/BeemChatManager.java Sun Mar 15 18:57:24 2015 +0100
+++ b/app/src/main/java/com/beem/project/beem/service/BeemChatManager.java Sun Mar 15 20:41:17 2015 +0100
@@ -397,7 +397,7 @@
return;
}
- if (Status.getStatusFromPresence(presence) >= Status.CONTACT_STATUS_DISCONNECT) {
+ if (Status.getStatusFromPresence(presence) <= Status.CONTACT_STATUS_DISCONNECT) {
try {
mChats.get(key).localEndOtrSession();
} catch (OtrException e) {
--- a/app/src/main/java/com/beem/project/beem/service/ChatAdapter.java Sun Mar 15 18:57:24 2015 +0100
+++ b/app/src/main/java/com/beem/project/beem/service/ChatAdapter.java Sun Mar 15 20:41:17 2015 +0100
@@ -332,10 +332,15 @@
if (mOtrSessionId != null && unencrypted != null && unencrypted.getBody() != null) {
try {
- String body = BeemOtrManager.getInstance().getOtrManager()
+
+ String[] bodies = BeemOtrManager.getInstance().getOtrManager()
.transformSending(mOtrSessionId, unencrypted.getBody());
+ StringBuilder concatBody = new StringBuilder();
+ for(String body: bodies) {
+ concatBody.append(body);
+ }
Message result = new Message(unencrypted.getTo(), unencrypted.getType());
- result.setBody(body);
+ result.setBody(concatBody.toString());
return result;
} catch (OtrException e) {
Log.e(TAG, "OTR: Unable to encrypt message", e);
--- a/app/src/main/java/net/java/otr4j/OtrEngine.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-package net.java.otr4j;
-
-import java.security.PublicKey;
-
-import net.java.otr4j.session.SessionID;
-import net.java.otr4j.session.SessionStatus;
-
-/**
- *
- * @author George Politis
- *
- */
-public interface OtrEngine {
-
- /**
- *
- * @param sessionID
- * The session identifier.
- * @param content
- * The message content to be transformed.
- * @return The transformed message content.
- * @throws OtrException
- */
- public abstract String transformReceiving(SessionID sessionID,
- String content) throws OtrException;
-
- /**
- *
- * @param sessionID
- * The session identifier.
- * @param content
- * The message content to be transformed.
- * @return The transformed message content.
- * @throws OtrException
- */
- public abstract String transformSending(SessionID sessionID, String content) throws OtrException;
-
- /**
- * Starts an Off-the-Record session, if there is no active one.
- *
- * @param sessionID
- * The session identifier.
- * @throws OtrException
- */
- public abstract void startSession(SessionID sessionID) throws OtrException;
-
- /**
- * Ends the Off-the-Record session, if exists.
- *
- * @param sessionID
- * The session identifier.
- * @throws OtrException
- */
- public abstract void endSession(SessionID sessionID) throws OtrException;
-
- /**
- * Stops/Starts the Off-the-Record session.
- *
- * @param sessionID
- * The session identifier.
- * @throws OtrException
- */
- public abstract void refreshSession(SessionID sessionID) throws OtrException;
-
- /**
- *
- * @param sessionID
- * The session identifier.
- * @return The status of an Off-the-Record session.
- */
- public abstract SessionStatus getSessionStatus(SessionID sessionID);
-
- /**
- *
- * @param sessionID
- * The session identifier.
- * @return The remote public key.
- */
- public abstract PublicKey getRemotePublicKey(SessionID sessionID);
-
- public abstract void addOtrEngineListener(OtrEngineListener l);
-
- public abstract void removeOtrEngineListener(OtrEngineListener l);
-}
--- a/app/src/main/java/net/java/otr4j/OtrEngineHost.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j;
-
-import java.security.KeyPair;
-
-import net.java.otr4j.session.SessionID;
-
-/**
- *
- * This interface should be implemented by the host application. It is required
- * for otr4j to work properly.
- *
- * @author George Politis
- *
- */
-public abstract interface OtrEngineHost {
- public abstract void injectMessage(SessionID sessionID, String msg);
-
- public abstract void showWarning(SessionID sessionID, String warning);
-
- public abstract void showError(SessionID sessionID, String error);
-
- public abstract OtrPolicy getSessionPolicy(SessionID sessionID);
-
- public abstract KeyPair getKeyPair(SessionID sessionID);
-}
--- a/app/src/main/java/net/java/otr4j/OtrEngineImpl.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * otr4j, the open source java otr librar
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package net.java.otr4j;
-
-import java.security.PublicKey;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Vector;
-
-import net.java.otr4j.session.Session;
-import net.java.otr4j.session.SessionID;
-import net.java.otr4j.session.SessionImpl;
-import net.java.otr4j.session.SessionStatus;
-
-/**
- *
- * @author George Politis
- *
- */
-public class OtrEngineImpl implements OtrEngine {
-
- public OtrEngineImpl(OtrEngineHost host) {
- if (host == null)
- throw new IllegalArgumentException("OtrEgineHost is required.");
-
- this.setHost(host);
- }
-
- private OtrEngineHost host;
- private Map<SessionID, Session> sessions;
-
- private Session getSession(SessionID sessionID) {
-
- if (sessionID == null || sessionID.equals(SessionID.Empty))
- throw new IllegalArgumentException();
-
- if (sessions == null)
- sessions = new Hashtable<SessionID, Session>();
-
- if (!sessions.containsKey(sessionID)) {
- Session session = new SessionImpl(sessionID, getHost());
- sessions.put(sessionID, session);
-
- session.addOtrEngineListener(new OtrEngineListener() {
-
- public void sessionStatusChanged(SessionID sessionID) {
- for (OtrEngineListener l : listeners)
- l.sessionStatusChanged(sessionID);
- }
- });
- return session;
- } else
- return sessions.get(sessionID);
- }
-
- public SessionStatus getSessionStatus(SessionID sessionID) {
- return this.getSession(sessionID).getSessionStatus();
- }
-
- public String transformReceiving(SessionID sessionID, String msgText)
- throws OtrException {
- return this.getSession(sessionID).transformReceiving(msgText);
- }
-
- public String transformSending(SessionID sessionID, String msgText)
- throws OtrException {
- return this.getSession(sessionID).transformSending(msgText, null);
- }
-
- public void endSession(SessionID sessionID) throws OtrException {
- this.getSession(sessionID).endSession();
- }
-
- public void startSession(SessionID sessionID) throws OtrException {
- this.getSession(sessionID).startSession();
- }
-
- private void setHost(OtrEngineHost host) {
- this.host = host;
- }
-
- private OtrEngineHost getHost() {
- return host;
- }
-
- public void refreshSession(SessionID sessionID) throws OtrException {
- this.getSession(sessionID).refreshSession();
- }
-
- public PublicKey getRemotePublicKey(SessionID sessionID) {
- return this.getSession(sessionID).getRemotePublicKey();
- }
-
- private List<OtrEngineListener> listeners = new Vector<OtrEngineListener>();
-
- public void addOtrEngineListener(OtrEngineListener l) {
- synchronized (listeners) {
- if (!listeners.contains(l))
- listeners.add(l);
- }
- }
-
- public void removeOtrEngineListener(OtrEngineListener l) {
- synchronized (listeners) {
- listeners.remove(l);
- }
- }
-}
--- a/app/src/main/java/net/java/otr4j/OtrEngineListener.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-package net.java.otr4j;
-
-import net.java.otr4j.session.SessionID;
-
-/**
- * This interface should be implemented by the host application. It notifies
- * about session status changes.
- *
- * @author George Politis
- *
- */
-public interface OtrEngineListener {
- public abstract void sessionStatusChanged(SessionID sessionID);
-}
--- a/app/src/main/java/net/java/otr4j/OtrException.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-package net.java.otr4j;
-
-
-public class OtrException extends Exception {
- private static final long serialVersionUID = 1L;
-
- public OtrException(Exception e){
- super(e);
- }
-}
--- a/app/src/main/java/net/java/otr4j/OtrKeyManager.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-package net.java.otr4j;
-
-import java.security.KeyPair;
-import java.security.PublicKey;
-
-import net.java.otr4j.session.SessionID;
-
-public abstract interface OtrKeyManager {
-
- public abstract void addListener(OtrKeyManagerListener l);
-
- public abstract void removeListener(OtrKeyManagerListener l);
-
- public abstract void verify(SessionID sessionID);
-
- public abstract void unverify(SessionID sessionID);
-
- public abstract boolean isVerified(SessionID sessionID);
-
- public abstract String getRemoteFingerprint(SessionID sessionID);
-
- public abstract String getLocalFingerprint(SessionID sessionID);
-
- public abstract void savePublicKey(SessionID sessionID, PublicKey pubKey);
-
- public abstract PublicKey loadRemotePublicKey(SessionID sessionID);
-
- public abstract KeyPair loadLocalKeyPair(SessionID sessionID);
-
- public abstract void generateLocalKeyPair(SessionID sessionID);
-}
--- a/app/src/main/java/net/java/otr4j/OtrKeyManagerImpl.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,304 +0,0 @@
-package net.java.otr4j;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.List;
-import java.util.Properties;
-import java.util.Vector;
-
-import org.bouncycastle2.util.encoders.Base64;
-
-import net.java.otr4j.crypto.OtrCryptoEngineImpl;
-import net.java.otr4j.crypto.OtrCryptoException;
-import net.java.otr4j.session.SessionID;
-
-public class OtrKeyManagerImpl implements OtrKeyManager {
-
- private OtrKeyManagerStore store;
-
- public OtrKeyManagerImpl(OtrKeyManagerStore store) {
- this.store = store;
- }
-
- class DefaultPropertiesStore implements OtrKeyManagerStore {
- private final Properties properties = new Properties();
- private String filepath;
-
- public DefaultPropertiesStore(String filepath) throws IOException {
- if (filepath == null || filepath.length() < 1)
- throw new IllegalArgumentException();
- this.filepath = filepath;
- properties.clear();
-
- InputStream in = new BufferedInputStream(new FileInputStream(
- getConfigurationFile()));
- try {
- properties.load(in);
- } finally {
- in.close();
- }
- }
-
- private File getConfigurationFile() throws IOException {
- File configFile = new File(filepath);
- if (!configFile.exists())
- configFile.createNewFile();
- return configFile;
- }
-
- public void setProperty(String id, boolean value) {
- properties.setProperty(id, "true");
- try {
- this.store();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private void store() throws FileNotFoundException, IOException {
- OutputStream out = new FileOutputStream(getConfigurationFile());
- properties.store(out, null);
- out.close();
- }
-
- public void setProperty(String id, byte[] value) {
- properties.setProperty(id, new String(Base64.encode(value)));
- try {
- this.store();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void removeProperty(String id) {
- properties.remove(id);
-
- }
-
- public byte[] getPropertyBytes(String id) {
- String value = properties.getProperty(id);
- if (value == null)
- return null;
- return Base64.decode(value);
- }
-
- public boolean getPropertyBoolean(String id, boolean defaultValue) {
- try {
- return Boolean.valueOf(properties.get(id).toString());
- } catch (Exception e) {
- return defaultValue;
- }
- }
- }
-
- public OtrKeyManagerImpl(String filepath) throws IOException {
- this.store = new DefaultPropertiesStore(filepath);
- }
-
- private List<OtrKeyManagerListener> listeners = new Vector<OtrKeyManagerListener>();
-
- public void addListener(OtrKeyManagerListener l) {
- synchronized (listeners) {
- if (!listeners.contains(l))
- listeners.add(l);
- }
- }
-
- public void removeListener(OtrKeyManagerListener l) {
- synchronized (listeners) {
- listeners.remove(l);
- }
- }
-
- public void generateLocalKeyPair(SessionID sessionID) {
- if (sessionID == null)
- return;
-
- String accountID = sessionID.getAccountID();
- KeyPair keyPair;
- try {
- keyPair = KeyPairGenerator.getInstance("DSA").genKeyPair();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- return;
- }
-
- // Store Public Key.
- PublicKey pubKey = keyPair.getPublic();
- X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKey
- .getEncoded());
-
- this.store.setProperty(accountID + ".publicKey", x509EncodedKeySpec
- .getEncoded());
-
- // Store Private Key.
- PrivateKey privKey = keyPair.getPrivate();
- PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
- privKey.getEncoded());
-
- this.store.setProperty(accountID + ".privateKey", pkcs8EncodedKeySpec
- .getEncoded());
- }
-
- public String getLocalFingerprint(SessionID sessionID) {
- KeyPair keyPair = loadLocalKeyPair(sessionID);
-
- if (keyPair == null)
- return null;
-
- PublicKey pubKey = keyPair.getPublic();
-
- try {
- return new OtrCryptoEngineImpl().getFingerprint(pubKey);
- } catch (OtrCryptoException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- public String getRemoteFingerprint(SessionID sessionID) {
- PublicKey remotePublicKey = loadRemotePublicKey(sessionID);
- if (remotePublicKey == null)
- return null;
- try {
- return new OtrCryptoEngineImpl().getFingerprint(remotePublicKey);
- } catch (OtrCryptoException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- public boolean isVerified(SessionID sessionID) {
- if (sessionID == null)
- return false;
-
- return this.store.getPropertyBoolean(sessionID.getUserID()
- + ".publicKey.verified", false);
- }
-
- public KeyPair loadLocalKeyPair(SessionID sessionID) {
- if (sessionID == null)
- return null;
-
- String accountID = sessionID.getAccountID();
- // Load Private Key.
- byte[] b64PrivKey = this.store.getPropertyBytes(accountID
- + ".privateKey");
- if (b64PrivKey == null)
- return null;
-
- PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(b64PrivKey);
-
- // Load Public Key.
- byte[] b64PubKey = this.store
- .getPropertyBytes(accountID + ".publicKey");
- if (b64PubKey == null)
- return null;
-
- X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey);
-
- PublicKey publicKey;
- PrivateKey privateKey;
-
- // Generate KeyPair.
- KeyFactory keyFactory;
- try {
- keyFactory = KeyFactory.getInstance("DSA");
- publicKey = keyFactory.generatePublic(publicKeySpec);
- privateKey = keyFactory.generatePrivate(privateKeySpec);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- return null;
- } catch (InvalidKeySpecException e) {
- e.printStackTrace();
- return null;
- }
-
- return new KeyPair(publicKey, privateKey);
- }
-
- public PublicKey loadRemotePublicKey(SessionID sessionID) {
- if (sessionID == null)
- return null;
-
- String userID = sessionID.getUserID();
-
- byte[] b64PubKey = this.store.getPropertyBytes(userID + ".publicKey");
- if (b64PubKey == null)
- return null;
-
- X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey);
-
- // Generate KeyPair.
- KeyFactory keyFactory;
- try {
- keyFactory = KeyFactory.getInstance("DSA");
- return keyFactory.generatePublic(publicKeySpec);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- return null;
- } catch (InvalidKeySpecException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- public void savePublicKey(SessionID sessionID, PublicKey pubKey) {
- if (sessionID == null)
- return;
-
- X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKey
- .getEncoded());
-
- String userID = sessionID.getUserID();
- this.store.setProperty(userID + ".publicKey", x509EncodedKeySpec
- .getEncoded());
-
- this.store.removeProperty(userID + ".publicKey.verified");
- }
-
- public void unverify(SessionID sessionID) {
- if (sessionID == null)
- return;
-
- if (!isVerified(sessionID))
- return;
-
- this.store
- .removeProperty(sessionID.getUserID() + ".publicKey.verified");
-
- for (OtrKeyManagerListener l : listeners)
- l.verificationStatusChanged(sessionID);
-
- }
-
- public void verify(SessionID sessionID) {
- if (sessionID == null)
- return;
-
- if (this.isVerified(sessionID))
- return;
-
- this.store.setProperty(sessionID.getUserID() + ".publicKey.verified",
- true);
-
- for (OtrKeyManagerListener l : listeners)
- l.verificationStatusChanged(sessionID);
- }
-
-}
--- a/app/src/main/java/net/java/otr4j/OtrKeyManagerListener.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-package net.java.otr4j;
-
-import net.java.otr4j.session.SessionID;
-
-public interface OtrKeyManagerListener {
- public abstract void verificationStatusChanged(SessionID session);
-}
--- a/app/src/main/java/net/java/otr4j/OtrKeyManagerStore.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-package net.java.otr4j;
-
-public interface OtrKeyManagerStore {
- public abstract byte[] getPropertyBytes(String id);
-
- public abstract boolean getPropertyBoolean(String id, boolean defaultValue);
-
- public abstract void setProperty(String id, byte[] value);
-
- public abstract void setProperty(String id, boolean value);
-
- public abstract void removeProperty(String id);
-}
--- a/app/src/main/java/net/java/otr4j/OtrPolicy.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j;
-
-/**
- *
- * @author George Politis
- *
- */
-public interface OtrPolicy {
-
- public static final int ALLOW_V1 = 0x01;
- public static final int ALLOW_V2 = 0x02;
- public static final int REQUIRE_ENCRYPTION = 0x04;
- public static final int SEND_WHITESPACE_TAG = 0x08;
- public static final int WHITESPACE_START_AKE = 0x10;
- public static final int ERROR_START_AKE = 0x20;
- public static final int VERSION_MASK = (ALLOW_V1 | ALLOW_V2);
-
- // The four old version 1 policies correspond to the following combinations
- // of flags (adding an allowance for version 2 of the protocol):
-
- public static final int NEVER = 0x00;
- public static final int OPPORTUNISTIC = (ALLOW_V1 | ALLOW_V2
- | SEND_WHITESPACE_TAG | WHITESPACE_START_AKE | ERROR_START_AKE);
- public static final int OTRL_POLICY_MANUAL = (ALLOW_V1 | ALLOW_V2);
- public static final int OTRL_POLICY_ALWAYS = (ALLOW_V1 | ALLOW_V2
- | REQUIRE_ENCRYPTION | WHITESPACE_START_AKE | ERROR_START_AKE);
- public static final int OTRL_POLICY_DEFAULT = OPPORTUNISTIC;
-
- public abstract boolean getAllowV1();
-
- public abstract boolean getAllowV2();
-
- public abstract boolean getRequireEncryption();
-
- public abstract boolean getSendWhitespaceTag();
-
- public abstract boolean getWhitespaceStartAKE();
-
- public abstract boolean getErrorStartAKE();
-
- public abstract int getPolicy();
-
- public abstract void setAllowV1(boolean value);
-
- public abstract void setAllowV2(boolean value);
-
- public abstract void setRequireEncryption(boolean value);
-
- public abstract void setSendWhitespaceTag(boolean value);
-
- public abstract void setWhitespaceStartAKE(boolean value);
-
- public abstract void setErrorStartAKE(boolean value);
-
- public abstract void setEnableAlways(boolean value);
-
- public abstract boolean getEnableAlways();
-
- public abstract void setEnableManual(boolean value);
-
- public abstract boolean getEnableManual();
-}
--- a/app/src/main/java/net/java/otr4j/OtrPolicyImpl.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-package net.java.otr4j;
-
-public class OtrPolicyImpl implements OtrPolicy {
-
- public OtrPolicyImpl() {
- this.setPolicy(NEVER);
- }
-
- public OtrPolicyImpl(int policy) {
- this.setPolicy(policy);
- }
-
- private int policy;
-
- public int getPolicy() {
- return policy;
- }
-
- private void setPolicy(int policy) {
- this.policy = policy;
- }
-
- public boolean getAllowV1() {
- return (policy & OtrPolicy.ALLOW_V1) != 0;
- }
-
- public boolean getAllowV2() {
- return (policy & OtrPolicy.ALLOW_V2) != 0;
- }
-
- public boolean getErrorStartAKE() {
- return (policy & OtrPolicy.ERROR_START_AKE) != 0;
- }
-
- public boolean getRequireEncryption() {
- return getEnableManual()
- && (policy & OtrPolicy.REQUIRE_ENCRYPTION) != 0;
- }
-
- public boolean getSendWhitespaceTag() {
- return (policy & OtrPolicy.SEND_WHITESPACE_TAG) != 0;
- }
-
- public boolean getWhitespaceStartAKE() {
- return (policy & OtrPolicy.WHITESPACE_START_AKE) != 0;
- }
-
- public void setAllowV1(boolean value) {
- if (value)
- policy |= ALLOW_V1;
- else
- policy &= ~ALLOW_V1;
- }
-
- public void setAllowV2(boolean value) {
- if (value)
- policy |= ALLOW_V2;
- else
- policy &= ~ALLOW_V2;
- }
-
- public void setErrorStartAKE(boolean value) {
- if (value)
- policy |= ERROR_START_AKE;
- else
- policy &= ~ERROR_START_AKE;
- }
-
- public void setRequireEncryption(boolean value) {
- if (value)
- policy |= REQUIRE_ENCRYPTION;
- else
- policy &= ~REQUIRE_ENCRYPTION;
- }
-
- public void setSendWhitespaceTag(boolean value) {
- if (value)
- policy |= SEND_WHITESPACE_TAG;
- else
- policy &= ~SEND_WHITESPACE_TAG;
- }
-
- public void setWhitespaceStartAKE(boolean value) {
- if (value)
- policy |= WHITESPACE_START_AKE;
- else
- policy &= ~WHITESPACE_START_AKE;
- }
-
- public boolean getEnableAlways() {
- return getEnableManual() && getErrorStartAKE()
- && getSendWhitespaceTag() && getWhitespaceStartAKE();
- }
-
- public void setEnableAlways(boolean value) {
- if (value)
- setEnableManual(true);
-
- setErrorStartAKE(value);
- setSendWhitespaceTag(value);
- setWhitespaceStartAKE(value);
-
- }
-
- public boolean getEnableManual() {
- return getAllowV1() && getAllowV2();
- }
-
- public void setEnableManual(boolean value) {
- setAllowV1(value);
- setAllowV2(value);
- }
-
- public boolean equals(Object obj) {
- if (obj == this)
- return true;
- if (obj == null || obj.getClass() != this.getClass())
- return false;
-
- OtrPolicy policy = (OtrPolicy) obj;
-
- return policy.getPolicy() == this.getPolicy();
- }
-
- public int hashCode() {
- return this.getPolicy();
- }
-}
--- a/app/src/main/java/net/java/otr4j/crypto/OtrCryptoEngine.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package net.java.otr4j.crypto;
-
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-/**
- *
- * @author George Politis
- *
- */
-public interface OtrCryptoEngine {
-
- public static final String MODULUS_TEXT = "00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF";
- public static final BigInteger MODULUS = new BigInteger(MODULUS_TEXT, 16);
- public static final BigInteger BIGINTEGER_TWO = BigInteger.valueOf(2);
- public static final BigInteger MODULUS_MINUS_TWO = MODULUS
- .subtract(BIGINTEGER_TWO);
-
- public static String GENERATOR_TEXT = "2";
- public static BigInteger GENERATOR = new BigInteger(GENERATOR_TEXT, 10);
-
- public static final int AES_KEY_BYTE_LENGTH = 16;
- public static final int SHA256_HMAC_KEY_BYTE_LENGTH = 32;
- public static final int DH_PRIVATE_KEY_MINIMUM_BIT_LENGTH = 320;
- public static final byte[] ZERO_CTR = new byte[] { 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00 };
-
- public static final int DSA_PUB_TYPE = 0;
-
- public abstract KeyPair generateDHKeyPair() throws OtrCryptoException;
-
- public abstract DHPublicKey getDHPublicKey(byte[] mpiBytes)
- throws OtrCryptoException;
-
- public abstract DHPublicKey getDHPublicKey(BigInteger mpi)
- throws OtrCryptoException;
-
- public abstract byte[] sha256Hmac(byte[] b, byte[] key)
- throws OtrCryptoException;
-
- public abstract byte[] sha256Hmac(byte[] b, byte[] key, int length)
- throws OtrCryptoException;
-
- public abstract byte[] sha1Hmac(byte[] b, byte[] key, int length)
- throws OtrCryptoException;
-
- public abstract byte[] sha256Hmac160(byte[] b, byte[] key)
- throws OtrCryptoException;
-
- public abstract byte[] sha256Hash(byte[] b) throws OtrCryptoException;
-
- public abstract byte[] sha1Hash(byte[] b) throws OtrCryptoException;
-
- public abstract byte[] aesDecrypt(byte[] key, byte[] ctr, byte[] b)
- throws OtrCryptoException;
-
- public abstract byte[] aesEncrypt(byte[] key, byte[] ctr, byte[] b)
- throws OtrCryptoException;
-
- public abstract BigInteger generateSecret(PrivateKey privKey,
- PublicKey pubKey) throws OtrCryptoException;
-
- public abstract byte[] sign(byte[] b, PrivateKey privatekey)
- throws OtrCryptoException;
-
- public abstract boolean verify(byte[] b, PublicKey pubKey, byte[] rs)
- throws OtrCryptoException;
-
- public abstract String getFingerprint(PublicKey pubKey)
- throws OtrCryptoException;
-}
--- a/app/src/main/java/net/java/otr4j/crypto/OtrCryptoEngineImpl.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.crypto;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.interfaces.DSAParams;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-
-import javax.crypto.KeyAgreement;
-import javax.crypto.interfaces.DHPrivateKey;
-import javax.crypto.interfaces.DHPublicKey;
-import javax.crypto.spec.DHPrivateKeySpec;
-import javax.crypto.spec.DHPublicKeySpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import net.java.otr4j.io.SerializationUtils;
-
-import org.bouncycastle2.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle2.crypto.BufferedBlockCipher;
-import org.bouncycastle2.crypto.engines.AESFastEngine;
-import org.bouncycastle2.crypto.generators.DHKeyPairGenerator;
-import org.bouncycastle2.crypto.modes.SICBlockCipher;
-import org.bouncycastle2.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle2.crypto.params.DHParameters;
-import org.bouncycastle2.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle2.crypto.params.DHPublicKeyParameters;
-import org.bouncycastle2.crypto.params.DSAParameters;
-import org.bouncycastle2.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle2.crypto.params.DSAPublicKeyParameters;
-import org.bouncycastle2.crypto.params.KeyParameter;
-import org.bouncycastle2.crypto.params.ParametersWithIV;
-import org.bouncycastle2.crypto.signers.DSASigner;
-import org.bouncycastle2.util.BigIntegers;
-
-/**
- *
- * @author George Politis
- *
- */
-public class OtrCryptoEngineImpl implements OtrCryptoEngine {
-
- public KeyPair generateDHKeyPair() throws OtrCryptoException {
-
- // Generate a AsymmetricCipherKeyPair using BC.
- DHParameters dhParams = new DHParameters(MODULUS, GENERATOR, null,
- DH_PRIVATE_KEY_MINIMUM_BIT_LENGTH);
- DHKeyGenerationParameters params = new DHKeyGenerationParameters(
- new SecureRandom(), dhParams);
- DHKeyPairGenerator kpGen = new DHKeyPairGenerator();
-
- kpGen.init(params);
- AsymmetricCipherKeyPair pair = kpGen.generateKeyPair();
-
- // Convert this AsymmetricCipherKeyPair to a standard JCE KeyPair.
- DHPublicKeyParameters pub = (DHPublicKeyParameters) pair.getPublic();
- DHPrivateKeyParameters priv = (DHPrivateKeyParameters) pair
- .getPrivate();
-
- try {
- KeyFactory keyFac = KeyFactory.getInstance("DH");
-
- DHPublicKeySpec pubKeySpecs = new DHPublicKeySpec(pub.getY(),
- MODULUS, GENERATOR);
- DHPublicKey pubKey = (DHPublicKey) keyFac
- .generatePublic(pubKeySpecs);
-
- DHParameters dhParameters = priv.getParameters();
- DHPrivateKeySpec privKeySpecs = new DHPrivateKeySpec(priv.getX(),
- dhParameters.getP(), dhParameters.getG());
- DHPrivateKey privKey = (DHPrivateKey) keyFac
- .generatePrivate(privKeySpecs);
-
- return new KeyPair(pubKey, privKey);
- } catch (Exception e) {
- throw new OtrCryptoException(e);
- }
- }
-
- public DHPublicKey getDHPublicKey(byte[] mpiBytes)
- throws OtrCryptoException {
- return getDHPublicKey(new BigInteger(mpiBytes));
- }
-
- public DHPublicKey getDHPublicKey(BigInteger mpi) throws OtrCryptoException {
- DHPublicKeySpec pubKeySpecs = new DHPublicKeySpec(mpi, MODULUS,
- GENERATOR);
- try {
- KeyFactory keyFac = KeyFactory.getInstance("DH");
- return (DHPublicKey) keyFac.generatePublic(pubKeySpecs);
- } catch (Exception e) {
- throw new OtrCryptoException(e);
- }
- }
-
- public byte[] sha256Hmac(byte[] b, byte[] key) throws OtrCryptoException {
- return this.sha256Hmac(b, key, 0);
- }
-
- public byte[] sha256Hmac(byte[] b, byte[] key, int length)
- throws OtrCryptoException {
-
- SecretKeySpec keyspec = new SecretKeySpec(key, "HmacSHA256");
- javax.crypto.Mac mac;
- try {
- mac = javax.crypto.Mac.getInstance("HmacSHA256");
- } catch (NoSuchAlgorithmException e) {
- throw new OtrCryptoException(e);
- }
- try {
- mac.init(keyspec);
- } catch (InvalidKeyException e) {
- throw new OtrCryptoException(e);
- }
-
- byte[] macBytes = mac.doFinal(b);
-
- if (length > 0) {
- byte[] bytes = new byte[length];
- ByteBuffer buff = ByteBuffer.wrap(macBytes);
- buff.get(bytes);
- return bytes;
- } else {
- return macBytes;
- }
- }
-
- public byte[] sha1Hmac(byte[] b, byte[] key, int length)
- throws OtrCryptoException {
-
- try {
- SecretKeySpec keyspec = new SecretKeySpec(key, "HmacSHA1");
- javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
- mac.init(keyspec);
-
- byte[] macBytes = mac.doFinal(b);
-
- if (length > 0) {
- byte[] bytes = new byte[length];
- ByteBuffer buff = ByteBuffer.wrap(macBytes);
- buff.get(bytes);
- return bytes;
- } else {
- return macBytes;
- }
- } catch (Exception e) {
- throw new OtrCryptoException(e);
- }
- }
-
- public byte[] sha256Hmac160(byte[] b, byte[] key) throws OtrCryptoException {
- return sha256Hmac(b, key, 20);
- }
-
- public byte[] sha256Hash(byte[] b) throws OtrCryptoException {
- try {
- MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
- sha256.update(b, 0, b.length);
- return sha256.digest();
- } catch (Exception e) {
- throw new OtrCryptoException(e);
- }
- }
-
- public byte[] sha1Hash(byte[] b) throws OtrCryptoException {
- try {
- MessageDigest sha256 = MessageDigest.getInstance("SHA-1");
- sha256.update(b, 0, b.length);
- return sha256.digest();
- } catch (Exception e) {
- throw new OtrCryptoException(e);
- }
- }
-
- public byte[] aesDecrypt(byte[] key, byte[] ctr, byte[] b)
- throws OtrCryptoException {
-
- AESFastEngine aesDec = new AESFastEngine();
- SICBlockCipher sicAesDec = new SICBlockCipher(aesDec);
- BufferedBlockCipher bufSicAesDec = new BufferedBlockCipher(sicAesDec);
-
- // Create initial counter value 0.
- if (ctr == null)
- ctr = ZERO_CTR;
- bufSicAesDec.init(false, new ParametersWithIV(new KeyParameter(key),
- ctr));
- byte[] aesOutLwDec = new byte[b.length];
- int done = bufSicAesDec.processBytes(b, 0, b.length, aesOutLwDec, 0);
- try {
- bufSicAesDec.doFinal(aesOutLwDec, done);
- } catch (Exception e) {
- throw new OtrCryptoException(e);
- }
-
- return aesOutLwDec;
- }
-
- public byte[] aesEncrypt(byte[] key, byte[] ctr, byte[] b)
- throws OtrCryptoException {
-
- AESFastEngine aesEnc = new AESFastEngine();
- SICBlockCipher sicAesEnc = new SICBlockCipher(aesEnc);
- BufferedBlockCipher bufSicAesEnc = new BufferedBlockCipher(sicAesEnc);
-
- // Create initial counter value 0.
- if (ctr == null)
- ctr = ZERO_CTR;
- bufSicAesEnc.init(true,
- new ParametersWithIV(new KeyParameter(key), ctr));
- byte[] aesOutLwEnc = new byte[b.length];
- int done = bufSicAesEnc.processBytes(b, 0, b.length, aesOutLwEnc, 0);
- try {
- bufSicAesEnc.doFinal(aesOutLwEnc, done);
- } catch (Exception e) {
- throw new OtrCryptoException(e);
- }
- return aesOutLwEnc;
- }
-
- public BigInteger generateSecret(PrivateKey privKey, PublicKey pubKey)
- throws OtrCryptoException {
- try {
- KeyAgreement ka = KeyAgreement.getInstance("DH");
- ka.init(privKey);
- ka.doPhase(pubKey, true);
- byte[] sb = ka.generateSecret();
- BigInteger s = new BigInteger(1, sb);
- return s;
-
- } catch (Exception e) {
- throw new OtrCryptoException(e);
- }
- }
-
- public byte[] sign(byte[] b, PrivateKey privatekey)
- throws OtrCryptoException {
-
- if (!(privatekey instanceof DSAPrivateKey))
- throw new IllegalArgumentException();
-
- DSAParams dsaParams = ((DSAPrivateKey) privatekey).getParams();
- DSAParameters bcDSAParameters = new DSAParameters(dsaParams.getP(),
- dsaParams.getQ(), dsaParams.getG());
-
- DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) privatekey;
- DSAPrivateKeyParameters bcDSAPrivateKeyParms = new DSAPrivateKeyParameters(
- dsaPrivateKey.getX(), bcDSAParameters);
-
- DSASigner dsaSigner = new DSASigner();
- dsaSigner.init(true, bcDSAPrivateKeyParms);
-
- BigInteger q = dsaParams.getQ();
-
- // Ian: Note that if you can get the standard DSA implementation you're
- // using to not hash its input, you should be able to pass it ((256-bit
- // value) mod q), (rather than truncating the 256-bit value) and all
- // should be well.
- // ref: Interop problems with libotr - DSA signature
- BigInteger bmpi = new BigInteger(1, b);
- BigInteger[] rs = dsaSigner.generateSignature(BigIntegers
- .asUnsignedByteArray(bmpi.mod(q)));
-
- int siglen = q.bitLength() / 4;
- int rslen = siglen / 2;
- byte[] rb = BigIntegers.asUnsignedByteArray(rs[0]);
- byte[] sb = BigIntegers.asUnsignedByteArray(rs[1]);
-
- // Create the final signature array, padded with zeros if necessary.
- byte[] sig = new byte[siglen];
- Boolean writeR = false;
- Boolean writeS = false;
- for (int i = 0; i < siglen; i++) {
- if (i < rslen) {
- if (!writeR)
- writeR = rb.length >= rslen - i;
- sig[i] = (writeR) ? rb[i] : (byte) 0x0;
- } else {
- int j = i - rslen; // Rebase.
- if (!writeS)
- writeS = sb.length >= rslen - j;
- sig[i] = (writeS) ? sb[j] : (byte) 0x0;
- }
- }
- return sig;
- }
-
- public boolean verify(byte[] b, PublicKey pubKey, byte[] rs)
- throws OtrCryptoException {
-
- if (!(pubKey instanceof DSAPublicKey))
- throw new IllegalArgumentException();
-
- DSAParams dsaParams = ((DSAPublicKey) pubKey).getParams();
- int qlen = dsaParams.getQ().bitLength() / 8;
- ByteBuffer buff = ByteBuffer.wrap(rs);
- byte[] r = new byte[qlen];
- buff.get(r);
- byte[] s = new byte[qlen];
- buff.get(s);
- return verify(b, pubKey, r, s);
- }
-
- private Boolean verify(byte[] b, PublicKey pubKey, byte[] r, byte[] s)
- throws OtrCryptoException {
- Boolean result = verify(b, pubKey, new BigInteger(1, r),
- new BigInteger(1, s));
- return result;
- }
-
- private Boolean verify(byte[] b, PublicKey pubKey, BigInteger r,
- BigInteger s) throws OtrCryptoException {
-
- if (!(pubKey instanceof DSAPublicKey))
- throw new IllegalArgumentException();
-
- DSAParams dsaParams = ((DSAPublicKey) pubKey).getParams();
-
- BigInteger q = dsaParams.getQ();
- DSAParameters bcDSAParams = new DSAParameters(dsaParams.getP(), q,
- dsaParams.getG());
-
- DSAPublicKey dsaPrivateKey = (DSAPublicKey) pubKey;
- DSAPublicKeyParameters dsaPrivParms = new DSAPublicKeyParameters(
- dsaPrivateKey.getY(), bcDSAParams);
-
- // Ian: Note that if you can get the standard DSA implementation you're
- // using to not hash its input, you should be able to pass it ((256-bit
- // value) mod q), (rather than truncating the 256-bit value) and all
- // should be well.
- // ref: Interop problems with libotr - DSA signature
- DSASigner dsaSigner = new DSASigner();
- dsaSigner.init(false, dsaPrivParms);
-
- BigInteger bmpi = new BigInteger(1, b);
- Boolean result = dsaSigner.verifySignature(BigIntegers
- .asUnsignedByteArray(bmpi.mod(q)), r, s);
- return result;
- }
-
- public String getFingerprint(PublicKey pubKey) throws OtrCryptoException {
- byte[] b;
- try {
- byte[] bRemotePubKey = SerializationUtils.writePublicKey(pubKey);
-
- if (pubKey.getAlgorithm().equals("DSA")) {
- byte[] trimmed = new byte[bRemotePubKey.length - 2];
- System.arraycopy(bRemotePubKey, 2, trimmed, 0, trimmed.length);
- b = new OtrCryptoEngineImpl().sha1Hash(trimmed);
- } else
- b = new OtrCryptoEngineImpl().sha1Hash(bRemotePubKey);
- } catch (IOException e) {
- throw new OtrCryptoException(e);
- }
- return this.byteArrayToHexString(b);
- }
-
- private String byteArrayToHexString(byte in[]) {
- byte ch = 0x00;
- int i = 0;
- if (in == null || in.length <= 0)
- return null;
- String pseudo[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
- "A", "B", "C", "D", "E", "F" };
- StringBuffer out = new StringBuffer(in.length * 2);
- while (i < in.length) {
- ch = (byte) (in[i] & 0xF0);
- ch = (byte) (ch >>> 4);
- ch = (byte) (ch & 0x0F);
- out.append(pseudo[(int) ch]);
- ch = (byte) (in[i] & 0x0F);
- out.append(pseudo[(int) ch]);
- i++;
- }
-
- String rslt = new String(out);
- return rslt;
-
- }
-}
--- a/app/src/main/java/net/java/otr4j/crypto/OtrCryptoException.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-package net.java.otr4j.crypto;
-
-import net.java.otr4j.OtrException;
-
-@SuppressWarnings("serial")
-public class OtrCryptoException extends OtrException {
-
- public OtrCryptoException(Exception e) {
- super(e);
- }
-
-}
--- a/app/src/main/java/net/java/otr4j/io/OtrInputStream.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-package net.java.otr4j.io;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
-import java.security.PublicKey;
-import java.security.interfaces.DSAParams;
-import java.security.interfaces.DSAPublicKey;
-import java.security.spec.DSAPublicKeySpec;
-import java.security.spec.InvalidKeySpecException;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-import net.java.otr4j.crypto.OtrCryptoEngineImpl;
-import net.java.otr4j.io.messages.SignatureX;
-
-public class OtrInputStream extends FilterInputStream implements
- SerializationConstants {
-
- public OtrInputStream(InputStream in) {
- super(in);
- }
-
- private int readNumber(int length) throws IOException {
- byte[] b = new byte[length];
- read(b);
-
- int value = 0;
- for (int i = 0; i < b.length; i++) {
- int shift = (b.length - 1 - i) * 8;
- value += (b[i] & 0x000000FF) << shift;
- }
-
- return value;
- }
-
- public int readByte() throws IOException {
- return readNumber(TYPE_LEN_BYTE);
- }
-
- public int readInt() throws IOException {
- return readNumber(TYPE_LEN_INT);
- }
-
- public int readShort() throws IOException {
- return readNumber(TYPE_LEN_SHORT);
- }
-
- public byte[] readCtr() throws IOException {
- byte[] b = new byte[TYPE_LEN_CTR];
- read(b);
- return b;
- }
-
- public byte[] readMac() throws IOException {
- byte[] b = new byte[TYPE_LEN_MAC];
- read(b);
- return b;
- }
-
- public BigInteger readBigInt() throws IOException {
- byte[] b = readData();
- return new BigInteger(1, b);
- }
-
- public byte[] readData() throws IOException {
- int dataLen = readNumber(DATA_LEN);
- byte[] b = new byte[dataLen];
- read(b);
- return b;
- }
-
- public PublicKey readPublicKey() throws IOException {
- int type = readShort();
- switch (type) {
- case 0:
- BigInteger p = readBigInt();
- BigInteger q = readBigInt();
- BigInteger g = readBigInt();
- BigInteger y = readBigInt();
- DSAPublicKeySpec keySpec = new DSAPublicKeySpec(y, p, q, g);
- KeyFactory keyFactory;
- try {
- keyFactory = KeyFactory.getInstance("DSA");
- } catch (NoSuchAlgorithmException e) {
- throw new IOException();
- }
- try {
- return keyFactory.generatePublic(keySpec);
- } catch (InvalidKeySpecException e) {
- throw new IOException();
- }
- default:
- throw new UnsupportedOperationException();
- }
- }
-
- public DHPublicKey readDHPublicKey() throws IOException {
- BigInteger gyMpi = readBigInt();
- try {
- return new OtrCryptoEngineImpl().getDHPublicKey(gyMpi);
- } catch (Exception ex) {
- throw new IOException();
- }
- }
-
- public byte[] readTlvData() throws IOException {
- int len = readNumber(TYPE_LEN_BYTE);
-
- byte[] b = new byte[len];
- in.read(b);
- return b;
- }
-
- public byte[] readSignature(PublicKey pubKey) throws IOException {
- if (!pubKey.getAlgorithm().equals("DSA"))
- throw new UnsupportedOperationException();
-
- DSAPublicKey dsaPubKey = (DSAPublicKey) pubKey;
- DSAParams dsaParams = dsaPubKey.getParams();
- byte[] sig = new byte[dsaParams.getQ().bitLength() / 4];
- read(sig);
- return sig;
- }
-
- public SignatureX readMysteriousX() throws IOException {
- PublicKey pubKey = readPublicKey();
- int dhKeyID = readInt();
- byte[] sig = readSignature(pubKey);
- return new SignatureX(pubKey, dhKeyID, sig);
- }
-}
--- a/app/src/main/java/net/java/otr4j/io/OtrOutputStream.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-package net.java.otr4j.io;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.math.BigInteger;
-import java.security.PublicKey;
-import java.security.interfaces.DSAParams;
-import java.security.interfaces.DSAPublicKey;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-import net.java.otr4j.io.messages.SignatureM;
-import net.java.otr4j.io.messages.MysteriousT;
-import net.java.otr4j.io.messages.SignatureX;
-
-import org.bouncycastle2.util.BigIntegers;
-
-public class OtrOutputStream extends FilterOutputStream implements
- SerializationConstants {
-
- public OtrOutputStream(OutputStream out) {
- super(out);
- }
-
- private void writeNumber(int value, int length) throws IOException {
- byte[] b = new byte[length];
- for (int i = 0; i < length; i++) {
- int offset = (b.length - 1 - i) * 8;
- b[i] = (byte) ((value >>> offset) & 0xFF);
- }
- write(b);
- }
-
- public void writeBigInt(BigInteger bi) throws IOException {
- byte[] b = BigIntegers.asUnsignedByteArray(bi);
- writeData(b);
- }
-
- public void writeByte(int b) throws IOException {
- writeNumber(b, TYPE_LEN_BYTE);
- }
-
- public void writeData(byte[] b) throws IOException {
- int len = (b == null || b.length < 0) ? 0 : b.length;
- writeNumber(len, DATA_LEN);
- if (len > 0)
- write(b);
- }
-
- public void writeInt(int i) throws IOException {
- writeNumber(i, TYPE_LEN_INT);
-
- }
-
- public void writeShort(int s) throws IOException {
- writeNumber(s, TYPE_LEN_SHORT);
-
- }
-
- public void writeMac(byte[] mac) throws IOException {
- if (mac == null || mac.length != TYPE_LEN_MAC)
- throw new IllegalArgumentException();
-
- write(mac);
- }
-
- public void writeCtr(byte[] ctr) throws IOException {
- if (ctr == null || ctr.length < 1)
- return;
-
- int i = 0;
- while (i < TYPE_LEN_CTR && i < ctr.length) {
- write(ctr[i]);
- i++;
- }
- }
-
- public void writeDHPublicKey(DHPublicKey dhPublicKey) throws IOException {
- byte[] b = BigIntegers.asUnsignedByteArray(dhPublicKey.getY());
- writeData(b);
- }
-
- public void writePublicKey(PublicKey pubKey) throws IOException {
- if (!(pubKey instanceof DSAPublicKey))
- throw new UnsupportedOperationException(
- "Key types other than DSA are not supported at the moment.");
-
- DSAPublicKey dsaKey = (DSAPublicKey) pubKey;
-
- writeShort(0);
-
- DSAParams dsaParams = dsaKey.getParams();
- writeBigInt(dsaParams.getP());
- writeBigInt(dsaParams.getQ());
- writeBigInt(dsaParams.getG());
- writeBigInt(dsaKey.getY());
-
- }
-
- public void writeTlvData(byte[] b) throws IOException {
- int len = (b == null || b.length < 0) ? 0 : b.length;
- writeNumber(len, TLV_LEN);
- if (len > 0)
- write(b);
- }
-
- public void writeSignature(byte[] signature, PublicKey pubKey)
- throws IOException {
- if (!pubKey.getAlgorithm().equals("DSA"))
- throw new UnsupportedOperationException();
- out.write(signature);
- }
-
- public void writeMysteriousX(SignatureX x) throws IOException {
- writePublicKey(x.longTermPublicKey);
- writeInt(x.dhKeyID);
- writeSignature(x.signature, x.longTermPublicKey);
- }
-
- public void writeMysteriousX(SignatureM m) throws IOException {
- writeBigInt(m.localPubKey.getY());
- writeBigInt(m.remotePubKey.getY());
- writePublicKey(m.localLongTermPubKey);
- writeInt(m.keyPairID);
- }
-
- public void writeMysteriousT(MysteriousT t) throws IOException {
- writeShort(t.protocolVersion);
- writeByte(t.messageType);
- writeByte(t.flags);
-
- writeInt(t.senderKeyID);
- writeInt(t.recipientKeyID);
- writeDHPublicKey(t.nextDH);
- writeCtr(t.ctr);
- writeData(t.encryptedMessage);
-
- }
-}
--- a/app/src/main/java/net/java/otr4j/io/SerializationConstants.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io;
-
-/**
- *
- * @author George Politis
- */
-public interface SerializationConstants {
-
- public static final String HEAD = "?OTR";
- public static final char HEAD_ENCODED = ':';
- public static final char HEAD_ERROR = ' ';
- public static final char HEAD_QUERY_Q = '?';
- public static final char HEAD_QUERY_V = 'v';
-
- public static final int TYPE_LEN_BYTE = 1;
- public static final int TYPE_LEN_SHORT = 2;
- public static final int TYPE_LEN_INT = 4;
- public static final int TYPE_LEN_MAC = 20;
- public static final int TYPE_LEN_CTR = 8;
-
- public static final int DATA_LEN = TYPE_LEN_INT;
- public static final int TLV_LEN = TYPE_LEN_SHORT;
-}
--- a/app/src/main/java/net/java/otr4j/io/SerializationUtils.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,341 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.math.BigInteger;
-import java.security.PublicKey;
-import java.util.List;
-import java.util.Vector;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-import org.bouncycastle2.util.encoders.Base64;
-
-import net.java.otr4j.io.messages.AbstractEncodedMessage;
-import net.java.otr4j.io.messages.AbstractMessage;
-import net.java.otr4j.io.messages.DHCommitMessage;
-import net.java.otr4j.io.messages.DHKeyMessage;
-import net.java.otr4j.io.messages.DataMessage;
-import net.java.otr4j.io.messages.ErrorMessage;
-import net.java.otr4j.io.messages.MysteriousT;
-import net.java.otr4j.io.messages.PlainTextMessage;
-import net.java.otr4j.io.messages.QueryMessage;
-import net.java.otr4j.io.messages.RevealSignatureMessage;
-import net.java.otr4j.io.messages.SignatureM;
-import net.java.otr4j.io.messages.SignatureMessage;
-import net.java.otr4j.io.messages.SignatureX;
-
-/**
- *
- * @author George Politis
- */
-public class SerializationUtils {
- // Mysterious X IO.
- public static SignatureX toMysteriousX(byte[] b) throws IOException {
- ByteArrayInputStream in = new ByteArrayInputStream(b);
- OtrInputStream ois = new OtrInputStream(in);
- SignatureX x = ois.readMysteriousX();
- ois.close();
- return x;
- }
-
- public static byte[] toByteArray(SignatureX x) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- OtrOutputStream oos = new OtrOutputStream(out);
- oos.writeMysteriousX(x);
- byte[] b = out.toByteArray();
- oos.close();
- return b;
- }
-
- // Mysterious M IO.
- public static byte[] toByteArray(SignatureM m) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- OtrOutputStream oos = new OtrOutputStream(out);
- oos.writeMysteriousX(m);
- byte[] b = out.toByteArray();
- oos.close();
- return b;
- }
-
- // Mysterious T IO.
- public static byte[] toByteArray(MysteriousT t) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- OtrOutputStream oos = new OtrOutputStream(out);
- oos.writeMysteriousT(t);
- byte[] b = out.toByteArray();
- oos.close();
- return b;
- }
-
- // Basic IO.
- public static byte[] writeData(byte[] b) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- OtrOutputStream oos = new OtrOutputStream(out);
- oos.writeData(b);
- byte[] otrb = out.toByteArray();
- oos.close();
- return otrb;
- }
-
- // BigInteger IO.
- public static byte[] writeMpi(BigInteger bigInt) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- OtrOutputStream oos = new OtrOutputStream(out);
- oos.writeBigInt(bigInt);
- byte[] b = out.toByteArray();
- oos.close();
- return b;
- }
-
- public static BigInteger readMpi(byte[] b) throws IOException {
- ByteArrayInputStream in = new ByteArrayInputStream(b);
- OtrInputStream ois = new OtrInputStream(in);
- BigInteger bigint = ois.readBigInt();
- ois.close();
- return bigint;
- }
-
- // Public Key IO.
- public static byte[] writePublicKey(PublicKey pubKey) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- OtrOutputStream oos = new OtrOutputStream(out);
- oos.writePublicKey(pubKey);
- byte[] b = out.toByteArray();
- oos.close();
- return b;
- }
-
- // Message IO.
- public static String toString(AbstractMessage m) throws IOException {
- StringWriter writer = new StringWriter();
- writer.write(SerializationConstants.HEAD);
-
- switch (m.messageType) {
- case AbstractMessage.MESSAGE_ERROR:
- ErrorMessage error = (ErrorMessage) m;
- writer.write(SerializationConstants.HEAD_ERROR);
- writer.write(error.error);
- break;
- case AbstractMessage.MESSAGE_PLAINTEXT:
- PlainTextMessage plaintxt = (PlainTextMessage) m;
- writer.write(plaintxt.cleanText);
- if (plaintxt.versions != null && plaintxt.versions.size() > 0) {
- writer.write(" \\t \\t\\t\\t\\t \\t \\t \\t ");
- for (int version : plaintxt.versions) {
- if (version == 1)
- writer.write(" \\t\\t \\t ");
-
- if (version == 2)
- writer.write(" \\t \\t \\t ");
- }
- }
- break;
- case AbstractMessage.MESSAGE_QUERY:
- QueryMessage query = (QueryMessage) m;
- if (query.versions.size() == 1 && query.versions.get(0) == 1) {
- writer.write(SerializationConstants.HEAD_QUERY_Q);
- } else {
- writer.write(SerializationConstants.HEAD_QUERY_V);
- for (int version : query.versions)
- writer.write(String.valueOf(version));
-
- writer.write(SerializationConstants.HEAD_QUERY_Q);
- }
- break;
- case AbstractEncodedMessage.MESSAGE_DHKEY:
- case AbstractEncodedMessage.MESSAGE_REVEALSIG:
- case AbstractEncodedMessage.MESSAGE_SIGNATURE:
- case AbstractEncodedMessage.MESSAGE_DH_COMMIT:
- case AbstractEncodedMessage.MESSAGE_DATA:
- ByteArrayOutputStream o = new ByteArrayOutputStream();
- OtrOutputStream s = new OtrOutputStream(o);
-
- switch (m.messageType) {
- case AbstractEncodedMessage.MESSAGE_DHKEY:
- DHKeyMessage dhkey = (DHKeyMessage) m;
- s.writeShort(dhkey.protocolVersion);
- s.writeByte(dhkey.messageType);
- s.writeDHPublicKey(dhkey.dhPublicKey);
- break;
- case AbstractEncodedMessage.MESSAGE_REVEALSIG:
- RevealSignatureMessage revealsig = (RevealSignatureMessage) m;
- s.writeShort(revealsig.protocolVersion);
- s.writeByte(revealsig.messageType);
- s.writeData(revealsig.revealedKey);
- s.writeData(revealsig.xEncrypted);
- s.writeMac(revealsig.xEncryptedMAC);
- break;
- case AbstractEncodedMessage.MESSAGE_SIGNATURE:
- SignatureMessage sig = (SignatureMessage) m;
- s.writeShort(sig.protocolVersion);
- s.writeByte(sig.messageType);
- s.writeData(sig.xEncrypted);
- s.writeMac(sig.xEncryptedMAC);
- break;
- case AbstractEncodedMessage.MESSAGE_DH_COMMIT:
- DHCommitMessage dhcommit = (DHCommitMessage) m;
- s.writeShort(dhcommit.protocolVersion);
- s.writeByte(dhcommit.messageType);
- s.writeData(dhcommit.dhPublicKeyEncrypted);
- s.writeData(dhcommit.dhPublicKeyHash);
- break;
- case AbstractEncodedMessage.MESSAGE_DATA:
- DataMessage data = (DataMessage) m;
- s.writeShort(data.protocolVersion);
- s.writeByte(data.messageType);
- s.writeByte(data.flags);
- s.writeInt(data.senderKeyID);
- s.writeInt(data.recipientKeyID);
- s.writeDHPublicKey(data.nextDH);
- s.writeCtr(data.ctr);
- s.writeData(data.encryptedMessage);
- s.writeMac(data.mac);
- s.writeData(data.oldMACKeys);
- break;
- }
-
- writer.write(SerializationConstants.HEAD_ENCODED);
- writer.write(new String(Base64.encode(o.toByteArray())));
- writer.write(".");
- break;
- default:
- throw new IOException("Illegal message type.");
- }
-
- return writer.toString();
- }
-
- static final Pattern patternWhitespace = Pattern
- .compile("( \\t \\t\\t\\t\\t \\t \\t \\t )( \\t\\t \\t )?( \\t \\t \\t )?");
-
- public static AbstractMessage toMessage(String s) throws IOException {
- if (s == null || s.length() <= 1)
- return null;
-
- if (s.indexOf(SerializationConstants.HEAD) != 0
- || s.length() <= SerializationConstants.HEAD.length()) {
- // Try to detect whitespace tag.
- final Matcher matcher = patternWhitespace.matcher(s);
-
- boolean v1 = false;
- boolean v2 = false;
- while (matcher.find()) {
- if (!v1 && matcher.start(2) > -1)
- v1 = true;
-
- if (!v2 && matcher.start(3) > -1)
- v2 = true;
-
- if (v1 && v2)
- break;
- }
-
- String cleanText = matcher.replaceAll("");
- List<Integer> versions;
- if (v1 && v2) {
- versions = new Vector<Integer>(2);
- versions.add(0, 1);
- versions.add(0, 2);
- } else if (v1) {
- versions = new Vector<Integer>(1);
- versions.add(0, 1);
- } else if (v2) {
- versions = new Vector<Integer>(1);
- versions.add(2);
- } else
- versions = null;
-
- return new PlainTextMessage(versions, cleanText);
- } else {
- char contentType = s.charAt(SerializationConstants.HEAD.length());
- String content = s
- .substring(SerializationConstants.HEAD.length() + 1);
- switch (contentType) {
- case SerializationConstants.HEAD_ENCODED:
- ByteArrayInputStream bin = new ByteArrayInputStream(Base64
- .decode(content.getBytes()));
- OtrInputStream otr = new OtrInputStream(bin);
- // We have an encoded message.
- int protocolVersion = otr.readShort();
- int messageType = otr.readByte();
- switch (messageType) {
- case AbstractEncodedMessage.MESSAGE_DATA:
- int flags = otr.readByte();
- int senderKeyID = otr.readInt();
- int recipientKeyID = otr.readInt();
- DHPublicKey nextDH = otr.readDHPublicKey();
- byte[] ctr = otr.readCtr();
- byte[] encryptedMessage = otr.readData();
- byte[] mac = otr.readMac();
- byte[] oldMacKeys = otr.readMac();
- return new DataMessage(protocolVersion, flags, senderKeyID,
- recipientKeyID, nextDH, ctr, encryptedMessage, mac,
- oldMacKeys);
- case AbstractEncodedMessage.MESSAGE_DH_COMMIT:
- byte[] dhPublicKeyEncrypted = otr.readData();
- byte[] dhPublicKeyHash = otr.readData();
- return new DHCommitMessage(protocolVersion,
- dhPublicKeyHash, dhPublicKeyEncrypted);
- case AbstractEncodedMessage.MESSAGE_DHKEY:
- DHPublicKey dhPublicKey = otr.readDHPublicKey();
- return new DHKeyMessage(protocolVersion, dhPublicKey);
- case AbstractEncodedMessage.MESSAGE_REVEALSIG: {
- byte[] revealedKey = otr.readData();
- byte[] xEncrypted = otr.readData();
- byte[] xEncryptedMac = otr.readMac();
- return new RevealSignatureMessage(protocolVersion,
- xEncrypted, xEncryptedMac, revealedKey);
- }
- case AbstractEncodedMessage.MESSAGE_SIGNATURE: {
- byte[] xEncryted = otr.readData();
- byte[] xEncryptedMac = otr.readMac();
- return new SignatureMessage(protocolVersion, xEncryted,
- xEncryptedMac);
- }
- default:
- throw new IOException("Illegal message type.");
- }
- case SerializationConstants.HEAD_ERROR:
- return new ErrorMessage(AbstractMessage.MESSAGE_ERROR, content);
- case SerializationConstants.HEAD_QUERY_V:
- case SerializationConstants.HEAD_QUERY_Q:
- List<Integer> versions = new Vector<Integer>();
- String versionString = null;
- if (SerializationConstants.HEAD_QUERY_Q == contentType) {
- versions.add(1);
- if (content.charAt(0) == 'v') {
- versionString = content.substring(1, content
- .indexOf('?'));
- }
- } else if (SerializationConstants.HEAD_QUERY_V == contentType) {
- versionString = content.substring(0, content.indexOf('?'));
- }
-
- if (versionString != null) {
- StringReader sr = new StringReader(versionString);
- int c;
- while ((c = sr.read()) != -1)
- if (!versions.contains(c))
- versions.add(Integer.parseInt(String
- .valueOf((char) c)));
- }
- QueryMessage query = new QueryMessage(versions);
- return query;
- default:
- throw new IOException("Uknown message type.");
- }
- }
- }
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/AbstractEncodedMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-/**
- *
- * @author George Politis
- */
-public abstract class AbstractEncodedMessage extends AbstractMessage {
- // Fields.
- public int protocolVersion;
-
- // Ctor.
- public AbstractEncodedMessage(int messageType, int protocolVersion) {
- super(messageType);
- this.protocolVersion = protocolVersion;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + protocolVersion;
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- AbstractEncodedMessage other = (AbstractEncodedMessage) obj;
- if (protocolVersion != other.protocolVersion)
- return false;
- return true;
- }
-
- // Encoded Message Types
- public static final int MESSAGE_DH_COMMIT = 0x02;
- public static final int MESSAGE_DATA = 0x03;
- public static final int MESSAGE_DHKEY = 0x0a;
- public static final int MESSAGE_REVEALSIG = 0x11;
- public static final int MESSAGE_SIGNATURE = 0x12;
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/AbstractMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-/**
- *
- * @author George Politis
- */
-public abstract class AbstractMessage {
- // Fields.
- public int messageType;
-
- // Ctor.
- public AbstractMessage(int messageType) {
- this.messageType = messageType;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + messageType;
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- AbstractMessage other = (AbstractMessage) obj;
- if (messageType != other.messageType)
- return false;
- return true;
- }
-
- // Unencoded
- public static final int MESSAGE_ERROR = 0xff;
- public static final int MESSAGE_QUERY = 0x100;
- public static final int MESSAGE_PLAINTEXT = 0x102;
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/DHCommitMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-import java.util.Arrays;
-
-/**
- *
- * @author George Politis
- */
-public class DHCommitMessage extends AbstractEncodedMessage {
-
- // Fields.
- public byte[] dhPublicKeyEncrypted;
- public byte[] dhPublicKeyHash;
-
- // Ctor.
- public DHCommitMessage(int protocolVersion, byte[] dhPublicKeyHash,
- byte[] dhPublicKeyEncrypted) {
- super(MESSAGE_DH_COMMIT, protocolVersion);
- this.dhPublicKeyEncrypted = dhPublicKeyEncrypted;
- this.dhPublicKeyHash = dhPublicKeyHash;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + Arrays.hashCode(dhPublicKeyEncrypted);
- result = prime * result + Arrays.hashCode(dhPublicKeyHash);
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- DHCommitMessage other = (DHCommitMessage) obj;
- if (!Arrays.equals(dhPublicKeyEncrypted, other.dhPublicKeyEncrypted))
- return false;
- if (!Arrays.equals(dhPublicKeyHash, other.dhPublicKeyHash))
- return false;
- return true;
- }
-
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/DHKeyMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-/**
- *
- * @author George Politis
- */
-public class DHKeyMessage extends AbstractEncodedMessage {
-
- // Fields.
- public DHPublicKey dhPublicKey;
-
- // Ctor.
- public DHKeyMessage(int protocolVersion, DHPublicKey dhPublicKey) {
- super(MESSAGE_DHKEY, protocolVersion);
- this.dhPublicKey = dhPublicKey;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- // TODO: Needs work.
- result = prime * result
- + ((dhPublicKey == null) ? 0 : dhPublicKey.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- DHKeyMessage other = (DHKeyMessage) obj;
- if (dhPublicKey == null) {
- if (other.dhPublicKey != null)
- return false;
- } else if (dhPublicKey.getY().compareTo(other.dhPublicKey.getY()) != 0)
- return false;
- return true;
- }
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/DataMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-import java.util.Arrays;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-/**
- *
- * @author George Politis
- */
-public class DataMessage extends AbstractEncodedMessage {
-
- // Fields.
- public byte[] mac;
- public byte[] oldMACKeys;
-
- public int flags;
- public int senderKeyID;
- public int recipientKeyID;
- public DHPublicKey nextDH;
- public byte[] ctr;
- public byte[] encryptedMessage;
-
- // Ctor.
- public DataMessage(int protocolVersion, int flags, int senderKeyID,
- int recipientKeyID, DHPublicKey nextDH, byte[] ctr,
- byte[] encryptedMessage, byte[] mac, byte[] oldMacKeys) {
- super(MESSAGE_DATA, protocolVersion);
-
- this.flags = flags;
- this.senderKeyID = senderKeyID;
- this.recipientKeyID = recipientKeyID;
- this.nextDH = nextDH;
- this.ctr = ctr;
- this.encryptedMessage = encryptedMessage;
- this.mac = mac;
- this.oldMACKeys = oldMacKeys;
- }
-
- public DataMessage(MysteriousT t, byte[] mac, byte[] oldMacKeys) {
- this(t.protocolVersion, t.flags, t.senderKeyID, t.recipientKeyID,
- t.nextDH, t.ctr, t.encryptedMessage, mac, oldMacKeys);
- }
-
- // Methods.
- public MysteriousT getT() {
- return new MysteriousT(protocolVersion, flags, senderKeyID,
- recipientKeyID, nextDH, ctr, encryptedMessage);
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + Arrays.hashCode(ctr);
- result = prime * result + Arrays.hashCode(encryptedMessage);
- result = prime * result + flags;
- result = prime * result + Arrays.hashCode(mac);
- // TODO: Needs work.
- result = prime * result + ((nextDH == null) ? 0 : nextDH.hashCode());
- result = prime * result + Arrays.hashCode(oldMACKeys);
- result = prime * result + recipientKeyID;
- result = prime * result + senderKeyID;
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- DataMessage other = (DataMessage) obj;
- if (!Arrays.equals(ctr, other.ctr))
- return false;
- if (!Arrays.equals(encryptedMessage, other.encryptedMessage))
- return false;
- if (flags != other.flags)
- return false;
- if (!Arrays.equals(mac, other.mac))
- return false;
- if (nextDH == null) {
- if (other.nextDH != null)
- return false;
- } else if (!nextDH.equals(other.nextDH))
- return false;
- if (!Arrays.equals(oldMACKeys, other.oldMACKeys))
- return false;
- if (recipientKeyID != other.recipientKeyID)
- return false;
- if (senderKeyID != other.senderKeyID)
- return false;
- return true;
- }
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/ErrorMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-/**
- *
- * @author George Politis
- */
-public class ErrorMessage extends AbstractMessage {
- // Fields.
- public String error;
-
- // Ctor.
- public ErrorMessage(int messageType, String error) {
- super(messageType);
- this.error = error;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + ((error == null) ? 0 : error.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- ErrorMessage other = (ErrorMessage) obj;
- if (error == null) {
- if (other.error != null)
- return false;
- } else if (!error.equals(other.error))
- return false;
- return true;
- }
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/MysteriousT.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-package net.java.otr4j.io.messages;
-
-import java.util.Arrays;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-public class MysteriousT {
- // Fields.
- public int protocolVersion;
- public int messageType;
- public int flags;
- public int senderKeyID;
- public int recipientKeyID;
- public DHPublicKey nextDH;
- public byte[] ctr;
- public byte[] encryptedMessage;
-
- // Ctor.
- public MysteriousT(int protocolVersion, int flags, int senderKeyID,
- int recipientKeyID, DHPublicKey nextDH, byte[] ctr,
- byte[] encryptedMessage) {
-
- this.protocolVersion = protocolVersion;
- this.messageType = AbstractEncodedMessage.MESSAGE_DATA;
- this.flags = flags;
- this.senderKeyID = senderKeyID;
- this.recipientKeyID = recipientKeyID;
- this.nextDH = nextDH;
- this.ctr = ctr;
- this.encryptedMessage = encryptedMessage;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- // TODO: Needs work.
- final int prime = 31;
- int result = 1;
- result = prime * result + Arrays.hashCode(ctr);
- result = prime * result + Arrays.hashCode(encryptedMessage);
- result = prime * result + flags;
- result = prime * result + messageType;
- result = prime * result + ((nextDH == null) ? 0 : nextDH.hashCode());
- result = prime * result + protocolVersion;
- result = prime * result + recipientKeyID;
- result = prime * result + senderKeyID;
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- // TODO: Needs work.
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- MysteriousT other = (MysteriousT) obj;
- if (!Arrays.equals(ctr, other.ctr))
- return false;
- if (!Arrays.equals(encryptedMessage, other.encryptedMessage))
- return false;
- if (flags != other.flags)
- return false;
- if (messageType != other.messageType)
- return false;
- if (nextDH == null) {
- if (other.nextDH != null)
- return false;
- } else if (!nextDH.equals(other.nextDH))
- return false;
- if (protocolVersion != other.protocolVersion)
- return false;
- if (recipientKeyID != other.recipientKeyID)
- return false;
- if (senderKeyID != other.senderKeyID)
- return false;
- return true;
- }
-
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/PlainTextMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-import java.util.List;
-
-/**
- *
- * @author George Politis
- */
-public class PlainTextMessage extends QueryMessage {
- // Fields.
- public String cleanText;
-
- // Ctor.
- public PlainTextMessage(List<Integer> versions, String cleanText) {
- super(MESSAGE_PLAINTEXT, versions);
- this.cleanText = cleanText;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result
- + ((cleanText == null) ? 0 : cleanText.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- PlainTextMessage other = (PlainTextMessage) obj;
- if (cleanText == null) {
- if (other.cleanText != null)
- return false;
- } else if (!cleanText.equals(other.cleanText))
- return false;
- return true;
- }
-
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/QueryMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-import java.util.List;
-
-/**
- *
- * @author George Politis
- */
-public class QueryMessage extends AbstractMessage {
- // Fields.
- public List<Integer> versions;
-
- // Ctor.
- protected QueryMessage(int messageType, List<Integer> versions) {
- super(messageType);
- this.versions = versions;
- }
-
- public QueryMessage(List<Integer> versions) {
- this(MESSAGE_QUERY, versions);
- }
-
- // Methods.
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result
- + ((versions == null) ? 0 : versions.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- QueryMessage other = (QueryMessage) obj;
- if (versions == null) {
- if (other.versions != null)
- return false;
- } else if (!versions.equals(other.versions))
- return false;
- return true;
- }
-
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/RevealSignatureMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-import java.util.Arrays;
-
-/**
- *
- * @author George Politis
- */
-public class RevealSignatureMessage extends SignatureMessage {
- // Fields.
- public byte[] revealedKey;
-
- // Ctor.
- public RevealSignatureMessage(int protocolVersion, byte[] xEncrypted,
- byte[] xEncryptedMAC, byte[] revealedKey) {
- super(MESSAGE_REVEALSIG, protocolVersion, xEncrypted, xEncryptedMAC);
-
- this.revealedKey = revealedKey;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + Arrays.hashCode(revealedKey);
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- RevealSignatureMessage other = (RevealSignatureMessage) obj;
- if (!Arrays.equals(revealedKey, other.revealedKey))
- return false;
- return true;
- }
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/SignatureM.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-import java.security.PublicKey;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-/**
- *
- * @author George Politis
- */
-public class SignatureM {
- // Fields.
- public DHPublicKey localPubKey;
- public DHPublicKey remotePubKey;
- public PublicKey localLongTermPubKey;
- public int keyPairID;
-
- // Ctor.
- public SignatureM(DHPublicKey localPubKey, DHPublicKey remotePublicKey,
- PublicKey localLongTermPublicKey, int keyPairID) {
-
- this.localPubKey = localPubKey;
- this.remotePubKey = remotePublicKey;
- this.localLongTermPubKey = localLongTermPublicKey;
- this.keyPairID = keyPairID;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + keyPairID;
- // TODO: Needs work.
- result = prime
- * result
- + ((localLongTermPubKey == null) ? 0 : localLongTermPubKey
- .hashCode());
- result = prime * result
- + ((localPubKey == null) ? 0 : localPubKey.hashCode());
- result = prime * result
- + ((remotePubKey == null) ? 0 : remotePubKey.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- // TODO: Needs work.
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- SignatureM other = (SignatureM) obj;
- if (keyPairID != other.keyPairID)
- return false;
- if (localLongTermPubKey == null) {
- if (other.localLongTermPubKey != null)
- return false;
- } else if (!localLongTermPubKey.equals(other.localLongTermPubKey))
- return false;
- if (localPubKey == null) {
- if (other.localPubKey != null)
- return false;
- } else if (!localPubKey.equals(other.localPubKey))
- return false;
- if (remotePubKey == null) {
- if (other.remotePubKey != null)
- return false;
- } else if (!remotePubKey.equals(other.remotePubKey))
- return false;
- return true;
- }
-
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/SignatureMessage.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-import net.java.otr4j.OtrException;
-import net.java.otr4j.crypto.OtrCryptoEngineImpl;
-import net.java.otr4j.io.SerializationUtils;
-
-/**
- *
- * @author George Politis
- */
-public class SignatureMessage extends AbstractEncodedMessage {
- // Fields.
- public byte[] xEncrypted;
- public byte[] xEncryptedMAC;
-
- // Ctor.
- protected SignatureMessage(int messageType, int protocolVersion,
- byte[] xEncrypted, byte[] xEncryptedMAC) {
- super(messageType, protocolVersion);
- this.xEncrypted = xEncrypted;
- this.xEncryptedMAC = xEncryptedMAC;
- }
-
- public SignatureMessage(int protocolVersion, byte[] xEncrypted,
- byte[] xEncryptedMAC) {
- this(MESSAGE_SIGNATURE, protocolVersion, xEncrypted, xEncryptedMAC);
- }
-
- // Memthods.
- public byte[] decrypt(byte[] key) throws OtrException {
- return new OtrCryptoEngineImpl().aesDecrypt(key, null, xEncrypted);
- }
-
- public boolean verify(byte[] key) throws OtrException {
- // Hash the key.
- byte[] xbEncrypted;
- try {
- xbEncrypted = SerializationUtils.writeData(xEncrypted);
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- byte[] xEncryptedMAC = new OtrCryptoEngineImpl().sha256Hmac160(
- xbEncrypted, key);
- // Verify signature.
- return Arrays.equals(xEncryptedMAC, xEncryptedMAC);
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + Arrays.hashCode(xEncrypted);
- result = prime * result + Arrays.hashCode(xEncryptedMAC);
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!super.equals(obj))
- return false;
- if (getClass() != obj.getClass())
- return false;
- SignatureMessage other = (SignatureMessage) obj;
- if (!Arrays.equals(xEncrypted, other.xEncrypted))
- return false;
- if (!Arrays.equals(xEncryptedMAC, other.xEncryptedMAC))
- return false;
- return true;
- }
-}
--- a/app/src/main/java/net/java/otr4j/io/messages/SignatureX.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.io.messages;
-
-import java.security.PublicKey;
-import java.util.Arrays;
-
-/**
- *
- * @author George Politis
- */
-public class SignatureX {
- // Fields.
- public PublicKey longTermPublicKey;
- public int dhKeyID;
- public byte[] signature;
-
- // Ctor.
- public SignatureX(PublicKey ourLongTermPublicKey, int ourKeyID,
- byte[] signature) {
- this.longTermPublicKey = ourLongTermPublicKey;
- this.dhKeyID = ourKeyID;
- this.signature = signature;
- }
-
- // Methods.
- @Override
- public int hashCode() {
- // TODO: Needs work.
- final int prime = 31;
- int result = 1;
- result = prime * result + dhKeyID;
- result = prime
- * result
- + ((longTermPublicKey == null) ? 0 : longTermPublicKey
- .hashCode());
- result = prime * result + Arrays.hashCode(signature);
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- // TODO: Needs work.
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- SignatureX other = (SignatureX) obj;
- if (dhKeyID != other.dhKeyID)
- return false;
- if (longTermPublicKey == null) {
- if (other.longTermPublicKey != null)
- return false;
- } else if (!longTermPublicKey.equals(other.longTermPublicKey))
- return false;
- if (!Arrays.equals(signature, other.signature))
- return false;
- return true;
- }
-
-}
--- a/app/src/main/java/net/java/otr4j/session/AuthContext.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.session;
-
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.PublicKey;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-import net.java.otr4j.OtrException;
-import net.java.otr4j.io.messages.AbstractMessage;
-
-/**
- *
- * @author George Politis
- */
-interface AuthContext {
-
- public static final int NONE = 0;
- public static final int AWAITING_DHKEY = 1;
- public static final int AWAITING_REVEALSIG = 2;
- public static final int AWAITING_SIG = 3;
- public static final int V1_SETUP = 4;
- public static final byte C_START = (byte) 0x01;
- public static final byte M1_START = (byte) 0x02;
- public static final byte M2_START = (byte) 0x03;
- public static final byte M1p_START = (byte) 0x04;
- public static final byte M2p_START = (byte) 0x05;
-
- public abstract void reset();
-
- public abstract boolean getIsSecure();
-
- public abstract DHPublicKey getRemoteDHPublicKey();
-
- public abstract KeyPair getLocalDHKeyPair() throws OtrException;
-
- public abstract BigInteger getS() throws OtrException;
-
- public abstract void handleReceivingMessage(AbstractMessage m)
- throws OtrException;
-
- public abstract void startV2Auth() throws OtrException;
-
- public abstract void respondV2Auth() throws OtrException;
-
- public abstract PublicKey getRemoteLongTermPublicKey();
-
- public abstract KeyPair getLocalLongTermKeyPair();
-}
\ No newline at end of file
--- a/app/src/main/java/net/java/otr4j/session/AuthContextImpl.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,766 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.session;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.util.Arrays;
-import java.util.Random;
-import java.util.Vector;
-import java.util.logging.Logger;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-import net.java.otr4j.OtrException;
-import net.java.otr4j.crypto.OtrCryptoEngine;
-import net.java.otr4j.crypto.OtrCryptoEngineImpl;
-import net.java.otr4j.io.SerializationUtils;
-import net.java.otr4j.io.messages.DHCommitMessage;
-import net.java.otr4j.io.messages.DHKeyMessage;
-import net.java.otr4j.io.messages.AbstractEncodedMessage;
-import net.java.otr4j.io.messages.AbstractMessage;
-import net.java.otr4j.io.messages.SignatureM;
-import net.java.otr4j.io.messages.SignatureX;
-import net.java.otr4j.io.messages.QueryMessage;
-import net.java.otr4j.io.messages.RevealSignatureMessage;
-import net.java.otr4j.io.messages.SignatureMessage;
-
-/**
- *
- * @author George Politis
- */
-class AuthContextImpl implements AuthContext {
-
- public AuthContextImpl(Session session) {
- this.setSession(session);
- this.reset();
- }
-
- private Session session;
-
- private int authenticationState;
- private byte[] r;
-
- private DHPublicKey remoteDHPublicKey;
- private byte[] remoteDHPublicKeyEncrypted;
- private byte[] remoteDHPublicKeyHash;
-
- private KeyPair localDHKeyPair;
- private int localDHPrivateKeyID;
- private byte[] localDHPublicKeyBytes;
- private byte[] localDHPublicKeyHash;
- private byte[] localDHPublicKeyEncrypted;
-
- private BigInteger s;
- private byte[] c;
- private byte[] m1;
- private byte[] m2;
- private byte[] cp;
- private byte[] m1p;
- private byte[] m2p;
-
- private KeyPair localLongTermKeyPair;
- private Boolean isSecure = false;
- private int protocolVersion;
-
- private int getProtocolVersion() {
- return this.protocolVersion;
- }
-
- private void setProtocolVersion(int protoVersion) {
- this.protocolVersion = protoVersion;
- }
-
- private static Logger logger = Logger.getLogger(AuthContextImpl.class
- .getName());
-
- class MessageFactory {
-
- private QueryMessage getQueryMessage() {
- Vector<Integer> versions = new Vector<Integer>();
- versions.add(2);
- return new QueryMessage(versions);
- }
-
- private DHCommitMessage getDHCommitMessage() throws OtrException {
- return new DHCommitMessage(getProtocolVersion(),
- getLocalDHPublicKeyHash(), getLocalDHPublicKeyEncrypted());
- }
-
- private DHKeyMessage getDHKeyMessage() throws OtrException {
- return new DHKeyMessage(getProtocolVersion(),
- (DHPublicKey) getLocalDHKeyPair().getPublic());
- }
-
- private RevealSignatureMessage getRevealSignatureMessage()
- throws OtrException {
- try {
- SignatureM m = new SignatureM((DHPublicKey) getLocalDHKeyPair()
- .getPublic(), getRemoteDHPublicKey(),
- getLocalLongTermKeyPair().getPublic(),
- getLocalDHKeyPairID());
-
- OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl();
- byte[] mhash = otrCryptoEngine.sha256Hmac(SerializationUtils
- .toByteArray(m), getM1());
- byte[] signature = otrCryptoEngine.sign(mhash,
- getLocalLongTermKeyPair().getPrivate());
-
- SignatureX mysteriousX = new SignatureX(
- getLocalLongTermKeyPair().getPublic(),
- getLocalDHKeyPairID(), signature);
- byte[] xEncrypted = otrCryptoEngine.aesEncrypt(getC(), null,
- SerializationUtils.toByteArray(mysteriousX));
-
- byte[] tmp = SerializationUtils.writeData(xEncrypted);
-
- byte[] xEncryptedHash = otrCryptoEngine.sha256Hmac160(tmp,
- getM2());
- return new RevealSignatureMessage(getProtocolVersion(),
- xEncrypted, xEncryptedHash, getR());
- } catch (IOException e) {
- throw new OtrException(e);
- }
- }
-
- private SignatureMessage getSignatureMessage() throws OtrException {
- SignatureM m = new SignatureM((DHPublicKey) getLocalDHKeyPair()
- .getPublic(), getRemoteDHPublicKey(),
- getLocalLongTermKeyPair().getPublic(),
- getLocalDHKeyPairID());
-
- OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl();
- byte[] mhash;
- try {
- mhash = otrCryptoEngine.sha256Hmac(SerializationUtils
- .toByteArray(m), getM1p());
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- byte[] signature = otrCryptoEngine.sign(mhash,
- getLocalLongTermKeyPair().getPrivate());
-
- SignatureX mysteriousX = new SignatureX(getLocalLongTermKeyPair()
- .getPublic(), getLocalDHKeyPairID(), signature);
-
- byte[] xEncrypted;
- try {
- xEncrypted = otrCryptoEngine.aesEncrypt(getCp(), null,
- SerializationUtils.toByteArray(mysteriousX));
- byte[] tmp = SerializationUtils.writeData(xEncrypted);
- byte[] xEncryptedHash = otrCryptoEngine.sha256Hmac160(tmp,
- getM2p());
- return new SignatureMessage(getProtocolVersion(), xEncrypted,
- xEncryptedHash);
- } catch (IOException e) {
- throw new OtrException(e);
- }
- }
- }
-
- private MessageFactory messageFactory = new MessageFactory();
-
- public void reset() {
- logger.finest("Resetting authentication state.");
- authenticationState = AuthContext.NONE;
- r = null;
-
- remoteDHPublicKey = null;
- remoteDHPublicKeyEncrypted = null;
- remoteDHPublicKeyHash = null;
-
- localDHKeyPair = null;
- localDHPrivateKeyID = 1;
- localDHPublicKeyBytes = null;
- localDHPublicKeyHash = null;
- localDHPublicKeyEncrypted = null;
-
- s = null;
- c = m1 = m2 = cp = m1p = m2p = null;
-
- localLongTermKeyPair = null;
- protocolVersion = 0;
- setIsSecure(false);
- }
-
- private void setIsSecure(Boolean isSecure) {
- this.isSecure = isSecure;
- }
-
- public boolean getIsSecure() {
- return isSecure;
- }
-
- private void setAuthenticationState(int authenticationState) {
- this.authenticationState = authenticationState;
- }
-
- private int getAuthenticationState() {
- return authenticationState;
- }
-
- private byte[] getR() {
- if (r == null) {
- logger.finest("Picking random key r.");
- r = new byte[OtrCryptoEngine.AES_KEY_BYTE_LENGTH];
- new Random().nextBytes(r);
- }
- return r;
- }
-
- private void setRemoteDHPublicKey(DHPublicKey dhPublicKey) {
- // Verifies that Alice's gy is a legal value (2 <= gy <= modulus-2)
- if (dhPublicKey.getY().compareTo(OtrCryptoEngine.MODULUS_MINUS_TWO) > 0) {
- throw new IllegalArgumentException(
- "Illegal D-H Public Key value, Ignoring message.");
- } else if (dhPublicKey.getY().compareTo(OtrCryptoEngine.BIGINTEGER_TWO) < 0) {
- throw new IllegalArgumentException(
- "Illegal D-H Public Key value, Ignoring message.");
- }
- logger.finest("Received D-H Public Key is a legal value.");
-
- this.remoteDHPublicKey = dhPublicKey;
- }
-
- public DHPublicKey getRemoteDHPublicKey() {
- return remoteDHPublicKey;
- }
-
- private void setRemoteDHPublicKeyEncrypted(byte[] remoteDHPublicKeyEncrypted) {
- logger.finest("Storing encrypted remote public key.");
- this.remoteDHPublicKeyEncrypted = remoteDHPublicKeyEncrypted;
- }
-
- private byte[] getRemoteDHPublicKeyEncrypted() {
- return remoteDHPublicKeyEncrypted;
- }
-
- private void setRemoteDHPublicKeyHash(byte[] remoteDHPublicKeyHash) {
- logger.finest("Storing encrypted remote public key hash.");
- this.remoteDHPublicKeyHash = remoteDHPublicKeyHash;
- }
-
- private byte[] getRemoteDHPublicKeyHash() {
- return remoteDHPublicKeyHash;
- }
-
- public KeyPair getLocalDHKeyPair() throws OtrException {
- if (localDHKeyPair == null) {
- localDHKeyPair = new OtrCryptoEngineImpl().generateDHKeyPair();
- logger.finest("Generated local D-H key pair.");
- }
- return localDHKeyPair;
- }
-
- private int getLocalDHKeyPairID() {
- return localDHPrivateKeyID;
- }
-
- private byte[] getLocalDHPublicKeyHash() throws OtrException {
- if (localDHPublicKeyHash == null) {
- localDHPublicKeyHash = new OtrCryptoEngineImpl()
- .sha256Hash(getLocalDHPublicKeyBytes());
- logger.finest("Hashed local D-H public key.");
- }
- return localDHPublicKeyHash;
- }
-
- private byte[] getLocalDHPublicKeyEncrypted() throws OtrException {
- if (localDHPublicKeyEncrypted == null) {
- localDHPublicKeyEncrypted = new OtrCryptoEngineImpl().aesEncrypt(
- getR(), null, getLocalDHPublicKeyBytes());
- logger.finest("Encrypted our D-H public key.");
- }
- return localDHPublicKeyEncrypted;
- }
-
- public BigInteger getS() throws OtrException {
- if (s == null) {
- s = new OtrCryptoEngineImpl().generateSecret(this
- .getLocalDHKeyPair().getPrivate(), this
- .getRemoteDHPublicKey());
- logger.finest("Generated shared secret.");
- }
- return s;
- }
-
- private byte[] getC() throws OtrException {
- if (c != null)
- return c;
-
- byte[] h2 = h2(C_START);
- ByteBuffer buff = ByteBuffer.wrap(h2);
- this.c = new byte[OtrCryptoEngine.AES_KEY_BYTE_LENGTH];
- buff.get(this.c);
- logger.finest("Computed c.");
- return c;
-
- }
-
- private byte[] getM1() throws OtrException {
- if (m1 != null)
- return m1;
-
- byte[] h2 = h2(M1_START);
- ByteBuffer buff = ByteBuffer.wrap(h2);
- byte[] m1 = new byte[OtrCryptoEngine.SHA256_HMAC_KEY_BYTE_LENGTH];
- buff.get(m1);
- logger.finest("Computed m1.");
- this.m1 = m1;
- return m1;
- }
-
- private byte[] getM2() throws OtrException {
- if (m2 != null)
- return m2;
-
- byte[] h2 = h2(M2_START);
- ByteBuffer buff = ByteBuffer.wrap(h2);
- byte[] m2 = new byte[OtrCryptoEngine.SHA256_HMAC_KEY_BYTE_LENGTH];
- buff.get(m2);
- logger.finest("Computed m2.");
- this.m2 = m2;
- return m2;
- }
-
- private byte[] getCp() throws OtrException {
- if (cp != null)
- return cp;
-
- byte[] h2 = h2(C_START);
- ByteBuffer buff = ByteBuffer.wrap(h2);
- byte[] cp = new byte[OtrCryptoEngine.AES_KEY_BYTE_LENGTH];
- buff.position(OtrCryptoEngine.AES_KEY_BYTE_LENGTH);
- buff.get(cp);
- logger.finest("Computed c'.");
- this.cp = cp;
- return cp;
- }
-
- private byte[] getM1p() throws OtrException {
- if (m1p != null)
- return m1p;
-
- byte[] h2 = h2(M1p_START);
- ByteBuffer buff = ByteBuffer.wrap(h2);
- byte[] m1p = new byte[OtrCryptoEngine.SHA256_HMAC_KEY_BYTE_LENGTH];
- buff.get(m1p);
- this.m1p = m1p;
- logger.finest("Computed m1'.");
- return m1p;
- }
-
- private byte[] getM2p() throws OtrException {
- if (m2p != null)
- return m2p;
-
- byte[] h2 = h2(M2p_START);
- ByteBuffer buff = ByteBuffer.wrap(h2);
- byte[] m2p = new byte[OtrCryptoEngine.SHA256_HMAC_KEY_BYTE_LENGTH];
- buff.get(m2p);
- this.m2p = m2p;
- logger.finest("Computed m2'.");
- return m2p;
- }
-
- public KeyPair getLocalLongTermKeyPair() {
- if (localLongTermKeyPair == null) {
- localLongTermKeyPair = getSession().getLocalKeyPair();
- }
- return localLongTermKeyPair;
- }
-
- private byte[] h2(byte b) throws OtrException {
- byte[] secbytes;
- try {
- secbytes = SerializationUtils.writeMpi(getS());
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- int len = secbytes.length + 1;
- ByteBuffer buff = ByteBuffer.allocate(len);
- buff.put(b);
- buff.put(secbytes);
- byte[] sdata = buff.array();
- return new OtrCryptoEngineImpl().sha256Hash(sdata);
- }
-
- private byte[] getLocalDHPublicKeyBytes() throws OtrException {
- if (localDHPublicKeyBytes == null) {
- try {
- this.localDHPublicKeyBytes = SerializationUtils
- .writeMpi(((DHPublicKey) getLocalDHKeyPair()
- .getPublic()).getY());
-
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- }
- return localDHPublicKeyBytes;
- }
-
- public void handleReceivingMessage(AbstractMessage m) throws OtrException {
-
- switch (m.messageType) {
- case AbstractEncodedMessage.MESSAGE_DH_COMMIT:
- handleDHCommitMessage((DHCommitMessage) m);
- break;
- case AbstractEncodedMessage.MESSAGE_DHKEY:
- handleDHKeyMessage((DHKeyMessage) m);
- break;
- case AbstractEncodedMessage.MESSAGE_REVEALSIG:
- handleRevealSignatureMessage((RevealSignatureMessage) m);
- break;
- case AbstractEncodedMessage.MESSAGE_SIGNATURE:
- handleSignatureMessage((SignatureMessage) m);
- break;
- default:
- throw new UnsupportedOperationException();
- }
- }
-
- private void handleSignatureMessage(SignatureMessage m) throws OtrException {
- Session session = getSession();
- SessionID sessionID = session.getSessionID();
- logger.finest(sessionID.getAccountID()
- + " received a signature message from " + sessionID.getUserID()
- + " throught " + sessionID.getProtocolName() + ".");
- if (!session.getSessionPolicy().getAllowV2()) {
- logger.finest("Policy does not allow OTRv2, ignoring message.");
- return;
- }
-
- switch (this.getAuthenticationState()) {
- case AWAITING_SIG:
- // Verify MAC.
- if (!m.verify(this.getM2p())) {
- logger
- .finest("Signature MACs are not equal, ignoring message.");
- return;
- }
-
- // Decrypt X.
- byte[] remoteXDecrypted = m.decrypt(this.getCp());
- SignatureX remoteX;
- try {
- remoteX = SerializationUtils.toMysteriousX(remoteXDecrypted);
- } catch (IOException e) {
- throw new OtrException(e);
- }
- // Compute signature.
- PublicKey remoteLongTermPublicKey = remoteX.longTermPublicKey;
- SignatureM remoteM = new SignatureM(this.getRemoteDHPublicKey(),
- (DHPublicKey) this.getLocalDHKeyPair().getPublic(),
- remoteLongTermPublicKey, remoteX.dhKeyID);
- OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl();
- // Verify signature.
- byte[] signature;
- try {
- signature = otrCryptoEngine.sha256Hmac(SerializationUtils
- .toByteArray(remoteM), this.getM1p());
- } catch (IOException e) {
- throw new OtrException(e);
- }
- if (!otrCryptoEngine.verify(signature, remoteLongTermPublicKey,
- remoteX.signature)) {
- logger.finest("Signature verification failed.");
- return;
- }
-
- this.setIsSecure(true);
- this.setRemoteLongTermPublicKey(remoteLongTermPublicKey);
- break;
- default:
- logger
- .finest("We were not expecting a signature, ignoring message.");
- return;
- }
- }
-
- private void handleRevealSignatureMessage(RevealSignatureMessage m)
- throws OtrException {
- Session session = getSession();
- SessionID sessionID = session.getSessionID();
- logger.finest(sessionID.getAccountID()
- + " received a reveal signature message from "
- + sessionID.getUserID() + " throught "
- + sessionID.getProtocolName() + ".");
-
- if (!session.getSessionPolicy().getAllowV2()) {
- logger.finest("Policy does not allow OTRv2, ignoring message.");
- return;
- }
-
- switch (this.getAuthenticationState()) {
- case AWAITING_REVEALSIG:
- // Use the received value of r to decrypt the value of gx
- // received
- // in the D-H Commit Message, and verify the hash therein.
- // Decrypt
- // the encrypted signature, and verify the signature and the
- // MACs.
- // If everything checks out:
-
- // * Reply with a Signature Message.
- // * Transition authstate to AUTHSTATE_NONE.
- // * Transition msgstate to MSGSTATE_ENCRYPTED.
- // * TODO If there is a recent stored message, encrypt it and
- // send
- // it as a Data Message.
-
- OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl();
- // Uses r to decrypt the value of gx sent earlier
- byte[] remoteDHPublicKeyDecrypted = otrCryptoEngine.aesDecrypt(
- m.revealedKey, null, this.getRemoteDHPublicKeyEncrypted());
-
- // Verifies that HASH(gx) matches the value sent earlier
- byte[] remoteDHPublicKeyHash = otrCryptoEngine
- .sha256Hash(remoteDHPublicKeyDecrypted);
- if (!Arrays.equals(remoteDHPublicKeyHash, this
- .getRemoteDHPublicKeyHash())) {
- logger.finest("Hashes don't match, ignoring message.");
- return;
- }
-
- // Verifies that Bob's gx is a legal value (2 <= gx <=
- // modulus-2)
- BigInteger remoteDHPublicKeyMpi;
- try {
- remoteDHPublicKeyMpi = SerializationUtils
- .readMpi(remoteDHPublicKeyDecrypted);
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- this.setRemoteDHPublicKey(otrCryptoEngine
- .getDHPublicKey(remoteDHPublicKeyMpi));
-
- // Verify received Data.
- if (!m.verify(this.getM2())) {
- logger
- .finest("Signature MACs are not equal, ignoring message.");
- return;
- }
-
- // Decrypt X.
- byte[] remoteXDecrypted = m.decrypt(this.getC());
- SignatureX remoteX;
- try {
- remoteX = SerializationUtils.toMysteriousX(remoteXDecrypted);
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- // Compute signature.
- PublicKey remoteLongTermPublicKey = remoteX.longTermPublicKey;
- SignatureM remoteM = new SignatureM(this.getRemoteDHPublicKey(),
- (DHPublicKey) this.getLocalDHKeyPair().getPublic(),
- remoteLongTermPublicKey, remoteX.dhKeyID);
-
- // Verify signature.
- byte[] signature;
- try {
- signature = otrCryptoEngine.sha256Hmac(SerializationUtils
- .toByteArray(remoteM), this.getM1());
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- if (!otrCryptoEngine.verify(signature, remoteLongTermPublicKey,
- remoteX.signature)) {
- logger.finest("Signature verification failed.");
- return;
- }
-
- logger.finest("Signature verification succeeded.");
-
- this.setAuthenticationState(AuthContext.NONE);
- this.setIsSecure(true);
- this.setRemoteLongTermPublicKey(remoteLongTermPublicKey);
- getSession().injectMessage(messageFactory.getSignatureMessage());
- break;
- default:
- logger.finest("Ignoring message.");
- break;
- }
- }
-
- private void handleDHKeyMessage(DHKeyMessage m) throws OtrException {
- Session session = getSession();
- SessionID sessionID = session.getSessionID();
- logger.finest(sessionID.getAccountID()
- + " received a D-H key message from " + sessionID.getUserID()
- + " throught " + sessionID.getProtocolName() + ".");
-
- if (!session.getSessionPolicy().getAllowV2()) {
- logger.finest("If ALLOW_V2 is not set, ignore this message.");
- return;
- }
-
- switch (this.getAuthenticationState()) {
- case AWAITING_DHKEY:
- // Reply with a Reveal Signature Message and transition
- // authstate to
- // AUTHSTATE_AWAITING_SIG
- this.setRemoteDHPublicKey(m.dhPublicKey);
- this.setAuthenticationState(AuthContext.AWAITING_SIG);
- getSession().injectMessage(
- messageFactory.getRevealSignatureMessage());
- logger.finest("Sent Reveal Signature.");
- break;
- case AWAITING_SIG:
-
- if (m.dhPublicKey.getY().equals(this.getRemoteDHPublicKey().getY())) {
- // If this D-H Key message is the same the one you received
- // earlier (when you entered AUTHSTATE_AWAITING_SIG):
- // Retransmit
- // your Reveal Signature Message.
- getSession().injectMessage(
- messageFactory.getRevealSignatureMessage());
- logger.finest("Resent Reveal Signature.");
- } else {
- // Otherwise: Ignore the message.
- logger.finest("Ignoring message.");
- }
- break;
- default:
- // Ignore the message
- break;
- }
- }
-
- private void handleDHCommitMessage(DHCommitMessage m) throws OtrException {
- Session session = getSession();
- SessionID sessionID = session.getSessionID();
- logger.finest(sessionID.getAccountID()
- + " received a D-H commit message from "
- + sessionID.getUserID() + " throught "
- + sessionID.getProtocolName() + ".");
-
- if (!session.getSessionPolicy().getAllowV2()) {
- logger.finest("ALLOW_V2 is not set, ignore this message.");
- return;
- }
-
- switch (this.getAuthenticationState()) {
- case NONE:
- // Reply with a D-H Key Message, and transition authstate to
- // AUTHSTATE_AWAITING_REVEALSIG.
- this.reset();
- this.setProtocolVersion(2);
- this.setRemoteDHPublicKeyEncrypted(m.dhPublicKeyEncrypted);
- this.setRemoteDHPublicKeyHash(m.dhPublicKeyHash);
- this.setAuthenticationState(AuthContext.AWAITING_REVEALSIG);
- getSession().injectMessage(messageFactory.getDHKeyMessage());
- logger.finest("Sent D-H key.");
- break;
-
- case AWAITING_DHKEY:
- // This is the trickiest transition in the whole protocol. It
- // indicates that you have already sent a D-H Commit message to
- // your
- // correspondent, but that he either didn't receive it, or just
- // didn't receive it yet, and has sent you one as well. The
- // symmetry
- // will be broken by comparing the hashed gx you sent in your
- // D-H
- // Commit Message with the one you received, considered as
- // 32-byte
- // unsigned big-endian values.
- BigInteger ourHash = new BigInteger(1, this
- .getLocalDHPublicKeyHash());
- BigInteger theirHash = new BigInteger(1, m.dhPublicKeyHash);
-
- if (theirHash.compareTo(ourHash) == -1) {
- // Ignore the incoming D-H Commit message, but resend your
- // D-H
- // Commit message.
- getSession().injectMessage(messageFactory.getDHCommitMessage());
- logger
- .finest("Ignored the incoming D-H Commit message, but resent our D-H Commit message.");
- } else {
- // *Forget* your old gx value that you sent (encrypted)
- // earlier,
- // and pretend you're in AUTHSTATE_NONE; i.e. reply with a
- // D-H
- // Key Message, and transition authstate to
- // AUTHSTATE_AWAITING_REVEALSIG.
- this.reset();
- this.setProtocolVersion(2);
- this.setRemoteDHPublicKeyEncrypted(m.dhPublicKeyEncrypted);
- this.setRemoteDHPublicKeyHash(m.dhPublicKeyHash);
- this.setAuthenticationState(AuthContext.AWAITING_REVEALSIG);
- getSession().injectMessage(messageFactory.getDHKeyMessage());
- logger
- .finest("Forgot our old gx value that we sent (encrypted) earlier, and pretended we're in AUTHSTATE_NONE -> Sent D-H key.");
- }
- break;
-
- case AWAITING_REVEALSIG:
- // Retransmit your D-H Key Message (the same one as you sent
- // when
- // you entered AUTHSTATE_AWAITING_REVEALSIG). Forget the old D-H
- // Commit message, and use this new one instead.
- this.setRemoteDHPublicKeyEncrypted(m.dhPublicKeyEncrypted);
- this.setRemoteDHPublicKeyHash(m.dhPublicKeyHash);
- getSession().injectMessage(messageFactory.getDHKeyMessage());
- logger.finest("Sent D-H key.");
- break;
- case AWAITING_SIG:
- // Reply with a new D-H Key message, and transition authstate to
- // AUTHSTATE_AWAITING_REVEALSIG
- this.reset();
- this.setRemoteDHPublicKeyEncrypted(m.dhPublicKeyEncrypted);
- this.setRemoteDHPublicKeyHash(m.dhPublicKeyHash);
- this.setAuthenticationState(AuthContext.AWAITING_REVEALSIG);
- getSession().injectMessage(messageFactory.getDHKeyMessage());
- logger.finest("Sent D-H key.");
- break;
- case V1_SETUP:
- throw new UnsupportedOperationException();
- }
- }
-
- public void startV2Auth() throws OtrException {
- logger
- .finest("Starting Authenticated Key Exchange, sending query message");
- getSession().injectMessage(messageFactory.getQueryMessage());
- }
-
- public void respondV2Auth() throws OtrException {
- logger.finest("Responding to Query Message");
- this.reset();
- this.setProtocolVersion(2);
- this.setAuthenticationState(AuthContext.AWAITING_DHKEY);
- logger.finest("Sending D-H Commit.");
- getSession().injectMessage(messageFactory.getDHCommitMessage());
- }
-
- private void setSession(Session session) {
- this.session = session;
- }
-
- private Session getSession() {
- return session;
- }
-
- private PublicKey remoteLongTermPublicKey;
-
- public PublicKey getRemoteLongTermPublicKey() {
- return remoteLongTermPublicKey;
- }
-
- private void setRemoteLongTermPublicKey(PublicKey pubKey) {
- this.remoteLongTermPublicKey = pubKey;
- }
-}
--- a/app/src/main/java/net/java/otr4j/session/Session.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-package net.java.otr4j.session;
-
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.util.List;
-
-import net.java.otr4j.OtrEngineListener;
-import net.java.otr4j.OtrException;
-import net.java.otr4j.OtrPolicy;
-import net.java.otr4j.io.messages.AbstractMessage;
-import net.java.otr4j.session.SessionImpl.TLV;
-
-public interface Session {
-
- public abstract SessionStatus getSessionStatus();
-
- public abstract SessionID getSessionID();
-
- public abstract void injectMessage(AbstractMessage m) throws OtrException;
-
- public abstract KeyPair getLocalKeyPair();
-
- public abstract OtrPolicy getSessionPolicy();
-
- public abstract String transformReceiving(String content)
- throws OtrException;
-
- public abstract String transformSending(String content, List<TLV> tlvs)
- throws OtrException;
-
- public abstract void startSession() throws OtrException;
-
- public abstract void endSession() throws OtrException;
-
- public abstract void refreshSession() throws OtrException;
-
- public abstract PublicKey getRemotePublicKey();
-
- public abstract void addOtrEngineListener(OtrEngineListener l);
-
- public abstract void removeOtrEngineListener(OtrEngineListener l);
-}
\ No newline at end of file
--- a/app/src/main/java/net/java/otr4j/session/SessionID.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.session;
-
-/**
- *
- * @author George Politis
- *
- */
-public final class SessionID {
-
- public SessionID(String accountID, String userID, String protocolName) {
- this.setAccountID(accountID);
- this.setUserID(userID);
- this.setProtocolName(protocolName);
- }
-
- private String accountID;
- private String userID;
- private String protocolName;
- public static final SessionID Empty = new SessionID(null, null, null);
-
- public void setAccountID(String accountID) {
- this.accountID = accountID;
- }
-
- public String getAccountID() {
- return accountID;
- }
-
- private void setUserID(String userID) {
- this.userID = userID;
- }
-
- public String getUserID() {
- return userID;
- }
-
- private void setProtocolName(String protocolName) {
- this.protocolName = protocolName;
- }
-
- public String getProtocolName() {
- return protocolName;
- }
-
- public String toString() {
- return this.getAccountID() + "_" + this.getProtocolName() + "_"
- + this.getUserID();
- }
-
- public boolean equals(Object obj) {
- if (obj == this)
- return true;
- if (obj == null || obj.getClass() != this.getClass())
- return false;
-
- SessionID sessionID = (SessionID) obj;
-
- return this.toString().equals(sessionID.toString());
- }
-
- public int hashCode() {
- return this.toString().hashCode();
- }
-}
--- a/app/src/main/java/net/java/otr4j/session/SessionImpl.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,792 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package net.java.otr4j.session;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Vector;
-import java.util.logging.Logger;
-import javax.crypto.interfaces.DHPublicKey;
-
-import net.java.otr4j.OtrEngineHost;
-import net.java.otr4j.OtrEngineListener;
-import net.java.otr4j.OtrException;
-import net.java.otr4j.OtrPolicy;
-import net.java.otr4j.crypto.OtrCryptoEngine;
-import net.java.otr4j.crypto.OtrCryptoEngineImpl;
-import net.java.otr4j.io.OtrInputStream;
-import net.java.otr4j.io.OtrOutputStream;
-import net.java.otr4j.io.SerializationConstants;
-import net.java.otr4j.io.SerializationUtils;
-import net.java.otr4j.io.messages.DataMessage;
-import net.java.otr4j.io.messages.AbstractEncodedMessage;
-import net.java.otr4j.io.messages.ErrorMessage;
-import net.java.otr4j.io.messages.AbstractMessage;
-import net.java.otr4j.io.messages.MysteriousT;
-import net.java.otr4j.io.messages.PlainTextMessage;
-import net.java.otr4j.io.messages.QueryMessage;
-
-/**
- *
- * @author George Politis
- */
-public class SessionImpl implements Session {
-
- class TLV {
- public TLV(int type, byte[] value) {
- this.setType(type);
- this.setValue(value);
- }
-
- public void setType(int type) {
- this.type = type;
- }
-
- public int getType() {
- return type;
- }
-
- public void setValue(byte[] value) {
- this.value = value;
- }
-
- public byte[] getValue() {
- return value;
- }
-
- private int type;
- private byte[] value;
- }
-
- private SessionID sessionID;
- private OtrEngineHost host;
- private SessionStatus sessionStatus;
- private AuthContext authContext;
- private SessionKeys[][] sessionKeys;
- private Vector<byte[]> oldMacKeys;
- private static Logger logger = Logger
- .getLogger(SessionImpl.class.getName());
-
- public SessionImpl(SessionID sessionID, OtrEngineHost listener) {
-
- this.setSessionID(sessionID);
- this.setHost(listener);
-
- // client application calls OtrEngine.getSessionStatus()
- // -> create new session if it does not exist, end up here
- // -> setSessionStatus() fires statusChangedEvent
- // -> client application calls OtrEngine.getSessionStatus()
- this.sessionStatus = SessionStatus.PLAINTEXT;
- }
-
- private SessionKeys getEncryptionSessionKeys() {
- logger.finest("Getting encryption keys");
- return getSessionKeysByIndex(SessionKeys.Previous, SessionKeys.Current);
- }
-
- private SessionKeys getMostRecentSessionKeys() {
- logger.finest("Getting most recent keys.");
- return getSessionKeysByIndex(SessionKeys.Current, SessionKeys.Current);
- }
-
- private SessionKeys getSessionKeysByID(int localKeyID, int remoteKeyID) {
- logger
- .finest("Searching for session keys with (localKeyID, remoteKeyID) = ("
- + localKeyID + "," + remoteKeyID + ")");
-
- for (int i = 0; i < getSessionKeys().length; i++) {
- for (int j = 0; j < getSessionKeys()[i].length; j++) {
- SessionKeys current = getSessionKeysByIndex(i, j);
- if (current.getLocalKeyID() == localKeyID
- && current.getRemoteKeyID() == remoteKeyID) {
- logger.finest("Matching keys found.");
- return current;
- }
- }
- }
-
- return null;
- }
-
- private SessionKeys getSessionKeysByIndex(int localKeyIndex,
- int remoteKeyIndex) {
- if (getSessionKeys()[localKeyIndex][remoteKeyIndex] == null)
- getSessionKeys()[localKeyIndex][remoteKeyIndex] = new SessionKeysImpl(
- localKeyIndex, remoteKeyIndex);
-
- return getSessionKeys()[localKeyIndex][remoteKeyIndex];
- }
-
- private void rotateRemoteSessionKeys(DHPublicKey pubKey)
- throws OtrException {
-
- logger.finest("Rotating remote keys.");
- SessionKeys sess1 = getSessionKeysByIndex(SessionKeys.Current,
- SessionKeys.Previous);
- if (sess1.getIsUsedReceivingMACKey()) {
- logger
- .finest("Detected used Receiving MAC key. Adding to old MAC keys to reveal it.");
- getOldMacKeys().add(sess1.getReceivingMACKey());
- }
-
- SessionKeys sess2 = getSessionKeysByIndex(SessionKeys.Previous,
- SessionKeys.Previous);
- if (sess2.getIsUsedReceivingMACKey()) {
- logger
- .finest("Detected used Receiving MAC key. Adding to old MAC keys to reveal it.");
- getOldMacKeys().add(sess2.getReceivingMACKey());
- }
-
- SessionKeys sess3 = getSessionKeysByIndex(SessionKeys.Current,
- SessionKeys.Current);
- sess1
- .setRemoteDHPublicKey(sess3.getRemoteKey(), sess3
- .getRemoteKeyID());
-
- SessionKeys sess4 = getSessionKeysByIndex(SessionKeys.Previous,
- SessionKeys.Current);
- sess2
- .setRemoteDHPublicKey(sess4.getRemoteKey(), sess4
- .getRemoteKeyID());
-
- sess3.setRemoteDHPublicKey(pubKey, sess3.getRemoteKeyID() + 1);
- sess4.setRemoteDHPublicKey(pubKey, sess4.getRemoteKeyID() + 1);
- }
-
- private void rotateLocalSessionKeys() throws OtrException {
-
- logger.finest("Rotating local keys.");
- SessionKeys sess1 = getSessionKeysByIndex(SessionKeys.Previous,
- SessionKeys.Current);
- if (sess1.getIsUsedReceivingMACKey()) {
- logger
- .finest("Detected used Receiving MAC key. Adding to old MAC keys to reveal it.");
- getOldMacKeys().add(sess1.getReceivingMACKey());
- }
-
- SessionKeys sess2 = getSessionKeysByIndex(SessionKeys.Previous,
- SessionKeys.Previous);
- if (sess2.getIsUsedReceivingMACKey()) {
- logger
- .finest("Detected used Receiving MAC key. Adding to old MAC keys to reveal it.");
- getOldMacKeys().add(sess2.getReceivingMACKey());
- }
-
- SessionKeys sess3 = getSessionKeysByIndex(SessionKeys.Current,
- SessionKeys.Current);
- sess1.setLocalPair(sess3.getLocalPair(), sess3.getLocalKeyID());
- SessionKeys sess4 = getSessionKeysByIndex(SessionKeys.Current,
- SessionKeys.Previous);
- sess2.setLocalPair(sess4.getLocalPair(), sess4.getLocalKeyID());
-
- KeyPair newPair = new OtrCryptoEngineImpl().generateDHKeyPair();
- sess3.setLocalPair(newPair, sess3.getLocalKeyID() + 1);
- sess4.setLocalPair(newPair, sess4.getLocalKeyID() + 1);
- }
-
- private byte[] collectOldMacKeys() {
- logger.finest("Collecting old MAC keys to be revealed.");
- int len = 0;
- for (int i = 0; i < getOldMacKeys().size(); i++)
- len += getOldMacKeys().get(i).length;
-
- ByteBuffer buff = ByteBuffer.allocate(len);
- for (int i = 0; i < getOldMacKeys().size(); i++)
- buff.put(getOldMacKeys().get(i));
-
- getOldMacKeys().clear();
- return buff.array();
- }
-
- private void setSessionStatus(SessionStatus sessionStatus)
- throws OtrException {
-
- if (sessionStatus == this.sessionStatus)
- return;
-
- switch (sessionStatus) {
- case ENCRYPTED:
- AuthContext auth = this.getAuthContext();
- logger.finest("Setting most recent session keys from auth.");
- for (int i = 0; i < this.getSessionKeys()[0].length; i++) {
- SessionKeys current = getSessionKeysByIndex(0, i);
- current.setLocalPair(auth.getLocalDHKeyPair(), 1);
- current.setRemoteDHPublicKey(auth.getRemoteDHPublicKey(), 1);
- current.setS(auth.getS());
- }
-
- KeyPair nextDH = new OtrCryptoEngineImpl().generateDHKeyPair();
- for (int i = 0; i < this.getSessionKeys()[1].length; i++) {
- SessionKeys current = getSessionKeysByIndex(1, i);
- current.setRemoteDHPublicKey(auth.getRemoteDHPublicKey(), 1);
- current.setLocalPair(nextDH, 2);
- }
-
- this.setRemotePublicKey(auth.getRemoteLongTermPublicKey());
-
- auth.reset();
- break;
- }
-
- this.sessionStatus = sessionStatus;
-
- for (OtrEngineListener l : this.listeners)
- l.sessionStatusChanged(getSessionID());
- }
-
- /*
- * (non-Javadoc)
- *
- * @see net.java.otr4j.session.ISession#getSessionStatus()
- */
-
- public SessionStatus getSessionStatus() {
- return sessionStatus;
- }
-
- private void setSessionID(SessionID sessionID) {
- this.sessionID = sessionID;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see net.java.otr4j.session.ISession#getSessionID()
- */
- public SessionID getSessionID() {
- return sessionID;
- }
-
- private void setHost(OtrEngineHost host) {
- this.host = host;
- }
-
- private OtrEngineHost getHost() {
- return host;
- }
-
- private SessionKeys[][] getSessionKeys() {
- if (sessionKeys == null)
- sessionKeys = new SessionKeys[2][2];
- return sessionKeys;
- }
-
- private AuthContext getAuthContext() {
- if (authContext == null)
- authContext = new AuthContextImpl(this);
- return authContext;
- }
-
- private Vector<byte[]> getOldMacKeys() {
- if (oldMacKeys == null)
- oldMacKeys = new Vector<byte[]>();
- return oldMacKeys;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * net.java.otr4j.session.ISession#handleReceivingMessage(java.lang.String)
- */
- public String transformReceiving(String msgText) throws OtrException {
- OtrPolicy policy = getSessionPolicy();
- if (!policy.getAllowV1() && !policy.getAllowV2()) {
- logger
- .finest("Policy does not allow neither V1 not V2, ignoring message.");
- return msgText;
- }
-
- AbstractMessage m;
- try {
- m = SerializationUtils.toMessage(msgText);
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- if (m == null)
- return msgText; // Propably null or empty.
-
- switch (m.messageType) {
- case AbstractEncodedMessage.MESSAGE_DATA:
- return handleDataMessage((DataMessage) m);
- case AbstractMessage.MESSAGE_ERROR:
- handleErrorMessage((ErrorMessage) m);
- return null;
- case AbstractMessage.MESSAGE_PLAINTEXT:
- return handlePlainTextMessage((PlainTextMessage) m);
- case AbstractMessage.MESSAGE_QUERY:
- handleQueryMessage((QueryMessage) m);
- return null;
- case AbstractEncodedMessage.MESSAGE_DH_COMMIT:
- case AbstractEncodedMessage.MESSAGE_DHKEY:
- case AbstractEncodedMessage.MESSAGE_REVEALSIG:
- case AbstractEncodedMessage.MESSAGE_SIGNATURE:
- AuthContext auth = this.getAuthContext();
- auth.handleReceivingMessage(m);
-
- if (auth.getIsSecure()) {
- this.setSessionStatus(SessionStatus.ENCRYPTED);
- logger.finest("Gone Secure.");
- }
- return null;
- default:
- throw new UnsupportedOperationException(
- "Received an uknown message type.");
- }
- }
-
- private void handleQueryMessage(QueryMessage queryMessage)
- throws OtrException {
- logger.finest(getSessionID().getAccountID()
- + " received a query message from "
- + getSessionID().getUserID() + " throught "
- + getSessionID().getProtocolName() + ".");
-
- setSessionStatus(SessionStatus.PLAINTEXT);
-
- OtrPolicy policy = getSessionPolicy();
- if (queryMessage.versions.contains(2) && policy.getAllowV2()) {
- logger.finest("Query message with V2 support found.");
- getAuthContext().respondV2Auth();
- } else if (queryMessage.versions.contains(1) && policy.getAllowV1()) {
- throw new UnsupportedOperationException();
- }
- }
-
- private void handleErrorMessage(ErrorMessage errorMessage)
- throws OtrException {
- logger.finest(getSessionID().getAccountID()
- + " received an error message from "
- + getSessionID().getUserID() + " throught "
- + getSessionID().getUserID() + ".");
-
- getHost().showError(this.getSessionID(), errorMessage.error);
-
- OtrPolicy policy = getSessionPolicy();
- if (policy.getErrorStartAKE()) {
- logger.finest("Error message starts AKE.");
- Vector<Integer> versions = new Vector<Integer>();
- if (policy.getAllowV1())
- versions.add(1);
-
- if (policy.getAllowV2())
- versions.add(2);
-
- logger.finest("Sending Query");
- injectMessage(new QueryMessage(versions));
- }
- }
-
- private String handleDataMessage(DataMessage data) throws OtrException {
- logger.finest(getSessionID().getAccountID()
- + " received a data message from " + getSessionID().getUserID()
- + ".");
-
- switch (this.getSessionStatus()) {
- case ENCRYPTED:
- logger
- .finest("Message state is ENCRYPTED. Trying to decrypt message.");
-
- // Find matching session keys.
- int senderKeyID = data.senderKeyID;
- int receipientKeyID = data.recipientKeyID;
- SessionKeys matchingKeys = this.getSessionKeysByID(receipientKeyID,
- senderKeyID);
-
- if (matchingKeys == null) {
- logger.finest("No matching keys found.");
- return null;
- }
-
- // Verify received MAC with a locally calculated MAC.
- logger
- .finest("Transforming T to byte[] to calculate it's HmacSHA1.");
-
- byte[] serializedT;
- try {
- serializedT = SerializationUtils.toByteArray(data.getT());
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl();
-
- byte[] computedMAC = otrCryptoEngine.sha1Hmac(serializedT,
- matchingKeys.getReceivingMACKey(),
- SerializationConstants.TYPE_LEN_MAC);
-
- if (!Arrays.equals(computedMAC, data.mac)) {
- logger.finest("MAC verification failed, ignoring message");
- return null;
- }
-
- logger.finest("Computed HmacSHA1 value matches sent one.");
-
- // Mark this MAC key as old to be revealed.
- matchingKeys.setIsUsedReceivingMACKey(true);
-
- matchingKeys.setReceivingCtr(data.ctr);
-
- byte[] dmc = otrCryptoEngine.aesDecrypt(matchingKeys
- .getReceivingAESKey(), matchingKeys.getReceivingCtr(),
- data.encryptedMessage);
- String decryptedMsgContent;
- try {
- // Expect bytes to be text encoded in UTF-8.
- decryptedMsgContent = new String(dmc, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new OtrException(e);
- }
-
- logger.finest("Decrypted message: \"" + decryptedMsgContent + "\"");
-
- // Rotate keys if necessary.
- SessionKeys mostRecent = this.getMostRecentSessionKeys();
- if (mostRecent.getLocalKeyID() == receipientKeyID)
- this.rotateLocalSessionKeys();
-
- if (mostRecent.getRemoteKeyID() == senderKeyID)
- this.rotateRemoteSessionKeys(data.nextDH);
-
- // Handle TLVs
- List<TLV> tlvs = null;
- int tlvIndex = decryptedMsgContent.indexOf((char) 0x0);
- if (tlvIndex > -1) {
- decryptedMsgContent = decryptedMsgContent
- .substring(0, tlvIndex);
- tlvIndex++;
- byte[] tlvsb = new byte[dmc.length - tlvIndex];
- System.arraycopy(dmc, tlvIndex, tlvsb, 0, tlvsb.length);
-
- tlvs = new Vector<TLV>();
- ByteArrayInputStream tin = new ByteArrayInputStream(tlvsb);
- while (tin.available() > 0) {
- int type;
- byte[] tdata;
- OtrInputStream eois = new OtrInputStream(tin);
- try {
- type = eois.readShort();
- tdata = eois.readTlvData();
- eois.close();
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- tlvs.add(new TLV(type, tdata));
- }
- }
- if (tlvs != null && tlvs.size() > 0) {
- for (TLV tlv : tlvs) {
- switch (tlv.getType()) {
- case 1:
- this.setSessionStatus(SessionStatus.FINISHED);
- return null;
- default:
- return decryptedMsgContent;
- }
- }
- }
-
- return decryptedMsgContent;
-
- case FINISHED:
- case PLAINTEXT:
- getHost().showWarning(this.getSessionID(),
- "Unreadable encrypted message was received.");
-
- injectMessage(new ErrorMessage(AbstractMessage.MESSAGE_ERROR,
- "You sent me an unreadable encrypted message.."));
- break;
- }
-
- return null;
- }
-
- public void injectMessage(AbstractMessage m) throws OtrException {
- String msg;
- try {
- msg = SerializationUtils.toString(m);
- } catch (IOException e) {
- throw new OtrException(e);
- }
- getHost().injectMessage(getSessionID(), msg);
- }
-
- private String handlePlainTextMessage(PlainTextMessage plainTextMessage)
- throws OtrException {
- logger.finest(getSessionID().getAccountID()
- + " received a plaintext message from "
- + getSessionID().getUserID() + " throught "
- + getSessionID().getProtocolName() + ".");
-
- OtrPolicy policy = getSessionPolicy();
- List<Integer> versions = plainTextMessage.versions;
- if (versions == null || versions.size() < 1) {
- logger
- .finest("Received plaintext message without the whitespace tag.");
- switch (this.getSessionStatus()) {
- case ENCRYPTED:
- case FINISHED:
- // Display the message to the user, but warn him that the
- // message was received unencrypted.
- getHost().showWarning(this.getSessionID(),
- "The message was received unencrypted.");
- return plainTextMessage.cleanText;
- case PLAINTEXT:
- // Simply display the message to the user. If
- // REQUIRE_ENCRYPTION
- // is set, warn him that the message was received
- // unencrypted.
- if (policy.getRequireEncryption()) {
- getHost().showWarning(this.getSessionID(),
- "The message was received unencrypted.");
- }
- return plainTextMessage.cleanText;
- }
- } else {
- logger
- .finest("Received plaintext message with the whitespace tag.");
- switch (this.getSessionStatus()) {
- case ENCRYPTED:
- case FINISHED:
- // Remove the whitespace tag and display the message to the
- // user, but warn him that the message was received
- // unencrypted.
- getHost().showWarning(this.getSessionID(),
- "The message was received unencrypted.");
- case PLAINTEXT:
- // Remove the whitespace tag and display the message to the
- // user. If REQUIRE_ENCRYPTION is set, warn him that the
- // message
- // was received unencrypted.
- if (policy.getRequireEncryption())
- getHost().showWarning(this.getSessionID(),
- "The message was received unencrypted.");
- }
-
- if (policy.getWhitespaceStartAKE()) {
- logger.finest("WHITESPACE_START_AKE is set");
-
- if (plainTextMessage.versions.contains(2)
- && policy.getAllowV2()) {
- logger.finest("V2 tag found.");
- getAuthContext().respondV2Auth();
- } else if (plainTextMessage.versions.contains(1)
- && policy.getAllowV1()) {
- throw new UnsupportedOperationException();
- }
- }
- }
-
- return plainTextMessage.cleanText;
- }
-
- // Retransmit last sent message. Spec document does not mention where or
- // when that should happen, must check libotr code.
- private String lastSentMessage;
-
- public String transformSending(String msgText, List<TLV> tlvs)
- throws OtrException {
-
- switch (this.getSessionStatus()) {
- case PLAINTEXT:
- if (getSessionPolicy().getRequireEncryption()) {
- this.lastSentMessage = msgText;
- this.startSession();
- } else
- // TODO this does not precisly behave according to
- // specification.
- return msgText;
- case ENCRYPTED:
- this.lastSentMessage = msgText;
- logger.finest(getSessionID().getAccountID()
- + " sends an encrypted message to "
- + getSessionID().getUserID() + " throught "
- + getSessionID().getProtocolName() + ".");
-
- // Get encryption keys.
- SessionKeys encryptionKeys = this.getEncryptionSessionKeys();
- int senderKeyID = encryptionKeys.getLocalKeyID();
- int receipientKeyID = encryptionKeys.getRemoteKeyID();
-
- // Increment CTR.
- encryptionKeys.incrementSendingCtr();
- byte[] ctr = encryptionKeys.getSendingCtr();
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- if (msgText != null && msgText.length() > 0)
- try {
- out.write(msgText.getBytes("UTF8"));
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- // Append tlvs
- if (tlvs != null && tlvs.size() > 0) {
- out.write((byte) 0x00);
-
- OtrOutputStream eoos = new OtrOutputStream(out);
- for (TLV tlv : tlvs) {
- try {
- eoos.writeShort(tlv.type);
- eoos.writeTlvData(tlv.value);
- } catch (IOException e) {
- throw new OtrException(e);
- }
- }
- }
-
- OtrCryptoEngine otrCryptoEngine = new OtrCryptoEngineImpl();
-
- byte[] data = out.toByteArray();
- // Encrypt message.
- logger
- .finest("Encrypting message with keyids (localKeyID, remoteKeyID) = ("
- + senderKeyID + ", " + receipientKeyID + ")");
- byte[] encryptedMsg = otrCryptoEngine.aesEncrypt(encryptionKeys
- .getSendingAESKey(), ctr, data);
-
- // Get most recent keys to get the next D-H public key.
- SessionKeys mostRecentKeys = this.getMostRecentSessionKeys();
- DHPublicKey nextDH = (DHPublicKey) mostRecentKeys.getLocalPair()
- .getPublic();
-
- // Calculate T.
- MysteriousT t = new MysteriousT(2, 0, senderKeyID, receipientKeyID,
- nextDH, ctr, encryptedMsg);
-
- // Calculate T hash.
- byte[] sendingMACKey = encryptionKeys.getSendingMACKey();
-
- logger
- .finest("Transforming T to byte[] to calculate it's HmacSHA1.");
- byte[] serializedT;
- try {
- serializedT = SerializationUtils.toByteArray(t);
- } catch (IOException e) {
- throw new OtrException(e);
- }
-
- byte[] mac = otrCryptoEngine.sha1Hmac(serializedT, sendingMACKey,
- SerializationConstants.TYPE_LEN_MAC);
-
- // Get old MAC keys to be revealed.
- byte[] oldKeys = this.collectOldMacKeys();
- DataMessage m = new DataMessage(t, mac, oldKeys);
-
- try {
- return SerializationUtils.toString(m);
- } catch (IOException e) {
- throw new OtrException(e);
- }
- case FINISHED:
- this.lastSentMessage = msgText;
- getHost()
- .showError(
- sessionID,
- "Your message to "
- + sessionID.getUserID()
- + " was not sent. Either end your private conversation, or restart it.");
- return null;
- default:
- logger.finest("Uknown message state, not processing.");
- return msgText;
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see net.java.otr4j.session.ISession#startSession()
- */
- public void startSession() throws OtrException {
- if (this.getSessionStatus() == SessionStatus.ENCRYPTED)
- return;
-
- if (!getSessionPolicy().getAllowV2())
- throw new UnsupportedOperationException();
-
- this.getAuthContext().startV2Auth();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see net.java.otr4j.session.ISession#endSession()
- */
- public void endSession() throws OtrException {
- SessionStatus status = this.getSessionStatus();
- switch (status) {
- case ENCRYPTED:
- Vector<TLV> tlvs = new Vector<TLV>();
- tlvs.add(new TLV(1, null));
-
- String msg = this.transformSending(null, tlvs);
- getHost().injectMessage(getSessionID(), msg);
- this.setSessionStatus(SessionStatus.PLAINTEXT);
- break;
- case FINISHED:
- this.setSessionStatus(SessionStatus.PLAINTEXT);
- break;
- case PLAINTEXT:
- return;
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see net.java.otr4j.session.ISession#refreshSession()
- */
- public void refreshSession() throws OtrException {
- this.endSession();
- this.startSession();
- }
-
- private PublicKey remotePublicKey;
-
- private void setRemotePublicKey(PublicKey pubKey) {
- this.remotePublicKey = pubKey;
- }
-
- public PublicKey getRemotePublicKey() {
- return remotePublicKey;
- }
-
- private List<OtrEngineListener> listeners = new Vector<OtrEngineListener>();
-
- public void addOtrEngineListener(OtrEngineListener l) {
- synchronized (listeners) {
- if (!listeners.contains(l))
- listeners.add(l);
- }
- }
-
- public void removeOtrEngineListener(OtrEngineListener l) {
- synchronized (listeners) {
- listeners.remove(l);
- }
- }
-
- public OtrPolicy getSessionPolicy() {
- return getHost().getSessionPolicy(getSessionID());
- }
-
- public KeyPair getLocalKeyPair() {
- return getHost().getKeyPair(this.getSessionID());
- }
-}
--- a/app/src/main/java/net/java/otr4j/session/SessionKeys.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-package net.java.otr4j.session;
-
-import java.math.BigInteger;
-import java.security.KeyPair;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-import net.java.otr4j.OtrException;
-
-interface SessionKeys {
-
- public static final int Previous = 0;
- public static final int Current = 1;
- public static final byte HIGH_SEND_BYTE = (byte) 0x01;
- public static final byte HIGH_RECEIVE_BYTE = (byte) 0x02;
- public static final byte LOW_SEND_BYTE = (byte) 0x02;
- public static final byte LOW_RECEIVE_BYTE = (byte) 0x01;
-
- public abstract void setLocalPair(KeyPair keyPair, int localPairKeyID);
-
- public abstract void setRemoteDHPublicKey(DHPublicKey pubKey,
- int remoteKeyID);
-
- public abstract void incrementSendingCtr();
-
- public abstract byte[] getSendingCtr();
-
- public abstract byte[] getReceivingCtr();
-
- public abstract void setReceivingCtr(byte[] ctr);
-
- public abstract byte[] getSendingAESKey() throws OtrException;
-
- public abstract byte[] getReceivingAESKey() throws OtrException;
-
- public abstract byte[] getSendingMACKey() throws OtrException;
-
- public abstract byte[] getReceivingMACKey() throws OtrException;
-
- public abstract void setS(BigInteger s);
-
- public abstract void setIsUsedReceivingMACKey(Boolean isUsedReceivingMACKey);
-
- public abstract Boolean getIsUsedReceivingMACKey();
-
- public abstract int getLocalKeyID();
-
- public abstract int getRemoteKeyID();
-
- public abstract DHPublicKey getRemoteKey();
-
- public abstract KeyPair getLocalPair();
-
-}
\ No newline at end of file
--- a/app/src/main/java/net/java/otr4j/session/SessionKeysImpl.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.session;
-
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.security.KeyPair;
-import java.util.Arrays;
-import java.util.logging.Logger;
-
-import javax.crypto.interfaces.DHPublicKey;
-
-import net.java.otr4j.OtrException;
-import net.java.otr4j.crypto.OtrCryptoEngine;
-import net.java.otr4j.crypto.OtrCryptoEngineImpl;
-import net.java.otr4j.io.SerializationUtils;
-
-/**
- *
- * @author George Politis
- */
-class SessionKeysImpl implements SessionKeys {
-
- private static Logger logger = Logger.getLogger(SessionKeysImpl.class
- .getName());
- private String keyDescription;
-
- public SessionKeysImpl(int localKeyIndex, int remoteKeyIndex) {
- if (localKeyIndex == 0)
- keyDescription = "(Previous local, ";
- else
- keyDescription = "(Most recent local, ";
-
- if (remoteKeyIndex == 0)
- keyDescription += "Previous remote)";
- else
- keyDescription += "Most recent remote)";
-
- }
-
- public void setLocalPair(KeyPair keyPair, int localPairKeyID) {
- this.localPair = keyPair;
- this.setLocalKeyID(localPairKeyID);
- logger.finest(keyDescription + " current local key ID: "
- + this.getLocalKeyID());
- this.reset();
- }
-
- public void setRemoteDHPublicKey(DHPublicKey pubKey, int remoteKeyID) {
- this.setRemoteKey(pubKey);
- this.setRemoteKeyID(remoteKeyID);
- logger.finest(keyDescription + " current remote key ID: "
- + this.getRemoteKeyID());
- this.reset();
- }
-
- private byte[] sendingCtr = new byte[16];
- private byte[] receivingCtr = new byte[16];
-
- public void incrementSendingCtr() {
- logger.finest("Incrementing counter for (localkeyID, remoteKeyID) = ("
- + getLocalKeyID() + "," + getRemoteKeyID() + ")");
- // logger.debug("Counter prior increament: " +
- // Utils.dump(sendingCtr,
- // true, 16));
- for (int i = 7; i >= 0; i--)
- if (++sendingCtr[i] != 0)
- break;
- // logger.debug("Counter after increament: " +
- // Utils.dump(sendingCtr,
- // true, 16));
- }
-
- public byte[] getSendingCtr() {
- return sendingCtr;
- }
-
- public byte[] getReceivingCtr() {
- return receivingCtr;
- }
-
- public void setReceivingCtr(byte[] ctr) {
- for (int i = 0; i < ctr.length; i++)
- receivingCtr[i] = ctr[i];
- }
-
- private void reset() {
- logger.finest("Resetting " + keyDescription + " session keys.");
- Arrays.fill(this.sendingCtr, (byte) 0x00);
- Arrays.fill(this.receivingCtr, (byte) 0x00);
- this.sendingAESKey = null;
- this.receivingAESKey = null;
- this.sendingMACKey = null;
- this.receivingMACKey = null;
- this.setIsUsedReceivingMACKey(false);
- this.s = null;
- if (getLocalPair() != null && getRemoteKey() != null) {
- this.isHigh = ((DHPublicKey) getLocalPair().getPublic()).getY()
- .abs().compareTo(getRemoteKey().getY().abs()) == 1;
- }
-
- }
-
- private byte[] h1(byte b) throws OtrException {
-
- try {
- byte[] secbytes = SerializationUtils.writeMpi(getS());
-
- int len = secbytes.length + 1;
- ByteBuffer buff = ByteBuffer.allocate(len);
- buff.put(b);
- buff.put(secbytes);
- byte[] result = new OtrCryptoEngineImpl().sha1Hash(buff.array());
- return result;
- } catch (Exception e) {
- throw new OtrException(e);
- }
- }
-
- public byte[] getSendingAESKey() throws OtrException {
- if (sendingAESKey != null)
- return sendingAESKey;
-
- byte sendbyte = LOW_SEND_BYTE;
- if (this.isHigh)
- sendbyte = HIGH_SEND_BYTE;
-
- byte[] h1 = h1(sendbyte);
-
- byte[] key = new byte[OtrCryptoEngine.AES_KEY_BYTE_LENGTH];
- ByteBuffer buff = ByteBuffer.wrap(h1);
- buff.get(key);
- logger.finest("Calculated sending AES key.");
- this.sendingAESKey = key;
- return sendingAESKey;
- }
-
- public byte[] getReceivingAESKey() throws OtrException {
- if (receivingAESKey != null)
- return receivingAESKey;
-
- byte receivebyte = LOW_RECEIVE_BYTE;
- if (this.isHigh)
- receivebyte = HIGH_RECEIVE_BYTE;
-
- byte[] h1 = h1(receivebyte);
-
- byte[] key = new byte[OtrCryptoEngine.AES_KEY_BYTE_LENGTH];
- ByteBuffer buff = ByteBuffer.wrap(h1);
- buff.get(key);
- logger.finest("Calculated receiving AES key.");
- this.receivingAESKey = key;
-
- return receivingAESKey;
- }
-
- public byte[] getSendingMACKey() throws OtrException {
- if (sendingMACKey != null)
- return sendingMACKey;
-
- sendingMACKey = new OtrCryptoEngineImpl().sha1Hash(getSendingAESKey());
- logger.finest("Calculated sending MAC key.");
- return sendingMACKey;
- }
-
- public byte[] getReceivingMACKey() throws OtrException {
- if (receivingMACKey == null) {
- receivingMACKey = new OtrCryptoEngineImpl()
- .sha1Hash(getReceivingAESKey());
- logger.finest("Calculated receiving AES key.");
- }
- return receivingMACKey;
- }
-
- private BigInteger getS() throws OtrException {
- if (s == null) {
- s = new OtrCryptoEngineImpl().generateSecret(getLocalPair()
- .getPrivate(), getRemoteKey());
- logger.finest("Calculating shared secret S.");
- }
- return s;
- }
-
- public void setS(BigInteger s) {
- this.s = s;
- }
-
- public void setIsUsedReceivingMACKey(Boolean isUsedReceivingMACKey) {
- this.isUsedReceivingMACKey = isUsedReceivingMACKey;
- }
-
- public Boolean getIsUsedReceivingMACKey() {
- return isUsedReceivingMACKey;
- }
-
- private void setLocalKeyID(int localKeyID) {
- this.localKeyID = localKeyID;
- }
-
- public int getLocalKeyID() {
- return localKeyID;
- }
-
- private void setRemoteKeyID(int remoteKeyID) {
- this.remoteKeyID = remoteKeyID;
- }
-
- public int getRemoteKeyID() {
- return remoteKeyID;
- }
-
- private void setRemoteKey(DHPublicKey remoteKey) {
- this.remoteKey = remoteKey;
- }
-
- public DHPublicKey getRemoteKey() {
- return remoteKey;
- }
-
- public KeyPair getLocalPair() {
- return localPair;
- }
-
- private int localKeyID;
- private int remoteKeyID;
- private DHPublicKey remoteKey;
- private KeyPair localPair;
-
- private byte[] sendingAESKey;
- private byte[] receivingAESKey;
- private byte[] sendingMACKey;
- private byte[] receivingMACKey;
- private Boolean isUsedReceivingMACKey;
- private BigInteger s;
- private Boolean isHigh;
-}
--- a/app/src/main/java/net/java/otr4j/session/SessionStatus.java Sun Mar 15 18:57:24 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-/*
- * otr4j, the open source java otr library.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.otr4j.session;
-
-/**
- *
- * @author George Politis
- */
-public enum SessionStatus {
- PLAINTEXT,
- ENCRYPTED,
- FINISHED
-}