195 lines
9.2 KiB
Java
195 lines
9.2 KiB
Java
package de.vanitasvitae.oxclient;
|
|
|
|
import java.io.File;
|
|
import java.util.Scanner;
|
|
import java.util.Set;
|
|
|
|
import org.jivesoftware.smack.packet.Message;
|
|
import org.jivesoftware.smack.packet.Presence;
|
|
import org.jivesoftware.smack.roster.Roster;
|
|
import org.jivesoftware.smack.roster.RosterEntry;
|
|
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
|
import org.jivesoftware.smackx.ox.OXInstantMessagingManager;
|
|
import org.jivesoftware.smackx.ox.OpenPgpManager;
|
|
import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint;
|
|
import org.jivesoftware.smackx.ox.PubSubDelegate;
|
|
import org.jivesoftware.smackx.ox.bouncycastle.BCOpenPgpProvider;
|
|
import org.jivesoftware.smackx.ox.bouncycastle.FileBasedBcOpenPgpStore;
|
|
import org.jivesoftware.smackx.ox.callback.SecretKeyBackupSelectionCallback;
|
|
import org.jivesoftware.smackx.ox.callback.SecretKeyRestoreSelectionCallback;
|
|
|
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.BouncyGPG;
|
|
import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.callbacks.KeyringConfigCallbacks;
|
|
import org.jxmpp.jid.BareJid;
|
|
import org.jxmpp.jid.EntityBareJid;
|
|
import org.jxmpp.jid.impl.JidCreate;
|
|
import org.jxmpp.stringprep.XmppStringprepException;
|
|
|
|
public class Client {
|
|
|
|
private final XMPPTCPConnection connection;
|
|
|
|
public Client(String username, String password) throws XmppStringprepException {
|
|
this.connection = new XMPPTCPConnection(username, password);
|
|
}
|
|
|
|
public void start() throws Exception {
|
|
BouncyGPG.registerProvider();
|
|
connection.connect().login();
|
|
Scanner scanner = new Scanner(System.in);
|
|
|
|
BareJid user = connection.getUser().asBareJid();
|
|
OpenPgpManager manager = OpenPgpManager.getInstanceFor(connection);
|
|
BCOpenPgpProvider provider = new BCOpenPgpProvider(user);
|
|
FileBasedBcOpenPgpStore store = new FileBasedBcOpenPgpStore(new File("oxstore"), user,
|
|
KeyringConfigCallbacks.withUnprotectedKeys());
|
|
provider.setStore(store);
|
|
manager.setOpenPgpProvider(provider);
|
|
|
|
OXInstantMessagingManager instantManager = OXInstantMessagingManager.getInstanceFor(connection);
|
|
instantManager.addOpenPgpEncryptedMessageListener((from, originalMessage, decryptedPayload, chat) -> System.out.println("Received OX chat message from " + from + ":\n" +
|
|
decryptedPayload.<Message.Body>getExtension(
|
|
Message.Body.ELEMENT, Message.Body.NAMESPACE)
|
|
.getMessage()));
|
|
instantManager.announceSupportForOxInstantMessaging();
|
|
|
|
Roster.getInstanceFor(connection).setSubscriptionMode(Roster.SubscriptionMode.accept_all);
|
|
|
|
System.out.println("Client logged in successfully. To get a list of available commands, enter \"help\".");
|
|
|
|
BareJid jid;
|
|
outerloop: while (true) {
|
|
String cmd = scanner.nextLine();
|
|
switch (cmd) {
|
|
case "publishKeys":
|
|
if (provider.primaryOpenPgpKeyPairFingerprint() == null) {
|
|
System.out.println("No private key available. Try to generate one using \"generateKey\"");
|
|
break;
|
|
}
|
|
manager.announceSupportAndPublish();
|
|
System.out.println("Keys published successfully.");
|
|
break;
|
|
|
|
case "listContacts":
|
|
for (RosterEntry e : Roster.getInstanceFor(connection).getEntries()) {
|
|
System.out.println(e.getJid() +
|
|
" canSeeMe: " + e.canSeeMyPresence() +
|
|
" canSeeThem: " + e.canSeeHisPresence() +
|
|
" OX-support: " + instantManager.contactSupportsOxInstantMessaging(e.getJid()));
|
|
}
|
|
break;
|
|
|
|
case "addContact":
|
|
System.out.println("Enter a JID:");
|
|
jid = JidCreate.bareFrom(scanner.nextLine());
|
|
System.out.println("Enter a Nickname:");
|
|
String nick = scanner.nextLine();
|
|
|
|
Roster.getInstanceFor(connection).createEntry(jid, nick, null);
|
|
break;
|
|
|
|
case "exit":
|
|
case "quit":
|
|
connection.disconnect(new Presence(Presence.Type.unavailable));
|
|
System.out.println("Bye Bye!");
|
|
break outerloop;
|
|
|
|
case "generateKey":
|
|
provider.createOpenPgpKeyPair();
|
|
System.out.println("Key generated.");
|
|
System.out.println(manager.getOurFingerprint());
|
|
break;
|
|
|
|
case "deleteMetadata":
|
|
PubSubDelegate.deletePubkeysListNode(connection);
|
|
System.out.println("Metadata deleted.");
|
|
break;
|
|
|
|
case "fingerprint":
|
|
System.out.println("Enter a JID (leave empty to display our fingerprint):");
|
|
String l = scanner.nextLine();
|
|
|
|
if (l.isEmpty()) {
|
|
System.out.println(provider.primaryOpenPgpKeyPairFingerprint());
|
|
} else {
|
|
jid = JidCreate.bareFrom(l);
|
|
for (OpenPgpV4Fingerprint f : provider.availableOpenPgpPublicKeysFingerprints(jid)) {
|
|
System.out.println(f);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case "encrypt":
|
|
if (provider.primaryOpenPgpKeyPairFingerprint() == null) {
|
|
System.out.println("No private key available. Try to generate one using \"generateKey\"");
|
|
break;
|
|
}
|
|
System.out.println("Enter a JID:");
|
|
jid = JidCreate.entityBareFrom(scanner.nextLine());
|
|
System.out.println("Enter a message:");
|
|
String message = scanner.nextLine();
|
|
|
|
instantManager.chatWith(((EntityBareJid) jid).asEntityBareJid())
|
|
.send(new Message(jid), message);
|
|
System.out.println("Message sent.");
|
|
break;
|
|
|
|
case "backup":
|
|
if (provider.primaryOpenPgpKeyPairFingerprint() == null) {
|
|
System.out.println("No private key available. Try to generate one using \"generateKey\"");
|
|
break;
|
|
}
|
|
manager.backupSecretKeyToServer(
|
|
System.out::println,
|
|
availableSecretKeys -> availableSecretKeys);
|
|
break;
|
|
|
|
case "restore":
|
|
manager.restoreSecretKeyServerBackup(
|
|
() -> {
|
|
System.out.println("Enter Backup Code:");
|
|
return scanner.nextLine();
|
|
},
|
|
availableSecretKeys -> {
|
|
if (availableSecretKeys.size() > 1) {
|
|
System.out.println("Select key to restore:");
|
|
int i = 1;
|
|
for (OpenPgpV4Fingerprint f : availableSecretKeys) {
|
|
System.out.println(i++ + f.toString());
|
|
}
|
|
int s = scanner.nextInt();
|
|
i = 1;
|
|
for (OpenPgpV4Fingerprint f : availableSecretKeys) {
|
|
if (i++ == s) {
|
|
return f;
|
|
}
|
|
}
|
|
System.out.println("Invalid selection.");
|
|
return null;
|
|
}
|
|
if (availableSecretKeys.size() == 1) {
|
|
return availableSecretKeys.iterator().next();
|
|
}
|
|
System.out.println("Backup does not contain a key.");
|
|
return null;
|
|
});
|
|
System.out.println(manager.getOurFingerprint());
|
|
break;
|
|
|
|
case "help":
|
|
System.out.println("Available commands:");
|
|
System.out.println("\tfingerprint - Display OpenPGP fingerprints of users.");
|
|
System.out.println("\tlistContacts - List the roster of contacts.");
|
|
System.out.println("\taddContact - Add a user to the roster.");
|
|
System.out.println("\tencrypt - Send an encrypted message to a recipient.");
|
|
System.out.println("\tgenerateKey - Generate and use a fresh OpenPGP key.");
|
|
System.out.println("\tpublishKeys - Publish public keys.");
|
|
System.out.println("\tbackup - Put a backup of our secret keys into a private pubsub node.");
|
|
System.out.println("\trestore - Restore a secret key backup.");
|
|
System.out.println("\texit/quit - Exit the client.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|