mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-27 14:32:06 +01:00
Temp
This commit is contained in:
parent
06dbb37a0e
commit
8e4013fff3
25 changed files with 422 additions and 185 deletions
|
@ -16,8 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.openpgp;
|
package org.jivesoftware.smackx.openpgp;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertTrue;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
@ -29,11 +27,10 @@ import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smackx.ox.OXInstantMessagingManager;
|
import org.jivesoftware.smackx.ox.OXInstantMessagingManager;
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpContact;
|
import org.jivesoftware.smackx.ox.OpenPgpContact;
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpManager;
|
import org.jivesoftware.smackx.ox.OpenPgpManager;
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint;
|
import org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider;
|
||||||
import org.jivesoftware.smackx.ox.bouncycastle.FileBasedPainlessOpenPgpStore;
|
|
||||||
import org.jivesoftware.smackx.ox.bouncycastle.PainlessOpenPgpProvider;
|
|
||||||
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
import org.jivesoftware.smackx.ox.listener.OxMessageListener;
|
import org.jivesoftware.smackx.ox.listener.OxMessageListener;
|
||||||
|
import org.jivesoftware.smackx.ox.store.filebased.FileBasedOpenPgpStore;
|
||||||
import org.jivesoftware.smackx.ox.util.PubSubDelegate;
|
import org.jivesoftware.smackx.ox.util.PubSubDelegate;
|
||||||
|
|
||||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||||
|
@ -43,6 +40,7 @@ import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
|
||||||
import org.pgpainless.pgpainless.key.protection.UnprotectedKeysProtector;
|
import org.pgpainless.pgpainless.key.protection.UnprotectedKeysProtector;
|
||||||
|
|
||||||
public class BasicOpenPgpInstantMessagingIntegrationTest extends AbstractOpenPgpIntegrationTest {
|
public class BasicOpenPgpInstantMessagingIntegrationTest extends AbstractOpenPgpIntegrationTest {
|
||||||
|
@ -75,11 +73,13 @@ public class BasicOpenPgpInstantMessagingIntegrationTest extends AbstractOpenPgp
|
||||||
final SimpleResultSyncPoint bobReceivedMessage = new SimpleResultSyncPoint();
|
final SimpleResultSyncPoint bobReceivedMessage = new SimpleResultSyncPoint();
|
||||||
final String body = "Writing integration tests is an annoying task, but it has to be done, so lets do it!!!";
|
final String body = "Writing integration tests is an annoying task, but it has to be done, so lets do it!!!";
|
||||||
|
|
||||||
FileBasedPainlessOpenPgpStore aliceStore = new FileBasedPainlessOpenPgpStore(aliceStorePath, new UnprotectedKeysProtector());
|
FileBasedOpenPgpStore aliceStore = new FileBasedOpenPgpStore(aliceStorePath);
|
||||||
FileBasedPainlessOpenPgpStore bobStore = new FileBasedPainlessOpenPgpStore(bobStorePath, new UnprotectedKeysProtector());
|
aliceStore.setKeyRingProtector(new UnprotectedKeysProtector());
|
||||||
|
FileBasedOpenPgpStore bobStore = new FileBasedOpenPgpStore(bobStorePath);
|
||||||
|
bobStore.setKeyRingProtector(new UnprotectedKeysProtector());
|
||||||
|
|
||||||
PainlessOpenPgpProvider aliceProvider = new PainlessOpenPgpProvider(alice, aliceStore);
|
PainlessOpenPgpProvider aliceProvider = new PainlessOpenPgpProvider(aliceStore);
|
||||||
PainlessOpenPgpProvider bobProvider = new PainlessOpenPgpProvider(bob, bobStore);
|
PainlessOpenPgpProvider bobProvider = new PainlessOpenPgpProvider(bobStore);
|
||||||
|
|
||||||
OpenPgpManager aliceOpenPgp = OpenPgpManager.getInstanceFor(aliceConnection);
|
OpenPgpManager aliceOpenPgp = OpenPgpManager.getInstanceFor(aliceConnection);
|
||||||
OpenPgpManager bobOpenPgp = OpenPgpManager.getInstanceFor(bobConnection);
|
OpenPgpManager bobOpenPgp = OpenPgpManager.getInstanceFor(bobConnection);
|
||||||
|
@ -104,20 +104,13 @@ public class BasicOpenPgpInstantMessagingIntegrationTest extends AbstractOpenPgp
|
||||||
aliceFingerprint = aliceOpenPgp.generateAndImportKeyPair(alice);
|
aliceFingerprint = aliceOpenPgp.generateAndImportKeyPair(alice);
|
||||||
bobFingerprint = bobOpenPgp.generateAndImportKeyPair(bob);
|
bobFingerprint = bobOpenPgp.generateAndImportKeyPair(bob);
|
||||||
|
|
||||||
aliceStore.setSigningKeyPairFingerprint(aliceFingerprint);
|
|
||||||
bobStore.setSigningKeyPairFingerprint(bobFingerprint);
|
|
||||||
|
|
||||||
aliceOpenPgp.announceSupportAndPublish();
|
aliceOpenPgp.announceSupportAndPublish();
|
||||||
bobOpenPgp.announceSupportAndPublish();
|
bobOpenPgp.announceSupportAndPublish();
|
||||||
|
|
||||||
OpenPgpContact bobForAlice = aliceOpenPgp.getOpenPgpContact(bob.asEntityBareJidIfPossible());
|
OpenPgpContact bobForAlice = aliceOpenPgp.getOpenPgpContact(bob.asEntityBareJidIfPossible());
|
||||||
OpenPgpContact aliceForBob = bobOpenPgp.getOpenPgpContact(alice.asEntityBareJidIfPossible());
|
OpenPgpContact aliceForBob = bobOpenPgp.getOpenPgpContact(alice.asEntityBareJidIfPossible());
|
||||||
|
|
||||||
bobForAlice.updateKeys();
|
// TODO: Update keys
|
||||||
aliceForBob.updateKeys();
|
|
||||||
|
|
||||||
assertTrue(bobForAlice.getActiveKeys().contains(bobFingerprint));
|
|
||||||
assertTrue(aliceForBob.getActiveKeys().contains(aliceFingerprint));
|
|
||||||
|
|
||||||
aliceInstantMessaging.sendOxMessage(bobForAlice, body);
|
aliceInstantMessaging.sendOxMessage(bobForAlice, body);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.jivesoftware.smackx.openpgp;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertEquals;
|
import static junit.framework.TestCase.assertEquals;
|
||||||
import static junit.framework.TestCase.assertFalse;
|
import static junit.framework.TestCase.assertFalse;
|
||||||
|
import static junit.framework.TestCase.assertNotNull;
|
||||||
import static junit.framework.TestCase.assertNull;
|
import static junit.framework.TestCase.assertNull;
|
||||||
import static junit.framework.TestCase.assertTrue;
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
|
||||||
|
@ -34,21 +35,23 @@ import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smack.util.FileUtils;
|
import org.jivesoftware.smack.util.FileUtils;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpManager;
|
import org.jivesoftware.smackx.ox.OpenPgpManager;
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpV4Fingerprint;
|
import org.jivesoftware.smackx.ox.OpenPgpSelf;
|
||||||
import org.jivesoftware.smackx.ox.bouncycastle.FileBasedPainlessOpenPgpStore;
|
|
||||||
import org.jivesoftware.smackx.ox.bouncycastle.PainlessOpenPgpProvider;
|
|
||||||
import org.jivesoftware.smackx.ox.callback.backup.AskForBackupCodeCallback;
|
import org.jivesoftware.smackx.ox.callback.backup.AskForBackupCodeCallback;
|
||||||
import org.jivesoftware.smackx.ox.callback.backup.DisplayBackupCodeCallback;
|
import org.jivesoftware.smackx.ox.callback.backup.DisplayBackupCodeCallback;
|
||||||
import org.jivesoftware.smackx.ox.callback.backup.SecretKeyBackupSelectionCallback;
|
import org.jivesoftware.smackx.ox.callback.backup.SecretKeyBackupSelectionCallback;
|
||||||
import org.jivesoftware.smackx.ox.callback.backup.SecretKeyRestoreSelectionCallback;
|
import org.jivesoftware.smackx.ox.callback.backup.SecretKeyRestoreSelectionCallback;
|
||||||
|
import org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider;
|
||||||
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
|
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
|
||||||
|
import org.jivesoftware.smackx.ox.exception.MissingOpenPgpKeyPairException;
|
||||||
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
|
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
|
||||||
import org.jivesoftware.smackx.ox.exception.NoBackupFoundException;
|
import org.jivesoftware.smackx.ox.exception.NoBackupFoundException;
|
||||||
import org.jivesoftware.smackx.ox.exception.SmackOpenPgpException;
|
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
|
||||||
|
import org.jivesoftware.smackx.ox.store.filebased.FileBasedOpenPgpStore;
|
||||||
import org.jivesoftware.smackx.ox.util.PubSubDelegate;
|
import org.jivesoftware.smackx.ox.util.PubSubDelegate;
|
||||||
import org.jivesoftware.smackx.pubsub.PubSubException;
|
import org.jivesoftware.smackx.pubsub.PubSubException;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||||
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||||
import org.igniterealtime.smack.inttest.TestNotPossibleException;
|
import org.igniterealtime.smack.inttest.TestNotPossibleException;
|
||||||
|
@ -56,6 +59,7 @@ import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
|
||||||
import org.pgpainless.pgpainless.key.protection.UnprotectedKeysProtector;
|
import org.pgpainless.pgpainless.key.protection.UnprotectedKeysProtector;
|
||||||
|
|
||||||
public class SecretKeyBackupRestoreIntegrationTest extends AbstractOpenPgpIntegrationTest {
|
public class SecretKeyBackupRestoreIntegrationTest extends AbstractOpenPgpIntegrationTest {
|
||||||
|
@ -90,24 +94,29 @@ public class SecretKeyBackupRestoreIntegrationTest extends AbstractOpenPgpIntegr
|
||||||
}
|
}
|
||||||
|
|
||||||
@SmackIntegrationTest
|
@SmackIntegrationTest
|
||||||
public void test() throws SmackOpenPgpException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
|
public void test() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException,
|
||||||
NoSuchProviderException, IOException, InterruptedException, PubSubException.NotALeafNodeException,
|
NoSuchProviderException, IOException, InterruptedException, PubSubException.NotALeafNodeException,
|
||||||
SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException,
|
||||||
SmackException.NotLoggedInException, SmackException.FeatureNotSupportedException,
|
SmackException.NotLoggedInException, SmackException.FeatureNotSupportedException,
|
||||||
MissingUserIdOnKeyException, NoBackupFoundException, InvalidBackupCodeException, PGPException {
|
MissingUserIdOnKeyException, NoBackupFoundException, InvalidBackupCodeException, PGPException, MissingOpenPgpKeyPairException {
|
||||||
|
|
||||||
FileBasedPainlessOpenPgpStore beforeStore = new FileBasedPainlessOpenPgpStore(beforePath, new UnprotectedKeysProtector());
|
OpenPgpStore beforeStore = new FileBasedOpenPgpStore(beforePath);
|
||||||
PainlessOpenPgpProvider beforeProvider = new PainlessOpenPgpProvider(alice, beforeStore);
|
beforeStore.setKeyRingProtector(new UnprotectedKeysProtector());
|
||||||
|
PainlessOpenPgpProvider beforeProvider = new PainlessOpenPgpProvider(beforeStore);
|
||||||
OpenPgpManager openPgpManager = OpenPgpManager.getInstanceFor(aliceConnection);
|
OpenPgpManager openPgpManager = OpenPgpManager.getInstanceFor(aliceConnection);
|
||||||
openPgpManager.setOpenPgpProvider(beforeProvider);
|
openPgpManager.setOpenPgpProvider(beforeProvider);
|
||||||
|
|
||||||
assertNull(beforeStore.getSigningKeyPairFingerprint());
|
OpenPgpSelf self = openPgpManager.getOpenPgpSelf();
|
||||||
|
|
||||||
|
assertNull(self.getSigningKeyFingerprint());
|
||||||
|
|
||||||
OpenPgpV4Fingerprint keyFingerprint = openPgpManager.generateAndImportKeyPair(alice);
|
OpenPgpV4Fingerprint keyFingerprint = openPgpManager.generateAndImportKeyPair(alice);
|
||||||
beforeStore.setSigningKeyPairFingerprint(keyFingerprint);
|
assertEquals(keyFingerprint, self.getSigningKeyFingerprint());
|
||||||
assertEquals(keyFingerprint, beforeStore.getSigningKeyPairFingerprint());
|
|
||||||
|
|
||||||
assertTrue(beforeStore.getAvailableKeyPairFingerprints(alice).contains(keyFingerprint));
|
assertTrue(self.getSecretKeys().contains(keyFingerprint.getKeyId()));
|
||||||
|
|
||||||
|
PGPSecretKeyRing beforeKeys = beforeStore.getSecretKeyRing(alice, keyFingerprint);
|
||||||
|
assertNotNull(beforeKeys);
|
||||||
|
|
||||||
openPgpManager.backupSecretKeyToServer(new DisplayBackupCodeCallback() {
|
openPgpManager.backupSecretKeyToServer(new DisplayBackupCodeCallback() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -121,12 +130,15 @@ public class SecretKeyBackupRestoreIntegrationTest extends AbstractOpenPgpIntegr
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
FileBasedPainlessOpenPgpStore afterStore = new FileBasedPainlessOpenPgpStore(afterPath, new UnprotectedKeysProtector());
|
FileBasedOpenPgpStore afterStore = new FileBasedOpenPgpStore(afterPath);
|
||||||
PainlessOpenPgpProvider afterProvider = new PainlessOpenPgpProvider(alice, afterStore);
|
afterStore.setKeyRingProtector(new UnprotectedKeysProtector());
|
||||||
|
PainlessOpenPgpProvider afterProvider = new PainlessOpenPgpProvider(afterStore);
|
||||||
openPgpManager.setOpenPgpProvider(afterProvider);
|
openPgpManager.setOpenPgpProvider(afterProvider);
|
||||||
|
|
||||||
assertNull(afterStore.getSigningKeyPairFingerprint());
|
self = openPgpManager.getOpenPgpSelf();
|
||||||
assertFalse(afterStore.getAvailableKeyPairFingerprints(alice).contains(keyFingerprint));
|
|
||||||
|
assertNull(self.getSigningKeyFingerprint());
|
||||||
|
assertFalse(self.getSecretKeys().contains(keyFingerprint.getKeyId()));
|
||||||
|
|
||||||
OpenPgpV4Fingerprint fingerprint = openPgpManager.restoreSecretKeyServerBackup(new AskForBackupCodeCallback() {
|
OpenPgpV4Fingerprint fingerprint = openPgpManager.restoreSecretKeyServerBackup(new AskForBackupCodeCallback() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -140,11 +152,12 @@ public class SecretKeyBackupRestoreIntegrationTest extends AbstractOpenPgpIntegr
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
assertTrue(afterStore.getAvailableKeyPairFingerprints(alice).contains(keyFingerprint));
|
assertTrue(self.getSecretKeys().contains(keyFingerprint.getKeyId()));
|
||||||
|
|
||||||
afterStore.setSigningKeyPairFingerprint(fingerprint);
|
assertEquals(keyFingerprint, self.getSigningKeyFingerprint());
|
||||||
|
|
||||||
assertEquals(keyFingerprint, afterStore.getSigningKeyPairFingerprint());
|
PGPSecretKeyRing afterKeys = afterStore.getSecretKeyRing(alice, keyFingerprint);
|
||||||
assertTrue(Arrays.equals(beforeStore.getSecretKeyRings(alice).getEncoded(), afterStore.getSecretKeyRings(alice).getEncoded()));
|
assertNotNull(afterKeys);
|
||||||
|
assertTrue(Arrays.equals(beforeKeys.getEncoded(), afterKeys.getEncoded()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.jivesoftware.smackx.ox;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -34,13 +35,14 @@ import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
import org.jivesoftware.smackx.eme.element.ExplicitMessageEncryptionElement;
|
import org.jivesoftware.smackx.eme.element.ExplicitMessageEncryptionElement;
|
||||||
import org.jivesoftware.smackx.hints.element.StoreHint;
|
import org.jivesoftware.smackx.hints.element.StoreHint;
|
||||||
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
import org.jivesoftware.smackx.ox.exception.MissingOpenPgpKeyPairException;
|
|
||||||
import org.jivesoftware.smackx.ox.exception.SmackOpenPgpException;
|
|
||||||
import org.jivesoftware.smackx.ox.listener.OxMessageListener;
|
import org.jivesoftware.smackx.ox.listener.OxMessageListener;
|
||||||
import org.jivesoftware.smackx.ox.listener.internal.SigncryptElementReceivedListener;
|
import org.jivesoftware.smackx.ox.listener.internal.SigncryptElementReceivedListener;
|
||||||
|
|
||||||
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
|
import org.jxmpp.jid.Jid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point of Smacks API for XEP-0374: OpenPGP for XMPP: Instant Messaging.
|
* Entry point of Smacks API for XEP-0374: OpenPGP for XMPP: Instant Messaging.
|
||||||
|
@ -55,10 +57,12 @@ public final class OXInstantMessagingManager extends Manager implements Signcryp
|
||||||
private static final Map<XMPPConnection, OXInstantMessagingManager> INSTANCES = new WeakHashMap<>();
|
private static final Map<XMPPConnection, OXInstantMessagingManager> INSTANCES = new WeakHashMap<>();
|
||||||
|
|
||||||
private final Set<OxMessageListener> oxMessageListeners = new HashSet<>();
|
private final Set<OxMessageListener> oxMessageListeners = new HashSet<>();
|
||||||
|
private final OpenPgpManager openPgpManager;
|
||||||
|
|
||||||
private OXInstantMessagingManager(final XMPPConnection connection) {
|
private OXInstantMessagingManager(final XMPPConnection connection) {
|
||||||
super(connection);
|
super(connection);
|
||||||
OpenPgpManager.getInstanceFor(connection).registerSigncryptReceivedListener(this);
|
openPgpManager = OpenPgpManager.getInstanceFor(connection);
|
||||||
|
openPgpManager.registerSigncryptReceivedListener(this);
|
||||||
announceSupportForOxInstantMessaging();
|
announceSupportForOxInstantMessaging();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,15 +157,13 @@ public final class OXInstantMessagingManager extends Manager implements Signcryp
|
||||||
* @param contact contact capable of OpenPGP for XMPP: Instant Messaging.
|
* @param contact contact capable of OpenPGP for XMPP: Instant Messaging.
|
||||||
* @param body message body.
|
* @param body message body.
|
||||||
* @throws InterruptedException if the thread is interrupted
|
* @throws InterruptedException if the thread is interrupted
|
||||||
* @throws MissingOpenPgpKeyPairException if we cannot access our signing key
|
|
||||||
* @throws IOException IO is dangerous
|
* @throws IOException IO is dangerous
|
||||||
* @throws SmackException.NotConnectedException if we are not connected
|
* @throws SmackException.NotConnectedException if we are not connected
|
||||||
* @throws SmackOpenPgpException in case of an OpenPGP error
|
|
||||||
* @throws SmackException.NotLoggedInException if we are not logged in
|
* @throws SmackException.NotLoggedInException if we are not logged in
|
||||||
*/
|
*/
|
||||||
public void sendOxMessage(OpenPgpContact contact, CharSequence body)
|
public void sendOxMessage(OpenPgpContact contact, CharSequence body)
|
||||||
throws InterruptedException, MissingOpenPgpKeyPairException, IOException,
|
throws InterruptedException, IOException,
|
||||||
SmackException.NotConnectedException, SmackOpenPgpException, SmackException.NotLoggedInException {
|
SmackException.NotConnectedException, SmackException.NotLoggedInException, PGPException {
|
||||||
Message message = new Message(contact.getJid());
|
Message message = new Message(contact.getJid());
|
||||||
List<ExtensionElement> payload = new ArrayList<>();
|
List<ExtensionElement> payload = new ArrayList<>();
|
||||||
payload.add(new Message.Body(null, body.toString()));
|
payload.add(new Message.Body(null, body.toString()));
|
||||||
|
@ -172,7 +174,12 @@ public final class OXInstantMessagingManager extends Manager implements Signcryp
|
||||||
StoreHint.set(message);
|
StoreHint.set(message);
|
||||||
message.setBody("This message is encrypted using XEP-0374: OpenPGP for XMPP: Instant Messaging.");
|
message.setBody("This message is encrypted using XEP-0374: OpenPGP for XMPP: Instant Messaging.");
|
||||||
|
|
||||||
//contact.addSignedEncryptedPayloadTo(message, payload);
|
SigncryptElement signcryptElement = new SigncryptElement(Collections.<Jid>singleton(contact.jid), payload);
|
||||||
|
|
||||||
|
OpenPgpElement encrypted = openPgpManager.getProvider().signAndEncrypt(signcryptElement,
|
||||||
|
openPgpManager.getOpenPgpSelf(), Collections.singleton(contact));
|
||||||
|
|
||||||
|
message.addExtension(encrypted);
|
||||||
|
|
||||||
ChatManager.getInstanceFor(connection()).chatWith(contact.getJid().asEntityBareJidIfPossible()).send(message);
|
ChatManager.getInstanceFor(connection()).chatWith(contact.getJid().asEntityBareJidIfPossible()).send(message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,29 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Paul Schaub.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
package org.jivesoftware.smackx.ox;
|
package org.jivesoftware.smackx.ox;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.ox.selection_strategy.AnnouncedKeys;
|
||||||
|
import org.jivesoftware.smackx.ox.selection_strategy.BareJidUserId;
|
||||||
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
|
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
@ -35,14 +55,25 @@ public class OpenPgpContact {
|
||||||
|
|
||||||
public PGPPublicKeyRingCollection getAnnouncedPublicKeys() throws IOException, PGPException {
|
public PGPPublicKeyRingCollection getAnnouncedPublicKeys() throws IOException, PGPException {
|
||||||
PGPPublicKeyRingCollection anyKeys = getAnyPublicKeys();
|
PGPPublicKeyRingCollection anyKeys = getAnyPublicKeys();
|
||||||
Set<OpenPgpV4Fingerprint> announced = store.getAnnouncedFingerprintsOf(jid).keySet();
|
Map<OpenPgpV4Fingerprint, Date> announced = store.getAnnouncedFingerprintsOf(jid);
|
||||||
|
|
||||||
PGPPublicKeyRingCollection announcedKeysCollection = anyKeys;
|
PGPPublicKeyRingCollection announcedKeysCollection = anyKeys;
|
||||||
|
|
||||||
|
BareJidUserId.PubRingSelectionStrategy userIdFilter = new BareJidUserId.PubRingSelectionStrategy();
|
||||||
|
AnnouncedKeys.PubKeyRingSelectionStrategy announcedFilter = new AnnouncedKeys.PubKeyRingSelectionStrategy();
|
||||||
|
|
||||||
for (PGPPublicKeyRing ring : anyKeys) {
|
for (PGPPublicKeyRing ring : anyKeys) {
|
||||||
|
|
||||||
OpenPgpV4Fingerprint fingerprint = new OpenPgpV4Fingerprint(ring.getPublicKey());
|
if (!userIdFilter.accept(getJid(), ring)) {
|
||||||
|
LOGGER.log(Level.WARNING, "Ignore key " + Long.toHexString(ring.getPublicKey().getKeyID()) +
|
||||||
|
" as it lacks the user-id \"xmpp" + getJid().toString() + "\"");
|
||||||
|
announcedKeysCollection = PGPPublicKeyRingCollection.removePublicKeyRing(announcedKeysCollection, ring);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!announced.contains(fingerprint)) {
|
if (!announcedFilter.accept(announced, ring)) {
|
||||||
|
LOGGER.log(Level.WARNING, "Ignore key " + Long.toHexString(ring.getPublicKey().getKeyID()) +
|
||||||
|
" as it is not announced by " + getJid().toString());
|
||||||
announcedKeysCollection = PGPPublicKeyRingCollection.removePublicKeyRing(announcedKeysCollection, ring);
|
announcedKeysCollection = PGPPublicKeyRingCollection.removePublicKeyRing(announcedKeysCollection, ring);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.jivesoftware.smackx.ox;
|
||||||
|
|
||||||
import static org.jivesoftware.smackx.ox.util.PubSubDelegate.PEP_NODE_PUBLIC_KEYS;
|
import static org.jivesoftware.smackx.ox.util.PubSubDelegate.PEP_NODE_PUBLIC_KEYS;
|
||||||
import static org.jivesoftware.smackx.ox.util.PubSubDelegate.PEP_NODE_PUBLIC_KEYS_NOTIFY;
|
import static org.jivesoftware.smackx.ox.util.PubSubDelegate.PEP_NODE_PUBLIC_KEYS_NOTIFY;
|
||||||
|
import static org.jivesoftware.smackx.ox.util.PubSubDelegate.publishPublicKey;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -50,16 +51,18 @@ import org.jivesoftware.smackx.ox.callback.backup.SecretKeyBackupSelectionCallba
|
||||||
import org.jivesoftware.smackx.ox.callback.backup.SecretKeyRestoreSelectionCallback;
|
import org.jivesoftware.smackx.ox.callback.backup.SecretKeyRestoreSelectionCallback;
|
||||||
import org.jivesoftware.smackx.ox.crypto.OpenPgpProvider;
|
import org.jivesoftware.smackx.ox.crypto.OpenPgpProvider;
|
||||||
import org.jivesoftware.smackx.ox.element.CryptElement;
|
import org.jivesoftware.smackx.ox.element.CryptElement;
|
||||||
|
import org.jivesoftware.smackx.ox.element.OpenPgpContentElement;
|
||||||
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
import org.jivesoftware.smackx.ox.element.PubkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SecretkeyElement;
|
import org.jivesoftware.smackx.ox.element.SecretkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SignElement;
|
import org.jivesoftware.smackx.ox.element.SignElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
|
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
|
||||||
|
import org.jivesoftware.smackx.ox.exception.MissingOpenPgpKeyPairException;
|
||||||
import org.jivesoftware.smackx.ox.exception.MissingOpenPgpPublicKeyException;
|
import org.jivesoftware.smackx.ox.exception.MissingOpenPgpPublicKeyException;
|
||||||
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
|
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
|
||||||
import org.jivesoftware.smackx.ox.exception.NoBackupFoundException;
|
import org.jivesoftware.smackx.ox.exception.NoBackupFoundException;
|
||||||
import org.jivesoftware.smackx.ox.exception.SmackOpenPgpException;
|
|
||||||
import org.jivesoftware.smackx.ox.listener.internal.CryptElementReceivedListener;
|
import org.jivesoftware.smackx.ox.listener.internal.CryptElementReceivedListener;
|
||||||
import org.jivesoftware.smackx.ox.listener.internal.SignElementReceivedListener;
|
import org.jivesoftware.smackx.ox.listener.internal.SignElementReceivedListener;
|
||||||
import org.jivesoftware.smackx.ox.listener.internal.SigncryptElementReceivedListener;
|
import org.jivesoftware.smackx.ox.listener.internal.SigncryptElementReceivedListener;
|
||||||
|
@ -75,10 +78,15 @@ import org.jivesoftware.smackx.pubsub.PubSubException;
|
||||||
import org.jivesoftware.smackx.pubsub.PubSubFeature;
|
import org.jivesoftware.smackx.pubsub.PubSubFeature;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
import org.pgpainless.pgpainless.PGPainless;
|
||||||
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
|
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
public final class OpenPgpManager extends Manager {
|
public final class OpenPgpManager extends Manager {
|
||||||
|
|
||||||
|
@ -94,8 +102,6 @@ public final class OpenPgpManager extends Manager {
|
||||||
*/
|
*/
|
||||||
private OpenPgpProvider provider;
|
private OpenPgpProvider provider;
|
||||||
|
|
||||||
private OpenPgpStore store;
|
|
||||||
|
|
||||||
private final Map<BareJid, OpenPgpContact> openPgpCapableContacts = new HashMap<>();
|
private final Map<BareJid, OpenPgpContact> openPgpCapableContacts = new HashMap<>();
|
||||||
|
|
||||||
private final Set<SigncryptElementReceivedListener> signcryptElementReceivedListeners = new HashSet<>();
|
private final Set<SigncryptElementReceivedListener> signcryptElementReceivedListeners = new HashSet<>();
|
||||||
|
@ -144,6 +150,10 @@ public final class OpenPgpManager extends Manager {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OpenPgpProvider getProvider() {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get our OpenPGP self.
|
* Get our OpenPGP self.
|
||||||
*
|
*
|
||||||
|
@ -151,8 +161,10 @@ public final class OpenPgpManager extends Manager {
|
||||||
* @throws SmackException.NotLoggedInException if we are not logged in
|
* @throws SmackException.NotLoggedInException if we are not logged in
|
||||||
*/
|
*/
|
||||||
public OpenPgpSelf getOpenPgpSelf() throws SmackException.NotLoggedInException {
|
public OpenPgpSelf getOpenPgpSelf() throws SmackException.NotLoggedInException {
|
||||||
|
throwIfNoProviderSet();
|
||||||
|
|
||||||
if (self == null) {
|
if (self == null) {
|
||||||
self = new OpenPgpSelf(getJidOrThrow(), store);
|
self = new OpenPgpSelf(getJidOrThrow(), provider.getStore());
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -165,7 +177,6 @@ public final class OpenPgpManager extends Manager {
|
||||||
*
|
*
|
||||||
* @throws NoSuchAlgorithmException if we are missing an algorithm to generate a fresh key pair.
|
* @throws NoSuchAlgorithmException if we are missing an algorithm to generate a fresh key pair.
|
||||||
* @throws NoSuchProviderException if we are missing a suitable {@link java.security.Provider}.
|
* @throws NoSuchProviderException if we are missing a suitable {@link java.security.Provider}.
|
||||||
* @throws SmackOpenPgpException if something bad happens during key generation/loading.
|
|
||||||
* @throws InterruptedException if the thread gets interrupted.
|
* @throws InterruptedException if the thread gets interrupted.
|
||||||
* @throws PubSubException.NotALeafNodeException if one of the PubSub nodes is not a {@link LeafNode}.
|
* @throws PubSubException.NotALeafNodeException if one of the PubSub nodes is not a {@link LeafNode}.
|
||||||
* @throws XMPPException.XMPPErrorException in case of an XMPP protocol error.
|
* @throws XMPPException.XMPPErrorException in case of an XMPP protocol error.
|
||||||
|
@ -174,33 +185,32 @@ public final class OpenPgpManager extends Manager {
|
||||||
* @throws IOException IO is dangerous.
|
* @throws IOException IO is dangerous.
|
||||||
* @throws InvalidAlgorithmParameterException if illegal algorithm parameters are used for key generation.
|
* @throws InvalidAlgorithmParameterException if illegal algorithm parameters are used for key generation.
|
||||||
* @throws SmackException.NotLoggedInException if we are not logged in.
|
* @throws SmackException.NotLoggedInException if we are not logged in.
|
||||||
|
* @throws PGPException if something goes wrong during key loading/generating
|
||||||
*/
|
*/
|
||||||
public void announceSupportAndPublish()
|
public void announceSupportAndPublish()
|
||||||
throws NoSuchAlgorithmException, NoSuchProviderException, SmackOpenPgpException,
|
throws NoSuchAlgorithmException, NoSuchProviderException, InterruptedException,
|
||||||
InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
|
PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
|
||||||
SmackException.NotConnectedException, SmackException.NoResponseException, IOException,
|
SmackException.NotConnectedException, SmackException.NoResponseException, IOException,
|
||||||
InvalidAlgorithmParameterException, SmackException.NotLoggedInException {
|
InvalidAlgorithmParameterException, SmackException.NotLoggedInException, PGPException {
|
||||||
throwIfNoProviderSet();
|
throwIfNoProviderSet();
|
||||||
throwIfNotAuthenticated();
|
throwIfNotAuthenticated();
|
||||||
|
|
||||||
BareJid ourJid = connection().getUser().asBareJid();
|
OpenPgpV4Fingerprint primaryFingerprint = getOurFingerprint();
|
||||||
|
|
||||||
// OpenPgpV4Fingerprint primaryFingerprint = getOurFingerprint();
|
if (primaryFingerprint == null) {
|
||||||
|
primaryFingerprint = generateAndImportKeyPair(getJidOrThrow());
|
||||||
// if (primaryFingerprint == null) {
|
}
|
||||||
// primaryFingerprint = generateAndImportKeyPair(ourJid);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Create <pubkey/> element
|
// Create <pubkey/> element
|
||||||
PubkeyElement pubkeyElement;
|
PubkeyElement pubkeyElement;
|
||||||
// try {
|
try {
|
||||||
// pubkeyElement = createPubkeyElement(ourJid, primaryFingerprint, new Date());
|
pubkeyElement = createPubkeyElement(getJidOrThrow(), primaryFingerprint, new Date());
|
||||||
// } catch (MissingOpenPgpPublicKeyException e) {
|
} catch (MissingOpenPgpPublicKeyException e) {
|
||||||
// throw new AssertionError("Cannot publish our public key, since it is missing (MUST NOT happen!)");
|
throw new AssertionError("Cannot publish our public key, since it is missing (MUST NOT happen!)");
|
||||||
// }
|
}
|
||||||
|
|
||||||
// publish it
|
// publish it
|
||||||
// publishPublicKey(connection(), pubkeyElement, primaryFingerprint);
|
publishPublicKey(connection(), pubkeyElement, primaryFingerprint);
|
||||||
|
|
||||||
// Subscribe to public key changes
|
// Subscribe to public key changes
|
||||||
// PEPManager.getInstanceFor(connection()).addPEPListener(metadataListener);
|
// PEPManager.getInstanceFor(connection()).addPEPListener(metadataListener);
|
||||||
|
@ -216,19 +226,20 @@ public final class OpenPgpManager extends Manager {
|
||||||
* @throws NoSuchAlgorithmException if the JVM doesn't support one of the used algorithms.
|
* @throws NoSuchAlgorithmException if the JVM doesn't support one of the used algorithms.
|
||||||
* @throws InvalidAlgorithmParameterException if the used algorithm parameters are invalid.
|
* @throws InvalidAlgorithmParameterException if the used algorithm parameters are invalid.
|
||||||
* @throws NoSuchProviderException if we are missing a cryptographic provider.
|
* @throws NoSuchProviderException if we are missing a cryptographic provider.
|
||||||
* @throws SmackOpenPgpException in case of an OpenPGP error.
|
|
||||||
*/
|
*/
|
||||||
public OpenPgpV4Fingerprint generateAndImportKeyPair(BareJid ourJid)
|
public OpenPgpV4Fingerprint generateAndImportKeyPair(BareJid ourJid)
|
||||||
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchProviderException,
|
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchProviderException,
|
||||||
SmackOpenPgpException, PGPException {
|
PGPException, IOException {
|
||||||
|
|
||||||
|
throwIfNoProviderSet();
|
||||||
|
OpenPgpStore store = provider.getStore();
|
||||||
PGPSecretKeyRing keyPair = store.generateKeyRing(ourJid);
|
PGPSecretKeyRing keyPair = store.generateKeyRing(ourJid);
|
||||||
// try {
|
try {
|
||||||
// provider.importSecretKey(ourJid, keyPair);
|
store.importSecretKey(ourJid, keyPair);
|
||||||
// } catch (MissingUserIdOnKeyException e) {
|
} catch (MissingUserIdOnKeyException e) {
|
||||||
// This should never throw, since we set our jid literally one line above this comment.
|
// This should never throw, since we set our jid literally one line above this comment.
|
||||||
// throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
// }
|
}
|
||||||
|
|
||||||
return new OpenPgpV4Fingerprint(keyPair);
|
return new OpenPgpV4Fingerprint(keyPair);
|
||||||
}
|
}
|
||||||
|
@ -251,7 +262,8 @@ public final class OpenPgpManager extends Manager {
|
||||||
* @return {@link OpenPgpContact}.
|
* @return {@link OpenPgpContact}.
|
||||||
*/
|
*/
|
||||||
public OpenPgpContact getOpenPgpContact(EntityBareJid jid) {
|
public OpenPgpContact getOpenPgpContact(EntityBareJid jid) {
|
||||||
return store.getOpenPgpContact(jid);
|
throwIfNoProviderSet();
|
||||||
|
return provider.getStore().getOpenPgpContact(jid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -288,7 +300,6 @@ public final class OpenPgpManager extends Manager {
|
||||||
* @throws SmackException.NotConnectedException if we are not connected.
|
* @throws SmackException.NotConnectedException if we are not connected.
|
||||||
* @throws SmackException.NoResponseException if the server doesn't respond.
|
* @throws SmackException.NoResponseException if the server doesn't respond.
|
||||||
* @throws SmackException.NotLoggedInException if we are not logged in.
|
* @throws SmackException.NotLoggedInException if we are not logged in.
|
||||||
* @throws SmackOpenPgpException in case of an OpenPGP exception.
|
|
||||||
* @throws IOException IO is dangerous.
|
* @throws IOException IO is dangerous.
|
||||||
* @throws SmackException.FeatureNotSupportedException if the server doesn't support the PubSub whitelist access model.
|
* @throws SmackException.FeatureNotSupportedException if the server doesn't support the PubSub whitelist access model.
|
||||||
*/
|
*/
|
||||||
|
@ -296,21 +307,28 @@ public final class OpenPgpManager extends Manager {
|
||||||
SecretKeyBackupSelectionCallback selectKeyCallback)
|
SecretKeyBackupSelectionCallback selectKeyCallback)
|
||||||
throws InterruptedException, PubSubException.NotALeafNodeException,
|
throws InterruptedException, PubSubException.NotALeafNodeException,
|
||||||
XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException,
|
XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException,
|
||||||
SmackException.NotLoggedInException, SmackOpenPgpException, IOException,
|
SmackException.NotLoggedInException, IOException,
|
||||||
SmackException.FeatureNotSupportedException {
|
SmackException.FeatureNotSupportedException, PGPException, MissingOpenPgpKeyPairException {
|
||||||
throwIfNoProviderSet();
|
throwIfNoProviderSet();
|
||||||
throwIfNotAuthenticated();
|
throwIfNotAuthenticated();
|
||||||
|
|
||||||
BareJid ownJid = connection().getUser().asBareJid();
|
BareJid ownJid = connection().getUser().asBareJid();
|
||||||
|
|
||||||
String backupCode = SecretKeyBackupHelper.generateBackupPassword();
|
String backupCode = SecretKeyBackupHelper.generateBackupPassword();
|
||||||
// Set<OpenPgpV4Fingerprint> availableKeyPairs = provider.getStore().getAvailableKeyPairFingerprints(ownJid);
|
|
||||||
// Set<OpenPgpV4Fingerprint> selectedKeyPairs = selectKeyCallback.selectKeysToBackup(availableKeyPairs);
|
|
||||||
|
|
||||||
// SecretkeyElement secretKey = SecretKeyBackupHelper.createSecretkeyElement(provider, ownJid, selectedKeyPairs, backupCode);
|
PGPSecretKeyRingCollection secretKeyRings = provider.getStore().getSecretKeysOf(ownJid);
|
||||||
|
|
||||||
// PubSubDelegate.depositSecretKey(connection(), secretKey);
|
Set<OpenPgpV4Fingerprint> availableKeyPairs = new HashSet<>();
|
||||||
// displayCodeCallback.displayBackupCode(backupCode);
|
for (PGPSecretKeyRing ring : secretKeyRings) {
|
||||||
|
availableKeyPairs.add(new OpenPgpV4Fingerprint(ring));
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<OpenPgpV4Fingerprint> selectedKeyPairs = selectKeyCallback.selectKeysToBackup(availableKeyPairs);
|
||||||
|
|
||||||
|
SecretkeyElement secretKey = SecretKeyBackupHelper.createSecretkeyElement(provider, ownJid, selectedKeyPairs, backupCode);
|
||||||
|
|
||||||
|
PubSubDelegate.depositSecretKey(connection(), secretKey);
|
||||||
|
displayCodeCallback.displayBackupCode(backupCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -342,7 +360,6 @@ public final class OpenPgpManager extends Manager {
|
||||||
* @throws XMPPException.XMPPErrorException in case of an XMPP protocol error.
|
* @throws XMPPException.XMPPErrorException in case of an XMPP protocol error.
|
||||||
* @throws SmackException.NotConnectedException if we are not connected.
|
* @throws SmackException.NotConnectedException if we are not connected.
|
||||||
* @throws SmackException.NoResponseException if the server doesn't respond.
|
* @throws SmackException.NoResponseException if the server doesn't respond.
|
||||||
* @throws SmackOpenPgpException if something goes wrong while restoring the secret key.
|
|
||||||
* @throws InvalidBackupCodeException if the user-provided backup code is invalid.
|
* @throws InvalidBackupCodeException if the user-provided backup code is invalid.
|
||||||
* @throws SmackException.NotLoggedInException if we are not logged in
|
* @throws SmackException.NotLoggedInException if we are not logged in
|
||||||
* @throws IOException IO is dangerous
|
* @throws IOException IO is dangerous
|
||||||
|
@ -352,9 +369,9 @@ public final class OpenPgpManager extends Manager {
|
||||||
public OpenPgpV4Fingerprint restoreSecretKeyServerBackup(AskForBackupCodeCallback codeCallback,
|
public OpenPgpV4Fingerprint restoreSecretKeyServerBackup(AskForBackupCodeCallback codeCallback,
|
||||||
SecretKeyRestoreSelectionCallback selectionCallback)
|
SecretKeyRestoreSelectionCallback selectionCallback)
|
||||||
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
|
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
|
||||||
SmackException.NotConnectedException, SmackException.NoResponseException, SmackOpenPgpException,
|
SmackException.NotConnectedException, SmackException.NoResponseException,
|
||||||
InvalidBackupCodeException, SmackException.NotLoggedInException, IOException, MissingUserIdOnKeyException,
|
InvalidBackupCodeException, SmackException.NotLoggedInException, IOException, MissingUserIdOnKeyException,
|
||||||
NoBackupFoundException {
|
NoBackupFoundException, PGPException {
|
||||||
throwIfNoProviderSet();
|
throwIfNoProviderSet();
|
||||||
throwIfNotAuthenticated();
|
throwIfNotAuthenticated();
|
||||||
SecretkeyElement backup = PubSubDelegate.fetchSecretKey(connection());
|
SecretkeyElement backup = PubSubDelegate.fetchSecretKey(connection());
|
||||||
|
@ -364,8 +381,9 @@ public final class OpenPgpManager extends Manager {
|
||||||
|
|
||||||
String backupCode = codeCallback.askForBackupCode();
|
String backupCode = codeCallback.askForBackupCode();
|
||||||
|
|
||||||
OpenPgpV4Fingerprint fingerprint = SecretKeyBackupHelper.restoreSecretKeyBackup(provider, backup, backupCode);
|
PGPSecretKeyRing key = SecretKeyBackupHelper.restoreSecretKeyBackup(backup, backupCode);
|
||||||
return fingerprint;
|
provider.getStore().importSecretKey(getJidOrThrow(), key);
|
||||||
|
return new OpenPgpV4Fingerprint(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -394,21 +412,24 @@ public final class OpenPgpManager extends Manager {
|
||||||
};
|
};
|
||||||
|
|
||||||
private void processPublicKeysListElement(BareJid contact, PublicKeysListElement listElement) {
|
private void processPublicKeysListElement(BareJid contact, PublicKeysListElement listElement) {
|
||||||
/*
|
|
||||||
OpenPgpContact openPgpContact = getOpenPgpContact(contact.asEntityBareJidIfPossible());
|
|
||||||
try {
|
try {
|
||||||
openPgpContact.updateKeys(listElement);
|
PGPPublicKeyRingCollection contactsKeys = provider.getStore().getPublicKeysOf(contact);
|
||||||
} catch (SmackOpenPgpException e) {
|
for (OpenPgpV4Fingerprint fingerprint : listElement.getMetadata().keySet()) {
|
||||||
LOGGER.log(Level.WARNING, "Could not read key ring of contact " + contact, e);
|
PGPPublicKeyRing key = contactsKeys.getPublicKeyRing(fingerprint.getKeyId());
|
||||||
|
if (key == null) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PGPException | IOException e) {
|
||||||
|
LOGGER.log(Level.WARNING, "Could not read public keys of " + contact, e);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final IncomingChatMessageListener incomingOpenPgpMessageListener =
|
private final IncomingChatMessageListener incomingOpenPgpMessageListener =
|
||||||
new IncomingChatMessageListener() {
|
new IncomingChatMessageListener() {
|
||||||
@Override
|
@Override
|
||||||
public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
|
public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
|
||||||
/*
|
|
||||||
OpenPgpElement element = message.getExtension(OpenPgpElement.ELEMENT, OpenPgpElement.NAMESPACE);
|
OpenPgpElement element = message.getExtension(OpenPgpElement.ELEMENT, OpenPgpElement.NAMESPACE);
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
// Message does not contain an OpenPgpElement -> discard
|
// Message does not contain an OpenPgpElement -> discard
|
||||||
|
@ -419,13 +440,11 @@ public final class OpenPgpManager extends Manager {
|
||||||
|
|
||||||
OpenPgpContentElement contentElement = null;
|
OpenPgpContentElement contentElement = null;
|
||||||
try {
|
try {
|
||||||
contentElement = contact.receive(element);
|
contentElement = provider.decryptAndOrVerify(element, self, contact).getOpenPgpContentElement();
|
||||||
} catch (SmackOpenPgpException e) {
|
} catch (PGPException e) {
|
||||||
LOGGER.log(Level.WARNING, "Could not decrypt incoming OpenPGP encrypted message", e);
|
LOGGER.log(Level.WARNING, "Could not decrypt incoming OpenPGP encrypted message", e);
|
||||||
} catch (XmlPullParserException | IOException e) {
|
} catch (XmlPullParserException | IOException e) {
|
||||||
LOGGER.log(Level.WARNING, "Invalid XML content of incoming OpenPGP encrypted message", e);
|
LOGGER.log(Level.WARNING, "Invalid XML content of incoming OpenPGP encrypted message", e);
|
||||||
} catch (MissingOpenPgpKeyPairException e) {
|
|
||||||
LOGGER.log(Level.WARNING, "Could not decrypt incoming OpenPGP encrypted message due to missing secret key", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contentElement instanceof SigncryptElement) {
|
if (contentElement instanceof SigncryptElement) {
|
||||||
|
@ -452,7 +471,6 @@ public final class OpenPgpManager extends Manager {
|
||||||
else {
|
else {
|
||||||
throw new AssertionError("Invalid element received: " + contentElement.getClass().getName());
|
throw new AssertionError("Invalid element received: " + contentElement.getClass().getName());
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -468,12 +486,12 @@ public final class OpenPgpManager extends Manager {
|
||||||
* @throws MissingUserIdOnKeyException if the key does not have an OpenPGP user-id of the form
|
* @throws MissingUserIdOnKeyException if the key does not have an OpenPGP user-id of the form
|
||||||
* "xmpp:juliet@capulet.lit" with the owners {@link BareJid}
|
* "xmpp:juliet@capulet.lit" with the owners {@link BareJid}
|
||||||
* @throws IOException row, row, row your byte gently down the {@link InputStream}
|
* @throws IOException row, row, row your byte gently down the {@link InputStream}
|
||||||
* @throws SmackOpenPgpException if the key cannot be deserialized
|
|
||||||
*/
|
*/
|
||||||
private void processPublicKey(PubkeyElement pubkeyElement, BareJid owner)
|
private void processPublicKey(PubkeyElement pubkeyElement, BareJid owner)
|
||||||
throws MissingUserIdOnKeyException, IOException, SmackOpenPgpException {
|
throws MissingUserIdOnKeyException, IOException, PGPException {
|
||||||
byte[] base64 = pubkeyElement.getDataElement().getB64Data();
|
byte[] base64 = pubkeyElement.getDataElement().getB64Data();
|
||||||
// provider.importPublicKey(owner, Base64.decode(base64));
|
PGPPublicKeyRing keyRing = PGPainless.readKeyRing().publicKeyRing(Base64.decode(base64));
|
||||||
|
provider.getStore().importPublicKey(owner, keyRing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -490,10 +508,16 @@ public final class OpenPgpManager extends Manager {
|
||||||
private PubkeyElement createPubkeyElement(BareJid owner,
|
private PubkeyElement createPubkeyElement(BareJid owner,
|
||||||
OpenPgpV4Fingerprint fingerprint,
|
OpenPgpV4Fingerprint fingerprint,
|
||||||
Date date)
|
Date date)
|
||||||
throws MissingOpenPgpPublicKeyException {
|
throws MissingOpenPgpPublicKeyException, IOException, PGPException {
|
||||||
// byte[] keyBytes = provider.getStore().getPublicKeyRingBytes(owner, fingerprint);
|
PGPPublicKeyRingCollection publicKeyRingCollection = provider.getStore().getPublicKeysOf(owner);
|
||||||
// return createPubkeyElement(keyBytes, date);
|
if (publicKeyRingCollection != null) {
|
||||||
return null;
|
PGPPublicKeyRing keys = publicKeyRingCollection.getPublicKeyRing(fingerprint.getKeyId());
|
||||||
|
if (keys != null) {
|
||||||
|
byte[] keyBytes = keys.getEncoded(true);
|
||||||
|
return createPubkeyElement(keyBytes, date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new MissingOpenPgpPublicKeyException(owner, fingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Paul Schaub.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
package org.jivesoftware.smackx.ox;
|
package org.jivesoftware.smackx.ox;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -26,11 +26,14 @@ import org.jivesoftware.smackx.ox.element.CryptElement;
|
||||||
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SignElement;
|
import org.jivesoftware.smackx.ox.element.SignElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
|
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
|
||||||
public interface OpenPgpProvider {
|
public interface OpenPgpProvider {
|
||||||
|
|
||||||
|
OpenPgpStore getStore();
|
||||||
|
|
||||||
OpenPgpElement signAndEncrypt(SigncryptElement element, OpenPgpSelf self, Collection<OpenPgpContact> recipients)
|
OpenPgpElement signAndEncrypt(SigncryptElement element, OpenPgpSelf self, Collection<OpenPgpContact> recipients)
|
||||||
throws IOException, PGPException;
|
throws IOException, PGPException;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Paul Schaub.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
package org.jivesoftware.smackx.ox.crypto;
|
package org.jivesoftware.smackx.ox.crypto;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
@ -14,6 +30,7 @@ import org.jivesoftware.smackx.ox.element.CryptElement;
|
||||||
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
import org.jivesoftware.smackx.ox.element.OpenPgpElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SignElement;
|
import org.jivesoftware.smackx.ox.element.SignElement;
|
||||||
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
|
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||||
|
@ -25,6 +42,17 @@ import org.pgpainless.pgpainless.encryption_signing.EncryptionStream;
|
||||||
|
|
||||||
public class PainlessOpenPgpProvider implements OpenPgpProvider {
|
public class PainlessOpenPgpProvider implements OpenPgpProvider {
|
||||||
|
|
||||||
|
private final OpenPgpStore store;
|
||||||
|
|
||||||
|
public PainlessOpenPgpProvider(OpenPgpStore store) {
|
||||||
|
this.store = store;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OpenPgpStore getStore() {
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenPgpElement signAndEncrypt(SigncryptElement element, OpenPgpSelf self, Collection<OpenPgpContact> recipients)
|
public OpenPgpElement signAndEncrypt(SigncryptElement element, OpenPgpSelf self, Collection<OpenPgpContact> recipients)
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright 2018 Paul Schaub.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.jivesoftware.smackx.ox.exception;
|
|
||||||
|
|
||||||
public class SmackOpenPgpException extends Exception {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
public SmackOpenPgpException(Throwable cause) {
|
|
||||||
super(cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SmackOpenPgpException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Paul Schaub.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.ox.selection_strategy;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
|
||||||
|
import org.pgpainless.pgpainless.key.selection.keyring.PublicKeyRingSelectionStrategy;
|
||||||
|
import org.pgpainless.pgpainless.key.selection.keyring.SecretKeyRingSelectionStrategy;
|
||||||
|
|
||||||
|
public class AnnouncedKeys {
|
||||||
|
|
||||||
|
public static class PubKeyRingSelectionStrategy extends PublicKeyRingSelectionStrategy<Map<OpenPgpV4Fingerprint, Date>> {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(PubKeyRingSelectionStrategy.class.getName());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(Map<OpenPgpV4Fingerprint, Date> announcedKeys, PGPPublicKeyRing publicKeys) {
|
||||||
|
try {
|
||||||
|
return announcedKeys.keySet().contains(new OpenPgpV4Fingerprint(publicKeys));
|
||||||
|
} catch (PGPException e) {
|
||||||
|
LOGGER.log(Level.WARNING, "Key might be damaged.", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SecKeyRingSelectionStrategy extends SecretKeyRingSelectionStrategy<Map<OpenPgpV4Fingerprint, Date>> {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(SecKeyRingSelectionStrategy.class.getName());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(Map<OpenPgpV4Fingerprint, Date> announcedKeys, PGPSecretKeyRing secretKeys) {
|
||||||
|
try {
|
||||||
|
return announcedKeys.keySet().contains(new OpenPgpV4Fingerprint(secretKeys));
|
||||||
|
} catch (PGPException e) {
|
||||||
|
LOGGER.log(Level.WARNING, "Key might be damaged.", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,7 +22,11 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
|
||||||
|
import org.jivesoftware.smackx.ox.selection_strategy.BareJidUserId;
|
||||||
import org.jivesoftware.smackx.ox.store.definition.OpenPgpKeyStore;
|
import org.jivesoftware.smackx.ox.store.definition.OpenPgpKeyStore;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
@ -37,12 +41,10 @@ import org.pgpainless.pgpainless.key.generation.type.length.RsaLength;
|
||||||
|
|
||||||
public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
|
public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
|
||||||
|
|
||||||
public AbstractOpenPgpKeyStore() {
|
private static final Logger LOGGER = Logger.getLogger(AbstractOpenPgpKeyStore.class.getName());
|
||||||
|
|
||||||
}
|
protected Map<BareJid, PGPPublicKeyRingCollection> publicKeyRingCollections = new HashMap<>();
|
||||||
|
protected Map<BareJid, PGPSecretKeyRingCollection> secretKeyRingCollections = new HashMap<>();
|
||||||
protected Map<BareJid, PGPPublicKeyRingCollection> publicKeys = new HashMap<>();
|
|
||||||
protected Map<BareJid, PGPSecretKeyRingCollection> secretKeys = new HashMap<>();
|
|
||||||
|
|
||||||
protected abstract PGPPublicKeyRingCollection readPublicKeysOf(BareJid owner) throws IOException, PGPException;
|
protected abstract PGPPublicKeyRingCollection readPublicKeysOf(BareJid owner) throws IOException, PGPException;
|
||||||
|
|
||||||
|
@ -54,11 +56,11 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PGPPublicKeyRingCollection getPublicKeysOf(BareJid owner) throws IOException, PGPException {
|
public PGPPublicKeyRingCollection getPublicKeysOf(BareJid owner) throws IOException, PGPException {
|
||||||
PGPPublicKeyRingCollection keys = publicKeys.get(owner);
|
PGPPublicKeyRingCollection keys = publicKeyRingCollections.get(owner);
|
||||||
if (keys == null) {
|
if (keys == null) {
|
||||||
keys = readPublicKeysOf(owner);
|
keys = readPublicKeysOf(owner);
|
||||||
if (keys != null) {
|
if (keys != null) {
|
||||||
publicKeys.put(owner, keys);
|
publicKeyRingCollections.put(owner, keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
|
@ -66,16 +68,53 @@ public abstract class AbstractOpenPgpKeyStore implements OpenPgpKeyStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PGPSecretKeyRingCollection getSecretKeysOf(BareJid owner) throws IOException, PGPException {
|
public PGPSecretKeyRingCollection getSecretKeysOf(BareJid owner) throws IOException, PGPException {
|
||||||
PGPSecretKeyRingCollection keys = secretKeys.get(owner);
|
PGPSecretKeyRingCollection keys = secretKeyRingCollections.get(owner);
|
||||||
if (keys == null) {
|
if (keys == null) {
|
||||||
keys = readSecretKeysOf(owner);
|
keys = readSecretKeysOf(owner);
|
||||||
if (keys != null) {
|
if (keys != null) {
|
||||||
secretKeys.put(owner, keys);
|
secretKeyRingCollections.put(owner, keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void importSecretKey(BareJid owner, PGPSecretKeyRing secretKeys)
|
||||||
|
throws IOException, PGPException, MissingUserIdOnKeyException {
|
||||||
|
|
||||||
|
if (!new BareJidUserId.SecRingSelectionStrategy().accept(owner, secretKeys)) {
|
||||||
|
throw new MissingUserIdOnKeyException(owner, secretKeys.getPublicKey().getKeyID());
|
||||||
|
}
|
||||||
|
|
||||||
|
PGPSecretKeyRingCollection secretKeyRings = getSecretKeysOf(owner);
|
||||||
|
try {
|
||||||
|
secretKeyRings = PGPSecretKeyRingCollection.addSecretKeyRing(secretKeyRings, secretKeys);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
LOGGER.log(Level.INFO, "Skipping secret key ring " + Long.toHexString(secretKeys.getPublicKey().getKeyID()) +
|
||||||
|
" as it is already in the key ring of " + owner.toString());
|
||||||
|
}
|
||||||
|
this.secretKeyRingCollections.put(owner, secretKeyRings);
|
||||||
|
writeSecretKeysOf(owner, secretKeyRings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void importPublicKey(BareJid owner, PGPPublicKeyRing publicKeys) throws IOException, PGPException, MissingUserIdOnKeyException {
|
||||||
|
|
||||||
|
if (!new BareJidUserId.PubRingSelectionStrategy().accept(owner, publicKeys)) {
|
||||||
|
throw new MissingUserIdOnKeyException(owner, publicKeys.getPublicKey().getKeyID());
|
||||||
|
}
|
||||||
|
|
||||||
|
PGPPublicKeyRingCollection publicKeyRings = getPublicKeysOf(owner);
|
||||||
|
try {
|
||||||
|
publicKeyRings = PGPPublicKeyRingCollection.addPublicKeyRing(publicKeyRings, publicKeys);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
LOGGER.log(Level.INFO, "Skipping public key ring " + Long.toHexString(publicKeys.getPublicKey().getKeyID()) +
|
||||||
|
" as it is already in the key ring of " + owner.toString());
|
||||||
|
}
|
||||||
|
this.publicKeyRingCollections.put(owner, publicKeyRings);
|
||||||
|
writePublicKeysOf(owner, publicKeyRings);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PGPPublicKeyRing getPublicKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException {
|
public PGPPublicKeyRing getPublicKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException {
|
||||||
PGPPublicKeyRingCollection publicKeyRings = getPublicKeysOf(owner);
|
PGPPublicKeyRingCollection publicKeyRings = getPublicKeysOf(owner);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -28,6 +28,7 @@ import java.util.Observable;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpContact;
|
import org.jivesoftware.smackx.ox.OpenPgpContact;
|
||||||
import org.jivesoftware.smackx.ox.callback.SecretKeyPassphraseCallback;
|
import org.jivesoftware.smackx.ox.callback.SecretKeyPassphraseCallback;
|
||||||
|
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
|
||||||
import org.jivesoftware.smackx.ox.store.definition.OpenPgpKeyStore;
|
import org.jivesoftware.smackx.ox.store.definition.OpenPgpKeyStore;
|
||||||
import org.jivesoftware.smackx.ox.store.definition.OpenPgpMetadataStore;
|
import org.jivesoftware.smackx.ox.store.definition.OpenPgpMetadataStore;
|
||||||
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
|
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
|
||||||
|
@ -115,6 +116,16 @@ public abstract class AbstractOpenPgpStore extends Observable implements OpenPgp
|
||||||
return keyStore.generateKeyRing(owner);
|
return keyStore.generateKeyRing(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void importSecretKey(BareJid owner, PGPSecretKeyRing secretKeys) throws IOException, PGPException, MissingUserIdOnKeyException {
|
||||||
|
keyStore.importSecretKey(owner, secretKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void importPublicKey(BareJid owner, PGPPublicKeyRing publicKeys) throws IOException, PGPException, MissingUserIdOnKeyException {
|
||||||
|
keyStore.importPublicKey(owner, publicKeys);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
OpenPgpMetadataStore
|
OpenPgpMetadataStore
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Paul Schaub.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
package org.jivesoftware.smackx.ox.store.abstr;
|
package org.jivesoftware.smackx.ox.store.abstr;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -21,6 +21,8 @@ import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||||
|
@ -42,4 +44,8 @@ public interface OpenPgpKeyStore {
|
||||||
PGPSecretKeyRing getSecretKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException;
|
PGPSecretKeyRing getSecretKeyRing(BareJid owner, OpenPgpV4Fingerprint fingerprint) throws IOException, PGPException;
|
||||||
|
|
||||||
PGPSecretKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException;
|
PGPSecretKeyRing generateKeyRing(BareJid owner) throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException;
|
||||||
|
|
||||||
|
void importSecretKey(BareJid owner, PGPSecretKeyRing secretKeys) throws IOException, PGPException, MissingUserIdOnKeyException;
|
||||||
|
|
||||||
|
void importPublicKey(BareJid owner, PGPPublicKeyRing publicKeys) throws IOException, PGPException, MissingUserIdOnKeyException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Paul Schaub.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
package org.jivesoftware.smackx.ox.store.definition;
|
package org.jivesoftware.smackx.ox.store.definition;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.ox.OpenPgpContact;
|
import org.jivesoftware.smackx.ox.OpenPgpContact;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2017 Florian Schmaus, 2018 Paul Schaub.
|
* Copyright 2018 Paul Schaub.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -468,7 +468,8 @@ public class PubSubDelegate {
|
||||||
|
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException |
|
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException |
|
||||||
NoSuchFieldException e) {
|
NoSuchFieldException e) {
|
||||||
throw new AssertionError("Using reflections to create a LeafNode and put it into PubSubManagers nodeMap failed.", e);
|
LOGGER.log(Level.SEVERE, "Using reflections to create a LeafNode and put it into PubSubManagers nodeMap failed.", e);
|
||||||
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,22 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.ox.util;
|
package org.jivesoftware.smackx.ox.util;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||||
import org.jivesoftware.smackx.ox.crypto.OpenPgpProvider;
|
import org.jivesoftware.smackx.ox.crypto.OpenPgpProvider;
|
||||||
import org.jivesoftware.smackx.ox.element.SecretkeyElement;
|
import org.jivesoftware.smackx.ox.element.SecretkeyElement;
|
||||||
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
|
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
|
||||||
import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException;
|
import org.jivesoftware.smackx.ox.exception.MissingOpenPgpKeyPairException;
|
||||||
import org.jivesoftware.smackx.ox.exception.SmackOpenPgpException;
|
|
||||||
|
|
||||||
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.jxmpp.jid.BareJid;
|
import org.jxmpp.jid.BareJid;
|
||||||
|
import org.pgpainless.pgpainless.PGPainless;
|
||||||
|
import org.pgpainless.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
|
import org.pgpainless.pgpainless.key.OpenPgpV4Fingerprint;
|
||||||
|
|
||||||
public class SecretKeyBackupHelper {
|
public class SecretKeyBackupHelper {
|
||||||
|
@ -62,45 +67,41 @@ public class SecretKeyBackupHelper {
|
||||||
public static SecretkeyElement createSecretkeyElement(OpenPgpProvider provider,
|
public static SecretkeyElement createSecretkeyElement(OpenPgpProvider provider,
|
||||||
BareJid owner,
|
BareJid owner,
|
||||||
Set<OpenPgpV4Fingerprint> fingerprints,
|
Set<OpenPgpV4Fingerprint> fingerprints,
|
||||||
String backupCode) throws SmackOpenPgpException, IOException {
|
String backupCode) throws PGPException, IOException, MissingOpenPgpKeyPairException {
|
||||||
/*
|
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
for (OpenPgpV4Fingerprint fingerprint : fingerprints) {
|
for (OpenPgpV4Fingerprint fingerprint : fingerprints) {
|
||||||
try {
|
|
||||||
byte[] bytes = provider.getStore().getSecretKeyRingBytes(owner, fingerprint);
|
PGPSecretKeyRing key = provider.getStore().getSecretKeyRing(owner, fingerprint);
|
||||||
buffer.write(bytes);
|
if (key == null) {
|
||||||
} catch (MissingOpenPgpKeyPairException | IOException e) {
|
throw new MissingOpenPgpKeyPairException(owner, fingerprint);
|
||||||
throw new SmackOpenPgpException("Cannot backup secret key " + Long.toHexString(fingerprint.getKeyId()) + ".", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] bytes = key.getEncoded();
|
||||||
|
buffer.write(bytes);
|
||||||
}
|
}
|
||||||
return createSecretkeyElement(provider, buffer.toByteArray(), backupCode);
|
return createSecretkeyElement(provider, buffer.toByteArray(), backupCode);
|
||||||
*/
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SecretkeyElement createSecretkeyElement(OpenPgpProvider provider,
|
public static SecretkeyElement createSecretkeyElement(OpenPgpProvider provider,
|
||||||
byte[] keys,
|
byte[] keys,
|
||||||
String backupCode)
|
String backupCode)
|
||||||
throws SmackOpenPgpException, IOException {
|
throws PGPException, IOException {
|
||||||
// byte[] encrypted = provider.symmetricallyEncryptWithPassword(keys, backupCode);
|
byte[] encrypted = PGPainless.encryptWithPassword(keys, backupCode.toCharArray(), SymmetricKeyAlgorithm.AES_256);
|
||||||
// return new SecretkeyElement(Base64.encode(encrypted));
|
return new SecretkeyElement(Base64.encode(encrypted));
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OpenPgpV4Fingerprint restoreSecretKeyBackup(OpenPgpProvider provider, SecretkeyElement backup, String backupCode)
|
public static PGPSecretKeyRing restoreSecretKeyBackup(SecretkeyElement backup, String backupCode)
|
||||||
throws InvalidBackupCodeException, IOException, MissingUserIdOnKeyException, SmackOpenPgpException {
|
throws InvalidBackupCodeException, IOException, PGPException {
|
||||||
/*
|
|
||||||
byte[] encrypted = Base64.decode(backup.getB64Data());
|
byte[] encrypted = Base64.decode(backup.getB64Data());
|
||||||
|
|
||||||
byte[] decrypted;
|
byte[] decrypted;
|
||||||
try {
|
try {
|
||||||
decrypted = provider.symmetricallyDecryptWithPassword(encrypted, backupCode);
|
decrypted = PGPainless.decryptWithPassword(encrypted, backupCode.toCharArray());
|
||||||
} catch (IOException | SmackOpenPgpException e) {
|
} catch (IOException | PGPException e) {
|
||||||
throw new InvalidBackupCodeException("Could not decrypt secret key backup. Possibly wrong passphrase?", e);
|
throw new InvalidBackupCodeException("Could not decrypt secret key backup. Possibly wrong passphrase?", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return provider.importSecretKey(decrypted);
|
return PGPainless.readKeyRing().secretKeyRing(decrypted);
|
||||||
*/
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue