mirror of
https://github.com/igniterealtime/Spark.git
synced 2025-12-01 12:27:58 +00:00
moving on, OTR Plugin, the next step
git-svn-id: http://svn.igniterealtime.org/svn/repos/spark/branches/otrplugin@12451 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
committed by
holger.bergunde
parent
25ee667d15
commit
e895d58af7
@ -7,6 +7,7 @@
|
||||
<email>holger@bergunde.de</email>
|
||||
<description>Adds OTR support to Spark</description>
|
||||
<minSparkVersion>2.6.0</minSparkVersion>
|
||||
<java>1.6.0_1</java>
|
||||
<class>org.jivesoftware.spark.otrplug.OTRPlugin</class>
|
||||
<os>Windows,Linux,Mac</os>
|
||||
</plugin>
|
||||
|
||||
@ -33,7 +33,8 @@ public class OTRManager extends ChatRoomListenerAdapter {
|
||||
private MessageListenerHandler _msgListener;
|
||||
private Map<String, OTRSession> _activeSessions = new HashMap<String,OTRSession>();
|
||||
final ChatManager chatManager = SparkManager.getChatManager();
|
||||
private static OtrKeyManager _keyManager;
|
||||
private static MyOtrKeyManager _keyManager;
|
||||
|
||||
|
||||
private OTRManager()
|
||||
{
|
||||
@ -81,7 +82,7 @@ public class OTRManager extends ChatRoomListenerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
public OtrKeyManager getKeyManager()
|
||||
public MyOtrKeyManager getKeyManager()
|
||||
{
|
||||
return _keyManager;
|
||||
}
|
||||
|
||||
@ -0,0 +1,139 @@
|
||||
|
||||
package org.jivesoftware.spark.otrplug;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
|
||||
/**
|
||||
* RoarProperties file stuff
|
||||
*
|
||||
* @author wolf.posdorfer
|
||||
*
|
||||
*/
|
||||
public class OTRProperties {
|
||||
private Properties props;
|
||||
private File configFile;
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
private static OTRProperties instance = null;
|
||||
|
||||
/**
|
||||
* returns the Instance of this Properties file
|
||||
* @return
|
||||
*/
|
||||
public static OTRProperties getInstance() {
|
||||
synchronized (LOCK) {
|
||||
if (instance == null) {
|
||||
instance = new OTRProperties();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private OTRProperties() {
|
||||
this.props = new Properties();
|
||||
|
||||
try {
|
||||
props.load(new FileInputStream(getConfigFile()));
|
||||
} catch (IOException e) {
|
||||
// Can't load ConfigFile
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private File getConfigFile() {
|
||||
if (configFile == null)
|
||||
configFile = new File(SparkManager.getUserDirectory(), "otr.properties");
|
||||
|
||||
return configFile;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try {
|
||||
props.store(new FileOutputStream(getConfigFile()),
|
||||
"Storing OTRPlugin properties");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getIsOTREnabled()
|
||||
{
|
||||
return getBoolean("isOTREnabled", true);
|
||||
}
|
||||
|
||||
public void setIsOTREnabled(boolean enabled)
|
||||
{
|
||||
setBoolean("isOTREnabeld", enabled);
|
||||
}
|
||||
|
||||
|
||||
// ===============================================================================
|
||||
// ===============================================================================
|
||||
// ===============================================================================
|
||||
private boolean getBoolean(String property, boolean defaultValue) {
|
||||
return Boolean.parseBoolean(props.getProperty(property,
|
||||
Boolean.toString(defaultValue)));
|
||||
}
|
||||
|
||||
private void setBoolean(String property, boolean value) {
|
||||
props.setProperty(property, Boolean.toString(value));
|
||||
}
|
||||
|
||||
private int getInt(String property) {
|
||||
return Integer.parseInt(props.getProperty(property, "0"));
|
||||
}
|
||||
|
||||
private void setInt(String property, int integer) {
|
||||
props.setProperty(property, "" + integer);
|
||||
}
|
||||
|
||||
private void setColor(String property, Color color) {
|
||||
props.setProperty(property, convertColor(color));
|
||||
}
|
||||
|
||||
private Color getColor(String property, Color defaultcolor) {
|
||||
try {
|
||||
return convertString(props.getProperty(property));
|
||||
} catch (Exception e) {
|
||||
return defaultcolor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getProperty(String property) {
|
||||
return props.getProperty(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link String} matching xxx,xxx,xxx to a {@link Color}<br>
|
||||
* where xxx is a number from 0 to 255
|
||||
*
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public static Color convertString(String s) throws Exception {
|
||||
String[] arr = s.split(",");
|
||||
return new Color(Integer.parseInt(arr[0]), Integer.parseInt(arr[1]),
|
||||
Integer.parseInt(arr[2]));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link Color} to a {@link String} in this format:<br>
|
||||
* <b>xxx,xxx,xxx</b> <br>
|
||||
* where xxx is a number from 0 to 255
|
||||
*
|
||||
* @param color
|
||||
* @return
|
||||
*/
|
||||
public static String convertColor(Color color) {
|
||||
return color.getRed() + "," + color.getGreen() + "," + color.getBlue();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package org.jivesoftware.spark.otrplug;
|
||||
|
||||
import java.util.PropertyResourceBundle;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import org.jivesoftware.spark.util.log.Log;
|
||||
|
||||
public class OTRResources {
|
||||
|
||||
private static PropertyResourceBundle prb;
|
||||
|
||||
static ClassLoader cl = OTRResources.class.getClassLoader();
|
||||
|
||||
static {
|
||||
prb = (PropertyResourceBundle) ResourceBundle.getBundle("i18n/otrplugin_i18n");
|
||||
}
|
||||
|
||||
public static final String getString(String propertyName) {
|
||||
try {
|
||||
return prb.getString(propertyName);
|
||||
} catch (Exception e) {
|
||||
Log.error(e);
|
||||
return propertyName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -32,276 +32,264 @@ import net.java.otr4j.session.SessionID;
|
||||
|
||||
public class MyOtrKeyManager implements OtrKeyManager {
|
||||
|
||||
private OtrKeyManagerStore store;
|
||||
private OtrKeyManagerStore store;
|
||||
|
||||
public MyOtrKeyManager(OtrKeyManagerStore store) {
|
||||
this.store = store;
|
||||
public MyOtrKeyManager(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();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private File getConfigurationFile() throws IOException {
|
||||
File configFile = new File(filepath);
|
||||
if (!configFile.exists())
|
||||
configFile.createNewFile();
|
||||
return configFile;
|
||||
}
|
||||
|
||||
public MyOtrKeyManager(String filepath) throws IOException {
|
||||
this.store = new DefaultPropertiesStore(filepath);
|
||||
public void setProperty(String id, boolean value) {
|
||||
properties.setProperty(id, "true");
|
||||
try {
|
||||
this.store();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private List<OtrKeyManagerListener> listeners = new Vector<OtrKeyManagerListener>();
|
||||
|
||||
public void addListener(OtrKeyManagerListener l) {
|
||||
synchronized (listeners) {
|
||||
if (!listeners.contains(l))
|
||||
listeners.add(l);
|
||||
}
|
||||
private void store() throws FileNotFoundException, IOException {
|
||||
OutputStream out = new FileOutputStream(getConfigurationFile());
|
||||
properties.store(out, null);
|
||||
out.close();
|
||||
}
|
||||
|
||||
public void removeListener(OtrKeyManagerListener l) {
|
||||
synchronized (listeners) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
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 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 removeProperty(String id) {
|
||||
properties.remove(id);
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
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 MyOtrKeyManager(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
package org.jivesoftware.spark.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
|
||||
import javax.swing.event.TableModelListener;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
||||
import org.jivesoftware.spark.otrplug.OTRResources;
|
||||
|
||||
public class OTRKeyTable extends JComponent {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -2922785387942547350L;
|
||||
private JTable _table;
|
||||
private DefaultTableModel _tableModel;
|
||||
|
||||
public OTRKeyTable() {
|
||||
|
||||
final String[] header = { OTRResources.getString("otr.table.jid"), OTRResources.getString("otr.table.public.key"), OTRResources.getString("otr.key.verified") };
|
||||
|
||||
_tableModel = new MyTableModel(header);
|
||||
_table = new JTable(_tableModel);
|
||||
|
||||
this.setLayout(new BorderLayout());
|
||||
this.add(new JScrollPane(_table), BorderLayout.CENTER);
|
||||
|
||||
}
|
||||
|
||||
class MyTableModel extends DefaultTableModel {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -2930577433474767242L;
|
||||
|
||||
public MyTableModel(String[] headers) {
|
||||
super(headers, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
if (column == 2)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
if (columnIndex == 2) {
|
||||
return Boolean.class;
|
||||
} else
|
||||
return String.class;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void addTableChangeListener(TableModelListener listener) {
|
||||
_tableModel.addTableModelListener(listener);
|
||||
}
|
||||
|
||||
public void addEntry(String jid, String hash, boolean verified) {
|
||||
Vector<Object> data = new Vector<Object>(3);
|
||||
|
||||
data.add(jid);
|
||||
data.add(hash);
|
||||
data.add(verified);
|
||||
|
||||
_tableModel.addRow(data);
|
||||
}
|
||||
|
||||
public Object getValueAt(int row, int col) {
|
||||
return _tableModel.getValueAt(row, col);
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,46 +3,157 @@ package org.jivesoftware.spark.ui;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.TableModelEvent;
|
||||
import javax.swing.event.TableModelListener;
|
||||
|
||||
import net.java.otr4j.session.SessionID;
|
||||
|
||||
import org.jivesoftware.smack.RosterEntry;
|
||||
import org.jivesoftware.spark.SparkManager;
|
||||
import org.jivesoftware.spark.component.VerticalFlowLayout;
|
||||
import org.jivesoftware.spark.otrplug.OTRManager;
|
||||
import org.jivesoftware.spark.otrplug.OTRProperties;
|
||||
import org.jivesoftware.spark.otrplug.OTRResources;
|
||||
|
||||
public class OTRPrefPanel extends JPanel{
|
||||
|
||||
public class OTRPrefPanel extends JPanel {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -7125162190413040003L;
|
||||
private OTRManager _manager;
|
||||
private SessionID _mySession = new SessionID(SparkManager.getConnection().getUser(), SparkManager.getConnection().getUser(), "Scytale");
|
||||
public OTRPrefPanel()
|
||||
{
|
||||
|
||||
private JCheckBox _enableOTR;
|
||||
private JCheckBox _closeSessionOff;
|
||||
private JCheckBox _closeSessionOnWindowClose;
|
||||
private JLabel _currentKeyLabel;
|
||||
private JButton _renewPrivateKey;
|
||||
private OTRKeyTable _keytable;
|
||||
private JTextField _privateKey;
|
||||
private JPanel _gridPanel;
|
||||
private MyOtrKeyManager _keyManager;
|
||||
private OTRProperties _properties;
|
||||
|
||||
public OTRPrefPanel() {
|
||||
|
||||
_manager = OTRManager.getInstance();
|
||||
setLayout(new GridBagLayout());
|
||||
|
||||
_keyManager = _manager.getKeyManager();
|
||||
_properties = OTRProperties.getInstance();
|
||||
setLayout(new VerticalFlowLayout());
|
||||
init();
|
||||
buildGUI();
|
||||
}
|
||||
|
||||
|
||||
private void buildGUI()
|
||||
{
|
||||
//_manager.getKeyManager().generateLocalKeyPair(_mySession);
|
||||
KeyPair key = _manager.getKeyManager().loadLocalKeyPair(_mySession);
|
||||
|
||||
String privkey = _manager.getKeyManager().getLocalFingerprint(_mySession);
|
||||
|
||||
System.out.println( privkey);
|
||||
this.add(new JLabel("key: "), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
|
||||
this.add(new JTextField(privkey), new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
|
||||
|
||||
|
||||
OtrEnableSwitch();
|
||||
this.add(_gridPanel);
|
||||
}
|
||||
|
||||
private void OtrEnableSwitch() {
|
||||
|
||||
_enableOTR.setSelected(_properties.getIsOTREnabled());
|
||||
|
||||
}
|
||||
|
||||
public boolean isOTREnabled()
|
||||
{
|
||||
return _enableOTR.isSelected();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
_gridPanel = new JPanel(new GridBagLayout());
|
||||
|
||||
_enableOTR = new JCheckBox();
|
||||
_enableOTR.setText(OTRResources.getString("otr.enable"));
|
||||
|
||||
_closeSessionOff = new JCheckBox();
|
||||
_closeSessionOff.setText(OTRResources.getString("otr.close.session.on.contact.off"));
|
||||
|
||||
_closeSessionOnWindowClose = new JCheckBox();
|
||||
_closeSessionOnWindowClose.setText(OTRResources.getString("otr.close.session.on.window.close"));
|
||||
|
||||
_currentKeyLabel = new JLabel();
|
||||
_currentKeyLabel.setText(OTRResources.getString("current.priv.key"));
|
||||
|
||||
_renewPrivateKey = new JButton();
|
||||
_renewPrivateKey.setText(OTRResources.getString("renew.current.key"));
|
||||
_renewPrivateKey.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SessionID mySession = new SessionID(SparkManager.getConnection().getUser(), "no one", "Scytale");
|
||||
_manager.getKeyManager().generateLocalKeyPair(mySession);
|
||||
_privateKey.setText(getCurrentLocalKey());
|
||||
}
|
||||
});
|
||||
|
||||
_privateKey = new JTextField();
|
||||
_privateKey.setEditable(false);
|
||||
_privateKey.setSize(300, 20);
|
||||
_privateKey.setText(getCurrentLocalKey());
|
||||
|
||||
_keytable = new OTRKeyTable();
|
||||
|
||||
loadRemoteKeys();
|
||||
|
||||
_keytable.addTableChangeListener(new TableModelListener() {
|
||||
|
||||
@Override
|
||||
public void tableChanged(TableModelEvent e) {
|
||||
int col = e.getColumn();
|
||||
int row = e.getFirstRow();
|
||||
|
||||
if (col == 2) {
|
||||
boolean selection = (Boolean) _keytable.getValueAt(row, col);
|
||||
String JID = (String)_keytable.getValueAt(row, 0);
|
||||
SessionID curSelectedSession = new SessionID(SparkManager.getConnection().getUser(), JID, "Scytale");
|
||||
if (selection) {
|
||||
_keyManager.verify(curSelectedSession);
|
||||
} else
|
||||
|
||||
{
|
||||
_keyManager.unverify(curSelectedSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private String getCurrentLocalKey() {
|
||||
SessionID mySession = new SessionID(SparkManager.getConnection().getUser(), "no one", "Scytale");
|
||||
String myKey = _keyManager.getLocalFingerprint(mySession);
|
||||
return myKey;
|
||||
}
|
||||
|
||||
private void loadRemoteKeys() {
|
||||
|
||||
for (RosterEntry entry : SparkManager.getConnection().getRoster().getEntries()) {
|
||||
SessionID curSession = new SessionID(SparkManager.getConnection().getUser(), entry.getUser(), "Scytale");
|
||||
String remoteKey = _keyManager.getRemoteFingerprint(curSession);
|
||||
if (remoteKey != null) {
|
||||
boolean isVerified = _keyManager.isVerified(curSession);
|
||||
_keytable.addEntry(entry.getUser(), remoteKey, isVerified);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildGUI() {
|
||||
_gridPanel.setBorder(BorderFactory.createTitledBorder(OTRResources.getString("otr.settings")));
|
||||
|
||||
_gridPanel.add(_enableOTR, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
_gridPanel.add(_closeSessionOff, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
_gridPanel.add(_closeSessionOnWindowClose, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
_gridPanel.add(_currentKeyLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 0, 0, 0), 0, 0));
|
||||
_gridPanel.add(_privateKey, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 0), 0, 0));
|
||||
_gridPanel.add(_renewPrivateKey, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
|
||||
_gridPanel.add(_keytable, new GridBagConstraints(0, 5, 2, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(20, 0, 0, 0), 0, 0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -4,13 +4,17 @@ import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import org.jivesoftware.spark.otrplug.OTRManager;
|
||||
import org.jivesoftware.spark.otrplug.OTRProperties;
|
||||
import org.jivesoftware.spark.otrplug.OTRResources;
|
||||
import org.jivesoftware.spark.preference.Preference;
|
||||
|
||||
public class OTRPreferences implements Preference {
|
||||
|
||||
private OTRPrefPanel pref = new OTRPrefPanel();
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Off-The-Record Plugin";
|
||||
return OTRResources.getString("otr.title");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -27,7 +31,7 @@ public class OTRPreferences implements Preference {
|
||||
@Override
|
||||
public String getListName() {
|
||||
|
||||
return "OTR";
|
||||
return OTRResources.getString("otr.list.entry");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -38,7 +42,7 @@ public class OTRPreferences implements Preference {
|
||||
|
||||
@Override
|
||||
public JComponent getGUI() {
|
||||
return new OTRPrefPanel();
|
||||
return pref;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,7 +53,8 @@ public class OTRPreferences implements Preference {
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
// TODO Auto-generated method stub
|
||||
OTRProperties.getInstance().setIsOTREnabled(pref.isOTREnabled());
|
||||
OTRProperties.getInstance().save();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -162,8 +162,20 @@ public class OTRSession {
|
||||
{
|
||||
PublicKey rempubkey = _engine.getRemotePublicKey(_mySession);
|
||||
OTRManager.getInstance().getKeyManager().savePublicKey(_mySession, rempubkey);
|
||||
remkey = OTRManager.getInstance().getKeyManager().getRemoteFingerprint(_mySession);
|
||||
remkey = OTRManager.getInstance().getKeyManager().getRemoteFingerprint(_mySession);
|
||||
}
|
||||
|
||||
System.out.println(remkey);
|
||||
|
||||
if (OTRManager.getInstance().getKeyManager().isVerified(_mySession))
|
||||
{
|
||||
System.out.println("verified");
|
||||
|
||||
}
|
||||
|
||||
System.out.println(_mySession.getUserID());
|
||||
System.out.println( OTRManager.getInstance().getKeyManager().getLocalFingerprint(_mySession));;
|
||||
|
||||
//String remkey = OTRManager.getInstance().getKeyManager().getRemoteFingerprint(_mySession);
|
||||
_chatRoom.getTranscriptWindow().insertNotificationMessage("From now on, your conversation is encrypted Remotekey: "+remkey, Color.gray);
|
||||
_otrButton.setIcon(new ImageIcon(cl.getResource("otr_on.png")));
|
||||
|
||||
19
src/plugins/otr/src/resources/i18n/otrplugin_i18n.properties
Normal file
19
src/plugins/otr/src/resources/i18n/otrplugin_i18n.properties
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
# OTR language file
|
||||
|
||||
otr.title = Off-the-Record Messaging
|
||||
otr.list.entry = OTR Messaging
|
||||
otr.settings = OTR Settings
|
||||
otr.enable = OTR Enabled
|
||||
current.priv.key = Current private key:
|
||||
renew.current.key = Generate a new key
|
||||
otr.close.session.on.window.close = Close OTR session when chat window is closed
|
||||
otr.close.session.on.contact.off = Close OTR session when contact went offline
|
||||
|
||||
|
||||
#Table Columns
|
||||
otr.table.jid = User's JID
|
||||
otr.table.public.key = Public key
|
||||
otr.key.verified = Verified
|
||||
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
|
||||
# OTR language file
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.3 KiB |
Reference in New Issue
Block a user